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