diff --git a/crates/uv-cli/src/lib.rs b/crates/uv-cli/src/lib.rs index d41e52f67e385..286bc1428f40e 100644 --- a/crates/uv-cli/src/lib.rs +++ b/crates/uv-cli/src/lib.rs @@ -2462,9 +2462,6 @@ pub struct InitArgs { pub vcs: Option, /// Initialize a build-backend of choice for the project. - /// - /// By default, uv will use (`hatchling`). Use `--build-backend` to specify an - /// alternative build backend. #[arg(long, value_enum, conflicts_with_all=["script", "no_package"])] pub build_backend: Option, diff --git a/crates/uv/src/commands/project/init.rs b/crates/uv/src/commands/project/init.rs index ad5f6b44c58c9..2dd1e887de360 100644 --- a/crates/uv/src/commands/project/init.rs +++ b/crates/uv/src/commands/project/init.rs @@ -655,21 +655,9 @@ impl InitProjectKind { pyproject.push('\n'); pyproject.push_str(&pyproject_build_system(name, build_backend)); pyproject_build_backend_prerequisites(name, path, build_backend)?; - } - // Create the source structure. - if package { - // Retrieve build backend - let build_backend = build_backend.unwrap_or_default(); - - // Create `src/{name}/__init__.py`, if it doesn't exist already. - let src_dir = path.join("src").join(&*name.as_dist_info_name()); - fs_err::create_dir_all(&src_dir)?; - let init_py = src_dir.join("__init__.py"); - let packaged_script = generate_package_script(name, path, build_backend, false)?; - if !init_py.try_exists()? { - fs_err::write(init_py, packaged_script)?; - } + // Generate `src` files + generate_package_scripts(name, path, build_backend, false)?; } else { // Create `hello.py` if it doesn't exist // TODO(zanieb): Only create `hello.py` if there are no other Python files? @@ -741,20 +729,8 @@ impl InitProjectKind { fs_err::write(path.join("pyproject.toml"), pyproject)?; - // Create `src/{name}/__init__.py`, if it doesn't exist already. - let src_dir = path.join("src").join(&*name.as_dist_info_name()); - fs_err::create_dir_all(&src_dir)?; - let init_py = src_dir.join("__init__.py"); - let packaged_script = generate_package_script(name, path, build_backend, true)?; - if !init_py.try_exists()? { - fs_err::write(init_py, packaged_script)?; - } - - // Create a `py.typed` file - let py_typed = src_dir.join("py.typed"); - if !py_typed.try_exists()? { - fs_err::write(py_typed, "")?; - } + // Generate `src` files + generate_package_scripts(name, path, build_backend, true)?; // Write .python-version if it doesn't exist. if let Some(python_request) = python_request { @@ -912,8 +888,8 @@ fn pyproject_build_backend_prerequisites( [dependencies] # "extension-module" tells pyo3 we want to build an extension module (skips linking against libpython.so) - # "abi3-py38" tells pyo3 (and maturin) to build using the stable ABI with minimum Python version 3.8 - pyo3 = {{ version = "0.22.3", features = ["extension-module", "abi3-py38"] }} + # "abi3-py39" tells pyo3 (and maturin) to build using the stable ABI with minimum Python version 3.9 + pyo3 = {{ version = "0.22.4", features = ["extension-module", "abi3-py39"] }} "#}, )?; } @@ -975,14 +951,18 @@ fn pyproject_build_backend_prerequisites( } /// Generate startup scripts for a package-based application or library. -fn generate_package_script( +fn generate_package_scripts( package: &PackageName, path: &Path, build_backend: ProjectBuildBackend, is_lib: bool, -) -> Result { +) -> Result<()> { let module_name = package.as_dist_info_name(); + let src_dir = path.join("src"); + let pkg_dir = src_dir.join(&*module_name); + fs_err::create_dir_all(&pkg_dir)?; + // Python script for pure-python packaged apps or libs let pure_python_script = if is_lib { indoc::formatdoc! {r#" @@ -1023,10 +1003,10 @@ fn generate_package_script( let package_script = match build_backend { ProjectBuildBackend::Maturin => { // Generate lib.rs - let lib_rs = path.join("src").join("lib.rs"); - if !lib_rs.try_exists()? { + let native_src = src_dir.join("lib.rs"); + if !native_src.try_exists()? { fs_err::write( - lib_rs, + native_src, indoc::formatdoc! {r#" use pyo3::prelude::*; @@ -1047,7 +1027,7 @@ fn generate_package_script( )?; } // Generate .pyi file - let pyi_file = path.join("src").join(&*module_name).join("_core.pyi"); + let pyi_file = pkg_dir.join("_core.pyi"); if !pyi_file.try_exists()? { fs_err::write(pyi_file, pyi_contents)?; }; @@ -1056,10 +1036,10 @@ fn generate_package_script( } ProjectBuildBackend::Scikit | ProjectBuildBackend::Meson => { // Generate main.cpp - let lib_rs = path.join("src").join("main.cpp"); - if !lib_rs.try_exists()? { + let native_src = src_dir.join("main.cpp"); + if !native_src.try_exists()? { fs_err::write( - lib_rs, + native_src, indoc::formatdoc! {r#" #include @@ -1078,7 +1058,7 @@ fn generate_package_script( )?; } // Generate .pyi file - let pyi_file = path.join("src").join(&*module_name).join("_core.pyi"); + let pyi_file = pkg_dir.join("_core.pyi"); if !pyi_file.try_exists()? { fs_err::write(pyi_file, pyi_contents)?; }; @@ -1088,7 +1068,21 @@ fn generate_package_script( _ => pure_python_script, }; - Ok(package_script) + // Create `src/{name}/__init__.py`, if it doesn't exist already. + let init_py = pkg_dir.join("__init__.py"); + if !init_py.try_exists()? { + fs_err::write(init_py, package_script)?; + } + + // Create `src/{name}/py.typed`, if it doesn't exist already. + if is_lib { + let py_typed = pkg_dir.join("py.typed"); + if !py_typed.try_exists()? { + fs_err::write(py_typed, "")?; + } + } + + Ok(()) } /// Initialize the version control system at the given path. diff --git a/crates/uv/tests/it/init.rs b/crates/uv/tests/it/init.rs index d6299c728349b..93db5674e1995 100644 --- a/crates/uv/tests/it/init.rs +++ b/crates/uv/tests/it/init.rs @@ -2660,8 +2660,8 @@ fn init_app_build_backend_maturin() -> Result<()> { [dependencies] # "extension-module" tells pyo3 we want to build an extension module (skips linking against libpython.so) - # "abi3-py38" tells pyo3 (and maturin) to build using the stable ABI with minimum Python version 3.8 - pyo3 = { version = "0.22.3", features = ["extension-module", "abi3-py38"] } + # "abi3-py39" tells pyo3 (and maturin) to build using the stable ABI with minimum Python version 3.9 + pyo3 = { version = "0.22.4", features = ["extension-module", "abi3-py39"] } "### ); }); @@ -3061,8 +3061,8 @@ fn init_lib_build_backend_maturin() -> Result<()> { [dependencies] # "extension-module" tells pyo3 we want to build an extension module (skips linking against libpython.so) - # "abi3-py38" tells pyo3 (and maturin) to build using the stable ABI with minimum Python version 3.8 - pyo3 = { version = "0.22.3", features = ["extension-module", "abi3-py38"] } + # "abi3-py39" tells pyo3 (and maturin) to build using the stable ABI with minimum Python version 3.9 + pyo3 = { version = "0.22.4", features = ["extension-module", "abi3-py39"] } "### ); }); diff --git a/docs/reference/cli.md b/docs/reference/cli.md index 6aa86a7c8fd49..1baa9149183b4 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -453,9 +453,7 @@ uv init [OPTIONS] [PATH]
  • none: Do not infer the author information
  • -
    --build-backend build-backend

    Initialize a build-backend of choice for the project.

    - -

    By default, uv will use (hatchling). Use --build-backend to specify an alternative build backend.

    +
    --build-backend build-backend

    Initialize a build-backend of choice for the project

    Possible values: