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, ExcludeDependency, IndexStrategy, KeyringProviderType, PackageNameSpecifier,
10 ProxyUrl, Reinstall, 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, OverrideDependency};
31use uv_workspace::pyproject_mut::AddBoundsKind;
32
33use crate::{EnvironmentOptions, FilesystemOptions};
34
35#[allow(dead_code)]
37#[derive(Debug, Clone, Default, Deserialize)]
38pub(crate) struct PyProjectToml {
39 pub(crate) tool: Option<Tools>,
40}
41
42#[allow(dead_code)]
44#[derive(Debug, Clone, Default, Deserialize)]
45pub(crate) struct Tools {
46 pub(crate) uv: Option<Options>,
47}
48
49#[derive(Debug, Clone, Default, Deserialize)]
51pub(crate) struct PyProjectRequiredVersionToml {
52 pub(crate) tool: Option<RequiredVersionTools>,
53}
54
55#[derive(Debug, Clone, Default, Deserialize)]
57pub(crate) struct RequiredVersionTools {
58 pub(crate) uv: Option<RequiredVersionOptions>,
59}
60
61#[derive(Debug, Clone, Default, Deserialize)]
63#[serde(rename_all = "kebab-case")]
64pub(crate) struct RequiredVersionOptions {
65 pub(crate) required_version: Option<RequiredVersion>,
66}
67
68#[derive(Debug, Clone, Default, Deserialize)]
70#[serde(rename_all = "kebab-case")]
71pub(crate) struct UvRequiredVersionToml {
72 pub(crate) required_version: Option<RequiredVersion>,
73}
74
75#[allow(dead_code)]
77#[derive(Debug, Clone, Default, Deserialize, CombineOptions, OptionsMetadata)]
78#[serde(try_from = "OptionsWire", rename_all = "kebab-case")]
79#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
80#[cfg_attr(feature = "schemars", schemars(!try_from))]
81pub struct Options {
82 #[serde(flatten)]
83 pub globals: GlobalOptions,
84
85 #[serde(flatten)]
86 pub top_level: ResolverInstallerSchema,
87
88 #[serde(flatten)]
89 pub install_mirrors: PythonInstallMirrors,
90
91 #[serde(flatten)]
92 pub publish: PublishOptions,
93
94 #[serde(flatten)]
95 pub add: AddOptions,
96
97 #[option_group]
98 pub audit: Option<AuditOptions>,
99
100 #[option_group]
101 pub pip: Option<PipOptions>,
102
103 #[option(
139 default = r#"[{ file = "pyproject.toml" }, { file = "setup.py" }, { file = "setup.cfg" }]"#,
140 value_type = "list[dict]",
141 example = r#"
142 cache-keys = [{ file = "pyproject.toml" }, { file = "requirements.txt" }, { git = { commit = true } }]
143 "#
144 )]
145 pub cache_keys: Option<Vec<CacheKey>>,
146
147 #[cfg_attr(feature = "schemars", schemars(skip))]
151 pub override_dependencies: Option<Vec<OverrideDependency>>,
152
153 #[cfg_attr(feature = "schemars", schemars(skip))]
154 pub exclude_dependencies: Option<Vec<ExcludeDependency>>,
155
156 #[cfg_attr(feature = "schemars", schemars(skip))]
157 pub constraint_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
158
159 #[cfg_attr(feature = "schemars", schemars(skip))]
160 pub build_constraint_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
161
162 #[cfg_attr(feature = "schemars", schemars(skip))]
163 pub environments: Option<SupportedEnvironments>,
164
165 #[cfg_attr(feature = "schemars", schemars(skip))]
166 pub required_environments: Option<SupportedEnvironments>,
167
168 #[cfg_attr(feature = "schemars", schemars(skip))]
172 pub(crate) conflicts: Option<serde::de::IgnoredAny>,
173
174 #[cfg_attr(feature = "schemars", schemars(skip))]
175 pub(crate) workspace: Option<serde::de::IgnoredAny>,
176
177 #[cfg_attr(feature = "schemars", schemars(skip))]
178 pub(crate) sources: Option<serde::de::IgnoredAny>,
179
180 #[cfg_attr(feature = "schemars", schemars(skip))]
181 pub(crate) dev_dependencies: Option<serde::de::IgnoredAny>,
182
183 #[cfg_attr(feature = "schemars", schemars(skip))]
184 pub(crate) default_groups: Option<serde::de::IgnoredAny>,
185
186 #[cfg_attr(feature = "schemars", schemars(skip))]
187 pub(crate) dependency_groups: Option<serde::de::IgnoredAny>,
188
189 #[cfg_attr(feature = "schemars", schemars(skip))]
190 pub(crate) managed: Option<serde::de::IgnoredAny>,
191
192 #[cfg_attr(feature = "schemars", schemars(skip))]
193 pub(crate) r#package: Option<serde::de::IgnoredAny>,
194
195 #[cfg_attr(feature = "schemars", schemars(skip))]
196 pub(crate) build_backend: Option<serde::de::IgnoredAny>,
197}
198
199impl Options {
200 pub fn simple(globals: GlobalOptions, top_level: ResolverInstallerSchema) -> Self {
202 Self {
203 globals,
204 top_level,
205 ..Default::default()
206 }
207 }
208
209 #[must_use]
211 pub(crate) fn with_origin(mut self, origin: Origin) -> Self {
212 if let Some(indexes) = &mut self.top_level.index {
213 for index in indexes {
214 index.origin.get_or_insert(origin);
215 }
216 }
217 if let Some(index_url) = &mut self.top_level.index_url {
218 index_url.try_set_origin(origin);
219 }
220 if let Some(extra_index_urls) = &mut self.top_level.extra_index_url {
221 for index_url in extra_index_urls {
222 index_url.try_set_origin(origin);
223 }
224 }
225 if let Some(pip) = &mut self.pip {
226 if let Some(indexes) = &mut pip.index {
227 for index in indexes {
228 index.origin.get_or_insert(origin);
229 }
230 }
231 if let Some(index_url) = &mut pip.index_url {
232 index_url.try_set_origin(origin);
233 }
234 if let Some(extra_index_urls) = &mut pip.extra_index_url {
235 for index_url in extra_index_urls {
236 index_url.try_set_origin(origin);
237 }
238 }
239 }
240 self
241 }
242
243 pub(crate) fn relative_to(self, root_dir: &Path) -> Result<Self, IndexUrlError> {
245 Ok(Self {
246 top_level: self.top_level.relative_to(root_dir)?,
247 pip: self.pip.map(|pip| pip.relative_to(root_dir)).transpose()?,
248 ..self
249 })
250 }
251}
252
253#[derive(Debug, Clone, Default, Deserialize, CombineOptions, OptionsMetadata)]
255#[serde(try_from = "GlobalOptionsWire", rename_all = "kebab-case")]
256#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
257#[cfg_attr(feature = "schemars", schemars(!try_from))]
258pub struct GlobalOptions {
259 #[option(
266 default = "null",
267 value_type = "str",
268 example = r#"
269 required-version = ">=0.5.0"
270 "#
271 )]
272 pub required_version: Option<RequiredVersion>,
273 #[option(
278 default = "false",
279 value_type = "bool",
280 uv_toml_only = true,
281 example = r#"
282 system-certs = true
283 "#
284 )]
285 pub system_certs: Option<bool>,
286 #[deprecated(note = "use `system-certs` instead")]
293 #[option(
294 default = "false",
295 value_type = "bool",
296 uv_toml_only = true,
297 example = r#"
298 native-tls = true
299 "#
300 )]
301 pub native_tls: Option<bool>,
302 #[option(
304 default = "false",
305 value_type = "bool",
306 example = r#"
307 offline = true
308 "#
309 )]
310 pub offline: Option<bool>,
311 #[option(
314 default = "false",
315 value_type = "bool",
316 example = r#"
317 no-cache = true
318 "#
319 )]
320 pub no_cache: Option<bool>,
321 #[option(
326 default = "None",
327 value_type = "str",
328 uv_toml_only = true,
329 example = r#"
330 cache-dir = "./.uv_cache"
331 "#
332 )]
333 pub cache_dir: Option<PathBuf>,
334
335 #[serde(flatten)]
337 pub preview: Option<PreviewOption>,
338
339 #[option(
342 default = "\"managed\"",
343 value_type = "str",
344 example = r#"
345 python-preference = "managed"
346 "#,
347 possible_values = true
348 )]
349 pub python_preference: Option<PythonPreference>,
350 #[option(
352 default = "\"automatic\"",
353 value_type = "str",
354 example = r#"
355 python-downloads = "manual"
356 "#,
357 possible_values = true
358 )]
359 pub python_downloads: Option<PythonDownloads>,
360 #[option(
363 default = "50",
364 value_type = "int",
365 example = r#"
366 concurrent-downloads = 4
367 "#
368 )]
369 pub concurrent_downloads: Option<NonZeroUsize>,
370 #[option(
375 default = "None",
376 value_type = "int",
377 example = r#"
378 concurrent-builds = 4
379 "#
380 )]
381 pub concurrent_builds: Option<NonZeroUsize>,
382 #[option(
386 default = "None",
387 value_type = "int",
388 example = r#"
389 concurrent-installs = 4
390 "#
391 )]
392 pub concurrent_installs: Option<NonZeroUsize>,
393 #[option(
395 default = "None",
396 value_type = "str",
397 uv_toml_only = true,
398 example = r#"
399 http-proxy = "http://proxy.example.com"
400 "#
401 )]
402 pub http_proxy: Option<ProxyUrl>,
403 #[option(
405 default = "None",
406 value_type = "str",
407 uv_toml_only = true,
408 example = r#"
409 https-proxy = "https://proxy.example.com"
410 "#
411 )]
412 pub https_proxy: Option<ProxyUrl>,
413 #[option(
415 default = "None",
416 value_type = "list[str]",
417 uv_toml_only = true,
418 example = r#"
419 no-proxy = ["localhost", "127.0.0.1"]
420 "#
421 )]
422 pub no_proxy: Option<Vec<String>>,
423 #[option(
432 default = "[]",
433 value_type = "list[str]",
434 example = r#"
435 allow-insecure-host = ["localhost:8080"]
436 "#
437 )]
438 pub allow_insecure_host: Option<Vec<TrustedHost>>,
439}
440
441#[derive(Debug, Clone, Default, Deserialize)]
444#[serde(rename_all = "kebab-case")]
445struct GlobalOptionsWire {
446 required_version: Option<RequiredVersion>,
447 system_certs: Option<bool>,
448 native_tls: Option<bool>,
449 offline: Option<bool>,
450 no_cache: Option<bool>,
451 cache_dir: Option<PathBuf>,
452
453 preview: Option<bool>,
454 preview_features: Option<PreviewFeaturesOption>,
455
456 python_preference: Option<PythonPreference>,
457 python_downloads: Option<PythonDownloads>,
458 concurrent_downloads: Option<NonZeroUsize>,
459 concurrent_builds: Option<NonZeroUsize>,
460 concurrent_installs: Option<NonZeroUsize>,
461 http_proxy: Option<ProxyUrl>,
462 https_proxy: Option<ProxyUrl>,
463 no_proxy: Option<Vec<String>>,
464 allow_insecure_host: Option<Vec<TrustedHost>>,
465}
466
467impl TryFrom<GlobalOptionsWire> for GlobalOptions {
468 type Error = &'static str;
469
470 #[allow(deprecated)]
471 fn try_from(value: GlobalOptionsWire) -> Result<Self, Self::Error> {
472 let GlobalOptionsWire {
473 required_version,
474 system_certs,
475 native_tls,
476 offline,
477 no_cache,
478 cache_dir,
479 preview,
480 preview_features,
481 python_preference,
482 python_downloads,
483 concurrent_downloads,
484 concurrent_builds,
485 concurrent_installs,
486 http_proxy,
487 https_proxy,
488 no_proxy,
489 allow_insecure_host,
490 } = value;
491
492 Ok(Self {
493 required_version,
494 system_certs,
495 native_tls,
496 offline,
497 no_cache,
498 cache_dir,
499 preview: PreviewOption::try_from(preview, preview_features)?,
500 python_preference,
501 python_downloads,
502 concurrent_downloads,
503 concurrent_builds,
504 concurrent_installs,
505 http_proxy,
506 https_proxy,
507 no_proxy,
508 allow_insecure_host,
509 })
510 }
511}
512
513#[derive(Debug, Clone, Default, CombineOptions)]
515pub struct InstallerOptions {
516 index: Option<Vec<Index>>,
517 index_url: Option<PipIndex>,
518 extra_index_url: Option<Vec<PipExtraIndex>>,
519 no_index: Option<bool>,
520 find_links: Option<Vec<PipFindLinks>>,
521 index_strategy: Option<IndexStrategy>,
522 keyring_provider: Option<KeyringProviderType>,
523 config_settings: Option<ConfigSettings>,
524 exclude_newer: Option<ExcludeNewerOverride>,
525 link_mode: Option<LinkMode>,
526 compile_bytecode: Option<bool>,
527 reinstall: Option<Reinstall>,
528 build_isolation: Option<BuildIsolation>,
529 no_build: Option<bool>,
530 no_build_package: Option<Vec<PackageName>>,
531 no_binary: Option<bool>,
532 no_binary_package: Option<Vec<PackageName>>,
533 no_sources: Option<bool>,
534 no_sources_package: Option<Vec<PackageName>>,
535}
536
537#[derive(Debug, Clone, Default, CombineOptions)]
539pub struct ResolverOptions {
540 pub index: Option<Vec<Index>>,
541 pub index_url: Option<PipIndex>,
542 pub extra_index_url: Option<Vec<PipExtraIndex>>,
543 pub no_index: Option<bool>,
544 pub find_links: Option<Vec<PipFindLinks>>,
545 pub index_strategy: Option<IndexStrategy>,
546 pub keyring_provider: Option<KeyringProviderType>,
547 pub resolution: Option<ResolutionMode>,
548 pub prerelease: Option<PrereleaseMode>,
549 pub fork_strategy: Option<ForkStrategy>,
550 pub dependency_metadata: Option<Vec<StaticMetadata>>,
551 pub config_settings: Option<ConfigSettings>,
552 pub config_settings_package: Option<PackageConfigSettings>,
553 pub exclude_newer: Option<ExcludeNewerOverride>,
554 pub exclude_newer_package: Option<ExcludeNewerPackage>,
555 pub link_mode: Option<LinkMode>,
556 pub torch_backend: Option<TorchMode>,
557 pub upgrade: Option<Upgrade>,
558 pub build_isolation: Option<BuildIsolation>,
559 pub no_build: Option<bool>,
560 pub no_build_package: Option<Vec<PackageName>>,
561 pub no_binary: Option<bool>,
562 pub no_binary_package: Option<Vec<PackageName>>,
563 pub extra_build_dependencies: Option<ExtraBuildDependencies>,
564 pub extra_build_variables: Option<ExtraBuildVariables>,
565 pub no_sources: Option<bool>,
566 pub no_sources_package: Option<Vec<PackageName>>,
567}
568
569#[derive(Debug, Clone, Default, CombineOptions)]
572pub struct ResolverInstallerOptions {
573 pub index: Option<Vec<Index>>,
574 pub index_url: Option<PipIndex>,
575 pub extra_index_url: Option<Vec<PipExtraIndex>>,
576 pub no_index: Option<bool>,
577 pub find_links: Option<Vec<PipFindLinks>>,
578 pub index_strategy: Option<IndexStrategy>,
579 pub keyring_provider: Option<KeyringProviderType>,
580 pub resolution: Option<ResolutionMode>,
581 pub prerelease: Option<PrereleaseMode>,
582 pub fork_strategy: Option<ForkStrategy>,
583 pub dependency_metadata: Option<Vec<StaticMetadata>>,
584 pub config_settings: Option<ConfigSettings>,
585 pub config_settings_package: Option<PackageConfigSettings>,
586 pub build_isolation: Option<BuildIsolation>,
587 pub extra_build_dependencies: Option<ExtraBuildDependencies>,
588 pub extra_build_variables: Option<ExtraBuildVariables>,
589 pub exclude_newer: Option<ExcludeNewerOverride>,
590 pub exclude_newer_package: Option<ExcludeNewerPackage>,
591 pub link_mode: Option<LinkMode>,
592 pub torch_backend: Option<TorchMode>,
593 pub compile_bytecode: Option<bool>,
594 pub no_sources: Option<bool>,
595 pub no_sources_package: Option<Vec<PackageName>>,
596 pub upgrade: Option<Upgrade>,
597 pub reinstall: Option<Reinstall>,
598 pub no_build: Option<bool>,
599 pub no_build_package: Option<Vec<PackageName>>,
600 pub no_binary: Option<bool>,
601 pub no_binary_package: Option<Vec<PackageName>>,
602}
603
604impl From<ResolverInstallerSchema> for ResolverInstallerOptions {
605 fn from(value: ResolverInstallerSchema) -> Self {
606 let ResolverInstallerSchema {
607 index,
608 index_url,
609 extra_index_url,
610 no_index,
611 find_links,
612 index_strategy,
613 keyring_provider,
614 resolution,
615 prerelease,
616 fork_strategy,
617 dependency_metadata,
618 config_settings,
619 config_settings_package,
620 no_build_isolation,
621 no_build_isolation_package,
622 extra_build_dependencies,
623 extra_build_variables,
624 exclude_newer,
625 exclude_newer_package,
626 link_mode,
627 torch_backend,
628 compile_bytecode,
629 no_sources,
630 no_sources_package,
631 upgrade,
632 upgrade_package,
633 reinstall,
634 reinstall_package,
635 no_build,
636 no_build_package,
637 no_binary,
638 no_binary_package,
639 } = value;
640 Self {
641 index,
642 index_url,
643 extra_index_url,
644 no_index,
645 find_links,
646 index_strategy,
647 keyring_provider,
648 resolution,
649 prerelease,
650 fork_strategy,
651 dependency_metadata,
652 config_settings,
653 config_settings_package,
654 build_isolation: BuildIsolation::from_args(
655 no_build_isolation,
656 no_build_isolation_package.into_iter().flatten().collect(),
657 ),
658 extra_build_dependencies,
659 extra_build_variables,
660 exclude_newer,
661 exclude_newer_package,
662 link_mode,
663 torch_backend,
664 compile_bytecode,
665 no_sources,
666 no_sources_package,
667 upgrade: Upgrade::from_args(
668 upgrade,
669 upgrade_package
670 .into_iter()
671 .flatten()
672 .map(Into::into)
673 .collect(),
674 Vec::new(),
675 ),
676 reinstall: Reinstall::from_args(reinstall, reinstall_package.unwrap_or_default()),
677 no_build,
678 no_build_package,
679 no_binary,
680 no_binary_package,
681 }
682 }
683}
684
685impl ResolverInstallerSchema {
686 fn relative_to(self, root_dir: &Path) -> Result<Self, IndexUrlError> {
688 Ok(Self {
689 index: self
690 .index
691 .map(|index| {
692 index
693 .into_iter()
694 .map(|index| index.relative_to(root_dir))
695 .collect::<Result<Vec<_>, _>>()
696 })
697 .transpose()?,
698 index_url: self
699 .index_url
700 .map(|index_url| index_url.relative_to(root_dir))
701 .transpose()?,
702 extra_index_url: self
703 .extra_index_url
704 .map(|extra_index_url| {
705 extra_index_url
706 .into_iter()
707 .map(|extra_index_url| extra_index_url.relative_to(root_dir))
708 .collect::<Result<Vec<_>, _>>()
709 })
710 .transpose()?,
711 find_links: self
712 .find_links
713 .map(|find_links| {
714 find_links
715 .into_iter()
716 .map(|find_link| find_link.relative_to(root_dir))
717 .collect::<Result<Vec<_>, _>>()
718 })
719 .transpose()?,
720 ..self
721 })
722 }
723}
724
725#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
727#[serde(rename_all = "kebab-case")]
728#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
729pub struct ResolverInstallerSchema {
730 #[option(
758 default = "\"[]\"",
759 value_type = "dict",
760 example = r#"
761 [[tool.uv.index]]
762 name = "pytorch"
763 url = "https://download.pytorch.org/whl/cu130"
764 "#
765 )]
766 pub index: Option<Vec<Index>>,
767 #[option(
777 default = "\"https://pypi.org/simple\"",
778 value_type = "str",
779 example = r#"
780 index-url = "https://test.pypi.org/simple"
781 "#
782 )]
783 pub index_url: Option<PipIndex>,
784 #[option(
798 default = "[]",
799 value_type = "list[str]",
800 example = r#"
801 extra-index-url = ["https://download.pytorch.org/whl/cpu"]
802 "#
803 )]
804 pub extra_index_url: Option<Vec<PipExtraIndex>>,
805 #[option(
808 default = "false",
809 value_type = "bool",
810 example = r#"
811 no-index = true
812 "#
813 )]
814 pub no_index: Option<bool>,
815 #[option(
824 default = "[]",
825 value_type = "list[str]",
826 example = r#"
827 find-links = ["https://download.pytorch.org/whl/torch_stable.html"]
828 "#
829 )]
830 pub find_links: Option<Vec<PipFindLinks>>,
831 #[option(
838 default = "\"first-index\"",
839 value_type = "str",
840 example = r#"
841 index-strategy = "unsafe-best-match"
842 "#,
843 possible_values = true
844 )]
845 pub index_strategy: Option<IndexStrategy>,
846 #[option(
851 default = "\"disabled\"",
852 value_type = "str",
853 example = r#"
854 keyring-provider = "subprocess"
855 "#
856 )]
857 pub keyring_provider: Option<KeyringProviderType>,
858 #[option(
863 default = "\"highest\"",
864 value_type = "str",
865 example = r#"
866 resolution = "lowest-direct"
867 "#,
868 possible_values = true
869 )]
870 pub resolution: Option<ResolutionMode>,
871 #[option(
877 default = "\"if-necessary-or-explicit\"",
878 value_type = "str",
879 example = r#"
880 prerelease = "allow"
881 "#,
882 possible_values = true
883 )]
884 pub prerelease: Option<PrereleaseMode>,
885 #[option(
896 default = "\"requires-python\"",
897 value_type = "str",
898 example = r#"
899 fork-strategy = "fewest"
900 "#,
901 possible_values = true
902 )]
903 pub fork_strategy: Option<ForkStrategy>,
904 #[option(
918 default = r#"[]"#,
919 value_type = "list[dict]",
920 example = r#"
921 dependency-metadata = [
922 { name = "flask", version = "1.0.0", requires-dist = ["werkzeug"], requires-python = ">=3.6" },
923 ]
924 "#
925 )]
926 pub dependency_metadata: Option<Vec<StaticMetadata>>,
927 #[option(
930 default = "{}",
931 value_type = "dict",
932 example = r#"
933 config-settings = { editable_mode = "compat" }
934 "#
935 )]
936 pub config_settings: Option<ConfigSettings>,
937 #[option(
942 default = "{}",
943 value_type = "dict",
944 example = r#"
945 config-settings-package = { numpy = { editable_mode = "compat" } }
946 "#
947 )]
948 pub config_settings_package: Option<PackageConfigSettings>,
949 #[option(
954 default = "false",
955 value_type = "bool",
956 example = r#"
957 no-build-isolation = true
958 "#
959 )]
960 pub no_build_isolation: Option<bool>,
961 #[option(
966 default = "[]",
967 value_type = "list[str]",
968 example = r#"
969 no-build-isolation-package = ["package1", "package2"]
970 "#
971 )]
972 pub no_build_isolation_package: Option<Vec<PackageName>>,
973 #[option(
979 default = "[]",
980 value_type = "dict",
981 example = r#"
982 extra-build-dependencies = { pytest = ["setuptools"] }
983 "#
984 )]
985 pub extra_build_dependencies: Option<ExtraBuildDependencies>,
986 #[option(
991 default = r#"{}"#,
992 value_type = r#"dict[str, dict[str, str]]"#,
993 example = r#"
994 extra-build-variables = { flash-attn = { FLASH_ATTENTION_SKIP_CUDA_BUILD = "TRUE" } }
995 "#
996 )]
997 pub extra_build_variables: Option<ExtraBuildVariables>,
998 #[option(
1013 default = "None",
1014 value_type = "str | false",
1015 example = r#"
1016 exclude-newer = "2006-12-02T02:07:43Z"
1017 "#
1018 )]
1019 pub exclude_newer: Option<ExcludeNewerOverride>,
1020 #[option(
1034 default = "None",
1035 value_type = "dict",
1036 example = r#"
1037 exclude-newer-package = { tqdm = "2022-04-04T00:00:00Z", markupsafe = false }
1038 "#
1039 )]
1040 pub exclude_newer_package: Option<ExcludeNewerPackage>,
1041 #[option(
1051 default = "\"clone\" (macOS, Linux) or \"hardlink\" (Windows)",
1052 value_type = "str",
1053 example = r#"
1054 link-mode = "copy"
1055 "#,
1056 possible_values = true
1057 )]
1058 pub link_mode: Option<LinkMode>,
1059 #[option(
1070 default = "false",
1071 value_type = "bool",
1072 example = r#"
1073 compile-bytecode = true
1074 "#
1075 )]
1076 pub compile_bytecode: Option<bool>,
1077 #[option(
1081 default = "false",
1082 value_type = "bool",
1083 example = r#"
1084 no-sources = true
1085 "#
1086 )]
1087 pub no_sources: Option<bool>,
1088 #[option(
1090 default = "[]",
1091 value_type = "list[str]",
1092 example = r#"
1093 no-sources-package = ["ruff"]
1094 "#
1095 )]
1096 pub no_sources_package: Option<Vec<PackageName>>,
1097 #[option(
1099 default = "false",
1100 value_type = "bool",
1101 example = r#"
1102 upgrade = true
1103 "#
1104 )]
1105 pub upgrade: Option<bool>,
1106 #[option(
1111 default = "[]",
1112 value_type = "list[str]",
1113 example = r#"
1114 upgrade-package = ["ruff"]
1115 "#
1116 )]
1117 pub upgrade_package: Option<Vec<Requirement<VerbatimParsedUrl>>>,
1118 #[option(
1120 default = "false",
1121 value_type = "bool",
1122 example = r#"
1123 reinstall = true
1124 "#
1125 )]
1126 pub reinstall: Option<bool>,
1127 #[option(
1130 default = "[]",
1131 value_type = "list[str]",
1132 example = r#"
1133 reinstall-package = ["ruff"]
1134 "#
1135 )]
1136 pub reinstall_package: Option<Vec<PackageName>>,
1137 #[option(
1143 default = "false",
1144 value_type = "bool",
1145 example = r#"
1146 no-build = true
1147 "#
1148 )]
1149 pub no_build: Option<bool>,
1150 #[option(
1152 default = "[]",
1153 value_type = "list[str]",
1154 example = r#"
1155 no-build-package = ["ruff"]
1156 "#
1157 )]
1158 pub no_build_package: Option<Vec<PackageName>>,
1159 #[option(
1164 default = "false",
1165 value_type = "bool",
1166 example = r#"
1167 no-binary = true
1168 "#
1169 )]
1170 pub no_binary: Option<bool>,
1171 #[option(
1173 default = "[]",
1174 value_type = "list[str]",
1175 example = r#"
1176 no-binary-package = ["ruff"]
1177 "#
1178 )]
1179 pub no_binary_package: Option<Vec<PackageName>>,
1180 #[option(
1195 default = "null",
1196 value_type = "str",
1197 example = r#"
1198 torch-backend = "auto"
1199 "#
1200 )]
1201 pub torch_backend: Option<TorchMode>,
1202}
1203
1204#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
1206#[serde(rename_all = "kebab-case")]
1207#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1208pub struct PythonInstallMirrors {
1209 #[option(
1217 default = "None",
1218 value_type = "str",
1219 uv_toml_only = true,
1220 example = r#"
1221 python-install-mirror = "https://github.com/astral-sh/python-build-standalone/releases/download"
1222 "#
1223 )]
1224 pub python_install_mirror: Option<String>,
1225 #[option(
1234 default = "None",
1235 value_type = "str",
1236 uv_toml_only = true,
1237 example = r#"
1238 pypy-install-mirror = "https://downloads.python.org/pypy"
1239 "#
1240 )]
1241 pub pypy_install_mirror: Option<String>,
1242
1243 #[option(
1245 default = "None",
1246 value_type = "str",
1247 uv_toml_only = true,
1248 example = r#"
1249 python-downloads-json-url = "/etc/uv/python-downloads.json"
1250 "#
1251 )]
1252 pub python_downloads_json_url: Option<String>,
1253}
1254
1255impl PythonInstallMirrors {
1256 #[must_use]
1257 pub fn combine(self, other: Self) -> Self {
1258 Self {
1259 python_install_mirror: self.python_install_mirror.or(other.python_install_mirror),
1260 pypy_install_mirror: self.pypy_install_mirror.or(other.pypy_install_mirror),
1261 python_downloads_json_url: self
1262 .python_downloads_json_url
1263 .or(other.python_downloads_json_url),
1264 }
1265 }
1266}
1267
1268#[derive(Debug, Clone, Default, Deserialize, CombineOptions, OptionsMetadata)]
1273#[serde(deny_unknown_fields, rename_all = "kebab-case")]
1274#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1275pub struct PipOptions {
1276 #[option(
1289 default = "None",
1290 value_type = "str",
1291 example = r#"
1292 python = "3.10"
1293 "#
1294 )]
1295 pub python: Option<String>,
1296 #[option(
1305 default = "false",
1306 value_type = "bool",
1307 example = r#"
1308 system = true
1309 "#
1310 )]
1311 pub system: Option<bool>,
1312 #[option(
1319 default = "false",
1320 value_type = "bool",
1321 example = r#"
1322 break-system-packages = true
1323 "#
1324 )]
1325 pub break_system_packages: Option<bool>,
1326 #[option(
1329 default = "None",
1330 value_type = "str",
1331 example = r#"
1332 target = "./target"
1333 "#
1334 )]
1335 pub target: Option<PathBuf>,
1336 #[option(
1344 default = "None",
1345 value_type = "str",
1346 example = r#"
1347 prefix = "./prefix"
1348 "#
1349 )]
1350 pub prefix: Option<PathBuf>,
1351 #[serde(skip)]
1352 #[cfg_attr(feature = "schemars", schemars(skip))]
1353 pub index: Option<Vec<Index>>,
1354 #[option(
1362 default = "\"https://pypi.org/simple\"",
1363 value_type = "str",
1364 example = r#"
1365 index-url = "https://test.pypi.org/simple"
1366 "#
1367 )]
1368 pub index_url: Option<PipIndex>,
1369 #[option(
1380 default = "[]",
1381 value_type = "list[str]",
1382 example = r#"
1383 extra-index-url = ["https://download.pytorch.org/whl/cpu"]
1384 "#
1385 )]
1386 pub extra_index_url: Option<Vec<PipExtraIndex>>,
1387 #[option(
1390 default = "false",
1391 value_type = "bool",
1392 example = r#"
1393 no-index = true
1394 "#
1395 )]
1396 pub no_index: Option<bool>,
1397 #[option(
1406 default = "[]",
1407 value_type = "list[str]",
1408 example = r#"
1409 find-links = ["https://download.pytorch.org/whl/torch_stable.html"]
1410 "#
1411 )]
1412 pub find_links: Option<Vec<PipFindLinks>>,
1413 #[option(
1420 default = "\"first-index\"",
1421 value_type = "str",
1422 example = r#"
1423 index-strategy = "unsafe-best-match"
1424 "#,
1425 possible_values = true
1426 )]
1427 pub index_strategy: Option<IndexStrategy>,
1428 #[option(
1433 default = "disabled",
1434 value_type = "str",
1435 example = r#"
1436 keyring-provider = "subprocess"
1437 "#
1438 )]
1439 pub keyring_provider: Option<KeyringProviderType>,
1440 #[option(
1448 default = "false",
1449 value_type = "bool",
1450 example = r#"
1451 no-build = true
1452 "#
1453 )]
1454 pub no_build: Option<bool>,
1455 #[option(
1463 default = "[]",
1464 value_type = "list[str]",
1465 example = r#"
1466 no-binary = ["ruff"]
1467 "#
1468 )]
1469 pub no_binary: Option<Vec<PackageNameSpecifier>>,
1470 #[option(
1480 default = "[]",
1481 value_type = "list[str]",
1482 example = r#"
1483 only-binary = ["ruff"]
1484 "#
1485 )]
1486 pub only_binary: Option<Vec<PackageNameSpecifier>>,
1487 #[option(
1492 default = "false",
1493 value_type = "bool",
1494 example = r#"
1495 no-build-isolation = true
1496 "#
1497 )]
1498 pub no_build_isolation: Option<bool>,
1499 #[option(
1504 default = "[]",
1505 value_type = "list[str]",
1506 example = r#"
1507 no-build-isolation-package = ["package1", "package2"]
1508 "#
1509 )]
1510 pub no_build_isolation_package: Option<Vec<PackageName>>,
1511 #[option(
1517 default = "[]",
1518 value_type = "dict",
1519 example = r#"
1520 extra-build-dependencies = { pytest = ["setuptools"] }
1521 "#
1522 )]
1523 pub extra_build_dependencies: Option<ExtraBuildDependencies>,
1524 #[option(
1529 default = r#"{}"#,
1530 value_type = r#"dict[str, dict[str, str]]"#,
1531 example = r#"
1532 extra-build-variables = { flash-attn = { FLASH_ATTENTION_SKIP_CUDA_BUILD = "TRUE" } }
1533 "#
1534 )]
1535 pub extra_build_variables: Option<ExtraBuildVariables>,
1536 #[option(
1539 default = "false",
1540 value_type = "bool",
1541 example = r#"
1542 strict = true
1543 "#
1544 )]
1545 pub strict: Option<bool>,
1546 #[option(
1550 default = "[]",
1551 value_type = "list[str]",
1552 example = r#"
1553 extra = ["dev", "docs"]
1554 "#
1555 )]
1556 pub extra: Option<Vec<ExtraName>>,
1557 #[option(
1561 default = "false",
1562 value_type = "bool",
1563 example = r#"
1564 all-extras = true
1565 "#
1566 )]
1567 pub all_extras: Option<bool>,
1568 #[option(
1570 default = "[]",
1571 value_type = "list[str]",
1572 example = r#"
1573 all-extras = true
1574 no-extra = ["dev", "docs"]
1575 "#
1576 )]
1577 pub no_extra: Option<Vec<ExtraName>>,
1578 #[option(
1581 default = "false",
1582 value_type = "bool",
1583 example = r#"
1584 no-deps = true
1585 "#
1586 )]
1587 pub no_deps: Option<bool>,
1588 #[option(
1590 default = "None",
1591 value_type = "list[str]",
1592 example = r#"
1593 group = ["dev", "docs"]
1594 "#
1595 )]
1596 pub group: Option<Vec<PipGroupName>>,
1597 #[option(
1600 default = "false",
1601 value_type = "bool",
1602 example = r#"
1603 allow-empty-requirements = true
1604 "#
1605 )]
1606 pub allow_empty_requirements: Option<bool>,
1607 #[option(
1612 default = "\"highest\"",
1613 value_type = "str",
1614 example = r#"
1615 resolution = "lowest-direct"
1616 "#,
1617 possible_values = true
1618 )]
1619 pub resolution: Option<ResolutionMode>,
1620 #[option(
1626 default = "\"if-necessary-or-explicit\"",
1627 value_type = "str",
1628 example = r#"
1629 prerelease = "allow"
1630 "#,
1631 possible_values = true
1632 )]
1633 pub prerelease: Option<PrereleaseMode>,
1634 #[option(
1645 default = "\"requires-python\"",
1646 value_type = "str",
1647 example = r#"
1648 fork-strategy = "fewest"
1649 "#,
1650 possible_values = true
1651 )]
1652 pub fork_strategy: Option<ForkStrategy>,
1653 #[option(
1667 default = r#"[]"#,
1668 value_type = "list[dict]",
1669 example = r#"
1670 dependency-metadata = [
1671 { name = "flask", version = "1.0.0", requires-dist = ["werkzeug"], requires-python = ">=3.6" },
1672 ]
1673 "#
1674 )]
1675 pub dependency_metadata: Option<Vec<StaticMetadata>>,
1676 #[option(
1681 default = "None",
1682 value_type = "str",
1683 example = r#"
1684 output-file = "requirements.txt"
1685 "#
1686 )]
1687 pub output_file: Option<PathBuf>,
1688 #[option(
1694 default = "false",
1695 value_type = "bool",
1696 example = r#"
1697 no-strip-extras = true
1698 "#
1699 )]
1700 pub no_strip_extras: Option<bool>,
1701 #[option(
1706 default = "false",
1707 value_type = "bool",
1708 example = r#"
1709 no-strip-markers = true
1710 "#
1711 )]
1712 pub no_strip_markers: Option<bool>,
1713 #[option(
1716 default = "false",
1717 value_type = "bool",
1718 example = r#"
1719 no-annotate = true
1720 "#
1721 )]
1722 pub no_annotate: Option<bool>,
1723 #[option(
1725 default = r#"false"#,
1726 value_type = "bool",
1727 example = r#"
1728 no-header = true
1729 "#
1730 )]
1731 pub no_header: Option<bool>,
1732 #[option(
1736 default = "None",
1737 value_type = "str",
1738 example = r#"
1739 custom-compile-command = "./custom-uv-compile.sh"
1740 "#
1741 )]
1742 pub custom_compile_command: Option<String>,
1743 #[option(
1745 default = "false",
1746 value_type = "bool",
1747 example = r#"
1748 generate-hashes = true
1749 "#
1750 )]
1751 pub generate_hashes: Option<bool>,
1752 #[option(
1755 default = "{}",
1756 value_type = "dict",
1757 example = r#"
1758 config-settings = { editable_mode = "compat" }
1759 "#
1760 )]
1761 pub config_settings: Option<ConfigSettings>,
1762 #[option(
1765 default = "{}",
1766 value_type = "dict",
1767 example = r#"
1768 config-settings-package = { numpy = { editable_mode = "compat" } }
1769 "#
1770 )]
1771 pub config_settings_package: Option<PackageConfigSettings>,
1772 #[option(
1778 default = "None",
1779 value_type = "str",
1780 example = r#"
1781 python-version = "3.8"
1782 "#
1783 )]
1784 pub python_version: Option<PythonVersion>,
1785 #[option(
1791 default = "None",
1792 value_type = "str",
1793 example = r#"
1794 python-platform = "x86_64-unknown-linux-gnu"
1795 "#
1796 )]
1797 pub python_platform: Option<TargetTriple>,
1798 #[option(
1806 default = "false",
1807 value_type = "bool",
1808 example = r#"
1809 universal = true
1810 "#
1811 )]
1812 pub universal: Option<bool>,
1813 #[option(
1828 default = "None",
1829 value_type = "str | false",
1830 example = r#"
1831 exclude-newer = "2006-12-02T02:07:43Z"
1832 "#
1833 )]
1834 pub exclude_newer: Option<ExcludeNewerOverride>,
1835 #[option(
1848 default = "None",
1849 value_type = "dict",
1850 example = r#"
1851 exclude-newer-package = { tqdm = "2022-04-04T00:00:00Z", markupsafe = false }
1852 "#
1853 )]
1854 pub exclude_newer_package: Option<ExcludeNewerPackage>,
1855 #[option(
1858 default = "[]",
1859 value_type = "list[str]",
1860 example = r#"
1861 no-emit-package = ["ruff"]
1862 "#
1863 )]
1864 pub no_emit_package: Option<Vec<PackageName>>,
1865 #[option(
1867 default = "false",
1868 value_type = "bool",
1869 example = r#"
1870 emit-index-url = true
1871 "#
1872 )]
1873 pub emit_index_url: Option<bool>,
1874 #[option(
1876 default = "false",
1877 value_type = "bool",
1878 example = r#"
1879 emit-find-links = true
1880 "#
1881 )]
1882 pub emit_find_links: Option<bool>,
1883 #[option(
1885 default = "false",
1886 value_type = "bool",
1887 example = r#"
1888 emit-build-options = true
1889 "#
1890 )]
1891 pub emit_build_options: Option<bool>,
1892 #[option(
1899 default = "false",
1900 value_type = "bool",
1901 example = r#"
1902 emit-marker-expression = true
1903 "#
1904 )]
1905 pub emit_marker_expression: Option<bool>,
1906 #[option(
1909 default = "false",
1910 value_type = "bool",
1911 example = r#"
1912 emit-index-annotation = true
1913 "#
1914 )]
1915 pub emit_index_annotation: Option<bool>,
1916 #[option(
1919 default = "\"split\"",
1920 value_type = "str",
1921 example = r#"
1922 annotation-style = "line"
1923 "#,
1924 possible_values = true
1925 )]
1926 pub annotation_style: Option<AnnotationStyle>,
1927 #[option(
1937 default = "\"clone\" (macOS, Linux) or \"hardlink\" (Windows)",
1938 value_type = "str",
1939 example = r#"
1940 link-mode = "copy"
1941 "#,
1942 possible_values = true
1943 )]
1944 pub link_mode: Option<LinkMode>,
1945 #[option(
1956 default = "false",
1957 value_type = "bool",
1958 example = r#"
1959 compile-bytecode = true
1960 "#
1961 )]
1962 pub compile_bytecode: Option<bool>,
1963 #[option(
1976 default = "false",
1977 value_type = "bool",
1978 example = r#"
1979 require-hashes = true
1980 "#
1981 )]
1982 pub require_hashes: Option<bool>,
1983 #[option(
1989 default = "true",
1990 value_type = "bool",
1991 example = r#"
1992 verify-hashes = true
1993 "#
1994 )]
1995 pub verify_hashes: Option<bool>,
1996 #[option(
2000 default = "false",
2001 value_type = "bool",
2002 example = r#"
2003 no-sources = true
2004 "#
2005 )]
2006 pub no_sources: Option<bool>,
2007 #[option(
2009 default = "[]",
2010 value_type = "list[str]",
2011 example = r#"
2012 no-sources-package = ["ruff"]
2013 "#
2014 )]
2015 pub no_sources_package: Option<Vec<PackageName>>,
2016 #[option(
2018 default = "false",
2019 value_type = "bool",
2020 example = r#"
2021 upgrade = true
2022 "#
2023 )]
2024 pub upgrade: Option<bool>,
2025 #[option(
2030 default = "[]",
2031 value_type = "list[str]",
2032 example = r#"
2033 upgrade-package = ["ruff"]
2034 "#
2035 )]
2036 pub upgrade_package: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2037 #[option(
2039 default = "false",
2040 value_type = "bool",
2041 example = r#"
2042 reinstall = true
2043 "#
2044 )]
2045 pub reinstall: Option<bool>,
2046 #[option(
2049 default = "[]",
2050 value_type = "list[str]",
2051 example = r#"
2052 reinstall-package = ["ruff"]
2053 "#
2054 )]
2055 pub reinstall_package: Option<Vec<PackageName>>,
2056 #[option(
2071 default = "null",
2072 value_type = "str",
2073 example = r#"
2074 torch-backend = "auto"
2075 "#
2076 )]
2077 pub torch_backend: Option<TorchMode>,
2078}
2079
2080impl PipOptions {
2081 fn relative_to(self, root_dir: &Path) -> Result<Self, IndexUrlError> {
2083 Ok(Self {
2084 index: self
2085 .index
2086 .map(|index| {
2087 index
2088 .into_iter()
2089 .map(|index| index.relative_to(root_dir))
2090 .collect::<Result<Vec<_>, _>>()
2091 })
2092 .transpose()?,
2093 index_url: self
2094 .index_url
2095 .map(|index_url| index_url.relative_to(root_dir))
2096 .transpose()?,
2097 extra_index_url: self
2098 .extra_index_url
2099 .map(|extra_index_url| {
2100 extra_index_url
2101 .into_iter()
2102 .map(|extra_index_url| extra_index_url.relative_to(root_dir))
2103 .collect::<Result<Vec<_>, _>>()
2104 })
2105 .transpose()?,
2106 find_links: self
2107 .find_links
2108 .map(|find_links| {
2109 find_links
2110 .into_iter()
2111 .map(|find_link| find_link.relative_to(root_dir))
2112 .collect::<Result<Vec<_>, _>>()
2113 })
2114 .transpose()?,
2115 ..self
2116 })
2117 }
2118}
2119
2120impl From<ResolverInstallerSchema> for ResolverOptions {
2121 fn from(value: ResolverInstallerSchema) -> Self {
2122 Self {
2123 index: value.index,
2124 index_url: value.index_url,
2125 extra_index_url: value.extra_index_url,
2126 no_index: value.no_index,
2127 find_links: value.find_links,
2128 index_strategy: value.index_strategy,
2129 keyring_provider: value.keyring_provider,
2130 resolution: value.resolution,
2131 prerelease: value.prerelease,
2132 fork_strategy: value.fork_strategy,
2133 dependency_metadata: value.dependency_metadata,
2134 config_settings: value.config_settings,
2135 config_settings_package: value.config_settings_package,
2136 exclude_newer: value.exclude_newer,
2137 exclude_newer_package: value.exclude_newer_package,
2138 link_mode: value.link_mode,
2139 upgrade: Upgrade::from_args(
2140 value.upgrade,
2141 value
2142 .upgrade_package
2143 .into_iter()
2144 .flatten()
2145 .map(Into::into)
2146 .collect(),
2147 Vec::new(),
2148 ),
2149 no_build: value.no_build,
2150 no_build_package: value.no_build_package,
2151 no_binary: value.no_binary,
2152 no_binary_package: value.no_binary_package,
2153 build_isolation: BuildIsolation::from_args(
2154 value.no_build_isolation,
2155 value.no_build_isolation_package.unwrap_or_default(),
2156 ),
2157 extra_build_dependencies: value.extra_build_dependencies,
2158 extra_build_variables: value.extra_build_variables,
2159 no_sources: value.no_sources,
2160 no_sources_package: value.no_sources_package,
2161 torch_backend: value.torch_backend,
2162 }
2163 }
2164}
2165
2166impl From<ResolverInstallerSchema> for InstallerOptions {
2167 fn from(value: ResolverInstallerSchema) -> Self {
2168 Self {
2169 index: value.index,
2170 index_url: value.index_url,
2171 extra_index_url: value.extra_index_url,
2172 no_index: value.no_index,
2173 find_links: value.find_links,
2174 index_strategy: value.index_strategy,
2175 keyring_provider: value.keyring_provider,
2176 config_settings: value.config_settings,
2177 exclude_newer: value.exclude_newer,
2178 link_mode: value.link_mode,
2179 compile_bytecode: value.compile_bytecode,
2180 reinstall: Reinstall::from_args(
2181 value.reinstall,
2182 value.reinstall_package.unwrap_or_default(),
2183 ),
2184 build_isolation: BuildIsolation::from_args(
2185 value.no_build_isolation,
2186 value.no_build_isolation_package.unwrap_or_default(),
2187 ),
2188 no_build: value.no_build,
2189 no_build_package: value.no_build_package,
2190 no_binary: value.no_binary,
2191 no_binary_package: value.no_binary_package,
2192 no_sources: value.no_sources,
2193 no_sources_package: value.no_sources_package,
2194 }
2195 }
2196}
2197
2198#[derive(
2203 Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, CombineOptions, OptionsMetadata,
2204)]
2205#[serde(deny_unknown_fields, rename_all = "kebab-case")]
2206#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2207pub struct ToolOptions {
2208 index: Option<Vec<Index>>,
2209 index_url: Option<PipIndex>,
2210 extra_index_url: Option<Vec<PipExtraIndex>>,
2211 no_index: Option<bool>,
2212 find_links: Option<Vec<PipFindLinks>>,
2213 index_strategy: Option<IndexStrategy>,
2214 keyring_provider: Option<KeyringProviderType>,
2215 resolution: Option<ResolutionMode>,
2216 prerelease: Option<PrereleaseMode>,
2217 fork_strategy: Option<ForkStrategy>,
2218 dependency_metadata: Option<Vec<StaticMetadata>>,
2219 config_settings: Option<ConfigSettings>,
2220 config_settings_package: Option<PackageConfigSettings>,
2221 build_isolation: Option<BuildIsolation>,
2222 extra_build_dependencies: Option<ExtraBuildDependencies>,
2223 extra_build_variables: Option<ExtraBuildVariables>,
2224 exclude_newer: Option<ExcludeNewerOverride>,
2225 exclude_newer_package: Option<ExcludeNewerPackage>,
2226 link_mode: Option<LinkMode>,
2227 compile_bytecode: Option<bool>,
2228 no_sources: Option<bool>,
2229 no_sources_package: Option<Vec<PackageName>>,
2230 no_build: Option<bool>,
2231 no_build_package: Option<Vec<PackageName>>,
2232 no_binary: Option<bool>,
2233 no_binary_package: Option<Vec<PackageName>>,
2234 torch_backend: Option<TorchMode>,
2235}
2236
2237#[derive(Debug, Clone, Default, Serialize, Deserialize)]
2239#[serde(deny_unknown_fields, rename_all = "kebab-case")]
2240pub struct ToolOptionsWire {
2241 index: Option<Vec<Index>>,
2242 index_url: Option<PipIndex>,
2243 extra_index_url: Option<Vec<PipExtraIndex>>,
2244 no_index: Option<bool>,
2245 find_links: Option<Vec<PipFindLinks>>,
2246 index_strategy: Option<IndexStrategy>,
2247 keyring_provider: Option<KeyringProviderType>,
2248 resolution: Option<ResolutionMode>,
2249 prerelease: Option<PrereleaseMode>,
2250 fork_strategy: Option<ForkStrategy>,
2251 dependency_metadata: Option<Vec<StaticMetadata>>,
2252 config_settings: Option<ConfigSettings>,
2253 config_settings_package: Option<PackageConfigSettings>,
2254 build_isolation: Option<BuildIsolation>,
2255 extra_build_dependencies: Option<ExtraBuildDependencies>,
2256 extra_build_variables: Option<ExtraBuildVariables>,
2257 exclude_newer: Option<ExcludeNewerOverride>,
2258 exclude_newer_span: Option<ExcludeNewerSpan>,
2259 #[serde(serialize_with = "serialize_exclude_newer_package_with_spans")]
2260 exclude_newer_package: Option<ExcludeNewerPackage>,
2261 link_mode: Option<LinkMode>,
2262 compile_bytecode: Option<bool>,
2263 no_sources: Option<bool>,
2264 no_sources_package: Option<Vec<PackageName>>,
2265 no_build: Option<bool>,
2266 no_build_package: Option<Vec<PackageName>>,
2267 no_binary: Option<bool>,
2268 no_binary_package: Option<Vec<PackageName>>,
2269 torch_backend: Option<TorchMode>,
2270}
2271
2272impl From<ResolverInstallerOptions> for ToolOptions {
2273 fn from(value: ResolverInstallerOptions) -> Self {
2274 Self {
2275 index: value.index.map(|indexes| {
2276 indexes
2277 .into_iter()
2278 .map(Index::with_promoted_auth_policy)
2279 .collect()
2280 }),
2281 index_url: value.index_url,
2282 extra_index_url: value.extra_index_url,
2283 no_index: value.no_index,
2284 find_links: value.find_links,
2285 index_strategy: value.index_strategy,
2286 keyring_provider: value.keyring_provider,
2287 resolution: value.resolution,
2288 prerelease: value.prerelease,
2289 fork_strategy: value.fork_strategy,
2290 dependency_metadata: value.dependency_metadata,
2291 config_settings: value.config_settings,
2292 config_settings_package: value.config_settings_package,
2293 build_isolation: value.build_isolation,
2294 extra_build_dependencies: value.extra_build_dependencies,
2295 extra_build_variables: value.extra_build_variables,
2296 exclude_newer: value.exclude_newer,
2297 exclude_newer_package: value.exclude_newer_package,
2298 link_mode: value.link_mode,
2299 compile_bytecode: value.compile_bytecode,
2300 no_sources: value.no_sources,
2301 no_sources_package: value.no_sources_package,
2302 no_build: value.no_build,
2303 no_build_package: value.no_build_package,
2304 no_binary: value.no_binary,
2305 no_binary_package: value.no_binary_package,
2306 torch_backend: value.torch_backend,
2307 }
2308 }
2309}
2310
2311impl From<ToolOptionsWire> for ToolOptions {
2312 fn from(value: ToolOptionsWire) -> Self {
2313 let exclude_newer = value
2314 .exclude_newer
2315 .map(|exclude_newer| match exclude_newer {
2316 ExcludeNewerOverride::Disabled => ExcludeNewerOverride::Disabled,
2317 ExcludeNewerOverride::Enabled(exclude_newer) => {
2318 let exclude_newer = *exclude_newer;
2319 if let Some(span) = value.exclude_newer_span
2320 && exclude_newer.span().is_none()
2321 {
2322 ExcludeNewerValue::relative(span).into()
2323 } else {
2324 exclude_newer.into()
2325 }
2326 }
2327 });
2328
2329 Self {
2330 index: value.index,
2331 index_url: value.index_url,
2332 extra_index_url: value.extra_index_url,
2333 no_index: value.no_index,
2334 find_links: value.find_links,
2335 index_strategy: value.index_strategy,
2336 keyring_provider: value.keyring_provider,
2337 resolution: value.resolution,
2338 prerelease: value.prerelease,
2339 fork_strategy: value.fork_strategy,
2340 dependency_metadata: value.dependency_metadata,
2341 config_settings: value.config_settings,
2342 config_settings_package: value.config_settings_package,
2343 build_isolation: value.build_isolation,
2344 extra_build_dependencies: value.extra_build_dependencies,
2345 extra_build_variables: value.extra_build_variables,
2346 exclude_newer,
2347 exclude_newer_package: value.exclude_newer_package,
2348 link_mode: value.link_mode,
2349 compile_bytecode: value.compile_bytecode,
2350 no_sources: value.no_sources,
2351 no_sources_package: value.no_sources_package,
2352 no_build: value.no_build,
2353 no_build_package: value.no_build_package,
2354 no_binary: value.no_binary,
2355 no_binary_package: value.no_binary_package,
2356 torch_backend: value.torch_backend,
2357 }
2358 }
2359}
2360
2361impl From<ToolOptions> for ToolOptionsWire {
2362 fn from(value: ToolOptions) -> Self {
2363 let (exclude_newer, exclude_newer_span) = match &value.exclude_newer {
2364 Some(ExcludeNewerOverride::Disabled) => (Some(ExcludeNewerOverride::Disabled), None),
2365 Some(ExcludeNewerOverride::Enabled(value)) => match value.as_ref() {
2366 ExcludeNewerValue::Absolute(_) => {
2367 (Some(ExcludeNewerOverride::Enabled(value.clone())), None)
2368 }
2369 ExcludeNewerValue::Relative(span) => (
2370 Some(ExcludeNewerValue::absolute(value.timestamp()).into()),
2371 Some(*span),
2372 ),
2373 },
2374 None => (None, None),
2375 };
2376
2377 Self {
2378 index: value.index,
2379 index_url: value.index_url,
2380 extra_index_url: value.extra_index_url,
2381 no_index: value.no_index,
2382 find_links: value.find_links,
2383 index_strategy: value.index_strategy,
2384 keyring_provider: value.keyring_provider,
2385 resolution: value.resolution,
2386 prerelease: value.prerelease,
2387 fork_strategy: value.fork_strategy,
2388 dependency_metadata: value.dependency_metadata,
2389 config_settings: value.config_settings,
2390 config_settings_package: value.config_settings_package,
2391 build_isolation: value.build_isolation,
2392 extra_build_dependencies: value.extra_build_dependencies,
2393 extra_build_variables: value.extra_build_variables,
2394 exclude_newer,
2395 exclude_newer_span,
2396 exclude_newer_package: value.exclude_newer_package,
2397 link_mode: value.link_mode,
2398 compile_bytecode: value.compile_bytecode,
2399 no_sources: value.no_sources,
2400 no_sources_package: value.no_sources_package,
2401 no_build: value.no_build,
2402 no_build_package: value.no_build_package,
2403 no_binary: value.no_binary,
2404 no_binary_package: value.no_binary_package,
2405 torch_backend: value.torch_backend,
2406 }
2407 }
2408}
2409
2410impl From<ToolOptions> for ResolverInstallerOptions {
2411 fn from(value: ToolOptions) -> Self {
2412 Self {
2413 index: value.index,
2414 index_url: value.index_url,
2415 extra_index_url: value.extra_index_url,
2416 no_index: value.no_index,
2417 find_links: value.find_links,
2418 index_strategy: value.index_strategy,
2419 keyring_provider: value.keyring_provider,
2420 resolution: value.resolution,
2421 prerelease: value.prerelease,
2422 fork_strategy: value.fork_strategy,
2423 dependency_metadata: value.dependency_metadata,
2424 config_settings: value.config_settings,
2425 config_settings_package: value.config_settings_package,
2426 build_isolation: value.build_isolation,
2427 extra_build_dependencies: value.extra_build_dependencies,
2428 extra_build_variables: value.extra_build_variables,
2429 exclude_newer: value.exclude_newer,
2430 exclude_newer_package: value.exclude_newer_package,
2431 link_mode: value.link_mode,
2432 compile_bytecode: value.compile_bytecode,
2433 no_sources: value.no_sources,
2434 no_sources_package: value.no_sources_package,
2435 upgrade: None,
2436 reinstall: None,
2437 no_build: value.no_build,
2438 no_build_package: value.no_build_package,
2439 no_binary: value.no_binary,
2440 no_binary_package: value.no_binary_package,
2441 torch_backend: value.torch_backend,
2442 }
2443 }
2444}
2445
2446#[derive(Debug, Clone, Default, Deserialize)]
2449#[serde(rename_all = "kebab-case", deny_unknown_fields)]
2450struct OptionsWire {
2451 required_version: Option<RequiredVersion>,
2454 system_certs: Option<bool>,
2455 native_tls: Option<bool>,
2456 offline: Option<bool>,
2457 no_cache: Option<bool>,
2458 cache_dir: Option<PathBuf>,
2459 preview: Option<bool>,
2460 preview_features: Option<PreviewFeaturesOption>,
2461 python_preference: Option<PythonPreference>,
2462 python_downloads: Option<PythonDownloads>,
2463 concurrent_downloads: Option<NonZeroUsize>,
2464 concurrent_builds: Option<NonZeroUsize>,
2465 concurrent_installs: Option<NonZeroUsize>,
2466
2467 index: Option<Vec<Index>>,
2470 index_url: Option<PipIndex>,
2471 extra_index_url: Option<Vec<PipExtraIndex>>,
2472 no_index: Option<bool>,
2473 find_links: Option<Vec<PipFindLinks>>,
2474 index_strategy: Option<IndexStrategy>,
2475 keyring_provider: Option<KeyringProviderType>,
2476 http_proxy: Option<ProxyUrl>,
2477 https_proxy: Option<ProxyUrl>,
2478 no_proxy: Option<Vec<String>>,
2479 allow_insecure_host: Option<Vec<TrustedHost>>,
2480 resolution: Option<ResolutionMode>,
2481 prerelease: Option<PrereleaseMode>,
2482 fork_strategy: Option<ForkStrategy>,
2483 dependency_metadata: Option<Vec<StaticMetadata>>,
2484 config_settings: Option<ConfigSettings>,
2485 config_settings_package: Option<PackageConfigSettings>,
2486 no_build_isolation: Option<bool>,
2487 no_build_isolation_package: Option<Vec<PackageName>>,
2488 extra_build_dependencies: Option<ExtraBuildDependencies>,
2489 extra_build_variables: Option<ExtraBuildVariables>,
2490 exclude_newer: Option<ExcludeNewerOverride>,
2491 exclude_newer_package: Option<ExcludeNewerPackage>,
2492 link_mode: Option<LinkMode>,
2493 compile_bytecode: Option<bool>,
2494 no_sources: Option<bool>,
2495 no_sources_package: Option<Vec<PackageName>>,
2496 upgrade: Option<bool>,
2497 upgrade_package: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2498 reinstall: Option<bool>,
2499 reinstall_package: Option<Vec<PackageName>>,
2500 no_build: Option<bool>,
2501 no_build_package: Option<Vec<PackageName>>,
2502 no_binary: Option<bool>,
2503 no_binary_package: Option<Vec<PackageName>>,
2504 torch_backend: Option<TorchMode>,
2505
2506 python_install_mirror: Option<String>,
2509 pypy_install_mirror: Option<String>,
2510 python_downloads_json_url: Option<String>,
2511
2512 publish_url: Option<DisplaySafeUrl>,
2515 trusted_publishing: Option<TrustedPublishing>,
2516 check_url: Option<IndexUrl>,
2517
2518 add_bounds: Option<AddBoundsKind>,
2521
2522 audit: Option<AuditOptions>,
2523 pip: Option<PipOptions>,
2524 cache_keys: Option<Vec<CacheKey>>,
2525
2526 override_dependencies: Option<Vec<OverrideDependency>>,
2530 exclude_dependencies: Option<Vec<ExcludeDependency>>,
2531 constraint_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2532 build_constraint_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2533 environments: Option<SupportedEnvironments>,
2534 required_environments: Option<SupportedEnvironments>,
2535
2536 conflicts: Option<serde::de::IgnoredAny>,
2540 workspace: Option<serde::de::IgnoredAny>,
2541 sources: Option<serde::de::IgnoredAny>,
2542 managed: Option<serde::de::IgnoredAny>,
2543 r#package: Option<serde::de::IgnoredAny>,
2544 default_groups: Option<serde::de::IgnoredAny>,
2545 dependency_groups: Option<serde::de::IgnoredAny>,
2546 dev_dependencies: Option<serde::de::IgnoredAny>,
2547
2548 build_backend: Option<serde::de::IgnoredAny>,
2550}
2551
2552impl TryFrom<OptionsWire> for Options {
2553 type Error = &'static str;
2554
2555 #[allow(deprecated)]
2556 fn try_from(value: OptionsWire) -> Result<Self, Self::Error> {
2557 let OptionsWire {
2558 required_version,
2559 system_certs,
2560 native_tls,
2561 offline,
2562 no_cache,
2563 cache_dir,
2564 preview,
2565 preview_features,
2566 python_preference,
2567 python_downloads,
2568 python_install_mirror,
2569 pypy_install_mirror,
2570 python_downloads_json_url,
2571 concurrent_downloads,
2572 concurrent_builds,
2573 concurrent_installs,
2574 index,
2575 index_url,
2576 extra_index_url,
2577 no_index,
2578 find_links,
2579 index_strategy,
2580 keyring_provider,
2581 http_proxy,
2582 https_proxy,
2583 no_proxy,
2584 allow_insecure_host,
2585 resolution,
2586 prerelease,
2587 fork_strategy,
2588 dependency_metadata,
2589 config_settings,
2590 config_settings_package,
2591 no_build_isolation,
2592 no_build_isolation_package,
2593 exclude_newer,
2594 exclude_newer_package,
2595 link_mode,
2596 compile_bytecode,
2597 no_sources,
2598 no_sources_package,
2599 upgrade,
2600 upgrade_package,
2601 reinstall,
2602 reinstall_package,
2603 no_build,
2604 no_build_package,
2605 no_binary,
2606 no_binary_package,
2607 torch_backend,
2608 audit,
2609 pip,
2610 cache_keys,
2611 override_dependencies,
2612 exclude_dependencies,
2613 constraint_dependencies,
2614 build_constraint_dependencies,
2615 environments,
2616 required_environments,
2617 conflicts,
2618 publish_url,
2619 trusted_publishing,
2620 check_url,
2621 workspace,
2622 sources,
2623 default_groups,
2624 dependency_groups,
2625 extra_build_dependencies,
2626 extra_build_variables,
2627 dev_dependencies,
2628 managed,
2629 package,
2630 add_bounds: bounds,
2631 build_backend,
2633 } = value;
2634
2635 Ok(Self {
2636 globals: GlobalOptions {
2637 required_version,
2638 system_certs,
2639 native_tls,
2640 offline,
2641 no_cache,
2642 cache_dir,
2643 preview: PreviewOption::try_from(preview, preview_features)?,
2644 python_preference,
2645 python_downloads,
2646 concurrent_downloads,
2647 concurrent_builds,
2648 concurrent_installs,
2649 http_proxy,
2650 https_proxy,
2651 no_proxy,
2652 allow_insecure_host: allow_insecure_host.clone(),
2654 },
2655 top_level: ResolverInstallerSchema {
2656 index,
2657 index_url,
2658 extra_index_url,
2659 no_index,
2660 find_links,
2661 index_strategy,
2662 keyring_provider,
2663 resolution,
2664 prerelease,
2665 fork_strategy,
2666 dependency_metadata,
2667 config_settings,
2668 config_settings_package,
2669 no_build_isolation,
2670 no_build_isolation_package,
2671 extra_build_dependencies,
2672 extra_build_variables,
2673 exclude_newer,
2674 exclude_newer_package,
2675 link_mode,
2676 compile_bytecode,
2677 no_sources,
2678 no_sources_package,
2679 upgrade,
2680 upgrade_package,
2681 reinstall,
2682 reinstall_package,
2683 no_build,
2684 no_build_package,
2685 no_binary,
2686 no_binary_package,
2687 torch_backend,
2688 },
2689 pip,
2690 cache_keys,
2691 build_backend,
2692 override_dependencies,
2693 exclude_dependencies,
2694 constraint_dependencies,
2695 build_constraint_dependencies,
2696 environments,
2697 required_environments,
2698 install_mirrors: PythonInstallMirrors {
2699 python_install_mirror,
2700 pypy_install_mirror,
2701 python_downloads_json_url,
2702 },
2703 conflicts,
2704 publish: PublishOptions {
2705 publish_url,
2706 trusted_publishing,
2707 check_url,
2708 },
2709 add: AddOptions { add_bounds: bounds },
2710 audit,
2711 workspace,
2712 sources,
2713 dev_dependencies,
2714 default_groups,
2715 dependency_groups,
2716 managed,
2717 package,
2718 })
2719 }
2720}
2721
2722#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
2723#[serde(rename_all = "kebab-case")]
2724#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2725pub struct PublishOptions {
2726 #[option(
2729 default = "\"https://upload.pypi.org/legacy/\"",
2730 value_type = "str",
2731 example = r#"
2732 publish-url = "https://test.pypi.org/legacy/"
2733 "#
2734 )]
2735 pub publish_url: Option<DisplaySafeUrl>,
2736
2737 #[option(
2744 default = "automatic",
2745 value_type = "str",
2746 example = r#"
2747 trusted-publishing = "always"
2748 "#
2749 )]
2750 pub trusted_publishing: Option<TrustedPublishing>,
2751
2752 #[option(
2766 default = "None",
2767 value_type = "str",
2768 example = r#"
2769 check-url = "https://test.pypi.org/simple"
2770 "#
2771 )]
2772 pub check_url: Option<IndexUrl>,
2773}
2774
2775#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
2776#[serde(rename_all = "kebab-case")]
2777#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2778pub struct AddOptions {
2779 #[option(
2790 default = "\"lower\"",
2791 value_type = "str",
2792 example = r#"
2793 add-bounds = "major"
2794 "#,
2795 possible_values = true
2796 )]
2797 pub add_bounds: Option<AddBoundsKind>,
2798}
2799
2800#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
2801#[serde(rename_all = "kebab-case")]
2802#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2803pub struct AuditOptions {
2804 #[option(
2806 default = "false",
2807 value_type = "bool",
2808 example = r#"
2809 malware-check = true
2810 "#
2811 )]
2812 pub malware_check: Option<bool>,
2813
2814 #[option(
2816 default = "\"https://api.osv.dev/\"",
2817 value_type = "str",
2818 example = r#"
2819 malware-check-url = "https://example.com"
2820 "#
2821 )]
2822 pub malware_check_url: Option<DisplaySafeUrl>,
2823
2824 #[option(
2829 default = "[]",
2830 value_type = "list[str]",
2831 example = r#"
2832 ignore = ["PYSEC-2022-43017", "GHSA-5239-wwwm-4pmq"]
2833 "#
2834 )]
2835 pub ignore: Option<Vec<String>>,
2836
2837 #[option(
2843 default = "[]",
2844 value_type = "list[str]",
2845 example = r#"
2846 ignore-until-fixed = ["PYSEC-2022-43017"]
2847 "#
2848 )]
2849 pub ignore_until_fixed: Option<Vec<String>>,
2850}
2851
2852#[derive(Debug, Clone)]
2853pub struct MalwareCheckSettings {
2854 pub enabled: bool,
2856 pub malware_check_url: Option<DisplaySafeUrl>,
2858}
2859
2860impl MalwareCheckSettings {
2861 pub fn resolve(
2862 filesystem: Option<&FilesystemOptions>,
2863 environment: &EnvironmentOptions,
2864 ) -> Self {
2865 let audit = filesystem.and_then(|options| options.audit.as_ref());
2866
2867 Self {
2868 enabled: environment
2869 .malware_check
2870 .value
2871 .or(audit.and_then(|audit| audit.malware_check))
2872 .unwrap_or_default(),
2873 malware_check_url: environment
2874 .malware_check_url
2875 .clone()
2876 .or_else(|| audit.and_then(|audit| audit.malware_check_url.clone())),
2877 }
2878 }
2879}
2880
2881#[derive(Debug, Clone)]
2883#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2884#[cfg_attr(feature = "schemars", schemars(untagged))]
2885pub enum PreviewFeaturesOption {
2886 Toggle(bool),
2887 Features(Vec<MaybePreviewFeature>),
2888}
2889
2890impl<'de> Deserialize<'de> for PreviewFeaturesOption {
2893 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2894 where
2895 D: serde::Deserializer<'de>,
2896 {
2897 serde_untagged::UntaggedEnumVisitor::new()
2898 .expecting("a boolean or a list of preview feature names")
2899 .bool(|value| Ok(Self::Toggle(value)))
2900 .seq(|sequence| sequence.deserialize().map(Self::Features))
2901 .deserialize(deserializer)
2902 }
2903}
2904
2905#[expect(
2906 dead_code,
2907 reason = "Fields are only used by the OptionsMetadata and JsonSchema derives"
2908)]
2909#[derive(OptionsMetadata)]
2910#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2911#[cfg_attr(feature = "schemars", schemars(rename_all = "kebab-case"))]
2912struct PreviewOptionsDefinition {
2913 #[deprecated(note = "use `preview-features` instead")]
2919 preview: Option<bool>,
2920 #[option(
2924 default = "false",
2925 value_type = "bool | list[str]",
2926 example = r#"
2927 preview-features = true
2928 # or
2929 preview-features = ["python-upgrade"]
2930 "#
2931 )]
2932 preview_features: Option<PreviewFeaturesOption>,
2933}
2934
2935#[derive(Debug, Clone)]
2937pub enum PreviewOption {
2938 Preview(bool),
2940 PreviewFeatures(PreviewFeaturesOption),
2942}
2943
2944impl uv_options_metadata::OptionsMetadata for PreviewOption {
2945 fn record(visit: &mut dyn uv_options_metadata::Visit) {
2946 <PreviewOptionsDefinition as uv_options_metadata::OptionsMetadata>::record(visit);
2947 }
2948}
2949
2950#[cfg(feature = "schemars")]
2951struct ConflictingPreviewOptions;
2952
2953#[cfg(feature = "schemars")]
2954impl schemars::JsonSchema for ConflictingPreviewOptions {
2955 fn schema_name() -> Cow<'static, str> {
2956 Cow::Borrowed("ConflictingPreviewOptions")
2957 }
2958
2959 fn json_schema(_generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
2960 schemars::json_schema!({
2961 "type": "object",
2962 "properties": {
2963 "preview": {},
2964 "preview-features": {},
2965 },
2966 "required": ["preview", "preview-features"],
2967 })
2968 }
2969}
2970
2971#[cfg(feature = "schemars")]
2972impl schemars::JsonSchema for PreviewOption {
2973 fn schema_name() -> Cow<'static, str> {
2974 Cow::Borrowed("PreviewOption")
2975 }
2976
2977 fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
2978 let mut schema = <PreviewOptionsDefinition as schemars::JsonSchema>::json_schema(generator);
2979 schema.insert(
2982 "not".to_string(),
2983 generator
2984 .subschema_for::<ConflictingPreviewOptions>()
2985 .into(),
2986 );
2987 schema
2988 }
2989}
2990
2991impl PreviewOption {
2992 fn try_from(
2993 preview: Option<bool>,
2994 preview_features: Option<PreviewFeaturesOption>,
2995 ) -> Result<Option<Self>, &'static str> {
2996 match (preview, preview_features) {
2997 (Some(_), Some(_)) => Err("cannot specify both `preview` and `preview-features`"),
2998 (Some(b), None) => Ok(Some(Self::Preview(b))),
2999 (None, Some(features)) => Ok(Some(Self::PreviewFeatures(features))),
3000 (None, None) => Ok(None),
3001 }
3002 }
3003
3004 pub fn resolve(&self) -> Preview {
3006 use PreviewFeaturesOption::{Features, Toggle};
3007
3008 match self {
3009 Self::Preview(false) | Self::PreviewFeatures(Toggle(false)) => Preview::default(),
3010 Self::Preview(true) | Self::PreviewFeatures(Toggle(true)) => Preview::all(),
3011 Self::PreviewFeatures(Features(features)) => Preview::from_feature_names(features),
3012 }
3013 }
3014}