diff --git a/crates/uv-configuration/src/project_build_backend.rs b/crates/uv-configuration/src/project_build_backend.rs index df1d97978..86410e793 100644 --- a/crates/uv-configuration/src/project_build_backend.rs +++ b/crates/uv-configuration/src/project_build_backend.rs @@ -24,6 +24,10 @@ pub enum ProjectBuildBackend { #[serde(alias = "pdm-backend")] #[cfg_attr(feature = "clap", value(alias = "pdm-backend"))] PDM, + /// Use [poetry-core](https://pypi.org/project/poetry-core) as the project build backend. + #[serde(alias = "poetry-core")] + #[cfg_attr(feature = "clap", value(alias = "poetry-core", alias = "poetry_core"))] + Poetry, /// Use [setuptools](https://pypi.org/project/setuptools) as the project build backend. Setuptools, /// Use [maturin](https://pypi.org/project/maturin) as the project build backend. diff --git a/crates/uv/src/commands/project/init.rs b/crates/uv/src/commands/project/init.rs index a51f5489e..8ffc95fe5 100644 --- a/crates/uv/src/commands/project/init.rs +++ b/crates/uv/src/commands/project/init.rs @@ -959,6 +959,12 @@ fn pyproject_build_system(package: &PackageName, build_backend: ProjectBuildBack build-backend = "setuptools.build_meta" "#} .to_string(), + ProjectBuildBackend::Poetry => indoc::indoc! {r#" + [build-system] + requires = ["poetry-core>=2,<3"] + build-backend = "poetry.core.masonry.api" + "#} + .to_string(), // Binary build backends ProjectBuildBackend::Maturin => indoc::formatdoc! {r#" [tool.maturin] diff --git a/crates/uv/tests/it/init.rs b/crates/uv/tests/it/init.rs index ccb397490..48a06ddd4 100644 --- a/crates/uv/tests/it/init.rs +++ b/crates/uv/tests/it/init.rs @@ -3048,6 +3048,87 @@ fn init_backend_implies_package() { }); } +/// Run `uv init --build-backend poetry` to create a project with poetry-core build backend +#[test] +fn init_library_poetry() -> Result<()> { + let context = TestContext::new("3.12").with_exclude_newer("2025-04-28T00:00:00Z"); + + let child = context.temp_dir.child("foo"); + child.create_dir_all()?; + + let pyproject_toml = child.join("pyproject.toml"); + let init_py = child.join("src").join("foo").join("__init__.py"); + let py_typed = child.join("src").join("foo").join("py.typed"); + + uv_snapshot!(context.filters(), context.init().current_dir(&child).arg("--lib").arg("--build-backend").arg("poetry"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Initialized project `foo` + "###); + + let pyproject = fs_err::read_to_string(&pyproject_toml)?; + insta::with_settings!({ + filters => context.filters(), + }, { + assert_snapshot!( + pyproject, @r###" + [project] + name = "foo" + version = "0.1.0" + description = "Add your description here" + readme = "README.md" + requires-python = ">=3.12" + dependencies = [] + + [build-system] + requires = ["poetry-core>=2,<3"] + build-backend = "poetry.core.masonry.api" + "### + ); + }); + + let init = fs_err::read_to_string(init_py)?; + insta::with_settings!({ + filters => context.filters(), + }, { + assert_snapshot!( + init, @r###" + def hello() -> str: + return "Hello from foo!" + "### + ); + }); + + let py_typed = fs_err::read_to_string(py_typed)?; + insta::with_settings!({ + filters => context.filters(), + }, { + assert_snapshot!( + py_typed, @"" + ); + }); + + uv_snapshot!(context.filters(), context.run().current_dir(&child).env_remove(EnvVars::VIRTUAL_ENV).arg("python").arg("-c").arg("import foo; print(foo.hello())"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + Hello from foo! + + ----- stderr ----- + Using CPython 3.12.[X] interpreter at: [PYTHON-3.12] + Creating virtual environment at: .venv + Resolved 1 package in [TIME] + Prepared 1 package in [TIME] + Installed 1 package in [TIME] + + foo==0.1.0 (from file://[TEMP_DIR]/foo) + "###); + + Ok(()) +} + /// Run `uv init --app --package --build-backend maturin` to create a packaged application project #[test] #[cfg(feature = "crates-io")] diff --git a/docs/reference/cli.md b/docs/reference/cli.md index 049ef7670..332ae95cf 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -576,6 +576,8 @@ uv init [OPTIONS] [PATH]
  • pdm: Use pdm-backend as the project build backend
  • +
  • poetry: Use poetry-core as the project build backend
  • +
  • setuptools: Use setuptools as the project build backend
  • maturin: Use maturin as the project build backend