Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build backend: Add template to uv init #9661

Merged
merged 1 commit into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions crates/uv-configuration/src/project_build_backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub enum ProjectBuildBackend {
#[cfg_attr(feature = "clap", value(hide = true))]
#[cfg_attr(feature = "schemars", value(hide = true))]
/// Use uv as the project build backend.
Uv,
#[default]
#[serde(alias = "hatchling")]
#[cfg_attr(feature = "clap", value(alias = "hatchling"))]
Expand Down
1 change: 1 addition & 0 deletions crates/uv-dev/src/generate_cli_reference.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@ fn emit_possible_options(opt: &clap::Arg, output: &mut String) {
"\nPossible values:\n{}",
values
.into_iter()
.filter(|value| !value.is_hide_set())
.map(|value| {
let name = value.get_name();
value.get_help().map_or_else(
Expand Down
27 changes: 23 additions & 4 deletions crates/uv/src/commands/project/init.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
use anyhow::{anyhow, Context, Result};
use owo_colors::OwoColorize;
use std::fmt::Write;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};

use anyhow::{anyhow, Context, Result};
use owo_colors::OwoColorize;
use std::str::FromStr;

use tracing::{debug, warn};
use uv_cache::Cache;
use uv_cli::AuthorFrom;
use uv_client::{BaseClientBuilder, Connectivity};
use uv_configuration::{
ProjectBuildBackend, TrustedHost, VersionControlError, VersionControlSystem,
PreviewMode, ProjectBuildBackend, TrustedHost, VersionControlError, VersionControlSystem,
};
use uv_fs::{Simplified, CWD};
use uv_git::GIT;
Expand Down Expand Up @@ -57,7 +57,11 @@ pub(crate) async fn init(
no_config: bool,
cache: &Cache,
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 {
Expand Down Expand Up @@ -864,6 +868,21 @@ fn pyproject_project(
fn pyproject_build_system(package: &PackageName, build_backend: ProjectBuildBackend) -> String {
let module_name = package.as_dist_info_name();
match build_backend {
ProjectBuildBackend::Uv => {
// Limit to the stable version range.
let min_version = Version::from_str(uv_version::version()).unwrap();
debug_assert!(
min_version.release()[0] == 0,
"migrate to major version bumps"
);
let max_version = Version::new([0, min_version.release()[1] + 1]);
indoc::formatdoc! {r#"
[build-system]
requires = ["uv>={min_version},<{max_version}"]
build-backend = "uv"
"#}
}
.to_string(),
// Pure-python backends
ProjectBuildBackend::Hatch => indoc::indoc! {r#"
[build-system]
Expand Down
1 change: 1 addition & 0 deletions crates/uv/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1320,6 +1320,7 @@ async fn run_project(
no_config,
&cache,
printer,
globals.preview,
)
.await
}
Expand Down
78 changes: 78 additions & 0 deletions crates/uv/tests/it/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3193,3 +3193,81 @@ fn init_lib_build_backend_scikit() -> Result<()> {

Ok(())
}

/// Run `uv init --app --package --build-backend uv` to create a packaged application project
#[test]
fn init_application_package_uv() -> 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");

uv_snapshot!(context.filters(), context.init().current_dir(&child).arg("--app").arg("--package").arg("--build-backend").arg("uv"), @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>=.*,<.*"\]"#, r#"["uv[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 = []

[project.scripts]
foo = "foo:main"

[build-system]
requires = ["uv[SPECIFIERS]"]
build-backend = "uv"
"###
);
});

let init = fs_err::read_to_string(init_py)?;
insta::with_settings!({
filters => context.filters(),
}, {
assert_snapshot!(
init, @r###"
def main() -> None:
print("Hello from foo!")
"###
);
});

// 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###"
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(())
}
Loading