Skip to main content

uv_settings/
settings.rs

1use std::{fmt::Debug, num::NonZeroUsize, path::Path, path::PathBuf};
2
3use serde::{Deserialize, Serialize};
4
5use uv_cache_info::CacheKey;
6use uv_configuration::{
7    BuildIsolation, IndexStrategy, KeyringProviderType, PackageNameSpecifier, ProxyUrl, Reinstall,
8    RequiredVersion, TargetTriple, TrustedHost, TrustedPublishing, Upgrade,
9};
10use uv_distribution_types::{
11    ConfigSettings, ExtraBuildVariables, Index, IndexUrl, IndexUrlError, Origin,
12    PackageConfigSettings, PipExtraIndex, PipFindLinks, PipIndex, StaticMetadata,
13};
14use uv_install_wheel::LinkMode;
15use uv_macros::{CombineOptions, OptionsMetadata};
16use uv_normalize::{ExtraName, PackageName, PipGroupName};
17use uv_pep508::Requirement;
18use uv_pypi_types::{SupportedEnvironments, VerbatimParsedUrl};
19use uv_python::{PythonDownloads, PythonPreference, PythonVersion};
20use uv_redacted::DisplaySafeUrl;
21use uv_resolver::{
22    AnnotationStyle, ExcludeNewer, ExcludeNewerPackage, ExcludeNewerValue, ForkStrategy,
23    PrereleaseMode, ResolutionMode,
24};
25use uv_torch::TorchMode;
26use uv_workspace::pyproject::ExtraBuildDependencies;
27use uv_workspace::pyproject_mut::AddBoundsKind;
28
29/// A `pyproject.toml` with an (optional) `[tool.uv]` section.
30#[allow(dead_code)]
31#[derive(Debug, Clone, Default, Deserialize)]
32pub(crate) struct PyProjectToml {
33    pub(crate) tool: Option<Tools>,
34}
35
36/// A `[tool]` section.
37#[allow(dead_code)]
38#[derive(Debug, Clone, Default, Deserialize)]
39pub(crate) struct Tools {
40    pub(crate) uv: Option<Options>,
41}
42
43/// A `[tool.uv]` section.
44#[allow(dead_code)]
45#[derive(Debug, Clone, Default, Deserialize, CombineOptions, OptionsMetadata)]
46#[serde(from = "OptionsWire", rename_all = "kebab-case")]
47#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
48#[cfg_attr(feature = "schemars", schemars(!from))]
49pub struct Options {
50    #[serde(flatten)]
51    pub globals: GlobalOptions,
52
53    #[serde(flatten)]
54    pub top_level: ResolverInstallerSchema,
55
56    #[serde(flatten)]
57    pub install_mirrors: PythonInstallMirrors,
58
59    #[serde(flatten)]
60    pub publish: PublishOptions,
61
62    #[serde(flatten)]
63    pub add: AddOptions,
64
65    #[option_group]
66    pub pip: Option<PipOptions>,
67
68    /// The keys to consider when caching builds for the project.
69    ///
70    /// Cache keys enable you to specify the files or directories that should trigger a rebuild when
71    /// modified. By default, uv will rebuild a project whenever the `pyproject.toml`, `setup.py`,
72    /// or `setup.cfg` files in the project directory are modified, or if a `src` directory is
73    /// added or removed, i.e.:
74    ///
75    /// ```toml
76    /// cache-keys = [{ file = "pyproject.toml" }, { file = "setup.py" }, { file = "setup.cfg" }, { dir = "src" }]
77    /// ```
78    ///
79    /// As an example: if a project uses dynamic metadata to read its dependencies from a
80    /// `requirements.txt` file, you can specify `cache-keys = [{ file = "requirements.txt" }, { file = "pyproject.toml" }]`
81    /// to ensure that the project is rebuilt whenever the `requirements.txt` file is modified (in
82    /// addition to watching the `pyproject.toml`).
83    ///
84    /// Globs are supported, following the syntax of the [`glob`](https://docs.rs/glob/0.3.1/glob/struct.Pattern.html)
85    /// crate. For example, to invalidate the cache whenever a `.toml` file in the project directory
86    /// or any of its subdirectories is modified, you can specify `cache-keys = [{ file = "**/*.toml" }]`.
87    /// Note that the use of globs can be expensive, as uv may need to walk the filesystem to
88    /// determine whether any files have changed.
89    ///
90    /// Cache keys can also include version control information. For example, if a project uses
91    /// `setuptools_scm` to read its version from a Git commit, you can specify `cache-keys = [{ git = { commit = true }, { file = "pyproject.toml" }]`
92    /// to include the current Git commit hash in the cache key (in addition to the
93    /// `pyproject.toml`). Git tags are also supported via `cache-keys = [{ git = { commit = true, tags = true } }]`.
94    ///
95    /// Cache keys can also include environment variables. For example, if a project relies on
96    /// `MACOSX_DEPLOYMENT_TARGET` or other environment variables to determine its behavior, you can
97    /// specify `cache-keys = [{ env = "MACOSX_DEPLOYMENT_TARGET" }]` to invalidate the cache
98    /// whenever the environment variable changes.
99    ///
100    /// Cache keys only affect the project defined by the `pyproject.toml` in which they're
101    /// specified (as opposed to, e.g., affecting all members in a workspace), and all paths and
102    /// globs are interpreted as relative to the project directory.
103    #[option(
104        default = r#"[{ file = "pyproject.toml" }, { file = "setup.py" }, { file = "setup.cfg" }]"#,
105        value_type = "list[dict]",
106        example = r#"
107            cache-keys = [{ file = "pyproject.toml" }, { file = "requirements.txt" }, { git = { commit = true } }]
108        "#
109    )]
110    pub cache_keys: Option<Vec<CacheKey>>,
111
112    // NOTE(charlie): These fields are shared with `ToolUv` in
113    // `crates/uv-workspace/src/pyproject.rs`. The documentation lives on that struct.
114    // They're respected in both `pyproject.toml` and `uv.toml` files.
115    #[cfg_attr(feature = "schemars", schemars(skip))]
116    pub override_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
117
118    #[cfg_attr(feature = "schemars", schemars(skip))]
119    pub exclude_dependencies: Option<Vec<uv_normalize::PackageName>>,
120
121    #[cfg_attr(feature = "schemars", schemars(skip))]
122    pub constraint_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
123
124    #[cfg_attr(feature = "schemars", schemars(skip))]
125    pub build_constraint_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
126
127    #[cfg_attr(feature = "schemars", schemars(skip))]
128    pub environments: Option<SupportedEnvironments>,
129
130    #[cfg_attr(feature = "schemars", schemars(skip))]
131    pub required_environments: Option<SupportedEnvironments>,
132
133    // NOTE(charlie): These fields should be kept in-sync with `ToolUv` in
134    // `crates/uv-workspace/src/pyproject.rs`. The documentation lives on that struct.
135    // They're only respected in `pyproject.toml` files, and should be rejected in `uv.toml` files.
136    #[cfg_attr(feature = "schemars", schemars(skip))]
137    pub conflicts: Option<serde::de::IgnoredAny>,
138
139    #[cfg_attr(feature = "schemars", schemars(skip))]
140    pub workspace: Option<serde::de::IgnoredAny>,
141
142    #[cfg_attr(feature = "schemars", schemars(skip))]
143    pub sources: Option<serde::de::IgnoredAny>,
144
145    #[cfg_attr(feature = "schemars", schemars(skip))]
146    pub dev_dependencies: Option<serde::de::IgnoredAny>,
147
148    #[cfg_attr(feature = "schemars", schemars(skip))]
149    pub default_groups: Option<serde::de::IgnoredAny>,
150
151    #[cfg_attr(feature = "schemars", schemars(skip))]
152    pub dependency_groups: Option<serde::de::IgnoredAny>,
153
154    #[cfg_attr(feature = "schemars", schemars(skip))]
155    pub managed: Option<serde::de::IgnoredAny>,
156
157    #[cfg_attr(feature = "schemars", schemars(skip))]
158    pub r#package: Option<serde::de::IgnoredAny>,
159
160    #[cfg_attr(feature = "schemars", schemars(skip))]
161    pub build_backend: Option<serde::de::IgnoredAny>,
162}
163
164impl Options {
165    /// Construct an [`Options`] with the given global and top-level settings.
166    pub fn simple(globals: GlobalOptions, top_level: ResolverInstallerSchema) -> Self {
167        Self {
168            globals,
169            top_level,
170            ..Default::default()
171        }
172    }
173
174    /// Set the [`Origin`] on all indexes without an existing origin.
175    #[must_use]
176    pub fn with_origin(mut self, origin: Origin) -> Self {
177        if let Some(indexes) = &mut self.top_level.index {
178            for index in indexes {
179                index.origin.get_or_insert(origin);
180            }
181        }
182        if let Some(index_url) = &mut self.top_level.index_url {
183            index_url.try_set_origin(origin);
184        }
185        if let Some(extra_index_urls) = &mut self.top_level.extra_index_url {
186            for index_url in extra_index_urls {
187                index_url.try_set_origin(origin);
188            }
189        }
190        if let Some(pip) = &mut self.pip {
191            if let Some(indexes) = &mut pip.index {
192                for index in indexes {
193                    index.origin.get_or_insert(origin);
194                }
195            }
196            if let Some(index_url) = &mut pip.index_url {
197                index_url.try_set_origin(origin);
198            }
199            if let Some(extra_index_urls) = &mut pip.extra_index_url {
200                for index_url in extra_index_urls {
201                    index_url.try_set_origin(origin);
202                }
203            }
204        }
205        self
206    }
207
208    /// Resolve the [`Options`] relative to the given root directory.
209    pub fn relative_to(self, root_dir: &Path) -> Result<Self, IndexUrlError> {
210        Ok(Self {
211            top_level: self.top_level.relative_to(root_dir)?,
212            pip: self.pip.map(|pip| pip.relative_to(root_dir)).transpose()?,
213            ..self
214        })
215    }
216}
217
218/// Global settings, relevant to all invocations.
219#[derive(Debug, Clone, Default, Deserialize, CombineOptions, OptionsMetadata)]
220#[serde(rename_all = "kebab-case")]
221#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
222pub struct GlobalOptions {
223    /// Enforce a requirement on the version of uv.
224    ///
225    /// If the version of uv does not meet the requirement at runtime, uv will exit
226    /// with an error.
227    ///
228    /// Accepts a [PEP 440](https://peps.python.org/pep-0440/) specifier, like `==0.5.0` or `>=0.5.0`.
229    #[option(
230        default = "null",
231        value_type = "str",
232        example = r#"
233            required-version = ">=0.5.0"
234        "#
235    )]
236    pub required_version: Option<RequiredVersion>,
237    /// Whether to load TLS certificates from the platform's native certificate store.
238    ///
239    /// By default, uv uses bundled Mozilla root certificates. When enabled, this loads
240    /// certificates from the platform's native certificate store instead.
241    #[option(
242        default = "false",
243        value_type = "bool",
244        uv_toml_only = true,
245        example = r#"
246            system-certs = true
247        "#
248    )]
249    pub system_certs: Option<bool>,
250    /// Whether to load TLS certificates from the platform's native certificate store.
251    ///
252    /// By default, uv uses bundled Mozilla root certificates. When enabled, this loads
253    /// certificates from the platform's native certificate store instead.
254    ///
255    /// (Deprecated: use `system-certs` instead.)
256    #[deprecated(note = "use `system-certs` instead")]
257    #[option(
258        default = "false",
259        value_type = "bool",
260        uv_toml_only = true,
261        example = r#"
262            native-tls = true
263        "#
264    )]
265    pub native_tls: Option<bool>,
266    /// Disable network access, relying only on locally cached data and locally available files.
267    #[option(
268        default = "false",
269        value_type = "bool",
270        example = r#"
271            offline = true
272        "#
273    )]
274    pub offline: Option<bool>,
275    /// Avoid reading from or writing to the cache, instead using a temporary directory for the
276    /// duration of the operation.
277    #[option(
278        default = "false",
279        value_type = "bool",
280        example = r#"
281            no-cache = true
282        "#
283    )]
284    pub no_cache: Option<bool>,
285    /// Path to the cache directory.
286    ///
287    /// Defaults to `$XDG_CACHE_HOME/uv` or `$HOME/.cache/uv` on Linux and macOS, and
288    /// `%LOCALAPPDATA%\uv\cache` on Windows.
289    #[option(
290        default = "None",
291        value_type = "str",
292        uv_toml_only = true,
293        example = r#"
294            cache-dir = "./.uv_cache"
295        "#
296    )]
297    pub cache_dir: Option<PathBuf>,
298    /// Whether to enable experimental, preview features.
299    #[option(
300        default = "false",
301        value_type = "bool",
302        example = r#"
303            preview = true
304        "#
305    )]
306    pub preview: Option<bool>,
307    /// Whether to prefer using Python installations that are already present on the system, or
308    /// those that are downloaded and installed by uv.
309    #[option(
310        default = "\"managed\"",
311        value_type = "str",
312        example = r#"
313            python-preference = "managed"
314        "#,
315        possible_values = true
316    )]
317    pub python_preference: Option<PythonPreference>,
318    /// Whether to allow Python downloads.
319    #[option(
320        default = "\"automatic\"",
321        value_type = "str",
322        example = r#"
323            python-downloads = "manual"
324        "#,
325        possible_values = true
326    )]
327    pub python_downloads: Option<PythonDownloads>,
328    /// The maximum number of in-flight concurrent downloads that uv will perform at any given
329    /// time.
330    #[option(
331        default = "50",
332        value_type = "int",
333        example = r#"
334            concurrent-downloads = 4
335        "#
336    )]
337    pub concurrent_downloads: Option<NonZeroUsize>,
338    /// The maximum number of source distributions that uv will build concurrently at any given
339    /// time.
340    ///
341    /// Defaults to the number of available CPU cores.
342    #[option(
343        default = "None",
344        value_type = "int",
345        example = r#"
346            concurrent-builds = 4
347        "#
348    )]
349    pub concurrent_builds: Option<NonZeroUsize>,
350    /// The number of threads used when installing and unzipping packages.
351    ///
352    /// Defaults to the number of available CPU cores.
353    #[option(
354        default = "None",
355        value_type = "int",
356        example = r#"
357            concurrent-installs = 4
358        "#
359    )]
360    pub concurrent_installs: Option<NonZeroUsize>,
361    /// The URL of the HTTP proxy to use.
362    #[option(
363        default = "None",
364        value_type = "str",
365        uv_toml_only = true,
366        example = r#"
367            http-proxy = "http://proxy.example.com"
368        "#
369    )]
370    pub http_proxy: Option<ProxyUrl>,
371    /// The URL of the HTTPS proxy to use.
372    #[option(
373        default = "None",
374        value_type = "str",
375        uv_toml_only = true,
376        example = r#"
377            https-proxy = "https://proxy.example.com"
378        "#
379    )]
380    pub https_proxy: Option<ProxyUrl>,
381    /// A list of hosts to exclude from proxying.
382    #[option(
383        default = "None",
384        value_type = "list[str]",
385        uv_toml_only = true,
386        example = r#"
387            no-proxy = ["localhost", "127.0.0.1"]
388        "#
389    )]
390    pub no_proxy: Option<Vec<String>>,
391    /// Allow insecure connections to host.
392    ///
393    /// Expects to receive either a hostname (e.g., `localhost`), a host-port pair (e.g.,
394    /// `localhost:8080`), or a URL (e.g., `https://localhost`).
395    ///
396    /// WARNING: Hosts included in this list will not be verified against the system's certificate
397    /// store. Only use `--allow-insecure-host` in a secure network with verified sources, as it
398    /// bypasses SSL verification and could expose you to MITM attacks.
399    #[option(
400        default = "[]",
401        value_type = "list[str]",
402        example = r#"
403            allow-insecure-host = ["localhost:8080"]
404        "#
405    )]
406    pub allow_insecure_host: Option<Vec<TrustedHost>>,
407}
408
409/// Settings relevant to all installer operations.
410#[derive(Debug, Clone, Default, CombineOptions)]
411pub struct InstallerOptions {
412    pub index: Option<Vec<Index>>,
413    pub index_url: Option<PipIndex>,
414    pub extra_index_url: Option<Vec<PipExtraIndex>>,
415    pub no_index: Option<bool>,
416    pub find_links: Option<Vec<PipFindLinks>>,
417    pub index_strategy: Option<IndexStrategy>,
418    pub keyring_provider: Option<KeyringProviderType>,
419    pub config_settings: Option<ConfigSettings>,
420    pub exclude_newer: Option<ExcludeNewerValue>,
421    pub link_mode: Option<LinkMode>,
422    pub compile_bytecode: Option<bool>,
423    pub reinstall: Option<Reinstall>,
424    pub build_isolation: Option<BuildIsolation>,
425    pub no_build: Option<bool>,
426    pub no_build_package: Option<Vec<PackageName>>,
427    pub no_binary: Option<bool>,
428    pub no_binary_package: Option<Vec<PackageName>>,
429    pub no_sources: Option<bool>,
430    pub no_sources_package: Option<Vec<PackageName>>,
431}
432
433/// Settings relevant to all resolver operations.
434#[derive(Debug, Clone, Default, CombineOptions)]
435pub struct ResolverOptions {
436    pub index: Option<Vec<Index>>,
437    pub index_url: Option<PipIndex>,
438    pub extra_index_url: Option<Vec<PipExtraIndex>>,
439    pub no_index: Option<bool>,
440    pub find_links: Option<Vec<PipFindLinks>>,
441    pub index_strategy: Option<IndexStrategy>,
442    pub keyring_provider: Option<KeyringProviderType>,
443    pub resolution: Option<ResolutionMode>,
444    pub prerelease: Option<PrereleaseMode>,
445    pub fork_strategy: Option<ForkStrategy>,
446    pub dependency_metadata: Option<Vec<StaticMetadata>>,
447    pub config_settings: Option<ConfigSettings>,
448    pub config_settings_package: Option<PackageConfigSettings>,
449    pub exclude_newer: ExcludeNewer,
450    pub link_mode: Option<LinkMode>,
451    pub torch_backend: Option<TorchMode>,
452    pub upgrade: Option<Upgrade>,
453    pub build_isolation: Option<BuildIsolation>,
454    pub no_build: Option<bool>,
455    pub no_build_package: Option<Vec<PackageName>>,
456    pub no_binary: Option<bool>,
457    pub no_binary_package: Option<Vec<PackageName>>,
458    pub extra_build_dependencies: Option<ExtraBuildDependencies>,
459    pub extra_build_variables: Option<ExtraBuildVariables>,
460    pub no_sources: Option<bool>,
461    pub no_sources_package: Option<Vec<PackageName>>,
462}
463
464/// Shared settings, relevant to all operations that must resolve and install dependencies. The
465/// union of [`InstallerOptions`] and [`ResolverOptions`].
466#[derive(Debug, Clone, Default, CombineOptions)]
467pub struct ResolverInstallerOptions {
468    pub index: Option<Vec<Index>>,
469    pub index_url: Option<PipIndex>,
470    pub extra_index_url: Option<Vec<PipExtraIndex>>,
471    pub no_index: Option<bool>,
472    pub find_links: Option<Vec<PipFindLinks>>,
473    pub index_strategy: Option<IndexStrategy>,
474    pub keyring_provider: Option<KeyringProviderType>,
475    pub resolution: Option<ResolutionMode>,
476    pub prerelease: Option<PrereleaseMode>,
477    pub fork_strategy: Option<ForkStrategy>,
478    pub dependency_metadata: Option<Vec<StaticMetadata>>,
479    pub config_settings: Option<ConfigSettings>,
480    pub config_settings_package: Option<PackageConfigSettings>,
481    pub build_isolation: Option<BuildIsolation>,
482    pub extra_build_dependencies: Option<ExtraBuildDependencies>,
483    pub extra_build_variables: Option<ExtraBuildVariables>,
484    pub exclude_newer: Option<ExcludeNewerValue>,
485    pub exclude_newer_package: Option<ExcludeNewerPackage>,
486    pub link_mode: Option<LinkMode>,
487    pub torch_backend: Option<TorchMode>,
488    pub compile_bytecode: Option<bool>,
489    pub no_sources: Option<bool>,
490    pub no_sources_package: Option<Vec<PackageName>>,
491    pub upgrade: Option<Upgrade>,
492    pub reinstall: Option<Reinstall>,
493    pub no_build: Option<bool>,
494    pub no_build_package: Option<Vec<PackageName>>,
495    pub no_binary: Option<bool>,
496    pub no_binary_package: Option<Vec<PackageName>>,
497}
498
499impl From<ResolverInstallerSchema> for ResolverInstallerOptions {
500    fn from(value: ResolverInstallerSchema) -> Self {
501        let ResolverInstallerSchema {
502            index,
503            index_url,
504            extra_index_url,
505            no_index,
506            find_links,
507            index_strategy,
508            keyring_provider,
509            resolution,
510            prerelease,
511            fork_strategy,
512            dependency_metadata,
513            config_settings,
514            config_settings_package,
515            no_build_isolation,
516            no_build_isolation_package,
517            extra_build_dependencies,
518            extra_build_variables,
519            exclude_newer,
520            exclude_newer_package,
521            link_mode,
522            torch_backend,
523            compile_bytecode,
524            no_sources,
525            no_sources_package,
526            upgrade,
527            upgrade_package,
528            reinstall,
529            reinstall_package,
530            no_build,
531            no_build_package,
532            no_binary,
533            no_binary_package,
534        } = value;
535        Self {
536            index,
537            index_url,
538            extra_index_url,
539            no_index,
540            find_links,
541            index_strategy,
542            keyring_provider,
543            resolution,
544            prerelease,
545            fork_strategy,
546            dependency_metadata,
547            config_settings,
548            config_settings_package,
549            build_isolation: BuildIsolation::from_args(
550                no_build_isolation,
551                no_build_isolation_package.into_iter().flatten().collect(),
552            ),
553            extra_build_dependencies,
554            extra_build_variables,
555            exclude_newer,
556            exclude_newer_package,
557            link_mode,
558            torch_backend,
559            compile_bytecode,
560            no_sources,
561            no_sources_package,
562            upgrade: Upgrade::from_args(
563                upgrade,
564                upgrade_package
565                    .into_iter()
566                    .flatten()
567                    .map(Into::into)
568                    .collect(),
569            ),
570            reinstall: Reinstall::from_args(reinstall, reinstall_package.unwrap_or_default()),
571            no_build,
572            no_build_package,
573            no_binary,
574            no_binary_package,
575        }
576    }
577}
578
579impl ResolverInstallerSchema {
580    /// Resolve the [`ResolverInstallerSchema`] relative to the given root directory.
581    pub fn relative_to(self, root_dir: &Path) -> Result<Self, IndexUrlError> {
582        Ok(Self {
583            index: self
584                .index
585                .map(|index| {
586                    index
587                        .into_iter()
588                        .map(|index| index.relative_to(root_dir))
589                        .collect::<Result<Vec<_>, _>>()
590                })
591                .transpose()?,
592            index_url: self
593                .index_url
594                .map(|index_url| index_url.relative_to(root_dir))
595                .transpose()?,
596            extra_index_url: self
597                .extra_index_url
598                .map(|extra_index_url| {
599                    extra_index_url
600                        .into_iter()
601                        .map(|extra_index_url| extra_index_url.relative_to(root_dir))
602                        .collect::<Result<Vec<_>, _>>()
603                })
604                .transpose()?,
605            find_links: self
606                .find_links
607                .map(|find_links| {
608                    find_links
609                        .into_iter()
610                        .map(|find_link| find_link.relative_to(root_dir))
611                        .collect::<Result<Vec<_>, _>>()
612                })
613                .transpose()?,
614            ..self
615        })
616    }
617}
618
619/// The JSON schema for the `[tool.uv]` section of a `pyproject.toml` file.
620#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
621#[serde(rename_all = "kebab-case")]
622#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
623pub struct ResolverInstallerSchema {
624    /// The package indexes to use when resolving dependencies.
625    ///
626    /// Accepts either a repository compliant with [PEP 503](https://peps.python.org/pep-0503/)
627    /// (the simple repository API), or a local directory laid out in the same format.
628    ///
629    /// Indexes are considered in the order in which they're defined, such that the first-defined
630    /// index has the highest priority. Further, the indexes provided by this setting are given
631    /// higher priority than any indexes specified via [`index_url`](#index-url) or
632    /// [`extra_index_url`](#extra-index-url). uv will only consider the first index that contains
633    /// a given package, unless an alternative [index strategy](#index-strategy) is specified.
634    ///
635    /// If an index is marked as `explicit = true`, it will be used exclusively for those
636    /// dependencies that select it explicitly via `[tool.uv.sources]`, as in:
637    ///
638    /// ```toml
639    /// [[tool.uv.index]]
640    /// name = "pytorch"
641    /// url = "https://download.pytorch.org/whl/cu121"
642    /// explicit = true
643    ///
644    /// [tool.uv.sources]
645    /// torch = { index = "pytorch" }
646    /// ```
647    ///
648    /// If an index is marked as `default = true`, it will be moved to the end of the prioritized list, such that it is
649    /// given the lowest priority when resolving packages. Additionally, marking an index as default will disable the
650    /// PyPI default index.
651    #[option(
652        default = "\"[]\"",
653        value_type = "dict",
654        example = r#"
655            [[tool.uv.index]]
656            name = "pytorch"
657            url = "https://download.pytorch.org/whl/cu121"
658        "#
659    )]
660    pub index: Option<Vec<Index>>,
661    /// The URL of the Python package index (by default: <https://pypi.org/simple>).
662    ///
663    /// Accepts either a repository compliant with [PEP 503](https://peps.python.org/pep-0503/)
664    /// (the simple repository API), or a local directory laid out in the same format.
665    ///
666    /// The index provided by this setting is given lower priority than any indexes specified via
667    /// [`extra_index_url`](#extra-index-url) or [`index`](#index).
668    ///
669    /// (Deprecated: use `index` instead.)
670    #[option(
671        default = "\"https://pypi.org/simple\"",
672        value_type = "str",
673        example = r#"
674            index-url = "https://test.pypi.org/simple"
675        "#
676    )]
677    pub index_url: Option<PipIndex>,
678    /// Extra URLs of package indexes to use, in addition to `--index-url`.
679    ///
680    /// Accepts either a repository compliant with [PEP 503](https://peps.python.org/pep-0503/)
681    /// (the simple repository API), or a local directory laid out in the same format.
682    ///
683    /// All indexes provided via this flag take priority over the index specified by
684    /// [`index_url`](#index-url) or [`index`](#index) with `default = true`. When multiple indexes
685    /// are provided, earlier values take priority.
686    ///
687    /// To control uv's resolution strategy when multiple indexes are present, see
688    /// [`index_strategy`](#index-strategy).
689    ///
690    /// (Deprecated: use `index` instead.)
691    #[option(
692        default = "[]",
693        value_type = "list[str]",
694        example = r#"
695            extra-index-url = ["https://download.pytorch.org/whl/cpu"]
696        "#
697    )]
698    pub extra_index_url: Option<Vec<PipExtraIndex>>,
699    /// Ignore all registry indexes (e.g., PyPI), instead relying on direct URL dependencies and
700    /// those provided via `--find-links`.
701    #[option(
702        default = "false",
703        value_type = "bool",
704        example = r#"
705            no-index = true
706        "#
707    )]
708    pub no_index: Option<bool>,
709    /// Locations to search for candidate distributions, in addition to those found in the registry
710    /// indexes.
711    ///
712    /// If a path, the target must be a directory that contains packages as wheel files (`.whl`) or
713    /// source distributions (e.g., `.tar.gz` or `.zip`) at the top level.
714    ///
715    /// If a URL, the page must contain a flat list of links to package files adhering to the
716    /// formats described above.
717    #[option(
718        default = "[]",
719        value_type = "list[str]",
720        example = r#"
721            find-links = ["https://download.pytorch.org/whl/torch_stable.html"]
722        "#
723    )]
724    pub find_links: Option<Vec<PipFindLinks>>,
725    /// The strategy to use when resolving against multiple index URLs.
726    ///
727    /// By default, uv will stop at the first index on which a given package is available, and
728    /// limit resolutions to those present on that first index (`first-index`). This prevents
729    /// "dependency confusion" attacks, whereby an attacker can upload a malicious package under the
730    /// same name to an alternate index.
731    #[option(
732        default = "\"first-index\"",
733        value_type = "str",
734        example = r#"
735            index-strategy = "unsafe-best-match"
736        "#,
737        possible_values = true
738    )]
739    pub index_strategy: Option<IndexStrategy>,
740    /// Attempt to use `keyring` for authentication for index URLs.
741    ///
742    /// At present, only `--keyring-provider subprocess` is supported, which configures uv to
743    /// use the `keyring` CLI to handle authentication.
744    #[option(
745        default = "\"disabled\"",
746        value_type = "str",
747        example = r#"
748            keyring-provider = "subprocess"
749        "#
750    )]
751    pub keyring_provider: Option<KeyringProviderType>,
752    /// The strategy to use when selecting between the different compatible versions for a given
753    /// package requirement.
754    ///
755    /// By default, uv will use the latest compatible version of each package (`highest`).
756    #[option(
757        default = "\"highest\"",
758        value_type = "str",
759        example = r#"
760            resolution = "lowest-direct"
761        "#,
762        possible_values = true
763    )]
764    pub resolution: Option<ResolutionMode>,
765    /// The strategy to use when considering pre-release versions.
766    ///
767    /// By default, uv will accept pre-releases for packages that _only_ publish pre-releases,
768    /// along with first-party requirements that contain an explicit pre-release marker in the
769    /// declared specifiers (`if-necessary-or-explicit`).
770    #[option(
771        default = "\"if-necessary-or-explicit\"",
772        value_type = "str",
773        example = r#"
774            prerelease = "allow"
775        "#,
776        possible_values = true
777    )]
778    pub prerelease: Option<PrereleaseMode>,
779    /// The strategy to use when selecting multiple versions of a given package across Python
780    /// versions and platforms.
781    ///
782    /// By default, uv will optimize for selecting the latest version of each package for each
783    /// supported Python version (`requires-python`), while minimizing the number of selected
784    /// versions across platforms.
785    ///
786    /// Under `fewest`, uv will minimize the number of selected versions for each package,
787    /// preferring older versions that are compatible with a wider range of supported Python
788    /// versions or platforms.
789    #[option(
790        default = "\"requires-python\"",
791        value_type = "str",
792        example = r#"
793            fork-strategy = "fewest"
794        "#,
795        possible_values = true
796    )]
797    pub fork_strategy: Option<ForkStrategy>,
798    /// Pre-defined static metadata for dependencies of the project (direct or transitive). When
799    /// provided, enables the resolver to use the specified metadata instead of querying the
800    /// registry or building the relevant package from source.
801    ///
802    /// Metadata should be provided in adherence with the [Metadata 2.3](https://packaging.python.org/en/latest/specifications/core-metadata/)
803    /// standard, though only the following fields are respected:
804    ///
805    /// - `name`: The name of the package.
806    /// - (Optional) `version`: The version of the package. If omitted, the metadata will be applied
807    ///   to all versions of the package.
808    /// - (Optional) `requires-dist`: The dependencies of the package (e.g., `werkzeug>=0.14`).
809    /// - (Optional) `requires-python`: The Python version required by the package (e.g., `>=3.10`).
810    /// - (Optional) `provides-extra`: The extras provided by the package.
811    #[option(
812        default = r#"[]"#,
813        value_type = "list[dict]",
814        example = r#"
815            dependency-metadata = [
816                { name = "flask", version = "1.0.0", requires-dist = ["werkzeug"], requires-python = ">=3.6" },
817            ]
818        "#
819    )]
820    pub dependency_metadata: Option<Vec<StaticMetadata>>,
821    /// Settings to pass to the [PEP 517](https://peps.python.org/pep-0517/) build backend,
822    /// specified as `KEY=VALUE` pairs.
823    #[option(
824        default = "{}",
825        value_type = "dict",
826        example = r#"
827            config-settings = { editable_mode = "compat" }
828        "#
829    )]
830    pub config_settings: Option<ConfigSettings>,
831    /// Settings to pass to the [PEP 517](https://peps.python.org/pep-0517/) build backend for specific packages,
832    /// specified as `KEY=VALUE` pairs.
833    ///
834    /// Accepts a map from package names to string key-value pairs.
835    #[option(
836        default = "{}",
837        value_type = "dict",
838        example = r#"
839            config-settings-package = { numpy = { editable_mode = "compat" } }
840        "#
841    )]
842    pub config_settings_package: Option<PackageConfigSettings>,
843    /// Disable isolation when building source distributions.
844    ///
845    /// Assumes that build dependencies specified by [PEP 518](https://peps.python.org/pep-0518/)
846    /// are already installed.
847    #[option(
848        default = "false",
849        value_type = "bool",
850        example = r#"
851            no-build-isolation = true
852        "#
853    )]
854    pub no_build_isolation: Option<bool>,
855    /// Disable isolation when building source distributions for a specific package.
856    ///
857    /// Assumes that the packages' build dependencies specified by [PEP 518](https://peps.python.org/pep-0518/)
858    /// are already installed.
859    #[option(
860        default = "[]",
861        value_type = "list[str]",
862        example = r#"
863        no-build-isolation-package = ["package1", "package2"]
864    "#
865    )]
866    pub no_build_isolation_package: Option<Vec<PackageName>>,
867    /// Additional build dependencies for packages.
868    ///
869    /// This allows extending the PEP 517 build environment for the project's dependencies with
870    /// additional packages. This is useful for packages that assume the presence of packages like
871    /// `pip`, and do not declare them as build dependencies.
872    #[option(
873        default = "[]",
874        value_type = "dict",
875        example = r#"
876            extra-build-dependencies = { pytest = ["setuptools"] }
877        "#
878    )]
879    pub extra_build_dependencies: Option<ExtraBuildDependencies>,
880    /// Extra environment variables to set when building certain packages.
881    ///
882    /// Environment variables will be added to the environment when building the
883    /// specified packages.
884    #[option(
885        default = r#"{}"#,
886        value_type = r#"dict[str, dict[str, str]]"#,
887        example = r#"
888            extra-build-variables = { flash-attn = { FLASH_ATTENTION_SKIP_CUDA_BUILD = "TRUE" } }
889        "#
890    )]
891    pub extra_build_variables: Option<ExtraBuildVariables>,
892    /// Limit candidate packages to those that were uploaded prior to the given date.
893    ///
894    /// Accepts RFC 3339 timestamps (e.g., `2006-12-02T02:07:43Z`), a "friendly" duration (e.g.,
895    /// `24 hours`, `1 week`, `30 days`), or an ISO 8601 duration (e.g., `PT24H`, `P7D`, `P30D`).
896    ///
897    /// Durations do not respect semantics of the local time zone and are always resolved to a fixed
898    /// number of seconds assuming that a day is 24 hours (e.g., DST transitions are ignored).
899    /// Calendar units such as months and years are not allowed.
900    #[option(
901        default = "None",
902        value_type = "str",
903        example = r#"
904            exclude-newer = "2006-12-02T02:07:43Z"
905        "#
906    )]
907    pub exclude_newer: Option<ExcludeNewerValue>,
908    /// Limit candidate packages for specific packages to those that were uploaded prior to the
909    /// given date.
910    ///
911    /// Accepts a dictionary format of `PACKAGE = "DATE"` pairs, where `DATE` is an RFC 3339
912    /// timestamp (e.g., `2006-12-02T02:07:43Z`), a "friendly" duration (e.g., `24 hours`, `1 week`,
913    /// `30 days`), or a ISO 8601 duration (e.g., `PT24H`, `P7D`, `P30D`).
914    ///
915    /// Durations do not respect semantics of the local time zone and are always resolved to a fixed
916    /// number of seconds assuming that a day is 24 hours (e.g., DST transitions are ignored).
917    /// Calendar units such as months and years are not allowed.
918    #[option(
919        default = "None",
920        value_type = "dict",
921        example = r#"
922            exclude-newer-package = { tqdm = "2022-04-04T00:00:00Z" }
923        "#
924    )]
925    pub exclude_newer_package: Option<ExcludeNewerPackage>,
926    /// The method to use when installing packages from the global cache.
927    ///
928    /// Defaults to `clone` (also known as Copy-on-Write) on macOS and Linux, and `hardlink` on
929    /// Windows.
930    ///
931    /// WARNING: The use of symlink link mode is discouraged, as they create tight coupling between
932    /// the cache and the target environment. For example, clearing the cache (`uv cache clean`)
933    /// will break all installed packages by way of removing the underlying source files. Use
934    /// symlinks with caution.
935    #[option(
936        default = "\"clone\" (macOS, Linux) or \"hardlink\" (Windows)",
937        value_type = "str",
938        example = r#"
939            link-mode = "copy"
940        "#,
941        possible_values = true
942    )]
943    pub link_mode: Option<LinkMode>,
944    /// Compile Python files to bytecode after installation.
945    ///
946    /// By default, uv does not compile Python (`.py`) files to bytecode (`__pycache__/*.pyc`);
947    /// instead, compilation is performed lazily the first time a module is imported. For use-cases
948    /// in which start time is critical, such as CLI applications and Docker containers, this option
949    /// can be enabled to trade longer installation times for faster start times.
950    ///
951    /// When enabled, uv will process the entire site-packages directory (including packages that
952    /// are not being modified by the current operation) for consistency. Like pip, it will also
953    /// ignore errors.
954    #[option(
955        default = "false",
956        value_type = "bool",
957        example = r#"
958            compile-bytecode = true
959        "#
960    )]
961    pub compile_bytecode: Option<bool>,
962    /// Ignore the `tool.uv.sources` table when resolving dependencies. Used to lock against the
963    /// standards-compliant, publishable package metadata, as opposed to using any local or Git
964    /// sources.
965    #[option(
966        default = "false",
967        value_type = "bool",
968        example = r#"
969            no-sources = true
970        "#
971    )]
972    pub no_sources: Option<bool>,
973    /// Ignore `tool.uv.sources` for the specified packages.
974    #[option(
975        default = "[]",
976        value_type = "list[str]",
977        example = r#"
978            no-sources-package = ["ruff"]
979        "#
980    )]
981    pub no_sources_package: Option<Vec<PackageName>>,
982    /// Allow package upgrades, ignoring pinned versions in any existing output file.
983    #[option(
984        default = "false",
985        value_type = "bool",
986        example = r#"
987            upgrade = true
988        "#
989    )]
990    pub upgrade: Option<bool>,
991    /// Allow upgrades for a specific package, ignoring pinned versions in any existing output
992    /// file.
993    ///
994    /// Accepts both standalone package names (`ruff`) and version specifiers (`ruff<0.5.0`).
995    #[option(
996        default = "[]",
997        value_type = "list[str]",
998        example = r#"
999            upgrade-package = ["ruff"]
1000        "#
1001    )]
1002    pub upgrade_package: Option<Vec<Requirement<VerbatimParsedUrl>>>,
1003    /// Reinstall all packages, regardless of whether they're already installed. Implies `refresh`.
1004    #[option(
1005        default = "false",
1006        value_type = "bool",
1007        example = r#"
1008            reinstall = true
1009        "#
1010    )]
1011    pub reinstall: Option<bool>,
1012    /// Reinstall a specific package, regardless of whether it's already installed. Implies
1013    /// `refresh-package`.
1014    #[option(
1015        default = "[]",
1016        value_type = "list[str]",
1017        example = r#"
1018            reinstall-package = ["ruff"]
1019        "#
1020    )]
1021    pub reinstall_package: Option<Vec<PackageName>>,
1022    /// Don't build source distributions.
1023    ///
1024    /// When enabled, resolving will not run arbitrary Python code. The cached wheels of
1025    /// already-built source distributions will be reused, but operations that require building
1026    /// distributions will exit with an error.
1027    #[option(
1028        default = "false",
1029        value_type = "bool",
1030        example = r#"
1031            no-build = true
1032        "#
1033    )]
1034    pub no_build: Option<bool>,
1035    /// Don't build source distributions for a specific package.
1036    #[option(
1037        default = "[]",
1038        value_type = "list[str]",
1039        example = r#"
1040            no-build-package = ["ruff"]
1041        "#
1042    )]
1043    pub no_build_package: Option<Vec<PackageName>>,
1044    /// Don't install pre-built wheels.
1045    ///
1046    /// The given packages will be built and installed from source. The resolver will still use
1047    /// pre-built wheels to extract package metadata, if available.
1048    #[option(
1049        default = "false",
1050        value_type = "bool",
1051        example = r#"
1052            no-binary = true
1053        "#
1054    )]
1055    pub no_binary: Option<bool>,
1056    /// Don't install pre-built wheels for a specific package.
1057    #[option(
1058        default = "[]",
1059        value_type = "list[str]",
1060        example = r#"
1061            no-binary-package = ["ruff"]
1062        "#
1063    )]
1064    pub no_binary_package: Option<Vec<PackageName>>,
1065    /// The backend to use when fetching packages in the PyTorch ecosystem.
1066    ///
1067    /// When set, uv will ignore the configured index URLs for packages in the PyTorch ecosystem,
1068    /// and will instead use the defined backend.
1069    ///
1070    /// For example, when set to `cpu`, uv will use the CPU-only PyTorch index; when set to `cu126`,
1071    /// uv will use the PyTorch index for CUDA 12.6.
1072    ///
1073    /// The `auto` mode will attempt to detect the appropriate PyTorch index based on the currently
1074    /// installed CUDA drivers.
1075    ///
1076    /// This setting is only respected by `uv pip` commands.
1077    ///
1078    /// This option is in preview and may change in any future release.
1079    #[option(
1080        default = "null",
1081        value_type = "str",
1082        example = r#"
1083            torch-backend = "auto"
1084        "#
1085    )]
1086    pub torch_backend: Option<TorchMode>,
1087}
1088
1089/// Shared settings, relevant to all operations that might create managed python installations.
1090#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
1091#[serde(rename_all = "kebab-case")]
1092#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1093pub struct PythonInstallMirrors {
1094    /// Mirror URL for downloading managed Python installations.
1095    ///
1096    /// By default, managed Python installations are downloaded from [`python-build-standalone`](https://github.com/astral-sh/python-build-standalone).
1097    /// This variable can be set to a mirror URL to use a different source for Python installations.
1098    /// The provided URL will replace `https://github.com/astral-sh/python-build-standalone/releases/download` in, e.g., `https://github.com/astral-sh/python-build-standalone/releases/download/20240713/cpython-3.12.4%2B20240713-aarch64-apple-darwin-install_only.tar.gz`.
1099    ///
1100    /// Distributions can be read from a local directory by using the `file://` URL scheme.
1101    #[option(
1102        default = "None",
1103        value_type = "str",
1104        uv_toml_only = true,
1105        example = r#"
1106            python-install-mirror = "https://github.com/astral-sh/python-build-standalone/releases/download"
1107        "#
1108    )]
1109    pub python_install_mirror: Option<String>,
1110    /// Mirror URL to use for downloading managed PyPy installations.
1111    ///
1112    /// By default, managed PyPy installations are downloaded from [downloads.python.org](https://downloads.python.org/).
1113    /// This variable can be set to a mirror URL to use a different source for PyPy installations.
1114    /// The provided URL will replace `https://downloads.python.org/pypy` in, e.g., `https://downloads.python.org/pypy/pypy3.8-v7.3.7-osx64.tar.bz2`.
1115    ///
1116    /// Distributions can be read from a
1117    /// local directory by using the `file://` URL scheme.
1118    #[option(
1119        default = "None",
1120        value_type = "str",
1121        uv_toml_only = true,
1122        example = r#"
1123            pypy-install-mirror = "https://downloads.python.org/pypy"
1124        "#
1125    )]
1126    pub pypy_install_mirror: Option<String>,
1127
1128    /// URL pointing to JSON of custom Python installations.
1129    #[option(
1130        default = "None",
1131        value_type = "str",
1132        uv_toml_only = true,
1133        example = r#"
1134            python-downloads-json-url = "/etc/uv/python-downloads.json"
1135        "#
1136    )]
1137    pub python_downloads_json_url: Option<String>,
1138}
1139
1140impl PythonInstallMirrors {
1141    #[must_use]
1142    pub fn combine(self, other: Self) -> Self {
1143        Self {
1144            python_install_mirror: self.python_install_mirror.or(other.python_install_mirror),
1145            pypy_install_mirror: self.pypy_install_mirror.or(other.pypy_install_mirror),
1146            python_downloads_json_url: self
1147                .python_downloads_json_url
1148                .or(other.python_downloads_json_url),
1149        }
1150    }
1151}
1152
1153/// Settings that are specific to the `uv pip` command-line interface.
1154///
1155/// These values will be ignored when running commands outside the `uv pip` namespace (e.g.,
1156/// `uv lock`, `uvx`).
1157#[derive(Debug, Clone, Default, Deserialize, CombineOptions, OptionsMetadata)]
1158#[serde(deny_unknown_fields, rename_all = "kebab-case")]
1159#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1160pub struct PipOptions {
1161    /// The Python interpreter into which packages should be installed.
1162    ///
1163    /// By default, uv installs into the virtual environment in the current working directory or
1164    /// any parent directory. The `--python` option allows you to specify a different interpreter,
1165    /// which is intended for use in continuous integration (CI) environments or other automated
1166    /// workflows.
1167    ///
1168    /// Supported formats:
1169    /// - `3.10` looks for an installed Python 3.10 in the registry on Windows (see
1170    ///   `py --list-paths`), or `python3.10` on Linux and macOS.
1171    /// - `python3.10` or `python.exe` looks for a binary with the given name in `PATH`.
1172    /// - `/home/ferris/.local/bin/python3.10` uses the exact Python at the given path.
1173    #[option(
1174        default = "None",
1175        value_type = "str",
1176        example = r#"
1177            python = "3.10"
1178        "#
1179    )]
1180    pub python: Option<String>,
1181    /// Install packages into the system Python environment.
1182    ///
1183    /// By default, uv installs into the virtual environment in the current working directory or
1184    /// any parent directory. The `--system` option instructs uv to instead use the first Python
1185    /// found in the system `PATH`.
1186    ///
1187    /// WARNING: `--system` is intended for use in continuous integration (CI) environments and
1188    /// should be used with caution, as it can modify the system Python installation.
1189    #[option(
1190        default = "false",
1191        value_type = "bool",
1192        example = r#"
1193            system = true
1194        "#
1195    )]
1196    pub system: Option<bool>,
1197    /// Allow uv to modify an `EXTERNALLY-MANAGED` Python installation.
1198    ///
1199    /// WARNING: `--break-system-packages` is intended for use in continuous integration (CI)
1200    /// environments, when installing into Python installations that are managed by an external
1201    /// package manager, like `apt`. It should be used with caution, as such Python installations
1202    /// explicitly recommend against modifications by other package managers (like uv or pip).
1203    #[option(
1204        default = "false",
1205        value_type = "bool",
1206        example = r#"
1207            break-system-packages = true
1208        "#
1209    )]
1210    pub break_system_packages: Option<bool>,
1211    /// Install packages into the specified directory, rather than into the virtual or system Python
1212    /// environment. The packages will be installed at the top-level of the directory.
1213    #[option(
1214        default = "None",
1215        value_type = "str",
1216        example = r#"
1217            target = "./target"
1218        "#
1219    )]
1220    pub target: Option<PathBuf>,
1221    /// Install packages into `lib`, `bin`, and other top-level folders under the specified
1222    /// directory, as if a virtual environment were present at that location.
1223    ///
1224    /// In general, prefer the use of `--python` to install into an alternate environment, as
1225    /// scripts and other artifacts installed via `--prefix` will reference the installing
1226    /// interpreter, rather than any interpreter added to the `--prefix` directory, rendering them
1227    /// non-portable.
1228    #[option(
1229        default = "None",
1230        value_type = "str",
1231        example = r#"
1232            prefix = "./prefix"
1233        "#
1234    )]
1235    pub prefix: Option<PathBuf>,
1236    #[serde(skip)]
1237    #[cfg_attr(feature = "schemars", schemars(skip))]
1238    pub index: Option<Vec<Index>>,
1239    /// The URL of the Python package index (by default: <https://pypi.org/simple>).
1240    ///
1241    /// Accepts either a repository compliant with [PEP 503](https://peps.python.org/pep-0503/)
1242    /// (the simple repository API), or a local directory laid out in the same format.
1243    ///
1244    /// The index provided by this setting is given lower priority than any indexes specified via
1245    /// [`extra_index_url`](#extra-index-url).
1246    #[option(
1247        default = "\"https://pypi.org/simple\"",
1248        value_type = "str",
1249        example = r#"
1250            index-url = "https://test.pypi.org/simple"
1251        "#
1252    )]
1253    pub index_url: Option<PipIndex>,
1254    /// Extra URLs of package indexes to use, in addition to `--index-url`.
1255    ///
1256    /// Accepts either a repository compliant with [PEP 503](https://peps.python.org/pep-0503/)
1257    /// (the simple repository API), or a local directory laid out in the same format.
1258    ///
1259    /// All indexes provided via this flag take priority over the index specified by
1260    /// [`index_url`](#index-url). When multiple indexes are provided, earlier values take priority.
1261    ///
1262    /// To control uv's resolution strategy when multiple indexes are present, see
1263    /// [`index_strategy`](#index-strategy).
1264    #[option(
1265        default = "[]",
1266        value_type = "list[str]",
1267        example = r#"
1268            extra-index-url = ["https://download.pytorch.org/whl/cpu"]
1269        "#
1270    )]
1271    pub extra_index_url: Option<Vec<PipExtraIndex>>,
1272    /// Ignore all registry indexes (e.g., PyPI), instead relying on direct URL dependencies and
1273    /// those provided via `--find-links`.
1274    #[option(
1275        default = "false",
1276        value_type = "bool",
1277        example = r#"
1278            no-index = true
1279        "#
1280    )]
1281    pub no_index: Option<bool>,
1282    /// Locations to search for candidate distributions, in addition to those found in the registry
1283    /// indexes.
1284    ///
1285    /// If a path, the target must be a directory that contains packages as wheel files (`.whl`) or
1286    /// source distributions (e.g., `.tar.gz` or `.zip`) at the top level.
1287    ///
1288    /// If a URL, the page must contain a flat list of links to package files adhering to the
1289    /// formats described above.
1290    #[option(
1291        default = "[]",
1292        value_type = "list[str]",
1293        example = r#"
1294            find-links = ["https://download.pytorch.org/whl/torch_stable.html"]
1295        "#
1296    )]
1297    pub find_links: Option<Vec<PipFindLinks>>,
1298    /// The strategy to use when resolving against multiple index URLs.
1299    ///
1300    /// By default, uv will stop at the first index on which a given package is available, and
1301    /// limit resolutions to those present on that first index (`first-index`). This prevents
1302    /// "dependency confusion" attacks, whereby an attacker can upload a malicious package under the
1303    /// same name to an alternate index.
1304    #[option(
1305        default = "\"first-index\"",
1306        value_type = "str",
1307        example = r#"
1308            index-strategy = "unsafe-best-match"
1309        "#,
1310        possible_values = true
1311    )]
1312    pub index_strategy: Option<IndexStrategy>,
1313    /// Attempt to use `keyring` for authentication for index URLs.
1314    ///
1315    /// At present, only `--keyring-provider subprocess` is supported, which configures uv to
1316    /// use the `keyring` CLI to handle authentication.
1317    #[option(
1318        default = "disabled",
1319        value_type = "str",
1320        example = r#"
1321            keyring-provider = "subprocess"
1322        "#
1323    )]
1324    pub keyring_provider: Option<KeyringProviderType>,
1325    /// Don't build source distributions.
1326    ///
1327    /// When enabled, resolving will not run arbitrary Python code. The cached wheels of
1328    /// already-built source distributions will be reused, but operations that require building
1329    /// distributions will exit with an error.
1330    ///
1331    /// Alias for `--only-binary :all:`.
1332    #[option(
1333        default = "false",
1334        value_type = "bool",
1335        example = r#"
1336            no-build = true
1337        "#
1338    )]
1339    pub no_build: Option<bool>,
1340    /// Don't install pre-built wheels.
1341    ///
1342    /// The given packages will be built and installed from source. The resolver will still use
1343    /// pre-built wheels to extract package metadata, if available.
1344    ///
1345    /// Multiple packages may be provided. Disable binaries for all packages with `:all:`.
1346    /// Clear previously specified packages with `:none:`.
1347    #[option(
1348        default = "[]",
1349        value_type = "list[str]",
1350        example = r#"
1351            no-binary = ["ruff"]
1352        "#
1353    )]
1354    pub no_binary: Option<Vec<PackageNameSpecifier>>,
1355    /// Only use pre-built wheels; don't build source distributions.
1356    ///
1357    /// When enabled, resolving will not run code from the given packages. The cached wheels of already-built
1358    /// source distributions will be reused, but operations that require building distributions will
1359    /// exit with an error.
1360    ///
1361    /// Multiple packages may be provided. Disable binaries for all packages with `:all:`.
1362    /// Clear previously specified packages with `:none:`.
1363    #[option(
1364        default = "[]",
1365        value_type = "list[str]",
1366        example = r#"
1367            only-binary = ["ruff"]
1368        "#
1369    )]
1370    pub only_binary: Option<Vec<PackageNameSpecifier>>,
1371    /// Disable isolation when building source distributions.
1372    ///
1373    /// Assumes that build dependencies specified by [PEP 518](https://peps.python.org/pep-0518/)
1374    /// are already installed.
1375    #[option(
1376        default = "false",
1377        value_type = "bool",
1378        example = r#"
1379            no-build-isolation = true
1380        "#
1381    )]
1382    pub no_build_isolation: Option<bool>,
1383    /// Disable isolation when building source distributions for a specific package.
1384    ///
1385    /// Assumes that the packages' build dependencies specified by [PEP 518](https://peps.python.org/pep-0518/)
1386    /// are already installed.
1387    #[option(
1388        default = "[]",
1389        value_type = "list[str]",
1390        example = r#"
1391            no-build-isolation-package = ["package1", "package2"]
1392        "#
1393    )]
1394    pub no_build_isolation_package: Option<Vec<PackageName>>,
1395    /// Additional build dependencies for packages.
1396    ///
1397    /// This allows extending the PEP 517 build environment for the project's dependencies with
1398    /// additional packages. This is useful for packages that assume the presence of packages like
1399    /// `pip`, and do not declare them as build dependencies.
1400    #[option(
1401        default = "[]",
1402        value_type = "dict",
1403        example = r#"
1404            extra-build-dependencies = { pytest = ["setuptools"] }
1405        "#
1406    )]
1407    pub extra_build_dependencies: Option<ExtraBuildDependencies>,
1408    /// Extra environment variables to set when building certain packages.
1409    ///
1410    /// Environment variables will be added to the environment when building the
1411    /// specified packages.
1412    #[option(
1413        default = r#"{}"#,
1414        value_type = r#"dict[str, dict[str, str]]"#,
1415        example = r#"
1416            extra-build-variables = { flash-attn = { FLASH_ATTENTION_SKIP_CUDA_BUILD = "TRUE" } }
1417        "#
1418    )]
1419    pub extra_build_variables: Option<ExtraBuildVariables>,
1420    /// Validate the Python environment, to detect packages with missing dependencies and other
1421    /// issues.
1422    #[option(
1423        default = "false",
1424        value_type = "bool",
1425        example = r#"
1426            strict = true
1427        "#
1428    )]
1429    pub strict: Option<bool>,
1430    /// Include optional dependencies from the specified extra; may be provided more than once.
1431    ///
1432    /// Only applies to `pyproject.toml`, `setup.py`, and `setup.cfg` sources.
1433    #[option(
1434        default = "[]",
1435        value_type = "list[str]",
1436        example = r#"
1437            extra = ["dev", "docs"]
1438        "#
1439    )]
1440    pub extra: Option<Vec<ExtraName>>,
1441    /// Include all optional dependencies.
1442    ///
1443    /// Only applies to `pyproject.toml`, `setup.py`, and `setup.cfg` sources.
1444    #[option(
1445        default = "false",
1446        value_type = "bool",
1447        example = r#"
1448            all-extras = true
1449        "#
1450    )]
1451    pub all_extras: Option<bool>,
1452    /// Exclude the specified optional dependencies if `all-extras` is supplied.
1453    #[option(
1454        default = "[]",
1455        value_type = "list[str]",
1456        example = r#"
1457            all-extras = true
1458            no-extra = ["dev", "docs"]
1459        "#
1460    )]
1461    pub no_extra: Option<Vec<ExtraName>>,
1462    /// Ignore package dependencies, instead only add those packages explicitly listed
1463    /// on the command line to the resulting requirements file.
1464    #[option(
1465        default = "false",
1466        value_type = "bool",
1467        example = r#"
1468            no-deps = true
1469        "#
1470    )]
1471    pub no_deps: Option<bool>,
1472    /// Include the following dependency groups.
1473    #[option(
1474        default = "None",
1475        value_type = "list[str]",
1476        example = r#"
1477            group = ["dev", "docs"]
1478        "#
1479    )]
1480    pub group: Option<Vec<PipGroupName>>,
1481    /// Allow `uv pip sync` with empty requirements, which will clear the environment of all
1482    /// packages.
1483    #[option(
1484        default = "false",
1485        value_type = "bool",
1486        example = r#"
1487            allow-empty-requirements = true
1488        "#
1489    )]
1490    pub allow_empty_requirements: Option<bool>,
1491    /// The strategy to use when selecting between the different compatible versions for a given
1492    /// package requirement.
1493    ///
1494    /// By default, uv will use the latest compatible version of each package (`highest`).
1495    #[option(
1496        default = "\"highest\"",
1497        value_type = "str",
1498        example = r#"
1499            resolution = "lowest-direct"
1500        "#,
1501        possible_values = true
1502    )]
1503    pub resolution: Option<ResolutionMode>,
1504    /// The strategy to use when considering pre-release versions.
1505    ///
1506    /// By default, uv will accept pre-releases for packages that _only_ publish pre-releases,
1507    /// along with first-party requirements that contain an explicit pre-release marker in the
1508    /// declared specifiers (`if-necessary-or-explicit`).
1509    #[option(
1510        default = "\"if-necessary-or-explicit\"",
1511        value_type = "str",
1512        example = r#"
1513            prerelease = "allow"
1514        "#,
1515        possible_values = true
1516    )]
1517    pub prerelease: Option<PrereleaseMode>,
1518    /// The strategy to use when selecting multiple versions of a given package across Python
1519    /// versions and platforms.
1520    ///
1521    /// By default, uv will optimize for selecting the latest version of each package for each
1522    /// supported Python version (`requires-python`), while minimizing the number of selected
1523    /// versions across platforms.
1524    ///
1525    /// Under `fewest`, uv will minimize the number of selected versions for each package,
1526    /// preferring older versions that are compatible with a wider range of supported Python
1527    /// versions or platforms.
1528    #[option(
1529        default = "\"requires-python\"",
1530        value_type = "str",
1531        example = r#"
1532            fork-strategy = "fewest"
1533        "#,
1534        possible_values = true
1535    )]
1536    pub fork_strategy: Option<ForkStrategy>,
1537    /// Pre-defined static metadata for dependencies of the project (direct or transitive). When
1538    /// provided, enables the resolver to use the specified metadata instead of querying the
1539    /// registry or building the relevant package from source.
1540    ///
1541    /// Metadata should be provided in adherence with the [Metadata 2.3](https://packaging.python.org/en/latest/specifications/core-metadata/)
1542    /// standard, though only the following fields are respected:
1543    ///
1544    /// - `name`: The name of the package.
1545    /// - (Optional) `version`: The version of the package. If omitted, the metadata will be applied
1546    ///   to all versions of the package.
1547    /// - (Optional) `requires-dist`: The dependencies of the package (e.g., `werkzeug>=0.14`).
1548    /// - (Optional) `requires-python`: The Python version required by the package (e.g., `>=3.10`).
1549    /// - (Optional) `provides-extra`: The extras provided by the package.
1550    #[option(
1551        default = r#"[]"#,
1552        value_type = "list[dict]",
1553        example = r#"
1554            dependency-metadata = [
1555                { name = "flask", version = "1.0.0", requires-dist = ["werkzeug"], requires-python = ">=3.6" },
1556            ]
1557        "#
1558    )]
1559    pub dependency_metadata: Option<Vec<StaticMetadata>>,
1560    /// Write the requirements generated by `uv pip compile` to the given `requirements.txt` file.
1561    ///
1562    /// If the file already exists, the existing versions will be preferred when resolving
1563    /// dependencies, unless `--upgrade` is also specified.
1564    #[option(
1565        default = "None",
1566        value_type = "str",
1567        example = r#"
1568            output-file = "requirements.txt"
1569        "#
1570    )]
1571    pub output_file: Option<PathBuf>,
1572    /// Include extras in the output file.
1573    ///
1574    /// By default, uv strips extras, as any packages pulled in by the extras are already included
1575    /// as dependencies in the output file directly. Further, output files generated with
1576    /// `--no-strip-extras` cannot be used as constraints files in `install` and `sync` invocations.
1577    #[option(
1578        default = "false",
1579        value_type = "bool",
1580        example = r#"
1581            no-strip-extras = true
1582        "#
1583    )]
1584    pub no_strip_extras: Option<bool>,
1585    /// Include environment markers in the output file generated by `uv pip compile`.
1586    ///
1587    /// By default, uv strips environment markers, as the resolution generated by `compile` is
1588    /// only guaranteed to be correct for the target environment.
1589    #[option(
1590        default = "false",
1591        value_type = "bool",
1592        example = r#"
1593            no-strip-markers = true
1594        "#
1595    )]
1596    pub no_strip_markers: Option<bool>,
1597    /// Exclude comment annotations indicating the source of each package from the output file
1598    /// generated by `uv pip compile`.
1599    #[option(
1600        default = "false",
1601        value_type = "bool",
1602        example = r#"
1603            no-annotate = true
1604        "#
1605    )]
1606    pub no_annotate: Option<bool>,
1607    /// Exclude the comment header at the top of output file generated by `uv pip compile`.
1608    #[option(
1609        default = r#"false"#,
1610        value_type = "bool",
1611        example = r#"
1612            no-header = true
1613        "#
1614    )]
1615    pub no_header: Option<bool>,
1616    /// The header comment to include at the top of the output file generated by `uv pip compile`.
1617    ///
1618    /// Used to reflect custom build scripts and commands that wrap `uv pip compile`.
1619    #[option(
1620        default = "None",
1621        value_type = "str",
1622        example = r#"
1623            custom-compile-command = "./custom-uv-compile.sh"
1624        "#
1625    )]
1626    pub custom_compile_command: Option<String>,
1627    /// Include distribution hashes in the output file.
1628    #[option(
1629        default = "false",
1630        value_type = "bool",
1631        example = r#"
1632            generate-hashes = true
1633        "#
1634    )]
1635    pub generate_hashes: Option<bool>,
1636    /// Settings to pass to the [PEP 517](https://peps.python.org/pep-0517/) build backend,
1637    /// specified as `KEY=VALUE` pairs.
1638    #[option(
1639        default = "{}",
1640        value_type = "dict",
1641        example = r#"
1642            config-settings = { editable_mode = "compat" }
1643        "#
1644    )]
1645    pub config_settings: Option<ConfigSettings>,
1646    /// Settings to pass to the [PEP 517](https://peps.python.org/pep-0517/) build backend for specific packages,
1647    /// specified as `KEY=VALUE` pairs.
1648    #[option(
1649        default = "{}",
1650        value_type = "dict",
1651        example = r#"
1652            config-settings-package = { numpy = { editable_mode = "compat" } }
1653        "#
1654    )]
1655    pub config_settings_package: Option<PackageConfigSettings>,
1656    /// The minimum Python version that should be supported by the resolved requirements (e.g.,
1657    /// `3.8` or `3.8.17`).
1658    ///
1659    /// If a patch version is omitted, the minimum patch version is assumed. For example, `3.8` is
1660    /// mapped to `3.8.0`.
1661    #[option(
1662        default = "None",
1663        value_type = "str",
1664        example = r#"
1665            python-version = "3.8"
1666        "#
1667    )]
1668    pub python_version: Option<PythonVersion>,
1669    /// The platform for which requirements should be resolved.
1670    ///
1671    /// Represented as a "target triple", a string that describes the target platform in terms of
1672    /// its CPU, vendor, and operating system name, like `x86_64-unknown-linux-gnu` or
1673    /// `aarch64-apple-darwin`.
1674    #[option(
1675        default = "None",
1676        value_type = "str",
1677        example = r#"
1678            python-platform = "x86_64-unknown-linux-gnu"
1679        "#
1680    )]
1681    pub python_platform: Option<TargetTriple>,
1682    /// Perform a universal resolution, attempting to generate a single `requirements.txt` output
1683    /// file that is compatible with all operating systems, architectures, and Python
1684    /// implementations.
1685    ///
1686    /// In universal mode, the current Python version (or user-provided `--python-version`) will be
1687    /// treated as a lower bound. For example, `--universal --python-version 3.7` would produce a
1688    /// universal resolution for Python 3.7 and later.
1689    #[option(
1690        default = "false",
1691        value_type = "bool",
1692        example = r#"
1693            universal = true
1694        "#
1695    )]
1696    pub universal: Option<bool>,
1697    /// Limit candidate packages to those that were uploaded prior to a given point in time.
1698    ///
1699    /// Accepts a superset of [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) (e.g.,
1700    /// `2006-12-02T02:07:43Z`). A full timestamp is required to ensure that the resolver will
1701    /// behave consistently across timezones.
1702    #[option(
1703        default = "None",
1704        value_type = "str",
1705        example = r#"
1706            exclude-newer = "2006-12-02T02:07:43Z"
1707        "#
1708    )]
1709    pub exclude_newer: Option<ExcludeNewerValue>,
1710    /// Limit candidate packages for specific packages to those that were uploaded prior to the given date.
1711    ///
1712    /// Accepts package-date pairs in a dictionary format.
1713    #[option(
1714        default = "None",
1715        value_type = "dict",
1716        example = r#"
1717            exclude-newer-package = { tqdm = "2022-04-04T00:00:00Z" }
1718        "#
1719    )]
1720    pub exclude_newer_package: Option<ExcludeNewerPackage>,
1721    /// Specify a package to omit from the output resolution. Its dependencies will still be
1722    /// included in the resolution. Equivalent to pip-compile's `--unsafe-package` option.
1723    #[option(
1724        default = "[]",
1725        value_type = "list[str]",
1726        example = r#"
1727            no-emit-package = ["ruff"]
1728        "#
1729    )]
1730    pub no_emit_package: Option<Vec<PackageName>>,
1731    /// Include `--index-url` and `--extra-index-url` entries in the output file generated by `uv pip compile`.
1732    #[option(
1733        default = "false",
1734        value_type = "bool",
1735        example = r#"
1736            emit-index-url = true
1737        "#
1738    )]
1739    pub emit_index_url: Option<bool>,
1740    /// Include `--find-links` entries in the output file generated by `uv pip compile`.
1741    #[option(
1742        default = "false",
1743        value_type = "bool",
1744        example = r#"
1745            emit-find-links = true
1746        "#
1747    )]
1748    pub emit_find_links: Option<bool>,
1749    /// Include `--no-binary` and `--only-binary` entries in the output file generated by `uv pip compile`.
1750    #[option(
1751        default = "false",
1752        value_type = "bool",
1753        example = r#"
1754            emit-build-options = true
1755        "#
1756    )]
1757    pub emit_build_options: Option<bool>,
1758    /// Whether to emit a marker string indicating the conditions under which the set of pinned
1759    /// dependencies is valid.
1760    ///
1761    /// The pinned dependencies may be valid even when the marker expression is
1762    /// false, but when the expression is true, the requirements are known to
1763    /// be correct.
1764    #[option(
1765        default = "false",
1766        value_type = "bool",
1767        example = r#"
1768            emit-marker-expression = true
1769        "#
1770    )]
1771    pub emit_marker_expression: Option<bool>,
1772    /// Include comment annotations indicating the index used to resolve each package (e.g.,
1773    /// `# from https://pypi.org/simple`).
1774    #[option(
1775        default = "false",
1776        value_type = "bool",
1777        example = r#"
1778            emit-index-annotation = true
1779        "#
1780    )]
1781    pub emit_index_annotation: Option<bool>,
1782    /// The style of the annotation comments included in the output file, used to indicate the
1783    /// source of each package.
1784    #[option(
1785        default = "\"split\"",
1786        value_type = "str",
1787        example = r#"
1788            annotation-style = "line"
1789        "#,
1790        possible_values = true
1791    )]
1792    pub annotation_style: Option<AnnotationStyle>,
1793    /// The method to use when installing packages from the global cache.
1794    ///
1795    /// Defaults to `clone` (also known as Copy-on-Write) on macOS and Linux, and `hardlink` on
1796    /// Windows.
1797    ///
1798    /// WARNING: The use of symlink link mode is discouraged, as they create tight coupling between
1799    /// the cache and the target environment. For example, clearing the cache (`uv cache clean`)
1800    /// will break all installed packages by way of removing the underlying source files. Use
1801    /// symlinks with caution.
1802    #[option(
1803        default = "\"clone\" (macOS, Linux) or \"hardlink\" (Windows)",
1804        value_type = "str",
1805        example = r#"
1806            link-mode = "copy"
1807        "#,
1808        possible_values = true
1809    )]
1810    pub link_mode: Option<LinkMode>,
1811    /// Compile Python files to bytecode after installation.
1812    ///
1813    /// By default, uv does not compile Python (`.py`) files to bytecode (`__pycache__/*.pyc`);
1814    /// instead, compilation is performed lazily the first time a module is imported. For use-cases
1815    /// in which start time is critical, such as CLI applications and Docker containers, this option
1816    /// can be enabled to trade longer installation times for faster start times.
1817    ///
1818    /// When enabled, uv will process the entire site-packages directory (including packages that
1819    /// are not being modified by the current operation) for consistency. Like pip, it will also
1820    /// ignore errors.
1821    #[option(
1822        default = "false",
1823        value_type = "bool",
1824        example = r#"
1825            compile-bytecode = true
1826        "#
1827    )]
1828    pub compile_bytecode: Option<bool>,
1829    /// Require a matching hash for each requirement.
1830    ///
1831    /// Hash-checking mode is all or nothing. If enabled, _all_ requirements must be provided
1832    /// with a corresponding hash or set of hashes. Additionally, if enabled, _all_ requirements
1833    /// must either be pinned to exact versions (e.g., `==1.0.0`), or be specified via direct URL.
1834    ///
1835    /// Hash-checking mode introduces a number of additional constraints:
1836    ///
1837    /// - Git dependencies are not supported.
1838    /// - Editable installations are not supported.
1839    /// - Local dependencies are not supported, unless they point to a specific wheel (`.whl`) or
1840    ///   source archive (`.zip`, `.tar.gz`), as opposed to a directory.
1841    #[option(
1842        default = "false",
1843        value_type = "bool",
1844        example = r#"
1845            require-hashes = true
1846        "#
1847    )]
1848    pub require_hashes: Option<bool>,
1849    /// Validate any hashes provided in the requirements file.
1850    ///
1851    /// Unlike `--require-hashes`, `--verify-hashes` does not require that all requirements have
1852    /// hashes; instead, it will limit itself to verifying the hashes of those requirements that do
1853    /// include them.
1854    #[option(
1855        default = "true",
1856        value_type = "bool",
1857        example = r#"
1858            verify-hashes = true
1859        "#
1860    )]
1861    pub verify_hashes: Option<bool>,
1862    /// Ignore the `tool.uv.sources` table when resolving dependencies. Used to lock against the
1863    /// standards-compliant, publishable package metadata, as opposed to using any local or Git
1864    /// sources.
1865    #[option(
1866        default = "false",
1867        value_type = "bool",
1868        example = r#"
1869            no-sources = true
1870        "#
1871    )]
1872    pub no_sources: Option<bool>,
1873    /// Ignore `tool.uv.sources` for the specified packages.
1874    #[option(
1875        default = "[]",
1876        value_type = "list[str]",
1877        example = r#"
1878            no-sources-package = ["ruff"]
1879        "#
1880    )]
1881    pub no_sources_package: Option<Vec<PackageName>>,
1882    /// Allow package upgrades, ignoring pinned versions in any existing output file.
1883    #[option(
1884        default = "false",
1885        value_type = "bool",
1886        example = r#"
1887            upgrade = true
1888        "#
1889    )]
1890    pub upgrade: Option<bool>,
1891    /// Allow upgrades for a specific package, ignoring pinned versions in any existing output
1892    /// file.
1893    ///
1894    /// Accepts both standalone package names (`ruff`) and version specifiers (`ruff<0.5.0`).
1895    #[option(
1896        default = "[]",
1897        value_type = "list[str]",
1898        example = r#"
1899            upgrade-package = ["ruff"]
1900        "#
1901    )]
1902    pub upgrade_package: Option<Vec<Requirement<VerbatimParsedUrl>>>,
1903    /// Reinstall all packages, regardless of whether they're already installed. Implies `refresh`.
1904    #[option(
1905        default = "false",
1906        value_type = "bool",
1907        example = r#"
1908            reinstall = true
1909        "#
1910    )]
1911    pub reinstall: Option<bool>,
1912    /// Reinstall a specific package, regardless of whether it's already installed. Implies
1913    /// `refresh-package`.
1914    #[option(
1915        default = "[]",
1916        value_type = "list[str]",
1917        example = r#"
1918            reinstall-package = ["ruff"]
1919        "#
1920    )]
1921    pub reinstall_package: Option<Vec<PackageName>>,
1922    /// The backend to use when fetching packages in the PyTorch ecosystem.
1923    ///
1924    /// When set, uv will ignore the configured index URLs for packages in the PyTorch ecosystem,
1925    /// and will instead use the defined backend.
1926    ///
1927    /// For example, when set to `cpu`, uv will use the CPU-only PyTorch index; when set to `cu126`,
1928    /// uv will use the PyTorch index for CUDA 12.6.
1929    ///
1930    /// The `auto` mode will attempt to detect the appropriate PyTorch index based on the currently
1931    /// installed CUDA drivers.
1932    ///
1933    /// This setting is only respected by `uv pip` commands.
1934    ///
1935    /// This option is in preview and may change in any future release.
1936    #[option(
1937        default = "null",
1938        value_type = "str",
1939        example = r#"
1940            torch-backend = "auto"
1941        "#
1942    )]
1943    pub torch_backend: Option<TorchMode>,
1944}
1945
1946impl PipOptions {
1947    /// Resolve the [`PipOptions`] relative to the given root directory.
1948    pub fn relative_to(self, root_dir: &Path) -> Result<Self, IndexUrlError> {
1949        Ok(Self {
1950            index: self
1951                .index
1952                .map(|index| {
1953                    index
1954                        .into_iter()
1955                        .map(|index| index.relative_to(root_dir))
1956                        .collect::<Result<Vec<_>, _>>()
1957                })
1958                .transpose()?,
1959            index_url: self
1960                .index_url
1961                .map(|index_url| index_url.relative_to(root_dir))
1962                .transpose()?,
1963            extra_index_url: self
1964                .extra_index_url
1965                .map(|extra_index_url| {
1966                    extra_index_url
1967                        .into_iter()
1968                        .map(|extra_index_url| extra_index_url.relative_to(root_dir))
1969                        .collect::<Result<Vec<_>, _>>()
1970                })
1971                .transpose()?,
1972            find_links: self
1973                .find_links
1974                .map(|find_links| {
1975                    find_links
1976                        .into_iter()
1977                        .map(|find_link| find_link.relative_to(root_dir))
1978                        .collect::<Result<Vec<_>, _>>()
1979                })
1980                .transpose()?,
1981            ..self
1982        })
1983    }
1984}
1985
1986impl From<ResolverInstallerSchema> for ResolverOptions {
1987    fn from(value: ResolverInstallerSchema) -> Self {
1988        Self {
1989            index: value.index,
1990            index_url: value.index_url,
1991            extra_index_url: value.extra_index_url,
1992            no_index: value.no_index,
1993            find_links: value.find_links,
1994            index_strategy: value.index_strategy,
1995            keyring_provider: value.keyring_provider,
1996            resolution: value.resolution,
1997            prerelease: value.prerelease,
1998            fork_strategy: value.fork_strategy,
1999            dependency_metadata: value.dependency_metadata,
2000            config_settings: value.config_settings,
2001            config_settings_package: value.config_settings_package,
2002            exclude_newer: ExcludeNewer::from_args(
2003                value.exclude_newer,
2004                value
2005                    .exclude_newer_package
2006                    .unwrap_or_default()
2007                    .into_iter()
2008                    .map(Into::into)
2009                    .collect(),
2010            ),
2011            link_mode: value.link_mode,
2012            upgrade: Upgrade::from_args(
2013                value.upgrade,
2014                value
2015                    .upgrade_package
2016                    .into_iter()
2017                    .flatten()
2018                    .map(Into::into)
2019                    .collect(),
2020            ),
2021            no_build: value.no_build,
2022            no_build_package: value.no_build_package,
2023            no_binary: value.no_binary,
2024            no_binary_package: value.no_binary_package,
2025            build_isolation: BuildIsolation::from_args(
2026                value.no_build_isolation,
2027                value.no_build_isolation_package.unwrap_or_default(),
2028            ),
2029            extra_build_dependencies: value.extra_build_dependencies,
2030            extra_build_variables: value.extra_build_variables,
2031            no_sources: value.no_sources,
2032            no_sources_package: value.no_sources_package,
2033            torch_backend: value.torch_backend,
2034        }
2035    }
2036}
2037
2038impl From<ResolverInstallerSchema> for InstallerOptions {
2039    fn from(value: ResolverInstallerSchema) -> Self {
2040        Self {
2041            index: value.index,
2042            index_url: value.index_url,
2043            extra_index_url: value.extra_index_url,
2044            no_index: value.no_index,
2045            find_links: value.find_links,
2046            index_strategy: value.index_strategy,
2047            keyring_provider: value.keyring_provider,
2048            config_settings: value.config_settings,
2049            exclude_newer: ExcludeNewer::from_args(
2050                value.exclude_newer,
2051                value
2052                    .exclude_newer_package
2053                    .unwrap_or_default()
2054                    .into_iter()
2055                    .map(Into::into)
2056                    .collect(),
2057            )
2058            .global,
2059            link_mode: value.link_mode,
2060            compile_bytecode: value.compile_bytecode,
2061            reinstall: Reinstall::from_args(
2062                value.reinstall,
2063                value.reinstall_package.unwrap_or_default(),
2064            ),
2065            build_isolation: BuildIsolation::from_args(
2066                value.no_build_isolation,
2067                value.no_build_isolation_package.unwrap_or_default(),
2068            ),
2069            no_build: value.no_build,
2070            no_build_package: value.no_build_package,
2071            no_binary: value.no_binary,
2072            no_binary_package: value.no_binary_package,
2073            no_sources: value.no_sources,
2074            no_sources_package: value.no_sources_package,
2075        }
2076    }
2077}
2078
2079/// The options persisted alongside an installed tool.
2080///
2081/// A mirror of [`ResolverInstallerSchema`], without upgrades and reinstalls, which shouldn't be
2082/// persisted in a tool receipt.
2083#[derive(
2084    Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, CombineOptions, OptionsMetadata,
2085)]
2086#[serde(deny_unknown_fields, rename_all = "kebab-case")]
2087#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2088pub struct ToolOptions {
2089    pub index: Option<Vec<Index>>,
2090    pub index_url: Option<PipIndex>,
2091    pub extra_index_url: Option<Vec<PipExtraIndex>>,
2092    pub no_index: Option<bool>,
2093    pub find_links: Option<Vec<PipFindLinks>>,
2094    pub index_strategy: Option<IndexStrategy>,
2095    pub keyring_provider: Option<KeyringProviderType>,
2096    pub resolution: Option<ResolutionMode>,
2097    pub prerelease: Option<PrereleaseMode>,
2098    pub fork_strategy: Option<ForkStrategy>,
2099    pub dependency_metadata: Option<Vec<StaticMetadata>>,
2100    pub config_settings: Option<ConfigSettings>,
2101    pub config_settings_package: Option<PackageConfigSettings>,
2102    pub build_isolation: Option<BuildIsolation>,
2103    pub extra_build_dependencies: Option<ExtraBuildDependencies>,
2104    pub extra_build_variables: Option<ExtraBuildVariables>,
2105    pub exclude_newer: Option<ExcludeNewerValue>,
2106    pub exclude_newer_package: Option<ExcludeNewerPackage>,
2107    pub link_mode: Option<LinkMode>,
2108    pub compile_bytecode: Option<bool>,
2109    pub no_sources: Option<bool>,
2110    pub no_sources_package: Option<Vec<PackageName>>,
2111    pub no_build: Option<bool>,
2112    pub no_build_package: Option<Vec<PackageName>>,
2113    pub no_binary: Option<bool>,
2114    pub no_binary_package: Option<Vec<PackageName>>,
2115    pub torch_backend: Option<TorchMode>,
2116}
2117
2118impl From<ResolverInstallerOptions> for ToolOptions {
2119    fn from(value: ResolverInstallerOptions) -> Self {
2120        Self {
2121            index: value.index.map(|indexes| {
2122                indexes
2123                    .into_iter()
2124                    .map(Index::with_promoted_auth_policy)
2125                    .collect()
2126            }),
2127            index_url: value.index_url,
2128            extra_index_url: value.extra_index_url,
2129            no_index: value.no_index,
2130            find_links: value.find_links,
2131            index_strategy: value.index_strategy,
2132            keyring_provider: value.keyring_provider,
2133            resolution: value.resolution,
2134            prerelease: value.prerelease,
2135            fork_strategy: value.fork_strategy,
2136            dependency_metadata: value.dependency_metadata,
2137            config_settings: value.config_settings,
2138            config_settings_package: value.config_settings_package,
2139            build_isolation: value.build_isolation,
2140            extra_build_dependencies: value.extra_build_dependencies,
2141            extra_build_variables: value.extra_build_variables,
2142            exclude_newer: value.exclude_newer,
2143            exclude_newer_package: value.exclude_newer_package,
2144            link_mode: value.link_mode,
2145            compile_bytecode: value.compile_bytecode,
2146            no_sources: value.no_sources,
2147            no_sources_package: value.no_sources_package,
2148            no_build: value.no_build,
2149            no_build_package: value.no_build_package,
2150            no_binary: value.no_binary,
2151            no_binary_package: value.no_binary_package,
2152            torch_backend: value.torch_backend,
2153        }
2154    }
2155}
2156
2157impl From<ToolOptions> for ResolverInstallerOptions {
2158    fn from(value: ToolOptions) -> Self {
2159        Self {
2160            index: value.index,
2161            index_url: value.index_url,
2162            extra_index_url: value.extra_index_url,
2163            no_index: value.no_index,
2164            find_links: value.find_links,
2165            index_strategy: value.index_strategy,
2166            keyring_provider: value.keyring_provider,
2167            resolution: value.resolution,
2168            prerelease: value.prerelease,
2169            fork_strategy: value.fork_strategy,
2170            dependency_metadata: value.dependency_metadata,
2171            config_settings: value.config_settings,
2172            config_settings_package: value.config_settings_package,
2173            build_isolation: value.build_isolation,
2174            extra_build_dependencies: value.extra_build_dependencies,
2175            extra_build_variables: value.extra_build_variables,
2176            exclude_newer: value.exclude_newer,
2177            exclude_newer_package: value.exclude_newer_package,
2178            link_mode: value.link_mode,
2179            compile_bytecode: value.compile_bytecode,
2180            no_sources: value.no_sources,
2181            no_sources_package: value.no_sources_package,
2182            upgrade: None,
2183            reinstall: None,
2184            no_build: value.no_build,
2185            no_build_package: value.no_build_package,
2186            no_binary: value.no_binary,
2187            no_binary_package: value.no_binary_package,
2188            torch_backend: value.torch_backend,
2189        }
2190    }
2191}
2192
2193/// Like [`Options]`, but with any `#[serde(flatten)]` fields inlined. This leads to far, far
2194/// better error messages when deserializing.
2195#[derive(Debug, Clone, Default, Deserialize)]
2196#[serde(rename_all = "kebab-case", deny_unknown_fields)]
2197pub struct OptionsWire {
2198    // #[serde(flatten)]
2199    // globals: GlobalOptions
2200    required_version: Option<RequiredVersion>,
2201    system_certs: Option<bool>,
2202    native_tls: Option<bool>,
2203    offline: Option<bool>,
2204    no_cache: Option<bool>,
2205    cache_dir: Option<PathBuf>,
2206    preview: Option<bool>,
2207    python_preference: Option<PythonPreference>,
2208    python_downloads: Option<PythonDownloads>,
2209    concurrent_downloads: Option<NonZeroUsize>,
2210    concurrent_builds: Option<NonZeroUsize>,
2211    concurrent_installs: Option<NonZeroUsize>,
2212
2213    // #[serde(flatten)]
2214    // top_level: ResolverInstallerOptions
2215    index: Option<Vec<Index>>,
2216    index_url: Option<PipIndex>,
2217    extra_index_url: Option<Vec<PipExtraIndex>>,
2218    no_index: Option<bool>,
2219    find_links: Option<Vec<PipFindLinks>>,
2220    index_strategy: Option<IndexStrategy>,
2221    keyring_provider: Option<KeyringProviderType>,
2222    http_proxy: Option<ProxyUrl>,
2223    https_proxy: Option<ProxyUrl>,
2224    no_proxy: Option<Vec<String>>,
2225    allow_insecure_host: Option<Vec<TrustedHost>>,
2226    resolution: Option<ResolutionMode>,
2227    prerelease: Option<PrereleaseMode>,
2228    fork_strategy: Option<ForkStrategy>,
2229    dependency_metadata: Option<Vec<StaticMetadata>>,
2230    config_settings: Option<ConfigSettings>,
2231    config_settings_package: Option<PackageConfigSettings>,
2232    no_build_isolation: Option<bool>,
2233    no_build_isolation_package: Option<Vec<PackageName>>,
2234    extra_build_dependencies: Option<ExtraBuildDependencies>,
2235    extra_build_variables: Option<ExtraBuildVariables>,
2236    exclude_newer: Option<ExcludeNewerValue>,
2237    exclude_newer_package: Option<ExcludeNewerPackage>,
2238    link_mode: Option<LinkMode>,
2239    compile_bytecode: Option<bool>,
2240    no_sources: Option<bool>,
2241    no_sources_package: Option<Vec<PackageName>>,
2242    upgrade: Option<bool>,
2243    upgrade_package: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2244    reinstall: Option<bool>,
2245    reinstall_package: Option<Vec<PackageName>>,
2246    no_build: Option<bool>,
2247    no_build_package: Option<Vec<PackageName>>,
2248    no_binary: Option<bool>,
2249    no_binary_package: Option<Vec<PackageName>>,
2250    torch_backend: Option<TorchMode>,
2251
2252    // #[serde(flatten)]
2253    // install_mirror: PythonInstallMirrors,
2254    python_install_mirror: Option<String>,
2255    pypy_install_mirror: Option<String>,
2256    python_downloads_json_url: Option<String>,
2257
2258    // #[serde(flatten)]
2259    // publish: PublishOptions
2260    publish_url: Option<DisplaySafeUrl>,
2261    trusted_publishing: Option<TrustedPublishing>,
2262    check_url: Option<IndexUrl>,
2263
2264    // #[serde(flatten)]
2265    // add: AddOptions
2266    add_bounds: Option<AddBoundsKind>,
2267
2268    pip: Option<PipOptions>,
2269    cache_keys: Option<Vec<CacheKey>>,
2270
2271    // NOTE(charlie): These fields are shared with `ToolUv` in
2272    // `crates/uv-workspace/src/pyproject.rs`. The documentation lives on that struct.
2273    // They're respected in both `pyproject.toml` and `uv.toml` files.
2274    override_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2275    exclude_dependencies: Option<Vec<PackageName>>,
2276    constraint_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2277    build_constraint_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2278    environments: Option<SupportedEnvironments>,
2279    required_environments: Option<SupportedEnvironments>,
2280
2281    // NOTE(charlie): These fields should be kept in-sync with `ToolUv` in
2282    // `crates/uv-workspace/src/pyproject.rs`. The documentation lives on that struct.
2283    // They're only respected in `pyproject.toml` files, and should be rejected in `uv.toml` files.
2284    conflicts: Option<serde::de::IgnoredAny>,
2285    workspace: Option<serde::de::IgnoredAny>,
2286    sources: Option<serde::de::IgnoredAny>,
2287    managed: Option<serde::de::IgnoredAny>,
2288    r#package: Option<serde::de::IgnoredAny>,
2289    default_groups: Option<serde::de::IgnoredAny>,
2290    dependency_groups: Option<serde::de::IgnoredAny>,
2291    dev_dependencies: Option<serde::de::IgnoredAny>,
2292
2293    // Build backend
2294    build_backend: Option<serde::de::IgnoredAny>,
2295}
2296
2297impl From<OptionsWire> for Options {
2298    #[allow(deprecated)]
2299    fn from(value: OptionsWire) -> Self {
2300        let OptionsWire {
2301            required_version,
2302            system_certs,
2303            native_tls,
2304            offline,
2305            no_cache,
2306            cache_dir,
2307            preview,
2308            python_preference,
2309            python_downloads,
2310            python_install_mirror,
2311            pypy_install_mirror,
2312            python_downloads_json_url,
2313            concurrent_downloads,
2314            concurrent_builds,
2315            concurrent_installs,
2316            index,
2317            index_url,
2318            extra_index_url,
2319            no_index,
2320            find_links,
2321            index_strategy,
2322            keyring_provider,
2323            http_proxy,
2324            https_proxy,
2325            no_proxy,
2326            allow_insecure_host,
2327            resolution,
2328            prerelease,
2329            fork_strategy,
2330            dependency_metadata,
2331            config_settings,
2332            config_settings_package,
2333            no_build_isolation,
2334            no_build_isolation_package,
2335            exclude_newer,
2336            exclude_newer_package,
2337            link_mode,
2338            compile_bytecode,
2339            no_sources,
2340            no_sources_package,
2341            upgrade,
2342            upgrade_package,
2343            reinstall,
2344            reinstall_package,
2345            no_build,
2346            no_build_package,
2347            no_binary,
2348            no_binary_package,
2349            torch_backend,
2350            pip,
2351            cache_keys,
2352            override_dependencies,
2353            exclude_dependencies,
2354            constraint_dependencies,
2355            build_constraint_dependencies,
2356            environments,
2357            required_environments,
2358            conflicts,
2359            publish_url,
2360            trusted_publishing,
2361            check_url,
2362            workspace,
2363            sources,
2364            default_groups,
2365            dependency_groups,
2366            extra_build_dependencies,
2367            extra_build_variables,
2368            dev_dependencies,
2369            managed,
2370            package,
2371            add_bounds: bounds,
2372            // Used by the build backend
2373            build_backend,
2374        } = value;
2375
2376        Self {
2377            globals: GlobalOptions {
2378                required_version,
2379                system_certs,
2380                native_tls,
2381                offline,
2382                no_cache,
2383                cache_dir,
2384                preview,
2385                python_preference,
2386                python_downloads,
2387                concurrent_downloads,
2388                concurrent_builds,
2389                concurrent_installs,
2390                http_proxy,
2391                https_proxy,
2392                no_proxy,
2393                // Used twice for backwards compatibility
2394                allow_insecure_host: allow_insecure_host.clone(),
2395            },
2396            top_level: ResolverInstallerSchema {
2397                index,
2398                index_url,
2399                extra_index_url,
2400                no_index,
2401                find_links,
2402                index_strategy,
2403                keyring_provider,
2404                resolution,
2405                prerelease,
2406                fork_strategy,
2407                dependency_metadata,
2408                config_settings,
2409                config_settings_package,
2410                no_build_isolation,
2411                no_build_isolation_package,
2412                extra_build_dependencies,
2413                extra_build_variables,
2414                exclude_newer,
2415                exclude_newer_package,
2416                link_mode,
2417                compile_bytecode,
2418                no_sources,
2419                no_sources_package,
2420                upgrade,
2421                upgrade_package,
2422                reinstall,
2423                reinstall_package,
2424                no_build,
2425                no_build_package,
2426                no_binary,
2427                no_binary_package,
2428                torch_backend,
2429            },
2430            pip,
2431            cache_keys,
2432            build_backend,
2433            override_dependencies,
2434            exclude_dependencies,
2435            constraint_dependencies,
2436            build_constraint_dependencies,
2437            environments,
2438            required_environments,
2439            install_mirrors: PythonInstallMirrors {
2440                python_install_mirror,
2441                pypy_install_mirror,
2442                python_downloads_json_url,
2443            },
2444            conflicts,
2445            publish: PublishOptions {
2446                publish_url,
2447                trusted_publishing,
2448                check_url,
2449            },
2450            add: AddOptions { add_bounds: bounds },
2451            workspace,
2452            sources,
2453            dev_dependencies,
2454            default_groups,
2455            dependency_groups,
2456            managed,
2457            package,
2458        }
2459    }
2460}
2461
2462#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
2463#[serde(rename_all = "kebab-case")]
2464#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2465pub struct PublishOptions {
2466    /// The URL for publishing packages to the Python package index (by default:
2467    /// <https://upload.pypi.org/legacy/>).
2468    #[option(
2469        default = "\"https://upload.pypi.org/legacy/\"",
2470        value_type = "str",
2471        example = r#"
2472            publish-url = "https://test.pypi.org/legacy/"
2473        "#
2474    )]
2475    pub publish_url: Option<DisplaySafeUrl>,
2476
2477    /// Configure trusted publishing.
2478    ///
2479    /// By default, uv checks for trusted publishing when running in a supported environment, but
2480    /// ignores it if it isn't configured.
2481    ///
2482    /// uv's supported environments for trusted publishing include GitHub Actions and GitLab CI/CD.
2483    #[option(
2484        default = "automatic",
2485        value_type = "str",
2486        example = r#"
2487            trusted-publishing = "always"
2488        "#
2489    )]
2490    pub trusted_publishing: Option<TrustedPublishing>,
2491
2492    /// Check an index URL for existing files to skip duplicate uploads.
2493    ///
2494    /// This option allows retrying publishing that failed after only some, but not all files have
2495    /// been uploaded, and handles error due to parallel uploads of the same file.
2496    ///
2497    /// Before uploading, the index is checked. If the exact same file already exists in the index,
2498    /// the file will not be uploaded. If an error occurred during the upload, the index is checked
2499    /// again, to handle cases where the identical file was uploaded twice in parallel.
2500    ///
2501    /// The exact behavior will vary based on the index. When uploading to PyPI, uploading the same
2502    /// file succeeds even without `--check-url`, while most other indexes error.
2503    ///
2504    /// The index must provide one of the supported hashes (SHA-256, SHA-384, or SHA-512).
2505    #[option(
2506        default = "None",
2507        value_type = "str",
2508        example = r#"
2509            check-url = "https://test.pypi.org/simple"
2510        "#
2511    )]
2512    pub check_url: Option<IndexUrl>,
2513}
2514
2515#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
2516#[serde(rename_all = "kebab-case")]
2517#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2518pub struct AddOptions {
2519    /// The default version specifier when adding a dependency.
2520    ///
2521    /// When adding a dependency to the project, if no constraint or URL is provided, a constraint
2522    /// is added based on the latest compatible version of the package. By default, a lower bound
2523    /// constraint is used, e.g., `>=1.2.3`.
2524    ///
2525    /// When `--frozen` is provided, no resolution is performed, and dependencies are always added
2526    /// without constraints.
2527    ///
2528    /// This option is in preview and may change in any future release.
2529    #[option(
2530        default = "\"lower\"",
2531        value_type = "str",
2532        example = r#"
2533            add-bounds = "major"
2534        "#,
2535        possible_values = true
2536    )]
2537    pub add_bounds: Option<AddBoundsKind>,
2538}