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, ExcludeNewer, ExcludeNewerPackage, ExcludeNewerSpan, ExcludeNewerValue,
26 ForkStrategy, PrereleaseMode, ResolutionMode, serialize_exclude_newer_package_with_spans,
27};
28use uv_torch::TorchMode;
29use uv_workspace::pyproject::ExtraBuildDependencies;
30use uv_workspace::pyproject_mut::AddBoundsKind;
31
32#[allow(dead_code)]
34#[derive(Debug, Clone, Default, Deserialize)]
35pub(crate) struct PyProjectToml {
36 pub(crate) tool: Option<Tools>,
37}
38
39#[allow(dead_code)]
41#[derive(Debug, Clone, Default, Deserialize)]
42pub(crate) struct Tools {
43 pub(crate) uv: Option<Options>,
44}
45
46#[derive(Debug, Clone, Default, Deserialize)]
48pub(crate) struct PyProjectRequiredVersionToml {
49 pub(crate) tool: Option<RequiredVersionTools>,
50}
51
52#[derive(Debug, Clone, Default, Deserialize)]
54pub(crate) struct RequiredVersionTools {
55 pub(crate) uv: Option<RequiredVersionOptions>,
56}
57
58#[derive(Debug, Clone, Default, Deserialize)]
60#[serde(rename_all = "kebab-case")]
61pub(crate) struct RequiredVersionOptions {
62 pub(crate) required_version: Option<RequiredVersion>,
63}
64
65#[derive(Debug, Clone, Default, Deserialize)]
67#[serde(rename_all = "kebab-case")]
68pub(crate) struct UvRequiredVersionToml {
69 pub(crate) required_version: Option<RequiredVersion>,
70}
71
72#[allow(dead_code)]
74#[derive(Debug, Clone, Default, Deserialize, CombineOptions, OptionsMetadata)]
75#[serde(try_from = "OptionsWire", rename_all = "kebab-case")]
76#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
77#[cfg_attr(feature = "schemars", schemars(!try_from))]
78pub struct Options {
79 #[serde(flatten)]
80 pub globals: GlobalOptions,
81
82 #[serde(flatten)]
83 pub top_level: ResolverInstallerSchema,
84
85 #[serde(flatten)]
86 pub install_mirrors: PythonInstallMirrors,
87
88 #[serde(flatten)]
89 pub publish: PublishOptions,
90
91 #[serde(flatten)]
92 pub add: AddOptions,
93
94 #[option_group]
95 pub audit: Option<AuditOptions>,
96
97 #[option_group]
98 pub pip: Option<PipOptions>,
99
100 #[option(
136 default = r#"[{ file = "pyproject.toml" }, { file = "setup.py" }, { file = "setup.cfg" }]"#,
137 value_type = "list[dict]",
138 example = r#"
139 cache-keys = [{ file = "pyproject.toml" }, { file = "requirements.txt" }, { git = { commit = true } }]
140 "#
141 )]
142 pub cache_keys: Option<Vec<CacheKey>>,
143
144 #[cfg_attr(feature = "schemars", schemars(skip))]
148 pub override_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
149
150 #[cfg_attr(feature = "schemars", schemars(skip))]
151 pub exclude_dependencies: Option<Vec<uv_normalize::PackageName>>,
152
153 #[cfg_attr(feature = "schemars", schemars(skip))]
154 pub constraint_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
155
156 #[cfg_attr(feature = "schemars", schemars(skip))]
157 pub build_constraint_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
158
159 #[cfg_attr(feature = "schemars", schemars(skip))]
160 pub environments: Option<SupportedEnvironments>,
161
162 #[cfg_attr(feature = "schemars", schemars(skip))]
163 pub required_environments: Option<SupportedEnvironments>,
164
165 #[cfg_attr(feature = "schemars", schemars(skip))]
169 pub(crate) conflicts: Option<serde::de::IgnoredAny>,
170
171 #[cfg_attr(feature = "schemars", schemars(skip))]
172 pub(crate) workspace: Option<serde::de::IgnoredAny>,
173
174 #[cfg_attr(feature = "schemars", schemars(skip))]
175 pub(crate) sources: Option<serde::de::IgnoredAny>,
176
177 #[cfg_attr(feature = "schemars", schemars(skip))]
178 pub(crate) dev_dependencies: Option<serde::de::IgnoredAny>,
179
180 #[cfg_attr(feature = "schemars", schemars(skip))]
181 pub(crate) default_groups: Option<serde::de::IgnoredAny>,
182
183 #[cfg_attr(feature = "schemars", schemars(skip))]
184 pub(crate) dependency_groups: Option<serde::de::IgnoredAny>,
185
186 #[cfg_attr(feature = "schemars", schemars(skip))]
187 pub(crate) managed: Option<serde::de::IgnoredAny>,
188
189 #[cfg_attr(feature = "schemars", schemars(skip))]
190 pub(crate) r#package: Option<serde::de::IgnoredAny>,
191
192 #[cfg_attr(feature = "schemars", schemars(skip))]
193 pub(crate) build_backend: Option<serde::de::IgnoredAny>,
194}
195
196impl Options {
197 pub fn simple(globals: GlobalOptions, top_level: ResolverInstallerSchema) -> Self {
199 Self {
200 globals,
201 top_level,
202 ..Default::default()
203 }
204 }
205
206 #[must_use]
208 pub(crate) fn with_origin(mut self, origin: Origin) -> Self {
209 if let Some(indexes) = &mut self.top_level.index {
210 for index in indexes {
211 index.origin.get_or_insert(origin);
212 }
213 }
214 if let Some(index_url) = &mut self.top_level.index_url {
215 index_url.try_set_origin(origin);
216 }
217 if let Some(extra_index_urls) = &mut self.top_level.extra_index_url {
218 for index_url in extra_index_urls {
219 index_url.try_set_origin(origin);
220 }
221 }
222 if let Some(pip) = &mut self.pip {
223 if let Some(indexes) = &mut pip.index {
224 for index in indexes {
225 index.origin.get_or_insert(origin);
226 }
227 }
228 if let Some(index_url) = &mut pip.index_url {
229 index_url.try_set_origin(origin);
230 }
231 if let Some(extra_index_urls) = &mut pip.extra_index_url {
232 for index_url in extra_index_urls {
233 index_url.try_set_origin(origin);
234 }
235 }
236 }
237 self
238 }
239
240 pub(crate) fn relative_to(self, root_dir: &Path) -> Result<Self, IndexUrlError> {
242 Ok(Self {
243 top_level: self.top_level.relative_to(root_dir)?,
244 pip: self.pip.map(|pip| pip.relative_to(root_dir)).transpose()?,
245 ..self
246 })
247 }
248}
249
250#[derive(Debug, Clone, Default, Deserialize, CombineOptions, OptionsMetadata)]
252#[serde(try_from = "GlobalOptionsWire", rename_all = "kebab-case")]
253#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
254#[cfg_attr(feature = "schemars", schemars(!try_from))]
255pub struct GlobalOptions {
256 #[option(
263 default = "null",
264 value_type = "str",
265 example = r#"
266 required-version = ">=0.5.0"
267 "#
268 )]
269 pub required_version: Option<RequiredVersion>,
270 #[option(
275 default = "false",
276 value_type = "bool",
277 uv_toml_only = true,
278 example = r#"
279 system-certs = true
280 "#
281 )]
282 pub system_certs: Option<bool>,
283 #[deprecated(note = "use `system-certs` instead")]
290 #[option(
291 default = "false",
292 value_type = "bool",
293 uv_toml_only = true,
294 example = r#"
295 native-tls = true
296 "#
297 )]
298 pub native_tls: Option<bool>,
299 #[option(
301 default = "false",
302 value_type = "bool",
303 example = r#"
304 offline = true
305 "#
306 )]
307 pub offline: Option<bool>,
308 #[option(
311 default = "false",
312 value_type = "bool",
313 example = r#"
314 no-cache = true
315 "#
316 )]
317 pub no_cache: Option<bool>,
318 #[option(
323 default = "None",
324 value_type = "str",
325 uv_toml_only = true,
326 example = r#"
327 cache-dir = "./.uv_cache"
328 "#
329 )]
330 pub cache_dir: Option<PathBuf>,
331
332 #[serde(flatten)]
334 pub preview: Option<PreviewOption>,
335
336 #[option(
339 default = "\"managed\"",
340 value_type = "str",
341 example = r#"
342 python-preference = "managed"
343 "#,
344 possible_values = true
345 )]
346 pub python_preference: Option<PythonPreference>,
347 #[option(
349 default = "\"automatic\"",
350 value_type = "str",
351 example = r#"
352 python-downloads = "manual"
353 "#,
354 possible_values = true
355 )]
356 pub python_downloads: Option<PythonDownloads>,
357 #[option(
360 default = "50",
361 value_type = "int",
362 example = r#"
363 concurrent-downloads = 4
364 "#
365 )]
366 pub concurrent_downloads: Option<NonZeroUsize>,
367 #[option(
372 default = "None",
373 value_type = "int",
374 example = r#"
375 concurrent-builds = 4
376 "#
377 )]
378 pub concurrent_builds: Option<NonZeroUsize>,
379 #[option(
383 default = "None",
384 value_type = "int",
385 example = r#"
386 concurrent-installs = 4
387 "#
388 )]
389 pub concurrent_installs: Option<NonZeroUsize>,
390 #[option(
392 default = "None",
393 value_type = "str",
394 uv_toml_only = true,
395 example = r#"
396 http-proxy = "http://proxy.example.com"
397 "#
398 )]
399 pub http_proxy: Option<ProxyUrl>,
400 #[option(
402 default = "None",
403 value_type = "str",
404 uv_toml_only = true,
405 example = r#"
406 https-proxy = "https://proxy.example.com"
407 "#
408 )]
409 pub https_proxy: Option<ProxyUrl>,
410 #[option(
412 default = "None",
413 value_type = "list[str]",
414 uv_toml_only = true,
415 example = r#"
416 no-proxy = ["localhost", "127.0.0.1"]
417 "#
418 )]
419 pub no_proxy: Option<Vec<String>>,
420 #[option(
429 default = "[]",
430 value_type = "list[str]",
431 example = r#"
432 allow-insecure-host = ["localhost:8080"]
433 "#
434 )]
435 pub allow_insecure_host: Option<Vec<TrustedHost>>,
436}
437
438#[derive(Debug, Clone, Default, Deserialize)]
441#[serde(rename_all = "kebab-case")]
442struct GlobalOptionsWire {
443 required_version: Option<RequiredVersion>,
444 system_certs: Option<bool>,
445 native_tls: Option<bool>,
446 offline: Option<bool>,
447 no_cache: Option<bool>,
448 cache_dir: Option<PathBuf>,
449
450 preview: Option<bool>,
451 preview_features: Option<PreviewFeaturesOption>,
452
453 python_preference: Option<PythonPreference>,
454 python_downloads: Option<PythonDownloads>,
455 concurrent_downloads: Option<NonZeroUsize>,
456 concurrent_builds: Option<NonZeroUsize>,
457 concurrent_installs: Option<NonZeroUsize>,
458 http_proxy: Option<ProxyUrl>,
459 https_proxy: Option<ProxyUrl>,
460 no_proxy: Option<Vec<String>>,
461 allow_insecure_host: Option<Vec<TrustedHost>>,
462}
463
464impl TryFrom<GlobalOptionsWire> for GlobalOptions {
465 type Error = &'static str;
466
467 #[allow(deprecated)]
468 fn try_from(value: GlobalOptionsWire) -> Result<Self, Self::Error> {
469 let GlobalOptionsWire {
470 required_version,
471 system_certs,
472 native_tls,
473 offline,
474 no_cache,
475 cache_dir,
476 preview,
477 preview_features,
478 python_preference,
479 python_downloads,
480 concurrent_downloads,
481 concurrent_builds,
482 concurrent_installs,
483 http_proxy,
484 https_proxy,
485 no_proxy,
486 allow_insecure_host,
487 } = value;
488
489 Ok(Self {
490 required_version,
491 system_certs,
492 native_tls,
493 offline,
494 no_cache,
495 cache_dir,
496 preview: PreviewOption::try_from(preview, preview_features)?,
497 python_preference,
498 python_downloads,
499 concurrent_downloads,
500 concurrent_builds,
501 concurrent_installs,
502 http_proxy,
503 https_proxy,
504 no_proxy,
505 allow_insecure_host,
506 })
507 }
508}
509
510#[derive(Debug, Clone, Default, CombineOptions)]
512pub struct InstallerOptions {
513 index: Option<Vec<Index>>,
514 index_url: Option<PipIndex>,
515 extra_index_url: Option<Vec<PipExtraIndex>>,
516 no_index: Option<bool>,
517 find_links: Option<Vec<PipFindLinks>>,
518 index_strategy: Option<IndexStrategy>,
519 keyring_provider: Option<KeyringProviderType>,
520 config_settings: Option<ConfigSettings>,
521 exclude_newer: Option<ExcludeNewerValue>,
522 link_mode: Option<LinkMode>,
523 compile_bytecode: Option<bool>,
524 reinstall: Option<Reinstall>,
525 build_isolation: Option<BuildIsolation>,
526 no_build: Option<bool>,
527 no_build_package: Option<Vec<PackageName>>,
528 no_binary: Option<bool>,
529 no_binary_package: Option<Vec<PackageName>>,
530 no_sources: Option<bool>,
531 no_sources_package: Option<Vec<PackageName>>,
532}
533
534#[derive(Debug, Clone, Default, CombineOptions)]
536pub struct ResolverOptions {
537 pub index: Option<Vec<Index>>,
538 pub index_url: Option<PipIndex>,
539 pub extra_index_url: Option<Vec<PipExtraIndex>>,
540 pub no_index: Option<bool>,
541 pub find_links: Option<Vec<PipFindLinks>>,
542 pub index_strategy: Option<IndexStrategy>,
543 pub keyring_provider: Option<KeyringProviderType>,
544 pub resolution: Option<ResolutionMode>,
545 pub prerelease: Option<PrereleaseMode>,
546 pub fork_strategy: Option<ForkStrategy>,
547 pub dependency_metadata: Option<Vec<StaticMetadata>>,
548 pub config_settings: Option<ConfigSettings>,
549 pub config_settings_package: Option<PackageConfigSettings>,
550 pub exclude_newer: ExcludeNewer,
551 pub link_mode: Option<LinkMode>,
552 pub torch_backend: Option<TorchMode>,
553 pub upgrade: Option<Upgrade>,
554 pub build_isolation: Option<BuildIsolation>,
555 pub no_build: Option<bool>,
556 pub no_build_package: Option<Vec<PackageName>>,
557 pub no_binary: Option<bool>,
558 pub no_binary_package: Option<Vec<PackageName>>,
559 pub extra_build_dependencies: Option<ExtraBuildDependencies>,
560 pub extra_build_variables: Option<ExtraBuildVariables>,
561 pub no_sources: Option<bool>,
562 pub no_sources_package: Option<Vec<PackageName>>,
563}
564
565#[derive(Debug, Clone, Default, CombineOptions)]
568pub struct ResolverInstallerOptions {
569 pub index: Option<Vec<Index>>,
570 pub index_url: Option<PipIndex>,
571 pub extra_index_url: Option<Vec<PipExtraIndex>>,
572 pub no_index: Option<bool>,
573 pub find_links: Option<Vec<PipFindLinks>>,
574 pub index_strategy: Option<IndexStrategy>,
575 pub keyring_provider: Option<KeyringProviderType>,
576 pub resolution: Option<ResolutionMode>,
577 pub prerelease: Option<PrereleaseMode>,
578 pub fork_strategy: Option<ForkStrategy>,
579 pub dependency_metadata: Option<Vec<StaticMetadata>>,
580 pub config_settings: Option<ConfigSettings>,
581 pub config_settings_package: Option<PackageConfigSettings>,
582 pub build_isolation: Option<BuildIsolation>,
583 pub extra_build_dependencies: Option<ExtraBuildDependencies>,
584 pub extra_build_variables: Option<ExtraBuildVariables>,
585 pub exclude_newer: Option<ExcludeNewerValue>,
586 pub exclude_newer_package: Option<ExcludeNewerPackage>,
587 pub link_mode: Option<LinkMode>,
588 pub torch_backend: Option<TorchMode>,
589 pub compile_bytecode: Option<bool>,
590 pub no_sources: Option<bool>,
591 pub no_sources_package: Option<Vec<PackageName>>,
592 pub upgrade: Option<Upgrade>,
593 pub reinstall: Option<Reinstall>,
594 pub no_build: Option<bool>,
595 pub no_build_package: Option<Vec<PackageName>>,
596 pub no_binary: Option<bool>,
597 pub no_binary_package: Option<Vec<PackageName>>,
598}
599
600impl From<ResolverInstallerSchema> for ResolverInstallerOptions {
601 fn from(value: ResolverInstallerSchema) -> Self {
602 let ResolverInstallerSchema {
603 index,
604 index_url,
605 extra_index_url,
606 no_index,
607 find_links,
608 index_strategy,
609 keyring_provider,
610 resolution,
611 prerelease,
612 fork_strategy,
613 dependency_metadata,
614 config_settings,
615 config_settings_package,
616 no_build_isolation,
617 no_build_isolation_package,
618 extra_build_dependencies,
619 extra_build_variables,
620 exclude_newer,
621 exclude_newer_package,
622 link_mode,
623 torch_backend,
624 compile_bytecode,
625 no_sources,
626 no_sources_package,
627 upgrade,
628 upgrade_package,
629 reinstall,
630 reinstall_package,
631 no_build,
632 no_build_package,
633 no_binary,
634 no_binary_package,
635 } = value;
636 Self {
637 index,
638 index_url,
639 extra_index_url,
640 no_index,
641 find_links,
642 index_strategy,
643 keyring_provider,
644 resolution,
645 prerelease,
646 fork_strategy,
647 dependency_metadata,
648 config_settings,
649 config_settings_package,
650 build_isolation: BuildIsolation::from_args(
651 no_build_isolation,
652 no_build_isolation_package.into_iter().flatten().collect(),
653 ),
654 extra_build_dependencies,
655 extra_build_variables,
656 exclude_newer,
657 exclude_newer_package,
658 link_mode,
659 torch_backend,
660 compile_bytecode,
661 no_sources,
662 no_sources_package,
663 upgrade: Upgrade::from_args(
664 upgrade,
665 upgrade_package
666 .into_iter()
667 .flatten()
668 .map(Into::into)
669 .collect(),
670 Vec::new(),
671 ),
672 reinstall: Reinstall::from_args(reinstall, reinstall_package.unwrap_or_default()),
673 no_build,
674 no_build_package,
675 no_binary,
676 no_binary_package,
677 }
678 }
679}
680
681impl ResolverInstallerSchema {
682 fn relative_to(self, root_dir: &Path) -> Result<Self, IndexUrlError> {
684 Ok(Self {
685 index: self
686 .index
687 .map(|index| {
688 index
689 .into_iter()
690 .map(|index| index.relative_to(root_dir))
691 .collect::<Result<Vec<_>, _>>()
692 })
693 .transpose()?,
694 index_url: self
695 .index_url
696 .map(|index_url| index_url.relative_to(root_dir))
697 .transpose()?,
698 extra_index_url: self
699 .extra_index_url
700 .map(|extra_index_url| {
701 extra_index_url
702 .into_iter()
703 .map(|extra_index_url| extra_index_url.relative_to(root_dir))
704 .collect::<Result<Vec<_>, _>>()
705 })
706 .transpose()?,
707 find_links: self
708 .find_links
709 .map(|find_links| {
710 find_links
711 .into_iter()
712 .map(|find_link| find_link.relative_to(root_dir))
713 .collect::<Result<Vec<_>, _>>()
714 })
715 .transpose()?,
716 ..self
717 })
718 }
719}
720
721#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
723#[serde(rename_all = "kebab-case")]
724#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
725pub struct ResolverInstallerSchema {
726 #[option(
754 default = "\"[]\"",
755 value_type = "dict",
756 example = r#"
757 [[tool.uv.index]]
758 name = "pytorch"
759 url = "https://download.pytorch.org/whl/cu130"
760 "#
761 )]
762 pub index: Option<Vec<Index>>,
763 #[option(
773 default = "\"https://pypi.org/simple\"",
774 value_type = "str",
775 example = r#"
776 index-url = "https://test.pypi.org/simple"
777 "#
778 )]
779 pub index_url: Option<PipIndex>,
780 #[option(
794 default = "[]",
795 value_type = "list[str]",
796 example = r#"
797 extra-index-url = ["https://download.pytorch.org/whl/cpu"]
798 "#
799 )]
800 pub extra_index_url: Option<Vec<PipExtraIndex>>,
801 #[option(
804 default = "false",
805 value_type = "bool",
806 example = r#"
807 no-index = true
808 "#
809 )]
810 pub no_index: Option<bool>,
811 #[option(
820 default = "[]",
821 value_type = "list[str]",
822 example = r#"
823 find-links = ["https://download.pytorch.org/whl/torch_stable.html"]
824 "#
825 )]
826 pub find_links: Option<Vec<PipFindLinks>>,
827 #[option(
834 default = "\"first-index\"",
835 value_type = "str",
836 example = r#"
837 index-strategy = "unsafe-best-match"
838 "#,
839 possible_values = true
840 )]
841 pub index_strategy: Option<IndexStrategy>,
842 #[option(
847 default = "\"disabled\"",
848 value_type = "str",
849 example = r#"
850 keyring-provider = "subprocess"
851 "#
852 )]
853 pub keyring_provider: Option<KeyringProviderType>,
854 #[option(
859 default = "\"highest\"",
860 value_type = "str",
861 example = r#"
862 resolution = "lowest-direct"
863 "#,
864 possible_values = true
865 )]
866 pub resolution: Option<ResolutionMode>,
867 #[option(
873 default = "\"if-necessary-or-explicit\"",
874 value_type = "str",
875 example = r#"
876 prerelease = "allow"
877 "#,
878 possible_values = true
879 )]
880 pub prerelease: Option<PrereleaseMode>,
881 #[option(
892 default = "\"requires-python\"",
893 value_type = "str",
894 example = r#"
895 fork-strategy = "fewest"
896 "#,
897 possible_values = true
898 )]
899 pub fork_strategy: Option<ForkStrategy>,
900 #[option(
914 default = r#"[]"#,
915 value_type = "list[dict]",
916 example = r#"
917 dependency-metadata = [
918 { name = "flask", version = "1.0.0", requires-dist = ["werkzeug"], requires-python = ">=3.6" },
919 ]
920 "#
921 )]
922 pub dependency_metadata: Option<Vec<StaticMetadata>>,
923 #[option(
926 default = "{}",
927 value_type = "dict",
928 example = r#"
929 config-settings = { editable_mode = "compat" }
930 "#
931 )]
932 pub config_settings: Option<ConfigSettings>,
933 #[option(
938 default = "{}",
939 value_type = "dict",
940 example = r#"
941 config-settings-package = { numpy = { editable_mode = "compat" } }
942 "#
943 )]
944 pub config_settings_package: Option<PackageConfigSettings>,
945 #[option(
950 default = "false",
951 value_type = "bool",
952 example = r#"
953 no-build-isolation = true
954 "#
955 )]
956 pub no_build_isolation: Option<bool>,
957 #[option(
962 default = "[]",
963 value_type = "list[str]",
964 example = r#"
965 no-build-isolation-package = ["package1", "package2"]
966 "#
967 )]
968 pub no_build_isolation_package: Option<Vec<PackageName>>,
969 #[option(
975 default = "[]",
976 value_type = "dict",
977 example = r#"
978 extra-build-dependencies = { pytest = ["setuptools"] }
979 "#
980 )]
981 pub extra_build_dependencies: Option<ExtraBuildDependencies>,
982 #[option(
987 default = r#"{}"#,
988 value_type = r#"dict[str, dict[str, str]]"#,
989 example = r#"
990 extra-build-variables = { flash-attn = { FLASH_ATTENTION_SKIP_CUDA_BUILD = "TRUE" } }
991 "#
992 )]
993 pub extra_build_variables: Option<ExtraBuildVariables>,
994 #[option(
1007 default = "None",
1008 value_type = "str",
1009 example = r#"
1010 exclude-newer = "2006-12-02T02:07:43Z"
1011 "#
1012 )]
1013 pub exclude_newer: Option<ExcludeNewerValue>,
1014 #[option(
1028 default = "None",
1029 value_type = "dict",
1030 example = r#"
1031 exclude-newer-package = { tqdm = "2022-04-04T00:00:00Z", markupsafe = false }
1032 "#
1033 )]
1034 pub exclude_newer_package: Option<ExcludeNewerPackage>,
1035 #[option(
1045 default = "\"clone\" (macOS, Linux) or \"hardlink\" (Windows)",
1046 value_type = "str",
1047 example = r#"
1048 link-mode = "copy"
1049 "#,
1050 possible_values = true
1051 )]
1052 pub link_mode: Option<LinkMode>,
1053 #[option(
1064 default = "false",
1065 value_type = "bool",
1066 example = r#"
1067 compile-bytecode = true
1068 "#
1069 )]
1070 pub compile_bytecode: Option<bool>,
1071 #[option(
1075 default = "false",
1076 value_type = "bool",
1077 example = r#"
1078 no-sources = true
1079 "#
1080 )]
1081 pub no_sources: Option<bool>,
1082 #[option(
1084 default = "[]",
1085 value_type = "list[str]",
1086 example = r#"
1087 no-sources-package = ["ruff"]
1088 "#
1089 )]
1090 pub no_sources_package: Option<Vec<PackageName>>,
1091 #[option(
1093 default = "false",
1094 value_type = "bool",
1095 example = r#"
1096 upgrade = true
1097 "#
1098 )]
1099 pub upgrade: Option<bool>,
1100 #[option(
1105 default = "[]",
1106 value_type = "list[str]",
1107 example = r#"
1108 upgrade-package = ["ruff"]
1109 "#
1110 )]
1111 pub upgrade_package: Option<Vec<Requirement<VerbatimParsedUrl>>>,
1112 #[option(
1114 default = "false",
1115 value_type = "bool",
1116 example = r#"
1117 reinstall = true
1118 "#
1119 )]
1120 pub reinstall: Option<bool>,
1121 #[option(
1124 default = "[]",
1125 value_type = "list[str]",
1126 example = r#"
1127 reinstall-package = ["ruff"]
1128 "#
1129 )]
1130 pub reinstall_package: Option<Vec<PackageName>>,
1131 #[option(
1137 default = "false",
1138 value_type = "bool",
1139 example = r#"
1140 no-build = true
1141 "#
1142 )]
1143 pub no_build: Option<bool>,
1144 #[option(
1146 default = "[]",
1147 value_type = "list[str]",
1148 example = r#"
1149 no-build-package = ["ruff"]
1150 "#
1151 )]
1152 pub no_build_package: Option<Vec<PackageName>>,
1153 #[option(
1158 default = "false",
1159 value_type = "bool",
1160 example = r#"
1161 no-binary = true
1162 "#
1163 )]
1164 pub no_binary: Option<bool>,
1165 #[option(
1167 default = "[]",
1168 value_type = "list[str]",
1169 example = r#"
1170 no-binary-package = ["ruff"]
1171 "#
1172 )]
1173 pub no_binary_package: Option<Vec<PackageName>>,
1174 #[option(
1189 default = "null",
1190 value_type = "str",
1191 example = r#"
1192 torch-backend = "auto"
1193 "#
1194 )]
1195 pub torch_backend: Option<TorchMode>,
1196}
1197
1198#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
1200#[serde(rename_all = "kebab-case")]
1201#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1202pub struct PythonInstallMirrors {
1203 #[option(
1211 default = "None",
1212 value_type = "str",
1213 uv_toml_only = true,
1214 example = r#"
1215 python-install-mirror = "https://github.com/astral-sh/python-build-standalone/releases/download"
1216 "#
1217 )]
1218 pub python_install_mirror: Option<String>,
1219 #[option(
1228 default = "None",
1229 value_type = "str",
1230 uv_toml_only = true,
1231 example = r#"
1232 pypy-install-mirror = "https://downloads.python.org/pypy"
1233 "#
1234 )]
1235 pub pypy_install_mirror: Option<String>,
1236
1237 #[option(
1239 default = "None",
1240 value_type = "str",
1241 uv_toml_only = true,
1242 example = r#"
1243 python-downloads-json-url = "/etc/uv/python-downloads.json"
1244 "#
1245 )]
1246 pub python_downloads_json_url: Option<String>,
1247}
1248
1249impl PythonInstallMirrors {
1250 #[must_use]
1251 pub fn combine(self, other: Self) -> Self {
1252 Self {
1253 python_install_mirror: self.python_install_mirror.or(other.python_install_mirror),
1254 pypy_install_mirror: self.pypy_install_mirror.or(other.pypy_install_mirror),
1255 python_downloads_json_url: self
1256 .python_downloads_json_url
1257 .or(other.python_downloads_json_url),
1258 }
1259 }
1260}
1261
1262#[derive(Debug, Clone, Default, Deserialize, CombineOptions, OptionsMetadata)]
1267#[serde(deny_unknown_fields, rename_all = "kebab-case")]
1268#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1269pub struct PipOptions {
1270 #[option(
1283 default = "None",
1284 value_type = "str",
1285 example = r#"
1286 python = "3.10"
1287 "#
1288 )]
1289 pub python: Option<String>,
1290 #[option(
1299 default = "false",
1300 value_type = "bool",
1301 example = r#"
1302 system = true
1303 "#
1304 )]
1305 pub system: Option<bool>,
1306 #[option(
1313 default = "false",
1314 value_type = "bool",
1315 example = r#"
1316 break-system-packages = true
1317 "#
1318 )]
1319 pub break_system_packages: Option<bool>,
1320 #[option(
1323 default = "None",
1324 value_type = "str",
1325 example = r#"
1326 target = "./target"
1327 "#
1328 )]
1329 pub target: Option<PathBuf>,
1330 #[option(
1338 default = "None",
1339 value_type = "str",
1340 example = r#"
1341 prefix = "./prefix"
1342 "#
1343 )]
1344 pub prefix: Option<PathBuf>,
1345 #[serde(skip)]
1346 #[cfg_attr(feature = "schemars", schemars(skip))]
1347 pub index: Option<Vec<Index>>,
1348 #[option(
1356 default = "\"https://pypi.org/simple\"",
1357 value_type = "str",
1358 example = r#"
1359 index-url = "https://test.pypi.org/simple"
1360 "#
1361 )]
1362 pub index_url: Option<PipIndex>,
1363 #[option(
1374 default = "[]",
1375 value_type = "list[str]",
1376 example = r#"
1377 extra-index-url = ["https://download.pytorch.org/whl/cpu"]
1378 "#
1379 )]
1380 pub extra_index_url: Option<Vec<PipExtraIndex>>,
1381 #[option(
1384 default = "false",
1385 value_type = "bool",
1386 example = r#"
1387 no-index = true
1388 "#
1389 )]
1390 pub no_index: Option<bool>,
1391 #[option(
1400 default = "[]",
1401 value_type = "list[str]",
1402 example = r#"
1403 find-links = ["https://download.pytorch.org/whl/torch_stable.html"]
1404 "#
1405 )]
1406 pub find_links: Option<Vec<PipFindLinks>>,
1407 #[option(
1414 default = "\"first-index\"",
1415 value_type = "str",
1416 example = r#"
1417 index-strategy = "unsafe-best-match"
1418 "#,
1419 possible_values = true
1420 )]
1421 pub index_strategy: Option<IndexStrategy>,
1422 #[option(
1427 default = "disabled",
1428 value_type = "str",
1429 example = r#"
1430 keyring-provider = "subprocess"
1431 "#
1432 )]
1433 pub keyring_provider: Option<KeyringProviderType>,
1434 #[option(
1442 default = "false",
1443 value_type = "bool",
1444 example = r#"
1445 no-build = true
1446 "#
1447 )]
1448 pub no_build: Option<bool>,
1449 #[option(
1457 default = "[]",
1458 value_type = "list[str]",
1459 example = r#"
1460 no-binary = ["ruff"]
1461 "#
1462 )]
1463 pub no_binary: Option<Vec<PackageNameSpecifier>>,
1464 #[option(
1473 default = "[]",
1474 value_type = "list[str]",
1475 example = r#"
1476 only-binary = ["ruff"]
1477 "#
1478 )]
1479 pub only_binary: Option<Vec<PackageNameSpecifier>>,
1480 #[option(
1485 default = "false",
1486 value_type = "bool",
1487 example = r#"
1488 no-build-isolation = true
1489 "#
1490 )]
1491 pub no_build_isolation: Option<bool>,
1492 #[option(
1497 default = "[]",
1498 value_type = "list[str]",
1499 example = r#"
1500 no-build-isolation-package = ["package1", "package2"]
1501 "#
1502 )]
1503 pub no_build_isolation_package: Option<Vec<PackageName>>,
1504 #[option(
1510 default = "[]",
1511 value_type = "dict",
1512 example = r#"
1513 extra-build-dependencies = { pytest = ["setuptools"] }
1514 "#
1515 )]
1516 pub extra_build_dependencies: Option<ExtraBuildDependencies>,
1517 #[option(
1522 default = r#"{}"#,
1523 value_type = r#"dict[str, dict[str, str]]"#,
1524 example = r#"
1525 extra-build-variables = { flash-attn = { FLASH_ATTENTION_SKIP_CUDA_BUILD = "TRUE" } }
1526 "#
1527 )]
1528 pub extra_build_variables: Option<ExtraBuildVariables>,
1529 #[option(
1532 default = "false",
1533 value_type = "bool",
1534 example = r#"
1535 strict = true
1536 "#
1537 )]
1538 pub strict: Option<bool>,
1539 #[option(
1543 default = "[]",
1544 value_type = "list[str]",
1545 example = r#"
1546 extra = ["dev", "docs"]
1547 "#
1548 )]
1549 pub extra: Option<Vec<ExtraName>>,
1550 #[option(
1554 default = "false",
1555 value_type = "bool",
1556 example = r#"
1557 all-extras = true
1558 "#
1559 )]
1560 pub all_extras: Option<bool>,
1561 #[option(
1563 default = "[]",
1564 value_type = "list[str]",
1565 example = r#"
1566 all-extras = true
1567 no-extra = ["dev", "docs"]
1568 "#
1569 )]
1570 pub no_extra: Option<Vec<ExtraName>>,
1571 #[option(
1574 default = "false",
1575 value_type = "bool",
1576 example = r#"
1577 no-deps = true
1578 "#
1579 )]
1580 pub no_deps: Option<bool>,
1581 #[option(
1583 default = "None",
1584 value_type = "list[str]",
1585 example = r#"
1586 group = ["dev", "docs"]
1587 "#
1588 )]
1589 pub group: Option<Vec<PipGroupName>>,
1590 #[option(
1593 default = "false",
1594 value_type = "bool",
1595 example = r#"
1596 allow-empty-requirements = true
1597 "#
1598 )]
1599 pub allow_empty_requirements: Option<bool>,
1600 #[option(
1605 default = "\"highest\"",
1606 value_type = "str",
1607 example = r#"
1608 resolution = "lowest-direct"
1609 "#,
1610 possible_values = true
1611 )]
1612 pub resolution: Option<ResolutionMode>,
1613 #[option(
1619 default = "\"if-necessary-or-explicit\"",
1620 value_type = "str",
1621 example = r#"
1622 prerelease = "allow"
1623 "#,
1624 possible_values = true
1625 )]
1626 pub prerelease: Option<PrereleaseMode>,
1627 #[option(
1638 default = "\"requires-python\"",
1639 value_type = "str",
1640 example = r#"
1641 fork-strategy = "fewest"
1642 "#,
1643 possible_values = true
1644 )]
1645 pub fork_strategy: Option<ForkStrategy>,
1646 #[option(
1660 default = r#"[]"#,
1661 value_type = "list[dict]",
1662 example = r#"
1663 dependency-metadata = [
1664 { name = "flask", version = "1.0.0", requires-dist = ["werkzeug"], requires-python = ">=3.6" },
1665 ]
1666 "#
1667 )]
1668 pub dependency_metadata: Option<Vec<StaticMetadata>>,
1669 #[option(
1674 default = "None",
1675 value_type = "str",
1676 example = r#"
1677 output-file = "requirements.txt"
1678 "#
1679 )]
1680 pub output_file: Option<PathBuf>,
1681 #[option(
1687 default = "false",
1688 value_type = "bool",
1689 example = r#"
1690 no-strip-extras = true
1691 "#
1692 )]
1693 pub no_strip_extras: Option<bool>,
1694 #[option(
1699 default = "false",
1700 value_type = "bool",
1701 example = r#"
1702 no-strip-markers = true
1703 "#
1704 )]
1705 pub no_strip_markers: Option<bool>,
1706 #[option(
1709 default = "false",
1710 value_type = "bool",
1711 example = r#"
1712 no-annotate = true
1713 "#
1714 )]
1715 pub no_annotate: Option<bool>,
1716 #[option(
1718 default = r#"false"#,
1719 value_type = "bool",
1720 example = r#"
1721 no-header = true
1722 "#
1723 )]
1724 pub no_header: Option<bool>,
1725 #[option(
1729 default = "None",
1730 value_type = "str",
1731 example = r#"
1732 custom-compile-command = "./custom-uv-compile.sh"
1733 "#
1734 )]
1735 pub custom_compile_command: Option<String>,
1736 #[option(
1738 default = "false",
1739 value_type = "bool",
1740 example = r#"
1741 generate-hashes = true
1742 "#
1743 )]
1744 pub generate_hashes: Option<bool>,
1745 #[option(
1748 default = "{}",
1749 value_type = "dict",
1750 example = r#"
1751 config-settings = { editable_mode = "compat" }
1752 "#
1753 )]
1754 pub config_settings: Option<ConfigSettings>,
1755 #[option(
1758 default = "{}",
1759 value_type = "dict",
1760 example = r#"
1761 config-settings-package = { numpy = { editable_mode = "compat" } }
1762 "#
1763 )]
1764 pub config_settings_package: Option<PackageConfigSettings>,
1765 #[option(
1771 default = "None",
1772 value_type = "str",
1773 example = r#"
1774 python-version = "3.8"
1775 "#
1776 )]
1777 pub python_version: Option<PythonVersion>,
1778 #[option(
1784 default = "None",
1785 value_type = "str",
1786 example = r#"
1787 python-platform = "x86_64-unknown-linux-gnu"
1788 "#
1789 )]
1790 pub python_platform: Option<TargetTriple>,
1791 #[option(
1799 default = "false",
1800 value_type = "bool",
1801 example = r#"
1802 universal = true
1803 "#
1804 )]
1805 pub universal: Option<bool>,
1806 #[option(
1819 default = "None",
1820 value_type = "str",
1821 example = r#"
1822 exclude-newer = "2006-12-02T02:07:43Z"
1823 "#
1824 )]
1825 pub exclude_newer: Option<ExcludeNewerValue>,
1826 #[option(
1839 default = "None",
1840 value_type = "dict",
1841 example = r#"
1842 exclude-newer-package = { tqdm = "2022-04-04T00:00:00Z", markupsafe = false }
1843 "#
1844 )]
1845 pub exclude_newer_package: Option<ExcludeNewerPackage>,
1846 #[option(
1849 default = "[]",
1850 value_type = "list[str]",
1851 example = r#"
1852 no-emit-package = ["ruff"]
1853 "#
1854 )]
1855 pub no_emit_package: Option<Vec<PackageName>>,
1856 #[option(
1858 default = "false",
1859 value_type = "bool",
1860 example = r#"
1861 emit-index-url = true
1862 "#
1863 )]
1864 pub emit_index_url: Option<bool>,
1865 #[option(
1867 default = "false",
1868 value_type = "bool",
1869 example = r#"
1870 emit-find-links = true
1871 "#
1872 )]
1873 pub emit_find_links: Option<bool>,
1874 #[option(
1876 default = "false",
1877 value_type = "bool",
1878 example = r#"
1879 emit-build-options = true
1880 "#
1881 )]
1882 pub emit_build_options: Option<bool>,
1883 #[option(
1890 default = "false",
1891 value_type = "bool",
1892 example = r#"
1893 emit-marker-expression = true
1894 "#
1895 )]
1896 pub emit_marker_expression: Option<bool>,
1897 #[option(
1900 default = "false",
1901 value_type = "bool",
1902 example = r#"
1903 emit-index-annotation = true
1904 "#
1905 )]
1906 pub emit_index_annotation: Option<bool>,
1907 #[option(
1910 default = "\"split\"",
1911 value_type = "str",
1912 example = r#"
1913 annotation-style = "line"
1914 "#,
1915 possible_values = true
1916 )]
1917 pub annotation_style: Option<AnnotationStyle>,
1918 #[option(
1928 default = "\"clone\" (macOS, Linux) or \"hardlink\" (Windows)",
1929 value_type = "str",
1930 example = r#"
1931 link-mode = "copy"
1932 "#,
1933 possible_values = true
1934 )]
1935 pub link_mode: Option<LinkMode>,
1936 #[option(
1947 default = "false",
1948 value_type = "bool",
1949 example = r#"
1950 compile-bytecode = true
1951 "#
1952 )]
1953 pub compile_bytecode: Option<bool>,
1954 #[option(
1967 default = "false",
1968 value_type = "bool",
1969 example = r#"
1970 require-hashes = true
1971 "#
1972 )]
1973 pub require_hashes: Option<bool>,
1974 #[option(
1980 default = "true",
1981 value_type = "bool",
1982 example = r#"
1983 verify-hashes = true
1984 "#
1985 )]
1986 pub verify_hashes: Option<bool>,
1987 #[option(
1991 default = "false",
1992 value_type = "bool",
1993 example = r#"
1994 no-sources = true
1995 "#
1996 )]
1997 pub no_sources: Option<bool>,
1998 #[option(
2000 default = "[]",
2001 value_type = "list[str]",
2002 example = r#"
2003 no-sources-package = ["ruff"]
2004 "#
2005 )]
2006 pub no_sources_package: Option<Vec<PackageName>>,
2007 #[option(
2009 default = "false",
2010 value_type = "bool",
2011 example = r#"
2012 upgrade = true
2013 "#
2014 )]
2015 pub upgrade: Option<bool>,
2016 #[option(
2021 default = "[]",
2022 value_type = "list[str]",
2023 example = r#"
2024 upgrade-package = ["ruff"]
2025 "#
2026 )]
2027 pub upgrade_package: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2028 #[option(
2030 default = "false",
2031 value_type = "bool",
2032 example = r#"
2033 reinstall = true
2034 "#
2035 )]
2036 pub reinstall: Option<bool>,
2037 #[option(
2040 default = "[]",
2041 value_type = "list[str]",
2042 example = r#"
2043 reinstall-package = ["ruff"]
2044 "#
2045 )]
2046 pub reinstall_package: Option<Vec<PackageName>>,
2047 #[option(
2062 default = "null",
2063 value_type = "str",
2064 example = r#"
2065 torch-backend = "auto"
2066 "#
2067 )]
2068 pub torch_backend: Option<TorchMode>,
2069}
2070
2071impl PipOptions {
2072 fn relative_to(self, root_dir: &Path) -> Result<Self, IndexUrlError> {
2074 Ok(Self {
2075 index: self
2076 .index
2077 .map(|index| {
2078 index
2079 .into_iter()
2080 .map(|index| index.relative_to(root_dir))
2081 .collect::<Result<Vec<_>, _>>()
2082 })
2083 .transpose()?,
2084 index_url: self
2085 .index_url
2086 .map(|index_url| index_url.relative_to(root_dir))
2087 .transpose()?,
2088 extra_index_url: self
2089 .extra_index_url
2090 .map(|extra_index_url| {
2091 extra_index_url
2092 .into_iter()
2093 .map(|extra_index_url| extra_index_url.relative_to(root_dir))
2094 .collect::<Result<Vec<_>, _>>()
2095 })
2096 .transpose()?,
2097 find_links: self
2098 .find_links
2099 .map(|find_links| {
2100 find_links
2101 .into_iter()
2102 .map(|find_link| find_link.relative_to(root_dir))
2103 .collect::<Result<Vec<_>, _>>()
2104 })
2105 .transpose()?,
2106 ..self
2107 })
2108 }
2109}
2110
2111impl From<ResolverInstallerSchema> for ResolverOptions {
2112 fn from(value: ResolverInstallerSchema) -> Self {
2113 Self {
2114 index: value.index,
2115 index_url: value.index_url,
2116 extra_index_url: value.extra_index_url,
2117 no_index: value.no_index,
2118 find_links: value.find_links,
2119 index_strategy: value.index_strategy,
2120 keyring_provider: value.keyring_provider,
2121 resolution: value.resolution,
2122 prerelease: value.prerelease,
2123 fork_strategy: value.fork_strategy,
2124 dependency_metadata: value.dependency_metadata,
2125 config_settings: value.config_settings,
2126 config_settings_package: value.config_settings_package,
2127 exclude_newer: ExcludeNewer::from_args(
2128 value.exclude_newer,
2129 value
2130 .exclude_newer_package
2131 .unwrap_or_default()
2132 .into_iter()
2133 .map(Into::into)
2134 .collect(),
2135 ),
2136 link_mode: value.link_mode,
2137 upgrade: Upgrade::from_args(
2138 value.upgrade,
2139 value
2140 .upgrade_package
2141 .into_iter()
2142 .flatten()
2143 .map(Into::into)
2144 .collect(),
2145 Vec::new(),
2146 ),
2147 no_build: value.no_build,
2148 no_build_package: value.no_build_package,
2149 no_binary: value.no_binary,
2150 no_binary_package: value.no_binary_package,
2151 build_isolation: BuildIsolation::from_args(
2152 value.no_build_isolation,
2153 value.no_build_isolation_package.unwrap_or_default(),
2154 ),
2155 extra_build_dependencies: value.extra_build_dependencies,
2156 extra_build_variables: value.extra_build_variables,
2157 no_sources: value.no_sources,
2158 no_sources_package: value.no_sources_package,
2159 torch_backend: value.torch_backend,
2160 }
2161 }
2162}
2163
2164impl From<ResolverInstallerSchema> for InstallerOptions {
2165 fn from(value: ResolverInstallerSchema) -> Self {
2166 Self {
2167 index: value.index,
2168 index_url: value.index_url,
2169 extra_index_url: value.extra_index_url,
2170 no_index: value.no_index,
2171 find_links: value.find_links,
2172 index_strategy: value.index_strategy,
2173 keyring_provider: value.keyring_provider,
2174 config_settings: value.config_settings,
2175 exclude_newer: ExcludeNewer::from_args(
2176 value.exclude_newer,
2177 value
2178 .exclude_newer_package
2179 .unwrap_or_default()
2180 .into_iter()
2181 .map(Into::into)
2182 .collect(),
2183 )
2184 .global,
2185 link_mode: value.link_mode,
2186 compile_bytecode: value.compile_bytecode,
2187 reinstall: Reinstall::from_args(
2188 value.reinstall,
2189 value.reinstall_package.unwrap_or_default(),
2190 ),
2191 build_isolation: BuildIsolation::from_args(
2192 value.no_build_isolation,
2193 value.no_build_isolation_package.unwrap_or_default(),
2194 ),
2195 no_build: value.no_build,
2196 no_build_package: value.no_build_package,
2197 no_binary: value.no_binary,
2198 no_binary_package: value.no_binary_package,
2199 no_sources: value.no_sources,
2200 no_sources_package: value.no_sources_package,
2201 }
2202 }
2203}
2204
2205#[derive(
2210 Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, CombineOptions, OptionsMetadata,
2211)]
2212#[serde(deny_unknown_fields, rename_all = "kebab-case")]
2213#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2214pub struct ToolOptions {
2215 index: Option<Vec<Index>>,
2216 index_url: Option<PipIndex>,
2217 extra_index_url: Option<Vec<PipExtraIndex>>,
2218 no_index: Option<bool>,
2219 find_links: Option<Vec<PipFindLinks>>,
2220 index_strategy: Option<IndexStrategy>,
2221 keyring_provider: Option<KeyringProviderType>,
2222 resolution: Option<ResolutionMode>,
2223 prerelease: Option<PrereleaseMode>,
2224 fork_strategy: Option<ForkStrategy>,
2225 dependency_metadata: Option<Vec<StaticMetadata>>,
2226 config_settings: Option<ConfigSettings>,
2227 config_settings_package: Option<PackageConfigSettings>,
2228 build_isolation: Option<BuildIsolation>,
2229 extra_build_dependencies: Option<ExtraBuildDependencies>,
2230 extra_build_variables: Option<ExtraBuildVariables>,
2231 exclude_newer: Option<ExcludeNewerValue>,
2232 exclude_newer_package: Option<ExcludeNewerPackage>,
2233 link_mode: Option<LinkMode>,
2234 compile_bytecode: Option<bool>,
2235 no_sources: Option<bool>,
2236 no_sources_package: Option<Vec<PackageName>>,
2237 no_build: Option<bool>,
2238 no_build_package: Option<Vec<PackageName>>,
2239 no_binary: Option<bool>,
2240 no_binary_package: Option<Vec<PackageName>>,
2241 torch_backend: Option<TorchMode>,
2242}
2243
2244#[derive(Debug, Clone, Default, Serialize, Deserialize)]
2246#[serde(deny_unknown_fields, rename_all = "kebab-case")]
2247pub struct ToolOptionsWire {
2248 index: Option<Vec<Index>>,
2249 index_url: Option<PipIndex>,
2250 extra_index_url: Option<Vec<PipExtraIndex>>,
2251 no_index: Option<bool>,
2252 find_links: Option<Vec<PipFindLinks>>,
2253 index_strategy: Option<IndexStrategy>,
2254 keyring_provider: Option<KeyringProviderType>,
2255 resolution: Option<ResolutionMode>,
2256 prerelease: Option<PrereleaseMode>,
2257 fork_strategy: Option<ForkStrategy>,
2258 dependency_metadata: Option<Vec<StaticMetadata>>,
2259 config_settings: Option<ConfigSettings>,
2260 config_settings_package: Option<PackageConfigSettings>,
2261 build_isolation: Option<BuildIsolation>,
2262 extra_build_dependencies: Option<ExtraBuildDependencies>,
2263 extra_build_variables: Option<ExtraBuildVariables>,
2264 exclude_newer: Option<ExcludeNewerValue>,
2265 exclude_newer_span: Option<ExcludeNewerSpan>,
2266 #[serde(serialize_with = "serialize_exclude_newer_package_with_spans")]
2267 exclude_newer_package: Option<ExcludeNewerPackage>,
2268 link_mode: Option<LinkMode>,
2269 compile_bytecode: Option<bool>,
2270 no_sources: Option<bool>,
2271 no_sources_package: Option<Vec<PackageName>>,
2272 no_build: Option<bool>,
2273 no_build_package: Option<Vec<PackageName>>,
2274 no_binary: Option<bool>,
2275 no_binary_package: Option<Vec<PackageName>>,
2276 torch_backend: Option<TorchMode>,
2277}
2278
2279impl From<ResolverInstallerOptions> for ToolOptions {
2280 fn from(value: ResolverInstallerOptions) -> Self {
2281 Self {
2282 index: value.index.map(|indexes| {
2283 indexes
2284 .into_iter()
2285 .map(Index::with_promoted_auth_policy)
2286 .collect()
2287 }),
2288 index_url: value.index_url,
2289 extra_index_url: value.extra_index_url,
2290 no_index: value.no_index,
2291 find_links: value.find_links,
2292 index_strategy: value.index_strategy,
2293 keyring_provider: value.keyring_provider,
2294 resolution: value.resolution,
2295 prerelease: value.prerelease,
2296 fork_strategy: value.fork_strategy,
2297 dependency_metadata: value.dependency_metadata,
2298 config_settings: value.config_settings,
2299 config_settings_package: value.config_settings_package,
2300 build_isolation: value.build_isolation,
2301 extra_build_dependencies: value.extra_build_dependencies,
2302 extra_build_variables: value.extra_build_variables,
2303 exclude_newer: value.exclude_newer,
2304 exclude_newer_package: value.exclude_newer_package,
2305 link_mode: value.link_mode,
2306 compile_bytecode: value.compile_bytecode,
2307 no_sources: value.no_sources,
2308 no_sources_package: value.no_sources_package,
2309 no_build: value.no_build,
2310 no_build_package: value.no_build_package,
2311 no_binary: value.no_binary,
2312 no_binary_package: value.no_binary_package,
2313 torch_backend: value.torch_backend,
2314 }
2315 }
2316}
2317
2318impl From<ToolOptionsWire> for ToolOptions {
2319 fn from(value: ToolOptionsWire) -> Self {
2320 let exclude_newer = value.exclude_newer.map(|exclude_newer| {
2321 if let Some(span) = value.exclude_newer_span
2322 && exclude_newer.span().is_none()
2323 {
2324 ExcludeNewerValue::relative(span)
2325 } else {
2326 exclude_newer
2327 }
2328 });
2329
2330 Self {
2331 index: value.index,
2332 index_url: value.index_url,
2333 extra_index_url: value.extra_index_url,
2334 no_index: value.no_index,
2335 find_links: value.find_links,
2336 index_strategy: value.index_strategy,
2337 keyring_provider: value.keyring_provider,
2338 resolution: value.resolution,
2339 prerelease: value.prerelease,
2340 fork_strategy: value.fork_strategy,
2341 dependency_metadata: value.dependency_metadata,
2342 config_settings: value.config_settings,
2343 config_settings_package: value.config_settings_package,
2344 build_isolation: value.build_isolation,
2345 extra_build_dependencies: value.extra_build_dependencies,
2346 extra_build_variables: value.extra_build_variables,
2347 exclude_newer,
2348 exclude_newer_package: value.exclude_newer_package,
2349 link_mode: value.link_mode,
2350 compile_bytecode: value.compile_bytecode,
2351 no_sources: value.no_sources,
2352 no_sources_package: value.no_sources_package,
2353 no_build: value.no_build,
2354 no_build_package: value.no_build_package,
2355 no_binary: value.no_binary,
2356 no_binary_package: value.no_binary_package,
2357 torch_backend: value.torch_backend,
2358 }
2359 }
2360}
2361
2362impl From<ToolOptions> for ToolOptionsWire {
2363 fn from(value: ToolOptions) -> Self {
2364 let (exclude_newer, exclude_newer_span) = match &value.exclude_newer {
2365 Some(value @ ExcludeNewerValue::Absolute(_)) => (Some(value.clone()), None),
2366 Some(value @ ExcludeNewerValue::Relative(span)) => (
2367 Some(ExcludeNewerValue::absolute(value.timestamp())),
2368 Some(*span),
2369 ),
2370 None => (None, None),
2371 };
2372
2373 Self {
2374 index: value.index,
2375 index_url: value.index_url,
2376 extra_index_url: value.extra_index_url,
2377 no_index: value.no_index,
2378 find_links: value.find_links,
2379 index_strategy: value.index_strategy,
2380 keyring_provider: value.keyring_provider,
2381 resolution: value.resolution,
2382 prerelease: value.prerelease,
2383 fork_strategy: value.fork_strategy,
2384 dependency_metadata: value.dependency_metadata,
2385 config_settings: value.config_settings,
2386 config_settings_package: value.config_settings_package,
2387 build_isolation: value.build_isolation,
2388 extra_build_dependencies: value.extra_build_dependencies,
2389 extra_build_variables: value.extra_build_variables,
2390 exclude_newer,
2391 exclude_newer_span,
2392 exclude_newer_package: value.exclude_newer_package,
2393 link_mode: value.link_mode,
2394 compile_bytecode: value.compile_bytecode,
2395 no_sources: value.no_sources,
2396 no_sources_package: value.no_sources_package,
2397 no_build: value.no_build,
2398 no_build_package: value.no_build_package,
2399 no_binary: value.no_binary,
2400 no_binary_package: value.no_binary_package,
2401 torch_backend: value.torch_backend,
2402 }
2403 }
2404}
2405
2406impl From<ToolOptions> for ResolverInstallerOptions {
2407 fn from(value: ToolOptions) -> Self {
2408 Self {
2409 index: value.index,
2410 index_url: value.index_url,
2411 extra_index_url: value.extra_index_url,
2412 no_index: value.no_index,
2413 find_links: value.find_links,
2414 index_strategy: value.index_strategy,
2415 keyring_provider: value.keyring_provider,
2416 resolution: value.resolution,
2417 prerelease: value.prerelease,
2418 fork_strategy: value.fork_strategy,
2419 dependency_metadata: value.dependency_metadata,
2420 config_settings: value.config_settings,
2421 config_settings_package: value.config_settings_package,
2422 build_isolation: value.build_isolation,
2423 extra_build_dependencies: value.extra_build_dependencies,
2424 extra_build_variables: value.extra_build_variables,
2425 exclude_newer: value.exclude_newer,
2426 exclude_newer_package: value.exclude_newer_package,
2427 link_mode: value.link_mode,
2428 compile_bytecode: value.compile_bytecode,
2429 no_sources: value.no_sources,
2430 no_sources_package: value.no_sources_package,
2431 upgrade: None,
2432 reinstall: None,
2433 no_build: value.no_build,
2434 no_build_package: value.no_build_package,
2435 no_binary: value.no_binary,
2436 no_binary_package: value.no_binary_package,
2437 torch_backend: value.torch_backend,
2438 }
2439 }
2440}
2441
2442#[derive(Debug, Clone, Default, Deserialize)]
2445#[serde(rename_all = "kebab-case", deny_unknown_fields)]
2446struct OptionsWire {
2447 required_version: Option<RequiredVersion>,
2450 system_certs: Option<bool>,
2451 native_tls: Option<bool>,
2452 offline: Option<bool>,
2453 no_cache: Option<bool>,
2454 cache_dir: Option<PathBuf>,
2455 preview: Option<bool>,
2456 preview_features: Option<PreviewFeaturesOption>,
2457 python_preference: Option<PythonPreference>,
2458 python_downloads: Option<PythonDownloads>,
2459 concurrent_downloads: Option<NonZeroUsize>,
2460 concurrent_builds: Option<NonZeroUsize>,
2461 concurrent_installs: Option<NonZeroUsize>,
2462
2463 index: Option<Vec<Index>>,
2466 index_url: Option<PipIndex>,
2467 extra_index_url: Option<Vec<PipExtraIndex>>,
2468 no_index: Option<bool>,
2469 find_links: Option<Vec<PipFindLinks>>,
2470 index_strategy: Option<IndexStrategy>,
2471 keyring_provider: Option<KeyringProviderType>,
2472 http_proxy: Option<ProxyUrl>,
2473 https_proxy: Option<ProxyUrl>,
2474 no_proxy: Option<Vec<String>>,
2475 allow_insecure_host: Option<Vec<TrustedHost>>,
2476 resolution: Option<ResolutionMode>,
2477 prerelease: Option<PrereleaseMode>,
2478 fork_strategy: Option<ForkStrategy>,
2479 dependency_metadata: Option<Vec<StaticMetadata>>,
2480 config_settings: Option<ConfigSettings>,
2481 config_settings_package: Option<PackageConfigSettings>,
2482 no_build_isolation: Option<bool>,
2483 no_build_isolation_package: Option<Vec<PackageName>>,
2484 extra_build_dependencies: Option<ExtraBuildDependencies>,
2485 extra_build_variables: Option<ExtraBuildVariables>,
2486 exclude_newer: Option<ExcludeNewerValue>,
2487 exclude_newer_package: Option<ExcludeNewerPackage>,
2488 link_mode: Option<LinkMode>,
2489 compile_bytecode: Option<bool>,
2490 no_sources: Option<bool>,
2491 no_sources_package: Option<Vec<PackageName>>,
2492 upgrade: Option<bool>,
2493 upgrade_package: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2494 reinstall: Option<bool>,
2495 reinstall_package: Option<Vec<PackageName>>,
2496 no_build: Option<bool>,
2497 no_build_package: Option<Vec<PackageName>>,
2498 no_binary: Option<bool>,
2499 no_binary_package: Option<Vec<PackageName>>,
2500 torch_backend: Option<TorchMode>,
2501
2502 python_install_mirror: Option<String>,
2505 pypy_install_mirror: Option<String>,
2506 python_downloads_json_url: Option<String>,
2507
2508 publish_url: Option<DisplaySafeUrl>,
2511 trusted_publishing: Option<TrustedPublishing>,
2512 check_url: Option<IndexUrl>,
2513
2514 add_bounds: Option<AddBoundsKind>,
2517
2518 audit: Option<AuditOptions>,
2519 pip: Option<PipOptions>,
2520 cache_keys: Option<Vec<CacheKey>>,
2521
2522 override_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2526 exclude_dependencies: Option<Vec<PackageName>>,
2527 constraint_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2528 build_constraint_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2529 environments: Option<SupportedEnvironments>,
2530 required_environments: Option<SupportedEnvironments>,
2531
2532 conflicts: Option<serde::de::IgnoredAny>,
2536 workspace: Option<serde::de::IgnoredAny>,
2537 sources: Option<serde::de::IgnoredAny>,
2538 managed: Option<serde::de::IgnoredAny>,
2539 r#package: Option<serde::de::IgnoredAny>,
2540 default_groups: Option<serde::de::IgnoredAny>,
2541 dependency_groups: Option<serde::de::IgnoredAny>,
2542 dev_dependencies: Option<serde::de::IgnoredAny>,
2543
2544 build_backend: Option<serde::de::IgnoredAny>,
2546}
2547
2548impl TryFrom<OptionsWire> for Options {
2549 type Error = &'static str;
2550
2551 #[allow(deprecated)]
2552 fn try_from(value: OptionsWire) -> Result<Self, Self::Error> {
2553 let OptionsWire {
2554 required_version,
2555 system_certs,
2556 native_tls,
2557 offline,
2558 no_cache,
2559 cache_dir,
2560 preview,
2561 preview_features,
2562 python_preference,
2563 python_downloads,
2564 python_install_mirror,
2565 pypy_install_mirror,
2566 python_downloads_json_url,
2567 concurrent_downloads,
2568 concurrent_builds,
2569 concurrent_installs,
2570 index,
2571 index_url,
2572 extra_index_url,
2573 no_index,
2574 find_links,
2575 index_strategy,
2576 keyring_provider,
2577 http_proxy,
2578 https_proxy,
2579 no_proxy,
2580 allow_insecure_host,
2581 resolution,
2582 prerelease,
2583 fork_strategy,
2584 dependency_metadata,
2585 config_settings,
2586 config_settings_package,
2587 no_build_isolation,
2588 no_build_isolation_package,
2589 exclude_newer,
2590 exclude_newer_package,
2591 link_mode,
2592 compile_bytecode,
2593 no_sources,
2594 no_sources_package,
2595 upgrade,
2596 upgrade_package,
2597 reinstall,
2598 reinstall_package,
2599 no_build,
2600 no_build_package,
2601 no_binary,
2602 no_binary_package,
2603 torch_backend,
2604 audit,
2605 pip,
2606 cache_keys,
2607 override_dependencies,
2608 exclude_dependencies,
2609 constraint_dependencies,
2610 build_constraint_dependencies,
2611 environments,
2612 required_environments,
2613 conflicts,
2614 publish_url,
2615 trusted_publishing,
2616 check_url,
2617 workspace,
2618 sources,
2619 default_groups,
2620 dependency_groups,
2621 extra_build_dependencies,
2622 extra_build_variables,
2623 dev_dependencies,
2624 managed,
2625 package,
2626 add_bounds: bounds,
2627 build_backend,
2629 } = value;
2630
2631 Ok(Self {
2632 globals: GlobalOptions {
2633 required_version,
2634 system_certs,
2635 native_tls,
2636 offline,
2637 no_cache,
2638 cache_dir,
2639 preview: PreviewOption::try_from(preview, preview_features)?,
2640 python_preference,
2641 python_downloads,
2642 concurrent_downloads,
2643 concurrent_builds,
2644 concurrent_installs,
2645 http_proxy,
2646 https_proxy,
2647 no_proxy,
2648 allow_insecure_host: allow_insecure_host.clone(),
2650 },
2651 top_level: ResolverInstallerSchema {
2652 index,
2653 index_url,
2654 extra_index_url,
2655 no_index,
2656 find_links,
2657 index_strategy,
2658 keyring_provider,
2659 resolution,
2660 prerelease,
2661 fork_strategy,
2662 dependency_metadata,
2663 config_settings,
2664 config_settings_package,
2665 no_build_isolation,
2666 no_build_isolation_package,
2667 extra_build_dependencies,
2668 extra_build_variables,
2669 exclude_newer,
2670 exclude_newer_package,
2671 link_mode,
2672 compile_bytecode,
2673 no_sources,
2674 no_sources_package,
2675 upgrade,
2676 upgrade_package,
2677 reinstall,
2678 reinstall_package,
2679 no_build,
2680 no_build_package,
2681 no_binary,
2682 no_binary_package,
2683 torch_backend,
2684 },
2685 pip,
2686 cache_keys,
2687 build_backend,
2688 override_dependencies,
2689 exclude_dependencies,
2690 constraint_dependencies,
2691 build_constraint_dependencies,
2692 environments,
2693 required_environments,
2694 install_mirrors: PythonInstallMirrors {
2695 python_install_mirror,
2696 pypy_install_mirror,
2697 python_downloads_json_url,
2698 },
2699 conflicts,
2700 publish: PublishOptions {
2701 publish_url,
2702 trusted_publishing,
2703 check_url,
2704 },
2705 add: AddOptions { add_bounds: bounds },
2706 audit,
2707 workspace,
2708 sources,
2709 dev_dependencies,
2710 default_groups,
2711 dependency_groups,
2712 managed,
2713 package,
2714 })
2715 }
2716}
2717
2718#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
2719#[serde(rename_all = "kebab-case")]
2720#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2721pub struct PublishOptions {
2722 #[option(
2725 default = "\"https://upload.pypi.org/legacy/\"",
2726 value_type = "str",
2727 example = r#"
2728 publish-url = "https://test.pypi.org/legacy/"
2729 "#
2730 )]
2731 pub publish_url: Option<DisplaySafeUrl>,
2732
2733 #[option(
2740 default = "automatic",
2741 value_type = "str",
2742 example = r#"
2743 trusted-publishing = "always"
2744 "#
2745 )]
2746 pub trusted_publishing: Option<TrustedPublishing>,
2747
2748 #[option(
2762 default = "None",
2763 value_type = "str",
2764 example = r#"
2765 check-url = "https://test.pypi.org/simple"
2766 "#
2767 )]
2768 pub check_url: Option<IndexUrl>,
2769}
2770
2771#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
2772#[serde(rename_all = "kebab-case")]
2773#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2774pub struct AddOptions {
2775 #[option(
2786 default = "\"lower\"",
2787 value_type = "str",
2788 example = r#"
2789 add-bounds = "major"
2790 "#,
2791 possible_values = true
2792 )]
2793 pub add_bounds: Option<AddBoundsKind>,
2794}
2795
2796#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
2797#[serde(rename_all = "kebab-case")]
2798#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2799pub struct AuditOptions {
2800 #[option(
2805 default = "[]",
2806 value_type = "list[str]",
2807 example = r#"
2808 ignore = ["PYSEC-2022-43017", "GHSA-5239-wwwm-4pmq"]
2809 "#
2810 )]
2811 pub ignore: Option<Vec<String>>,
2812
2813 #[option(
2819 default = "[]",
2820 value_type = "list[str]",
2821 example = r#"
2822 ignore-until-fixed = ["PYSEC-2022-43017"]
2823 "#
2824 )]
2825 pub ignore_until_fixed: Option<Vec<String>>,
2826}
2827
2828#[derive(Debug, Clone)]
2829pub struct MalwareCheckSettings {
2830 pub enabled: bool,
2832 pub malware_check_url: Option<DisplaySafeUrl>,
2834}
2835
2836impl From<&crate::EnvironmentOptions> for MalwareCheckSettings {
2837 fn from(options: &crate::EnvironmentOptions) -> Self {
2838 Self {
2839 enabled: options.malware_check.value == Some(true),
2840 malware_check_url: options.malware_check_url.clone(),
2841 }
2842 }
2843}
2844
2845#[derive(Debug, Clone)]
2847#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2848#[cfg_attr(feature = "schemars", schemars(untagged))]
2849pub enum PreviewFeaturesOption {
2850 Toggle(bool),
2851 Features(Vec<MaybePreviewFeature>),
2852}
2853
2854impl<'de> Deserialize<'de> for PreviewFeaturesOption {
2857 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2858 where
2859 D: serde::Deserializer<'de>,
2860 {
2861 serde_untagged::UntaggedEnumVisitor::new()
2862 .expecting("a boolean or a list of preview feature names")
2863 .bool(|value| Ok(Self::Toggle(value)))
2864 .seq(|sequence| sequence.deserialize().map(Self::Features))
2865 .deserialize(deserializer)
2866 }
2867}
2868
2869#[expect(
2870 dead_code,
2871 reason = "Fields are only used by the OptionsMetadata and JsonSchema derives"
2872)]
2873#[derive(OptionsMetadata)]
2874#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2875#[cfg_attr(feature = "schemars", schemars(rename_all = "kebab-case"))]
2876struct PreviewOptionsDefinition {
2877 #[deprecated(note = "use `preview-features` instead")]
2883 preview: Option<bool>,
2884 #[option(
2888 default = "false",
2889 value_type = "bool | list[str]",
2890 example = r#"
2891 preview-features = true
2892 # or
2893 preview-features = ["python-upgrade"]
2894 "#
2895 )]
2896 preview_features: Option<PreviewFeaturesOption>,
2897}
2898
2899#[derive(Debug, Clone)]
2901pub enum PreviewOption {
2902 Preview(bool),
2904 PreviewFeatures(PreviewFeaturesOption),
2906}
2907
2908impl uv_options_metadata::OptionsMetadata for PreviewOption {
2909 fn record(visit: &mut dyn uv_options_metadata::Visit) {
2910 <PreviewOptionsDefinition as uv_options_metadata::OptionsMetadata>::record(visit);
2911 }
2912}
2913
2914#[cfg(feature = "schemars")]
2915impl schemars::JsonSchema for PreviewOption {
2916 fn schema_name() -> Cow<'static, str> {
2917 Cow::Borrowed("PreviewOption")
2918 }
2919
2920 fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
2921 let mut schema = <PreviewOptionsDefinition as schemars::JsonSchema>::json_schema(generator);
2922 schema.insert(
2923 "not".to_string(),
2924 schemars::json_schema!({
2925 "required": ["preview", "preview-features"],
2926 })
2927 .into(),
2928 );
2929 schema
2930 }
2931}
2932
2933impl PreviewOption {
2934 fn try_from(
2935 preview: Option<bool>,
2936 preview_features: Option<PreviewFeaturesOption>,
2937 ) -> Result<Option<Self>, &'static str> {
2938 match (preview, preview_features) {
2939 (Some(_), Some(_)) => Err("cannot specify both `preview` and `preview-features`"),
2940 (Some(b), None) => Ok(Some(Self::Preview(b))),
2941 (None, Some(features)) => Ok(Some(Self::PreviewFeatures(features))),
2942 (None, None) => Ok(None),
2943 }
2944 }
2945
2946 pub fn resolve(&self) -> Preview {
2948 use PreviewFeaturesOption::{Features, Toggle};
2949
2950 match self {
2951 Self::Preview(false) | Self::PreviewFeatures(Toggle(false)) => Preview::default(),
2952 Self::Preview(true) | Self::PreviewFeatures(Toggle(true)) => Preview::all(),
2953 Self::PreviewFeatures(Features(features)) => Preview::from_feature_names(features),
2954 }
2955 }
2956}