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