1#![deny(clippy::print_stdout, clippy::print_stderr)]
2
3use std::borrow::Cow;
4use std::ffi::OsString;
5use std::fmt::Write;
6use std::io::stdout;
7#[cfg(feature = "self-update")]
8use std::ops::Bound;
9use std::path::Path;
10use std::process::ExitCode;
11use std::str::FromStr;
12use std::sync::atomic::Ordering;
13
14use anstream::eprintln;
15use anyhow::{Result, anyhow, bail};
16use clap::error::{ContextKind, ContextValue};
17use clap::{CommandFactory, Parser};
18use futures::FutureExt;
19use owo_colors::OwoColorize;
20use settings::PipTreeSettings;
21use tokio::task::spawn_blocking;
22use tracing::{debug, instrument, trace};
23
24#[cfg(not(feature = "self-update"))]
25use crate::install_source::InstallSource;
26use uv_cache::{Cache, Refresh};
27use uv_cache_info::Timestamp;
28#[cfg(feature = "self-update")]
29use uv_cli::SelfUpdateArgs;
30use uv_cli::{
31 AuthCommand, AuthHelperCommand, AuthNamespace, BuildBackendCommand, CacheCommand,
32 CacheNamespace, Cli, Commands, PipCommand, PipNamespace, ProjectCommand, PythonCommand,
33 PythonNamespace, SelfCommand, SelfNamespace, ToolCommand, ToolNamespace, TopLevelArgs,
34 WorkspaceCommand, WorkspaceNamespace, compat::CompatArgs,
35};
36use uv_client::BaseClientBuilder;
37use uv_configuration::min_stack_size;
38use uv_flags::EnvironmentFlags;
39use uv_fs::{CWD, Simplified};
40#[cfg(feature = "self-update")]
41use uv_pep440::release_specifiers_to_ranges;
42use uv_pep508::VersionOrUrl;
43use uv_preview::{Preview, PreviewFeature};
44use uv_pypi_types::{ParsedDirectoryUrl, ParsedUrl};
45use uv_python::PythonRequest;
46use uv_requirements::{GroupsSpecification, RequirementsSource};
47use uv_requirements_txt::RequirementsTxtRequirement;
48use uv_scripts::{Pep723Error, Pep723Item, Pep723Script};
49use uv_settings::{Combine, EnvironmentOptions, FilesystemOptions, Options};
50use uv_static::EnvVars;
51use uv_warnings::{warn_user, warn_user_once};
52use uv_workspace::{DiscoveryOptions, Workspace, WorkspaceCache};
53
54use crate::commands::{ExitStatus, ParsedRunCommand, RunCommand, ScriptPath, ToolRunCommand};
55use crate::printer::Printer;
56use crate::settings::{
57 CacheSettings, GlobalSettings, PipCheckSettings, PipCompileSettings, PipFreezeSettings,
58 PipInstallSettings, PipListSettings, PipShowSettings, PipSyncSettings, PipUninstallSettings,
59 PublishSettings,
60};
61
62pub(crate) mod child;
63pub(crate) mod commands;
64#[cfg(not(feature = "self-update"))]
65mod install_source;
66pub(crate) mod logging;
67pub(crate) mod printer;
68pub(crate) mod settings;
69#[cfg(windows)]
70mod windows_exception;
71
72#[instrument(skip_all)]
73async fn run(cli: Cli) -> Result<ExitStatus> {
74 if cli.top_level.global_args.quiet == 0 {
76 uv_warnings::enable();
77 }
78
79 let directory =
81 cli.top_level.global_args.directory.clone().or_else(|| {
82 std::env::var_os(EnvVars::UV_WORKING_DIRECTORY).map(std::path::PathBuf::from)
83 });
84
85 if let Some(directory) = directory.as_ref() {
87 std::env::set_current_dir(directory)?;
88 }
89
90 let parsed_run_command = if let Commands::Project(command) = &*cli.command
92 && let ProjectCommand::Run(uv_cli::RunArgs {
93 command: Some(ref command),
94 module,
95 script,
96 gui_script,
97 ..
98 }) = **command
99 {
100 Some(ParsedRunCommand::from_args(
101 command, module, script, gui_script,
102 )?)
103 } else {
104 None
105 };
106
107 let environment = EnvironmentOptions::new()?;
109
110 let early_preview = Preview::from_args(
112 settings::resolve_preview(&cli.top_level.global_args, None, &environment),
113 cli.top_level.global_args.no_preview,
114 &cli.top_level.global_args.preview_features,
115 );
116
117 let project_dir = if let Some(project) = &cli.top_level.global_args.project {
122 let path = uv_fs::normalize_path_buf(std::path::absolute(project)?);
123 if let Some(name) = path.file_name()
124 && name == "pyproject.toml"
125 && path.is_file()
126 && let Some(parent) = path.parent()
127 {
128 Cow::Owned(parent.to_path_buf())
129 } else {
130 Cow::Owned(path)
131 }
132 } else if let Some(run_command) = &parsed_run_command
133 && early_preview.is_enabled(PreviewFeature::TargetWorkspaceDiscovery)
134 && let Some(dir) = run_command.script_dir()
135 {
136 Cow::Owned(std::path::absolute(dir)?)
139 } else {
140 Cow::Borrowed(&*CWD)
141 };
142
143 let skip_project_validation = matches!(
146 &*cli.command,
147 Commands::Project(command) if matches!(**command, ProjectCommand::Init(_))
148 );
149
150 if !skip_project_validation {
151 if let Some(project_path) = cli.top_level.global_args.project.as_ref() {
152 if !project_dir.exists() {
153 if early_preview.is_enabled(PreviewFeature::ProjectDirectoryMustExist) {
154 bail!(
155 "Project directory `{}` does not exist",
156 project_path.user_display()
157 );
158 }
159 warn_user_once!(
160 "Project directory `{}` does not exist. \
161 This will become an error in a future release. \
162 Use `--preview-features project-directory-must-exist` to error on this now.",
163 project_path.user_display()
164 );
165 } else if !project_dir.is_dir() {
166 if early_preview.is_enabled(PreviewFeature::ProjectDirectoryMustExist) {
169 bail!(
170 "Project path `{}` is not a directory",
171 project_path.user_display()
172 );
173 }
174 warn_user_once!(
175 "Project path `{}` is not a directory. \
176 This will become an error in a future release. \
177 Use `--preview-features project-directory-must-exist` to error on this now.",
178 project_path.user_display()
179 );
180 }
181 }
182 }
183
184 let deprecated_isolated = if cli.top_level.global_args.isolated {
186 match &*cli.command {
187 Commands::Tool(ToolNamespace {
189 command: ToolCommand::Uvx(_) | ToolCommand::Run(_),
190 }) => false,
191
192 Commands::Project(command) if matches!(**command, ProjectCommand::Run(_)) => false,
194
195 Commands::Project(command) if matches!(**command, ProjectCommand::Init(_)) => {
197 warn_user!(
198 "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."
199 );
200 false
201 }
202
203 Commands::Project(_) | Commands::Tool(_) | Commands::Python(_) => {
205 warn_user!(
206 "The `--isolated` flag is deprecated and has no effect. Instead, use `--no-config` to prevent uv from discovering configuration files."
207 );
208 false
209 }
210
211 _ => {
213 warn_user!(
214 "The `--isolated` flag is deprecated. Instead, use `--no-config` to prevent uv from discovering configuration files."
215 );
216 true
217 }
218 }
219 } else {
220 false
221 };
222
223 let workspace_cache = WorkspaceCache::default();
230 let filesystem = if let Some(config_file) = cli.top_level.config_file.as_ref() {
231 if config_file
232 .file_name()
233 .is_some_and(|file_name| file_name == "pyproject.toml")
234 {
235 warn_user!(
236 "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."
237 );
238 }
239 Some(FilesystemOptions::from_file(config_file)?)
240 } else if deprecated_isolated || cli.top_level.no_config {
241 None
242 } else if matches!(&*cli.command, Commands::Tool(_) | Commands::Self_(_)) {
243 FilesystemOptions::user()?.combine(FilesystemOptions::system()?)
245 } else if let Ok(workspace) =
246 Workspace::discover(&project_dir, &DiscoveryOptions::default(), &workspace_cache).await
247 {
248 let project = FilesystemOptions::find(workspace.install_path())?;
249 let system = FilesystemOptions::system()?;
250 let user = FilesystemOptions::user()?;
251 project.combine(user).combine(system)
252 } else {
253 let project = FilesystemOptions::find(&project_dir)?;
254 let system = FilesystemOptions::system()?;
255 let user = FilesystemOptions::user()?;
256 project.combine(user).combine(system)
257 };
258
259 let (run_script, run_command) = if let Some(parsed_run_command) = parsed_run_command {
262 let (script, run_command) = parsed_run_command
263 .resolve(
264 &cli.top_level.global_args,
265 filesystem.as_ref(),
266 &environment,
267 )
268 .await?;
269 (script, Some(run_command))
270 } else {
271 (None, None)
272 };
273 let script = if let Some(run_script) = run_script {
274 Some(run_script)
275 } else if let Commands::Project(command) = &*cli.command {
276 match &**command {
277 ProjectCommand::Add(uv_cli::AddArgs {
280 script: Some(script),
281 ..
282 })
283 | ProjectCommand::Lock(uv_cli::LockArgs {
284 script: Some(script),
285 ..
286 }) => match Pep723Script::read(script).await {
287 Ok(Some(script)) => Some(Pep723Item::Script(script)),
288 Ok(None) => None,
289 Err(err) => return Err(err.into()),
290 },
291 ProjectCommand::Remove(uv_cli::RemoveArgs {
293 script: Some(script),
294 ..
295 })
296 | ProjectCommand::Sync(uv_cli::SyncArgs {
297 script: Some(script),
298 ..
299 })
300 | ProjectCommand::Tree(uv_cli::TreeArgs {
301 script: Some(script),
302 ..
303 })
304 | ProjectCommand::Export(uv_cli::ExportArgs {
305 script: Some(script),
306 ..
307 }) => match Pep723Script::read(script).await {
308 Ok(Some(script)) => Some(Pep723Item::Script(script)),
309 Ok(None) => {
310 bail!(
311 "`{}` does not contain a PEP 723 metadata tag; run `{}` to initialize the script",
312 script.user_display().cyan(),
313 format!("uv init --script {}", script.user_display()).green()
314 )
315 }
316 Err(Pep723Error::Io(err)) if err.kind() == std::io::ErrorKind::NotFound => {
317 bail!(
318 "Failed to read `{}` (not found); run `{}` to create a PEP 723 script",
319 script.user_display().cyan(),
320 format!("uv init --script {}", script.user_display()).green()
321 )
322 }
323 Err(err) => return Err(err.into()),
324 },
325 _ => None,
326 }
327 } else if let Commands::Python(uv_cli::PythonNamespace {
328 command:
329 PythonCommand::Find(uv_cli::PythonFindArgs {
330 script: Some(script),
331 ..
332 }),
333 }) = &*cli.command
334 {
335 match Pep723Script::read(&script).await {
336 Ok(Some(script)) => Some(Pep723Item::Script(script)),
337 Ok(None) => {
338 bail!(
339 "`{}` does not contain a PEP 723 metadata tag; run `{}` to initialize the script",
340 script.user_display().cyan(),
341 format!("uv init --script {}", script.user_display()).green()
342 )
343 }
344 Err(Pep723Error::Io(err)) if err.kind() == std::io::ErrorKind::NotFound => {
345 bail!(
346 "Failed to read `{}` (not found); run `{}` to create a PEP 723 script",
347 script.user_display().cyan(),
348 format!("uv init --script {}", script.user_display()).green()
349 )
350 }
351 Err(err) => return Err(err.into()),
352 }
353 } else {
354 None
355 };
356
357 let filesystem = script
359 .as_ref()
360 .map(Pep723Item::metadata)
361 .and_then(|metadata| metadata.tool.as_ref())
362 .and_then(|tool| tool.uv.as_ref())
363 .map(|uv| Options::simple(uv.globals.clone(), uv.top_level.clone()))
364 .map(FilesystemOptions::from)
365 .combine(filesystem);
366
367 let globals = GlobalSettings::resolve(
369 &cli.top_level.global_args,
370 filesystem.as_ref(),
371 &environment,
372 );
373
374 uv_flags::init(EnvironmentFlags::from(&environment))
376 .map_err(|()| anyhow::anyhow!("Flags are already initialized"))?;
377
378 #[cfg(feature = "tracing-durations-export")]
380 let (durations_layer, _duration_guard) =
381 logging::setup_durations(environment.tracing_durations_file.as_ref())?;
382 #[cfg(not(feature = "tracing-durations-export"))]
383 let durations_layer = None::<tracing_subscriber::layer::Identity>;
384 logging::setup_logging(
385 match globals.verbose {
386 0 => logging::Level::Off,
387 1 => logging::Level::DebugUv,
388 2 => logging::Level::TraceUv,
389 3.. => logging::Level::TraceAll,
390 },
391 durations_layer,
392 globals.color,
393 environment.log_context.unwrap_or_default(),
394 )?;
395
396 debug!("uv {}", uv_cli::version::uv_self_version());
397 if let Some(config_file) = cli.top_level.config_file.as_ref() {
398 debug!("Using configuration file: {}", config_file.user_display());
399 }
400 if globals.preview.all_enabled() {
401 debug!("All preview features are enabled");
402 } else if globals.preview.any_enabled() {
403 debug!(
404 "The following preview features are enabled: {}",
405 globals.preview
406 );
407 }
408
409 #[cfg(unix)]
411 if globals.preview.is_enabled(PreviewFeature::AdjustUlimit) {
412 match uv_unix::adjust_open_file_limit() {
413 Ok(_) | Err(uv_unix::OpenFileLimitError::AlreadySufficient { .. }) => {}
414 Err(err) => warn_user!("{err}"),
417 }
418 }
419
420 let cache_settings = CacheSettings::resolve(*cli.top_level.cache_args, filesystem.as_ref());
422
423 uv_preview::init(globals.preview)?;
425
426 if let Some(required_version) = globals.required_version.as_ref() {
428 let package_version = uv_pep440::Version::from_str(uv_version::version())?;
429 if !required_version.contains(&package_version) {
430 #[cfg(feature = "self-update")]
431 let hint = {
432 let ranges = release_specifiers_to_ranges(required_version.specifiers().clone());
435
436 if let Some(singleton) = ranges.as_singleton() {
437 format!(
439 ". Update `uv` by running `{}`.",
440 format!("uv self update {singleton}").green()
441 )
442 } else if ranges
443 .bounding_range()
444 .iter()
445 .any(|(lowest, _highest)| match lowest {
446 Bound::Included(version) => **version > package_version,
447 Bound::Excluded(version) => **version > package_version,
448 Bound::Unbounded => false,
449 })
450 {
451 format!(". Update `uv` by running `{}`.", "uv self update".cyan())
453 } else {
454 String::new()
455 }
456 };
457 #[cfg(not(feature = "self-update"))]
458 let hint = "";
459 return Err(anyhow::anyhow!(
460 "Required uv version `{required_version}` does not match the running version `{package_version}`{hint}",
461 ));
462 }
463 }
464
465 let printer = if globals.quiet == 1 {
467 Printer::Quiet
468 } else if globals.quiet > 1 {
469 Printer::Silent
470 } else if globals.verbose > 0 {
471 Printer::Verbose
472 } else if globals.no_progress {
473 Printer::NoProgress
474 } else {
475 Printer::Default
476 };
477
478 if globals.quiet > 0 {
480 uv_warnings::disable();
481 } else {
482 uv_warnings::enable();
483 }
484
485 anstream::ColorChoice::write_global(globals.color.into());
486
487 miette::set_hook(Box::new(|_| {
488 Box::new(
489 miette::MietteHandlerOpts::new()
490 .break_words(false)
491 .word_separator(textwrap::WordSeparator::AsciiSpace)
492 .word_splitter(textwrap::WordSplitter::NoHyphenation)
493 .wrap_lines(
494 std::env::var(EnvVars::UV_NO_WRAP)
495 .map(|_| false)
496 .unwrap_or(true),
497 )
498 .build(),
499 )
500 }))?;
501
502 uv_configuration::RAYON_PARALLELISM.store(globals.concurrency.installs, Ordering::Relaxed);
504
505 macro_rules! show_settings {
507 ($arg:expr) => {
508 if globals.show_settings {
509 writeln!(printer.stdout(), "{:#?}", $arg)?;
510 return Ok(ExitStatus::Success);
511 }
512 };
513 ($arg:expr, false) => {
514 if globals.show_settings {
515 writeln!(printer.stdout(), "{:#?}", $arg)?;
516 }
517 };
518 }
519 show_settings!(globals, false);
520 show_settings!(cache_settings, false);
521
522 if cache_settings.no_cache {
524 debug!("Disabling the uv cache due to `--no-cache`");
525 }
526 let cache = Cache::from_settings(cache_settings.no_cache, cache_settings.cache_dir)?;
527
528 let client_builder = BaseClientBuilder::new(
530 globals.network_settings.connectivity,
531 globals.network_settings.system_certs,
532 globals.network_settings.allow_insecure_host.clone(),
533 globals.preview,
534 globals.network_settings.read_timeout,
535 globals.network_settings.connect_timeout,
536 globals.network_settings.retries,
537 )
538 .http_proxy(globals.network_settings.http_proxy.clone())
539 .https_proxy(globals.network_settings.https_proxy.clone())
540 .no_proxy(globals.network_settings.no_proxy.clone());
541
542 match *cli.command {
543 Commands::Auth(AuthNamespace {
544 command: AuthCommand::Login(args),
545 }) => {
546 let args = settings::AuthLoginSettings::resolve(args);
548 show_settings!(args);
549
550 commands::auth_login(
551 args.service,
552 args.username,
553 args.password,
554 args.token,
555 client_builder,
556 printer,
557 globals.preview,
558 )
559 .await
560 }
561 Commands::Auth(AuthNamespace {
562 command: AuthCommand::Logout(args),
563 }) => {
564 let args = settings::AuthLogoutSettings::resolve(args);
566 show_settings!(args);
567
568 commands::auth_logout(
569 args.service,
570 args.username,
571 client_builder,
572 printer,
573 globals.preview,
574 )
575 .await
576 }
577 Commands::Auth(AuthNamespace {
578 command: AuthCommand::Token(args),
579 }) => {
580 let args = settings::AuthTokenSettings::resolve(args);
582 show_settings!(args);
583
584 commands::auth_token(
585 args.service,
586 args.username,
587 client_builder,
588 printer,
589 globals.preview,
590 )
591 .await
592 }
593 Commands::Auth(AuthNamespace {
594 command: AuthCommand::Dir(args),
595 }) => {
596 commands::auth_dir(args.service.as_ref(), printer)?;
597 Ok(ExitStatus::Success)
598 }
599 Commands::Auth(AuthNamespace {
600 command: AuthCommand::Helper(args),
601 }) => {
602 use uv_cli::AuthHelperProtocol;
603
604 match args.protocol {
606 AuthHelperProtocol::Bazel => {}
607 }
608
609 match args.command {
610 AuthHelperCommand::Get => {
611 commands::auth_helper(client_builder, globals.preview, printer).await
612 }
613 }
614 }
615 Commands::Help(args) => commands::help(
616 args.command.unwrap_or_default().as_slice(),
617 printer,
618 args.no_pager,
619 ),
620 Commands::Pip(PipNamespace {
621 command: PipCommand::Compile(args),
622 }) => {
623 args.compat_args.validate()?;
624
625 let args = PipCompileSettings::resolve(args, filesystem, environment);
627 show_settings!(args);
628
629 globals
631 .network_settings
632 .check_refresh_conflict(&args.refresh);
633
634 let cache = cache.init().await?.with_refresh(
636 args.refresh
637 .combine(Refresh::from(args.settings.reinstall.clone()))
638 .combine(Refresh::from(args.settings.upgrade.clone())),
639 );
640
641 let requirements = args
642 .src_file
643 .into_iter()
644 .map(RequirementsSource::from_requirements_file)
645 .collect::<Result<Vec<_>, _>>()?;
646 let constraints = args
647 .constraints
648 .into_iter()
649 .map(RequirementsSource::from_constraints_txt)
650 .collect::<Result<Vec<_>, _>>()?;
651 let overrides = args
652 .overrides
653 .into_iter()
654 .map(RequirementsSource::from_overrides_txt)
655 .collect::<Result<Vec<_>, _>>()?;
656 let excludes = args
657 .excludes
658 .into_iter()
659 .map(RequirementsSource::from_requirements_txt)
660 .collect::<Result<Vec<_>, _>>()?;
661 let build_constraints = args
662 .build_constraints
663 .into_iter()
664 .map(RequirementsSource::from_constraints_txt)
665 .collect::<Result<Vec<_>, _>>()?;
666 let groups = GroupsSpecification {
667 root: project_dir.to_path_buf(),
668 groups: args.settings.groups,
669 };
670
671 commands::pip_compile(
672 &requirements,
673 &constraints,
674 &overrides,
675 &excludes,
676 &build_constraints,
677 args.constraints_from_workspace,
678 args.overrides_from_workspace,
679 args.excludes_from_workspace,
680 args.build_constraints_from_workspace,
681 args.environments,
682 args.settings.extras,
683 groups,
684 args.settings.output_file.as_deref(),
685 args.format,
686 args.settings.resolution,
687 args.settings.prerelease,
688 args.settings.fork_strategy,
689 args.settings.dependency_mode,
690 args.settings.upgrade,
691 args.settings.generate_hashes,
692 args.settings.no_emit_package,
693 args.settings.no_strip_extras,
694 args.settings.no_strip_markers,
695 !args.settings.no_annotate,
696 !args.settings.no_header,
697 args.settings.custom_compile_command,
698 args.settings.emit_index_url,
699 args.settings.emit_find_links,
700 args.settings.emit_build_options,
701 args.settings.emit_marker_expression,
702 args.settings.emit_index_annotation,
703 args.settings.index_locations,
704 args.settings.index_strategy,
705 args.settings.torch_backend,
706 args.settings.dependency_metadata,
707 args.settings.keyring_provider,
708 &client_builder.subcommand(vec!["pip".to_owned(), "compile".to_owned()]),
709 args.settings.config_setting,
710 args.settings.config_settings_package,
711 args.settings.build_isolation.clone(),
712 &args.settings.extra_build_dependencies,
713 &args.settings.extra_build_variables,
714 args.settings.build_options,
715 args.settings.install_mirrors,
716 args.settings.python_version,
717 args.settings.python_platform,
718 globals.python_downloads,
719 args.settings.universal,
720 args.settings.exclude_newer,
721 args.settings.sources,
722 args.settings.annotation_style,
723 args.settings.link_mode,
724 args.settings.python,
725 args.settings.system,
726 globals.python_preference,
727 globals.concurrency,
728 globals.quiet > 0,
729 cache,
730 workspace_cache,
731 printer,
732 globals.preview,
733 )
734 .await
735 }
736 Commands::Pip(PipNamespace {
737 command: PipCommand::Sync(args),
738 }) => {
739 args.compat_args.validate()?;
740
741 let args = PipSyncSettings::resolve(args, filesystem, environment);
743 show_settings!(args);
744
745 globals
747 .network_settings
748 .check_refresh_conflict(&args.refresh);
749
750 let cache = cache.init().await?.with_refresh(
752 args.refresh
753 .combine(Refresh::from(args.settings.reinstall.clone()))
754 .combine(Refresh::from(args.settings.upgrade.clone())),
755 );
756
757 let requirements = args
758 .src_file
759 .into_iter()
760 .map(RequirementsSource::from_requirements_file)
761 .collect::<Result<Vec<_>, _>>()?;
762 let constraints = args
763 .constraints
764 .into_iter()
765 .map(RequirementsSource::from_constraints_txt)
766 .collect::<Result<Vec<_>, _>>()?;
767 let build_constraints = args
768 .build_constraints
769 .into_iter()
770 .map(RequirementsSource::from_constraints_txt)
771 .collect::<Result<Vec<_>, _>>()?;
772 let groups = GroupsSpecification {
773 root: project_dir.to_path_buf(),
774 groups: args.settings.groups,
775 };
776
777 commands::pip_sync(
778 &requirements,
779 &constraints,
780 &build_constraints,
781 &args.settings.extras,
782 &groups,
783 args.settings.reinstall,
784 args.settings.link_mode,
785 args.settings.compile_bytecode,
786 args.settings.hash_checking,
787 args.settings.index_locations,
788 args.settings.index_strategy,
789 args.settings.torch_backend,
790 args.settings.dependency_metadata,
791 args.settings.keyring_provider,
792 &client_builder.subcommand(vec!["pip".to_owned(), "sync".to_owned()]),
793 args.settings.allow_empty_requirements,
794 globals.installer_metadata,
795 &args.settings.config_setting,
796 &args.settings.config_settings_package,
797 args.settings.build_isolation.clone(),
798 &args.settings.extra_build_dependencies,
799 &args.settings.extra_build_variables,
800 args.settings.build_options,
801 args.settings.python_version,
802 args.settings.python_platform,
803 globals.python_downloads,
804 args.settings.install_mirrors,
805 args.settings.strict,
806 args.settings.exclude_newer,
807 args.settings.python,
808 args.settings.system,
809 args.settings.break_system_packages,
810 args.settings.target,
811 args.settings.prefix,
812 args.settings.sources,
813 globals.python_preference,
814 globals.concurrency,
815 cache,
816 workspace_cache,
817 args.dry_run,
818 printer,
819 globals.preview,
820 )
821 .await
822 }
823 Commands::Pip(PipNamespace {
824 command: PipCommand::Install(args),
825 }) => {
826 args.compat_args.validate()?;
827
828 let mut args = PipInstallSettings::resolve(args, filesystem, environment);
830 show_settings!(args);
831
832 let mut requirements = Vec::with_capacity(
833 args.package.len() + args.editables.len() + args.requirements.len(),
834 );
835 for package in args.package {
836 requirements.push(RequirementsSource::from_package_argument(&package)?);
837 }
838 for package in args.editables {
839 requirements.push(RequirementsSource::from_editable(&package)?);
840 }
841 requirements.extend(
842 args.requirements
843 .into_iter()
844 .map(RequirementsSource::from_requirements_file)
845 .collect::<Result<Vec<_>, _>>()?,
846 );
847 let constraints = args
848 .constraints
849 .into_iter()
850 .map(RequirementsSource::from_constraints_txt)
851 .collect::<Result<Vec<_>, _>>()?;
852 let overrides = args
853 .overrides
854 .into_iter()
855 .map(RequirementsSource::from_overrides_txt)
856 .collect::<Result<Vec<_>, _>>()?;
857 let excludes = args
858 .excludes
859 .into_iter()
860 .map(RequirementsSource::from_requirements_txt)
861 .collect::<Result<Vec<_>, _>>()?;
862 let build_constraints = args
863 .build_constraints
864 .into_iter()
865 .map(RequirementsSource::from_overrides_txt)
866 .collect::<Result<Vec<_>, _>>()?;
867 let groups = GroupsSpecification {
868 root: project_dir.to_path_buf(),
869 groups: args.settings.groups,
870 };
871
872 for requirement in &requirements {
876 let requirement = match requirement {
877 RequirementsSource::Package(requirement) => requirement,
878 RequirementsSource::Editable(requirement) => requirement,
879 _ => continue,
880 };
881 match requirement {
882 RequirementsTxtRequirement::Named(requirement) => {
883 if let Some(VersionOrUrl::Url(url)) = requirement.version_or_url.as_ref() {
884 if let ParsedUrl::Directory(ParsedDirectoryUrl {
885 install_path, ..
886 }) = &url.parsed_url
887 {
888 debug!(
889 "Marking explicit source tree for reinstall: `{}`",
890 install_path.display()
891 );
892 args.settings.reinstall = args
893 .settings
894 .reinstall
895 .with_package(requirement.name.clone());
896 }
897 }
898 }
899 RequirementsTxtRequirement::Unnamed(requirement) => {
900 if let ParsedUrl::Directory(ParsedDirectoryUrl { install_path, .. }) =
901 &requirement.url.parsed_url
902 {
903 debug!(
904 "Marking explicit source tree for reinstall: `{}`",
905 install_path.display()
906 );
907 args.settings.reinstall =
908 args.settings.reinstall.with_path(install_path.clone());
909 }
910 }
911 }
912 }
913
914 globals
916 .network_settings
917 .check_refresh_conflict(&args.refresh);
918
919 let cache = cache.init().await?.with_refresh(
921 args.refresh
922 .combine(Refresh::from(args.settings.reinstall.clone()))
923 .combine(Refresh::from(args.settings.upgrade.clone())),
924 );
925
926 Box::pin(commands::pip_install(
927 &requirements,
928 &constraints,
929 &overrides,
930 &excludes,
931 &build_constraints,
932 args.constraints_from_workspace,
933 args.overrides_from_workspace,
934 args.excludes_from_workspace,
935 args.build_constraints_from_workspace,
936 &args.settings.extras,
937 &groups,
938 args.settings.resolution,
939 args.settings.prerelease,
940 args.settings.dependency_mode,
941 args.settings.upgrade,
942 args.settings.index_locations,
943 args.settings.index_strategy,
944 args.settings.torch_backend,
945 args.settings.dependency_metadata,
946 args.settings.keyring_provider,
947 &client_builder.subcommand(vec!["pip".to_owned(), "install".to_owned()]),
948 args.settings.reinstall,
949 args.settings.link_mode,
950 args.settings.compile_bytecode,
951 args.settings.hash_checking,
952 globals.installer_metadata,
953 &args.settings.config_setting,
954 &args.settings.config_settings_package,
955 args.settings.build_isolation.clone(),
956 &args.settings.extra_build_dependencies,
957 &args.settings.extra_build_variables,
958 args.settings.build_options,
959 args.modifications,
960 args.settings.python_version,
961 args.settings.python_platform,
962 globals.python_downloads,
963 args.settings.install_mirrors,
964 args.settings.strict,
965 args.settings.exclude_newer,
966 args.settings.sources,
967 args.settings.python,
968 args.settings.system,
969 args.settings.break_system_packages,
970 args.settings.target,
971 args.settings.prefix,
972 globals.python_preference,
973 globals.concurrency,
974 cache,
975 workspace_cache,
976 args.dry_run,
977 printer,
978 globals.preview,
979 ))
980 .await
981 }
982 Commands::Pip(PipNamespace {
983 command: PipCommand::Uninstall(args),
984 }) => {
985 let args = PipUninstallSettings::resolve(args, filesystem, environment);
987 show_settings!(args);
988
989 let cache = cache.init().await?;
991
992 let mut sources = Vec::with_capacity(args.package.len() + args.requirements.len());
993 for package in args.package {
994 sources.push(RequirementsSource::from_package_argument(&package)?);
995 }
996 sources.extend(
997 args.requirements
998 .into_iter()
999 .map(RequirementsSource::from_requirements_file)
1000 .collect::<Result<Vec<_>, _>>()?,
1001 );
1002 commands::pip_uninstall(
1003 &sources,
1004 args.settings.python,
1005 args.settings.system,
1006 args.settings.break_system_packages,
1007 args.settings.target,
1008 args.settings.prefix,
1009 cache,
1010 args.settings.keyring_provider,
1011 &client_builder.subcommand(vec!["pip".to_owned(), "uninstall".to_owned()]),
1012 args.dry_run,
1013 printer,
1014 globals.preview,
1015 )
1016 .await
1017 }
1018 Commands::Pip(PipNamespace {
1019 command: PipCommand::Freeze(args),
1020 }) => {
1021 let args = PipFreezeSettings::resolve(args, filesystem, environment);
1023 show_settings!(args);
1024
1025 let cache = cache.init().await?;
1027
1028 commands::pip_freeze(
1029 args.exclude_editable,
1030 &args.exclude,
1031 args.settings.strict,
1032 args.settings.python.as_deref(),
1033 args.settings.system,
1034 args.settings.target,
1035 args.settings.prefix,
1036 args.paths,
1037 &cache,
1038 printer,
1039 globals.preview,
1040 )
1041 }
1042 Commands::Pip(PipNamespace {
1043 command: PipCommand::List(args),
1044 }) => {
1045 args.compat_args.validate()?;
1046
1047 let args = PipListSettings::resolve(args, filesystem, environment);
1049 show_settings!(args);
1050
1051 let cache = cache.init().await?;
1053
1054 commands::pip_list(
1055 args.editable,
1056 &args.exclude,
1057 &args.format,
1058 args.outdated,
1059 args.settings.prerelease,
1060 args.settings.index_locations,
1061 args.settings.index_strategy,
1062 args.settings.keyring_provider,
1063 &client_builder.subcommand(vec!["pip".to_owned(), "list".to_owned()]),
1064 globals.concurrency,
1065 args.settings.strict,
1066 args.settings.exclude_newer,
1067 args.settings.python.as_deref(),
1068 args.settings.system,
1069 args.settings.target,
1070 args.settings.prefix,
1071 &cache,
1072 printer,
1073 globals.preview,
1074 )
1075 .await
1076 }
1077 Commands::Pip(PipNamespace {
1078 command: PipCommand::Show(args),
1079 }) => {
1080 let args = PipShowSettings::resolve(args, filesystem, environment);
1082 show_settings!(args);
1083
1084 let cache = cache.init().await?;
1086
1087 commands::pip_show(
1088 args.package,
1089 args.settings.strict,
1090 args.settings.python.as_deref(),
1091 args.settings.system,
1092 args.settings.target,
1093 args.settings.prefix,
1094 args.files,
1095 &cache,
1096 printer,
1097 globals.preview,
1098 )
1099 }
1100 Commands::Pip(PipNamespace {
1101 command: PipCommand::Tree(args),
1102 }) => {
1103 let args = PipTreeSettings::resolve(args, filesystem, environment);
1105
1106 let cache = cache.init().await?;
1108
1109 commands::pip_tree(
1110 args.show_version_specifiers,
1111 args.depth,
1112 &args.prune,
1113 &args.package,
1114 args.no_dedupe,
1115 args.invert,
1116 args.outdated,
1117 args.settings.prerelease,
1118 args.settings.index_locations,
1119 args.settings.index_strategy,
1120 args.settings.keyring_provider,
1121 client_builder.subcommand(vec!["pip".to_owned(), "tree".to_owned()]),
1122 globals.concurrency,
1123 args.settings.strict,
1124 args.settings.exclude_newer,
1125 args.settings.python.as_deref(),
1126 args.settings.system,
1127 &cache,
1128 printer,
1129 globals.preview,
1130 )
1131 .await
1132 }
1133 Commands::Pip(PipNamespace {
1134 command: PipCommand::Check(args),
1135 }) => {
1136 let args = PipCheckSettings::resolve(args, filesystem, environment);
1138 show_settings!(args);
1139
1140 let cache = cache.init().await?;
1142
1143 commands::pip_check(
1144 args.settings.python.as_deref(),
1145 args.settings.system,
1146 args.settings.python_version.as_ref(),
1147 args.settings.python_platform.as_ref(),
1148 &cache,
1149 printer,
1150 globals.preview,
1151 )
1152 }
1153 Commands::Pip(PipNamespace {
1154 command: PipCommand::Debug(_),
1155 }) => Err(anyhow!(
1156 "pip's `debug` is unsupported (consider using `uvx pip debug` instead)"
1157 )),
1158 Commands::Cache(CacheNamespace {
1159 command: CacheCommand::Clean(args),
1160 })
1161 | Commands::Clean(args) => {
1162 show_settings!(args);
1163 commands::cache_clean(&args.package, args.force, cache, printer).await
1164 }
1165 Commands::Cache(CacheNamespace {
1166 command: CacheCommand::Prune(args),
1167 }) => {
1168 show_settings!(args);
1169 commands::cache_prune(args.ci, args.force, cache, printer).await
1170 }
1171 Commands::Cache(CacheNamespace {
1172 command: CacheCommand::Dir,
1173 }) => commands::cache_dir(&cache, printer),
1174 Commands::Cache(CacheNamespace {
1175 command: CacheCommand::Size(args),
1176 }) => commands::cache_size(&cache, args.human, printer, globals.preview),
1177 Commands::Build(args) => {
1178 let args = settings::BuildSettings::resolve(args, filesystem, environment);
1180 show_settings!(args);
1181
1182 globals
1184 .network_settings
1185 .check_refresh_conflict(&args.refresh);
1186
1187 let cache = cache.init().await?.with_refresh(
1189 args.refresh
1190 .combine(Refresh::from(args.settings.upgrade.clone())),
1191 );
1192
1193 let build_constraints = args
1195 .build_constraints
1196 .into_iter()
1197 .map(RequirementsSource::from_constraints_txt)
1198 .collect::<Result<Vec<_>, _>>()?;
1199
1200 commands::build_frontend(
1201 &project_dir,
1202 args.src,
1203 args.package,
1204 args.all_packages,
1205 args.out_dir,
1206 args.sdist,
1207 args.wheel,
1208 args.list,
1209 args.build_logs,
1210 args.gitignore,
1211 args.force_pep517,
1212 args.clear,
1213 build_constraints,
1214 args.build_constraints_from_workspace,
1215 args.hash_checking,
1216 args.python,
1217 args.install_mirrors,
1218 &args.settings,
1219 &client_builder.subcommand(vec!["build".to_owned()]),
1220 cli.top_level.no_config,
1221 globals.python_preference,
1222 globals.python_downloads,
1223 globals.concurrency,
1224 &cache,
1225 &workspace_cache,
1226 printer,
1227 globals.preview,
1228 )
1229 .await
1230 }
1231 Commands::Venv(args) => {
1232 args.compat_args.validate()?;
1233
1234 if args.no_system {
1235 warn_user_once!(
1236 "The `--no-system` flag has no effect, `uv venv` always ignores virtual environments when finding a Python interpreter; did you mean `--managed-python`?"
1237 );
1238 }
1239
1240 if args.system {
1241 warn_user_once!(
1242 "The `--system` flag has no effect, `uv venv` always ignores virtual environments when finding a Python interpreter; did you mean `--no-managed-python`?"
1243 );
1244 }
1245
1246 let args = settings::VenvSettings::resolve(args, filesystem, environment);
1248 show_settings!(args);
1249
1250 globals
1252 .network_settings
1253 .check_refresh_conflict(&args.refresh);
1254
1255 let cache = cache.init().await?.with_refresh(
1257 args.refresh
1258 .combine(Refresh::from(args.settings.reinstall.clone()))
1259 .combine(Refresh::from(args.settings.upgrade.clone())),
1260 );
1261
1262 let prompt = args.prompt.or_else(|| {
1264 if args.path.is_none() {
1265 Some(".".to_string())
1266 } else {
1267 None
1268 }
1269 });
1270
1271 let python_request: Option<PythonRequest> =
1272 args.settings.python.as_deref().map(PythonRequest::parse);
1273
1274 let on_existing = uv_virtualenv::OnExisting::from_args(
1275 args.allow_existing,
1276 args.clear,
1277 args.no_clear,
1278 );
1279
1280 commands::venv(
1281 &project_dir,
1282 args.path,
1283 python_request,
1284 args.settings.install_mirrors,
1285 globals.python_preference,
1286 globals.python_downloads,
1287 args.settings.link_mode,
1288 &args.settings.index_locations,
1289 args.settings.index_strategy,
1290 args.settings.dependency_metadata,
1291 args.settings.keyring_provider,
1292 &client_builder.subcommand(vec!["venv".to_owned()]),
1293 uv_virtualenv::Prompt::from_args(prompt),
1294 args.system_site_packages,
1295 args.seed,
1296 on_existing,
1297 args.settings.exclude_newer,
1298 globals.concurrency,
1299 cli.top_level.no_config,
1300 args.no_project,
1301 &cache,
1302 &workspace_cache,
1303 printer,
1304 args.relocatable
1305 || (globals
1306 .preview
1307 .is_enabled(PreviewFeature::RelocatableEnvsDefault)
1308 && !args.no_relocatable),
1309 globals.preview,
1310 )
1311 .await
1312 }
1313 Commands::Project(project) => {
1314 Box::pin(run_project(
1315 project,
1316 &project_dir,
1317 run_command,
1318 script,
1319 globals,
1320 cli.top_level.no_config,
1321 cli.top_level.global_args.project.is_some(),
1322 client_builder,
1323 filesystem,
1324 cache,
1325 &workspace_cache,
1326 printer,
1327 ))
1328 .await
1329 }
1330 #[cfg(feature = "self-update")]
1331 Commands::Self_(SelfNamespace {
1332 command:
1333 SelfCommand::Update(SelfUpdateArgs {
1334 target_version,
1335 token,
1336 dry_run,
1337 }),
1338 }) => {
1339 commands::self_update(
1340 target_version,
1341 token,
1342 dry_run,
1343 printer,
1344 client_builder.subcommand(vec!["self".to_owned(), "update".to_owned()]),
1345 )
1346 .await
1347 }
1348 Commands::Self_(SelfNamespace {
1349 command:
1350 SelfCommand::Version {
1351 short,
1352 output_format,
1353 },
1354 }) => {
1355 commands::self_version(short, output_format, printer)?;
1356 Ok(ExitStatus::Success)
1357 }
1358 #[cfg(not(feature = "self-update"))]
1359 Commands::Self_(_) => {
1360 const BASE_MESSAGE: &str =
1361 "uv was installed through an external package manager and cannot update itself.";
1362
1363 let message = match InstallSource::detect() {
1364 Some(source) => format!(
1365 "{base}\n\n{hint}{colon} You installed uv using {}. To update uv, run `{}`",
1366 source.description(),
1367 source.update_instructions().green(),
1368 hint = "hint".bold().cyan(),
1369 colon = ":".bold(),
1370 base = BASE_MESSAGE
1371 ),
1372 None => format!("{BASE_MESSAGE} Please use your package manager to update uv."),
1373 };
1374
1375 anyhow::bail!(message);
1376 }
1377 Commands::GenerateShellCompletion(args) => {
1378 args.shell.generate(&mut Cli::command(), &mut stdout());
1379 Ok(ExitStatus::Success)
1380 }
1381 Commands::Tool(ToolNamespace {
1382 command: run_variant @ (ToolCommand::Uvx(_) | ToolCommand::Run(_)),
1383 }) => {
1384 let (args, invocation_source) = match run_variant {
1385 ToolCommand::Uvx(args) => (args.tool_run, ToolRunCommand::Uvx),
1386 ToolCommand::Run(args) => (args, ToolRunCommand::ToolRun),
1387 _ => unreachable!(),
1389 };
1390
1391 if let Some(shell) = args.generate_shell_completion {
1392 let mut uvx = Cli::command()
1394 .find_subcommand("tool")
1395 .unwrap()
1396 .find_subcommand("uvx")
1397 .unwrap()
1398 .clone()
1399 .disable_help_flag(true)
1402 .disable_version_flag(true);
1403
1404 for arg in TopLevelArgs::command().get_arguments() {
1407 if arg.get_id() != "isolated" && arg.get_id() != "version" {
1408 uvx = uvx.arg(arg);
1409 }
1410 }
1411 shell.generate(&mut uvx, &mut stdout());
1412 return Ok(ExitStatus::Success);
1413 }
1414
1415 let args = settings::ToolRunSettings::resolve(
1417 args,
1418 filesystem,
1419 invocation_source,
1420 environment,
1421 );
1422 show_settings!(args);
1423
1424 globals
1426 .network_settings
1427 .check_refresh_conflict(&args.refresh);
1428
1429 let cache = cache.init().await?.with_refresh(
1431 args.refresh
1432 .combine(Refresh::from(args.settings.reinstall.clone()))
1433 .combine(Refresh::from(args.settings.resolver.upgrade.clone())),
1434 );
1435
1436 let requirements = {
1437 let mut requirements = Vec::with_capacity(
1438 args.with.len() + args.with_editable.len() + args.with_requirements.len(),
1439 );
1440 for package in args.with {
1441 requirements.push(RequirementsSource::from_with_package_argument(&package)?);
1442 }
1443 for package in args.with_editable {
1444 requirements.push(RequirementsSource::from_editable(&package)?);
1445 }
1446 requirements.extend(
1447 args.with_requirements
1448 .into_iter()
1449 .map(RequirementsSource::from_requirements_file)
1450 .collect::<Result<Vec<_>, _>>()?,
1451 );
1452 requirements
1453 };
1454 let constraints = args
1455 .constraints
1456 .into_iter()
1457 .map(RequirementsSource::from_constraints_txt)
1458 .collect::<Result<Vec<_>, _>>()?;
1459 let overrides = args
1460 .overrides
1461 .into_iter()
1462 .map(RequirementsSource::from_overrides_txt)
1463 .collect::<Result<Vec<_>, _>>()?;
1464
1465 let build_constraints = args
1466 .build_constraints
1467 .into_iter()
1468 .map(RequirementsSource::from_constraints_txt)
1469 .collect::<Result<Vec<_>, _>>()?;
1470
1471 let client_builder = match invocation_source {
1472 ToolRunCommand::Uvx => client_builder.subcommand(vec!["uvx".to_owned()]),
1473 ToolRunCommand::ToolRun => {
1474 client_builder.subcommand(vec!["tool".to_owned(), "run".to_owned()])
1475 }
1476 };
1477
1478 Box::pin(commands::tool_run(
1479 args.command,
1480 args.from,
1481 &requirements,
1482 &constraints,
1483 &overrides,
1484 &build_constraints,
1485 args.show_resolution || globals.verbose > 0,
1486 args.lfs,
1487 args.python,
1488 args.python_platform,
1489 args.install_mirrors,
1490 args.options,
1491 args.settings,
1492 client_builder,
1493 invocation_source,
1494 args.isolated,
1495 globals.python_preference,
1496 globals.python_downloads,
1497 globals.installer_metadata,
1498 globals.concurrency,
1499 cache,
1500 workspace_cache,
1501 printer,
1502 args.env_file,
1503 args.no_env_file,
1504 globals.preview,
1505 ))
1506 .await
1507 }
1508 Commands::Tool(ToolNamespace {
1509 command: ToolCommand::Install(args),
1510 }) => {
1511 let args = settings::ToolInstallSettings::resolve(args, filesystem, environment);
1513 show_settings!(args);
1514
1515 globals
1517 .network_settings
1518 .check_refresh_conflict(&args.refresh);
1519
1520 let cache = cache.init().await?.with_refresh(
1522 args.refresh
1523 .combine(Refresh::from(args.settings.reinstall.clone()))
1524 .combine(Refresh::from(args.settings.resolver.upgrade.clone())),
1525 );
1526
1527 let mut entrypoints = Vec::with_capacity(args.with_executables_from.len());
1528 let mut requirements = Vec::with_capacity(
1529 args.with.len()
1530 + args.with_editable.len()
1531 + args.with_requirements.len()
1532 + args.with_executables_from.len(),
1533 );
1534 for pkg in args.with {
1535 requirements.push(RequirementsSource::from_with_package_argument(&pkg)?);
1536 }
1537 for pkg in args.with_editable {
1538 requirements.push(RequirementsSource::from_editable(&pkg)?);
1539 }
1540 for path in args.with_requirements {
1541 requirements.push(RequirementsSource::from_requirements_file(path)?);
1542 }
1543 for pkg in &args.with_executables_from {
1544 let source = RequirementsSource::from_with_package_argument(pkg)?;
1545 let RequirementsSource::Package(RequirementsTxtRequirement::Named(requirement)) =
1546 &source
1547 else {
1548 bail!(
1549 "Expected a named package for `--with-executables-from`, but got: {}",
1550 source.to_string().cyan()
1551 )
1552 };
1553 entrypoints.push(requirement.name.clone());
1554 requirements.push(source);
1555 }
1556
1557 let constraints = args
1558 .constraints
1559 .into_iter()
1560 .map(RequirementsSource::from_constraints_txt)
1561 .collect::<Result<Vec<_>, _>>()?;
1562 let overrides = args
1563 .overrides
1564 .into_iter()
1565 .map(RequirementsSource::from_overrides_txt)
1566 .collect::<Result<Vec<_>, _>>()?;
1567 let excludes = args
1568 .excludes
1569 .into_iter()
1570 .map(RequirementsSource::from_requirements_txt)
1571 .collect::<Result<Vec<_>, _>>()?;
1572 let build_constraints = args
1573 .build_constraints
1574 .into_iter()
1575 .map(RequirementsSource::from_constraints_txt)
1576 .collect::<Result<Vec<_>, _>>()?;
1577
1578 Box::pin(commands::tool_install(
1579 args.package,
1580 args.editable,
1581 args.from,
1582 &requirements,
1583 &constraints,
1584 &overrides,
1585 &excludes,
1586 &build_constraints,
1587 &entrypoints,
1588 args.lfs,
1589 args.python,
1590 args.python_platform,
1591 args.install_mirrors,
1592 args.force,
1593 args.options,
1594 args.settings,
1595 client_builder.subcommand(vec!["tool".to_owned(), "install".to_owned()]),
1596 globals.python_preference,
1597 globals.python_downloads,
1598 globals.installer_metadata,
1599 globals.concurrency,
1600 cli.top_level.no_config,
1601 cache,
1602 &workspace_cache,
1603 printer,
1604 globals.preview,
1605 ))
1606 .await
1607 }
1608 Commands::Tool(ToolNamespace {
1609 command: ToolCommand::List(args),
1610 }) => {
1611 let args = settings::ToolListSettings::resolve(args, filesystem);
1613 show_settings!(args);
1614
1615 let cache = cache.init().await?;
1617
1618 commands::tool_list(
1619 args.show_paths,
1620 args.show_version_specifiers,
1621 args.show_with,
1622 args.show_extras,
1623 args.show_python,
1624 args.outdated,
1625 client_builder.subcommand(vec!["tool".to_owned(), "list".to_owned()]),
1626 globals.concurrency,
1627 &cache,
1628 printer,
1629 )
1630 .await
1631 }
1632 Commands::Tool(ToolNamespace {
1633 command: ToolCommand::Upgrade(args),
1634 }) => {
1635 let args = settings::ToolUpgradeSettings::resolve(args, filesystem, &environment);
1637 show_settings!(args);
1638
1639 let cache = cache
1641 .init()
1642 .await?
1643 .with_refresh(Refresh::All(Timestamp::now()));
1644
1645 Box::pin(commands::tool_upgrade(
1646 args.names,
1647 args.python,
1648 args.python_platform,
1649 args.install_mirrors,
1650 args.args,
1651 args.filesystem,
1652 client_builder.subcommand(vec!["tool".to_owned(), "upgrade".to_owned()]),
1653 globals.python_preference,
1654 globals.python_downloads,
1655 globals.installer_metadata,
1656 globals.concurrency,
1657 &cache,
1658 &workspace_cache,
1659 printer,
1660 globals.preview,
1661 ))
1662 .await
1663 }
1664 Commands::Tool(ToolNamespace {
1665 command: ToolCommand::Uninstall(args),
1666 }) => {
1667 let args = settings::ToolUninstallSettings::resolve(args, filesystem);
1669 show_settings!(args);
1670
1671 commands::tool_uninstall(args.name, printer).await
1672 }
1673 Commands::Tool(ToolNamespace {
1674 command: ToolCommand::UpdateShell,
1675 }) => {
1676 commands::tool_update_shell(printer).await?;
1677 Ok(ExitStatus::Success)
1678 }
1679 Commands::Tool(ToolNamespace {
1680 command: ToolCommand::Dir(args),
1681 }) => {
1682 let args = settings::ToolDirSettings::resolve(args, filesystem);
1684 show_settings!(args);
1685
1686 commands::tool_dir(args.bin, globals.preview, printer)?;
1687 Ok(ExitStatus::Success)
1688 }
1689 Commands::Python(PythonNamespace {
1690 command: PythonCommand::List(args),
1691 }) => {
1692 let args = settings::PythonListSettings::resolve(args, filesystem, environment);
1694 show_settings!(args);
1695
1696 let cache = cache.init().await?;
1698
1699 commands::python_list(
1700 args.request,
1701 args.kinds,
1702 args.all_versions,
1703 args.all_platforms,
1704 args.all_arches,
1705 args.show_urls,
1706 args.output_format,
1707 args.python_downloads_json_url,
1708 args.python_install_mirror,
1709 args.pypy_install_mirror,
1710 globals.python_preference,
1711 globals.python_downloads,
1712 &client_builder.subcommand(vec!["python".to_owned(), "list".to_owned()]),
1713 &cache,
1714 printer,
1715 globals.preview,
1716 )
1717 .await
1718 }
1719 Commands::Python(PythonNamespace {
1720 command: PythonCommand::Install(args),
1721 }) => {
1722 let args = settings::PythonInstallSettings::resolve(args, filesystem, environment);
1724 show_settings!(args);
1725
1726 let cache = cache.init().await?;
1728
1729 commands::python_install(
1730 &project_dir,
1731 args.install_dir,
1732 args.targets,
1733 args.reinstall,
1734 args.upgrade,
1735 args.bin,
1736 args.registry,
1737 args.force,
1738 args.python_install_mirror,
1739 args.pypy_install_mirror,
1740 args.python_downloads_json_url,
1741 client_builder.subcommand(vec!["python".to_owned(), "install".to_owned()]),
1742 args.default,
1743 globals.python_downloads,
1744 cli.top_level.no_config,
1745 args.compile_bytecode,
1746 &globals.concurrency,
1747 &cache,
1748 globals.preview,
1749 printer,
1750 )
1751 .await
1752 }
1753 Commands::Python(PythonNamespace {
1754 command: PythonCommand::Upgrade(args),
1755 }) => {
1756 let args = settings::PythonUpgradeSettings::resolve(args, filesystem, environment);
1758 show_settings!(args);
1759 let upgrade = commands::PythonUpgrade::Enabled(commands::PythonUpgradeSource::Upgrade);
1760
1761 let cache = cache.init().await?;
1763
1764 commands::python_install(
1765 &project_dir,
1766 args.install_dir,
1767 args.targets,
1768 args.reinstall,
1769 upgrade,
1770 args.bin,
1771 args.registry,
1772 args.force,
1773 args.python_install_mirror,
1774 args.pypy_install_mirror,
1775 args.python_downloads_json_url,
1776 client_builder.subcommand(vec!["python".to_owned(), "upgrade".to_owned()]),
1777 args.default,
1778 globals.python_downloads,
1779 cli.top_level.no_config,
1780 args.compile_bytecode,
1781 &globals.concurrency,
1782 &cache,
1783 globals.preview,
1784 printer,
1785 )
1786 .await
1787 }
1788 Commands::Python(PythonNamespace {
1789 command: PythonCommand::Uninstall(args),
1790 }) => {
1791 let args = settings::PythonUninstallSettings::resolve(args, filesystem);
1793 show_settings!(args);
1794
1795 commands::python_uninstall(args.install_dir, args.targets, args.all, printer).await
1796 }
1797 Commands::Python(PythonNamespace {
1798 command: PythonCommand::Find(args),
1799 }) => {
1800 let args = settings::PythonFindSettings::resolve(args, filesystem, environment);
1802
1803 let cache = cache.init().await?;
1805
1806 if let Some(Pep723Item::Script(script)) = script {
1807 commands::python_find_script(
1808 (&script).into(),
1809 args.show_version,
1810 args.resolve_links,
1811 &client_builder.subcommand(vec!["python".to_owned(), "find".to_owned()]),
1813 globals.python_preference,
1814 globals.python_downloads,
1815 cli.top_level.no_config,
1816 &cache,
1817 printer,
1818 globals.preview,
1819 )
1820 .await
1821 } else {
1822 commands::python_find(
1823 &project_dir,
1824 args.request,
1825 args.show_version,
1826 args.resolve_links,
1827 args.no_project,
1828 cli.top_level.no_config,
1829 args.system,
1830 globals.python_preference,
1831 args.python_downloads_json_url.as_deref(),
1832 &client_builder.subcommand(vec!["python".to_owned(), "find".to_owned()]),
1833 &cache,
1834 &workspace_cache,
1835 printer,
1836 globals.preview,
1837 )
1838 .await
1839 }
1840 }
1841 Commands::Python(PythonNamespace {
1842 command: PythonCommand::Pin(args),
1843 }) => {
1844 let args = settings::PythonPinSettings::resolve(args, filesystem, environment);
1846
1847 let cache = cache.init().await?;
1849
1850 commands::python_pin(
1851 &project_dir,
1852 args.request,
1853 args.resolved,
1854 globals.python_preference,
1855 globals.python_downloads,
1856 args.no_project,
1857 args.global,
1858 args.rm,
1859 args.install_mirrors,
1860 client_builder.subcommand(vec!["python".to_owned(), "pin".to_owned()]),
1861 &cache,
1862 &workspace_cache,
1863 printer,
1864 globals.preview,
1865 )
1866 .await
1867 }
1868 Commands::Python(PythonNamespace {
1869 command: PythonCommand::Dir(args),
1870 }) => {
1871 let args = settings::PythonDirSettings::resolve(args, filesystem);
1873 show_settings!(args);
1874
1875 commands::python_dir(args.bin, printer)?;
1876 Ok(ExitStatus::Success)
1877 }
1878 Commands::Python(PythonNamespace {
1879 command: PythonCommand::UpdateShell,
1880 }) => {
1881 commands::python_update_shell(printer).await?;
1882 Ok(ExitStatus::Success)
1883 }
1884 Commands::Publish(args) => {
1885 show_settings!(args);
1886
1887 if args.skip_existing {
1888 bail!(
1889 "`uv publish` does not support `--skip-existing` because there is not a \
1890 reliable way to identify when an upload fails due to an existing \
1891 distribution. Instead, use `--check-url` to provide the URL to the simple \
1892 API for your index. uv will check the index for existing distributions before \
1893 attempting uploads."
1894 );
1895 }
1896
1897 let PublishSettings {
1899 files,
1900 username,
1901 password,
1902 dry_run,
1903 no_attestations,
1904 direct,
1905 publish_url,
1906 trusted_publishing,
1907 keyring_provider,
1908 check_url,
1909 index,
1910 index_locations,
1911 } = PublishSettings::resolve(args, filesystem);
1912
1913 commands::publish(
1914 files,
1915 publish_url,
1916 trusted_publishing,
1917 keyring_provider,
1918 &environment,
1919 &client_builder.subcommand(vec!["publish".to_owned()]),
1920 username,
1921 password,
1922 check_url,
1923 index,
1924 index_locations,
1925 dry_run,
1926 no_attestations,
1927 direct,
1928 globals.preview,
1929 &cache,
1930 printer,
1931 )
1932 .await
1933 }
1934 Commands::Workspace(WorkspaceNamespace { command }) => match command {
1935 WorkspaceCommand::Metadata(_args) => {
1936 commands::metadata(&project_dir, globals.preview, &workspace_cache, printer).await
1937 }
1938 WorkspaceCommand::Dir(args) => {
1939 commands::dir(args.package, &project_dir, &workspace_cache, printer).await
1940 }
1941 WorkspaceCommand::List(args) => {
1942 commands::list(&project_dir, args.paths, &workspace_cache, printer).await
1943 }
1944 },
1945 Commands::BuildBackend { command } => spawn_blocking(move || match command {
1946 BuildBackendCommand::BuildSdist { sdist_directory } => {
1947 commands::build_backend::build_sdist(&sdist_directory)
1948 }
1949 BuildBackendCommand::BuildWheel {
1950 wheel_directory,
1951 metadata_directory,
1952 } => commands::build_backend::build_wheel(
1953 &wheel_directory,
1954 metadata_directory.as_deref(),
1955 ),
1956 BuildBackendCommand::BuildEditable {
1957 wheel_directory,
1958 metadata_directory,
1959 } => commands::build_backend::build_editable(
1960 &wheel_directory,
1961 metadata_directory.as_deref(),
1962 ),
1963 BuildBackendCommand::GetRequiresForBuildSdist => {
1964 commands::build_backend::get_requires_for_build_sdist()
1965 }
1966 BuildBackendCommand::GetRequiresForBuildWheel => {
1967 commands::build_backend::get_requires_for_build_wheel()
1968 }
1969 BuildBackendCommand::PrepareMetadataForBuildWheel { wheel_directory } => {
1970 commands::build_backend::prepare_metadata_for_build_wheel(&wheel_directory)
1971 }
1972 BuildBackendCommand::GetRequiresForBuildEditable => {
1973 commands::build_backend::get_requires_for_build_editable()
1974 }
1975 BuildBackendCommand::PrepareMetadataForBuildEditable { wheel_directory } => {
1976 commands::build_backend::prepare_metadata_for_build_editable(&wheel_directory)
1977 }
1978 })
1979 .await
1980 .expect("tokio threadpool exited unexpectedly"),
1981 }
1982}
1983
1984async fn run_project(
1986 project_command: Box<ProjectCommand>,
1987 project_dir: &Path,
1988 command: Option<RunCommand>,
1989 script: Option<Pep723Item>,
1990 globals: GlobalSettings,
1991 no_config: bool,
1993 explicit_project: bool,
1994 client_builder: BaseClientBuilder<'_>,
1995 filesystem: Option<FilesystemOptions>,
1996 cache: Cache,
1997 workspace_cache: &WorkspaceCache,
1998 printer: Printer,
1999) -> Result<ExitStatus> {
2000 macro_rules! show_settings {
2002 ($arg:expr) => {
2003 if globals.show_settings {
2004 writeln!(printer.stdout(), "{:#?}", $arg)?;
2005 return Ok(ExitStatus::Success);
2006 }
2007 };
2008 }
2009
2010 let environment = EnvironmentOptions::new()?;
2012
2013 match *project_command {
2014 ProjectCommand::Init(args) => {
2015 let args = settings::InitSettings::resolve(args, filesystem, environment);
2017 show_settings!(args);
2018
2019 if explicit_project {
2021 if globals.preview.is_enabled(PreviewFeature::InitProjectFlag) {
2022 bail!(
2023 "The `--project` option cannot be used in `uv init`. {}",
2024 if args.path.is_some() {
2025 "Use `--directory` instead."
2026 } else {
2027 "Use `--directory` or a positional path instead."
2028 }
2029 )
2030 }
2031
2032 warn_user!(
2033 "Use of the `--project` option in `uv init` is deprecated and will be removed in a future release. {}",
2034 if args.path.is_some() {
2035 "Since a positional path was provided, the `--project` option has no effect. Consider using `--directory` instead."
2036 } else {
2037 "Consider using `uv init <PATH>` instead."
2038 }
2039 );
2040 }
2041
2042 let cache = cache.init().await?;
2044
2045 commands::init(
2046 project_dir,
2047 args.path,
2048 args.name,
2049 args.package,
2050 args.kind,
2051 args.bare,
2052 args.description,
2053 args.no_description,
2054 args.vcs,
2055 args.build_backend,
2056 args.no_readme,
2057 args.author_from,
2058 args.pin_python,
2059 args.python,
2060 args.install_mirrors,
2061 args.no_workspace,
2062 &client_builder.subcommand(vec!["init".to_owned()]),
2063 globals.python_preference,
2064 globals.python_downloads,
2065 no_config,
2066 &cache,
2067 printer,
2068 globals.preview,
2069 )
2070 .await
2071 }
2072 ProjectCommand::Run(args) => {
2073 let args = settings::RunSettings::resolve(args, filesystem, environment);
2075 show_settings!(args);
2076
2077 globals
2079 .network_settings
2080 .check_refresh_conflict(&args.refresh);
2081
2082 let cache = cache.init().await?.with_refresh(
2084 args.refresh
2085 .combine(Refresh::from(args.settings.reinstall.clone()))
2086 .combine(Refresh::from(args.settings.resolver.upgrade.clone())),
2087 );
2088
2089 let mut requirements = Vec::with_capacity(
2090 args.with.len() + args.with_editable.len() + args.with_requirements.len(),
2091 );
2092 for package in args.with {
2093 requirements.push(RequirementsSource::from_with_package_argument(&package)?);
2094 }
2095 for package in args.with_editable {
2096 requirements.push(RequirementsSource::from_editable(&package)?);
2097 }
2098 requirements.extend(
2099 args.with_requirements
2100 .into_iter()
2101 .map(RequirementsSource::from_requirements_file)
2102 .collect::<Result<Vec<_>, _>>()?,
2103 );
2104
2105 Box::pin(commands::run(
2106 project_dir,
2107 script,
2108 command,
2109 requirements,
2110 args.show_resolution || globals.verbose > 0,
2111 args.lock_check,
2112 args.frozen,
2113 args.active,
2114 args.no_sync,
2115 args.isolated,
2116 args.all_packages,
2117 args.package,
2118 args.no_project,
2119 no_config,
2120 args.extras,
2121 args.groups,
2122 args.editable,
2123 args.modifications,
2124 args.python,
2125 args.python_platform,
2126 args.install_mirrors,
2127 args.settings,
2128 client_builder.subcommand(vec!["run".to_owned()]),
2129 globals.python_preference,
2130 globals.python_downloads,
2131 globals.installer_metadata,
2132 globals.concurrency,
2133 cache,
2134 workspace_cache,
2135 printer,
2136 args.env_file,
2137 globals.preview,
2138 args.max_recursion_depth,
2139 ))
2140 .await
2141 }
2142 ProjectCommand::Sync(args) => {
2143 let args = settings::SyncSettings::resolve(args, filesystem, environment);
2145 show_settings!(args);
2146
2147 globals
2149 .network_settings
2150 .check_refresh_conflict(&args.refresh);
2151
2152 let cache = cache.init().await?.with_refresh(
2154 args.refresh
2155 .combine(Refresh::from(args.settings.reinstall.clone()))
2156 .combine(Refresh::from(args.settings.resolver.upgrade.clone())),
2157 );
2158
2159 let script = script.map(|script| match script {
2161 Pep723Item::Script(script) => script,
2162 Pep723Item::Stdin(..) => unreachable!("`uv lock` does not support stdin"),
2163 Pep723Item::Remote(..) => unreachable!("`uv lock` does not support remote files"),
2164 });
2165
2166 Box::pin(commands::sync(
2167 project_dir,
2168 args.lock_check,
2169 args.frozen,
2170 args.dry_run,
2171 args.active,
2172 args.all_packages,
2173 args.package,
2174 args.extras,
2175 args.groups,
2176 args.editable,
2177 args.install_options,
2178 args.modifications,
2179 args.python,
2180 args.python_platform,
2181 args.install_mirrors,
2182 globals.python_preference,
2183 globals.python_downloads,
2184 args.settings,
2185 client_builder.subcommand(vec!["sync".to_owned()]),
2186 script,
2187 globals.installer_metadata,
2188 globals.concurrency,
2189 no_config,
2190 &cache,
2191 workspace_cache,
2192 printer,
2193 globals.preview,
2194 args.output_format,
2195 ))
2196 .await
2197 }
2198 ProjectCommand::Lock(args) => {
2199 let args = settings::LockSettings::resolve(args, filesystem, environment);
2201 show_settings!(args);
2202
2203 globals
2205 .network_settings
2206 .check_refresh_conflict(&args.refresh);
2207
2208 let cache = cache.init().await?.with_refresh(
2210 args.refresh
2211 .clone()
2212 .combine(Refresh::from(args.settings.upgrade.clone())),
2213 );
2214
2215 let script = script
2218 .map(|script| match script {
2219 Pep723Item::Script(script) => script,
2220 Pep723Item::Stdin(..) => unreachable!("`uv add` does not support stdin"),
2221 Pep723Item::Remote(..) => {
2222 unreachable!("`uv add` does not support remote files")
2223 }
2224 })
2225 .map(ScriptPath::Script)
2226 .or(args.script.map(ScriptPath::Path));
2227
2228 Box::pin(commands::lock(
2229 project_dir,
2230 args.lock_check,
2231 args.frozen,
2232 args.dry_run,
2233 args.refresh,
2234 args.python,
2235 args.install_mirrors,
2236 args.settings,
2237 client_builder.subcommand(vec!["lock".to_owned()]),
2238 script,
2239 globals.python_preference,
2240 globals.python_downloads,
2241 globals.concurrency,
2242 no_config,
2243 &cache,
2244 workspace_cache,
2245 printer,
2246 globals.preview,
2247 ))
2248 .await
2249 }
2250 ProjectCommand::Add(args) => {
2251 let mut args = settings::AddSettings::resolve(args, filesystem, environment);
2253 show_settings!(args);
2254
2255 let script = script
2258 .map(|script| match script {
2259 Pep723Item::Script(script) => script,
2260 Pep723Item::Stdin(..) => unreachable!("`uv add` does not support stdin"),
2261 Pep723Item::Remote(..) => {
2262 unreachable!("`uv add` does not support remote files")
2263 }
2264 })
2265 .map(ScriptPath::Script)
2266 .or(args.script.map(ScriptPath::Path));
2267
2268 let requirements = args
2269 .packages
2270 .iter()
2271 .map(String::as_str)
2272 .map(RequirementsSource::from_package_argument)
2273 .chain(
2274 args.requirements
2275 .into_iter()
2276 .map(RequirementsSource::from_requirements_file),
2277 )
2278 .collect::<Result<Vec<_>>>()?;
2279
2280 for requirement in &requirements {
2283 let requirement = match requirement {
2284 RequirementsSource::Package(requirement) => requirement,
2285 RequirementsSource::Editable(requirement) => requirement,
2286 _ => continue,
2287 };
2288 match requirement {
2289 RequirementsTxtRequirement::Named(requirement) => {
2290 if let Some(VersionOrUrl::Url(url)) = requirement.version_or_url.as_ref() {
2291 if let ParsedUrl::Directory(ParsedDirectoryUrl {
2292 install_path, ..
2293 }) = &url.parsed_url
2294 {
2295 debug!(
2296 "Marking explicit source tree for reinstall: `{}`",
2297 install_path.display()
2298 );
2299 args.settings.reinstall = args
2300 .settings
2301 .reinstall
2302 .with_package(requirement.name.clone());
2303 }
2304 }
2305 }
2306 RequirementsTxtRequirement::Unnamed(requirement) => {
2307 if let ParsedUrl::Directory(ParsedDirectoryUrl { install_path, .. }) =
2308 &requirement.url.parsed_url
2309 {
2310 debug!(
2311 "Marking explicit source tree for reinstall: `{}`",
2312 install_path.display()
2313 );
2314 args.settings.reinstall =
2315 args.settings.reinstall.with_path(install_path.clone());
2316 }
2317 }
2318 }
2319 }
2320
2321 globals
2323 .network_settings
2324 .check_refresh_conflict(&args.refresh);
2325
2326 let cache = cache.init().await?.with_refresh(
2328 args.refresh
2329 .combine(Refresh::from(args.settings.reinstall.clone()))
2330 .combine(Refresh::from(args.settings.resolver.upgrade.clone())),
2331 );
2332
2333 let constraints = args
2334 .constraints
2335 .into_iter()
2336 .map(RequirementsSource::from_constraints_txt)
2337 .collect::<Result<Vec<_>, _>>()?;
2338
2339 Box::pin(commands::add(
2340 project_dir,
2341 args.lock_check,
2342 args.frozen,
2343 args.active,
2344 args.no_sync,
2345 args.no_install_project,
2346 args.only_install_project,
2347 args.no_install_workspace,
2348 args.only_install_workspace,
2349 args.no_install_local,
2350 args.only_install_local,
2351 args.no_install_package,
2352 args.only_install_package,
2353 requirements,
2354 constraints,
2355 args.marker,
2356 args.editable,
2357 args.dependency_type,
2358 args.raw,
2359 args.bounds,
2360 args.indexes,
2361 args.rev,
2362 args.tag,
2363 args.branch,
2364 args.lfs,
2365 args.extras,
2366 args.package,
2367 args.python,
2368 args.workspace,
2369 args.install_mirrors,
2370 args.settings,
2371 client_builder.subcommand(vec!["add".to_owned()]),
2372 script,
2373 globals.python_preference,
2374 globals.python_downloads,
2375 globals.installer_metadata,
2376 globals.concurrency,
2377 no_config,
2378 &cache,
2379 printer,
2380 globals.preview,
2381 ))
2382 .await
2383 }
2384 ProjectCommand::Remove(args) => {
2385 let args = settings::RemoveSettings::resolve(args, filesystem, environment);
2387 show_settings!(args);
2388
2389 globals
2391 .network_settings
2392 .check_refresh_conflict(&args.refresh);
2393
2394 let cache = cache.init().await?.with_refresh(
2396 args.refresh
2397 .combine(Refresh::from(args.settings.reinstall.clone()))
2398 .combine(Refresh::from(args.settings.resolver.upgrade.clone())),
2399 );
2400
2401 let script = script.map(|script| match script {
2403 Pep723Item::Script(script) => script,
2404 Pep723Item::Stdin(..) => unreachable!("`uv remove` does not support stdin"),
2405 Pep723Item::Remote(..) => unreachable!("`uv remove` does not support remote files"),
2406 });
2407
2408 Box::pin(commands::remove(
2409 project_dir,
2410 args.lock_check,
2411 args.frozen,
2412 args.active,
2413 args.no_sync,
2414 args.packages,
2415 args.dependency_type,
2416 args.package,
2417 args.python,
2418 args.install_mirrors,
2419 args.settings,
2420 client_builder.subcommand(vec!["remove".to_owned()]),
2421 script,
2422 globals.python_preference,
2423 globals.python_downloads,
2424 globals.installer_metadata,
2425 globals.concurrency,
2426 no_config,
2427 &cache,
2428 printer,
2429 globals.preview,
2430 ))
2431 .await
2432 }
2433 ProjectCommand::Version(args) => {
2434 let args = settings::VersionSettings::resolve(args, filesystem, environment);
2436 show_settings!(args);
2437
2438 globals
2440 .network_settings
2441 .check_refresh_conflict(&args.refresh);
2442
2443 let cache = cache.init().await?.with_refresh(
2445 args.refresh
2446 .combine(Refresh::from(args.settings.reinstall.clone()))
2447 .combine(Refresh::from(args.settings.resolver.upgrade.clone())),
2448 );
2449
2450 Box::pin(commands::project_version(
2451 args.value,
2452 args.bump,
2453 args.short,
2454 args.output_format,
2455 project_dir,
2456 args.package,
2457 explicit_project,
2458 args.dry_run,
2459 args.lock_check,
2460 args.frozen,
2461 args.active,
2462 args.no_sync,
2463 args.python,
2464 args.install_mirrors,
2465 args.settings,
2466 client_builder.subcommand(vec!["version".to_owned()]),
2467 globals.python_preference,
2468 globals.python_downloads,
2469 globals.installer_metadata,
2470 globals.concurrency,
2471 no_config,
2472 &cache,
2473 workspace_cache,
2474 printer,
2475 globals.preview,
2476 ))
2477 .await
2478 }
2479 ProjectCommand::Tree(args) => {
2480 let args = settings::TreeSettings::resolve(args, filesystem, environment);
2482 show_settings!(args);
2483
2484 let cache = cache.init().await?;
2486
2487 let script = script.map(|script| match script {
2489 Pep723Item::Script(script) => script,
2490 Pep723Item::Stdin(..) => unreachable!("`uv tree` does not support stdin"),
2491 Pep723Item::Remote(..) => unreachable!("`uv tree` does not support remote files"),
2492 });
2493
2494 Box::pin(commands::tree(
2495 project_dir,
2496 args.groups,
2497 args.lock_check,
2498 args.frozen,
2499 args.universal,
2500 args.depth,
2501 args.prune,
2502 args.package,
2503 args.no_dedupe,
2504 args.invert,
2505 args.outdated,
2506 args.show_sizes,
2507 args.python_version,
2508 args.python_platform,
2509 args.python,
2510 args.install_mirrors,
2511 args.resolver,
2512 &client_builder.subcommand(vec!["tree".to_owned()]),
2513 script,
2514 globals.python_preference,
2515 globals.python_downloads,
2516 globals.concurrency,
2517 no_config,
2518 &cache,
2519 printer,
2520 globals.preview,
2521 ))
2522 .await
2523 }
2524 ProjectCommand::Export(args) => {
2525 let args = settings::ExportSettings::resolve(args, filesystem, environment);
2527 show_settings!(args);
2528
2529 let cache = cache.init().await?;
2531
2532 let script = script.map(|script| match script {
2534 Pep723Item::Script(script) => script,
2535 Pep723Item::Stdin(..) => unreachable!("`uv export` does not support stdin"),
2536 Pep723Item::Remote(..) => unreachable!("`uv export` does not support remote files"),
2537 });
2538
2539 commands::export(
2540 project_dir,
2541 args.format,
2542 args.all_packages,
2543 args.package,
2544 args.prune,
2545 args.hashes,
2546 args.install_options,
2547 args.output_file,
2548 args.extras,
2549 args.groups,
2550 args.editable,
2551 args.lock_check,
2552 args.frozen,
2553 args.include_annotations,
2554 args.include_header,
2555 script,
2556 args.python,
2557 args.install_mirrors,
2558 args.settings,
2559 client_builder.subcommand(vec!["export".to_owned()]),
2560 globals.python_preference,
2561 globals.python_downloads,
2562 globals.concurrency,
2563 no_config,
2564 globals.quiet > 0,
2565 &cache,
2566 printer,
2567 globals.preview,
2568 )
2569 .boxed_local()
2570 .await
2571 }
2572 ProjectCommand::Format(args) => {
2573 let args = settings::FormatSettings::resolve(args, filesystem);
2575 show_settings!(args);
2576
2577 let cache = cache.init().await?;
2579
2580 Box::pin(commands::format(
2581 project_dir,
2582 args.check,
2583 args.diff,
2584 args.extra_args,
2585 args.version,
2586 args.exclude_newer,
2587 args.show_version,
2588 client_builder.subcommand(vec!["format".to_owned()]),
2589 cache,
2590 printer,
2591 globals.preview,
2592 args.no_project,
2593 ))
2594 .await
2595 }
2596 ProjectCommand::Audit(audit_args) => {
2597 let args = settings::AuditSettings::resolve(audit_args, filesystem, environment);
2598 show_settings!(args);
2599
2600 let cache = cache.init().await?;
2602
2603 let script = script.map(|script| match script {
2605 Pep723Item::Script(script) => script,
2606 Pep723Item::Stdin(..) => unreachable!("`uv audit` does not support stdin"),
2607 Pep723Item::Remote(..) => unreachable!("`uv audit` does not support remote files"),
2608 });
2609
2610 Box::pin(commands::audit(
2611 project_dir,
2612 args.extras,
2613 args.groups,
2614 args.lock_check,
2615 args.frozen,
2616 script,
2617 args.python_version,
2618 args.python_platform,
2619 args.install_mirrors,
2620 args.settings,
2621 client_builder.subcommand(vec!["audit".to_owned()]),
2622 globals.python_preference,
2623 globals.python_downloads,
2624 globals.concurrency,
2625 no_config,
2626 cache,
2627 printer,
2628 globals.preview,
2629 args.service_format,
2630 args.service_url,
2631 ))
2632 .await
2633 }
2634 }
2635}
2636
2637#[allow(unsafe_code)]
2652pub unsafe fn main<I, T>(args: I) -> ExitCode
2653where
2654 I: IntoIterator<Item = T>,
2655 T: Into<OsString> + Clone,
2656{
2657 #[cfg(windows)]
2658 windows_exception::setup();
2659
2660 if let Ok(current_exe) = std::env::current_exe() {
2663 unsafe {
2665 std::env::set_var(EnvVars::UV, current_exe);
2668 }
2669 }
2670
2671 let cli = match Cli::try_parse_from(args) {
2674 Ok(cli) => cli,
2675 Err(mut err) => {
2676 if let Some(ContextValue::String(subcommand)) = err.get(ContextKind::InvalidSubcommand)
2677 {
2678 match subcommand.as_str() {
2679 "compile" => {
2680 err.insert(
2681 ContextKind::SuggestedSubcommand,
2682 ContextValue::String("uv pip compile".to_string()),
2683 );
2684 }
2685 "install" => {
2686 err.insert(
2687 ContextKind::SuggestedSubcommand,
2688 ContextValue::String("uv pip install".to_string()),
2689 );
2690 }
2691 "uninstall" => {
2692 err.insert(
2693 ContextKind::SuggestedSubcommand,
2694 ContextValue::String("uv pip uninstall".to_string()),
2695 );
2696 }
2697 "freeze" => {
2698 err.insert(
2699 ContextKind::SuggestedSubcommand,
2700 ContextValue::String("uv pip freeze".to_string()),
2701 );
2702 }
2703 "list" => {
2704 err.insert(
2705 ContextKind::SuggestedSubcommand,
2706 ContextValue::String("uv pip list".to_string()),
2707 );
2708 }
2709 "show" => {
2710 err.insert(
2711 ContextKind::SuggestedSubcommand,
2712 ContextValue::String("uv pip show".to_string()),
2713 );
2714 }
2715 _ => {}
2716 }
2717 }
2718 err.exit()
2719 }
2720 };
2721
2722 let min_stack_size = min_stack_size();
2724 let main2 = move || {
2725 let runtime = tokio::runtime::Builder::new_current_thread()
2726 .enable_all()
2727 .thread_stack_size(min_stack_size)
2728 .build()
2729 .expect("Failed building the Runtime");
2730 let result = runtime.block_on(Box::pin(run(cli)));
2732 runtime.shutdown_background();
2738 result
2739 };
2740 let result = std::thread::Builder::new()
2741 .name("main2".to_owned())
2742 .stack_size(min_stack_size)
2743 .spawn(main2)
2744 .expect("Tokio executor failed, was there a panic?")
2745 .join()
2746 .expect("Tokio executor failed, was there a panic?");
2747
2748 match result {
2749 Ok(code) => code.into(),
2750 Err(err) => {
2751 trace!("Error trace: {err:?}");
2752 let mut causes = err.chain();
2753 eprintln!(
2754 "{}: {}",
2755 "error".red().bold(),
2756 causes.next().unwrap().to_string().trim()
2757 );
2758 for err in causes {
2759 eprintln!(" {}: {}", "Caused by".red().bold(), err.to_string().trim());
2760 }
2761 ExitStatus::Error.into()
2762 }
2763 }
2764}