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