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