uv init: Make uv_build the default build backend (from hatchling) (#14661)

Closes https://github.com/astral-sh/uv/issues/14298

Switch the default build backend for `uv init` from `hatchling` to
`uv_build`.

This change affects the following two commands:

* `uv init --lib`
* `uv init [--app] --package`

It does not affect `uv init` or `uv init --app` without `--package`. `uv
init --build-backend <...>` also works as before.

**Before**

```
$ uv init --lib project
$ cat project/pyproject.toml
[project]
name = "project"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
authors = [
    { name = "konstin", email = "konstin@mailbox.org" }
]
requires-python = ">=3.13.2"
dependencies = []

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
```

**After**

```
$ uv init --lib project
$ cat project/pyproject.toml
[project]
name = "project"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
authors = [
    { name = "konstin", email = "konstin@mailbox.org" }
]
requires-python = ">=3.13.2"
dependencies = []

[build-system]
requires = ["uv_build>=0.7.20,<0.8"]
build-backend = "uv_build"
```

I cleaned up some tests for consistency in the second commit.
This commit is contained in:
konsti 2025-07-16 19:07:08 +01:00 committed by Zanie Blue
parent b15d59b4ad
commit d4153258d6
7 changed files with 99 additions and 223 deletions

View file

@ -171,7 +171,7 @@ impl PyProjectToml {
///
/// ```toml
/// [build-system]
/// requires = ["uv_build>=0.4.15,<5"]
/// requires = ["uv_build>=0.4.15,<0.5"]
/// build-backend = "uv_build"
/// ```
pub fn check_build_system(&self, uv_version: &str) -> Vec<String> {
@ -826,7 +826,7 @@ mod tests {
{payload}
[build-system]
requires = ["uv_build>=0.4.15,<5"]
requires = ["uv_build>=0.4.15,<0.5"]
build-backend = "uv_build"
"#
}
@ -909,7 +909,7 @@ mod tests {
foo-bar = "foo:bar"
[build-system]
requires = ["uv_build>=0.4.15,<5"]
requires = ["uv_build>=0.4.15,<0.5"]
build-backend = "uv_build"
"#
};
@ -1036,7 +1036,7 @@ mod tests {
foo-bar = "foo:bar"
[build-system]
requires = ["uv_build>=0.4.15,<5"]
requires = ["uv_build>=0.4.15,<0.5"]
build-backend = "uv_build"
"#
};
@ -1104,7 +1104,7 @@ mod tests {
let contents = extend_project("");
let pyproject_toml = PyProjectToml::parse(&contents).unwrap();
assert_snapshot!(
pyproject_toml.check_build_system("1.0.0+test").join("\n"),
pyproject_toml.check_build_system("0.4.15+test").join("\n"),
@""
);
}
@ -1135,7 +1135,7 @@ mod tests {
version = "0.1.0"
[build-system]
requires = ["uv_build>=0.4.15,<5", "wheel"]
requires = ["uv_build>=0.4.15,<0.5", "wheel"]
build-backend = "uv_build"
"#};
let pyproject_toml = PyProjectToml::parse(contents).unwrap();
@ -1171,7 +1171,7 @@ mod tests {
version = "0.1.0"
[build-system]
requires = ["uv_build>=0.4.15,<5"]
requires = ["uv_build>=0.4.15,<0.5"]
build-backend = "setuptools"
"#};
let pyproject_toml = PyProjectToml::parse(contents).unwrap();

View file

@ -63,9 +63,6 @@ pub(crate) async fn init(
printer: Printer,
preview: PreviewMode,
) -> Result<ExitStatus> {
if build_backend == Some(ProjectBuildBackend::Uv) && preview.is_disabled() {
warn_user_once!("The uv build backend is experimental and may change without warning");
}
match init_kind {
InitKind::Script => {
let Some(path) = explicit_path.as_deref() else {
@ -596,7 +593,6 @@ async fn init_project(
author_from,
no_readme,
package,
preview,
)?;
if let Some(workspace) = workspace {
@ -724,7 +720,6 @@ impl InitProjectKind {
author_from: Option<AuthorFrom>,
no_readme: bool,
package: bool,
preview: PreviewMode,
) -> Result<()> {
match self {
InitProjectKind::Application => InitProjectKind::init_application(
@ -739,7 +734,6 @@ impl InitProjectKind {
author_from,
no_readme,
package,
preview,
),
InitProjectKind::Library => InitProjectKind::init_library(
name,
@ -753,7 +747,6 @@ impl InitProjectKind {
author_from,
no_readme,
package,
preview,
),
}
}
@ -772,7 +765,6 @@ impl InitProjectKind {
author_from: Option<AuthorFrom>,
no_readme: bool,
package: bool,
preview: PreviewMode,
) -> Result<()> {
fs_err::create_dir_all(path)?;
@ -805,11 +797,7 @@ impl InitProjectKind {
}
// Add a build system
let build_backend = match build_backend {
Some(build_backend) => build_backend,
None if preview.is_enabled() => ProjectBuildBackend::Uv,
None => ProjectBuildBackend::Hatch,
};
let build_backend = build_backend.unwrap_or(ProjectBuildBackend::Uv);
pyproject.push('\n');
pyproject.push_str(&pyproject_build_system(name, build_backend));
pyproject_build_backend_prerequisites(name, path, build_backend)?;
@ -859,7 +847,6 @@ impl InitProjectKind {
author_from: Option<AuthorFrom>,
no_readme: bool,
package: bool,
preview: PreviewMode,
) -> Result<()> {
if !package {
return Err(anyhow!("Library projects must be packaged"));
@ -880,11 +867,7 @@ impl InitProjectKind {
);
// Always include a build system if the project is packaged.
let build_backend = match build_backend {
Some(build_backend) => build_backend,
None if preview.is_enabled() => ProjectBuildBackend::Uv,
None => ProjectBuildBackend::Hatch,
};
let build_backend = build_backend.unwrap_or(ProjectBuildBackend::Uv);
pyproject.push('\n');
pyproject.push_str(&pyproject_build_system(name, build_backend));
pyproject_build_backend_prerequisites(name, path, build_backend)?;

View file

@ -1439,7 +1439,6 @@ fn build_fast_path() -> Result<()> {
let built_by_uv = current_dir()?.join("../../scripts/packages/built-by-uv");
uv_snapshot!(context.build()
.arg("--preview")
.arg(&built_by_uv)
.arg("--out-dir")
.arg(context.temp_dir.join("output1")), @r###"
@ -1465,7 +1464,6 @@ fn build_fast_path() -> Result<()> {
.assert(predicate::path::is_file());
uv_snapshot!(context.build()
.arg("--preview")
.arg(&built_by_uv)
.arg("--out-dir")
.arg(context.temp_dir.join("output2"))
@ -1485,7 +1483,6 @@ fn build_fast_path() -> Result<()> {
.assert(predicate::path::is_file());
uv_snapshot!(context.build()
.arg("--preview")
.arg(&built_by_uv)
.arg("--out-dir")
.arg(context.temp_dir.join("output3"))
@ -1505,7 +1502,6 @@ fn build_fast_path() -> Result<()> {
.assert(predicate::path::is_file());
uv_snapshot!(context.build()
.arg("--preview")
.arg(&built_by_uv)
.arg("--out-dir")
.arg(context.temp_dir.join("output4"))
@ -1545,7 +1541,6 @@ fn build_list_files() -> Result<()> {
// By default, we build the wheel from the source dist, which we need to do even for the list
// task.
uv_snapshot!(context.build()
.arg("--preview")
.arg(&built_by_uv)
.arg("--out-dir")
.arg(context.temp_dir.join("output1"))
@ -1601,7 +1596,6 @@ fn build_list_files() -> Result<()> {
.assert(predicate::path::missing());
uv_snapshot!(context.build()
.arg("--preview")
.arg(&built_by_uv)
.arg("--out-dir")
.arg(context.temp_dir.join("output2"))
@ -1670,7 +1664,6 @@ fn build_list_files_errors() -> Result<()> {
// In CI, we run with link mode settings.
filters.push(("--link-mode <LINK_MODE> ", ""));
uv_snapshot!(filters, context.build()
.arg("--preview")
.arg(&built_by_uv)
.arg("--out-dir")
.arg(context.temp_dir.join("output1"))
@ -1694,7 +1687,6 @@ fn build_list_files_errors() -> Result<()> {
// Windows normalization
filters.push(("/crates/uv/../../", "/"));
uv_snapshot!(filters, context.build()
.arg("--preview")
.arg(&anyio_local)
.arg("--out-dir")
.arg(context.temp_dir.join("output2"))
@ -1987,12 +1979,7 @@ fn force_pep517() -> Result<()> {
// We need to use a real `uv_build` package.
let context = TestContext::new("3.12").with_exclude_newer("2025-05-27T00:00:00Z");
context
.init()
.arg("--build-backend")
.arg("uv")
.assert()
.success();
context.init().assert().success();
let pyproject_toml = context.temp_dir.child("pyproject.toml");
pyproject_toml.write_str(indoc! {r#"
@ -2026,7 +2013,7 @@ fn force_pep517() -> Result<()> {
----- stderr -----
Building source distribution...
Error: Missing module directory for `does_not_exist` in `src`. Found: `temp`
Error: Missing source directory at: `src`
× Failed to build `[TEMP_DIR]/`
The build backend returned an error
Call to `uv_build.build_sdist` failed (exit status: 1)

View file

@ -222,8 +222,7 @@ fn preserve_executable_bit() -> Result<()> {
let project_dir = context.temp_dir.path().join("preserve_executable_bit");
context
.init()
.arg("--build-backend")
.arg("uv")
.arg("--lib")
.arg(&project_dir)
.assert()
.success();
@ -296,7 +295,7 @@ fn rename_module() -> Result<()> {
module-name = "bar"
[build-system]
requires = ["uv_build>=0.5,<0.8"]
requires = ["uv_build>=0.7,<10000"]
build-backend = "uv_build"
"#})?;
@ -377,7 +376,7 @@ fn rename_module_editable_build() -> Result<()> {
module-name = "bar"
[build-system]
requires = ["uv_build>=0.5,<0.8"]
requires = ["uv_build>=0.7,<10000"]
build-backend = "uv_build"
"#})?;
@ -436,7 +435,7 @@ fn build_module_name_normalization() -> Result<()> {
version = "1.0.0"
[build-system]
requires = ["uv_build>=0.5,<0.8"]
requires = ["uv_build>=0.7,<10000"]
build-backend = "uv_build"
[tool.uv.build-backend]
@ -548,7 +547,7 @@ fn build_sdist_with_long_path() -> Result<()> {
version = "1.0.0"
[build-system]
requires = ["uv_build>=0.7,<0.8"]
requires = ["uv_build>=0.7,<10000"]
build-backend = "uv_build"
"#})?;
context
@ -591,7 +590,7 @@ fn sdist_error_without_module() -> Result<()> {
version = "1.0.0"
[build-system]
requires = ["uv_build>=0.7,<0.8"]
requires = ["uv_build>=0.7,<10000"]
build-backend = "uv_build"
"#})?;
@ -661,7 +660,7 @@ fn complex_namespace_packages() -> Result<()> {
module-name = "{project_name_dist_info}.{part_name}"
[build-system]
requires = ["uv_build>=0.5.15,<10000"]
requires = ["uv_build>=0.7,<10000"]
build-backend = "uv_build"
"#
};
@ -770,8 +769,7 @@ fn symlinked_file() -> Result<()> {
let project = context.temp_dir.child("project");
context
.init()
.arg("--build-backend")
.arg("uv")
.arg("--lib")
.arg(project.path())
.assert()
.success();
@ -783,7 +781,7 @@ fn symlinked_file() -> Result<()> {
license-files = ["LICENSE"]
[build-system]
requires = ["uv_build>=0.5.15,<10000"]
requires = ["uv_build>=0.7,<10000"]
build-backend = "uv_build"
"#
})?;

View file

@ -664,6 +664,14 @@ impl TestContext {
));
// For wiremock tests
filters.push((r"127\.0\.0\.1:\d*".to_string(), "[LOCALHOST]".to_string()));
// Avoid breaking the tests when bumping the uv version
filters.push((
format!(
r#"requires = \["uv_build>={},<[0-9.]+"\]"#,
uv_version::version()
),
r#"requires = ["uv_build>=[CURRENT_VERSION],<[NEXT_BREAKING]"]"#.to_string(),
));
Self {
root: ChildPath::new(root.path()),

View file

@ -314,7 +314,7 @@ fn init_application_package() -> Result<()> {
filters => context.filters(),
}, {
assert_snapshot!(
pyproject, @r###"
pyproject, @r#"
[project]
name = "foo"
version = "0.1.0"
@ -327,9 +327,9 @@ fn init_application_package() -> Result<()> {
foo = "foo:main"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
"###
requires = ["uv_build>=[CURRENT_VERSION],<[NEXT_BREAKING]"]
build-backend = "uv_build"
"#
);
});
@ -390,7 +390,7 @@ fn init_library() -> Result<()> {
filters => context.filters(),
}, {
assert_snapshot!(
pyproject, @r###"
pyproject, @r#"
[project]
name = "foo"
version = "0.1.0"
@ -400,9 +400,9 @@ fn init_library() -> Result<()> {
dependencies = []
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
"###
requires = ["uv_build>=[CURRENT_VERSION],<[NEXT_BREAKING]"]
build-backend = "uv_build"
"#
);
});
@ -446,91 +446,6 @@ fn init_library() -> Result<()> {
Ok(())
}
/// Test the uv build backend with using `uv init --lib --preview`. To be merged with the regular
/// init lib test once the uv build backend becomes the stable default.
#[test]
fn init_library_preview() -> Result<()> {
let context = TestContext::new("3.12");
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("--preview"), @r###"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Initialized project `foo`
"###);
let pyproject = fs_err::read_to_string(&pyproject_toml)?;
let mut filters = context.filters();
filters.push((r#"\["uv_build>=.*,<.*"\]"#, r#"["uv_build[SPECIFIERS]"]"#));
insta::with_settings!({
filters => 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 = ["uv_build[SPECIFIERS]"]
build-backend = "uv_build"
"#
);
});
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().arg("--preview").current_dir(&child).arg("python").arg("-c").arg("import foo; print(foo.hello())"), @r###"
success: true
exit_code: 0
----- stdout -----
Hello from foo!
----- stderr -----
warning: `VIRTUAL_ENV=[VENV]/` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead
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(())
}
/// Test the uv build backend with using `uv init --package --preview`. To be merged with the regular
/// init lib test once the uv build backend becomes the stable default.
#[test]
@ -550,10 +465,8 @@ fn init_package_preview() -> Result<()> {
"###);
let pyproject = fs_err::read_to_string(child.join("pyproject.toml"))?;
let mut filters = context.filters();
filters.push((r#"\["uv_build>=.*,<.*"\]"#, r#"["uv_build[SPECIFIERS]"]"#));
insta::with_settings!({
filters => filters,
filters => context.filters(),
}, {
assert_snapshot!(
pyproject, @r#"
@ -569,7 +482,7 @@ fn init_package_preview() -> Result<()> {
foo = "foo:main"
[build-system]
requires = ["uv_build[SPECIFIERS]"]
requires = ["uv_build>=[CURRENT_VERSION],<[NEXT_BREAKING]"]
build-backend = "uv_build"
"#
);
@ -615,7 +528,7 @@ fn init_bare_lib() {
filters => context.filters(),
}, {
assert_snapshot!(
pyproject, @r###"
pyproject, @r#"
[project]
name = "foo"
version = "0.1.0"
@ -623,9 +536,9 @@ fn init_bare_lib() {
dependencies = []
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
"###
requires = ["uv_build>=[CURRENT_VERSION],<[NEXT_BREAKING]"]
build-backend = "uv_build"
"#
);
});
}
@ -667,7 +580,7 @@ fn init_bare_package() {
filters => context.filters(),
}, {
assert_snapshot!(
pyproject, @r###"
pyproject, @r#"
[project]
name = "foo"
version = "0.1.0"
@ -675,9 +588,9 @@ fn init_bare_package() {
dependencies = []
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
"###
requires = ["uv_build>=[CURRENT_VERSION],<[NEXT_BREAKING]"]
build-backend = "uv_build"
"#
);
});
}
@ -1154,7 +1067,7 @@ fn init_library_current_dir() -> Result<()> {
filters => context.filters(),
}, {
assert_snapshot!(
pyproject, @r###"
pyproject, @r#"
[project]
name = "foo"
version = "0.1.0"
@ -1164,9 +1077,9 @@ fn init_library_current_dir() -> Result<()> {
dependencies = []
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
"###
requires = ["uv_build>=[CURRENT_VERSION],<[NEXT_BREAKING]"]
build-backend = "uv_build"
"#
);
});
@ -1283,7 +1196,7 @@ fn init_dot_args() -> Result<()> {
filters => context.filters(),
}, {
assert_snapshot!(
pyproject, @r###"
pyproject, @r#"
[project]
name = "foo"
version = "0.1.0"
@ -1293,9 +1206,9 @@ fn init_dot_args() -> Result<()> {
dependencies = []
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
"###
requires = ["uv_build>=[CURRENT_VERSION],<[NEXT_BREAKING]"]
build-backend = "uv_build"
"#
);
});
@ -1361,7 +1274,7 @@ fn init_workspace() -> Result<()> {
filters => context.filters(),
}, {
assert_snapshot!(
pyproject, @r###"
pyproject, @r#"
[project]
name = "foo"
version = "0.1.0"
@ -1371,9 +1284,9 @@ fn init_workspace() -> Result<()> {
dependencies = []
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
"###
requires = ["uv_build>=[CURRENT_VERSION],<[NEXT_BREAKING]"]
build-backend = "uv_build"
"#
);
});
@ -1546,7 +1459,7 @@ fn init_workspace_relative_sub_package() -> Result<()> {
filters => context.filters(),
}, {
assert_snapshot!(
pyproject, @r###"
pyproject, @r#"
[project]
name = "foo"
version = "0.1.0"
@ -1556,9 +1469,9 @@ fn init_workspace_relative_sub_package() -> Result<()> {
dependencies = []
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
"###
requires = ["uv_build>=[CURRENT_VERSION],<[NEXT_BREAKING]"]
build-backend = "uv_build"
"#
);
});
@ -1643,7 +1556,7 @@ fn init_workspace_outside() -> Result<()> {
filters => context.filters(),
}, {
assert_snapshot!(
pyproject, @r###"
pyproject, @r#"
[project]
name = "foo"
version = "0.1.0"
@ -1653,9 +1566,9 @@ fn init_workspace_outside() -> Result<()> {
dependencies = []
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
"###
requires = ["uv_build>=[CURRENT_VERSION],<[NEXT_BREAKING]"]
build-backend = "uv_build"
"#
);
});
@ -1725,7 +1638,7 @@ fn init_normalized_names() -> Result<()> {
filters => context.filters(),
}, {
assert_snapshot!(
pyproject, @r###"
pyproject, @r#"
[project]
name = "foo-bar"
version = "0.1.0"
@ -1735,9 +1648,9 @@ fn init_normalized_names() -> Result<()> {
dependencies = []
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
"###
requires = ["uv_build>=[CURRENT_VERSION],<[NEXT_BREAKING]"]
build-backend = "uv_build"
"#
);
});
@ -3008,8 +2921,8 @@ fn init_with_author() {
dependencies = []
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
requires = ["uv_build>=[CURRENT_VERSION],<[NEXT_BREAKING]"]
build-backend = "uv_build"
"#
);
});
@ -3038,8 +2951,8 @@ fn init_with_author() {
dependencies = []
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
requires = ["uv_build>=[CURRENT_VERSION],<[NEXT_BREAKING]"]
build-backend = "uv_build"
"#
);
});
@ -3822,9 +3735,9 @@ fn init_lib_build_backend_scikit() -> Result<()> {
Ok(())
}
/// Run `uv init --app --package --build-backend uv` to create a packaged application project
/// Run `uv init --app --package --build-backend hatchling` to create a packaged application project
#[test]
fn init_application_package_uv() -> Result<()> {
fn init_application_package_hatchling() -> Result<()> {
let context = TestContext::new("3.12");
let child = context.temp_dir.child("foo");
@ -3833,41 +3746,34 @@ fn init_application_package_uv() -> Result<()> {
let pyproject_toml = child.join("pyproject.toml");
let init_py = child.join("src").join("foo").join("__init__.py");
uv_snapshot!(context.filters(), context.init().current_dir(&child).arg("--app").arg("--package").arg("--build-backend").arg("uv"), @r###"
uv_snapshot!(context.filters(), context.init().current_dir(&child).arg("--app").arg("--package").arg("--build-backend").arg("hatchling"), @r###"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
warning: The uv build backend is experimental and may change without warning
Initialized project `foo`
"###);
let pyproject = fs_err::read_to_string(&pyproject_toml)?;
let mut filters = context.filters();
filters.push((r#"\["uv_build>=.*,<.*"\]"#, r#"["uv_build[SPECIFIERS]"]"#));
insta::with_settings!({
filters => 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 = []
assert_snapshot!(
pyproject, @r#"
[project]
name = "foo"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = []
[project.scripts]
foo = "foo:main"
[project.scripts]
foo = "foo:main"
[build-system]
requires = ["uv_build[SPECIFIERS]"]
build-backend = "uv_build"
"###
);
});
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
"#
);
let init = fs_err::read_to_string(init_py)?;
insta::with_settings!({
@ -3881,8 +3787,7 @@ fn init_application_package_uv() -> Result<()> {
);
});
// Use preview to go through the fast path.
uv_snapshot!(context.filters(), context.run().arg("--preview").arg("foo").current_dir(&child).env_remove(EnvVars::VIRTUAL_ENV), @r###"
uv_snapshot!(context.filters(), context.run().arg("foo").current_dir(&child).env_remove(EnvVars::VIRTUAL_ENV), @r###"
success: true
exit_code: 0
----- stdout -----
@ -3935,8 +3840,8 @@ fn init_with_description() -> Result<()> {
dependencies = []
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
requires = ["uv_build>=[CURRENT_VERSION],<[NEXT_BREAKING]"]
build-backend = "uv_build"
"#
);
});
@ -3977,8 +3882,8 @@ fn init_without_description() -> Result<()> {
dependencies = []
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
requires = ["uv_build>=[CURRENT_VERSION],<[NEXT_BREAKING]"]
build-backend = "uv_build"
"#
);
});

View file

@ -1,10 +1,5 @@
# The uv build backend
!!! note
Currently, the default build backend for `uv init` is
[hatchling](https://pypi.org/project/hatchling/). This will change to `uv` in a future version.
A build backend transforms a source tree (i.e., a directory) into a source distribution or a wheel.
uv supports all build backends (as specified by [PEP 517](https://peps.python.org/pep-0517/)), but
@ -49,7 +44,7 @@ build-backend = "uv_build"
To create a new project that uses the uv build backend, use `uv init`:
```console
$ uv init --build-backend uv
$ uv init
```
When the project is built, e.g., with [`uv build`](../guides/package.md), the uv build backend will