Add support for optional --description in uv init (#10209)
Some checks failed
CI / Determine changes (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / cargo shear (push) Has been cancelled
CI / typos (push) Has been cancelled
CI / mkdocs (push) Has been cancelled
CI / cargo clippy | ubuntu (push) Has been cancelled
CI / cargo clippy | windows (push) Has been cancelled
CI / cargo dev generate-all (push) Has been cancelled
CI / cargo test | ubuntu (push) Has been cancelled
CI / test windows trampoline | i686 (push) Has been cancelled
CI / cargo test | macos (push) Has been cancelled
CI / cargo test | windows (push) Has been cancelled
CI / check windows trampoline | aarch64 (push) Has been cancelled
CI / check windows trampoline | i686 (push) Has been cancelled
CI / check windows trampoline | x86_64 (push) Has been cancelled
CI / test windows trampoline | x86_64 (push) Has been cancelled
CI / build binary | linux (push) Has been cancelled
CI / build binary | macos aarch64 (push) Has been cancelled
CI / build binary | macos x86_64 (push) Has been cancelled
CI / build binary | windows (push) Has been cancelled
CI / cargo build (msrv) (push) Has been cancelled
CI / build binary | freebsd (push) Has been cancelled
CI / ecosystem test | prefecthq/prefect (push) Has been cancelled
CI / ecosystem test | pallets/flask (push) Has been cancelled
CI / integration test | conda on ubuntu (push) Has been cancelled
CI / integration test | free-threaded on linux (push) Has been cancelled
CI / integration test | free-threaded on windows (push) Has been cancelled
CI / integration test | pypy on ubuntu (push) Has been cancelled
CI / integration test | pypy on windows (push) Has been cancelled
CI / integration test | graalpy on ubuntu (push) Has been cancelled
CI / integration test | graalpy on windows (push) Has been cancelled
CI / integration test | github actions (push) Has been cancelled
CI / integration test | determine publish changes (push) Has been cancelled
CI / integration test | uv publish (push) Has been cancelled
CI / check cache | ubuntu (push) Has been cancelled
CI / check cache | macos aarch64 (push) Has been cancelled
CI / check system | python on debian (push) Has been cancelled
CI / check system | python on fedora (push) Has been cancelled
CI / check system | python on ubuntu (push) Has been cancelled
CI / check system | python on opensuse (push) Has been cancelled
CI / check system | homebrew python on macos aarch64 (push) Has been cancelled
CI / check system | python on rocky linux 8 (push) Has been cancelled
CI / check system | python on rocky linux 9 (push) Has been cancelled
CI / check system | pypy on ubuntu (push) Has been cancelled
CI / check system | pyston (push) Has been cancelled
CI / check system | alpine (push) Has been cancelled
CI / check system | python on macos aarch64 (push) Has been cancelled
CI / check system | python on macos x86_64 (push) Has been cancelled
CI / check system | python3.10 on windows (push) Has been cancelled
CI / check system | python3.10 on windows x86 (push) Has been cancelled
CI / check system | python3.13 on windows (push) Has been cancelled
CI / check system | python3.12 via chocolatey (push) Has been cancelled
CI / check system | conda3.11 on windows (push) Has been cancelled
CI / check system | python3.9 via pyenv (push) Has been cancelled
CI / check system | python3.13 (push) Has been cancelled
CI / check system | conda3.11 on linux (push) Has been cancelled
CI / check system | conda3.8 on linux (push) Has been cancelled
CI / check system | conda3.11 on macos (push) Has been cancelled
CI / check system | conda3.8 on macos (push) Has been cancelled
CI / check system | conda3.8 on windows (push) Has been cancelled
CI / check system | amazonlinux (push) Has been cancelled
CI / check system | embedded python3.10 on windows (push) Has been cancelled
CI / benchmarks (push) Has been cancelled

## Summary
Closes #7913 by adding an optional `--description` argument to `uv init`
that fills the description field in the pyproject.toml with the supplied
arg value.

Updated `uv init` docs to describe this new optional argument.
<!-- What's the purpose of the change? What does it do, and why? -->

## Test Plan
Added snapshot tests in `uv/crates/uv/tests/it/init.rs` to test this
functionality.
<!-- How was it tested? -->

---------

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
This commit is contained in:
Arnav Gupta 2024-12-27 19:06:51 -05:00 committed by GitHub
parent 8992f5524c
commit 3733008e6c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 123 additions and 4 deletions

View file

@ -2568,9 +2568,13 @@ pub struct InitArgs {
///
/// By default, adds a requirement on the system Python version; use `--python` to specify an
/// alternative Python version requirement.
#[arg(long, conflicts_with_all=["app", "lib", "package", "build_backend"])]
#[arg(long, conflicts_with_all=["app", "lib", "package", "build_backend", "description"])]
pub r#script: bool,
/// Set the project description.
#[arg(long, conflicts_with = "script")]
pub description: Option<String>,
/// Initialize a version control system for the project.
///
/// By default, uv will initialize a Git repository (`git`). Use `--vcs none` to explicitly

View file

@ -41,6 +41,7 @@ pub(crate) async fn init(
name: Option<PackageName>,
package: bool,
init_kind: InitKind,
description: Option<String>,
vcs: Option<VersionControlSystem>,
build_backend: Option<ProjectBuildBackend>,
no_readme: bool,
@ -129,6 +130,7 @@ pub(crate) async fn init(
&name,
package,
project_kind,
description,
vcs,
build_backend,
no_readme,
@ -270,6 +272,7 @@ async fn init_project(
name: &PackageName,
package: bool,
project_kind: InitProjectKind,
description: Option<String>,
vcs: Option<VersionControlSystem>,
build_backend: Option<ProjectBuildBackend>,
no_readme: bool,
@ -564,6 +567,7 @@ async fn init_project(
name,
path,
&requires_python,
description.as_deref(),
vcs,
build_backend,
author_from,
@ -687,6 +691,7 @@ impl InitProjectKind {
name: &PackageName,
path: &Path,
requires_python: &RequiresPython,
description: Option<&str>,
vcs: Option<VersionControlSystem>,
build_backend: Option<ProjectBuildBackend>,
author_from: Option<AuthorFrom>,
@ -698,6 +703,7 @@ impl InitProjectKind {
name,
path,
requires_python,
description,
vcs,
build_backend,
author_from,
@ -708,6 +714,7 @@ impl InitProjectKind {
name,
path,
requires_python,
description,
vcs,
build_backend,
author_from,
@ -722,6 +729,7 @@ impl InitProjectKind {
name: &PackageName,
path: &Path,
requires_python: &RequiresPython,
description: Option<&str>,
vcs: Option<VersionControlSystem>,
build_backend: Option<ProjectBuildBackend>,
author_from: Option<AuthorFrom>,
@ -741,7 +749,13 @@ impl InitProjectKind {
let author = get_author_info(path, author_from);
// Create the `pyproject.toml`
let mut pyproject = pyproject_project(name, requires_python, author.as_ref(), no_readme);
let mut pyproject = pyproject_project(
name,
requires_python,
author.as_ref(),
description,
no_readme,
);
// Include additional project configuration for packaged applications
if package {
@ -788,6 +802,7 @@ impl InitProjectKind {
name: &PackageName,
path: &Path,
requires_python: &RequiresPython,
description: Option<&str>,
vcs: Option<VersionControlSystem>,
build_backend: Option<ProjectBuildBackend>,
author_from: Option<AuthorFrom>,
@ -803,7 +818,13 @@ impl InitProjectKind {
let author = get_author_info(path, author_from.unwrap_or_default());
// Create the `pyproject.toml`
let mut pyproject = pyproject_project(name, requires_python, author.as_ref(), no_readme);
let mut pyproject = pyproject_project(
name,
requires_python,
author.as_ref(),
description,
no_readme,
);
// Always include a build system if the project is packaged.
let build_backend = build_backend.unwrap_or_default();
@ -847,19 +868,21 @@ fn pyproject_project(
name: &PackageName,
requires_python: &RequiresPython,
author: Option<&Author>,
description: Option<&str>,
no_readme: bool,
) -> String {
indoc::formatdoc! {r#"
[project]
name = "{name}"
version = "0.1.0"
description = "Add your description here"{readme}{authors}
description = "{description}"{readme}{authors}
requires-python = "{requires_python}"
dependencies = []
"#,
readme = if no_readme { "" } else { "\nreadme = \"README.md\"" },
authors = author.map_or_else(String::new, |author| format!("\nauthors = [\n {}\n]", author.to_toml_string())),
requires_python = requires_python.specifiers(),
description = description.unwrap_or("Add your description here"),
}
}

View file

@ -1360,6 +1360,7 @@ async fn run_project(
args.name,
args.package,
args.kind,
args.description,
args.vcs,
args.build_backend,
args.no_readme,

View file

@ -189,6 +189,7 @@ pub(crate) struct InitSettings {
pub(crate) name: Option<PackageName>,
pub(crate) package: bool,
pub(crate) kind: InitKind,
pub(crate) description: Option<String>,
pub(crate) vcs: Option<VersionControlSystem>,
pub(crate) build_backend: Option<ProjectBuildBackend>,
pub(crate) no_readme: bool,
@ -212,6 +213,7 @@ impl InitSettings {
app,
lib,
script,
description,
vcs,
build_backend,
no_readme,
@ -241,6 +243,7 @@ impl InitSettings {
name,
package,
kind,
description,
vcs,
build_backend,
no_readme,

View file

@ -3271,3 +3271,89 @@ fn init_application_package_uv() -> Result<()> {
Ok(())
}
#[test]
fn init_with_description() -> Result<()> {
let context = TestContext::new("3.12");
let child = context.temp_dir.join("foo");
fs_err::create_dir_all(&child)?;
// Initialize the project with a description
context
.init()
.current_dir(&child)
.arg("--description")
.arg("A sample project description")
.arg("--lib")
.assert()
.success();
// Read the generated pyproject.toml
let pyproject = fs_err::read_to_string(child.join("pyproject.toml"))?;
// Verify the description in pyproject.toml
insta::with_settings!({
filters => context.filters(),
}, {
assert_snapshot!(
pyproject, @r#"
[project]
name = "foo"
version = "0.1.0"
description = "A sample project description"
readme = "README.md"
requires-python = ">=3.12"
dependencies = []
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
"#
);
});
Ok(())
}
#[test]
fn init_without_description() -> Result<()> {
let context = TestContext::new("3.12");
let child = context.temp_dir.join("bar");
fs_err::create_dir_all(&child)?;
// Initialize the project without a description
context
.init()
.current_dir(&child)
.arg("--lib")
.assert()
.success();
// Read the generated pyproject.toml
let pyproject = fs_err::read_to_string(child.join("pyproject.toml"))?;
// Verify the default description in pyproject.toml
insta::with_settings!({
filters => context.filters(),
}, {
assert_snapshot!(
pyproject, @r#"
[project]
name = "bar"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = []
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
"#
);
});
Ok(())
}

View file

@ -589,6 +589,8 @@ uv init [OPTIONS] [PATH]
<p>While uv configuration can be included in a <code>pyproject.toml</code> file, it is not allowed in this context.</p>
<p>May also be set with the <code>UV_CONFIG_FILE</code> environment variable.</p>
</dd><dt><code>--description</code> <i>description</i></dt><dd><p>Set the project description</p>
</dd><dt><code>--directory</code> <i>directory</i></dt><dd><p>Change to the given directory prior to running the command.</p>
<p>Relative paths are resolved with the given directory as the base.</p>