mirror of
https://github.com/astral-sh/uv.git
synced 2025-09-27 04:29:10 +00:00
Fill in authors
filed during uv init
(#7756)
## Summary Fill in the `authors` field of `pyproject.toml` by fetching author info from Git. Resolves #7718
This commit is contained in:
parent
56521937b7
commit
15e5e3f6af
6 changed files with 288 additions and 11 deletions
|
@ -2346,6 +2346,17 @@ impl ExternalCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Copy, Clone, clap::ValueEnum)]
|
||||||
|
pub enum AuthorFrom {
|
||||||
|
/// Fetch the author information from some sources (e.g., Git) automatically.
|
||||||
|
#[default]
|
||||||
|
Auto,
|
||||||
|
/// Fetch the author information from Git configuration only.
|
||||||
|
Git,
|
||||||
|
/// Do not infer the author information.
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
#[allow(clippy::struct_excessive_bools)]
|
#[allow(clippy::struct_excessive_bools)]
|
||||||
pub struct InitArgs {
|
pub struct InitArgs {
|
||||||
|
@ -2432,6 +2443,14 @@ pub struct InitArgs {
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub no_readme: bool,
|
pub no_readme: bool,
|
||||||
|
|
||||||
|
/// Fill in the `authors` field in the `pyproject.toml`.
|
||||||
|
///
|
||||||
|
/// By default, uv will attempt to infer the author information from some sources (e.g., Git) (`auto`).
|
||||||
|
/// Use `--author-from git` to only infer from Git configuration.
|
||||||
|
/// Use `--author-from none` to avoid inferring the author information.
|
||||||
|
#[arg(long, value_enum)]
|
||||||
|
pub author_from: Option<AuthorFrom>,
|
||||||
|
|
||||||
/// Do not create a `.python-version` file for the project.
|
/// Do not create a `.python-version` file for the project.
|
||||||
///
|
///
|
||||||
/// By default, uv will create a `.python-version` file containing the minor version of
|
/// By default, uv will create a `.python-version` file containing the minor version of
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::process::{Command, Stdio};
|
||||||
|
|
||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
use owo_colors::OwoColorize;
|
use owo_colors::OwoColorize;
|
||||||
|
|
||||||
use tracing::{debug, warn};
|
use tracing::{debug, warn};
|
||||||
use uv_cache::Cache;
|
use uv_cache::Cache;
|
||||||
|
use uv_cli::AuthorFrom;
|
||||||
use uv_client::{BaseClientBuilder, Connectivity};
|
use uv_client::{BaseClientBuilder, Connectivity};
|
||||||
use uv_configuration::{VersionControlError, VersionControlSystem};
|
use uv_configuration::{VersionControlError, VersionControlSystem};
|
||||||
use uv_fs::{Simplified, CWD};
|
use uv_fs::{Simplified, CWD};
|
||||||
|
@ -36,6 +38,7 @@ pub(crate) async fn init(
|
||||||
init_kind: InitKind,
|
init_kind: InitKind,
|
||||||
vcs: Option<VersionControlSystem>,
|
vcs: Option<VersionControlSystem>,
|
||||||
no_readme: bool,
|
no_readme: bool,
|
||||||
|
author_from: Option<AuthorFrom>,
|
||||||
no_pin_python: bool,
|
no_pin_python: bool,
|
||||||
python: Option<String>,
|
python: Option<String>,
|
||||||
no_workspace: bool,
|
no_workspace: bool,
|
||||||
|
@ -62,6 +65,7 @@ pub(crate) async fn init(
|
||||||
printer,
|
printer,
|
||||||
no_workspace,
|
no_workspace,
|
||||||
no_readme,
|
no_readme,
|
||||||
|
author_from,
|
||||||
no_pin_python,
|
no_pin_python,
|
||||||
package,
|
package,
|
||||||
native_tls,
|
native_tls,
|
||||||
|
@ -111,6 +115,7 @@ pub(crate) async fn init(
|
||||||
project_kind,
|
project_kind,
|
||||||
vcs,
|
vcs,
|
||||||
no_readme,
|
no_readme,
|
||||||
|
author_from,
|
||||||
no_pin_python,
|
no_pin_python,
|
||||||
python,
|
python,
|
||||||
no_workspace,
|
no_workspace,
|
||||||
|
@ -165,6 +170,7 @@ async fn init_script(
|
||||||
printer: Printer,
|
printer: Printer,
|
||||||
no_workspace: bool,
|
no_workspace: bool,
|
||||||
no_readme: bool,
|
no_readme: bool,
|
||||||
|
author_from: Option<AuthorFrom>,
|
||||||
no_pin_python: bool,
|
no_pin_python: bool,
|
||||||
package: bool,
|
package: bool,
|
||||||
native_tls: bool,
|
native_tls: bool,
|
||||||
|
@ -175,6 +181,9 @@ async fn init_script(
|
||||||
if no_readme {
|
if no_readme {
|
||||||
warn_user_once!("`--no_readme` is a no-op for Python scripts, which are standalone");
|
warn_user_once!("`--no_readme` is a no-op for Python scripts, which are standalone");
|
||||||
}
|
}
|
||||||
|
if author_from.is_some() {
|
||||||
|
warn_user_once!("`--author-from` is a no-op for Python scripts, which are standalone");
|
||||||
|
}
|
||||||
if package {
|
if package {
|
||||||
warn_user_once!("`--package` is a no-op for Python scripts, which are standalone");
|
warn_user_once!("`--package` is a no-op for Python scripts, which are standalone");
|
||||||
}
|
}
|
||||||
|
@ -237,6 +246,7 @@ async fn init_project(
|
||||||
project_kind: InitProjectKind,
|
project_kind: InitProjectKind,
|
||||||
vcs: Option<VersionControlSystem>,
|
vcs: Option<VersionControlSystem>,
|
||||||
no_readme: bool,
|
no_readme: bool,
|
||||||
|
author_from: Option<AuthorFrom>,
|
||||||
no_pin_python: bool,
|
no_pin_python: bool,
|
||||||
python: Option<String>,
|
python: Option<String>,
|
||||||
no_workspace: bool,
|
no_workspace: bool,
|
||||||
|
@ -475,6 +485,7 @@ async fn init_project(
|
||||||
&requires_python,
|
&requires_python,
|
||||||
python_request.as_ref(),
|
python_request.as_ref(),
|
||||||
vcs,
|
vcs,
|
||||||
|
author_from,
|
||||||
no_readme,
|
no_readme,
|
||||||
package,
|
package,
|
||||||
)
|
)
|
||||||
|
@ -564,6 +575,7 @@ impl InitProjectKind {
|
||||||
requires_python: &RequiresPython,
|
requires_python: &RequiresPython,
|
||||||
python_request: Option<&PythonRequest>,
|
python_request: Option<&PythonRequest>,
|
||||||
vcs: Option<VersionControlSystem>,
|
vcs: Option<VersionControlSystem>,
|
||||||
|
author_from: Option<AuthorFrom>,
|
||||||
no_readme: bool,
|
no_readme: bool,
|
||||||
package: bool,
|
package: bool,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
@ -575,6 +587,7 @@ impl InitProjectKind {
|
||||||
requires_python,
|
requires_python,
|
||||||
python_request,
|
python_request,
|
||||||
vcs,
|
vcs,
|
||||||
|
author_from,
|
||||||
no_readme,
|
no_readme,
|
||||||
package,
|
package,
|
||||||
)
|
)
|
||||||
|
@ -587,6 +600,7 @@ impl InitProjectKind {
|
||||||
requires_python,
|
requires_python,
|
||||||
python_request,
|
python_request,
|
||||||
vcs,
|
vcs,
|
||||||
|
author_from,
|
||||||
no_readme,
|
no_readme,
|
||||||
package,
|
package,
|
||||||
)
|
)
|
||||||
|
@ -603,11 +617,24 @@ impl InitProjectKind {
|
||||||
requires_python: &RequiresPython,
|
requires_python: &RequiresPython,
|
||||||
python_request: Option<&PythonRequest>,
|
python_request: Option<&PythonRequest>,
|
||||||
vcs: Option<VersionControlSystem>,
|
vcs: Option<VersionControlSystem>,
|
||||||
|
author_from: Option<AuthorFrom>,
|
||||||
no_readme: bool,
|
no_readme: bool,
|
||||||
package: bool,
|
package: bool,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
fs_err::create_dir_all(path)?;
|
||||||
|
|
||||||
|
// Do no fill in `authors` for non-packaged applications unless explicitly requested.
|
||||||
|
let author_from = author_from.unwrap_or_else(|| {
|
||||||
|
if package {
|
||||||
|
AuthorFrom::default()
|
||||||
|
} else {
|
||||||
|
AuthorFrom::None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let author = get_author_info(path, author_from);
|
||||||
|
|
||||||
// Create the `pyproject.toml`
|
// Create the `pyproject.toml`
|
||||||
let mut pyproject = pyproject_project(name, requires_python, no_readme);
|
let mut pyproject = pyproject_project(name, requires_python, author.as_ref(), no_readme);
|
||||||
|
|
||||||
// Include additional project configuration for packaged applications
|
// Include additional project configuration for packaged applications
|
||||||
if package {
|
if package {
|
||||||
|
@ -620,8 +647,6 @@ impl InitProjectKind {
|
||||||
pyproject.push_str(pyproject_build_system());
|
pyproject.push_str(pyproject_build_system());
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_err::create_dir_all(path)?;
|
|
||||||
|
|
||||||
// Create the source structure.
|
// Create the source structure.
|
||||||
if package {
|
if package {
|
||||||
// Create `src/{name}/__init__.py`, if it doesn't exist already.
|
// Create `src/{name}/__init__.py`, if it doesn't exist already.
|
||||||
|
@ -684,6 +709,7 @@ impl InitProjectKind {
|
||||||
requires_python: &RequiresPython,
|
requires_python: &RequiresPython,
|
||||||
python_request: Option<&PythonRequest>,
|
python_request: Option<&PythonRequest>,
|
||||||
vcs: Option<VersionControlSystem>,
|
vcs: Option<VersionControlSystem>,
|
||||||
|
author_from: Option<AuthorFrom>,
|
||||||
no_readme: bool,
|
no_readme: bool,
|
||||||
package: bool,
|
package: bool,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
@ -691,14 +717,17 @@ impl InitProjectKind {
|
||||||
return Err(anyhow!("Library projects must be packaged"));
|
return Err(anyhow!("Library projects must be packaged"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fs_err::create_dir_all(path)?;
|
||||||
|
|
||||||
|
let author = get_author_info(path, author_from.unwrap_or_default());
|
||||||
|
|
||||||
// Create the `pyproject.toml`
|
// Create the `pyproject.toml`
|
||||||
let mut pyproject = pyproject_project(name, requires_python, no_readme);
|
let mut pyproject = pyproject_project(name, requires_python, author.as_ref(), no_readme);
|
||||||
|
|
||||||
// Always include a build system if the project is packaged.
|
// Always include a build system if the project is packaged.
|
||||||
pyproject.push('\n');
|
pyproject.push('\n');
|
||||||
pyproject.push_str(pyproject_build_system());
|
pyproject.push_str(pyproject_build_system());
|
||||||
|
|
||||||
fs_err::create_dir_all(path)?;
|
|
||||||
fs_err::write(path.join("pyproject.toml"), pyproject)?;
|
fs_err::write(path.join("pyproject.toml"), pyproject)?;
|
||||||
|
|
||||||
// Create `src/{name}/__init__.py`, if it doesn't exist already.
|
// Create `src/{name}/__init__.py`, if it doesn't exist already.
|
||||||
|
@ -742,21 +771,42 @@ impl InitProjectKind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum Author {
|
||||||
|
Name(String),
|
||||||
|
Email(String),
|
||||||
|
NameEmail { name: String, email: String },
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Author {
|
||||||
|
fn to_toml_string(&self) -> String {
|
||||||
|
match self {
|
||||||
|
Self::NameEmail { name, email } => {
|
||||||
|
format!("{{ name = \"{name}\", email = \"{email}\" }}")
|
||||||
|
}
|
||||||
|
Self::Name(name) => format!("{{ name = \"{name}\" }}"),
|
||||||
|
Self::Email(email) => format!("{{ email = \"{email}\" }}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Generate the `[project]` section of a `pyproject.toml`.
|
/// Generate the `[project]` section of a `pyproject.toml`.
|
||||||
fn pyproject_project(
|
fn pyproject_project(
|
||||||
name: &PackageName,
|
name: &PackageName,
|
||||||
requires_python: &RequiresPython,
|
requires_python: &RequiresPython,
|
||||||
|
author: Option<&Author>,
|
||||||
no_readme: bool,
|
no_readme: bool,
|
||||||
) -> String {
|
) -> String {
|
||||||
indoc::formatdoc! {r#"
|
indoc::formatdoc! {r#"
|
||||||
[project]
|
[project]
|
||||||
name = "{name}"
|
name = "{name}"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
description = "Add your description here"{readme}
|
description = "Add your description here"{readme}{authors}
|
||||||
requires-python = "{requires_python}"
|
requires-python = "{requires_python}"
|
||||||
dependencies = []
|
dependencies = []
|
||||||
"#,
|
"#,
|
||||||
readme = if no_readme { "" } else { "\nreadme = \"README.md\"" },
|
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(),
|
requires_python = requires_python.specifiers(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -826,3 +876,63 @@ fn init_vcs(path: &Path, vcs: Option<VersionControlSystem>) -> Result<()> {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Try to get the author information.
|
||||||
|
///
|
||||||
|
/// Currently, this only tries to get the author information from git.
|
||||||
|
fn get_author_info(path: &Path, author_from: AuthorFrom) -> Option<Author> {
|
||||||
|
if matches!(author_from, AuthorFrom::None) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
if matches!(author_from, AuthorFrom::Auto | AuthorFrom::Git) {
|
||||||
|
match get_author_from_git(path) {
|
||||||
|
Ok(author) => return Some(author),
|
||||||
|
Err(err) => warn!("Failed to get author from git: {err}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch the default author from git configuration.
|
||||||
|
fn get_author_from_git(path: &Path) -> Result<Author> {
|
||||||
|
let Ok(git) = which::which("git") else {
|
||||||
|
anyhow::bail!("`git` not found in PATH")
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut name = None;
|
||||||
|
let mut email = None;
|
||||||
|
|
||||||
|
let output = Command::new(&git)
|
||||||
|
.arg("config")
|
||||||
|
.arg("get")
|
||||||
|
.arg("user.name")
|
||||||
|
.current_dir(path)
|
||||||
|
.stdout(Stdio::piped())
|
||||||
|
.stderr(Stdio::null())
|
||||||
|
.output()?;
|
||||||
|
if output.status.success() {
|
||||||
|
name = Some(String::from_utf8_lossy(&output.stdout).trim().to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
let output = Command::new(&git)
|
||||||
|
.arg("config")
|
||||||
|
.arg("get")
|
||||||
|
.arg("user.email")
|
||||||
|
.current_dir(path)
|
||||||
|
.stdout(Stdio::piped())
|
||||||
|
.stderr(Stdio::null())
|
||||||
|
.output()?;
|
||||||
|
if output.status.success() {
|
||||||
|
email = Some(String::from_utf8_lossy(&output.stdout).trim().to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
let author = match (name, email) {
|
||||||
|
(Some(name), Some(email)) => Author::NameEmail { name, email },
|
||||||
|
(Some(name), None) => Author::Name(name),
|
||||||
|
(None, Some(email)) => Author::Email(email),
|
||||||
|
(None, None) => anyhow::bail!("No author information found"),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(author)
|
||||||
|
}
|
||||||
|
|
|
@ -1198,6 +1198,7 @@ async fn run_project(
|
||||||
args.kind,
|
args.kind,
|
||||||
args.vcs,
|
args.vcs,
|
||||||
args.no_readme,
|
args.no_readme,
|
||||||
|
args.author_from,
|
||||||
args.no_pin_python,
|
args.no_pin_python,
|
||||||
args.python,
|
args.python,
|
||||||
args.no_workspace,
|
args.no_workspace,
|
||||||
|
|
|
@ -8,7 +8,7 @@ use url::Url;
|
||||||
use uv_cache::{CacheArgs, Refresh};
|
use uv_cache::{CacheArgs, Refresh};
|
||||||
use uv_cli::{
|
use uv_cli::{
|
||||||
options::{flag, resolver_installer_options, resolver_options},
|
options::{flag, resolver_installer_options, resolver_options},
|
||||||
BuildArgs, ExportArgs, PublishArgs, ToolUpgradeArgs,
|
AuthorFrom, BuildArgs, ExportArgs, PublishArgs, ToolUpgradeArgs,
|
||||||
};
|
};
|
||||||
use uv_cli::{
|
use uv_cli::{
|
||||||
AddArgs, ColorChoice, ExternalCommand, GlobalArgs, InitArgs, ListFormat, LockArgs, Maybe,
|
AddArgs, ColorChoice, ExternalCommand, GlobalArgs, InitArgs, ListFormat, LockArgs, Maybe,
|
||||||
|
@ -164,6 +164,7 @@ pub(crate) struct InitSettings {
|
||||||
pub(crate) kind: InitKind,
|
pub(crate) kind: InitKind,
|
||||||
pub(crate) vcs: Option<VersionControlSystem>,
|
pub(crate) vcs: Option<VersionControlSystem>,
|
||||||
pub(crate) no_readme: bool,
|
pub(crate) no_readme: bool,
|
||||||
|
pub(crate) author_from: Option<AuthorFrom>,
|
||||||
pub(crate) no_pin_python: bool,
|
pub(crate) no_pin_python: bool,
|
||||||
pub(crate) no_workspace: bool,
|
pub(crate) no_workspace: bool,
|
||||||
pub(crate) python: Option<String>,
|
pub(crate) python: Option<String>,
|
||||||
|
@ -184,6 +185,7 @@ impl InitSettings {
|
||||||
script,
|
script,
|
||||||
vcs,
|
vcs,
|
||||||
no_readme,
|
no_readme,
|
||||||
|
author_from,
|
||||||
no_pin_python,
|
no_pin_python,
|
||||||
no_workspace,
|
no_workspace,
|
||||||
python,
|
python,
|
||||||
|
@ -206,6 +208,7 @@ impl InitSettings {
|
||||||
kind,
|
kind,
|
||||||
vcs,
|
vcs,
|
||||||
no_readme,
|
no_readme,
|
||||||
|
author_from,
|
||||||
no_pin_python,
|
no_pin_python,
|
||||||
no_workspace,
|
no_workspace,
|
||||||
python: python.and_then(Maybe::into_option),
|
python: python.and_then(Maybe::into_option),
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use assert_cmd::prelude::OutputAssertExt;
|
||||||
use assert_fs::prelude::*;
|
use assert_fs::prelude::*;
|
||||||
use indoc::indoc;
|
use indoc::indoc;
|
||||||
use insta::assert_snapshot;
|
use insta::assert_snapshot;
|
||||||
|
@ -2188,13 +2189,14 @@ fn init_vcs_none() {
|
||||||
|
|
||||||
/// Run `uv init` from within a Git repository. Do not try to reinitialize one.
|
/// Run `uv init` from within a Git repository. Do not try to reinitialize one.
|
||||||
#[test]
|
#[test]
|
||||||
fn init_inside_git_repo() -> Result<()> {
|
fn init_inside_git_repo() {
|
||||||
let context = TestContext::new("3.12");
|
let context = TestContext::new("3.12");
|
||||||
|
|
||||||
Command::new("git")
|
Command::new("git")
|
||||||
.arg("init")
|
.arg("init")
|
||||||
.current_dir(&context.temp_dir)
|
.current_dir(&context.temp_dir)
|
||||||
.status()?;
|
.assert()
|
||||||
|
.success();
|
||||||
|
|
||||||
let child = context.temp_dir.child("foo");
|
let child = context.temp_dir.child("foo");
|
||||||
|
|
||||||
|
@ -2220,8 +2222,6 @@ fn init_inside_git_repo() -> Result<()> {
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
child.child(".gitignore").assert(predicate::path::missing());
|
child.child(".gitignore").assert(predicate::path::missing());
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -2252,3 +2252,134 @@ fn init_git_not_installed() {
|
||||||
error: Attempted to initialize a Git repository, but `git` was not found in PATH
|
error: Attempted to initialize a Git repository, but `git` was not found in PATH
|
||||||
"###);
|
"###);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn init_with_author() {
|
||||||
|
let context = TestContext::new("3.12");
|
||||||
|
|
||||||
|
// Create a Git repository and set the author.
|
||||||
|
Command::new("git")
|
||||||
|
.arg("init")
|
||||||
|
.current_dir(&context.temp_dir)
|
||||||
|
.assert()
|
||||||
|
.success();
|
||||||
|
Command::new("git")
|
||||||
|
.arg("config")
|
||||||
|
.arg("--local")
|
||||||
|
.arg("user.name")
|
||||||
|
.arg("Alice")
|
||||||
|
.current_dir(&context.temp_dir)
|
||||||
|
.assert()
|
||||||
|
.success();
|
||||||
|
Command::new("git")
|
||||||
|
.arg("config")
|
||||||
|
.arg("--local")
|
||||||
|
.arg("user.email")
|
||||||
|
.arg("alice@example.com")
|
||||||
|
.current_dir(&context.temp_dir)
|
||||||
|
.assert()
|
||||||
|
.success();
|
||||||
|
|
||||||
|
// `authors` is not filled for non-package application by default,
|
||||||
|
context.init().arg("foo").assert().success();
|
||||||
|
let pyproject = context.read("foo/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 = []
|
||||||
|
"#
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// use `--author-from auto` to explicitly fill it.
|
||||||
|
context
|
||||||
|
.init()
|
||||||
|
.arg("bar")
|
||||||
|
.arg("--author-from")
|
||||||
|
.arg("auto")
|
||||||
|
.assert()
|
||||||
|
.success();
|
||||||
|
let pyproject = context.read("bar/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"
|
||||||
|
authors = [
|
||||||
|
{ name = "Alice", email = "alice@example.com" }
|
||||||
|
]
|
||||||
|
requires-python = ">=3.12"
|
||||||
|
dependencies = []
|
||||||
|
"#
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Fill `authors` for library by default,
|
||||||
|
context.init().arg("baz").arg("--lib").assert().success();
|
||||||
|
let pyproject = context.read("baz/pyproject.toml");
|
||||||
|
insta::with_settings!({
|
||||||
|
filters => context.filters(),
|
||||||
|
}, {
|
||||||
|
assert_snapshot!(
|
||||||
|
pyproject, @r#"
|
||||||
|
[project]
|
||||||
|
name = "baz"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "Add your description here"
|
||||||
|
readme = "README.md"
|
||||||
|
authors = [
|
||||||
|
{ name = "Alice", email = "alice@example.com" }
|
||||||
|
]
|
||||||
|
requires-python = ">=3.12"
|
||||||
|
dependencies = []
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = ["hatchling"]
|
||||||
|
build-backend = "hatchling.build"
|
||||||
|
"#
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// use `--authors-from none` to prevent it.
|
||||||
|
context
|
||||||
|
.init()
|
||||||
|
.arg("qux")
|
||||||
|
.arg("--lib")
|
||||||
|
.arg("--author-from")
|
||||||
|
.arg("none")
|
||||||
|
.assert()
|
||||||
|
.success();
|
||||||
|
let pyproject = context.read("qux/pyproject.toml");
|
||||||
|
insta::with_settings!({
|
||||||
|
filters => context.filters(),
|
||||||
|
}, {
|
||||||
|
assert_snapshot!(
|
||||||
|
pyproject, @r#"
|
||||||
|
[project]
|
||||||
|
name = "qux"
|
||||||
|
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"
|
||||||
|
"#
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -440,6 +440,19 @@ uv init [OPTIONS] [PATH]
|
||||||
|
|
||||||
<p>By default, an application is not intended to be built and distributed as a Python package. The <code>--package</code> option can be used to create an application that is distributable, e.g., if you want to distribute a command-line interface via PyPI.</p>
|
<p>By default, an application is not intended to be built and distributed as a Python package. The <code>--package</code> option can be used to create an application that is distributable, e.g., if you want to distribute a command-line interface via PyPI.</p>
|
||||||
|
|
||||||
|
</dd><dt><code>--author-from</code> <i>author-from</i></dt><dd><p>Fill in the <code>authors</code> field in the <code>pyproject.toml</code>.</p>
|
||||||
|
|
||||||
|
<p>By default, uv will attempt to infer the author information from some sources (e.g., Git) (<code>auto</code>). Use <code>--author-from git</code> to only infer from Git configuration. Use <code>--author-from none</code> to avoid inferring the author information.</p>
|
||||||
|
|
||||||
|
<p>Possible values:</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><code>auto</code>: Fetch the author information from some sources (e.g., Git) automatically</li>
|
||||||
|
|
||||||
|
<li><code>git</code>: Fetch the author information from Git configuration only</li>
|
||||||
|
|
||||||
|
<li><code>none</code>: Do not infer the author information</li>
|
||||||
|
</ul>
|
||||||
</dd><dt><code>--cache-dir</code> <i>cache-dir</i></dt><dd><p>Path to the cache directory.</p>
|
</dd><dt><code>--cache-dir</code> <i>cache-dir</i></dt><dd><p>Path to the cache directory.</p>
|
||||||
|
|
||||||
<p>Defaults to <code>$HOME/Library/Caches/uv</code> on macOS, <code>$XDG_CACHE_HOME/uv</code> or <code>$HOME/.cache/uv</code> on Linux, and <code>%LOCALAPPDATA%\uv\cache</code> on Windows.</p>
|
<p>Defaults to <code>$HOME/Library/Caches/uv</code> on macOS, <code>$XDG_CACHE_HOME/uv</code> or <code>$HOME/.cache/uv</code> on Linux, and <code>%LOCALAPPDATA%\uv\cache</code> on Windows.</p>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue