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