1#[cfg(feature = "schemars")]
2use std::borrow::Cow;
3use std::{fmt::Debug, num::NonZeroUsize, path::Path, path::PathBuf};
4
5use serde::{Deserialize, Serialize};
6
7use uv_cache_info::CacheKey;
8use uv_configuration::{
9 BuildIsolation, IndexStrategy, KeyringProviderType, PackageNameSpecifier, ProxyUrl, Reinstall,
10 RequiredVersion, TargetTriple, TrustedHost, TrustedPublishing, Upgrade,
11};
12use uv_distribution_types::{
13 ConfigSettings, ExtraBuildVariables, Index, IndexUrl, IndexUrlError, Origin,
14 PackageConfigSettings, PipExtraIndex, PipFindLinks, PipIndex, StaticMetadata,
15};
16use uv_install_wheel::LinkMode;
17use uv_macros::{CombineOptions, OptionsMetadata};
18use uv_normalize::{ExtraName, PackageName, PipGroupName};
19use uv_pep508::Requirement;
20use uv_preview::{MaybePreviewFeature, Preview};
21use uv_pypi_types::{SupportedEnvironments, VerbatimParsedUrl};
22use uv_python::{PythonDownloads, PythonPreference, PythonVersion};
23use uv_redacted::DisplaySafeUrl;
24use uv_resolver::{
25 AnnotationStyle, ExcludeNewerOverride, ExcludeNewerPackage, ExcludeNewerSpan,
26 ExcludeNewerValue, ForkStrategy, PrereleaseMode, ResolutionMode,
27 serialize_exclude_newer_package_with_spans,
28};
29use uv_torch::TorchMode;
30use uv_workspace::pyproject::ExtraBuildDependencies;
31use uv_workspace::pyproject_mut::AddBoundsKind;
32
33#[allow(dead_code)]
35#[derive(Debug, Clone, Default, Deserialize)]
36pub(crate) struct PyProjectToml {
37 pub(crate) tool: Option<Tools>,
38}
39
40#[allow(dead_code)]
42#[derive(Debug, Clone, Default, Deserialize)]
43pub(crate) struct Tools {
44 pub(crate) uv: Option<Options>,
45}
46
47#[derive(Debug, Clone, Default, Deserialize)]
49pub(crate) struct PyProjectRequiredVersionToml {
50 pub(crate) tool: Option<RequiredVersionTools>,
51}
52
53#[derive(Debug, Clone, Default, Deserialize)]
55pub(crate) struct RequiredVersionTools {
56 pub(crate) uv: Option<RequiredVersionOptions>,
57}
58
59#[derive(Debug, Clone, Default, Deserialize)]
61#[serde(rename_all = "kebab-case")]
62pub(crate) struct RequiredVersionOptions {
63 pub(crate) required_version: Option<RequiredVersion>,
64}
65
66#[derive(Debug, Clone, Default, Deserialize)]
68#[serde(rename_all = "kebab-case")]
69pub(crate) struct UvRequiredVersionToml {
70 pub(crate) required_version: Option<RequiredVersion>,
71}
72
73#[allow(dead_code)]
75#[derive(Debug, Clone, Default, Deserialize, CombineOptions, OptionsMetadata)]
76#[serde(try_from = "OptionsWire", rename_all = "kebab-case")]
77#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
78#[cfg_attr(feature = "schemars", schemars(!try_from))]
79pub struct Options {
80 #[serde(flatten)]
81 pub globals: GlobalOptions,
82
83 #[serde(flatten)]
84 pub top_level: ResolverInstallerSchema,
85
86 #[serde(flatten)]
87 pub install_mirrors: PythonInstallMirrors,
88
89 #[serde(flatten)]
90 pub publish: PublishOptions,
91
92 #[serde(flatten)]
93 pub add: AddOptions,
94
95 #[option_group]
96 pub audit: Option<AuditOptions>,
97
98 #[option_group]
99 pub pip: Option<PipOptions>,
100
101 #[option(
137 default = r#"[{ file = "pyproject.toml" }, { file = "setup.py" }, { file = "setup.cfg" }]"#,
138 value_type = "list[dict]",
139 example = r#"
140 cache-keys = [{ file = "pyproject.toml" }, { file = "requirements.txt" }, { git = { commit = true } }]
141 "#
142 )]
143 pub cache_keys: Option<Vec<CacheKey>>,
144
145 #[cfg_attr(feature = "schemars", schemars(skip))]
149 pub override_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
150
151 #[cfg_attr(feature = "schemars", schemars(skip))]
152 pub exclude_dependencies: Option<Vec<uv_normalize::PackageName>>,
153
154 #[cfg_attr(feature = "schemars", schemars(skip))]
155 pub constraint_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
156
157 #[cfg_attr(feature = "schemars", schemars(skip))]
158 pub build_constraint_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
159
160 #[cfg_attr(feature = "schemars", schemars(skip))]
161 pub environments: Option<SupportedEnvironments>,
162
163 #[cfg_attr(feature = "schemars", schemars(skip))]
164 pub required_environments: Option<SupportedEnvironments>,
165
166 #[cfg_attr(feature = "schemars", schemars(skip))]
170 pub(crate) conflicts: Option<serde::de::IgnoredAny>,
171
172 #[cfg_attr(feature = "schemars", schemars(skip))]
173 pub(crate) workspace: Option<serde::de::IgnoredAny>,
174
175 #[cfg_attr(feature = "schemars", schemars(skip))]
176 pub(crate) sources: Option<serde::de::IgnoredAny>,
177
178 #[cfg_attr(feature = "schemars", schemars(skip))]
179 pub(crate) dev_dependencies: Option<serde::de::IgnoredAny>,
180
181 #[cfg_attr(feature = "schemars", schemars(skip))]
182 pub(crate) default_groups: Option<serde::de::IgnoredAny>,
183
184 #[cfg_attr(feature = "schemars", schemars(skip))]
185 pub(crate) dependency_groups: Option<serde::de::IgnoredAny>,
186
187 #[cfg_attr(feature = "schemars", schemars(skip))]
188 pub(crate) managed: Option<serde::de::IgnoredAny>,
189
190 #[cfg_attr(feature = "schemars", schemars(skip))]
191 pub(crate) r#package: Option<serde::de::IgnoredAny>,
192
193 #[cfg_attr(feature = "schemars", schemars(skip))]
194 pub(crate) build_backend: Option<serde::de::IgnoredAny>,
195}
196
197impl Options {
198 pub fn simple(globals: GlobalOptions, top_level: ResolverInstallerSchema) -> Self {
200 Self {
201 globals,
202 top_level,
203 ..Default::default()
204 }
205 }
206
207 #[must_use]
209 pub(crate) fn with_origin(mut self, origin: Origin) -> Self {
210 if let Some(indexes) = &mut self.top_level.index {
211 for index in indexes {
212 index.origin.get_or_insert(origin);
213 }
214 }
215 if let Some(index_url) = &mut self.top_level.index_url {
216 index_url.try_set_origin(origin);
217 }
218 if let Some(extra_index_urls) = &mut self.top_level.extra_index_url {
219 for index_url in extra_index_urls {
220 index_url.try_set_origin(origin);
221 }
222 }
223 if let Some(pip) = &mut self.pip {
224 if let Some(indexes) = &mut pip.index {
225 for index in indexes {
226 index.origin.get_or_insert(origin);
227 }
228 }
229 if let Some(index_url) = &mut pip.index_url {
230 index_url.try_set_origin(origin);
231 }
232 if let Some(extra_index_urls) = &mut pip.extra_index_url {
233 for index_url in extra_index_urls {
234 index_url.try_set_origin(origin);
235 }
236 }
237 }
238 self
239 }
240
241 pub(crate) fn relative_to(self, root_dir: &Path) -> Result<Self, IndexUrlError> {
243 Ok(Self {
244 top_level: self.top_level.relative_to(root_dir)?,
245 pip: self.pip.map(|pip| pip.relative_to(root_dir)).transpose()?,
246 ..self
247 })
248 }
249}
250
251#[derive(Debug, Clone, Default, Deserialize, CombineOptions, OptionsMetadata)]
253#[serde(try_from = "GlobalOptionsWire", rename_all = "kebab-case")]
254#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
255#[cfg_attr(feature = "schemars", schemars(!try_from))]
256pub struct GlobalOptions {
257 #[option(
264 default = "null",
265 value_type = "str",
266 example = r#"
267 required-version = ">=0.5.0"
268 "#
269 )]
270 pub required_version: Option<RequiredVersion>,
271 #[option(
276 default = "false",
277 value_type = "bool",
278 uv_toml_only = true,
279 example = r#"
280 system-certs = true
281 "#
282 )]
283 pub system_certs: Option<bool>,
284 #[deprecated(note = "use `system-certs` instead")]
291 #[option(
292 default = "false",
293 value_type = "bool",
294 uv_toml_only = true,
295 example = r#"
296 native-tls = true
297 "#
298 )]
299 pub native_tls: Option<bool>,
300 #[option(
302 default = "false",
303 value_type = "bool",
304 example = r#"
305 offline = true
306 "#
307 )]
308 pub offline: Option<bool>,
309 #[option(
312 default = "false",
313 value_type = "bool",
314 example = r#"
315 no-cache = true
316 "#
317 )]
318 pub no_cache: Option<bool>,
319 #[option(
324 default = "None",
325 value_type = "str",
326 uv_toml_only = true,
327 example = r#"
328 cache-dir = "./.uv_cache"
329 "#
330 )]
331 pub cache_dir: Option<PathBuf>,
332
333 #[serde(flatten)]
335 pub preview: Option<PreviewOption>,
336
337 #[option(
340 default = "\"managed\"",
341 value_type = "str",
342 example = r#"
343 python-preference = "managed"
344 "#,
345 possible_values = true
346 )]
347 pub python_preference: Option<PythonPreference>,
348 #[option(
350 default = "\"automatic\"",
351 value_type = "str",
352 example = r#"
353 python-downloads = "manual"
354 "#,
355 possible_values = true
356 )]
357 pub python_downloads: Option<PythonDownloads>,
358 #[option(
361 default = "50",
362 value_type = "int",
363 example = r#"
364 concurrent-downloads = 4
365 "#
366 )]
367 pub concurrent_downloads: Option<NonZeroUsize>,
368 #[option(
373 default = "None",
374 value_type = "int",
375 example = r#"
376 concurrent-builds = 4
377 "#
378 )]
379 pub concurrent_builds: Option<NonZeroUsize>,
380 #[option(
384 default = "None",
385 value_type = "int",
386 example = r#"
387 concurrent-installs = 4
388 "#
389 )]
390 pub concurrent_installs: Option<NonZeroUsize>,
391 #[option(
393 default = "None",
394 value_type = "str",
395 uv_toml_only = true,
396 example = r#"
397 http-proxy = "http://proxy.example.com"
398 "#
399 )]
400 pub http_proxy: Option<ProxyUrl>,
401 #[option(
403 default = "None",
404 value_type = "str",
405 uv_toml_only = true,
406 example = r#"
407 https-proxy = "https://proxy.example.com"
408 "#
409 )]
410 pub https_proxy: Option<ProxyUrl>,
411 #[option(
413 default = "None",
414 value_type = "list[str]",
415 uv_toml_only = true,
416 example = r#"
417 no-proxy = ["localhost", "127.0.0.1"]
418 "#
419 )]
420 pub no_proxy: Option<Vec<String>>,
421 #[option(
430 default = "[]",
431 value_type = "list[str]",
432 example = r#"
433 allow-insecure-host = ["localhost:8080"]
434 "#
435 )]
436 pub allow_insecure_host: Option<Vec<TrustedHost>>,
437}
438
439#[derive(Debug, Clone, Default, Deserialize)]
442#[serde(rename_all = "kebab-case")]
443struct GlobalOptionsWire {
444 required_version: Option<RequiredVersion>,
445 system_certs: Option<bool>,
446 native_tls: Option<bool>,
447 offline: Option<bool>,
448 no_cache: Option<bool>,
449 cache_dir: Option<PathBuf>,
450
451 preview: Option<bool>,
452 preview_features: Option<PreviewFeaturesOption>,
453
454 python_preference: Option<PythonPreference>,
455 python_downloads: Option<PythonDownloads>,
456 concurrent_downloads: Option<NonZeroUsize>,
457 concurrent_builds: Option<NonZeroUsize>,
458 concurrent_installs: Option<NonZeroUsize>,
459 http_proxy: Option<ProxyUrl>,
460 https_proxy: Option<ProxyUrl>,
461 no_proxy: Option<Vec<String>>,
462 allow_insecure_host: Option<Vec<TrustedHost>>,
463}
464
465impl TryFrom<GlobalOptionsWire> for GlobalOptions {
466 type Error = &'static str;
467
468 #[allow(deprecated)]
469 fn try_from(value: GlobalOptionsWire) -> Result<Self, Self::Error> {
470 let GlobalOptionsWire {
471 required_version,
472 system_certs,
473 native_tls,
474 offline,
475 no_cache,
476 cache_dir,
477 preview,
478 preview_features,
479 python_preference,
480 python_downloads,
481 concurrent_downloads,
482 concurrent_builds,
483 concurrent_installs,
484 http_proxy,
485 https_proxy,
486 no_proxy,
487 allow_insecure_host,
488 } = value;
489
490 Ok(Self {
491 required_version,
492 system_certs,
493 native_tls,
494 offline,
495 no_cache,
496 cache_dir,
497 preview: PreviewOption::try_from(preview, preview_features)?,
498 python_preference,
499 python_downloads,
500 concurrent_downloads,
501 concurrent_builds,
502 concurrent_installs,
503 http_proxy,
504 https_proxy,
505 no_proxy,
506 allow_insecure_host,
507 })
508 }
509}
510
511#[derive(Debug, Clone, Default, CombineOptions)]
513pub struct InstallerOptions {
514 index: Option<Vec<Index>>,
515 index_url: Option<PipIndex>,
516 extra_index_url: Option<Vec<PipExtraIndex>>,
517 no_index: Option<bool>,
518 find_links: Option<Vec<PipFindLinks>>,
519 index_strategy: Option<IndexStrategy>,
520 keyring_provider: Option<KeyringProviderType>,
521 config_settings: Option<ConfigSettings>,
522 exclude_newer: Option<ExcludeNewerOverride>,
523 link_mode: Option<LinkMode>,
524 compile_bytecode: Option<bool>,
525 reinstall: Option<Reinstall>,
526 build_isolation: Option<BuildIsolation>,
527 no_build: Option<bool>,
528 no_build_package: Option<Vec<PackageName>>,
529 no_binary: Option<bool>,
530 no_binary_package: Option<Vec<PackageName>>,
531 no_sources: Option<bool>,
532 no_sources_package: Option<Vec<PackageName>>,
533}
534
535#[derive(Debug, Clone, Default, CombineOptions)]
537pub struct ResolverOptions {
538 pub index: Option<Vec<Index>>,
539 pub index_url: Option<PipIndex>,
540 pub extra_index_url: Option<Vec<PipExtraIndex>>,
541 pub no_index: Option<bool>,
542 pub find_links: Option<Vec<PipFindLinks>>,
543 pub index_strategy: Option<IndexStrategy>,
544 pub keyring_provider: Option<KeyringProviderType>,
545 pub resolution: Option<ResolutionMode>,
546 pub prerelease: Option<PrereleaseMode>,
547 pub fork_strategy: Option<ForkStrategy>,
548 pub dependency_metadata: Option<Vec<StaticMetadata>>,
549 pub config_settings: Option<ConfigSettings>,
550 pub config_settings_package: Option<PackageConfigSettings>,
551 pub exclude_newer: Option<ExcludeNewerOverride>,
552 pub exclude_newer_package: Option<ExcludeNewerPackage>,
553 pub link_mode: Option<LinkMode>,
554 pub torch_backend: Option<TorchMode>,
555 pub upgrade: Option<Upgrade>,
556 pub build_isolation: Option<BuildIsolation>,
557 pub no_build: Option<bool>,
558 pub no_build_package: Option<Vec<PackageName>>,
559 pub no_binary: Option<bool>,
560 pub no_binary_package: Option<Vec<PackageName>>,
561 pub extra_build_dependencies: Option<ExtraBuildDependencies>,
562 pub extra_build_variables: Option<ExtraBuildVariables>,
563 pub no_sources: Option<bool>,
564 pub no_sources_package: Option<Vec<PackageName>>,
565}
566
567#[derive(Debug, Clone, Default, CombineOptions)]
570pub struct ResolverInstallerOptions {
571 pub index: Option<Vec<Index>>,
572 pub index_url: Option<PipIndex>,
573 pub extra_index_url: Option<Vec<PipExtraIndex>>,
574 pub no_index: Option<bool>,
575 pub find_links: Option<Vec<PipFindLinks>>,
576 pub index_strategy: Option<IndexStrategy>,
577 pub keyring_provider: Option<KeyringProviderType>,
578 pub resolution: Option<ResolutionMode>,
579 pub prerelease: Option<PrereleaseMode>,
580 pub fork_strategy: Option<ForkStrategy>,
581 pub dependency_metadata: Option<Vec<StaticMetadata>>,
582 pub config_settings: Option<ConfigSettings>,
583 pub config_settings_package: Option<PackageConfigSettings>,
584 pub build_isolation: Option<BuildIsolation>,
585 pub extra_build_dependencies: Option<ExtraBuildDependencies>,
586 pub extra_build_variables: Option<ExtraBuildVariables>,
587 pub exclude_newer: Option<ExcludeNewerOverride>,
588 pub exclude_newer_package: Option<ExcludeNewerPackage>,
589 pub link_mode: Option<LinkMode>,
590 pub torch_backend: Option<TorchMode>,
591 pub compile_bytecode: Option<bool>,
592 pub no_sources: Option<bool>,
593 pub no_sources_package: Option<Vec<PackageName>>,
594 pub upgrade: Option<Upgrade>,
595 pub reinstall: Option<Reinstall>,
596 pub no_build: Option<bool>,
597 pub no_build_package: Option<Vec<PackageName>>,
598 pub no_binary: Option<bool>,
599 pub no_binary_package: Option<Vec<PackageName>>,
600}
601
602impl From<ResolverInstallerSchema> for ResolverInstallerOptions {
603 fn from(value: ResolverInstallerSchema) -> Self {
604 let ResolverInstallerSchema {
605 index,
606 index_url,
607 extra_index_url,
608 no_index,
609 find_links,
610 index_strategy,
611 keyring_provider,
612 resolution,
613 prerelease,
614 fork_strategy,
615 dependency_metadata,
616 config_settings,
617 config_settings_package,
618 no_build_isolation,
619 no_build_isolation_package,
620 extra_build_dependencies,
621 extra_build_variables,
622 exclude_newer,
623 exclude_newer_package,
624 link_mode,
625 torch_backend,
626 compile_bytecode,
627 no_sources,
628 no_sources_package,
629 upgrade,
630 upgrade_package,
631 reinstall,
632 reinstall_package,
633 no_build,
634 no_build_package,
635 no_binary,
636 no_binary_package,
637 } = value;
638 Self {
639 index,
640 index_url,
641 extra_index_url,
642 no_index,
643 find_links,
644 index_strategy,
645 keyring_provider,
646 resolution,
647 prerelease,
648 fork_strategy,
649 dependency_metadata,
650 config_settings,
651 config_settings_package,
652 build_isolation: BuildIsolation::from_args(
653 no_build_isolation,
654 no_build_isolation_package.into_iter().flatten().collect(),
655 ),
656 extra_build_dependencies,
657 extra_build_variables,
658 exclude_newer,
659 exclude_newer_package,
660 link_mode,
661 torch_backend,
662 compile_bytecode,
663 no_sources,
664 no_sources_package,
665 upgrade: Upgrade::from_args(
666 upgrade,
667 upgrade_package
668 .into_iter()
669 .flatten()
670 .map(Into::into)
671 .collect(),
672 Vec::new(),
673 ),
674 reinstall: Reinstall::from_args(reinstall, reinstall_package.unwrap_or_default()),
675 no_build,
676 no_build_package,
677 no_binary,
678 no_binary_package,
679 }
680 }
681}
682
683impl ResolverInstallerSchema {
684 fn relative_to(self, root_dir: &Path) -> Result<Self, IndexUrlError> {
686 Ok(Self {
687 index: self
688 .index
689 .map(|index| {
690 index
691 .into_iter()
692 .map(|index| index.relative_to(root_dir))
693 .collect::<Result<Vec<_>, _>>()
694 })
695 .transpose()?,
696 index_url: self
697 .index_url
698 .map(|index_url| index_url.relative_to(root_dir))
699 .transpose()?,
700 extra_index_url: self
701 .extra_index_url
702 .map(|extra_index_url| {
703 extra_index_url
704 .into_iter()
705 .map(|extra_index_url| extra_index_url.relative_to(root_dir))
706 .collect::<Result<Vec<_>, _>>()
707 })
708 .transpose()?,
709 find_links: self
710 .find_links
711 .map(|find_links| {
712 find_links
713 .into_iter()
714 .map(|find_link| find_link.relative_to(root_dir))
715 .collect::<Result<Vec<_>, _>>()
716 })
717 .transpose()?,
718 ..self
719 })
720 }
721}
722
723#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
725#[serde(rename_all = "kebab-case")]
726#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
727pub struct ResolverInstallerSchema {
728 #[option(
756 default = "\"[]\"",
757 value_type = "dict",
758 example = r#"
759 [[tool.uv.index]]
760 name = "pytorch"
761 url = "https://download.pytorch.org/whl/cu130"
762 "#
763 )]
764 pub index: Option<Vec<Index>>,
765 #[option(
775 default = "\"https://pypi.org/simple\"",
776 value_type = "str",
777 example = r#"
778 index-url = "https://test.pypi.org/simple"
779 "#
780 )]
781 pub index_url: Option<PipIndex>,
782 #[option(
796 default = "[]",
797 value_type = "list[str]",
798 example = r#"
799 extra-index-url = ["https://download.pytorch.org/whl/cpu"]
800 "#
801 )]
802 pub extra_index_url: Option<Vec<PipExtraIndex>>,
803 #[option(
806 default = "false",
807 value_type = "bool",
808 example = r#"
809 no-index = true
810 "#
811 )]
812 pub no_index: Option<bool>,
813 #[option(
822 default = "[]",
823 value_type = "list[str]",
824 example = r#"
825 find-links = ["https://download.pytorch.org/whl/torch_stable.html"]
826 "#
827 )]
828 pub find_links: Option<Vec<PipFindLinks>>,
829 #[option(
836 default = "\"first-index\"",
837 value_type = "str",
838 example = r#"
839 index-strategy = "unsafe-best-match"
840 "#,
841 possible_values = true
842 )]
843 pub index_strategy: Option<IndexStrategy>,
844 #[option(
849 default = "\"disabled\"",
850 value_type = "str",
851 example = r#"
852 keyring-provider = "subprocess"
853 "#
854 )]
855 pub keyring_provider: Option<KeyringProviderType>,
856 #[option(
861 default = "\"highest\"",
862 value_type = "str",
863 example = r#"
864 resolution = "lowest-direct"
865 "#,
866 possible_values = true
867 )]
868 pub resolution: Option<ResolutionMode>,
869 #[option(
875 default = "\"if-necessary-or-explicit\"",
876 value_type = "str",
877 example = r#"
878 prerelease = "allow"
879 "#,
880 possible_values = true
881 )]
882 pub prerelease: Option<PrereleaseMode>,
883 #[option(
894 default = "\"requires-python\"",
895 value_type = "str",
896 example = r#"
897 fork-strategy = "fewest"
898 "#,
899 possible_values = true
900 )]
901 pub fork_strategy: Option<ForkStrategy>,
902 #[option(
916 default = r#"[]"#,
917 value_type = "list[dict]",
918 example = r#"
919 dependency-metadata = [
920 { name = "flask", version = "1.0.0", requires-dist = ["werkzeug"], requires-python = ">=3.6" },
921 ]
922 "#
923 )]
924 pub dependency_metadata: Option<Vec<StaticMetadata>>,
925 #[option(
928 default = "{}",
929 value_type = "dict",
930 example = r#"
931 config-settings = { editable_mode = "compat" }
932 "#
933 )]
934 pub config_settings: Option<ConfigSettings>,
935 #[option(
940 default = "{}",
941 value_type = "dict",
942 example = r#"
943 config-settings-package = { numpy = { editable_mode = "compat" } }
944 "#
945 )]
946 pub config_settings_package: Option<PackageConfigSettings>,
947 #[option(
952 default = "false",
953 value_type = "bool",
954 example = r#"
955 no-build-isolation = true
956 "#
957 )]
958 pub no_build_isolation: Option<bool>,
959 #[option(
964 default = "[]",
965 value_type = "list[str]",
966 example = r#"
967 no-build-isolation-package = ["package1", "package2"]
968 "#
969 )]
970 pub no_build_isolation_package: Option<Vec<PackageName>>,
971 #[option(
977 default = "[]",
978 value_type = "dict",
979 example = r#"
980 extra-build-dependencies = { pytest = ["setuptools"] }
981 "#
982 )]
983 pub extra_build_dependencies: Option<ExtraBuildDependencies>,
984 #[option(
989 default = r#"{}"#,
990 value_type = r#"dict[str, dict[str, str]]"#,
991 example = r#"
992 extra-build-variables = { flash-attn = { FLASH_ATTENTION_SKIP_CUDA_BUILD = "TRUE" } }
993 "#
994 )]
995 pub extra_build_variables: Option<ExtraBuildVariables>,
996 #[option(
1011 default = "None",
1012 value_type = "str | false",
1013 example = r#"
1014 exclude-newer = "2006-12-02T02:07:43Z"
1015 "#
1016 )]
1017 pub exclude_newer: Option<ExcludeNewerOverride>,
1018 #[option(
1032 default = "None",
1033 value_type = "dict",
1034 example = r#"
1035 exclude-newer-package = { tqdm = "2022-04-04T00:00:00Z", markupsafe = false }
1036 "#
1037 )]
1038 pub exclude_newer_package: Option<ExcludeNewerPackage>,
1039 #[option(
1049 default = "\"clone\" (macOS, Linux) or \"hardlink\" (Windows)",
1050 value_type = "str",
1051 example = r#"
1052 link-mode = "copy"
1053 "#,
1054 possible_values = true
1055 )]
1056 pub link_mode: Option<LinkMode>,
1057 #[option(
1068 default = "false",
1069 value_type = "bool",
1070 example = r#"
1071 compile-bytecode = true
1072 "#
1073 )]
1074 pub compile_bytecode: Option<bool>,
1075 #[option(
1079 default = "false",
1080 value_type = "bool",
1081 example = r#"
1082 no-sources = true
1083 "#
1084 )]
1085 pub no_sources: Option<bool>,
1086 #[option(
1088 default = "[]",
1089 value_type = "list[str]",
1090 example = r#"
1091 no-sources-package = ["ruff"]
1092 "#
1093 )]
1094 pub no_sources_package: Option<Vec<PackageName>>,
1095 #[option(
1097 default = "false",
1098 value_type = "bool",
1099 example = r#"
1100 upgrade = true
1101 "#
1102 )]
1103 pub upgrade: Option<bool>,
1104 #[option(
1109 default = "[]",
1110 value_type = "list[str]",
1111 example = r#"
1112 upgrade-package = ["ruff"]
1113 "#
1114 )]
1115 pub upgrade_package: Option<Vec<Requirement<VerbatimParsedUrl>>>,
1116 #[option(
1118 default = "false",
1119 value_type = "bool",
1120 example = r#"
1121 reinstall = true
1122 "#
1123 )]
1124 pub reinstall: Option<bool>,
1125 #[option(
1128 default = "[]",
1129 value_type = "list[str]",
1130 example = r#"
1131 reinstall-package = ["ruff"]
1132 "#
1133 )]
1134 pub reinstall_package: Option<Vec<PackageName>>,
1135 #[option(
1141 default = "false",
1142 value_type = "bool",
1143 example = r#"
1144 no-build = true
1145 "#
1146 )]
1147 pub no_build: Option<bool>,
1148 #[option(
1150 default = "[]",
1151 value_type = "list[str]",
1152 example = r#"
1153 no-build-package = ["ruff"]
1154 "#
1155 )]
1156 pub no_build_package: Option<Vec<PackageName>>,
1157 #[option(
1162 default = "false",
1163 value_type = "bool",
1164 example = r#"
1165 no-binary = true
1166 "#
1167 )]
1168 pub no_binary: Option<bool>,
1169 #[option(
1171 default = "[]",
1172 value_type = "list[str]",
1173 example = r#"
1174 no-binary-package = ["ruff"]
1175 "#
1176 )]
1177 pub no_binary_package: Option<Vec<PackageName>>,
1178 #[option(
1193 default = "null",
1194 value_type = "str",
1195 example = r#"
1196 torch-backend = "auto"
1197 "#
1198 )]
1199 pub torch_backend: Option<TorchMode>,
1200}
1201
1202#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
1204#[serde(rename_all = "kebab-case")]
1205#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1206pub struct PythonInstallMirrors {
1207 #[option(
1215 default = "None",
1216 value_type = "str",
1217 uv_toml_only = true,
1218 example = r#"
1219 python-install-mirror = "https://github.com/astral-sh/python-build-standalone/releases/download"
1220 "#
1221 )]
1222 pub python_install_mirror: Option<String>,
1223 #[option(
1232 default = "None",
1233 value_type = "str",
1234 uv_toml_only = true,
1235 example = r#"
1236 pypy-install-mirror = "https://downloads.python.org/pypy"
1237 "#
1238 )]
1239 pub pypy_install_mirror: Option<String>,
1240
1241 #[option(
1243 default = "None",
1244 value_type = "str",
1245 uv_toml_only = true,
1246 example = r#"
1247 python-downloads-json-url = "/etc/uv/python-downloads.json"
1248 "#
1249 )]
1250 pub python_downloads_json_url: Option<String>,
1251}
1252
1253impl PythonInstallMirrors {
1254 #[must_use]
1255 pub fn combine(self, other: Self) -> Self {
1256 Self {
1257 python_install_mirror: self.python_install_mirror.or(other.python_install_mirror),
1258 pypy_install_mirror: self.pypy_install_mirror.or(other.pypy_install_mirror),
1259 python_downloads_json_url: self
1260 .python_downloads_json_url
1261 .or(other.python_downloads_json_url),
1262 }
1263 }
1264}
1265
1266#[derive(Debug, Clone, Default, Deserialize, CombineOptions, OptionsMetadata)]
1271#[serde(deny_unknown_fields, rename_all = "kebab-case")]
1272#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1273pub struct PipOptions {
1274 #[option(
1287 default = "None",
1288 value_type = "str",
1289 example = r#"
1290 python = "3.10"
1291 "#
1292 )]
1293 pub python: Option<String>,
1294 #[option(
1303 default = "false",
1304 value_type = "bool",
1305 example = r#"
1306 system = true
1307 "#
1308 )]
1309 pub system: Option<bool>,
1310 #[option(
1317 default = "false",
1318 value_type = "bool",
1319 example = r#"
1320 break-system-packages = true
1321 "#
1322 )]
1323 pub break_system_packages: Option<bool>,
1324 #[option(
1327 default = "None",
1328 value_type = "str",
1329 example = r#"
1330 target = "./target"
1331 "#
1332 )]
1333 pub target: Option<PathBuf>,
1334 #[option(
1342 default = "None",
1343 value_type = "str",
1344 example = r#"
1345 prefix = "./prefix"
1346 "#
1347 )]
1348 pub prefix: Option<PathBuf>,
1349 #[serde(skip)]
1350 #[cfg_attr(feature = "schemars", schemars(skip))]
1351 pub index: Option<Vec<Index>>,
1352 #[option(
1360 default = "\"https://pypi.org/simple\"",
1361 value_type = "str",
1362 example = r#"
1363 index-url = "https://test.pypi.org/simple"
1364 "#
1365 )]
1366 pub index_url: Option<PipIndex>,
1367 #[option(
1378 default = "[]",
1379 value_type = "list[str]",
1380 example = r#"
1381 extra-index-url = ["https://download.pytorch.org/whl/cpu"]
1382 "#
1383 )]
1384 pub extra_index_url: Option<Vec<PipExtraIndex>>,
1385 #[option(
1388 default = "false",
1389 value_type = "bool",
1390 example = r#"
1391 no-index = true
1392 "#
1393 )]
1394 pub no_index: Option<bool>,
1395 #[option(
1404 default = "[]",
1405 value_type = "list[str]",
1406 example = r#"
1407 find-links = ["https://download.pytorch.org/whl/torch_stable.html"]
1408 "#
1409 )]
1410 pub find_links: Option<Vec<PipFindLinks>>,
1411 #[option(
1418 default = "\"first-index\"",
1419 value_type = "str",
1420 example = r#"
1421 index-strategy = "unsafe-best-match"
1422 "#,
1423 possible_values = true
1424 )]
1425 pub index_strategy: Option<IndexStrategy>,
1426 #[option(
1431 default = "disabled",
1432 value_type = "str",
1433 example = r#"
1434 keyring-provider = "subprocess"
1435 "#
1436 )]
1437 pub keyring_provider: Option<KeyringProviderType>,
1438 #[option(
1446 default = "false",
1447 value_type = "bool",
1448 example = r#"
1449 no-build = true
1450 "#
1451 )]
1452 pub no_build: Option<bool>,
1453 #[option(
1461 default = "[]",
1462 value_type = "list[str]",
1463 example = r#"
1464 no-binary = ["ruff"]
1465 "#
1466 )]
1467 pub no_binary: Option<Vec<PackageNameSpecifier>>,
1468 #[option(
1477 default = "[]",
1478 value_type = "list[str]",
1479 example = r#"
1480 only-binary = ["ruff"]
1481 "#
1482 )]
1483 pub only_binary: Option<Vec<PackageNameSpecifier>>,
1484 #[option(
1489 default = "false",
1490 value_type = "bool",
1491 example = r#"
1492 no-build-isolation = true
1493 "#
1494 )]
1495 pub no_build_isolation: Option<bool>,
1496 #[option(
1501 default = "[]",
1502 value_type = "list[str]",
1503 example = r#"
1504 no-build-isolation-package = ["package1", "package2"]
1505 "#
1506 )]
1507 pub no_build_isolation_package: Option<Vec<PackageName>>,
1508 #[option(
1514 default = "[]",
1515 value_type = "dict",
1516 example = r#"
1517 extra-build-dependencies = { pytest = ["setuptools"] }
1518 "#
1519 )]
1520 pub extra_build_dependencies: Option<ExtraBuildDependencies>,
1521 #[option(
1526 default = r#"{}"#,
1527 value_type = r#"dict[str, dict[str, str]]"#,
1528 example = r#"
1529 extra-build-variables = { flash-attn = { FLASH_ATTENTION_SKIP_CUDA_BUILD = "TRUE" } }
1530 "#
1531 )]
1532 pub extra_build_variables: Option<ExtraBuildVariables>,
1533 #[option(
1536 default = "false",
1537 value_type = "bool",
1538 example = r#"
1539 strict = true
1540 "#
1541 )]
1542 pub strict: Option<bool>,
1543 #[option(
1547 default = "[]",
1548 value_type = "list[str]",
1549 example = r#"
1550 extra = ["dev", "docs"]
1551 "#
1552 )]
1553 pub extra: Option<Vec<ExtraName>>,
1554 #[option(
1558 default = "false",
1559 value_type = "bool",
1560 example = r#"
1561 all-extras = true
1562 "#
1563 )]
1564 pub all_extras: Option<bool>,
1565 #[option(
1567 default = "[]",
1568 value_type = "list[str]",
1569 example = r#"
1570 all-extras = true
1571 no-extra = ["dev", "docs"]
1572 "#
1573 )]
1574 pub no_extra: Option<Vec<ExtraName>>,
1575 #[option(
1578 default = "false",
1579 value_type = "bool",
1580 example = r#"
1581 no-deps = true
1582 "#
1583 )]
1584 pub no_deps: Option<bool>,
1585 #[option(
1587 default = "None",
1588 value_type = "list[str]",
1589 example = r#"
1590 group = ["dev", "docs"]
1591 "#
1592 )]
1593 pub group: Option<Vec<PipGroupName>>,
1594 #[option(
1597 default = "false",
1598 value_type = "bool",
1599 example = r#"
1600 allow-empty-requirements = true
1601 "#
1602 )]
1603 pub allow_empty_requirements: Option<bool>,
1604 #[option(
1609 default = "\"highest\"",
1610 value_type = "str",
1611 example = r#"
1612 resolution = "lowest-direct"
1613 "#,
1614 possible_values = true
1615 )]
1616 pub resolution: Option<ResolutionMode>,
1617 #[option(
1623 default = "\"if-necessary-or-explicit\"",
1624 value_type = "str",
1625 example = r#"
1626 prerelease = "allow"
1627 "#,
1628 possible_values = true
1629 )]
1630 pub prerelease: Option<PrereleaseMode>,
1631 #[option(
1642 default = "\"requires-python\"",
1643 value_type = "str",
1644 example = r#"
1645 fork-strategy = "fewest"
1646 "#,
1647 possible_values = true
1648 )]
1649 pub fork_strategy: Option<ForkStrategy>,
1650 #[option(
1664 default = r#"[]"#,
1665 value_type = "list[dict]",
1666 example = r#"
1667 dependency-metadata = [
1668 { name = "flask", version = "1.0.0", requires-dist = ["werkzeug"], requires-python = ">=3.6" },
1669 ]
1670 "#
1671 )]
1672 pub dependency_metadata: Option<Vec<StaticMetadata>>,
1673 #[option(
1678 default = "None",
1679 value_type = "str",
1680 example = r#"
1681 output-file = "requirements.txt"
1682 "#
1683 )]
1684 pub output_file: Option<PathBuf>,
1685 #[option(
1691 default = "false",
1692 value_type = "bool",
1693 example = r#"
1694 no-strip-extras = true
1695 "#
1696 )]
1697 pub no_strip_extras: Option<bool>,
1698 #[option(
1703 default = "false",
1704 value_type = "bool",
1705 example = r#"
1706 no-strip-markers = true
1707 "#
1708 )]
1709 pub no_strip_markers: Option<bool>,
1710 #[option(
1713 default = "false",
1714 value_type = "bool",
1715 example = r#"
1716 no-annotate = true
1717 "#
1718 )]
1719 pub no_annotate: Option<bool>,
1720 #[option(
1722 default = r#"false"#,
1723 value_type = "bool",
1724 example = r#"
1725 no-header = true
1726 "#
1727 )]
1728 pub no_header: Option<bool>,
1729 #[option(
1733 default = "None",
1734 value_type = "str",
1735 example = r#"
1736 custom-compile-command = "./custom-uv-compile.sh"
1737 "#
1738 )]
1739 pub custom_compile_command: Option<String>,
1740 #[option(
1742 default = "false",
1743 value_type = "bool",
1744 example = r#"
1745 generate-hashes = true
1746 "#
1747 )]
1748 pub generate_hashes: Option<bool>,
1749 #[option(
1752 default = "{}",
1753 value_type = "dict",
1754 example = r#"
1755 config-settings = { editable_mode = "compat" }
1756 "#
1757 )]
1758 pub config_settings: Option<ConfigSettings>,
1759 #[option(
1762 default = "{}",
1763 value_type = "dict",
1764 example = r#"
1765 config-settings-package = { numpy = { editable_mode = "compat" } }
1766 "#
1767 )]
1768 pub config_settings_package: Option<PackageConfigSettings>,
1769 #[option(
1775 default = "None",
1776 value_type = "str",
1777 example = r#"
1778 python-version = "3.8"
1779 "#
1780 )]
1781 pub python_version: Option<PythonVersion>,
1782 #[option(
1788 default = "None",
1789 value_type = "str",
1790 example = r#"
1791 python-platform = "x86_64-unknown-linux-gnu"
1792 "#
1793 )]
1794 pub python_platform: Option<TargetTriple>,
1795 #[option(
1803 default = "false",
1804 value_type = "bool",
1805 example = r#"
1806 universal = true
1807 "#
1808 )]
1809 pub universal: Option<bool>,
1810 #[option(
1825 default = "None",
1826 value_type = "str | false",
1827 example = r#"
1828 exclude-newer = "2006-12-02T02:07:43Z"
1829 "#
1830 )]
1831 pub exclude_newer: Option<ExcludeNewerOverride>,
1832 #[option(
1845 default = "None",
1846 value_type = "dict",
1847 example = r#"
1848 exclude-newer-package = { tqdm = "2022-04-04T00:00:00Z", markupsafe = false }
1849 "#
1850 )]
1851 pub exclude_newer_package: Option<ExcludeNewerPackage>,
1852 #[option(
1855 default = "[]",
1856 value_type = "list[str]",
1857 example = r#"
1858 no-emit-package = ["ruff"]
1859 "#
1860 )]
1861 pub no_emit_package: Option<Vec<PackageName>>,
1862 #[option(
1864 default = "false",
1865 value_type = "bool",
1866 example = r#"
1867 emit-index-url = true
1868 "#
1869 )]
1870 pub emit_index_url: Option<bool>,
1871 #[option(
1873 default = "false",
1874 value_type = "bool",
1875 example = r#"
1876 emit-find-links = true
1877 "#
1878 )]
1879 pub emit_find_links: Option<bool>,
1880 #[option(
1882 default = "false",
1883 value_type = "bool",
1884 example = r#"
1885 emit-build-options = true
1886 "#
1887 )]
1888 pub emit_build_options: Option<bool>,
1889 #[option(
1896 default = "false",
1897 value_type = "bool",
1898 example = r#"
1899 emit-marker-expression = true
1900 "#
1901 )]
1902 pub emit_marker_expression: Option<bool>,
1903 #[option(
1906 default = "false",
1907 value_type = "bool",
1908 example = r#"
1909 emit-index-annotation = true
1910 "#
1911 )]
1912 pub emit_index_annotation: Option<bool>,
1913 #[option(
1916 default = "\"split\"",
1917 value_type = "str",
1918 example = r#"
1919 annotation-style = "line"
1920 "#,
1921 possible_values = true
1922 )]
1923 pub annotation_style: Option<AnnotationStyle>,
1924 #[option(
1934 default = "\"clone\" (macOS, Linux) or \"hardlink\" (Windows)",
1935 value_type = "str",
1936 example = r#"
1937 link-mode = "copy"
1938 "#,
1939 possible_values = true
1940 )]
1941 pub link_mode: Option<LinkMode>,
1942 #[option(
1953 default = "false",
1954 value_type = "bool",
1955 example = r#"
1956 compile-bytecode = true
1957 "#
1958 )]
1959 pub compile_bytecode: Option<bool>,
1960 #[option(
1973 default = "false",
1974 value_type = "bool",
1975 example = r#"
1976 require-hashes = true
1977 "#
1978 )]
1979 pub require_hashes: Option<bool>,
1980 #[option(
1986 default = "true",
1987 value_type = "bool",
1988 example = r#"
1989 verify-hashes = true
1990 "#
1991 )]
1992 pub verify_hashes: Option<bool>,
1993 #[option(
1997 default = "false",
1998 value_type = "bool",
1999 example = r#"
2000 no-sources = true
2001 "#
2002 )]
2003 pub no_sources: Option<bool>,
2004 #[option(
2006 default = "[]",
2007 value_type = "list[str]",
2008 example = r#"
2009 no-sources-package = ["ruff"]
2010 "#
2011 )]
2012 pub no_sources_package: Option<Vec<PackageName>>,
2013 #[option(
2015 default = "false",
2016 value_type = "bool",
2017 example = r#"
2018 upgrade = true
2019 "#
2020 )]
2021 pub upgrade: Option<bool>,
2022 #[option(
2027 default = "[]",
2028 value_type = "list[str]",
2029 example = r#"
2030 upgrade-package = ["ruff"]
2031 "#
2032 )]
2033 pub upgrade_package: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2034 #[option(
2036 default = "false",
2037 value_type = "bool",
2038 example = r#"
2039 reinstall = true
2040 "#
2041 )]
2042 pub reinstall: Option<bool>,
2043 #[option(
2046 default = "[]",
2047 value_type = "list[str]",
2048 example = r#"
2049 reinstall-package = ["ruff"]
2050 "#
2051 )]
2052 pub reinstall_package: Option<Vec<PackageName>>,
2053 #[option(
2068 default = "null",
2069 value_type = "str",
2070 example = r#"
2071 torch-backend = "auto"
2072 "#
2073 )]
2074 pub torch_backend: Option<TorchMode>,
2075}
2076
2077impl PipOptions {
2078 fn relative_to(self, root_dir: &Path) -> Result<Self, IndexUrlError> {
2080 Ok(Self {
2081 index: self
2082 .index
2083 .map(|index| {
2084 index
2085 .into_iter()
2086 .map(|index| index.relative_to(root_dir))
2087 .collect::<Result<Vec<_>, _>>()
2088 })
2089 .transpose()?,
2090 index_url: self
2091 .index_url
2092 .map(|index_url| index_url.relative_to(root_dir))
2093 .transpose()?,
2094 extra_index_url: self
2095 .extra_index_url
2096 .map(|extra_index_url| {
2097 extra_index_url
2098 .into_iter()
2099 .map(|extra_index_url| extra_index_url.relative_to(root_dir))
2100 .collect::<Result<Vec<_>, _>>()
2101 })
2102 .transpose()?,
2103 find_links: self
2104 .find_links
2105 .map(|find_links| {
2106 find_links
2107 .into_iter()
2108 .map(|find_link| find_link.relative_to(root_dir))
2109 .collect::<Result<Vec<_>, _>>()
2110 })
2111 .transpose()?,
2112 ..self
2113 })
2114 }
2115}
2116
2117impl From<ResolverInstallerSchema> for ResolverOptions {
2118 fn from(value: ResolverInstallerSchema) -> Self {
2119 Self {
2120 index: value.index,
2121 index_url: value.index_url,
2122 extra_index_url: value.extra_index_url,
2123 no_index: value.no_index,
2124 find_links: value.find_links,
2125 index_strategy: value.index_strategy,
2126 keyring_provider: value.keyring_provider,
2127 resolution: value.resolution,
2128 prerelease: value.prerelease,
2129 fork_strategy: value.fork_strategy,
2130 dependency_metadata: value.dependency_metadata,
2131 config_settings: value.config_settings,
2132 config_settings_package: value.config_settings_package,
2133 exclude_newer: value.exclude_newer,
2134 exclude_newer_package: value.exclude_newer_package,
2135 link_mode: value.link_mode,
2136 upgrade: Upgrade::from_args(
2137 value.upgrade,
2138 value
2139 .upgrade_package
2140 .into_iter()
2141 .flatten()
2142 .map(Into::into)
2143 .collect(),
2144 Vec::new(),
2145 ),
2146 no_build: value.no_build,
2147 no_build_package: value.no_build_package,
2148 no_binary: value.no_binary,
2149 no_binary_package: value.no_binary_package,
2150 build_isolation: BuildIsolation::from_args(
2151 value.no_build_isolation,
2152 value.no_build_isolation_package.unwrap_or_default(),
2153 ),
2154 extra_build_dependencies: value.extra_build_dependencies,
2155 extra_build_variables: value.extra_build_variables,
2156 no_sources: value.no_sources,
2157 no_sources_package: value.no_sources_package,
2158 torch_backend: value.torch_backend,
2159 }
2160 }
2161}
2162
2163impl From<ResolverInstallerSchema> for InstallerOptions {
2164 fn from(value: ResolverInstallerSchema) -> Self {
2165 Self {
2166 index: value.index,
2167 index_url: value.index_url,
2168 extra_index_url: value.extra_index_url,
2169 no_index: value.no_index,
2170 find_links: value.find_links,
2171 index_strategy: value.index_strategy,
2172 keyring_provider: value.keyring_provider,
2173 config_settings: value.config_settings,
2174 exclude_newer: value.exclude_newer,
2175 link_mode: value.link_mode,
2176 compile_bytecode: value.compile_bytecode,
2177 reinstall: Reinstall::from_args(
2178 value.reinstall,
2179 value.reinstall_package.unwrap_or_default(),
2180 ),
2181 build_isolation: BuildIsolation::from_args(
2182 value.no_build_isolation,
2183 value.no_build_isolation_package.unwrap_or_default(),
2184 ),
2185 no_build: value.no_build,
2186 no_build_package: value.no_build_package,
2187 no_binary: value.no_binary,
2188 no_binary_package: value.no_binary_package,
2189 no_sources: value.no_sources,
2190 no_sources_package: value.no_sources_package,
2191 }
2192 }
2193}
2194
2195#[derive(
2200 Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, CombineOptions, OptionsMetadata,
2201)]
2202#[serde(deny_unknown_fields, rename_all = "kebab-case")]
2203#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2204pub struct ToolOptions {
2205 index: Option<Vec<Index>>,
2206 index_url: Option<PipIndex>,
2207 extra_index_url: Option<Vec<PipExtraIndex>>,
2208 no_index: Option<bool>,
2209 find_links: Option<Vec<PipFindLinks>>,
2210 index_strategy: Option<IndexStrategy>,
2211 keyring_provider: Option<KeyringProviderType>,
2212 resolution: Option<ResolutionMode>,
2213 prerelease: Option<PrereleaseMode>,
2214 fork_strategy: Option<ForkStrategy>,
2215 dependency_metadata: Option<Vec<StaticMetadata>>,
2216 config_settings: Option<ConfigSettings>,
2217 config_settings_package: Option<PackageConfigSettings>,
2218 build_isolation: Option<BuildIsolation>,
2219 extra_build_dependencies: Option<ExtraBuildDependencies>,
2220 extra_build_variables: Option<ExtraBuildVariables>,
2221 exclude_newer: Option<ExcludeNewerOverride>,
2222 exclude_newer_package: Option<ExcludeNewerPackage>,
2223 link_mode: Option<LinkMode>,
2224 compile_bytecode: Option<bool>,
2225 no_sources: Option<bool>,
2226 no_sources_package: Option<Vec<PackageName>>,
2227 no_build: Option<bool>,
2228 no_build_package: Option<Vec<PackageName>>,
2229 no_binary: Option<bool>,
2230 no_binary_package: Option<Vec<PackageName>>,
2231 torch_backend: Option<TorchMode>,
2232}
2233
2234#[derive(Debug, Clone, Default, Serialize, Deserialize)]
2236#[serde(deny_unknown_fields, rename_all = "kebab-case")]
2237pub struct ToolOptionsWire {
2238 index: Option<Vec<Index>>,
2239 index_url: Option<PipIndex>,
2240 extra_index_url: Option<Vec<PipExtraIndex>>,
2241 no_index: Option<bool>,
2242 find_links: Option<Vec<PipFindLinks>>,
2243 index_strategy: Option<IndexStrategy>,
2244 keyring_provider: Option<KeyringProviderType>,
2245 resolution: Option<ResolutionMode>,
2246 prerelease: Option<PrereleaseMode>,
2247 fork_strategy: Option<ForkStrategy>,
2248 dependency_metadata: Option<Vec<StaticMetadata>>,
2249 config_settings: Option<ConfigSettings>,
2250 config_settings_package: Option<PackageConfigSettings>,
2251 build_isolation: Option<BuildIsolation>,
2252 extra_build_dependencies: Option<ExtraBuildDependencies>,
2253 extra_build_variables: Option<ExtraBuildVariables>,
2254 exclude_newer: Option<ExcludeNewerOverride>,
2255 exclude_newer_span: Option<ExcludeNewerSpan>,
2256 #[serde(serialize_with = "serialize_exclude_newer_package_with_spans")]
2257 exclude_newer_package: Option<ExcludeNewerPackage>,
2258 link_mode: Option<LinkMode>,
2259 compile_bytecode: Option<bool>,
2260 no_sources: Option<bool>,
2261 no_sources_package: Option<Vec<PackageName>>,
2262 no_build: Option<bool>,
2263 no_build_package: Option<Vec<PackageName>>,
2264 no_binary: Option<bool>,
2265 no_binary_package: Option<Vec<PackageName>>,
2266 torch_backend: Option<TorchMode>,
2267}
2268
2269impl From<ResolverInstallerOptions> for ToolOptions {
2270 fn from(value: ResolverInstallerOptions) -> Self {
2271 Self {
2272 index: value.index.map(|indexes| {
2273 indexes
2274 .into_iter()
2275 .map(Index::with_promoted_auth_policy)
2276 .collect()
2277 }),
2278 index_url: value.index_url,
2279 extra_index_url: value.extra_index_url,
2280 no_index: value.no_index,
2281 find_links: value.find_links,
2282 index_strategy: value.index_strategy,
2283 keyring_provider: value.keyring_provider,
2284 resolution: value.resolution,
2285 prerelease: value.prerelease,
2286 fork_strategy: value.fork_strategy,
2287 dependency_metadata: value.dependency_metadata,
2288 config_settings: value.config_settings,
2289 config_settings_package: value.config_settings_package,
2290 build_isolation: value.build_isolation,
2291 extra_build_dependencies: value.extra_build_dependencies,
2292 extra_build_variables: value.extra_build_variables,
2293 exclude_newer: value.exclude_newer,
2294 exclude_newer_package: value.exclude_newer_package,
2295 link_mode: value.link_mode,
2296 compile_bytecode: value.compile_bytecode,
2297 no_sources: value.no_sources,
2298 no_sources_package: value.no_sources_package,
2299 no_build: value.no_build,
2300 no_build_package: value.no_build_package,
2301 no_binary: value.no_binary,
2302 no_binary_package: value.no_binary_package,
2303 torch_backend: value.torch_backend,
2304 }
2305 }
2306}
2307
2308impl From<ToolOptionsWire> for ToolOptions {
2309 fn from(value: ToolOptionsWire) -> Self {
2310 let exclude_newer = value
2311 .exclude_newer
2312 .map(|exclude_newer| match exclude_newer {
2313 ExcludeNewerOverride::Disabled => ExcludeNewerOverride::Disabled,
2314 ExcludeNewerOverride::Enabled(exclude_newer) => {
2315 let exclude_newer = *exclude_newer;
2316 if let Some(span) = value.exclude_newer_span
2317 && exclude_newer.span().is_none()
2318 {
2319 ExcludeNewerValue::relative(span).into()
2320 } else {
2321 exclude_newer.into()
2322 }
2323 }
2324 });
2325
2326 Self {
2327 index: value.index,
2328 index_url: value.index_url,
2329 extra_index_url: value.extra_index_url,
2330 no_index: value.no_index,
2331 find_links: value.find_links,
2332 index_strategy: value.index_strategy,
2333 keyring_provider: value.keyring_provider,
2334 resolution: value.resolution,
2335 prerelease: value.prerelease,
2336 fork_strategy: value.fork_strategy,
2337 dependency_metadata: value.dependency_metadata,
2338 config_settings: value.config_settings,
2339 config_settings_package: value.config_settings_package,
2340 build_isolation: value.build_isolation,
2341 extra_build_dependencies: value.extra_build_dependencies,
2342 extra_build_variables: value.extra_build_variables,
2343 exclude_newer,
2344 exclude_newer_package: value.exclude_newer_package,
2345 link_mode: value.link_mode,
2346 compile_bytecode: value.compile_bytecode,
2347 no_sources: value.no_sources,
2348 no_sources_package: value.no_sources_package,
2349 no_build: value.no_build,
2350 no_build_package: value.no_build_package,
2351 no_binary: value.no_binary,
2352 no_binary_package: value.no_binary_package,
2353 torch_backend: value.torch_backend,
2354 }
2355 }
2356}
2357
2358impl From<ToolOptions> for ToolOptionsWire {
2359 fn from(value: ToolOptions) -> Self {
2360 let (exclude_newer, exclude_newer_span) = match &value.exclude_newer {
2361 Some(ExcludeNewerOverride::Disabled) => (Some(ExcludeNewerOverride::Disabled), None),
2362 Some(ExcludeNewerOverride::Enabled(value)) => match value.as_ref() {
2363 ExcludeNewerValue::Absolute(_) => {
2364 (Some(ExcludeNewerOverride::Enabled(value.clone())), None)
2365 }
2366 ExcludeNewerValue::Relative(span) => (
2367 Some(ExcludeNewerValue::absolute(value.timestamp()).into()),
2368 Some(*span),
2369 ),
2370 },
2371 None => (None, None),
2372 };
2373
2374 Self {
2375 index: value.index,
2376 index_url: value.index_url,
2377 extra_index_url: value.extra_index_url,
2378 no_index: value.no_index,
2379 find_links: value.find_links,
2380 index_strategy: value.index_strategy,
2381 keyring_provider: value.keyring_provider,
2382 resolution: value.resolution,
2383 prerelease: value.prerelease,
2384 fork_strategy: value.fork_strategy,
2385 dependency_metadata: value.dependency_metadata,
2386 config_settings: value.config_settings,
2387 config_settings_package: value.config_settings_package,
2388 build_isolation: value.build_isolation,
2389 extra_build_dependencies: value.extra_build_dependencies,
2390 extra_build_variables: value.extra_build_variables,
2391 exclude_newer,
2392 exclude_newer_span,
2393 exclude_newer_package: value.exclude_newer_package,
2394 link_mode: value.link_mode,
2395 compile_bytecode: value.compile_bytecode,
2396 no_sources: value.no_sources,
2397 no_sources_package: value.no_sources_package,
2398 no_build: value.no_build,
2399 no_build_package: value.no_build_package,
2400 no_binary: value.no_binary,
2401 no_binary_package: value.no_binary_package,
2402 torch_backend: value.torch_backend,
2403 }
2404 }
2405}
2406
2407impl From<ToolOptions> for ResolverInstallerOptions {
2408 fn from(value: ToolOptions) -> Self {
2409 Self {
2410 index: value.index,
2411 index_url: value.index_url,
2412 extra_index_url: value.extra_index_url,
2413 no_index: value.no_index,
2414 find_links: value.find_links,
2415 index_strategy: value.index_strategy,
2416 keyring_provider: value.keyring_provider,
2417 resolution: value.resolution,
2418 prerelease: value.prerelease,
2419 fork_strategy: value.fork_strategy,
2420 dependency_metadata: value.dependency_metadata,
2421 config_settings: value.config_settings,
2422 config_settings_package: value.config_settings_package,
2423 build_isolation: value.build_isolation,
2424 extra_build_dependencies: value.extra_build_dependencies,
2425 extra_build_variables: value.extra_build_variables,
2426 exclude_newer: value.exclude_newer,
2427 exclude_newer_package: value.exclude_newer_package,
2428 link_mode: value.link_mode,
2429 compile_bytecode: value.compile_bytecode,
2430 no_sources: value.no_sources,
2431 no_sources_package: value.no_sources_package,
2432 upgrade: None,
2433 reinstall: None,
2434 no_build: value.no_build,
2435 no_build_package: value.no_build_package,
2436 no_binary: value.no_binary,
2437 no_binary_package: value.no_binary_package,
2438 torch_backend: value.torch_backend,
2439 }
2440 }
2441}
2442
2443#[derive(Debug, Clone, Default, Deserialize)]
2446#[serde(rename_all = "kebab-case", deny_unknown_fields)]
2447struct OptionsWire {
2448 required_version: Option<RequiredVersion>,
2451 system_certs: Option<bool>,
2452 native_tls: Option<bool>,
2453 offline: Option<bool>,
2454 no_cache: Option<bool>,
2455 cache_dir: Option<PathBuf>,
2456 preview: Option<bool>,
2457 preview_features: Option<PreviewFeaturesOption>,
2458 python_preference: Option<PythonPreference>,
2459 python_downloads: Option<PythonDownloads>,
2460 concurrent_downloads: Option<NonZeroUsize>,
2461 concurrent_builds: Option<NonZeroUsize>,
2462 concurrent_installs: Option<NonZeroUsize>,
2463
2464 index: Option<Vec<Index>>,
2467 index_url: Option<PipIndex>,
2468 extra_index_url: Option<Vec<PipExtraIndex>>,
2469 no_index: Option<bool>,
2470 find_links: Option<Vec<PipFindLinks>>,
2471 index_strategy: Option<IndexStrategy>,
2472 keyring_provider: Option<KeyringProviderType>,
2473 http_proxy: Option<ProxyUrl>,
2474 https_proxy: Option<ProxyUrl>,
2475 no_proxy: Option<Vec<String>>,
2476 allow_insecure_host: Option<Vec<TrustedHost>>,
2477 resolution: Option<ResolutionMode>,
2478 prerelease: Option<PrereleaseMode>,
2479 fork_strategy: Option<ForkStrategy>,
2480 dependency_metadata: Option<Vec<StaticMetadata>>,
2481 config_settings: Option<ConfigSettings>,
2482 config_settings_package: Option<PackageConfigSettings>,
2483 no_build_isolation: Option<bool>,
2484 no_build_isolation_package: Option<Vec<PackageName>>,
2485 extra_build_dependencies: Option<ExtraBuildDependencies>,
2486 extra_build_variables: Option<ExtraBuildVariables>,
2487 exclude_newer: Option<ExcludeNewerOverride>,
2488 exclude_newer_package: Option<ExcludeNewerPackage>,
2489 link_mode: Option<LinkMode>,
2490 compile_bytecode: Option<bool>,
2491 no_sources: Option<bool>,
2492 no_sources_package: Option<Vec<PackageName>>,
2493 upgrade: Option<bool>,
2494 upgrade_package: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2495 reinstall: Option<bool>,
2496 reinstall_package: Option<Vec<PackageName>>,
2497 no_build: Option<bool>,
2498 no_build_package: Option<Vec<PackageName>>,
2499 no_binary: Option<bool>,
2500 no_binary_package: Option<Vec<PackageName>>,
2501 torch_backend: Option<TorchMode>,
2502
2503 python_install_mirror: Option<String>,
2506 pypy_install_mirror: Option<String>,
2507 python_downloads_json_url: Option<String>,
2508
2509 publish_url: Option<DisplaySafeUrl>,
2512 trusted_publishing: Option<TrustedPublishing>,
2513 check_url: Option<IndexUrl>,
2514
2515 add_bounds: Option<AddBoundsKind>,
2518
2519 audit: Option<AuditOptions>,
2520 pip: Option<PipOptions>,
2521 cache_keys: Option<Vec<CacheKey>>,
2522
2523 override_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2527 exclude_dependencies: Option<Vec<PackageName>>,
2528 constraint_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2529 build_constraint_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2530 environments: Option<SupportedEnvironments>,
2531 required_environments: Option<SupportedEnvironments>,
2532
2533 conflicts: Option<serde::de::IgnoredAny>,
2537 workspace: Option<serde::de::IgnoredAny>,
2538 sources: Option<serde::de::IgnoredAny>,
2539 managed: Option<serde::de::IgnoredAny>,
2540 r#package: Option<serde::de::IgnoredAny>,
2541 default_groups: Option<serde::de::IgnoredAny>,
2542 dependency_groups: Option<serde::de::IgnoredAny>,
2543 dev_dependencies: Option<serde::de::IgnoredAny>,
2544
2545 build_backend: Option<serde::de::IgnoredAny>,
2547}
2548
2549impl TryFrom<OptionsWire> for Options {
2550 type Error = &'static str;
2551
2552 #[allow(deprecated)]
2553 fn try_from(value: OptionsWire) -> Result<Self, Self::Error> {
2554 let OptionsWire {
2555 required_version,
2556 system_certs,
2557 native_tls,
2558 offline,
2559 no_cache,
2560 cache_dir,
2561 preview,
2562 preview_features,
2563 python_preference,
2564 python_downloads,
2565 python_install_mirror,
2566 pypy_install_mirror,
2567 python_downloads_json_url,
2568 concurrent_downloads,
2569 concurrent_builds,
2570 concurrent_installs,
2571 index,
2572 index_url,
2573 extra_index_url,
2574 no_index,
2575 find_links,
2576 index_strategy,
2577 keyring_provider,
2578 http_proxy,
2579 https_proxy,
2580 no_proxy,
2581 allow_insecure_host,
2582 resolution,
2583 prerelease,
2584 fork_strategy,
2585 dependency_metadata,
2586 config_settings,
2587 config_settings_package,
2588 no_build_isolation,
2589 no_build_isolation_package,
2590 exclude_newer,
2591 exclude_newer_package,
2592 link_mode,
2593 compile_bytecode,
2594 no_sources,
2595 no_sources_package,
2596 upgrade,
2597 upgrade_package,
2598 reinstall,
2599 reinstall_package,
2600 no_build,
2601 no_build_package,
2602 no_binary,
2603 no_binary_package,
2604 torch_backend,
2605 audit,
2606 pip,
2607 cache_keys,
2608 override_dependencies,
2609 exclude_dependencies,
2610 constraint_dependencies,
2611 build_constraint_dependencies,
2612 environments,
2613 required_environments,
2614 conflicts,
2615 publish_url,
2616 trusted_publishing,
2617 check_url,
2618 workspace,
2619 sources,
2620 default_groups,
2621 dependency_groups,
2622 extra_build_dependencies,
2623 extra_build_variables,
2624 dev_dependencies,
2625 managed,
2626 package,
2627 add_bounds: bounds,
2628 build_backend,
2630 } = value;
2631
2632 Ok(Self {
2633 globals: GlobalOptions {
2634 required_version,
2635 system_certs,
2636 native_tls,
2637 offline,
2638 no_cache,
2639 cache_dir,
2640 preview: PreviewOption::try_from(preview, preview_features)?,
2641 python_preference,
2642 python_downloads,
2643 concurrent_downloads,
2644 concurrent_builds,
2645 concurrent_installs,
2646 http_proxy,
2647 https_proxy,
2648 no_proxy,
2649 allow_insecure_host: allow_insecure_host.clone(),
2651 },
2652 top_level: ResolverInstallerSchema {
2653 index,
2654 index_url,
2655 extra_index_url,
2656 no_index,
2657 find_links,
2658 index_strategy,
2659 keyring_provider,
2660 resolution,
2661 prerelease,
2662 fork_strategy,
2663 dependency_metadata,
2664 config_settings,
2665 config_settings_package,
2666 no_build_isolation,
2667 no_build_isolation_package,
2668 extra_build_dependencies,
2669 extra_build_variables,
2670 exclude_newer,
2671 exclude_newer_package,
2672 link_mode,
2673 compile_bytecode,
2674 no_sources,
2675 no_sources_package,
2676 upgrade,
2677 upgrade_package,
2678 reinstall,
2679 reinstall_package,
2680 no_build,
2681 no_build_package,
2682 no_binary,
2683 no_binary_package,
2684 torch_backend,
2685 },
2686 pip,
2687 cache_keys,
2688 build_backend,
2689 override_dependencies,
2690 exclude_dependencies,
2691 constraint_dependencies,
2692 build_constraint_dependencies,
2693 environments,
2694 required_environments,
2695 install_mirrors: PythonInstallMirrors {
2696 python_install_mirror,
2697 pypy_install_mirror,
2698 python_downloads_json_url,
2699 },
2700 conflicts,
2701 publish: PublishOptions {
2702 publish_url,
2703 trusted_publishing,
2704 check_url,
2705 },
2706 add: AddOptions { add_bounds: bounds },
2707 audit,
2708 workspace,
2709 sources,
2710 dev_dependencies,
2711 default_groups,
2712 dependency_groups,
2713 managed,
2714 package,
2715 })
2716 }
2717}
2718
2719#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
2720#[serde(rename_all = "kebab-case")]
2721#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2722pub struct PublishOptions {
2723 #[option(
2726 default = "\"https://upload.pypi.org/legacy/\"",
2727 value_type = "str",
2728 example = r#"
2729 publish-url = "https://test.pypi.org/legacy/"
2730 "#
2731 )]
2732 pub publish_url: Option<DisplaySafeUrl>,
2733
2734 #[option(
2741 default = "automatic",
2742 value_type = "str",
2743 example = r#"
2744 trusted-publishing = "always"
2745 "#
2746 )]
2747 pub trusted_publishing: Option<TrustedPublishing>,
2748
2749 #[option(
2763 default = "None",
2764 value_type = "str",
2765 example = r#"
2766 check-url = "https://test.pypi.org/simple"
2767 "#
2768 )]
2769 pub check_url: Option<IndexUrl>,
2770}
2771
2772#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
2773#[serde(rename_all = "kebab-case")]
2774#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2775pub struct AddOptions {
2776 #[option(
2787 default = "\"lower\"",
2788 value_type = "str",
2789 example = r#"
2790 add-bounds = "major"
2791 "#,
2792 possible_values = true
2793 )]
2794 pub add_bounds: Option<AddBoundsKind>,
2795}
2796
2797#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
2798#[serde(rename_all = "kebab-case")]
2799#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2800pub struct AuditOptions {
2801 #[option(
2806 default = "[]",
2807 value_type = "list[str]",
2808 example = r#"
2809 ignore = ["PYSEC-2022-43017", "GHSA-5239-wwwm-4pmq"]
2810 "#
2811 )]
2812 pub ignore: Option<Vec<String>>,
2813
2814 #[option(
2820 default = "[]",
2821 value_type = "list[str]",
2822 example = r#"
2823 ignore-until-fixed = ["PYSEC-2022-43017"]
2824 "#
2825 )]
2826 pub ignore_until_fixed: Option<Vec<String>>,
2827}
2828
2829#[derive(Debug, Clone)]
2830pub struct MalwareCheckSettings {
2831 pub enabled: bool,
2833 pub malware_check_url: Option<DisplaySafeUrl>,
2835}
2836
2837impl From<&crate::EnvironmentOptions> for MalwareCheckSettings {
2838 fn from(options: &crate::EnvironmentOptions) -> Self {
2839 Self {
2840 enabled: options.malware_check.value == Some(true),
2841 malware_check_url: options.malware_check_url.clone(),
2842 }
2843 }
2844}
2845
2846#[derive(Debug, Clone)]
2848#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2849#[cfg_attr(feature = "schemars", schemars(untagged))]
2850pub enum PreviewFeaturesOption {
2851 Toggle(bool),
2852 Features(Vec<MaybePreviewFeature>),
2853}
2854
2855impl<'de> Deserialize<'de> for PreviewFeaturesOption {
2858 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2859 where
2860 D: serde::Deserializer<'de>,
2861 {
2862 serde_untagged::UntaggedEnumVisitor::new()
2863 .expecting("a boolean or a list of preview feature names")
2864 .bool(|value| Ok(Self::Toggle(value)))
2865 .seq(|sequence| sequence.deserialize().map(Self::Features))
2866 .deserialize(deserializer)
2867 }
2868}
2869
2870#[expect(
2871 dead_code,
2872 reason = "Fields are only used by the OptionsMetadata and JsonSchema derives"
2873)]
2874#[derive(OptionsMetadata)]
2875#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2876#[cfg_attr(feature = "schemars", schemars(rename_all = "kebab-case"))]
2877struct PreviewOptionsDefinition {
2878 #[deprecated(note = "use `preview-features` instead")]
2884 preview: Option<bool>,
2885 #[option(
2889 default = "false",
2890 value_type = "bool | list[str]",
2891 example = r#"
2892 preview-features = true
2893 # or
2894 preview-features = ["python-upgrade"]
2895 "#
2896 )]
2897 preview_features: Option<PreviewFeaturesOption>,
2898}
2899
2900#[derive(Debug, Clone)]
2902pub enum PreviewOption {
2903 Preview(bool),
2905 PreviewFeatures(PreviewFeaturesOption),
2907}
2908
2909impl uv_options_metadata::OptionsMetadata for PreviewOption {
2910 fn record(visit: &mut dyn uv_options_metadata::Visit) {
2911 <PreviewOptionsDefinition as uv_options_metadata::OptionsMetadata>::record(visit);
2912 }
2913}
2914
2915#[cfg(feature = "schemars")]
2916impl schemars::JsonSchema for PreviewOption {
2917 fn schema_name() -> Cow<'static, str> {
2918 Cow::Borrowed("PreviewOption")
2919 }
2920
2921 fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
2922 let mut schema = <PreviewOptionsDefinition as schemars::JsonSchema>::json_schema(generator);
2923 schema.insert(
2924 "not".to_string(),
2925 schemars::json_schema!({
2926 "required": ["preview", "preview-features"],
2927 })
2928 .into(),
2929 );
2930 schema
2931 }
2932}
2933
2934impl PreviewOption {
2935 fn try_from(
2936 preview: Option<bool>,
2937 preview_features: Option<PreviewFeaturesOption>,
2938 ) -> Result<Option<Self>, &'static str> {
2939 match (preview, preview_features) {
2940 (Some(_), Some(_)) => Err("cannot specify both `preview` and `preview-features`"),
2941 (Some(b), None) => Ok(Some(Self::Preview(b))),
2942 (None, Some(features)) => Ok(Some(Self::PreviewFeatures(features))),
2943 (None, None) => Ok(None),
2944 }
2945 }
2946
2947 pub fn resolve(&self) -> Preview {
2949 use PreviewFeaturesOption::{Features, Toggle};
2950
2951 match self {
2952 Self::Preview(false) | Self::PreviewFeatures(Toggle(false)) => Preview::default(),
2953 Self::Preview(true) | Self::PreviewFeatures(Toggle(true)) => Preview::all(),
2954 Self::PreviewFeatures(Features(features)) => Preview::from_feature_names(features),
2955 }
2956 }
2957}