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 anyhow::{Result, anyhow, bail};
15use clap::error::{ContextKind, ContextValue};
16use clap::{CommandFactory, Error, Parser};
17use futures::FutureExt;
18use owo_colors::OwoColorize;
19use settings::PipTreeSettings;
20use tokio::task::spawn_blocking;
21use tracing::{debug, instrument, trace};
22
23#[cfg(not(feature = "self-update"))]
24use crate::install_source::InstallSource;
25use uv_cache::{Cache, Refresh};
26use uv_cache_info::Timestamp;
27#[cfg(feature = "self-update")]
28use uv_cli::SelfUpdateArgs;
29use uv_cli::{
30 AuthCommand, AuthHelperCommand, AuthNamespace, BuildBackendCommand, CacheCommand,
31 CacheNamespace, CacheSizeOutputFormat, Cli, Commands, PipCommand, PipNamespace, ProjectCommand,
32 PythonCommand, PythonNamespace, SelfCommand, SelfNamespace, ToolCommand, ToolNamespace,
33 TopLevelArgs, WorkspaceCommand, WorkspaceNamespace, compat::CompatArgs, options::ArgumentError,
34};
35use uv_client::BaseClientBuilder;
36use uv_configuration::min_stack_size;
37use uv_flags::EnvironmentFlags;
38use uv_fs::{CWD, Simplified, normalize_path};
39#[cfg(feature = "self-update")]
40use uv_pep440::release_specifiers_to_ranges;
41use uv_pep508::VersionOrUrl;
42use uv_preview::PreviewFeature;
43use uv_pypi_types::{ParsedDirectoryUrl, ParsedUrl};
44use uv_python::{ConfigDiscovery, PythonRequest};
45use uv_requirements::{GroupsSpecification, RequirementsSource};
46use uv_requirements_txt::RequirementsTxtRequirement;
47use uv_scripts::{Pep723Error, Pep723Item, Pep723Script};
48use uv_settings::{Combine, EnvironmentOptions, FilesystemOptions, Options};
49use uv_static::EnvVars;
50use uv_warnings::{warn_user, warn_user_once};
51use uv_workspace::{DiscoveryOptions, Workspace, WorkspaceCache};
52
53use crate::commands::{
54 ExitStatus, ParsedRunCommand, ProjectError, RunCommand, ScriptPath, ToolRunCommand, UvError,
55};
56use crate::printer::Printer;
57use crate::settings::{
58 CacheSettings, GlobalSettings, PipCheckSettings, PipCompileSettings, PipFreezeSettings,
59 PipInstallSettings, PipListSettings, PipShowSettings, PipSyncSettings, PipUninstallSettings,
60 PublishSettings, resolve_color,
61};
62
63pub(crate) mod child;
64pub mod commands;
65#[cfg(not(feature = "self-update"))]
66mod install_source;
67mod logging;
68pub(crate) mod printer;
69pub(crate) mod settings;
70
71pub(crate) fn base_client_builder<'a>(globals: &GlobalSettings) -> BaseClientBuilder<'a> {
73 let client_builder = BaseClientBuilder::new(
74 globals.network_settings.connectivity,
75 globals.network_settings.system_certs,
76 globals.network_settings.allow_insecure_host.clone(),
77 globals.preview,
78 globals.network_settings.read_timeout,
79 globals.network_settings.connect_timeout,
80 globals.network_settings.retries,
81 )
82 .cache_read_concurrency(globals.concurrency.cache_reads)
83 .http_proxy(globals.network_settings.http_proxy.clone())
84 .https_proxy(globals.network_settings.https_proxy.clone())
85 .no_proxy(globals.network_settings.no_proxy.clone());
86
87 if let Some(certificates) = &globals.network_settings.custom_certificates {
88 client_builder.custom_certificates(certificates.clone())
89 } else {
90 client_builder
91 }
92}
93
94#[derive(Debug, Copy, Clone, Eq, PartialEq)]
96#[doc(hidden)]
97pub enum GlobalInitialization {
98 Initialize,
100 Reuse,
102}
103
104impl GlobalInitialization {
105 const fn needs_initialization(self) -> bool {
106 matches!(self, Self::Initialize)
107 }
108}
109
110#[cfg(not(feature = "self-update"))]
112#[derive(Debug, thiserror::Error)]
113#[error("uv was installed through an external package manager and cannot update itself.")]
114struct ExternallyInstalledError {
115 install_source: Option<InstallSource>,
116}
117
118#[cfg(not(feature = "self-update"))]
119impl uv_errors::Hint for ExternallyInstalledError {
120 fn hints(&self) -> uv_errors::Hints<'_> {
121 if let Some(source) = &self.install_source {
122 uv_errors::Hints::from(format!(
123 "You installed uv using {}. To update uv, run `{}`",
124 source.description(),
125 source.update_instructions(),
126 ))
127 } else {
128 uv_errors::Hints::from("Please use your package manager to update uv")
129 }
130 }
131}
132
133#[doc(hidden)]
134pub async fn run(cli: Cli, global_initialization: GlobalInitialization) -> Result<ExitStatus> {
135 Box::pin(run_with_workspace_cache(
136 cli,
137 global_initialization,
138 WorkspaceCache::default(),
139 ))
140 .await
141}
142
143#[instrument(name = "run", skip_all)]
144async fn run_with_workspace_cache(
145 cli: Cli,
146 global_initialization: GlobalInitialization,
147 workspace_cache: WorkspaceCache,
148) -> Result<ExitStatus> {
149 let config_discovery = ConfigDiscovery::from_args(cli.top_level.no_config);
150
151 anstream::ColorChoice::write_global(resolve_color(&cli.top_level.global_args).into());
153
154 if cli.top_level.global_args.quiet == 0 {
156 uv_warnings::enable();
157 }
158
159 let directory =
161 cli.top_level.global_args.directory.clone().or_else(|| {
162 std::env::var_os(EnvVars::UV_WORKING_DIRECTORY).map(std::path::PathBuf::from)
163 });
164
165 if let Some(directory) = directory.as_ref() {
167 std::env::set_current_dir(directory)?;
168 }
169
170 let parsed_run_command = if let Commands::Project(command) = &*cli.command
172 && let ProjectCommand::Run(uv_cli::RunArgs {
173 command: Some(ref command),
174 module,
175 script,
176 gui_script,
177 ..
178 }) = **command
179 {
180 Some(ParsedRunCommand::from_args(
181 command, module, script, gui_script,
182 )?)
183 } else {
184 None
185 };
186
187 let environment = EnvironmentOptions::new()?;
189
190 let early_preview = settings::resolve_preview(&cli.top_level.global_args, None, &environment)?;
192
193 if global_initialization.needs_initialization() {
194 uv_preview::set(early_preview)?;
196 }
197
198 if global_initialization.needs_initialization() {
199 #[cfg(feature = "tracing-durations-export")]
201 let (durations_layer, _duration_guard) =
202 logging::setup_durations(environment.tracing_durations_file.as_ref())?;
203 #[cfg(not(feature = "tracing-durations-export"))]
204 let durations_layer = None::<tracing_subscriber::layer::Identity>;
205 logging::setup_logging(
206 match cli.top_level.global_args.verbose {
207 0 => logging::Level::Off,
208 1 => logging::Level::DebugUv,
209 2 => logging::Level::TraceUv,
210 3.. => logging::Level::TraceAll,
211 },
212 durations_layer,
213 resolve_color(&cli.top_level.global_args),
214 environment.log_context.unwrap_or_default(),
215 )?;
216 }
217
218 let project_dir: Cow<'_, Path> = if let Some(project) = &cli.top_level.global_args.project {
223 let path = normalize_path(std::path::absolute(project)?);
224 if let Some(name) = path.file_name()
225 && name == "pyproject.toml"
226 && path.is_file()
227 && let Some(parent) = path.parent()
228 {
229 Cow::Owned(parent.to_path_buf())
230 } else {
231 path
232 }
233 } else if let Some(run_command) = &parsed_run_command
234 && let Some(dir) = run_command.script_dir()
235 {
236 Cow::Owned(std::path::absolute(dir)?)
239 } else {
240 Cow::Borrowed(&*CWD)
241 };
242
243 let skip_project_validation = matches!(
246 &*cli.command,
247 Commands::Project(command) if matches!(**command, ProjectCommand::Init(_))
248 );
249
250 if !skip_project_validation {
251 if let Some(project_path) = cli.top_level.global_args.project.as_ref() {
252 if !project_dir.exists() {
253 bail!(
254 "Project directory `{}` does not exist",
255 project_path.user_display()
256 );
257 } else if !project_dir.is_dir() {
258 bail!(
261 "Project path `{}` is not a directory",
262 project_path.user_display()
263 );
264 }
265 }
266 }
267
268 let deprecated_isolated = if cli.top_level.global_args.isolated {
270 match &*cli.command {
271 Commands::Tool(ToolNamespace {
273 command: ToolCommand::Uvx(_) | ToolCommand::Run(_),
274 }) => false,
275
276 Commands::Project(command)
278 if matches!(**command, ProjectCommand::Run(_) | ProjectCommand::Check(_)) =>
279 {
280 false
281 }
282
283 Commands::Project(command) if matches!(**command, ProjectCommand::Init(_)) => {
285 warn_user!(
286 "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."
287 );
288 false
289 }
290
291 Commands::Project(_) | Commands::Tool(_) | Commands::Python(_) => {
293 warn_user!(
294 "The `--isolated` flag is deprecated and has no effect. Instead, use `--no-config` to prevent uv from discovering configuration files."
295 );
296 false
297 }
298
299 _ => {
301 warn_user!(
302 "The `--isolated` flag is deprecated. Instead, use `--no-config` to prevent uv from discovering configuration files."
303 );
304 true
305 }
306 }
307 } else {
308 false
309 };
310
311 let discovery_cache = Cache::from_settings(
320 cli.top_level.cache_args.no_cache,
321 cli.top_level.cache_args.cache_dir.clone(),
322 )?;
323 let filesystem = if let Some(config_file) = cli.top_level.config_file.as_ref() {
324 if config_file
325 .file_name()
326 .is_some_and(|file_name| file_name == "pyproject.toml")
327 {
328 warn_user!(
329 "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."
330 );
331 }
332 Some(FilesystemOptions::from_file(config_file).map_err(map_settings_error)?)
333 } else if deprecated_isolated || !config_discovery.enabled() {
334 None
335 } else if matches!(&*cli.command, Commands::Tool(_) | Commands::Self_(_)) {
336 FilesystemOptions::user()
338 .map_err(map_settings_error)?
339 .combine(FilesystemOptions::system().map_err(map_settings_error)?)
340 } else if let Ok(workspace) = Workspace::discover(
341 &project_dir,
342 &DiscoveryOptions::default(),
343 &discovery_cache,
344 &workspace_cache,
345 )
346 .await
347 {
348 let project =
349 FilesystemOptions::find(workspace.install_path()).map_err(map_settings_error)?;
350 let system = FilesystemOptions::system().map_err(map_settings_error)?;
351 let user = FilesystemOptions::user().map_err(map_settings_error)?;
352 project.combine(user).combine(system)
353 } else {
354 let project = FilesystemOptions::find(&project_dir).map_err(map_settings_error)?;
355 let system = FilesystemOptions::system().map_err(map_settings_error)?;
356 let user = FilesystemOptions::user().map_err(map_settings_error)?;
357 project.combine(user).combine(system)
358 };
359
360 let (run_script, run_command) = if let Some(parsed_run_command) = parsed_run_command {
363 let (script, run_command) = parsed_run_command
364 .resolve(
365 &cli.top_level.global_args,
366 filesystem.as_ref(),
367 &environment,
368 )
369 .await?;
370 (script, Some(run_command))
371 } else {
372 (None, None)
373 };
374 let script = if let Some(run_script) = run_script {
375 Some(run_script)
376 } else if let Commands::Project(command) = &*cli.command {
377 match &**command {
378 ProjectCommand::Add(uv_cli::AddArgs {
381 script: Some(script),
382 ..
383 })
384 | ProjectCommand::Lock(uv_cli::LockArgs {
385 script: Some(script),
386 ..
387 }) => match Pep723Script::read(script).await {
388 Ok(Some(script)) => Some(Pep723Item::Script(script)),
389 Ok(None) => None,
390 Err(err) => return Err(err.into()),
391 },
392 ProjectCommand::Remove(uv_cli::RemoveArgs {
394 script: Some(script),
395 ..
396 })
397 | ProjectCommand::Sync(uv_cli::SyncArgs {
398 script: Some(script),
399 ..
400 })
401 | ProjectCommand::Tree(uv_cli::TreeArgs {
402 script: Some(script),
403 ..
404 })
405 | ProjectCommand::Export(uv_cli::ExportArgs {
406 script: Some(script),
407 ..
408 })
409 | ProjectCommand::Audit(uv_cli::AuditArgs {
410 script: Some(script),
411 ..
412 })
413 | ProjectCommand::Check(uv_cli::CheckArgs {
414 script: Some(script),
415 ..
416 }) => match Pep723Script::read(script).await {
417 Ok(Some(script)) => Some(Pep723Item::Script(script)),
418 Ok(None) => {
419 bail!(
420 "`{}` does not contain a PEP 723 metadata tag; run `{}` to initialize the script",
421 script.user_display().cyan(),
422 format!("uv init --script {}", script.user_display()).green()
423 )
424 }
425 Err(Pep723Error::Io(err)) if err.kind() == std::io::ErrorKind::NotFound => {
426 bail!(
427 "Failed to read `{}` (not found); run `{}` to create a PEP 723 script",
428 script.user_display().cyan(),
429 format!("uv init --script {}", script.user_display()).green()
430 )
431 }
432 Err(err) => return Err(err.into()),
433 },
434 _ => None,
435 }
436 } else if let Commands::Workspace(WorkspaceNamespace {
437 command: WorkspaceCommand::Metadata(args),
438 }) = &*cli.command
439 && let Some(script) = args.script.as_ref()
440 {
441 match Pep723Script::read(script).await {
442 Ok(Some(script)) => Some(Pep723Item::Script(script)),
443 Ok(None) => {
444 bail!(
445 "`{}` does not contain a PEP 723 metadata tag; run `{}` to initialize the script",
446 script.user_display().cyan(),
447 format!("uv init --script {}", script.user_display()).green()
448 )
449 }
450 Err(Pep723Error::Io(err)) if err.kind() == std::io::ErrorKind::NotFound => {
451 bail!(
452 "Failed to read `{}` (not found); run `{}` to create a PEP 723 script",
453 script.user_display().cyan(),
454 format!("uv init --script {}", script.user_display()).green()
455 )
456 }
457 Err(err) => return Err(err.into()),
458 }
459 } else if let Commands::Python(uv_cli::PythonNamespace {
460 command:
461 PythonCommand::Find(uv_cli::PythonFindArgs {
462 script: Some(script),
463 ..
464 }),
465 }) = &*cli.command
466 {
467 match Pep723Script::read(&script).await {
468 Ok(Some(script)) => Some(Pep723Item::Script(script)),
469 Ok(None) => {
470 bail!(
471 "`{}` does not contain a PEP 723 metadata tag; run `{}` to initialize the script",
472 script.user_display().cyan(),
473 format!("uv init --script {}", script.user_display()).green()
474 )
475 }
476 Err(Pep723Error::Io(err)) if err.kind() == std::io::ErrorKind::NotFound => {
477 bail!(
478 "Failed to read `{}` (not found); run `{}` to create a PEP 723 script",
479 script.user_display().cyan(),
480 format!("uv init --script {}", script.user_display()).green()
481 )
482 }
483 Err(err) => return Err(err.into()),
484 }
485 } else {
486 None
487 };
488
489 let script_filesystem = script
491 .as_ref()
492 .map(Pep723Item::metadata)
493 .and_then(|metadata| metadata.tool.as_ref())
494 .and_then(|tool| tool.uv.as_ref())
495 .map(|uv| Options::simple(uv.globals.clone(), uv.top_level.clone()))
496 .map(FilesystemOptions::from);
497 let script_filesystem = if let Some(Pep723Item::Script(script)) = script.as_ref() {
498 let script_dir = script.path.parent().expect("script path has no parent");
499 script_filesystem
500 .map(|options| options.relative_to(script_dir))
501 .transpose()?
502 } else {
503 script_filesystem
504 };
505 let filesystem = script_filesystem.combine(filesystem);
506
507 let custom_certificate_file = match &*cli.command {
508 Commands::Pip(PipNamespace { cert, .. }) => cert.as_deref(),
509 _ => None,
510 };
511
512 let globals = GlobalSettings::resolve(
514 &cli.top_level.global_args,
515 filesystem.as_ref(),
516 &environment,
517 custom_certificate_file,
518 )?;
519
520 if global_initialization.needs_initialization() {
521 uv_flags::init(EnvironmentFlags::from(&environment))
523 .map_err(|()| anyhow::anyhow!("Flags are already initialized"))?;
524 }
525
526 debug!("uv {}", uv_cli::version::uv_self_version());
527 if let Some(config_file) = cli.top_level.config_file.as_ref() {
528 debug!("Using configuration file: {}", config_file.user_display());
529 }
530 if globals.preview.all_enabled() {
531 debug!("All preview features are enabled");
532 } else if globals.preview.any_enabled() {
533 debug!(
534 "The following preview features are enabled: {}",
535 globals.preview
536 );
537 }
538
539 #[cfg(unix)]
541 if global_initialization.needs_initialization() {
542 match uv_unix::adjust_open_file_limit() {
543 Ok(_) | Err(uv_unix::OpenFileLimitError::AlreadySufficient { .. }) => {}
544 Err(err) => debug!("{err}"),
545 }
546 }
547
548 let cache_settings = CacheSettings::resolve(*cli.top_level.cache_args, filesystem.as_ref());
550
551 if global_initialization.needs_initialization() {
552 uv_preview::set(globals.preview)?;
554 uv_preview::finalize()?;
555 }
556
557 if let Some(required_version) = globals.required_version.as_ref() {
559 let package_version = uv_pep440::Version::from_str(uv_version::version())?;
560 if !required_version.contains(&package_version) {
561 return Err(required_version_error(required_version, &package_version));
562 }
563 }
564
565 let printer = Printer::new(globals.quiet, globals.verbose, globals.no_progress);
567
568 if globals.quiet > 0 {
570 uv_warnings::disable();
571 } else {
572 uv_warnings::enable();
573 }
574
575 anstream::ColorChoice::write_global(globals.color.into());
576
577 if global_initialization.needs_initialization() {
578 miette::set_hook(Box::new(|_| {
579 Box::new(
580 miette::MietteHandlerOpts::new()
581 .break_words(false)
582 .word_separator(textwrap::WordSeparator::AsciiSpace)
583 .word_splitter(textwrap::WordSplitter::NoHyphenation)
584 .wrap_lines(std::env::var(EnvVars::UV_NO_WRAP).is_err())
585 .build(),
586 )
587 }))?;
588 }
589
590 uv_configuration::RAYON_PARALLELISM.store(globals.concurrency.installs, Ordering::Relaxed);
592
593 macro_rules! show_settings {
595 ($arg:expr) => {
596 if globals.show_settings {
597 writeln!(printer.stdout(), "{:#?}", $arg)?;
598 return Ok(ExitStatus::Success);
599 }
600 };
601 ($arg:expr, false) => {
602 if globals.show_settings {
603 writeln!(printer.stdout(), "{:#?}", $arg)?;
604 }
605 };
606 }
607 show_settings!(globals, false);
608 show_settings!(cache_settings, false);
609
610 if cache_settings.no_cache {
612 debug!("Disabling the uv cache due to `--no-cache`");
613 }
614 let cache = Cache::from_settings(cache_settings.no_cache, cache_settings.cache_dir)?;
615 let cache_dir = std::path::absolute(cache.root())?;
619 let project_is_in_build_dir =
622 std::env::var_os(EnvVars::UV_INTERNAL__BUILD_DIR).is_some_and(|build_dir| {
623 std::path::absolute(build_dir).is_ok_and(|build_dir| {
624 project_dir.starts_with(&build_dir)
625 || fs_err::canonicalize(&*project_dir).is_ok_and(|project_dir| {
626 fs_err::canonicalize(build_dir)
627 .is_ok_and(|build_dir| project_dir.starts_with(build_dir))
628 })
629 })
630 });
631 if !project_is_in_build_dir {
632 if project_dir.starts_with(&cache_dir) {
633 bail!(
634 "The project directory `{}` is inside the cache directory `{}`",
635 project_dir.user_display(),
636 cache_dir.user_display()
637 );
638 }
639 if let Ok(cache_dir) = fs_err::canonicalize(&cache_dir)
640 && let Ok(project_dir) = fs_err::canonicalize(&*project_dir)
641 && project_dir.starts_with(&cache_dir)
642 {
643 bail!(
644 "The project directory `{}` is inside the cache directory `{}`",
645 project_dir.user_display(),
646 cache_dir.user_display()
647 );
648 }
649 }
650
651 let workspace_cache = if cache.root() == discovery_cache.root() {
654 workspace_cache
655 } else {
656 WorkspaceCache::default()
657 };
658
659 let client_builder = base_client_builder(&globals);
661
662 match *cli.command {
663 Commands::Auth(AuthNamespace {
664 command: AuthCommand::Login(args),
665 }) => {
666 let args = settings::AuthLoginSettings::resolve(args);
668 show_settings!(args);
669
670 commands::auth_login(
671 args.service,
672 args.username,
673 args.password,
674 args.token,
675 client_builder,
676 printer,
677 globals.preview,
678 )
679 .await
680 }
681 Commands::Auth(AuthNamespace {
682 command: AuthCommand::Logout(args),
683 }) => {
684 let args = settings::AuthLogoutSettings::resolve(args);
686 show_settings!(args);
687
688 commands::auth_logout(
689 args.service,
690 args.username,
691 client_builder,
692 printer,
693 globals.preview,
694 )
695 .await
696 }
697 Commands::Auth(AuthNamespace {
698 command: AuthCommand::Token(args),
699 }) => {
700 let args = settings::AuthTokenSettings::resolve(args);
702 show_settings!(args);
703
704 commands::auth_token(
705 args.service,
706 args.username,
707 client_builder,
708 printer,
709 globals.preview,
710 )
711 .await
712 }
713 Commands::Auth(AuthNamespace {
714 command: AuthCommand::Dir(args),
715 }) => {
716 commands::auth_dir(args.service.as_ref(), printer)?;
717 Ok(ExitStatus::Success)
718 }
719 Commands::Auth(AuthNamespace {
720 command: AuthCommand::Helper(args),
721 }) => {
722 use uv_cli::AuthHelperProtocol;
723
724 match args.protocol {
726 AuthHelperProtocol::Bazel => {}
727 }
728
729 match args.command {
730 AuthHelperCommand::Get => {
731 commands::auth_helper(client_builder, globals.preview, printer).await
732 }
733 }
734 }
735 Commands::Help(args) => commands::help(
736 args.command.unwrap_or_default().as_slice(),
737 printer,
738 args.no_pager,
739 ),
740 Commands::Pip(PipNamespace {
741 command: PipCommand::Compile(args),
742 ..
743 }) => {
744 args.compat_args.validate()?;
745
746 let args = PipCompileSettings::resolve(args, filesystem, environment)?;
748 show_settings!(args);
749
750 globals
752 .network_settings
753 .check_refresh_conflict(&args.refresh)?;
754
755 let cache = cache.init().await?.with_refresh(
757 args.refresh
758 .combine(Refresh::from(args.settings.reinstall.clone()))
759 .combine(Refresh::from(args.settings.upgrade.clone())),
760 );
761
762 let requirements = args
763 .src_file
764 .into_iter()
765 .map(RequirementsSource::from_requirements_file)
766 .collect::<Result<Vec<_>, _>>()?;
767 let constraints = args
768 .constraints
769 .into_iter()
770 .map(RequirementsSource::from_constraints_txt)
771 .collect::<Result<Vec<_>, _>>()?;
772 let overrides = args
773 .overrides
774 .into_iter()
775 .map(RequirementsSource::from_overrides_txt)
776 .collect::<Result<Vec<_>, _>>()?;
777 let excludes = args
778 .excludes
779 .into_iter()
780 .map(RequirementsSource::from_requirements_txt)
781 .collect::<Result<Vec<_>, _>>()?;
782 let build_constraints = args
783 .build_constraints
784 .into_iter()
785 .map(RequirementsSource::from_constraints_txt)
786 .collect::<Result<Vec<_>, _>>()?;
787 let groups = GroupsSpecification {
788 root: project_dir.to_path_buf(),
789 groups: args.settings.groups,
790 };
791
792 Box::pin(commands::pip_compile(
793 &requirements,
794 &constraints,
795 &overrides,
796 &excludes,
797 &build_constraints,
798 args.constraints_from_workspace,
799 args.overrides_from_workspace,
800 args.excludes_from_workspace,
801 args.build_constraints_from_workspace,
802 args.environments,
803 args.required_environments,
804 args.settings.extras,
805 groups,
806 args.settings.output_file.as_deref(),
807 args.format,
808 args.settings.resolution,
809 args.settings.prerelease,
810 args.settings.fork_strategy,
811 args.settings.dependency_mode,
812 args.settings.upgrade,
813 args.settings.generate_hashes,
814 args.settings.no_emit_package,
815 args.settings.no_strip_extras,
816 args.settings.no_strip_markers,
817 !args.settings.no_annotate,
818 !args.settings.no_header,
819 args.settings.custom_compile_command,
820 args.settings.emit_index_url,
821 args.settings.emit_find_links,
822 args.settings.emit_build_options,
823 args.settings.emit_marker_expression,
824 args.settings.emit_index_annotation,
825 args.settings.index_locations,
826 args.settings.index_strategy,
827 args.settings.torch_backend,
828 args.settings.cuda_driver_version,
829 args.settings.amd_gpu_architecture,
830 args.settings.dependency_metadata,
831 args.settings.keyring_provider,
832 &client_builder.subcommand(vec!["pip".to_owned(), "compile".to_owned()]),
833 args.settings.config_setting,
834 args.settings.config_settings_package,
835 args.settings.build_isolation.clone(),
836 &args.settings.extra_build_dependencies,
837 &args.settings.extra_build_variables,
838 args.settings.build_options,
839 args.settings.install_mirrors,
840 args.settings.python_version,
841 args.settings.python_platform,
842 globals.python_downloads,
843 args.settings.universal,
844 args.settings.exclude_newer,
845 args.settings.sources,
846 args.settings.annotation_style,
847 args.settings.link_mode,
848 args.settings.python,
849 args.settings.system,
850 globals.python_preference,
851 globals.concurrency,
852 globals.quiet > 0,
853 cache,
854 workspace_cache,
855 printer,
856 globals.preview,
857 ))
858 .await
859 }
860 Commands::Pip(PipNamespace {
861 command: PipCommand::Sync(args),
862 ..
863 }) => {
864 args.compat_args.validate()?;
865
866 let args = PipSyncSettings::resolve(args, filesystem, environment)?;
868 show_settings!(args);
869
870 globals
872 .network_settings
873 .check_refresh_conflict(&args.refresh)?;
874
875 let cache = cache.init().await?.with_refresh(
877 args.refresh
878 .combine(Refresh::from(args.settings.reinstall.clone()))
879 .combine(Refresh::from(args.settings.upgrade.clone())),
880 );
881
882 let requirements = args
883 .src_file
884 .into_iter()
885 .map(RequirementsSource::from_requirements_file)
886 .collect::<Result<Vec<_>, _>>()?;
887 let constraints = args
888 .constraints
889 .into_iter()
890 .map(RequirementsSource::from_constraints_txt)
891 .collect::<Result<Vec<_>, _>>()?;
892 let build_constraints = args
893 .build_constraints
894 .into_iter()
895 .map(RequirementsSource::from_constraints_txt)
896 .collect::<Result<Vec<_>, _>>()?;
897 let groups = GroupsSpecification {
898 root: project_dir.to_path_buf(),
899 groups: args.settings.groups,
900 };
901
902 Box::pin(commands::pip_sync(
903 &requirements,
904 &constraints,
905 &build_constraints,
906 &args.settings.extras,
907 &groups,
908 args.settings.reinstall,
909 args.settings.link_mode,
910 args.settings.compile_bytecode,
911 args.settings.hash_checking,
912 args.settings.index_locations,
913 args.settings.index_strategy,
914 args.settings.torch_backend,
915 args.settings.cuda_driver_version,
916 args.settings.amd_gpu_architecture,
917 args.settings.dependency_metadata,
918 args.settings.keyring_provider,
919 &client_builder.subcommand(vec!["pip".to_owned(), "sync".to_owned()]),
920 args.settings.allow_empty_requirements,
921 globals.installer_metadata,
922 &args.settings.config_setting,
923 &args.settings.config_settings_package,
924 args.settings.build_isolation.clone(),
925 &args.settings.extra_build_dependencies,
926 &args.settings.extra_build_variables,
927 args.settings.build_options,
928 args.settings.python_version,
929 args.settings.python_platform,
930 globals.python_downloads,
931 args.settings.install_mirrors,
932 args.settings.strict,
933 args.settings.exclude_newer,
934 args.settings.python,
935 args.settings.system,
936 args.settings.break_system_packages,
937 args.settings.target,
938 args.settings.prefix,
939 args.settings.sources,
940 globals.python_preference,
941 globals.concurrency,
942 cache,
943 workspace_cache,
944 args.dry_run,
945 printer,
946 globals.preview,
947 ))
948 .await
949 }
950 Commands::Pip(PipNamespace {
951 command: PipCommand::Install(args),
952 ..
953 }) => {
954 args.compat_args.validate()?;
955
956 let mut args = PipInstallSettings::resolve(args, filesystem, environment)?;
958 show_settings!(args);
959
960 let mut requirements = Vec::with_capacity(
961 args.package.len() + args.editables.len() + args.requirements.len(),
962 );
963 for package in args.package {
964 requirements.push(RequirementsSource::from_package_argument(&package)?);
965 }
966 for package in args.editables {
967 requirements.push(RequirementsSource::from_editable(&package)?);
968 }
969 requirements.extend(
970 args.requirements
971 .into_iter()
972 .map(RequirementsSource::from_requirements_file)
973 .collect::<Result<Vec<_>, _>>()?,
974 );
975 let constraints = args
976 .constraints
977 .into_iter()
978 .map(RequirementsSource::from_constraints_txt)
979 .collect::<Result<Vec<_>, _>>()?;
980 let overrides = args
981 .overrides
982 .into_iter()
983 .map(RequirementsSource::from_overrides_txt)
984 .collect::<Result<Vec<_>, _>>()?;
985 let excludes = args
986 .excludes
987 .into_iter()
988 .map(RequirementsSource::from_requirements_txt)
989 .collect::<Result<Vec<_>, _>>()?;
990 let build_constraints = args
991 .build_constraints
992 .into_iter()
993 .map(RequirementsSource::from_overrides_txt)
994 .collect::<Result<Vec<_>, _>>()?;
995 let groups = GroupsSpecification {
996 root: project_dir.to_path_buf(),
997 groups: args.settings.groups,
998 };
999
1000 for requirement in &requirements {
1004 let requirement = match requirement {
1005 RequirementsSource::Package(requirement) => requirement,
1006 RequirementsSource::Editable(requirement) => requirement,
1007 _ => continue,
1008 };
1009 match requirement {
1010 RequirementsTxtRequirement::Named(requirement) => {
1011 if let Some(VersionOrUrl::Url(url)) = requirement.version_or_url.as_ref() {
1012 if let ParsedUrl::Directory(ParsedDirectoryUrl {
1013 install_path, ..
1014 }) = &url.parsed_url
1015 {
1016 debug!(
1017 "Marking explicit source tree for reinstall: `{}`",
1018 install_path.display()
1019 );
1020 args.settings.reinstall = args
1021 .settings
1022 .reinstall
1023 .with_package(requirement.name.clone());
1024 }
1025 }
1026 }
1027 RequirementsTxtRequirement::Unnamed(requirement) => {
1028 if let ParsedUrl::Directory(ParsedDirectoryUrl { install_path, .. }) =
1029 &requirement.url.parsed_url
1030 {
1031 debug!(
1032 "Marking explicit source tree for reinstall: `{}`",
1033 install_path.display()
1034 );
1035 args.settings.reinstall =
1036 args.settings.reinstall.with_path(install_path.clone());
1037 }
1038 }
1039 }
1040 }
1041
1042 globals
1044 .network_settings
1045 .check_refresh_conflict(&args.refresh)?;
1046
1047 let cache = cache.init().await?.with_refresh(
1049 args.refresh
1050 .combine(Refresh::from(args.settings.reinstall.clone()))
1051 .combine(Refresh::from(args.settings.upgrade.clone())),
1052 );
1053
1054 Box::pin(commands::pip_install(
1055 &requirements,
1056 &constraints,
1057 &overrides,
1058 &excludes,
1059 &build_constraints,
1060 args.constraints_from_workspace,
1061 args.overrides_from_workspace,
1062 args.excludes_from_workspace,
1063 args.build_constraints_from_workspace,
1064 args.editable,
1065 &args.settings.extras,
1066 &groups,
1067 args.settings.resolution,
1068 args.settings.prerelease,
1069 args.settings.dependency_mode,
1070 args.settings.upgrade,
1071 args.settings.index_locations,
1072 args.settings.index_strategy,
1073 args.settings.torch_backend,
1074 args.settings.cuda_driver_version,
1075 args.settings.amd_gpu_architecture,
1076 args.settings.dependency_metadata,
1077 args.settings.keyring_provider,
1078 &client_builder.subcommand(vec!["pip".to_owned(), "install".to_owned()]),
1079 args.settings.reinstall,
1080 args.settings.link_mode,
1081 args.settings.compile_bytecode,
1082 args.settings.hash_checking,
1083 globals.installer_metadata,
1084 &args.settings.config_setting,
1085 &args.settings.config_settings_package,
1086 args.settings.build_isolation.clone(),
1087 &args.settings.extra_build_dependencies,
1088 &args.settings.extra_build_variables,
1089 args.settings.build_options,
1090 args.modifications,
1091 args.settings.python_version,
1092 args.settings.python_platform,
1093 globals.python_downloads,
1094 args.settings.install_mirrors,
1095 args.settings.strict,
1096 args.settings.exclude_newer,
1097 args.settings.sources,
1098 args.settings.python,
1099 args.settings.system,
1100 args.settings.break_system_packages,
1101 args.settings.target,
1102 args.settings.prefix,
1103 globals.python_preference,
1104 globals.concurrency,
1105 cache,
1106 workspace_cache,
1107 args.dry_run,
1108 printer,
1109 globals.preview,
1110 ))
1111 .await
1112 }
1113 Commands::Pip(PipNamespace {
1114 command: PipCommand::Uninstall(args),
1115 ..
1116 }) => {
1117 args.compat_args.validate()?;
1118
1119 let args = PipUninstallSettings::resolve(args, filesystem, environment)?;
1121 show_settings!(args);
1122
1123 let cache = cache.init().await?;
1125
1126 let mut sources = Vec::with_capacity(args.package.len() + args.requirements.len());
1127 for package in args.package {
1128 sources.push(RequirementsSource::from_package_argument(&package)?);
1129 }
1130 sources.extend(
1131 args.requirements
1132 .into_iter()
1133 .map(RequirementsSource::from_requirements_file)
1134 .collect::<Result<Vec<_>, _>>()?,
1135 );
1136 commands::pip_uninstall(
1137 &sources,
1138 args.settings.python,
1139 args.settings.system,
1140 args.settings.break_system_packages,
1141 args.settings.target,
1142 args.settings.prefix,
1143 cache,
1144 args.settings.keyring_provider,
1145 &client_builder.subcommand(vec!["pip".to_owned(), "uninstall".to_owned()]),
1146 args.dry_run,
1147 printer,
1148 )
1149 .await
1150 }
1151 Commands::Pip(PipNamespace {
1152 command: PipCommand::Freeze(args),
1153 ..
1154 }) => {
1155 let args = PipFreezeSettings::resolve(args, filesystem, environment)?;
1157 show_settings!(args);
1158
1159 let cache = cache.init().await?;
1161
1162 commands::pip_freeze(
1163 args.exclude_editable,
1164 &args.exclude,
1165 args.settings.strict,
1166 &args.settings.dependency_metadata,
1167 args.settings.python.as_deref(),
1168 args.settings.system,
1169 args.settings.target,
1170 args.settings.prefix,
1171 args.paths,
1172 &cache,
1173 printer,
1174 )
1175 }
1176 Commands::Pip(PipNamespace {
1177 command: PipCommand::List(args),
1178 ..
1179 }) => {
1180 args.compat_args.validate()?;
1181
1182 let args = PipListSettings::resolve(args, filesystem, environment)?;
1184 show_settings!(args);
1185
1186 let cache = cache.init().await?;
1188
1189 commands::pip_list(
1190 args.editable,
1191 &args.exclude,
1192 &args.format,
1193 args.outdated,
1194 args.settings.prerelease,
1195 args.settings.index_locations,
1196 args.settings.index_strategy,
1197 args.settings.keyring_provider,
1198 &client_builder.subcommand(vec!["pip".to_owned(), "list".to_owned()]),
1199 globals.concurrency,
1200 args.settings.strict,
1201 args.settings.exclude_newer,
1202 &args.settings.dependency_metadata,
1203 args.settings.python.as_deref(),
1204 args.settings.system,
1205 args.settings.target,
1206 args.settings.prefix,
1207 &cache,
1208 printer,
1209 )
1210 .await
1211 }
1212 Commands::Pip(PipNamespace {
1213 command: PipCommand::Show(args),
1214 ..
1215 }) => {
1216 let args = PipShowSettings::resolve(args, filesystem, environment)?;
1218 show_settings!(args);
1219
1220 let cache = cache.init().await?;
1222
1223 commands::pip_show(
1224 args.package,
1225 args.settings.strict,
1226 &args.settings.dependency_metadata,
1227 args.settings.python.as_deref(),
1228 args.settings.system,
1229 args.settings.target,
1230 args.settings.prefix,
1231 args.files,
1232 &cache,
1233 printer,
1234 )
1235 }
1236 Commands::Pip(PipNamespace {
1237 command: PipCommand::Tree(args),
1238 ..
1239 }) => {
1240 let args = PipTreeSettings::resolve(args, filesystem, environment)?;
1242
1243 let cache = cache.init().await?;
1245
1246 commands::pip_tree(
1247 args.show_version_specifiers,
1248 args.depth,
1249 &args.prune,
1250 &args.package,
1251 args.no_dedupe,
1252 args.invert,
1253 args.outdated,
1254 args.settings.prerelease,
1255 args.settings.index_locations,
1256 args.settings.index_strategy,
1257 args.settings.keyring_provider,
1258 client_builder.subcommand(vec!["pip".to_owned(), "tree".to_owned()]),
1259 globals.concurrency,
1260 args.settings.strict,
1261 args.settings.exclude_newer,
1262 &args.settings.dependency_metadata,
1263 args.settings.python.as_deref(),
1264 args.settings.system,
1265 &cache,
1266 printer,
1267 )
1268 .await
1269 }
1270 Commands::Pip(PipNamespace {
1271 command: PipCommand::Check(args),
1272 ..
1273 }) => {
1274 let args = PipCheckSettings::resolve(args, filesystem, environment)?;
1276 show_settings!(args);
1277
1278 let cache = cache.init().await?;
1280
1281 commands::pip_check(
1282 args.settings.python.as_deref(),
1283 args.settings.system,
1284 args.settings.python_version.as_ref(),
1285 args.settings.python_platform.as_ref(),
1286 &args.settings.dependency_metadata,
1287 &cache,
1288 printer,
1289 )
1290 }
1291 Commands::Pip(PipNamespace {
1292 command: PipCommand::Debug(_),
1293 ..
1294 }) => Err(anyhow!(
1295 "pip's `debug` is unsupported (consider using `uvx pip debug` instead)"
1296 )),
1297 Commands::Cache(CacheNamespace {
1298 command: CacheCommand::Clean(args),
1299 })
1300 | Commands::Clean(args) => {
1301 show_settings!(args);
1302 commands::cache_clean(&args.package, args.force, cache, printer, globals.preview).await
1303 }
1304 Commands::Cache(CacheNamespace {
1305 command: CacheCommand::Prune(args),
1306 }) => {
1307 show_settings!(args);
1308 commands::cache_prune(args.ci, args.force, cache, printer, globals.preview).await
1309 }
1310 Commands::Cache(CacheNamespace {
1311 command: CacheCommand::Dir,
1312 }) => commands::cache_dir(&cache, printer),
1313 Commands::Cache(CacheNamespace {
1314 command: CacheCommand::Size(args),
1315 }) => {
1316 let output_format = if args.human {
1317 CacheSizeOutputFormat::Human
1318 } else {
1319 args.output_format
1320 };
1321 commands::cache_size(&cache, output_format, printer, globals.preview)
1322 }
1323 Commands::Build(args) => {
1324 let args = settings::BuildSettings::resolve(args, filesystem, environment)?;
1326 show_settings!(args);
1327
1328 globals
1330 .network_settings
1331 .check_refresh_conflict(&args.refresh)?;
1332
1333 let cache = cache.init().await?.with_refresh(
1335 args.refresh
1336 .combine(Refresh::from(args.settings.upgrade.clone())),
1337 );
1338
1339 let build_constraints = args
1341 .build_constraints
1342 .into_iter()
1343 .map(RequirementsSource::from_constraints_txt)
1344 .collect::<Result<Vec<_>, _>>()?;
1345
1346 commands::build_frontend(
1347 &project_dir,
1348 args.src,
1349 args.package,
1350 args.all_packages,
1351 args.out_dir,
1352 args.sdist,
1353 args.wheel,
1354 args.list,
1355 args.build_logs,
1356 args.gitignore,
1357 args.force_pep517,
1358 args.clear,
1359 build_constraints,
1360 args.build_constraints_from_workspace,
1361 args.hash_checking,
1362 args.python,
1363 args.install_mirrors,
1364 &args.settings,
1365 &client_builder.subcommand(vec!["build".to_owned()]),
1366 config_discovery,
1367 globals.python_preference,
1368 globals.python_downloads,
1369 globals.concurrency,
1370 &cache,
1371 &workspace_cache,
1372 printer,
1373 globals.preview,
1374 )
1375 .await
1376 }
1377 Commands::Venv(args) => {
1378 args.compat_args.validate()?;
1379
1380 if args.no_system {
1381 warn_user_once!(
1382 "The `--no-system` flag has no effect, `uv venv` always ignores virtual environments when finding a Python interpreter; did you mean `--managed-python`?"
1383 );
1384 }
1385
1386 if args.system {
1387 warn_user_once!(
1388 "The `--system` flag has no effect, `uv venv` always ignores virtual environments when finding a Python interpreter; did you mean `--no-managed-python`?"
1389 );
1390 }
1391
1392 let args = settings::VenvSettings::resolve(args, filesystem, environment)?;
1394 show_settings!(args);
1395
1396 globals
1398 .network_settings
1399 .check_refresh_conflict(&args.refresh)?;
1400
1401 let cache = cache.init().await?.with_refresh(
1403 args.refresh
1404 .combine(Refresh::from(args.settings.reinstall.clone()))
1405 .combine(Refresh::from(args.settings.upgrade.clone())),
1406 );
1407
1408 let prompt = args.prompt.or_else(|| {
1410 if args.path.is_none() {
1411 Some(".".to_string())
1412 } else {
1413 None
1414 }
1415 });
1416
1417 let python_request: Option<PythonRequest> =
1418 args.settings.python.as_deref().map(PythonRequest::parse);
1419
1420 let on_existing = uv_virtualenv::OnExisting::from_args(
1421 args.allow_existing,
1422 args.clear,
1423 args.no_clear,
1424 if args.force {
1425 uv_virtualenv::ClearNonVirtualenv::Allow
1426 } else {
1427 uv_virtualenv::ClearNonVirtualenv::Error
1428 },
1429 );
1430
1431 Box::pin(commands::venv(
1432 &project_dir,
1433 args.path,
1434 python_request,
1435 args.settings.install_mirrors,
1436 globals.python_preference,
1437 globals.python_downloads,
1438 args.settings.link_mode,
1439 &args.settings.index_locations,
1440 args.settings.index_strategy,
1441 args.settings.dependency_metadata,
1442 args.settings.keyring_provider,
1443 &client_builder.subcommand(vec!["venv".to_owned()]),
1444 uv_virtualenv::Prompt::from_args(prompt),
1445 args.system_site_packages,
1446 uv_virtualenv::Seed::from_args(args.seed),
1447 on_existing,
1448 args.settings.exclude_newer,
1449 globals.concurrency,
1450 args.no_project,
1451 config_discovery,
1452 &cache,
1453 &workspace_cache,
1454 printer,
1455 args.relocatable
1456 || (globals
1457 .preview
1458 .is_enabled(PreviewFeature::RelocatableEnvsDefault)
1459 && !args.no_relocatable),
1460 globals.preview,
1461 ))
1462 .await
1463 }
1464 Commands::Project(project) => {
1465 Box::pin(run_project(
1466 project,
1467 &project_dir,
1468 run_command,
1469 script,
1470 globals,
1471 config_discovery,
1472 cli.top_level.global_args.project.is_some(),
1473 client_builder,
1474 filesystem,
1475 cache,
1476 &workspace_cache,
1477 printer,
1478 ))
1479 .await
1480 }
1481 #[cfg(feature = "self-update")]
1482 Commands::Self_(SelfNamespace {
1483 command:
1484 SelfCommand::Update(SelfUpdateArgs {
1485 target_version,
1486 token,
1487 dry_run,
1488 }),
1489 }) => {
1490 commands::self_update(
1491 target_version,
1492 token,
1493 dry_run,
1494 printer,
1495 client_builder.subcommand(vec!["self".to_owned(), "update".to_owned()]),
1496 )
1497 .await
1498 }
1499 Commands::Self_(SelfNamespace {
1500 command:
1501 SelfCommand::Version {
1502 short,
1503 output_format,
1504 },
1505 }) => {
1506 commands::self_version(short, output_format, printer)?;
1507 Ok(ExitStatus::Success)
1508 }
1509 #[cfg(not(feature = "self-update"))]
1510 Commands::Self_(_) => {
1511 return Err(ExternallyInstalledError {
1512 install_source: InstallSource::detect(),
1513 }
1514 .into());
1515 }
1516 Commands::GenerateShellCompletion(args) => {
1517 args.shell.generate(&mut Cli::command(), &mut stdout());
1518 Ok(ExitStatus::Success)
1519 }
1520 Commands::Tool(ToolNamespace {
1521 command: run_variant @ (ToolCommand::Uvx(_) | ToolCommand::Run(_)),
1522 }) => {
1523 let (args, invocation_source) = match run_variant {
1524 ToolCommand::Uvx(args) => (args.tool_run, ToolRunCommand::Uvx),
1525 ToolCommand::Run(args) => (args, ToolRunCommand::ToolRun),
1526 _ => unreachable!(),
1528 };
1529
1530 if let Some(shell) = args.generate_shell_completion {
1531 let mut uvx = Cli::command()
1533 .find_subcommand("tool")
1534 .unwrap()
1535 .find_subcommand("uvx")
1536 .unwrap()
1537 .clone()
1538 .disable_help_flag(true)
1541 .disable_version_flag(true);
1542
1543 for arg in TopLevelArgs::command().get_arguments() {
1546 if arg.get_id() != "isolated" && arg.get_id() != "version" {
1547 uvx = uvx.arg(arg);
1548 }
1549 }
1550 shell.generate(&mut uvx, &mut stdout());
1551 return Ok(ExitStatus::Success);
1552 }
1553
1554 let args = settings::ToolRunSettings::resolve(
1556 args,
1557 filesystem,
1558 invocation_source,
1559 environment,
1560 )?;
1561 show_settings!(args);
1562
1563 globals
1565 .network_settings
1566 .check_refresh_conflict(&args.refresh)?;
1567
1568 let cache = cache.init().await?.with_refresh(
1570 args.refresh
1571 .combine(Refresh::from(args.settings.reinstall.clone()))
1572 .combine(Refresh::from(args.settings.resolver.upgrade.clone())),
1573 );
1574
1575 let requirements = {
1576 let mut requirements = Vec::with_capacity(
1577 args.with.len() + args.with_editable.len() + args.with_requirements.len(),
1578 );
1579 for package in args.with {
1580 requirements.push(RequirementsSource::from_with_package_argument(&package)?);
1581 }
1582 for package in args.with_editable {
1583 requirements.push(RequirementsSource::from_editable(&package)?);
1584 }
1585 requirements.extend(
1586 args.with_requirements
1587 .into_iter()
1588 .map(RequirementsSource::from_requirements_file)
1589 .collect::<Result<Vec<_>, _>>()?,
1590 );
1591 requirements
1592 };
1593 let constraints = args
1594 .constraints
1595 .into_iter()
1596 .map(RequirementsSource::from_constraints_txt)
1597 .collect::<Result<Vec<_>, _>>()?;
1598 let overrides = args
1599 .overrides
1600 .into_iter()
1601 .map(RequirementsSource::from_overrides_txt)
1602 .collect::<Result<Vec<_>, _>>()?;
1603
1604 let build_constraints = args
1605 .build_constraints
1606 .into_iter()
1607 .map(RequirementsSource::from_constraints_txt)
1608 .collect::<Result<Vec<_>, _>>()?;
1609
1610 let client_builder = match invocation_source {
1611 ToolRunCommand::Uvx => client_builder.subcommand(vec!["uvx".to_owned()]),
1612 ToolRunCommand::ToolRun => {
1613 client_builder.subcommand(vec!["tool".to_owned(), "run".to_owned()])
1614 }
1615 };
1616
1617 Box::pin(commands::tool_run(
1618 args.command,
1619 args.from,
1620 &requirements,
1621 &constraints,
1622 &overrides,
1623 &build_constraints,
1624 args.show_resolution || globals.verbose > 0,
1625 args.lfs,
1626 args.python,
1627 args.python_platform,
1628 args.install_mirrors,
1629 args.options,
1630 args.settings,
1631 client_builder,
1632 invocation_source,
1633 args.isolated,
1634 globals.python_preference,
1635 globals.python_downloads,
1636 globals.installer_metadata,
1637 globals.concurrency,
1638 cache,
1639 workspace_cache,
1640 printer,
1641 args.env_file,
1642 args.no_env_file,
1643 globals.preview,
1644 ))
1645 .await
1646 }
1647 Commands::Tool(ToolNamespace {
1648 command: ToolCommand::Install(args),
1649 }) => {
1650 let args = settings::ToolInstallSettings::resolve(args, filesystem, environment)?;
1652 show_settings!(args);
1653
1654 globals
1656 .network_settings
1657 .check_refresh_conflict(&args.refresh)?;
1658
1659 let refresh = args
1661 .refresh
1662 .combine(Refresh::from(args.settings.reinstall.clone()))
1663 .combine(Refresh::from(args.settings.resolver.upgrade.clone()));
1664 let cache = cache.init().await?.with_refresh(refresh.clone());
1665
1666 let mut entrypoints = Vec::with_capacity(args.with_executables_from.len());
1667 let mut requirements = Vec::with_capacity(
1668 args.with.len()
1669 + args.with_editable.len()
1670 + args.with_requirements.len()
1671 + args.with_executables_from.len(),
1672 );
1673 for pkg in args.with {
1674 requirements.push(RequirementsSource::from_with_package_argument(&pkg)?);
1675 }
1676 for pkg in args.with_editable {
1677 requirements.push(RequirementsSource::from_editable(&pkg)?);
1678 }
1679 for path in args.with_requirements {
1680 requirements.push(RequirementsSource::from_requirements_file(path)?);
1681 }
1682 for pkg in &args.with_executables_from {
1683 let source = RequirementsSource::from_with_package_argument(pkg)?;
1684 let RequirementsSource::Package(RequirementsTxtRequirement::Named(requirement)) =
1685 &source
1686 else {
1687 bail!(
1688 "Expected a named package for `--with-executables-from`, but got: {}",
1689 source.to_string().cyan()
1690 )
1691 };
1692 entrypoints.push(requirement.name.clone());
1693 requirements.push(source);
1694 }
1695
1696 let constraints = args
1697 .constraints
1698 .into_iter()
1699 .map(RequirementsSource::from_constraints_txt)
1700 .collect::<Result<Vec<_>, _>>()?;
1701 let overrides = args
1702 .overrides
1703 .into_iter()
1704 .map(RequirementsSource::from_overrides_txt)
1705 .collect::<Result<Vec<_>, _>>()?;
1706 let excludes = args
1707 .excludes
1708 .into_iter()
1709 .map(RequirementsSource::from_requirements_txt)
1710 .collect::<Result<Vec<_>, _>>()?;
1711 let build_constraints = args
1712 .build_constraints
1713 .into_iter()
1714 .map(RequirementsSource::from_constraints_txt)
1715 .collect::<Result<Vec<_>, _>>()?;
1716
1717 Box::pin(commands::tool_install(
1718 args.package,
1719 args.editable,
1720 args.from,
1721 &requirements,
1722 &constraints,
1723 &overrides,
1724 &excludes,
1725 &build_constraints,
1726 &entrypoints,
1727 args.lfs,
1728 args.python,
1729 args.python_platform,
1730 args.install_mirrors,
1731 args.force,
1732 args.options,
1733 args.settings,
1734 client_builder.subcommand(vec!["tool".to_owned(), "install".to_owned()]),
1735 globals.python_preference,
1736 globals.python_downloads,
1737 globals.installer_metadata,
1738 globals.concurrency,
1739 config_discovery,
1740 cache,
1741 refresh,
1742 &workspace_cache,
1743 printer,
1744 globals.preview,
1745 ))
1746 .await
1747 }
1748 Commands::Tool(ToolNamespace {
1749 command: ToolCommand::List(args),
1750 }) => {
1751 let args = settings::ToolListSettings::resolve(args, filesystem)?;
1753 show_settings!(args);
1754
1755 let cache = cache.init().await?;
1757
1758 commands::tool_list(
1759 args.show_paths,
1760 args.show_version_specifiers,
1761 args.show_with,
1762 args.show_extras,
1763 args.show_python,
1764 args.outdated,
1765 args.args,
1766 args.filesystem,
1767 client_builder.subcommand(vec!["tool".to_owned(), "list".to_owned()]),
1768 globals.concurrency,
1769 &cache,
1770 printer,
1771 )
1772 .await
1773 }
1774 Commands::Tool(ToolNamespace {
1775 command: ToolCommand::Audit(args),
1776 }) => {
1777 let args = settings::ToolAuditSettings::resolve(args, filesystem);
1778 show_settings!(args);
1779
1780 let cache = cache.init().await?;
1781
1782 commands::tool_audit(
1783 args.names,
1784 args.output_format,
1785 args.service_format,
1786 args.service_url,
1787 args.ignore,
1788 args.ignore_until_fixed,
1789 args.filesystem,
1790 client_builder.subcommand(vec!["tool".to_owned(), "audit".to_owned()]),
1791 globals.concurrency,
1792 &cache,
1793 printer,
1794 globals.preview,
1795 )
1796 .await
1797 }
1798 Commands::Tool(ToolNamespace {
1799 command: ToolCommand::Upgrade(args),
1800 }) => {
1801 let args = settings::ToolUpgradeSettings::resolve(args, filesystem, &environment)?;
1803 show_settings!(args);
1804
1805 let cache = cache
1807 .init()
1808 .await?
1809 .with_refresh(Refresh::All(Timestamp::now()));
1810
1811 Box::pin(commands::tool_upgrade(
1812 args.names,
1813 args.python,
1814 args.python_platform,
1815 args.install_mirrors,
1816 args.args,
1817 args.filesystem,
1818 client_builder.subcommand(vec!["tool".to_owned(), "upgrade".to_owned()]),
1819 globals.python_preference,
1820 globals.python_downloads,
1821 globals.installer_metadata,
1822 globals.concurrency,
1823 &cache,
1824 &workspace_cache,
1825 printer,
1826 globals.preview,
1827 ))
1828 .await
1829 }
1830 Commands::Tool(ToolNamespace {
1831 command: ToolCommand::Uninstall(args),
1832 }) => {
1833 let args = settings::ToolUninstallSettings::resolve(args, filesystem);
1835 show_settings!(args);
1836
1837 commands::tool_uninstall(args.name, printer).await
1838 }
1839 Commands::Tool(ToolNamespace {
1840 command: ToolCommand::UpdateShell,
1841 }) => {
1842 commands::tool_update_shell(printer).await?;
1843 Ok(ExitStatus::Success)
1844 }
1845 Commands::Tool(ToolNamespace {
1846 command: ToolCommand::Dir(args),
1847 }) => {
1848 let args = settings::ToolDirSettings::resolve(args, filesystem);
1850 show_settings!(args);
1851
1852 commands::tool_dir(args.bin, globals.preview, printer)?;
1853 Ok(ExitStatus::Success)
1854 }
1855 Commands::Python(PythonNamespace {
1856 command: PythonCommand::List(args),
1857 }) => {
1858 let args = settings::PythonListSettings::resolve(args, filesystem, environment);
1860 show_settings!(args);
1861
1862 let cache = cache.init().await?;
1864
1865 commands::python_list(
1866 args.request,
1867 args.kinds,
1868 args.all_versions,
1869 args.all_platforms,
1870 args.all_arches,
1871 args.show_urls,
1872 args.output_format,
1873 args.python_downloads_json_url,
1874 args.python_install_mirror,
1875 args.pypy_install_mirror,
1876 globals.python_preference,
1877 globals.python_downloads,
1878 &client_builder.subcommand(vec!["python".to_owned(), "list".to_owned()]),
1879 &cache,
1880 printer,
1881 )
1882 .await
1883 }
1884 Commands::Python(PythonNamespace {
1885 command: PythonCommand::Install(args),
1886 }) => {
1887 let args = settings::PythonInstallSettings::resolve(args, filesystem, environment)?;
1889 show_settings!(args);
1890
1891 let cache = cache.init().await?;
1893
1894 commands::python_install(
1895 &project_dir,
1896 args.install_dir,
1897 args.targets,
1898 args.reinstall,
1899 args.upgrade,
1900 args.bin,
1901 args.registry,
1902 args.force,
1903 args.python_install_mirror,
1904 args.pypy_install_mirror,
1905 args.python_downloads_json_url,
1906 client_builder.subcommand(vec!["python".to_owned(), "install".to_owned()]),
1907 args.default,
1908 globals.python_downloads,
1909 config_discovery,
1910 args.compile_bytecode,
1911 &globals.concurrency,
1912 &cache,
1913 globals.preview,
1914 printer,
1915 )
1916 .await
1917 }
1918 Commands::Python(PythonNamespace {
1919 command: PythonCommand::Upgrade(args),
1920 }) => {
1921 let args = settings::PythonUpgradeSettings::resolve(args, filesystem, environment)?;
1923 show_settings!(args);
1924 let upgrade = commands::PythonUpgrade::Enabled(commands::PythonUpgradeSource::Upgrade);
1925
1926 let cache = cache.init().await?;
1928
1929 commands::python_install(
1930 &project_dir,
1931 args.install_dir,
1932 args.targets,
1933 args.reinstall,
1934 upgrade,
1935 args.bin,
1936 args.registry,
1937 args.force,
1938 args.python_install_mirror,
1939 args.pypy_install_mirror,
1940 args.python_downloads_json_url,
1941 client_builder.subcommand(vec!["python".to_owned(), "upgrade".to_owned()]),
1942 args.default,
1943 globals.python_downloads,
1944 config_discovery,
1945 args.compile_bytecode,
1946 &globals.concurrency,
1947 &cache,
1948 globals.preview,
1949 printer,
1950 )
1951 .await
1952 }
1953 Commands::Python(PythonNamespace {
1954 command: PythonCommand::Uninstall(args),
1955 }) => {
1956 let args = settings::PythonUninstallSettings::resolve(args, filesystem);
1958 show_settings!(args);
1959
1960 commands::python_uninstall(args.install_dir, args.targets, args.all, printer).await
1961 }
1962 Commands::Python(PythonNamespace {
1963 command: PythonCommand::Find(args),
1964 }) => {
1965 let args = settings::PythonFindSettings::resolve(args, filesystem, environment)?;
1967
1968 let cache = cache.init().await?;
1970
1971 if let Some(Pep723Item::Script(script)) = script {
1972 commands::python_find_script(
1973 (&script).into(),
1974 args.show_version,
1975 args.resolve_links,
1976 &client_builder.subcommand(vec!["python".to_owned(), "find".to_owned()]),
1978 globals.python_preference,
1979 globals.python_downloads,
1980 config_discovery,
1981 &cache,
1982 printer,
1983 )
1984 .await
1985 } else {
1986 commands::python_find(
1987 &project_dir,
1988 args.request,
1989 args.show_version,
1990 args.resolve_links,
1991 args.no_project,
1992 args.system,
1993 config_discovery,
1994 globals.python_preference,
1995 args.python_downloads_json_url.as_deref(),
1996 &client_builder.subcommand(vec!["python".to_owned(), "find".to_owned()]),
1997 &cache,
1998 &workspace_cache,
1999 printer,
2000 )
2001 .await
2002 }
2003 }
2004 Commands::Python(PythonNamespace {
2005 command: PythonCommand::Pin(args),
2006 }) => {
2007 let args = settings::PythonPinSettings::resolve(args, filesystem, environment)?;
2009
2010 let cache = cache.init().await?;
2012
2013 Box::pin(commands::python_pin(
2014 &project_dir,
2015 args.request,
2016 args.resolved,
2017 globals.python_preference,
2018 globals.python_downloads,
2019 args.no_project,
2020 args.global,
2021 args.rm,
2022 args.install_mirrors,
2023 client_builder.subcommand(vec!["python".to_owned(), "pin".to_owned()]),
2024 &cache,
2025 &workspace_cache,
2026 printer,
2027 ))
2028 .await
2029 }
2030 Commands::Python(PythonNamespace {
2031 command: PythonCommand::Dir(args),
2032 }) => {
2033 let args = settings::PythonDirSettings::resolve(args, filesystem);
2035 show_settings!(args);
2036
2037 commands::python_dir(args.bin, printer)?;
2038 Ok(ExitStatus::Success)
2039 }
2040 Commands::Python(PythonNamespace {
2041 command: PythonCommand::UpdateShell,
2042 }) => {
2043 commands::python_update_shell(printer).await?;
2044 Ok(ExitStatus::Success)
2045 }
2046 Commands::Publish(args) => {
2047 if args.skip_existing {
2048 bail!(
2049 "`uv publish` does not support `--skip-existing` because there is not a \
2050 reliable way to identify when an upload fails due to an existing \
2051 distribution. Instead, use `--check-url` to provide the URL to the simple \
2052 API for your index. uv will check the index for existing distributions before \
2053 attempting uploads."
2054 );
2055 }
2056
2057 let args = PublishSettings::resolve(args, filesystem);
2059 show_settings!(args);
2060
2061 let PublishSettings {
2062 files,
2063 username,
2064 password,
2065 dry_run,
2066 no_attestations,
2067 direct,
2068 publish_url,
2069 trusted_publishing,
2070 keyring_provider,
2071 check_url,
2072 index,
2073 index_locations,
2074 } = args;
2075
2076 commands::publish(
2077 files,
2078 publish_url,
2079 trusted_publishing,
2080 keyring_provider,
2081 &environment,
2082 &client_builder.subcommand(vec!["publish".to_owned()]),
2083 username,
2084 password,
2085 check_url,
2086 index,
2087 index_locations,
2088 dry_run,
2089 no_attestations,
2090 direct,
2091 globals.preview,
2092 &cache,
2093 printer,
2094 )
2095 .await
2096 }
2097 Commands::Workspace(WorkspaceNamespace { command }) => match command {
2098 WorkspaceCommand::Metadata(args) => {
2099 let args = settings::MetadataSettings::resolve(args, filesystem, environment)?;
2101 show_settings!(args);
2102
2103 globals
2105 .network_settings
2106 .check_refresh_conflict(&args.refresh)?;
2107
2108 let cache = cache.init().await?.with_refresh(
2110 args.refresh
2111 .clone()
2112 .combine(Refresh::from(args.settings.upgrade.clone())),
2113 );
2114
2115 let script = script.and_then(|script| match script {
2116 Pep723Item::Script(script) => Some(script),
2117 Pep723Item::Remote(..) | Pep723Item::Stdin(..) => None,
2118 });
2119
2120 Box::pin(commands::metadata(
2121 &project_dir,
2122 args.lock_check,
2123 args.frozen,
2124 args.dry_run,
2125 args.refresh,
2126 args.sync,
2127 args.active,
2128 args.python,
2129 args.install_mirrors,
2130 args.malware_settings,
2131 args.settings,
2132 client_builder.subcommand(vec!["workspace".to_owned(), "metadata".to_owned()]),
2133 script,
2134 globals.python_preference,
2135 globals.python_downloads,
2136 globals.concurrency,
2137 config_discovery,
2138 &cache,
2139 &workspace_cache,
2140 printer,
2141 globals.preview,
2142 ))
2143 .await
2144 }
2145 WorkspaceCommand::Dir(args) => {
2146 commands::dir(
2147 args.package,
2148 &project_dir,
2149 &cache,
2150 &workspace_cache,
2151 printer,
2152 )
2153 .await
2154 }
2155 WorkspaceCommand::List(args) => {
2156 commands::list(
2157 &project_dir,
2158 args.paths,
2159 args.scripts,
2160 &cache,
2161 &workspace_cache,
2162 printer,
2163 globals.preview,
2164 )
2165 .await
2166 }
2167 },
2168 Commands::BuildBackend { command } => spawn_blocking(move || match command {
2169 BuildBackendCommand::BuildSdist { sdist_directory } => {
2170 commands::build_backend::build_sdist(&sdist_directory)
2171 }
2172 BuildBackendCommand::BuildWheel {
2173 wheel_directory,
2174 metadata_directory,
2175 } => commands::build_backend::build_wheel(
2176 &wheel_directory,
2177 metadata_directory.as_deref(),
2178 ),
2179 BuildBackendCommand::BuildEditable {
2180 wheel_directory,
2181 metadata_directory,
2182 } => commands::build_backend::build_editable(
2183 &wheel_directory,
2184 metadata_directory.as_deref(),
2185 ),
2186 BuildBackendCommand::GetRequiresForBuildSdist => {
2187 commands::build_backend::get_requires_for_build_sdist()
2188 }
2189 BuildBackendCommand::GetRequiresForBuildWheel => {
2190 commands::build_backend::get_requires_for_build_wheel()
2191 }
2192 BuildBackendCommand::PrepareMetadataForBuildWheel { wheel_directory } => {
2193 commands::build_backend::prepare_metadata_for_build_wheel(&wheel_directory)
2194 }
2195 BuildBackendCommand::GetRequiresForBuildEditable => {
2196 commands::build_backend::get_requires_for_build_editable()
2197 }
2198 BuildBackendCommand::PrepareMetadataForBuildEditable { wheel_directory } => {
2199 commands::build_backend::prepare_metadata_for_build_editable(&wheel_directory)
2200 }
2201 })
2202 .await
2203 .expect("tokio threadpool exited unexpectedly"),
2204 }
2205}
2206
2207fn map_settings_error(err: uv_settings::Error) -> anyhow::Error {
2208 match err {
2209 uv_settings::Error::RequiredVersion {
2210 required_version,
2211 package_version,
2212 } => required_version_error(&required_version, &package_version),
2213 err => err.into(),
2214 }
2215}
2216
2217fn required_version_error(
2218 required_version: &uv_configuration::RequiredVersion,
2219 package_version: &uv_pep440::Version,
2220) -> anyhow::Error {
2221 #[cfg(feature = "self-update")]
2222 let hint = {
2223 let ranges = release_specifiers_to_ranges(required_version.specifiers().clone());
2226
2227 if let Some(singleton) = ranges.as_singleton() {
2228 format!(
2229 ". Update `uv` by running `{}`.",
2230 format!("uv self update {singleton}").green()
2231 )
2232 } else if ranges
2233 .bounding_range()
2234 .iter()
2235 .any(|(lowest, _highest)| match lowest {
2236 Bound::Included(version) => **version > *package_version,
2237 Bound::Excluded(version) => **version > *package_version,
2238 Bound::Unbounded => false,
2239 })
2240 {
2241 format!(". Update `uv` by running `{}`.", "uv self update".cyan())
2242 } else {
2243 String::new()
2244 }
2245 };
2246 #[cfg(not(feature = "self-update"))]
2247 let hint = "";
2248
2249 anyhow!(
2250 "Required uv version `{required_version}` does not match the running version `{package_version}`{hint}",
2251 )
2252}
2253
2254async fn run_project(
2256 project_command: Box<ProjectCommand>,
2257 project_dir: &Path,
2258 command: Option<RunCommand>,
2259 script: Option<Pep723Item>,
2260 globals: GlobalSettings,
2261 config_discovery: ConfigDiscovery,
2262 explicit_project: bool,
2263 client_builder: BaseClientBuilder<'_>,
2264 filesystem: Option<FilesystemOptions>,
2265 cache: Cache,
2266 workspace_cache: &WorkspaceCache,
2267 printer: Printer,
2268) -> Result<ExitStatus> {
2269 macro_rules! show_settings {
2271 ($arg:expr) => {
2272 if globals.show_settings {
2273 writeln!(printer.stdout(), "{:#?}", $arg)?;
2274 return Ok(ExitStatus::Success);
2275 }
2276 };
2277 }
2278
2279 let environment = EnvironmentOptions::new()?;
2281
2282 match *project_command {
2283 ProjectCommand::Init(args) => {
2284 let args = settings::InitSettings::resolve(args, filesystem, environment)?;
2286 show_settings!(args);
2287
2288 if explicit_project {
2290 bail!(
2291 "The `--project` option cannot be used in `uv init`. {}",
2292 if args.path.is_some() {
2293 "Use `--directory` instead."
2294 } else {
2295 "Use `--directory` or a positional path instead."
2296 }
2297 )
2298 }
2299
2300 let cache = cache.init().await?;
2302
2303 Box::pin(commands::init(
2304 project_dir,
2305 args.path,
2306 args.name,
2307 args.kind,
2308 args.bare,
2309 args.description,
2310 args.no_description,
2311 args.vcs,
2312 args.build_backend,
2313 args.no_readme,
2314 args.author_from,
2315 args.pin_python,
2316 args.python,
2317 args.install_mirrors,
2318 args.no_workspace,
2319 &client_builder.subcommand(vec!["init".to_owned()]),
2320 globals.python_preference,
2321 globals.python_downloads,
2322 config_discovery,
2323 &cache,
2324 printer,
2325 ))
2326 .await
2327 }
2328 ProjectCommand::Run(args) => {
2329 let args = settings::RunSettings::resolve(args, filesystem, environment)?;
2331 show_settings!(args);
2332
2333 globals
2335 .network_settings
2336 .check_refresh_conflict(&args.refresh)?;
2337
2338 let cache = cache.init().await?.with_refresh(
2340 args.refresh
2341 .combine(Refresh::from(args.settings.reinstall.clone()))
2342 .combine(Refresh::from(args.settings.resolver.upgrade.clone())),
2343 );
2344
2345 let mut requirements = Vec::with_capacity(
2346 args.with.len() + args.with_editable.len() + args.with_requirements.len(),
2347 );
2348 for package in args.with {
2349 requirements.push(RequirementsSource::from_with_package_argument(&package)?);
2350 }
2351 for package in args.with_editable {
2352 requirements.push(RequirementsSource::from_editable(&package)?);
2353 }
2354 requirements.extend(
2355 args.with_requirements
2356 .into_iter()
2357 .map(RequirementsSource::from_requirements_file)
2358 .collect::<Result<Vec<_>, _>>()?,
2359 );
2360
2361 Box::pin(commands::run(
2362 project_dir,
2363 script,
2364 command,
2365 requirements,
2366 args.show_resolution || globals.verbose > 0,
2367 args.lock_check,
2368 args.frozen,
2369 args.active,
2370 args.no_sync,
2371 args.isolated,
2372 args.all_packages,
2373 args.package,
2374 args.no_project,
2375 config_discovery,
2376 args.extras,
2377 args.groups,
2378 args.editable,
2379 args.modifications,
2380 args.python,
2381 args.python_platform,
2382 args.install_mirrors,
2383 args.settings,
2384 client_builder.subcommand(vec!["run".to_owned()]),
2385 globals.python_preference,
2386 globals.python_downloads,
2387 globals.installer_metadata,
2388 globals.concurrency,
2389 cache,
2390 workspace_cache,
2391 printer,
2392 args.env_file,
2393 globals.preview,
2394 args.max_recursion_depth,
2395 args.malware_settings,
2396 #[cfg(unix)]
2397 args.run_rlimit_nofile,
2398 ))
2399 .await
2400 }
2401 ProjectCommand::Sync(args) => {
2402 let args = settings::SyncSettings::resolve(args, filesystem, environment)?;
2404 show_settings!(args);
2405
2406 globals
2408 .network_settings
2409 .check_refresh_conflict(&args.refresh)?;
2410
2411 let cache = cache.init().await?.with_refresh(
2413 args.refresh
2414 .combine(Refresh::from(args.settings.reinstall.clone()))
2415 .combine(Refresh::from(args.settings.resolver.upgrade.clone())),
2416 );
2417
2418 let script = script.map(|script| match script {
2420 Pep723Item::Script(script) => script,
2421 Pep723Item::Stdin(..) => unreachable!("`uv lock` does not support stdin"),
2422 Pep723Item::Remote(..) => unreachable!("`uv lock` does not support remote files"),
2423 });
2424
2425 Box::pin(commands::sync(
2426 project_dir,
2427 args.lock_check,
2428 args.frozen,
2429 args.dry_run,
2430 args.active,
2431 args.all_packages,
2432 args.package,
2433 args.extras,
2434 args.groups,
2435 args.editable,
2436 args.install_options,
2437 args.modifications,
2438 args.python,
2439 args.python_platform,
2440 args.install_mirrors,
2441 globals.python_preference,
2442 globals.python_downloads,
2443 args.settings,
2444 client_builder.subcommand(vec!["sync".to_owned()]),
2445 script,
2446 globals.installer_metadata,
2447 globals.concurrency,
2448 config_discovery,
2449 &cache,
2450 workspace_cache,
2451 printer,
2452 globals.preview,
2453 args.output_format,
2454 args.malware_settings,
2455 ))
2456 .await
2457 }
2458 ProjectCommand::Lock(args) => {
2459 let args = settings::LockSettings::resolve(args, filesystem, environment)?;
2461 show_settings!(args);
2462
2463 globals
2465 .network_settings
2466 .check_refresh_conflict(&args.refresh)?;
2467
2468 let cache = cache.init().await?.with_refresh(
2470 args.refresh
2471 .clone()
2472 .combine(Refresh::from(args.settings.upgrade.clone())),
2473 );
2474
2475 let script = script
2478 .map(|script| match script {
2479 Pep723Item::Script(script) => script,
2480 Pep723Item::Stdin(..) => unreachable!("`uv add` does not support stdin"),
2481 Pep723Item::Remote(..) => {
2482 unreachable!("`uv add` does not support remote files")
2483 }
2484 })
2485 .map(ScriptPath::Script)
2486 .or(args.script.map(ScriptPath::Path));
2487
2488 Box::pin(commands::lock(
2489 project_dir,
2490 args.lock_check,
2491 args.frozen,
2492 args.dry_run,
2493 args.refresh,
2494 args.python,
2495 args.install_mirrors,
2496 args.settings,
2497 client_builder.subcommand(vec!["lock".to_owned()]),
2498 script,
2499 globals.python_preference,
2500 globals.python_downloads,
2501 globals.concurrency,
2502 config_discovery,
2503 &cache,
2504 workspace_cache,
2505 printer,
2506 globals.preview,
2507 ))
2508 .await
2509 }
2510 ProjectCommand::Upgrade(args) => {
2511 let args = settings::UpgradeSettings::resolve(args, filesystem, environment);
2513 show_settings!(args);
2514
2515 let cache = cache
2517 .init()
2518 .await?
2519 .with_refresh(Refresh::from(args.settings.upgrade.clone()));
2520
2521 Box::pin(commands::upgrade(
2522 project_dir,
2523 args.packages,
2524 args.exclude,
2525 args.install_mirrors,
2526 args.settings,
2527 client_builder.subcommand(vec!["upgrade".to_owned()]),
2528 globals.python_preference,
2529 globals.python_downloads,
2530 globals.concurrency,
2531 config_discovery,
2532 &cache,
2533 workspace_cache,
2534 printer,
2535 globals.preview,
2536 ))
2537 .await
2538 }
2539 ProjectCommand::Add(args) => {
2540 let mut args = settings::AddSettings::resolve(args, filesystem, environment)?;
2542 show_settings!(args);
2543
2544 let script = script
2547 .map(|script| match script {
2548 Pep723Item::Script(script) => script,
2549 Pep723Item::Stdin(..) => unreachable!("`uv add` does not support stdin"),
2550 Pep723Item::Remote(..) => {
2551 unreachable!("`uv add` does not support remote files")
2552 }
2553 })
2554 .map(ScriptPath::Script)
2555 .or(args.script.map(ScriptPath::Path));
2556
2557 let requirements = args
2558 .packages
2559 .iter()
2560 .map(String::as_str)
2561 .map(RequirementsSource::from_package_argument)
2562 .chain(
2563 args.requirements
2564 .into_iter()
2565 .map(RequirementsSource::from_requirements_file),
2566 )
2567 .collect::<Result<Vec<_>>>()?;
2568
2569 for requirement in &requirements {
2572 let requirement = match requirement {
2573 RequirementsSource::Package(requirement) => requirement,
2574 RequirementsSource::Editable(requirement) => requirement,
2575 _ => continue,
2576 };
2577 match requirement {
2578 RequirementsTxtRequirement::Named(requirement) => {
2579 if let Some(VersionOrUrl::Url(url)) = requirement.version_or_url.as_ref() {
2580 if let ParsedUrl::Directory(ParsedDirectoryUrl {
2581 install_path, ..
2582 }) = &url.parsed_url
2583 {
2584 debug!(
2585 "Marking explicit source tree for reinstall: `{}`",
2586 install_path.display()
2587 );
2588 args.settings.reinstall = args
2589 .settings
2590 .reinstall
2591 .with_package(requirement.name.clone());
2592 }
2593 }
2594 }
2595 RequirementsTxtRequirement::Unnamed(requirement) => {
2596 if let ParsedUrl::Directory(ParsedDirectoryUrl { install_path, .. }) =
2597 &requirement.url.parsed_url
2598 {
2599 debug!(
2600 "Marking explicit source tree for reinstall: `{}`",
2601 install_path.display()
2602 );
2603 args.settings.reinstall =
2604 args.settings.reinstall.with_path(install_path.clone());
2605 }
2606 }
2607 }
2608 }
2609
2610 globals
2612 .network_settings
2613 .check_refresh_conflict(&args.refresh)?;
2614
2615 let cache = cache.init().await?.with_refresh(
2617 args.refresh
2618 .combine(Refresh::from(args.settings.reinstall.clone()))
2619 .combine(Refresh::from(args.settings.resolver.upgrade.clone())),
2620 );
2621
2622 let constraints = args
2623 .constraints
2624 .into_iter()
2625 .map(RequirementsSource::from_constraints_txt)
2626 .collect::<Result<Vec<_>, _>>()?;
2627
2628 Box::pin(commands::add(
2629 project_dir,
2630 args.lock_check,
2631 args.frozen,
2632 args.active,
2633 args.no_sync,
2634 args.no_install_project,
2635 args.only_install_project,
2636 args.no_install_workspace,
2637 args.only_install_workspace,
2638 args.no_install_local,
2639 args.only_install_local,
2640 args.no_install_package,
2641 args.only_install_package,
2642 requirements,
2643 constraints,
2644 args.marker,
2645 args.editable,
2646 args.dependency_type,
2647 args.raw,
2648 args.bounds,
2649 args.indexes,
2650 args.rev,
2651 args.tag,
2652 args.branch,
2653 args.lfs,
2654 args.extras,
2655 args.package,
2656 args.python,
2657 args.workspace,
2658 args.install_mirrors,
2659 args.settings,
2660 client_builder.subcommand(vec!["add".to_owned()]),
2661 script,
2662 globals.python_preference,
2663 globals.python_downloads,
2664 globals.installer_metadata,
2665 globals.concurrency,
2666 config_discovery,
2667 &cache,
2668 printer,
2669 globals.preview,
2670 &args.malware_settings,
2671 ))
2672 .await
2673 }
2674 ProjectCommand::Remove(args) => {
2675 let args = settings::RemoveSettings::resolve(args, filesystem, environment)?;
2677 show_settings!(args);
2678
2679 globals
2681 .network_settings
2682 .check_refresh_conflict(&args.refresh)?;
2683
2684 let cache = cache.init().await?.with_refresh(
2686 args.refresh
2687 .combine(Refresh::from(args.settings.reinstall.clone()))
2688 .combine(Refresh::from(args.settings.resolver.upgrade.clone())),
2689 );
2690
2691 let script = script.map(|script| match script {
2693 Pep723Item::Script(script) => script,
2694 Pep723Item::Stdin(..) => unreachable!("`uv remove` does not support stdin"),
2695 Pep723Item::Remote(..) => unreachable!("`uv remove` does not support remote files"),
2696 });
2697
2698 Box::pin(commands::remove(
2699 project_dir,
2700 args.lock_check,
2701 args.frozen,
2702 args.active,
2703 args.no_sync,
2704 args.packages,
2705 args.dependency_type,
2706 args.package,
2707 args.python,
2708 args.install_mirrors,
2709 args.settings,
2710 client_builder.subcommand(vec!["remove".to_owned()]),
2711 script,
2712 globals.python_preference,
2713 globals.python_downloads,
2714 globals.installer_metadata,
2715 globals.concurrency,
2716 config_discovery,
2717 &cache,
2718 printer,
2719 globals.preview,
2720 args.malware_settings,
2721 ))
2722 .await
2723 }
2724 ProjectCommand::Version(args) => {
2725 let args = settings::VersionSettings::resolve(args, filesystem, environment)?;
2727 show_settings!(args);
2728
2729 globals
2731 .network_settings
2732 .check_refresh_conflict(&args.refresh)?;
2733
2734 let cache = if args.value.is_none() && args.bump.is_empty() {
2736 cache
2737 } else {
2738 cache.init().await?
2739 }
2740 .with_refresh(
2741 args.refresh
2742 .combine(Refresh::from(args.settings.reinstall.clone()))
2743 .combine(Refresh::from(args.settings.resolver.upgrade.clone())),
2744 );
2745
2746 Box::pin(commands::project_version(
2747 args.value,
2748 args.bump,
2749 args.short,
2750 args.output_format,
2751 project_dir,
2752 args.package,
2753 explicit_project,
2754 args.dry_run,
2755 args.lock_check,
2756 args.frozen,
2757 args.active,
2758 args.no_sync,
2759 args.python,
2760 args.install_mirrors,
2761 args.settings,
2762 client_builder.subcommand(vec!["version".to_owned()]),
2763 globals.python_preference,
2764 globals.python_downloads,
2765 globals.installer_metadata,
2766 globals.concurrency,
2767 config_discovery,
2768 &cache,
2769 workspace_cache,
2770 printer,
2771 globals.preview,
2772 args.malware_settings,
2773 ))
2774 .await
2775 }
2776 ProjectCommand::Tree(args) => {
2777 let args = settings::TreeSettings::resolve(args, filesystem, environment)?;
2779 show_settings!(args);
2780
2781 let cache = cache.init().await?;
2783
2784 let script = script.map(|script| match script {
2786 Pep723Item::Script(script) => script,
2787 Pep723Item::Stdin(..) => unreachable!("`uv tree` does not support stdin"),
2788 Pep723Item::Remote(..) => unreachable!("`uv tree` does not support remote files"),
2789 });
2790
2791 Box::pin(commands::tree(
2792 project_dir,
2793 args.groups,
2794 args.lock_check,
2795 args.frozen,
2796 args.universal,
2797 args.format,
2798 args.depth,
2799 args.prune,
2800 args.package,
2801 args.no_dedupe,
2802 args.invert,
2803 args.outdated,
2804 args.show_sizes,
2805 args.python_version,
2806 args.python_platform,
2807 args.python,
2808 args.install_mirrors,
2809 args.resolver,
2810 &client_builder.subcommand(vec!["tree".to_owned()]),
2811 script,
2812 globals.python_preference,
2813 globals.python_downloads,
2814 globals.concurrency,
2815 config_discovery,
2816 &cache,
2817 workspace_cache,
2818 printer,
2819 globals.preview,
2820 ))
2821 .await
2822 }
2823 ProjectCommand::Export(args) => {
2824 let args = settings::ExportSettings::resolve(args, filesystem, environment)?;
2826 show_settings!(args);
2827
2828 let cache = cache.init().await?;
2830
2831 let script = script.map(|script| match script {
2833 Pep723Item::Script(script) => script,
2834 Pep723Item::Stdin(..) => unreachable!("`uv export` does not support stdin"),
2835 Pep723Item::Remote(..) => unreachable!("`uv export` does not support remote files"),
2836 });
2837
2838 commands::export(
2839 project_dir,
2840 args.format,
2841 args.all_packages,
2842 args.package,
2843 args.prune,
2844 args.hashes,
2845 args.install_options,
2846 args.output_file,
2847 args.extras,
2848 args.groups,
2849 args.editable,
2850 args.lock_check,
2851 args.frozen,
2852 args.include_annotations,
2853 args.include_header,
2854 args.include_index_url,
2855 args.include_find_links,
2856 script,
2857 args.python,
2858 args.install_mirrors,
2859 args.settings,
2860 client_builder.subcommand(vec!["export".to_owned()]),
2861 globals.python_preference,
2862 globals.python_downloads,
2863 globals.concurrency,
2864 config_discovery,
2865 globals.quiet > 0,
2866 &cache,
2867 workspace_cache,
2868 printer,
2869 globals.preview,
2870 )
2871 .boxed_local()
2872 .await
2873 }
2874 ProjectCommand::Format(args) => {
2875 let args = settings::FormatSettings::resolve(args, filesystem, environment);
2877 show_settings!(args);
2878
2879 let cache = cache.init().await?;
2881
2882 Box::pin(commands::format(
2883 project_dir,
2884 args.ruff_path,
2885 args.check,
2886 args.diff,
2887 args.extra_args,
2888 args.version,
2889 args.exclude_newer,
2890 args.show_version,
2891 client_builder.subcommand(vec!["format".to_owned()]),
2892 cache,
2893 workspace_cache,
2894 printer,
2895 globals.preview,
2896 args.no_project,
2897 ))
2898 .await
2899 }
2900 ProjectCommand::Check(args) => {
2901 let args = settings::CheckSettings::resolve(args, filesystem, environment)?;
2903 show_settings!(args);
2904
2905 globals
2907 .network_settings
2908 .check_refresh_conflict(&args.refresh)?;
2909
2910 let cache = cache.init().await?.with_refresh(
2912 args.refresh
2913 .combine(Refresh::from(args.settings.reinstall.clone()))
2914 .combine(Refresh::from(args.settings.resolver.upgrade.clone())),
2915 );
2916
2917 let script = script.and_then(|script| match script {
2918 Pep723Item::Script(script) => Some(script),
2919 Pep723Item::Remote(..) | Pep723Item::Stdin(..) => None,
2920 });
2921
2922 Box::pin(commands::check(
2923 project_dir,
2924 args.ty_path,
2925 args.fix,
2926 args.lock_check,
2927 args.frozen,
2928 args.no_sync,
2929 args.no_install_project,
2930 args.isolated,
2931 args.all_packages,
2932 args.package,
2933 args.extras,
2934 args.groups,
2935 args.python,
2936 args.install_mirrors,
2937 args.settings,
2938 args.ty_version,
2939 args.show_version,
2940 args.show_command,
2941 script,
2942 client_builder.subcommand(vec!["check".to_owned()]),
2943 globals.python_preference,
2944 globals.python_downloads,
2945 globals.installer_metadata,
2946 globals.concurrency,
2947 &cache,
2948 workspace_cache,
2949 globals.color,
2950 printer,
2951 globals.preview,
2952 args.no_project,
2953 config_discovery,
2954 args.malware_settings,
2955 ))
2956 .await
2957 }
2958 ProjectCommand::Audit(audit_args) => {
2959 let args = settings::AuditSettings::resolve(audit_args, filesystem, environment)?;
2960 show_settings!(args);
2961
2962 let cache = cache.init().await?;
2964
2965 let script = script.map(|script| match script {
2967 Pep723Item::Script(script) => script,
2968 Pep723Item::Stdin(..) => unreachable!("`uv audit` does not support stdin"),
2969 Pep723Item::Remote(..) => unreachable!("`uv audit` does not support remote files"),
2970 });
2971
2972 Box::pin(commands::audit(
2973 project_dir,
2974 args.extras,
2975 args.groups,
2976 args.lock_check,
2977 args.frozen,
2978 script,
2979 args.python_version,
2980 args.python_platform,
2981 args.install_mirrors,
2982 args.settings,
2983 client_builder.subcommand(vec!["audit".to_owned()]),
2984 globals.python_preference,
2985 globals.python_downloads,
2986 globals.concurrency,
2987 config_discovery,
2988 cache,
2989 workspace_cache,
2990 printer,
2991 globals.preview,
2992 args.output_format,
2993 args.service_format,
2994 args.service_url,
2995 args.ignore,
2996 args.ignore_until_fixed,
2997 ))
2998 .await
2999 }
3000 }
3001}
3002
3003fn suggest_subcommand(err: &mut Error) {
3005 if let Some(ContextValue::String(subcommand)) = err.get(ContextKind::InvalidSubcommand) {
3006 match subcommand.as_str() {
3007 "compile" => {
3008 err.insert(
3009 ContextKind::SuggestedSubcommand,
3010 ContextValue::String("uv pip compile".to_string()),
3011 );
3012 }
3013 "install" => {
3014 err.insert(
3015 ContextKind::SuggestedSubcommand,
3016 ContextValue::String("uv pip install".to_string()),
3017 );
3018 }
3019 "uninstall" => {
3020 err.insert(
3021 ContextKind::SuggestedSubcommand,
3022 ContextValue::String("uv pip uninstall".to_string()),
3023 );
3024 }
3025 "freeze" => {
3026 err.insert(
3027 ContextKind::SuggestedSubcommand,
3028 ContextValue::String("uv pip freeze".to_string()),
3029 );
3030 }
3031 "list" => {
3032 err.insert(
3033 ContextKind::SuggestedSubcommand,
3034 ContextValue::String("uv pip list".to_string()),
3035 );
3036 }
3037 "show" => {
3038 err.insert(
3039 ContextKind::SuggestedSubcommand,
3040 ContextValue::String("uv pip show".to_string()),
3041 );
3042 }
3043 _ => {}
3044 }
3045 }
3046}
3047
3048#[allow(unsafe_code)]
3063pub unsafe fn main<I, T>(args: I) -> ExitCode
3064where
3065 I: IntoIterator<Item = T>,
3066 T: Into<OsString> + Clone,
3067{
3068 #[cfg(windows)]
3069 uv_windows::install_unhandled_exception_handler();
3070
3071 if let Ok(current_exe) = std::env::current_exe() {
3074 unsafe {
3076 std::env::set_var(EnvVars::UV, current_exe);
3079 }
3080 }
3081
3082 let cli = match Cli::try_parse_from(args) {
3085 Ok(cli) => cli,
3086 Err(mut err) => {
3087 suggest_subcommand(&mut err);
3088 err.exit()
3089 }
3090 };
3091
3092 let printer = Printer::new(
3095 cli.top_level.global_args.quiet,
3096 cli.top_level.global_args.verbose,
3097 cli.top_level.global_args.no_progress,
3098 );
3099
3100 let workspace_cache = WorkspaceCache::default();
3105
3106 let min_stack_size = min_stack_size();
3108 let main2 = move || {
3109 let runtime = tokio::runtime::Builder::new_current_thread()
3110 .enable_all()
3111 .thread_stack_size(min_stack_size)
3112 .build()
3113 .expect("Failed building the Runtime");
3114 let result = runtime.block_on(Box::pin(run_with_workspace_cache(
3116 cli,
3117 GlobalInitialization::Initialize,
3118 workspace_cache,
3119 )));
3120 runtime.shutdown_background();
3126 result
3127 };
3128 let result = std::thread::Builder::new()
3129 .name("main2".to_owned())
3130 .stack_size(min_stack_size)
3131 .spawn(main2)
3132 .expect("Tokio executor failed, was there a panic?")
3133 .join()
3134 .expect("Tokio executor failed, was there a panic?");
3135
3136 match result {
3137 Ok(code) => code.into(),
3138 Err(err) => {
3139 let error = match err.downcast::<UvError>() {
3140 Ok(error) => error,
3141 Err(err) if err.is::<ArgumentError>() => UvError::argument(err),
3142 Err(err)
3143 if matches!(
3144 err.downcast_ref::<ProjectError>(),
3145 Some(ProjectError::LockFormat(..))
3146 ) =>
3147 {
3148 UvError::User(err)
3149 }
3150 Err(err) => UvError::unexpected(err),
3151 };
3152 match error {
3153 UvError::User(err) => {
3154 commands::diagnostics::write_error_chain(&err, printer)
3155 .expect("writing to stderr should not fail");
3156 ExitStatus::Failure.into()
3157 }
3158 UvError::Argument(err) => {
3159 commands::diagnostics::write_error_chain(&err, printer)
3160 .expect("writing to stderr should not fail");
3161 ExitStatus::Error.into()
3162 }
3163 UvError::Unexpected(err) => {
3164 trace!(
3165 "Error chain:\n{}",
3166 uv_errors::debug_error_chain(err.as_ref())
3167 );
3168 if err.backtrace().status() == std::backtrace::BacktraceStatus::Captured {
3169 trace!("Error backtrace:\n{}", err.backtrace());
3170 }
3171 commands::diagnostics::write_error_chain(&err, printer)
3172 .expect("writing to stderr should not fail");
3173 ExitStatus::Error.into()
3174 }
3175 }
3176 }
3177 }
3178}