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