mirror of https://github.com/astral-sh/uv
1634 lines
59 KiB
Rust
1634 lines
59 KiB
Rust
use std::borrow::Cow;
|
|
use std::ffi::OsString;
|
|
use std::fmt::Write;
|
|
use std::io::stdout;
|
|
use std::path::Path;
|
|
use std::process::ExitCode;
|
|
|
|
use anstream::eprintln;
|
|
use anyhow::Result;
|
|
use clap::error::{ContextKind, ContextValue};
|
|
use clap::{CommandFactory, Parser};
|
|
use owo_colors::OwoColorize;
|
|
use settings::PipTreeSettings;
|
|
use tokio::task::spawn_blocking;
|
|
use tracing::{debug, instrument};
|
|
use uv_cache::{Cache, Refresh};
|
|
use uv_cache_info::Timestamp;
|
|
use uv_cli::{
|
|
compat::CompatArgs, BuildBackendCommand, CacheCommand, CacheNamespace, Cli, Commands,
|
|
PipCommand, PipNamespace, ProjectCommand,
|
|
};
|
|
use uv_cli::{PythonCommand, PythonNamespace, ToolCommand, ToolNamespace, TopLevelArgs};
|
|
#[cfg(feature = "self-update")]
|
|
use uv_cli::{SelfCommand, SelfNamespace, SelfUpdateArgs};
|
|
use uv_fs::CWD;
|
|
use uv_requirements::RequirementsSource;
|
|
use uv_scripts::{Pep723Item, Pep723Metadata, Pep723Script};
|
|
use uv_settings::{Combine, FilesystemOptions, Options};
|
|
use uv_warnings::{warn_user, warn_user_once};
|
|
use uv_workspace::{DiscoveryOptions, Workspace};
|
|
|
|
use crate::commands::{ExitStatus, RunCommand, ToolRunCommand};
|
|
use crate::printer::Printer;
|
|
use crate::settings::{
|
|
CacheSettings, GlobalSettings, PipCheckSettings, PipCompileSettings, PipFreezeSettings,
|
|
PipInstallSettings, PipListSettings, PipShowSettings, PipSyncSettings, PipUninstallSettings,
|
|
PublishSettings,
|
|
};
|
|
|
|
pub(crate) mod commands;
|
|
pub(crate) mod logging;
|
|
pub(crate) mod printer;
|
|
pub(crate) mod settings;
|
|
pub(crate) mod version;
|
|
|
|
#[instrument(skip_all)]
|
|
async fn run(mut cli: Cli) -> Result<ExitStatus> {
|
|
// Enable flag to pick up warnings generated by workspace loading.
|
|
if !cli.top_level.global_args.quiet {
|
|
uv_warnings::enable();
|
|
}
|
|
|
|
// Switch directories as early as possible.
|
|
if let Some(directory) = cli.top_level.global_args.directory.as_ref() {
|
|
std::env::set_current_dir(directory)?;
|
|
}
|
|
|
|
// Determine the project directory.
|
|
let project_dir = cli
|
|
.top_level
|
|
.global_args
|
|
.project
|
|
.as_deref()
|
|
.map(std::path::absolute)
|
|
.transpose()?
|
|
.map(Cow::Owned)
|
|
.unwrap_or_else(|| Cow::Borrowed(&*CWD));
|
|
|
|
// The `--isolated` argument is deprecated on preview APIs, and warns on non-preview APIs.
|
|
let deprecated_isolated = if cli.top_level.global_args.isolated {
|
|
match &*cli.command {
|
|
// Supports `--isolated` as its own argument, so we can't warn either way.
|
|
Commands::Tool(ToolNamespace {
|
|
command: ToolCommand::Uvx(_) | ToolCommand::Run(_),
|
|
}) => false,
|
|
|
|
// Supports `--isolated` as its own argument, so we can't warn either way.
|
|
Commands::Project(command) if matches!(**command, ProjectCommand::Run(_)) => false,
|
|
|
|
// `--isolated` moved to `--no-workspace`.
|
|
Commands::Project(command) if matches!(**command, ProjectCommand::Init(_)) => {
|
|
warn_user!("The `--isolated` flag is deprecated and has no effect. Instead, use `--no-config` to prevent uv from discovering configuration files or `--no-workspace` to prevent uv from adding the initialized project to the containing workspace.");
|
|
false
|
|
}
|
|
|
|
// Preview APIs. Ignore `--isolated` and warn.
|
|
Commands::Project(_) | Commands::Tool(_) | Commands::Python(_) => {
|
|
warn_user!("The `--isolated` flag is deprecated and has no effect. Instead, use `--no-config` to prevent uv from discovering configuration files.");
|
|
false
|
|
}
|
|
|
|
// Non-preview APIs. Continue to support `--isolated`, but warn.
|
|
_ => {
|
|
warn_user!("The `--isolated` flag is deprecated. Instead, use `--no-config` to prevent uv from discovering configuration files.");
|
|
true
|
|
}
|
|
}
|
|
} else {
|
|
false
|
|
};
|
|
|
|
// Load configuration from the filesystem, prioritizing (in order):
|
|
// 1. The configuration file specified on the command-line.
|
|
// 2. The nearest configuration file (`uv.toml` or `pyproject.toml`) above the workspace root.
|
|
// If found, this file is combined with the user configuration file.
|
|
// 3. The nearest configuration file (`uv.toml` or `pyproject.toml`) in the directory tree,
|
|
// starting from the current directory.
|
|
let filesystem = if let Some(config_file) = cli.top_level.config_file.as_ref() {
|
|
if config_file
|
|
.file_name()
|
|
.is_some_and(|file_name| file_name == "pyproject.toml")
|
|
{
|
|
warn_user!("The `--config-file` argument expects to receive a `uv.toml` file, not a `pyproject.toml`. If you're trying to run a command from another project, use the `--project` argument instead.");
|
|
}
|
|
Some(FilesystemOptions::from_file(config_file)?)
|
|
} else if deprecated_isolated || cli.top_level.no_config {
|
|
None
|
|
} else if matches!(&*cli.command, Commands::Tool(_)) {
|
|
// For commands that operate at the user-level, ignore local configuration.
|
|
FilesystemOptions::user()?
|
|
} else if let Ok(workspace) =
|
|
Workspace::discover(&project_dir, &DiscoveryOptions::default()).await
|
|
{
|
|
let project = FilesystemOptions::find(workspace.install_path())?;
|
|
let user = FilesystemOptions::user()?;
|
|
project.combine(user)
|
|
} else {
|
|
let project = FilesystemOptions::find(&project_dir)?;
|
|
let user = FilesystemOptions::user()?;
|
|
project.combine(user)
|
|
};
|
|
|
|
// Parse the external command, if necessary.
|
|
let run_command = if let Commands::Project(command) = &mut *cli.command {
|
|
if let ProjectCommand::Run(uv_cli::RunArgs {
|
|
command: Some(command),
|
|
module,
|
|
script,
|
|
..
|
|
}) = &mut **command
|
|
{
|
|
let settings = GlobalSettings::resolve(&cli.top_level.global_args, filesystem.as_ref());
|
|
Some(
|
|
RunCommand::from_args(
|
|
command,
|
|
*module,
|
|
*script,
|
|
settings.connectivity,
|
|
settings.native_tls,
|
|
)
|
|
.await?,
|
|
)
|
|
} else {
|
|
None
|
|
}
|
|
} else {
|
|
None
|
|
};
|
|
|
|
// If the target is a PEP 723 script, parse it.
|
|
let script = if let Commands::Project(command) = &*cli.command {
|
|
if let ProjectCommand::Run(uv_cli::RunArgs { .. }) = &**command {
|
|
match run_command.as_ref() {
|
|
Some(
|
|
RunCommand::PythonScript(script, _) | RunCommand::PythonGuiScript(script, _),
|
|
) => Pep723Script::read(&script).await?.map(Pep723Item::Script),
|
|
Some(RunCommand::PythonRemote(script, _)) => {
|
|
Pep723Metadata::read(&script).await?.map(Pep723Item::Remote)
|
|
}
|
|
Some(RunCommand::PythonStdin(contents)) => {
|
|
Pep723Metadata::parse(contents)?.map(Pep723Item::Stdin)
|
|
}
|
|
_ => None,
|
|
}
|
|
} else if let ProjectCommand::Remove(uv_cli::RemoveArgs {
|
|
script: Some(script),
|
|
..
|
|
}) = &**command
|
|
{
|
|
Pep723Script::read(&script).await?.map(Pep723Item::Script)
|
|
} else {
|
|
None
|
|
}
|
|
} else {
|
|
None
|
|
};
|
|
|
|
// If the target is a PEP 723 script, merge the metadata into the filesystem metadata.
|
|
let filesystem = script
|
|
.as_ref()
|
|
.map(Pep723Item::metadata)
|
|
.and_then(|metadata| metadata.tool.as_ref())
|
|
.and_then(|tool| tool.uv.as_ref())
|
|
.map(|uv| Options::simple(uv.globals.clone(), uv.top_level.clone()))
|
|
.map(FilesystemOptions::from)
|
|
.combine(filesystem);
|
|
|
|
// Resolve the global settings.
|
|
let globals = GlobalSettings::resolve(&cli.top_level.global_args, filesystem.as_ref());
|
|
|
|
// Resolve the cache settings.
|
|
let cache_settings = CacheSettings::resolve(*cli.top_level.cache_args, filesystem.as_ref());
|
|
|
|
// Configure the `tracing` crate, which controls internal logging.
|
|
#[cfg(feature = "tracing-durations-export")]
|
|
let (duration_layer, _duration_guard) = logging::setup_duration()?;
|
|
#[cfg(not(feature = "tracing-durations-export"))]
|
|
let duration_layer = None::<tracing_subscriber::layer::Identity>;
|
|
logging::setup_logging(
|
|
match globals.verbose {
|
|
0 => logging::Level::Default,
|
|
1 => logging::Level::Verbose,
|
|
2.. => logging::Level::ExtraVerbose,
|
|
},
|
|
duration_layer,
|
|
)?;
|
|
|
|
// Configure the `Printer`, which controls user-facing output in the CLI.
|
|
let printer = if globals.quiet {
|
|
Printer::Quiet
|
|
} else if globals.verbose > 0 {
|
|
Printer::Verbose
|
|
} else if globals.no_progress {
|
|
Printer::NoProgress
|
|
} else {
|
|
Printer::Default
|
|
};
|
|
|
|
// Configure the `warn!` macros, which control user-facing warnings in the CLI.
|
|
if globals.quiet {
|
|
uv_warnings::disable();
|
|
} else {
|
|
uv_warnings::enable();
|
|
}
|
|
|
|
anstream::ColorChoice::write_global(globals.color.into());
|
|
|
|
miette::set_hook(Box::new(|_| {
|
|
Box::new(
|
|
miette::MietteHandlerOpts::new()
|
|
.break_words(false)
|
|
.word_separator(textwrap::WordSeparator::AsciiSpace)
|
|
.word_splitter(textwrap::WordSplitter::NoHyphenation)
|
|
.wrap_lines(std::env::var("UV_NO_WRAP").map(|_| false).unwrap_or(true))
|
|
.build(),
|
|
)
|
|
}))?;
|
|
|
|
rayon::ThreadPoolBuilder::new()
|
|
.num_threads(globals.concurrency.installs)
|
|
.build_global()
|
|
.expect("failed to initialize global rayon pool");
|
|
|
|
debug!("uv {}", version::version());
|
|
|
|
// Write out any resolved settings.
|
|
macro_rules! show_settings {
|
|
($arg:expr) => {
|
|
if globals.show_settings {
|
|
writeln!(printer.stdout(), "{:#?}", $arg)?;
|
|
return Ok(ExitStatus::Success);
|
|
}
|
|
};
|
|
($arg:expr, false) => {
|
|
if globals.show_settings {
|
|
writeln!(printer.stdout(), "{:#?}", $arg)?;
|
|
}
|
|
};
|
|
}
|
|
show_settings!(globals, false);
|
|
show_settings!(cache_settings, false);
|
|
|
|
// Configure the cache.
|
|
let cache = Cache::from_settings(cache_settings.no_cache, cache_settings.cache_dir)?;
|
|
|
|
let result = match *cli.command {
|
|
Commands::Help(args) => commands::help(
|
|
args.command.unwrap_or_default().as_slice(),
|
|
printer,
|
|
args.no_pager,
|
|
),
|
|
Commands::Pip(PipNamespace {
|
|
command: PipCommand::Compile(args),
|
|
}) => {
|
|
args.compat_args.validate()?;
|
|
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = PipCompileSettings::resolve(args, filesystem);
|
|
show_settings!(args);
|
|
|
|
// Initialize the cache.
|
|
let cache = cache.init()?.with_refresh(
|
|
args.refresh
|
|
.combine(Refresh::from(args.settings.reinstall.clone()))
|
|
.combine(Refresh::from(args.settings.upgrade.clone())),
|
|
);
|
|
|
|
let requirements = args
|
|
.src_file
|
|
.into_iter()
|
|
.map(RequirementsSource::from_requirements_file)
|
|
.collect::<Vec<_>>();
|
|
let constraints = args
|
|
.constraint
|
|
.into_iter()
|
|
.map(RequirementsSource::from_constraints_txt)
|
|
.collect::<Vec<_>>();
|
|
let overrides = args
|
|
.r#override
|
|
.into_iter()
|
|
.map(RequirementsSource::from_overrides_txt)
|
|
.collect::<Vec<_>>();
|
|
let build_constraints = args
|
|
.build_constraint
|
|
.into_iter()
|
|
.map(RequirementsSource::from_constraints_txt)
|
|
.collect::<Vec<_>>();
|
|
|
|
commands::pip_compile(
|
|
&requirements,
|
|
&constraints,
|
|
&overrides,
|
|
&build_constraints,
|
|
args.constraints_from_workspace,
|
|
args.overrides_from_workspace,
|
|
args.environments,
|
|
args.settings.extras,
|
|
args.settings.output_file.as_deref(),
|
|
args.settings.resolution,
|
|
args.settings.prerelease,
|
|
args.settings.dependency_mode,
|
|
args.settings.upgrade,
|
|
args.settings.generate_hashes,
|
|
args.settings.no_emit_package,
|
|
args.settings.no_strip_extras,
|
|
args.settings.no_strip_markers,
|
|
!args.settings.no_annotate,
|
|
!args.settings.no_header,
|
|
args.settings.custom_compile_command,
|
|
args.settings.emit_index_url,
|
|
args.settings.emit_find_links,
|
|
args.settings.emit_build_options,
|
|
args.settings.emit_marker_expression,
|
|
args.settings.emit_index_annotation,
|
|
args.settings.index_locations,
|
|
args.settings.index_strategy,
|
|
args.settings.dependency_metadata,
|
|
args.settings.keyring_provider,
|
|
args.settings.allow_insecure_host,
|
|
args.settings.config_setting,
|
|
globals.connectivity,
|
|
args.settings.no_build_isolation,
|
|
args.settings.no_build_isolation_package,
|
|
args.settings.build_options,
|
|
args.settings.python_version,
|
|
args.settings.python_platform,
|
|
args.settings.universal,
|
|
args.settings.exclude_newer,
|
|
args.settings.sources,
|
|
args.settings.annotation_style,
|
|
args.settings.link_mode,
|
|
args.settings.python,
|
|
args.settings.system,
|
|
globals.python_preference,
|
|
globals.concurrency,
|
|
globals.native_tls,
|
|
globals.quiet,
|
|
cache,
|
|
printer,
|
|
)
|
|
.await
|
|
}
|
|
Commands::Pip(PipNamespace {
|
|
command: PipCommand::Sync(args),
|
|
}) => {
|
|
args.compat_args.validate()?;
|
|
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = PipSyncSettings::resolve(args, filesystem);
|
|
show_settings!(args);
|
|
|
|
// Initialize the cache.
|
|
let cache = cache.init()?.with_refresh(
|
|
args.refresh
|
|
.combine(Refresh::from(args.settings.reinstall.clone()))
|
|
.combine(Refresh::from(args.settings.upgrade.clone())),
|
|
);
|
|
|
|
let requirements = args
|
|
.src_file
|
|
.into_iter()
|
|
.map(RequirementsSource::from_requirements_file)
|
|
.collect::<Vec<_>>();
|
|
let constraints = args
|
|
.constraint
|
|
.into_iter()
|
|
.map(RequirementsSource::from_constraints_txt)
|
|
.collect::<Vec<_>>();
|
|
let build_constraints = args
|
|
.build_constraint
|
|
.into_iter()
|
|
.map(RequirementsSource::from_constraints_txt)
|
|
.collect::<Vec<_>>();
|
|
|
|
commands::pip_sync(
|
|
&requirements,
|
|
&constraints,
|
|
&build_constraints,
|
|
args.settings.reinstall,
|
|
args.settings.link_mode,
|
|
args.settings.compile_bytecode,
|
|
args.settings.hash_checking,
|
|
args.settings.index_locations,
|
|
args.settings.index_strategy,
|
|
args.settings.dependency_metadata,
|
|
args.settings.keyring_provider,
|
|
args.settings.allow_insecure_host,
|
|
args.settings.allow_empty_requirements,
|
|
globals.connectivity,
|
|
&args.settings.config_setting,
|
|
args.settings.no_build_isolation,
|
|
args.settings.no_build_isolation_package,
|
|
args.settings.build_options,
|
|
args.settings.python_version,
|
|
args.settings.python_platform,
|
|
args.settings.strict,
|
|
args.settings.exclude_newer,
|
|
args.settings.python,
|
|
args.settings.system,
|
|
args.settings.break_system_packages,
|
|
args.settings.target,
|
|
args.settings.prefix,
|
|
args.settings.sources,
|
|
globals.concurrency,
|
|
globals.native_tls,
|
|
cache,
|
|
args.dry_run,
|
|
printer,
|
|
)
|
|
.await
|
|
}
|
|
Commands::Pip(PipNamespace {
|
|
command: PipCommand::Install(args),
|
|
}) => {
|
|
args.compat_args.validate()?;
|
|
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = PipInstallSettings::resolve(args, filesystem);
|
|
show_settings!(args);
|
|
|
|
// Initialize the cache.
|
|
let cache = cache.init()?.with_refresh(
|
|
args.refresh
|
|
.combine(Refresh::from(args.settings.reinstall.clone()))
|
|
.combine(Refresh::from(args.settings.upgrade.clone())),
|
|
);
|
|
|
|
let requirements = args
|
|
.package
|
|
.into_iter()
|
|
.map(RequirementsSource::from_package)
|
|
.chain(args.editable.into_iter().map(RequirementsSource::Editable))
|
|
.chain(
|
|
args.requirement
|
|
.into_iter()
|
|
.map(RequirementsSource::from_requirements_file),
|
|
)
|
|
.collect::<Vec<_>>();
|
|
let constraints = args
|
|
.constraint
|
|
.into_iter()
|
|
.map(RequirementsSource::from_constraints_txt)
|
|
.collect::<Vec<_>>();
|
|
let overrides = args
|
|
.r#override
|
|
.into_iter()
|
|
.map(RequirementsSource::from_overrides_txt)
|
|
.collect::<Vec<_>>();
|
|
let build_constraints = args
|
|
.build_constraint
|
|
.into_iter()
|
|
.map(RequirementsSource::from_overrides_txt)
|
|
.collect::<Vec<_>>();
|
|
|
|
commands::pip_install(
|
|
&requirements,
|
|
&constraints,
|
|
&overrides,
|
|
&build_constraints,
|
|
args.constraints_from_workspace,
|
|
args.overrides_from_workspace,
|
|
&args.settings.extras,
|
|
args.settings.resolution,
|
|
args.settings.prerelease,
|
|
args.settings.dependency_mode,
|
|
args.settings.upgrade,
|
|
args.settings.index_locations,
|
|
args.settings.index_strategy,
|
|
args.settings.dependency_metadata,
|
|
args.settings.keyring_provider,
|
|
args.settings.allow_insecure_host,
|
|
args.settings.reinstall,
|
|
args.settings.link_mode,
|
|
args.settings.compile_bytecode,
|
|
args.settings.hash_checking,
|
|
globals.connectivity,
|
|
&args.settings.config_setting,
|
|
args.settings.no_build_isolation,
|
|
args.settings.no_build_isolation_package,
|
|
args.settings.build_options,
|
|
args.modifications,
|
|
args.settings.python_version,
|
|
args.settings.python_platform,
|
|
args.settings.strict,
|
|
args.settings.exclude_newer,
|
|
args.settings.sources,
|
|
args.settings.python,
|
|
args.settings.system,
|
|
args.settings.break_system_packages,
|
|
args.settings.target,
|
|
args.settings.prefix,
|
|
globals.concurrency,
|
|
globals.native_tls,
|
|
cache,
|
|
args.dry_run,
|
|
printer,
|
|
)
|
|
.await
|
|
}
|
|
Commands::Pip(PipNamespace {
|
|
command: PipCommand::Uninstall(args),
|
|
}) => {
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = PipUninstallSettings::resolve(args, filesystem);
|
|
show_settings!(args);
|
|
|
|
// Initialize the cache.
|
|
let cache = cache.init()?;
|
|
|
|
let sources = args
|
|
.package
|
|
.into_iter()
|
|
.map(RequirementsSource::from_package)
|
|
.chain(
|
|
args.requirement
|
|
.into_iter()
|
|
.map(RequirementsSource::from_requirements_txt),
|
|
)
|
|
.collect::<Vec<_>>();
|
|
commands::pip_uninstall(
|
|
&sources,
|
|
args.settings.python,
|
|
args.settings.system,
|
|
args.settings.break_system_packages,
|
|
args.settings.target,
|
|
args.settings.prefix,
|
|
cache,
|
|
globals.connectivity,
|
|
globals.native_tls,
|
|
args.settings.keyring_provider,
|
|
args.settings.allow_insecure_host,
|
|
printer,
|
|
)
|
|
.await
|
|
}
|
|
Commands::Pip(PipNamespace {
|
|
command: PipCommand::Freeze(args),
|
|
}) => {
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = PipFreezeSettings::resolve(args, filesystem);
|
|
show_settings!(args);
|
|
|
|
// Initialize the cache.
|
|
let cache = cache.init()?;
|
|
|
|
commands::pip_freeze(
|
|
args.exclude_editable,
|
|
args.settings.strict,
|
|
args.settings.python.as_deref(),
|
|
args.settings.system,
|
|
&cache,
|
|
printer,
|
|
)
|
|
}
|
|
Commands::Pip(PipNamespace {
|
|
command: PipCommand::List(args),
|
|
}) => {
|
|
args.compat_args.validate()?;
|
|
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = PipListSettings::resolve(args, filesystem);
|
|
show_settings!(args);
|
|
|
|
// Initialize the cache.
|
|
let cache = cache.init()?;
|
|
|
|
commands::pip_list(
|
|
args.editable,
|
|
&args.exclude,
|
|
&args.format,
|
|
args.settings.strict,
|
|
args.settings.python.as_deref(),
|
|
args.settings.system,
|
|
&cache,
|
|
printer,
|
|
)
|
|
}
|
|
Commands::Pip(PipNamespace {
|
|
command: PipCommand::Show(args),
|
|
}) => {
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = PipShowSettings::resolve(args, filesystem);
|
|
show_settings!(args);
|
|
|
|
// Initialize the cache.
|
|
let cache = cache.init()?;
|
|
|
|
commands::pip_show(
|
|
args.package,
|
|
args.settings.strict,
|
|
args.settings.python.as_deref(),
|
|
args.settings.system,
|
|
&cache,
|
|
printer,
|
|
)
|
|
}
|
|
Commands::Pip(PipNamespace {
|
|
command: PipCommand::Tree(args),
|
|
}) => {
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = PipTreeSettings::resolve(args, filesystem);
|
|
|
|
// Initialize the cache.
|
|
let cache = cache.init()?;
|
|
|
|
commands::pip_tree(
|
|
args.show_version_specifiers,
|
|
args.depth,
|
|
args.prune,
|
|
args.package,
|
|
args.no_dedupe,
|
|
args.invert,
|
|
args.shared.strict,
|
|
args.shared.python.as_deref(),
|
|
args.shared.system,
|
|
&cache,
|
|
printer,
|
|
)
|
|
}
|
|
Commands::Pip(PipNamespace {
|
|
command: PipCommand::Check(args),
|
|
}) => {
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = PipCheckSettings::resolve(args, filesystem);
|
|
show_settings!(args);
|
|
|
|
// Initialize the cache.
|
|
let cache = cache.init()?;
|
|
|
|
commands::pip_check(
|
|
args.settings.python.as_deref(),
|
|
args.settings.system,
|
|
&cache,
|
|
printer,
|
|
)
|
|
}
|
|
Commands::Cache(CacheNamespace {
|
|
command: CacheCommand::Clean(args),
|
|
})
|
|
| Commands::Clean(args) => {
|
|
show_settings!(args);
|
|
commands::cache_clean(&args.package, &cache, printer)
|
|
}
|
|
Commands::Cache(CacheNamespace {
|
|
command: CacheCommand::Prune(args),
|
|
}) => {
|
|
show_settings!(args);
|
|
commands::cache_prune(args.ci, &cache, printer)
|
|
}
|
|
Commands::Cache(CacheNamespace {
|
|
command: CacheCommand::Dir,
|
|
}) => {
|
|
commands::cache_dir(&cache);
|
|
Ok(ExitStatus::Success)
|
|
}
|
|
Commands::Build(args) => {
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = settings::BuildSettings::resolve(args, filesystem);
|
|
show_settings!(args);
|
|
|
|
// Initialize the cache.
|
|
let cache = cache.init()?.with_refresh(
|
|
args.refresh
|
|
.combine(Refresh::from(args.settings.upgrade.clone())),
|
|
);
|
|
|
|
// Resolve the build constraints.
|
|
let build_constraints = args
|
|
.build_constraint
|
|
.into_iter()
|
|
.map(RequirementsSource::from_constraints_txt)
|
|
.collect::<Vec<_>>();
|
|
|
|
commands::build_frontend(
|
|
&project_dir,
|
|
args.src,
|
|
args.package,
|
|
args.all,
|
|
args.out_dir,
|
|
args.sdist,
|
|
args.wheel,
|
|
args.build_logs,
|
|
build_constraints,
|
|
args.hash_checking,
|
|
args.python,
|
|
args.settings,
|
|
cli.top_level.no_config,
|
|
globals.python_preference,
|
|
globals.python_downloads,
|
|
globals.connectivity,
|
|
globals.concurrency,
|
|
globals.native_tls,
|
|
&cache,
|
|
printer,
|
|
)
|
|
.await
|
|
}
|
|
Commands::Venv(args) => {
|
|
args.compat_args.validate()?;
|
|
|
|
if args.no_system {
|
|
warn_user_once!("The `--no-system` flag has no effect, a system Python interpreter is always used in `uv venv`");
|
|
}
|
|
|
|
if args.system {
|
|
warn_user_once!("The `--system` flag has no effect, a system Python interpreter is always used in `uv venv`");
|
|
}
|
|
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = settings::VenvSettings::resolve(args, filesystem);
|
|
show_settings!(args);
|
|
|
|
// Initialize the cache.
|
|
let cache = cache.init()?;
|
|
|
|
// Since we use ".venv" as the default name, we use "." as the default prompt.
|
|
let prompt = args.prompt.or_else(|| {
|
|
if args.path.is_none() {
|
|
Some(".".to_string())
|
|
} else {
|
|
None
|
|
}
|
|
});
|
|
|
|
commands::venv(
|
|
&project_dir,
|
|
args.path,
|
|
args.settings.python.as_deref(),
|
|
globals.python_preference,
|
|
globals.python_downloads,
|
|
args.settings.link_mode,
|
|
&args.settings.index_locations,
|
|
args.settings.index_strategy,
|
|
args.settings.dependency_metadata,
|
|
args.settings.keyring_provider,
|
|
args.settings.allow_insecure_host,
|
|
uv_virtualenv::Prompt::from_args(prompt),
|
|
args.system_site_packages,
|
|
globals.connectivity,
|
|
args.seed,
|
|
args.allow_existing,
|
|
args.settings.exclude_newer,
|
|
globals.concurrency,
|
|
globals.native_tls,
|
|
cli.top_level.no_config,
|
|
args.no_project,
|
|
&cache,
|
|
printer,
|
|
args.relocatable,
|
|
)
|
|
.await
|
|
}
|
|
Commands::Project(project) => {
|
|
Box::pin(run_project(
|
|
project,
|
|
&project_dir,
|
|
run_command,
|
|
script,
|
|
globals,
|
|
cli.top_level.no_config,
|
|
filesystem,
|
|
cache,
|
|
printer,
|
|
))
|
|
.await
|
|
}
|
|
#[cfg(feature = "self-update")]
|
|
Commands::Self_(SelfNamespace {
|
|
command:
|
|
SelfCommand::Update(SelfUpdateArgs {
|
|
target_version,
|
|
token,
|
|
}),
|
|
}) => commands::self_update(target_version, token, printer).await,
|
|
Commands::Version { output_format } => {
|
|
commands::version(output_format, &mut stdout())?;
|
|
Ok(ExitStatus::Success)
|
|
}
|
|
Commands::GenerateShellCompletion(args) => {
|
|
args.shell.generate(&mut Cli::command(), &mut stdout());
|
|
Ok(ExitStatus::Success)
|
|
}
|
|
Commands::Tool(ToolNamespace {
|
|
command: run_variant @ (ToolCommand::Uvx(_) | ToolCommand::Run(_)),
|
|
}) => {
|
|
let (args, invocation_source) = match run_variant {
|
|
ToolCommand::Uvx(args) => (args, ToolRunCommand::Uvx),
|
|
ToolCommand::Run(args) => (args, ToolRunCommand::ToolRun),
|
|
// OK guarded by the outer match statement
|
|
_ => unreachable!(),
|
|
};
|
|
|
|
if let Some(shell) = args.generate_shell_completion {
|
|
// uvx: combine `uv tool uvx` with the top-level arguments
|
|
let mut uvx = Cli::command()
|
|
.find_subcommand("tool")
|
|
.unwrap()
|
|
.find_subcommand("uvx")
|
|
.unwrap()
|
|
.clone()
|
|
// Avoid duplicating the `--help` and `--version` flags from the top-level arguments.
|
|
.disable_help_flag(true)
|
|
.disable_version_flag(true)
|
|
.version(env!("CARGO_PKG_VERSION"));
|
|
|
|
// Copy the top-level arguments into the `uvx` command. (Like `Args::augment_args`, but
|
|
// expanded to skip collisions.)
|
|
for arg in TopLevelArgs::command().get_arguments() {
|
|
if arg.get_id() != "isolated" {
|
|
uvx = uvx.arg(arg);
|
|
}
|
|
}
|
|
shell.generate(&mut uvx, &mut stdout());
|
|
return Ok(ExitStatus::Success);
|
|
}
|
|
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = settings::ToolRunSettings::resolve(args, filesystem, invocation_source);
|
|
show_settings!(args);
|
|
|
|
// Initialize the cache.
|
|
let cache = cache.init()?.with_refresh(
|
|
args.refresh
|
|
.combine(Refresh::from(args.settings.reinstall.clone()))
|
|
.combine(Refresh::from(args.settings.upgrade.clone())),
|
|
);
|
|
|
|
let requirements = args
|
|
.with
|
|
.into_iter()
|
|
.map(RequirementsSource::from_with_package)
|
|
.chain(
|
|
args.with_editable
|
|
.into_iter()
|
|
.map(RequirementsSource::Editable),
|
|
)
|
|
.chain(
|
|
args.with_requirements
|
|
.into_iter()
|
|
.map(RequirementsSource::from_requirements_file),
|
|
)
|
|
.collect::<Vec<_>>();
|
|
|
|
commands::tool_run(
|
|
args.command,
|
|
args.from,
|
|
&requirements,
|
|
args.show_resolution || globals.verbose > 0,
|
|
args.python,
|
|
args.settings,
|
|
invocation_source,
|
|
args.isolated,
|
|
globals.python_preference,
|
|
globals.python_downloads,
|
|
globals.connectivity,
|
|
globals.concurrency,
|
|
globals.native_tls,
|
|
cache,
|
|
printer,
|
|
)
|
|
.await
|
|
}
|
|
Commands::Tool(ToolNamespace {
|
|
command: ToolCommand::Install(args),
|
|
}) => {
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = settings::ToolInstallSettings::resolve(args, filesystem);
|
|
show_settings!(args);
|
|
|
|
// Initialize the cache.
|
|
let cache = cache.init()?.with_refresh(
|
|
args.refresh
|
|
.combine(Refresh::from(args.settings.reinstall.clone()))
|
|
.combine(Refresh::from(args.settings.upgrade.clone())),
|
|
);
|
|
|
|
let requirements = args
|
|
.with
|
|
.into_iter()
|
|
.map(RequirementsSource::from_with_package)
|
|
.chain(
|
|
args.with_requirements
|
|
.into_iter()
|
|
.map(RequirementsSource::from_requirements_file),
|
|
)
|
|
.collect::<Vec<_>>();
|
|
|
|
Box::pin(commands::tool_install(
|
|
args.package,
|
|
args.editable,
|
|
args.from,
|
|
&requirements,
|
|
args.python,
|
|
args.force,
|
|
args.options,
|
|
args.settings,
|
|
globals.python_preference,
|
|
globals.python_downloads,
|
|
globals.connectivity,
|
|
globals.concurrency,
|
|
globals.native_tls,
|
|
cache,
|
|
printer,
|
|
))
|
|
.await
|
|
}
|
|
Commands::Tool(ToolNamespace {
|
|
command: ToolCommand::List(args),
|
|
}) => {
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = settings::ToolListSettings::resolve(args, filesystem);
|
|
show_settings!(args);
|
|
|
|
// Initialize the cache.
|
|
let cache = cache.init()?;
|
|
|
|
commands::tool_list(
|
|
args.show_paths,
|
|
args.show_version_specifiers,
|
|
&cache,
|
|
printer,
|
|
)
|
|
.await
|
|
}
|
|
Commands::Tool(ToolNamespace {
|
|
command: ToolCommand::Upgrade(args),
|
|
}) => {
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = settings::ToolUpgradeSettings::resolve(args, filesystem);
|
|
show_settings!(args);
|
|
|
|
// Initialize the cache.
|
|
let cache = cache.init()?.with_refresh(Refresh::All(Timestamp::now()));
|
|
|
|
commands::tool_upgrade(
|
|
args.name,
|
|
args.python,
|
|
globals.connectivity,
|
|
args.args,
|
|
args.filesystem,
|
|
globals.python_preference,
|
|
globals.python_downloads,
|
|
globals.concurrency,
|
|
globals.native_tls,
|
|
&cache,
|
|
printer,
|
|
)
|
|
.await
|
|
}
|
|
Commands::Tool(ToolNamespace {
|
|
command: ToolCommand::Uninstall(args),
|
|
}) => {
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = settings::ToolUninstallSettings::resolve(args, filesystem);
|
|
show_settings!(args);
|
|
|
|
commands::tool_uninstall(args.name, printer).await
|
|
}
|
|
Commands::Tool(ToolNamespace {
|
|
command: ToolCommand::UpdateShell,
|
|
}) => {
|
|
commands::tool_update_shell(printer).await?;
|
|
Ok(ExitStatus::Success)
|
|
}
|
|
Commands::Tool(ToolNamespace {
|
|
command: ToolCommand::Dir(args),
|
|
}) => {
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = settings::ToolDirSettings::resolve(args, filesystem);
|
|
show_settings!(args);
|
|
|
|
commands::tool_dir(args.bin, globals.preview)?;
|
|
Ok(ExitStatus::Success)
|
|
}
|
|
Commands::Python(PythonNamespace {
|
|
command: PythonCommand::List(args),
|
|
}) => {
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = settings::PythonListSettings::resolve(args, filesystem);
|
|
show_settings!(args);
|
|
|
|
// Initialize the cache.
|
|
let cache = cache.init()?;
|
|
|
|
commands::python_list(
|
|
args.kinds,
|
|
args.all_versions,
|
|
args.all_platforms,
|
|
globals.python_preference,
|
|
globals.python_downloads,
|
|
&cache,
|
|
printer,
|
|
)
|
|
.await
|
|
}
|
|
Commands::Python(PythonNamespace {
|
|
command: PythonCommand::Install(args),
|
|
}) => {
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = settings::PythonInstallSettings::resolve(args, filesystem);
|
|
show_settings!(args);
|
|
|
|
commands::python_install(
|
|
&project_dir,
|
|
args.targets,
|
|
args.reinstall,
|
|
globals.python_downloads,
|
|
globals.native_tls,
|
|
globals.connectivity,
|
|
cli.top_level.no_config,
|
|
printer,
|
|
)
|
|
.await
|
|
}
|
|
Commands::Python(PythonNamespace {
|
|
command: PythonCommand::Uninstall(args),
|
|
}) => {
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = settings::PythonUninstallSettings::resolve(args, filesystem);
|
|
show_settings!(args);
|
|
|
|
commands::python_uninstall(args.targets, args.all, printer).await
|
|
}
|
|
Commands::Python(PythonNamespace {
|
|
command: PythonCommand::Find(args),
|
|
}) => {
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = settings::PythonFindSettings::resolve(args, filesystem);
|
|
|
|
// Initialize the cache.
|
|
let cache = cache.init()?;
|
|
|
|
commands::python_find(
|
|
&project_dir,
|
|
args.request,
|
|
args.no_project,
|
|
cli.top_level.no_config,
|
|
args.system,
|
|
globals.python_preference,
|
|
&cache,
|
|
)
|
|
.await
|
|
}
|
|
Commands::Python(PythonNamespace {
|
|
command: PythonCommand::Pin(args),
|
|
}) => {
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = settings::PythonPinSettings::resolve(args, filesystem);
|
|
|
|
// Initialize the cache.
|
|
let cache = cache.init()?;
|
|
|
|
commands::python_pin(
|
|
&project_dir,
|
|
args.request,
|
|
args.resolved,
|
|
globals.python_preference,
|
|
args.no_project,
|
|
&cache,
|
|
printer,
|
|
)
|
|
.await
|
|
}
|
|
Commands::Python(PythonNamespace {
|
|
command: PythonCommand::Dir,
|
|
}) => {
|
|
commands::python_dir()?;
|
|
Ok(ExitStatus::Success)
|
|
}
|
|
Commands::Publish(args) => {
|
|
show_settings!(args);
|
|
|
|
if globals.preview.is_disabled() {
|
|
warn_user_once!("`uv publish` is experimental and may change without warning");
|
|
}
|
|
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let PublishSettings {
|
|
files,
|
|
username,
|
|
password,
|
|
publish_url,
|
|
trusted_publishing,
|
|
keyring_provider,
|
|
allow_insecure_host,
|
|
} = PublishSettings::resolve(args, filesystem);
|
|
|
|
commands::publish(
|
|
files,
|
|
publish_url,
|
|
trusted_publishing,
|
|
keyring_provider,
|
|
allow_insecure_host,
|
|
username,
|
|
password,
|
|
globals.connectivity,
|
|
globals.native_tls,
|
|
printer,
|
|
)
|
|
.await
|
|
}
|
|
Commands::BuildBackend { command } => spawn_blocking(move || match command {
|
|
BuildBackendCommand::BuildSdist { sdist_directory } => {
|
|
commands::build_backend::build_sdist(&sdist_directory)
|
|
}
|
|
BuildBackendCommand::BuildWheel {
|
|
wheel_directory,
|
|
metadata_directory,
|
|
} => commands::build_backend::build_wheel(
|
|
&wheel_directory,
|
|
metadata_directory.as_deref(),
|
|
),
|
|
BuildBackendCommand::BuildEditable {
|
|
wheel_directory,
|
|
metadata_directory,
|
|
} => commands::build_backend::build_editable(
|
|
&wheel_directory,
|
|
metadata_directory.as_deref(),
|
|
),
|
|
BuildBackendCommand::GetRequiresForBuildSdist => {
|
|
commands::build_backend::get_requires_for_build_sdist()
|
|
}
|
|
BuildBackendCommand::GetRequiresForBuildWheel => {
|
|
commands::build_backend::get_requires_for_build_wheel()
|
|
}
|
|
BuildBackendCommand::PrepareMetadataForBuildWheel { wheel_directory } => {
|
|
commands::build_backend::prepare_metadata_for_build_wheel(&wheel_directory)
|
|
}
|
|
BuildBackendCommand::GetRequiresForBuildEditable => {
|
|
commands::build_backend::get_requires_for_build_editable()
|
|
}
|
|
BuildBackendCommand::PrepareMetadataForBuildEditable { wheel_directory } => {
|
|
commands::build_backend::prepare_metadata_for_build_editable(&wheel_directory)
|
|
}
|
|
})
|
|
.await
|
|
.expect("tokio threadpool exited unexpectedly"),
|
|
};
|
|
result
|
|
}
|
|
|
|
/// Run a [`ProjectCommand`].
|
|
async fn run_project(
|
|
project_command: Box<ProjectCommand>,
|
|
project_dir: &Path,
|
|
command: Option<RunCommand>,
|
|
script: Option<Pep723Item>,
|
|
globals: GlobalSettings,
|
|
// TODO(zanieb): Determine a better story for passing `no_config` in here
|
|
no_config: bool,
|
|
filesystem: Option<FilesystemOptions>,
|
|
cache: Cache,
|
|
printer: Printer,
|
|
) -> Result<ExitStatus> {
|
|
// Write out any resolved settings.
|
|
macro_rules! show_settings {
|
|
($arg:expr) => {
|
|
if globals.show_settings {
|
|
writeln!(printer.stdout(), "{:#?}", $arg)?;
|
|
return Ok(ExitStatus::Success);
|
|
}
|
|
};
|
|
($arg:expr, false) => {
|
|
if globals.show_settings {#
|
|
writeln!(printer.stdout(), "{:#?}", $arg)?;
|
|
}
|
|
};
|
|
}
|
|
|
|
match *project_command {
|
|
ProjectCommand::Init(args) => {
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = settings::InitSettings::resolve(args, filesystem);
|
|
show_settings!(args);
|
|
|
|
// Initialize the cache.
|
|
let cache = cache.init()?;
|
|
|
|
commands::init(
|
|
project_dir,
|
|
args.path,
|
|
args.name,
|
|
args.package,
|
|
args.kind,
|
|
args.vcs,
|
|
args.no_readme,
|
|
args.author_from,
|
|
args.no_pin_python,
|
|
args.python,
|
|
args.no_workspace,
|
|
globals.python_preference,
|
|
globals.python_downloads,
|
|
globals.connectivity,
|
|
globals.native_tls,
|
|
&cache,
|
|
printer,
|
|
)
|
|
.await
|
|
}
|
|
ProjectCommand::Run(args) => {
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = settings::RunSettings::resolve(args, filesystem);
|
|
show_settings!(args);
|
|
|
|
// Initialize the cache.
|
|
let cache = cache.init()?.with_refresh(
|
|
args.refresh
|
|
.combine(Refresh::from(args.settings.reinstall.clone()))
|
|
.combine(Refresh::from(args.settings.upgrade.clone())),
|
|
);
|
|
|
|
let requirements = args
|
|
.with
|
|
.into_iter()
|
|
.map(RequirementsSource::from_with_package)
|
|
.chain(
|
|
args.with_editable
|
|
.into_iter()
|
|
.map(RequirementsSource::Editable),
|
|
)
|
|
.chain(
|
|
args.with_requirements
|
|
.into_iter()
|
|
.map(RequirementsSource::from_requirements_file),
|
|
)
|
|
.collect::<Vec<_>>();
|
|
|
|
Box::pin(commands::run(
|
|
project_dir,
|
|
script,
|
|
command,
|
|
requirements,
|
|
args.show_resolution || globals.verbose > 0,
|
|
args.locked,
|
|
args.frozen,
|
|
args.no_sync,
|
|
args.isolated,
|
|
args.package,
|
|
args.no_project,
|
|
no_config,
|
|
args.extras,
|
|
args.dev,
|
|
args.editable,
|
|
args.python,
|
|
args.settings,
|
|
globals.python_preference,
|
|
globals.python_downloads,
|
|
globals.connectivity,
|
|
globals.concurrency,
|
|
globals.native_tls,
|
|
&cache,
|
|
printer,
|
|
))
|
|
.await
|
|
}
|
|
ProjectCommand::Sync(args) => {
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = settings::SyncSettings::resolve(args, filesystem);
|
|
show_settings!(args);
|
|
|
|
// Initialize the cache.
|
|
let cache = cache.init()?.with_refresh(
|
|
args.refresh
|
|
.combine(Refresh::from(args.settings.reinstall.clone()))
|
|
.combine(Refresh::from(args.settings.upgrade.clone())),
|
|
);
|
|
|
|
commands::sync(
|
|
project_dir,
|
|
args.locked,
|
|
args.frozen,
|
|
args.package,
|
|
args.extras,
|
|
args.dev,
|
|
args.editable,
|
|
args.install_options,
|
|
args.modifications,
|
|
args.python,
|
|
globals.python_preference,
|
|
globals.python_downloads,
|
|
args.settings,
|
|
globals.connectivity,
|
|
globals.concurrency,
|
|
globals.native_tls,
|
|
&cache,
|
|
printer,
|
|
)
|
|
.await
|
|
}
|
|
ProjectCommand::Lock(args) => {
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = settings::LockSettings::resolve(args, filesystem);
|
|
show_settings!(args);
|
|
|
|
// Initialize the cache.
|
|
let cache = cache.init()?.with_refresh(
|
|
args.refresh
|
|
.combine(Refresh::from(args.settings.upgrade.clone())),
|
|
);
|
|
|
|
commands::lock(
|
|
project_dir,
|
|
args.locked,
|
|
args.frozen,
|
|
args.python,
|
|
args.settings,
|
|
globals.python_preference,
|
|
globals.python_downloads,
|
|
globals.connectivity,
|
|
globals.concurrency,
|
|
globals.native_tls,
|
|
&cache,
|
|
printer,
|
|
)
|
|
.await
|
|
}
|
|
ProjectCommand::Add(args) => {
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = settings::AddSettings::resolve(args, filesystem);
|
|
show_settings!(args);
|
|
|
|
// Initialize the cache.
|
|
let cache = cache.init()?.with_refresh(
|
|
args.refresh
|
|
.combine(Refresh::from(args.settings.reinstall.clone()))
|
|
.combine(Refresh::from(args.settings.upgrade.clone())),
|
|
);
|
|
|
|
let requirements = args
|
|
.packages
|
|
.into_iter()
|
|
.map(RequirementsSource::Package)
|
|
.chain(
|
|
args.requirements
|
|
.into_iter()
|
|
.map(RequirementsSource::from_requirements_file),
|
|
)
|
|
.collect::<Vec<_>>();
|
|
|
|
Box::pin(commands::add(
|
|
project_dir,
|
|
args.locked,
|
|
args.frozen,
|
|
args.no_sync,
|
|
requirements,
|
|
args.editable,
|
|
args.dependency_type,
|
|
args.raw_sources,
|
|
args.rev,
|
|
args.tag,
|
|
args.branch,
|
|
args.extras,
|
|
args.package,
|
|
args.python,
|
|
args.settings,
|
|
args.script,
|
|
globals.python_preference,
|
|
globals.python_downloads,
|
|
globals.connectivity,
|
|
globals.concurrency,
|
|
globals.native_tls,
|
|
&cache,
|
|
printer,
|
|
))
|
|
.await
|
|
}
|
|
ProjectCommand::Remove(args) => {
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = settings::RemoveSettings::resolve(args, filesystem);
|
|
show_settings!(args);
|
|
|
|
// Initialize the cache.
|
|
let cache = cache.init()?.with_refresh(
|
|
args.refresh
|
|
.combine(Refresh::from(args.settings.reinstall.clone()))
|
|
.combine(Refresh::from(args.settings.upgrade.clone())),
|
|
);
|
|
|
|
// Unwrap the script.
|
|
let script = script.map(|script| match script {
|
|
Pep723Item::Script(script) => script,
|
|
Pep723Item::Stdin(_) => unreachable!("`uv remove` does not support stdin"),
|
|
Pep723Item::Remote(_) => unreachable!("`uv remove` does not support remote files"),
|
|
});
|
|
|
|
commands::remove(
|
|
project_dir,
|
|
args.locked,
|
|
args.frozen,
|
|
args.no_sync,
|
|
args.packages,
|
|
args.dependency_type,
|
|
args.package,
|
|
args.python,
|
|
args.settings,
|
|
script,
|
|
globals.python_preference,
|
|
globals.python_downloads,
|
|
globals.connectivity,
|
|
globals.concurrency,
|
|
globals.native_tls,
|
|
&cache,
|
|
printer,
|
|
)
|
|
.await
|
|
}
|
|
ProjectCommand::Tree(args) => {
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = settings::TreeSettings::resolve(args, filesystem);
|
|
show_settings!(args);
|
|
|
|
// Initialize the cache.
|
|
let cache = cache.init()?;
|
|
|
|
commands::tree(
|
|
project_dir,
|
|
args.dev,
|
|
args.locked,
|
|
args.frozen,
|
|
args.universal,
|
|
args.depth,
|
|
args.prune,
|
|
args.package,
|
|
args.no_dedupe,
|
|
args.invert,
|
|
args.python_version,
|
|
args.python_platform,
|
|
args.python,
|
|
args.resolver,
|
|
globals.python_preference,
|
|
globals.python_downloads,
|
|
globals.connectivity,
|
|
globals.concurrency,
|
|
globals.native_tls,
|
|
&cache,
|
|
printer,
|
|
)
|
|
.await
|
|
}
|
|
ProjectCommand::Export(args) => {
|
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
|
let args = settings::ExportSettings::resolve(args, filesystem);
|
|
show_settings!(args);
|
|
|
|
// Initialize the cache.
|
|
let cache = cache.init()?;
|
|
|
|
commands::export(
|
|
project_dir,
|
|
args.format,
|
|
args.package,
|
|
args.hashes,
|
|
args.install_options,
|
|
args.output_file,
|
|
args.extras,
|
|
args.dev,
|
|
args.editable,
|
|
args.locked,
|
|
args.frozen,
|
|
args.include_header,
|
|
args.python,
|
|
args.settings,
|
|
globals.python_preference,
|
|
globals.python_downloads,
|
|
globals.connectivity,
|
|
globals.concurrency,
|
|
globals.native_tls,
|
|
globals.quiet,
|
|
&cache,
|
|
printer,
|
|
)
|
|
.await
|
|
}
|
|
}
|
|
}
|
|
|
|
/// The main entry point for a uv invocation.
|
|
///
|
|
/// WARNING: This entry point is not recommended for external consumption, the
|
|
/// uv binary interface is the official public API. When using this entry
|
|
/// point, uv assumes it is running in a process it controls and that the
|
|
/// entire process lifetime is managed by uv. Unexpected behavior may be
|
|
/// encountered if this entry pointis called multiple times in a single process.
|
|
pub fn main<I, T>(args: I) -> ExitCode
|
|
where
|
|
I: IntoIterator<Item = T>,
|
|
T: Into<OsString> + Clone,
|
|
{
|
|
// `std::env::args` is not `Send` so we parse before passing to our runtime
|
|
// https://github.com/rust-lang/rust/pull/48005
|
|
let cli = match Cli::try_parse_from(args) {
|
|
Ok(cli) => cli,
|
|
Err(mut err) => {
|
|
if let Some(ContextValue::String(subcommand)) = err.get(ContextKind::InvalidSubcommand)
|
|
{
|
|
match subcommand.as_str() {
|
|
"compile" | "lock" => {
|
|
err.insert(
|
|
ContextKind::SuggestedSubcommand,
|
|
ContextValue::String("uv pip compile".to_string()),
|
|
);
|
|
}
|
|
"sync" => {
|
|
err.insert(
|
|
ContextKind::SuggestedSubcommand,
|
|
ContextValue::String("uv pip sync".to_string()),
|
|
);
|
|
}
|
|
"install" | "add" => {
|
|
err.insert(
|
|
ContextKind::SuggestedSubcommand,
|
|
ContextValue::String("uv pip install".to_string()),
|
|
);
|
|
}
|
|
"uninstall" | "remove" => {
|
|
err.insert(
|
|
ContextKind::SuggestedSubcommand,
|
|
ContextValue::String("uv pip uninstall".to_string()),
|
|
);
|
|
}
|
|
"freeze" => {
|
|
err.insert(
|
|
ContextKind::SuggestedSubcommand,
|
|
ContextValue::String("uv pip freeze".to_string()),
|
|
);
|
|
}
|
|
"list" => {
|
|
err.insert(
|
|
ContextKind::SuggestedSubcommand,
|
|
ContextValue::String("uv pip list".to_string()),
|
|
);
|
|
}
|
|
"show" => {
|
|
err.insert(
|
|
ContextKind::SuggestedSubcommand,
|
|
ContextValue::String("uv pip show".to_string()),
|
|
);
|
|
}
|
|
"tree" => {
|
|
err.insert(
|
|
ContextKind::SuggestedSubcommand,
|
|
ContextValue::String("uv pip tree".to_string()),
|
|
);
|
|
}
|
|
_ => {}
|
|
}
|
|
}
|
|
err.exit()
|
|
}
|
|
};
|
|
|
|
// Windows has a default stack size of 1MB, which is lower than the linux and mac default.
|
|
// https://learn.microsoft.com/en-us/cpp/build/reference/stack-stack-allocations?view=msvc-170
|
|
// We support increasing the stack size to avoid stack overflows in debug mode on Windows. In
|
|
// addition, we box types and futures in various places. This includes the `Box::pin(run())`
|
|
// here, which prevents the large (non-send) main future alone from overflowing the stack.
|
|
let result = if let Ok(stack_size) = std::env::var("UV_STACK_SIZE") {
|
|
let stack_size = stack_size.parse().expect("Invalid stack size");
|
|
let tokio_main = move || {
|
|
let runtime = tokio::runtime::Builder::new_current_thread()
|
|
.enable_all()
|
|
.thread_stack_size(stack_size)
|
|
.build()
|
|
.expect("Failed building the Runtime");
|
|
// Box the large main future to avoid stack overflows.
|
|
let result = runtime.block_on(Box::pin(run(cli)));
|
|
// Avoid waiting for pending tasks to complete.
|
|
//
|
|
// The resolver may have kicked off HTTP requests during resolution that
|
|
// turned out to be unnecessary. Waiting for those to complete can cause
|
|
// the CLI to hang before exiting.
|
|
runtime.shutdown_background();
|
|
result
|
|
};
|
|
std::thread::Builder::new()
|
|
.stack_size(stack_size)
|
|
.spawn(tokio_main)
|
|
.expect("Tokio executor failed, was there a panic?")
|
|
.join()
|
|
.expect("Tokio executor failed, was there a panic?")
|
|
} else {
|
|
let runtime = tokio::runtime::Builder::new_current_thread()
|
|
.enable_all()
|
|
.build()
|
|
.expect("Failed building the Runtime");
|
|
// Box the large main future to avoid stack overflows.
|
|
let result = runtime.block_on(Box::pin(run(cli)));
|
|
runtime.shutdown_background();
|
|
result
|
|
};
|
|
|
|
match result {
|
|
Ok(code) => code.into(),
|
|
Err(err) => {
|
|
let mut causes = err.chain();
|
|
eprintln!("{}: {}", "error".red().bold(), causes.next().unwrap());
|
|
for err in causes {
|
|
eprintln!(" {}: {}", "Caused by".red().bold(), err);
|
|
}
|
|
ExitStatus::Error.into()
|
|
}
|
|
}
|
|
}
|