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, IndexLocations, 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, PrereleasePackage, 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
513fn rebase_indexes(
515 root_dir: &Path,
516 indexes: &mut Option<Vec<Index>>,
517 index_url: &mut Option<PipIndex>,
518 extra_index_urls: &mut Option<Vec<PipExtraIndex>>,
519 find_links: &mut Option<Vec<PipFindLinks>>,
520) -> Result<(), IndexUrlError> {
521 *indexes = indexes
522 .take()
523 .map(|indexes| {
524 indexes
525 .into_iter()
526 .map(|index| index.relative_to(root_dir))
527 .collect::<Result<Vec<_>, _>>()
528 })
529 .transpose()?;
530 *index_url = index_url
531 .take()
532 .map(|index| index.relative_to(root_dir))
533 .transpose()?;
534 *extra_index_urls = extra_index_urls
535 .take()
536 .map(|indexes| {
537 indexes
538 .into_iter()
539 .map(|index| index.relative_to(root_dir))
540 .collect::<Result<Vec<_>, _>>()
541 })
542 .transpose()?;
543 *find_links = find_links
544 .take()
545 .map(|find_links| {
546 find_links
547 .into_iter()
548 .map(|find_link| find_link.relative_to(root_dir))
549 .collect::<Result<Vec<_>, _>>()
550 })
551 .transpose()?;
552
553 Ok(())
554}
555
556#[derive(Debug, Clone, Default, CombineOptions)]
558pub struct InstallerOptions {
559 index: Option<Vec<Index>>,
560 index_url: Option<PipIndex>,
561 extra_index_url: Option<Vec<PipExtraIndex>>,
562 no_index: Option<bool>,
563 find_links: Option<Vec<PipFindLinks>>,
564 index_strategy: Option<IndexStrategy>,
565 keyring_provider: Option<KeyringProviderType>,
566 config_settings: Option<ConfigSettings>,
567 exclude_newer: Option<ExcludeNewerOverride>,
568 link_mode: Option<LinkMode>,
569 compile_bytecode: Option<bool>,
570 reinstall: Option<Reinstall>,
571 build_isolation: Option<BuildIsolation>,
572 no_build: Option<bool>,
573 no_build_package: Option<Vec<PackageName>>,
574 no_binary: Option<bool>,
575 no_binary_package: Option<Vec<PackageName>>,
576 no_sources: Option<bool>,
577 no_sources_package: Option<Vec<PackageName>>,
578}
579
580#[derive(Debug, Clone, Default, CombineOptions)]
582pub struct IndexOptions {
583 pub index: Option<Vec<Index>>,
584 pub index_url: Option<PipIndex>,
585 pub extra_index_url: Option<Vec<PipExtraIndex>>,
586 pub no_index: Option<bool>,
587 pub find_links: Option<Vec<PipFindLinks>>,
588}
589
590impl IndexOptions {
591 pub fn relative_to(mut self, root_dir: &Path) -> Result<Self, IndexUrlError> {
593 rebase_indexes(
594 root_dir,
595 &mut self.index,
596 &mut self.index_url,
597 &mut self.extra_index_url,
598 &mut self.find_links,
599 )?;
600
601 Ok(self)
602 }
603}
604
605impl From<IndexOptions> for IndexLocations {
606 fn from(value: IndexOptions) -> Self {
607 let IndexOptions {
608 index,
609 index_url,
610 extra_index_url,
611 no_index,
612 find_links,
613 } = value;
614
615 Self::new(
616 index
617 .into_iter()
618 .flatten()
619 .chain(extra_index_url.into_iter().flatten().map(Index::from))
620 .chain(index_url.into_iter().map(Index::from))
621 .collect(),
622 find_links.into_iter().flatten().map(Index::from).collect(),
623 no_index.unwrap_or_default(),
624 )
625 }
626}
627
628impl From<IndexOptions> for PipOptions {
629 fn from(value: IndexOptions) -> Self {
630 let IndexOptions {
631 index,
632 index_url,
633 extra_index_url,
634 no_index,
635 find_links,
636 } = value;
637
638 Self {
639 index,
640 index_url,
641 extra_index_url,
642 no_index,
643 find_links,
644 ..Self::default()
645 }
646 }
647}
648
649#[derive(Debug, Clone, Default, CombineOptions)]
651pub struct ResolverOptions {
652 pub indexes: IndexOptions,
653 pub index_strategy: Option<IndexStrategy>,
654 pub keyring_provider: Option<KeyringProviderType>,
655 pub resolution: Option<ResolutionMode>,
656 pub prerelease: Option<PrereleaseMode>,
657 pub prerelease_package: Option<PrereleasePackage>,
658 pub fork_strategy: Option<ForkStrategy>,
659 pub dependency_metadata: Option<Vec<StaticMetadata>>,
660 pub config_settings: Option<ConfigSettings>,
661 pub config_settings_package: Option<PackageConfigSettings>,
662 pub exclude_newer: Option<ExcludeNewerOverride>,
663 pub exclude_newer_package: Option<ExcludeNewerPackage>,
664 pub link_mode: Option<LinkMode>,
665 pub torch_backend: Option<TorchMode>,
666 pub upgrade: Option<Upgrade>,
667 pub build_isolation: Option<BuildIsolation>,
668 pub no_build: Option<bool>,
669 pub no_build_package: Option<Vec<PackageName>>,
670 pub no_binary: Option<bool>,
671 pub no_binary_package: Option<Vec<PackageName>>,
672 pub extra_build_dependencies: Option<ExtraBuildDependencies>,
673 pub extra_build_variables: Option<ExtraBuildVariables>,
674 pub no_sources: Option<bool>,
675 pub no_sources_package: Option<Vec<PackageName>>,
676}
677
678impl ResolverOptions {
679 pub fn relative_to(mut self, root_dir: &Path) -> Result<Self, IndexUrlError> {
681 self.indexes = self.indexes.relative_to(root_dir)?;
682 Ok(self)
683 }
684}
685
686#[derive(Debug, Clone, Default, CombineOptions)]
689pub struct ResolverInstallerOptions {
690 pub indexes: IndexOptions,
691 pub index_strategy: Option<IndexStrategy>,
692 pub keyring_provider: Option<KeyringProviderType>,
693 pub resolution: Option<ResolutionMode>,
694 pub prerelease: Option<PrereleaseMode>,
695 pub prerelease_package: Option<PrereleasePackage>,
696 pub fork_strategy: Option<ForkStrategy>,
697 pub dependency_metadata: Option<Vec<StaticMetadata>>,
698 pub config_settings: Option<ConfigSettings>,
699 pub config_settings_package: Option<PackageConfigSettings>,
700 pub build_isolation: Option<BuildIsolation>,
701 pub extra_build_dependencies: Option<ExtraBuildDependencies>,
702 pub extra_build_variables: Option<ExtraBuildVariables>,
703 pub exclude_newer: Option<ExcludeNewerOverride>,
704 pub exclude_newer_package: Option<ExcludeNewerPackage>,
705 pub link_mode: Option<LinkMode>,
706 pub torch_backend: Option<TorchMode>,
707 pub compile_bytecode: Option<bool>,
708 pub no_sources: Option<bool>,
709 pub no_sources_package: Option<Vec<PackageName>>,
710 pub upgrade: Option<Upgrade>,
711 pub reinstall: Option<Reinstall>,
712 pub no_build: Option<bool>,
713 pub no_build_package: Option<Vec<PackageName>>,
714 pub no_binary: Option<bool>,
715 pub no_binary_package: Option<Vec<PackageName>>,
716}
717
718impl ResolverInstallerOptions {
719 pub fn relative_to(mut self, root_dir: &Path) -> Result<Self, IndexUrlError> {
721 self.indexes = self.indexes.relative_to(root_dir)?;
722 Ok(self)
723 }
724}
725
726impl From<ResolverInstallerSchema> for ResolverInstallerOptions {
727 fn from(value: ResolverInstallerSchema) -> Self {
728 let ResolverInstallerSchema {
729 index,
730 index_url,
731 extra_index_url,
732 no_index,
733 find_links,
734 index_strategy,
735 keyring_provider,
736 resolution,
737 prerelease,
738 prerelease_package,
739 fork_strategy,
740 dependency_metadata,
741 config_settings,
742 config_settings_package,
743 no_build_isolation,
744 no_build_isolation_package,
745 extra_build_dependencies,
746 extra_build_variables,
747 exclude_newer,
748 exclude_newer_package,
749 link_mode,
750 torch_backend,
751 compile_bytecode,
752 no_sources,
753 no_sources_package,
754 upgrade,
755 upgrade_package,
756 reinstall,
757 reinstall_package,
758 no_build,
759 no_build_package,
760 no_binary,
761 no_binary_package,
762 } = value;
763 Self {
764 indexes: IndexOptions {
765 index,
766 index_url,
767 extra_index_url,
768 no_index,
769 find_links,
770 },
771 index_strategy,
772 keyring_provider,
773 resolution,
774 prerelease,
775 prerelease_package,
776 fork_strategy,
777 dependency_metadata,
778 config_settings,
779 config_settings_package,
780 build_isolation: BuildIsolation::from_args(
781 no_build_isolation,
782 no_build_isolation_package.into_iter().flatten().collect(),
783 ),
784 extra_build_dependencies,
785 extra_build_variables,
786 exclude_newer,
787 exclude_newer_package,
788 link_mode,
789 torch_backend,
790 compile_bytecode,
791 no_sources,
792 no_sources_package,
793 upgrade: Upgrade::from_args(
794 upgrade,
795 upgrade_package
796 .into_iter()
797 .flatten()
798 .map(Into::into)
799 .collect(),
800 Vec::new(),
801 ),
802 reinstall: Reinstall::from_args(reinstall, reinstall_package.unwrap_or_default()),
803 no_build,
804 no_build_package,
805 no_binary,
806 no_binary_package,
807 }
808 }
809}
810
811impl ResolverInstallerSchema {
812 fn relative_to(mut self, root_dir: &Path) -> Result<Self, IndexUrlError> {
814 rebase_indexes(
815 root_dir,
816 &mut self.index,
817 &mut self.index_url,
818 &mut self.extra_index_url,
819 &mut self.find_links,
820 )?;
821
822 Ok(self)
823 }
824}
825
826#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
828#[serde(rename_all = "kebab-case")]
829#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
830pub struct ResolverInstallerSchema {
831 #[option(
859 default = "\"[]\"",
860 value_type = "dict",
861 example = r#"
862 [[tool.uv.index]]
863 name = "pytorch"
864 url = "https://download.pytorch.org/whl/cu130"
865 "#
866 )]
867 pub index: Option<Vec<Index>>,
868 #[option(
878 default = "\"https://pypi.org/simple\"",
879 value_type = "str",
880 example = r#"
881 index-url = "https://test.pypi.org/simple"
882 "#
883 )]
884 pub index_url: Option<PipIndex>,
885 #[option(
899 default = "[]",
900 value_type = "list[str]",
901 example = r#"
902 extra-index-url = ["https://download.pytorch.org/whl/cpu"]
903 "#
904 )]
905 pub extra_index_url: Option<Vec<PipExtraIndex>>,
906 #[option(
909 default = "false",
910 value_type = "bool",
911 example = r#"
912 no-index = true
913 "#
914 )]
915 pub no_index: Option<bool>,
916 #[option(
925 default = "[]",
926 value_type = "list[str]",
927 example = r#"
928 find-links = ["https://download.pytorch.org/whl/torch_stable.html"]
929 "#
930 )]
931 pub find_links: Option<Vec<PipFindLinks>>,
932 #[option(
939 default = "\"first-index\"",
940 value_type = "str",
941 example = r#"
942 index-strategy = "unsafe-best-match"
943 "#,
944 possible_values = true
945 )]
946 pub index_strategy: Option<IndexStrategy>,
947 #[option(
952 default = "\"disabled\"",
953 value_type = "str",
954 example = r#"
955 keyring-provider = "subprocess"
956 "#
957 )]
958 pub keyring_provider: Option<KeyringProviderType>,
959 #[option(
964 default = "\"highest\"",
965 value_type = "str",
966 example = r#"
967 resolution = "lowest-direct"
968 "#,
969 possible_values = true
970 )]
971 pub resolution: Option<ResolutionMode>,
972 #[option(
978 default = "\"if-necessary\"",
979 value_type = "str",
980 example = r#"
981 prerelease = "allow"
982 "#,
983 possible_values = true
984 )]
985 pub prerelease: Option<PrereleaseMode>,
986 #[option(
991 default = "{}",
992 value_type = "dict",
993 example = r#"
994 prerelease-package = { numpy = "allow", scipy = "disallow" }
995 "#
996 )]
997 pub prerelease_package: Option<PrereleasePackage>,
998 #[option(
1009 default = "\"requires-python\"",
1010 value_type = "str",
1011 example = r#"
1012 fork-strategy = "fewest"
1013 "#,
1014 possible_values = true
1015 )]
1016 pub fork_strategy: Option<ForkStrategy>,
1017 #[option(
1031 default = r#"[]"#,
1032 value_type = "list[dict]",
1033 example = r#"
1034 dependency-metadata = [
1035 { name = "flask", version = "1.0.0", requires-dist = ["werkzeug"], requires-python = ">=3.6" },
1036 ]
1037 "#
1038 )]
1039 pub dependency_metadata: Option<Vec<StaticMetadata>>,
1040 #[option(
1043 default = "{}",
1044 value_type = "dict",
1045 example = r#"
1046 config-settings = { editable_mode = "compat" }
1047 "#
1048 )]
1049 pub config_settings: Option<ConfigSettings>,
1050 #[option(
1055 default = "{}",
1056 value_type = "dict",
1057 example = r#"
1058 config-settings-package = { numpy = { editable_mode = "compat" } }
1059 "#
1060 )]
1061 pub config_settings_package: Option<PackageConfigSettings>,
1062 #[option(
1067 default = "false",
1068 value_type = "bool",
1069 example = r#"
1070 no-build-isolation = true
1071 "#
1072 )]
1073 pub no_build_isolation: Option<bool>,
1074 #[option(
1079 default = "[]",
1080 value_type = "list[str]",
1081 example = r#"
1082 no-build-isolation-package = ["package1", "package2"]
1083 "#
1084 )]
1085 pub no_build_isolation_package: Option<Vec<PackageName>>,
1086 #[option(
1092 default = "[]",
1093 value_type = "dict",
1094 example = r#"
1095 extra-build-dependencies = { pytest = ["setuptools"] }
1096 "#
1097 )]
1098 pub extra_build_dependencies: Option<ExtraBuildDependencies>,
1099 #[option(
1104 default = r#"{}"#,
1105 value_type = r#"dict[str, dict[str, str]]"#,
1106 example = r#"
1107 extra-build-variables = { flash-attn = { FLASH_ATTENTION_SKIP_CUDA_BUILD = "TRUE" } }
1108 "#
1109 )]
1110 pub extra_build_variables: Option<ExtraBuildVariables>,
1111 #[option(
1126 default = "None",
1127 value_type = "str | false",
1128 example = r#"
1129 exclude-newer = "2006-12-02T02:07:43Z"
1130 "#
1131 )]
1132 pub exclude_newer: Option<ExcludeNewerOverride>,
1133 #[option(
1147 default = "None",
1148 value_type = "dict",
1149 example = r#"
1150 exclude-newer-package = { tqdm = "2022-04-04T00:00:00Z", markupsafe = false }
1151 "#
1152 )]
1153 pub exclude_newer_package: Option<ExcludeNewerPackage>,
1154 #[option(
1164 default = "\"clone\" (macOS, Linux) or \"hardlink\" (Windows)",
1165 value_type = "str",
1166 example = r#"
1167 link-mode = "copy"
1168 "#,
1169 possible_values = true
1170 )]
1171 pub link_mode: Option<LinkMode>,
1172 #[option(
1183 default = "false",
1184 value_type = "bool",
1185 example = r#"
1186 compile-bytecode = true
1187 "#
1188 )]
1189 pub compile_bytecode: Option<bool>,
1190 #[option(
1194 default = "false",
1195 value_type = "bool",
1196 example = r#"
1197 no-sources = true
1198 "#
1199 )]
1200 pub no_sources: Option<bool>,
1201 #[option(
1203 default = "[]",
1204 value_type = "list[str]",
1205 example = r#"
1206 no-sources-package = ["ruff"]
1207 "#
1208 )]
1209 pub no_sources_package: Option<Vec<PackageName>>,
1210 #[option(
1212 default = "false",
1213 value_type = "bool",
1214 example = r#"
1215 upgrade = true
1216 "#
1217 )]
1218 pub upgrade: Option<bool>,
1219 #[option(
1224 default = "[]",
1225 value_type = "list[str]",
1226 example = r#"
1227 upgrade-package = ["ruff"]
1228 "#
1229 )]
1230 pub upgrade_package: Option<Vec<Requirement<VerbatimParsedUrl>>>,
1231 #[option(
1233 default = "false",
1234 value_type = "bool",
1235 example = r#"
1236 reinstall = true
1237 "#
1238 )]
1239 pub reinstall: Option<bool>,
1240 #[option(
1243 default = "[]",
1244 value_type = "list[str]",
1245 example = r#"
1246 reinstall-package = ["ruff"]
1247 "#
1248 )]
1249 pub reinstall_package: Option<Vec<PackageName>>,
1250 #[option(
1256 default = "false",
1257 value_type = "bool",
1258 example = r#"
1259 no-build = true
1260 "#
1261 )]
1262 pub no_build: Option<bool>,
1263 #[option(
1265 default = "[]",
1266 value_type = "list[str]",
1267 example = r#"
1268 no-build-package = ["ruff"]
1269 "#
1270 )]
1271 pub no_build_package: Option<Vec<PackageName>>,
1272 #[option(
1277 default = "false",
1278 value_type = "bool",
1279 example = r#"
1280 no-binary = true
1281 "#
1282 )]
1283 pub no_binary: Option<bool>,
1284 #[option(
1286 default = "[]",
1287 value_type = "list[str]",
1288 example = r#"
1289 no-binary-package = ["ruff"]
1290 "#
1291 )]
1292 pub no_binary_package: Option<Vec<PackageName>>,
1293 #[option(
1308 default = "null",
1309 value_type = "str",
1310 example = r#"
1311 torch-backend = "auto"
1312 "#
1313 )]
1314 pub torch_backend: Option<TorchMode>,
1315}
1316
1317#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
1319#[serde(rename_all = "kebab-case")]
1320#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1321pub struct PythonInstallMirrors {
1322 #[option(
1330 default = "None",
1331 value_type = "str",
1332 uv_toml_only = true,
1333 example = r#"
1334 python-install-mirror = "https://github.com/astral-sh/python-build-standalone/releases/download"
1335 "#
1336 )]
1337 pub python_install_mirror: Option<String>,
1338 #[option(
1347 default = "None",
1348 value_type = "str",
1349 uv_toml_only = true,
1350 example = r#"
1351 pypy-install-mirror = "https://downloads.python.org/pypy"
1352 "#
1353 )]
1354 pub pypy_install_mirror: Option<String>,
1355
1356 #[option(
1358 default = "None",
1359 value_type = "str",
1360 uv_toml_only = true,
1361 example = r#"
1362 python-downloads-json-url = "/etc/uv/python-downloads.json"
1363 "#
1364 )]
1365 pub python_downloads_json_url: Option<String>,
1366}
1367
1368impl PythonInstallMirrors {
1369 #[must_use]
1370 pub fn combine(self, other: Self) -> Self {
1371 Self {
1372 python_install_mirror: self.python_install_mirror.or(other.python_install_mirror),
1373 pypy_install_mirror: self.pypy_install_mirror.or(other.pypy_install_mirror),
1374 python_downloads_json_url: self
1375 .python_downloads_json_url
1376 .or(other.python_downloads_json_url),
1377 }
1378 }
1379}
1380
1381#[derive(Debug, Clone, Default, Deserialize, CombineOptions, OptionsMetadata)]
1386#[serde(deny_unknown_fields, rename_all = "kebab-case")]
1387#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1388pub struct PipOptions {
1389 #[option(
1402 default = "None",
1403 value_type = "str",
1404 example = r#"
1405 python = "3.10"
1406 "#
1407 )]
1408 pub python: Option<String>,
1409 #[option(
1418 default = "false",
1419 value_type = "bool",
1420 example = r#"
1421 system = true
1422 "#
1423 )]
1424 pub system: Option<bool>,
1425 #[option(
1432 default = "false",
1433 value_type = "bool",
1434 example = r#"
1435 break-system-packages = true
1436 "#
1437 )]
1438 pub break_system_packages: Option<bool>,
1439 #[option(
1442 default = "None",
1443 value_type = "str",
1444 example = r#"
1445 target = "./target"
1446 "#
1447 )]
1448 pub target: Option<PathBuf>,
1449 #[option(
1457 default = "None",
1458 value_type = "str",
1459 example = r#"
1460 prefix = "./prefix"
1461 "#
1462 )]
1463 pub prefix: Option<PathBuf>,
1464 #[serde(skip)]
1465 #[cfg_attr(feature = "schemars", schemars(skip))]
1466 pub index: Option<Vec<Index>>,
1467 #[option(
1475 default = "\"https://pypi.org/simple\"",
1476 value_type = "str",
1477 example = r#"
1478 index-url = "https://test.pypi.org/simple"
1479 "#
1480 )]
1481 pub index_url: Option<PipIndex>,
1482 #[option(
1493 default = "[]",
1494 value_type = "list[str]",
1495 example = r#"
1496 extra-index-url = ["https://download.pytorch.org/whl/cpu"]
1497 "#
1498 )]
1499 pub extra_index_url: Option<Vec<PipExtraIndex>>,
1500 #[option(
1503 default = "false",
1504 value_type = "bool",
1505 example = r#"
1506 no-index = true
1507 "#
1508 )]
1509 pub no_index: Option<bool>,
1510 #[option(
1519 default = "[]",
1520 value_type = "list[str]",
1521 example = r#"
1522 find-links = ["https://download.pytorch.org/whl/torch_stable.html"]
1523 "#
1524 )]
1525 pub find_links: Option<Vec<PipFindLinks>>,
1526 #[option(
1533 default = "\"first-index\"",
1534 value_type = "str",
1535 example = r#"
1536 index-strategy = "unsafe-best-match"
1537 "#,
1538 possible_values = true
1539 )]
1540 pub index_strategy: Option<IndexStrategy>,
1541 #[option(
1546 default = "disabled",
1547 value_type = "str",
1548 example = r#"
1549 keyring-provider = "subprocess"
1550 "#
1551 )]
1552 pub keyring_provider: Option<KeyringProviderType>,
1553 #[option(
1561 default = "false",
1562 value_type = "bool",
1563 example = r#"
1564 no-build = true
1565 "#
1566 )]
1567 pub no_build: Option<bool>,
1568 #[option(
1576 default = "[]",
1577 value_type = "list[str]",
1578 example = r#"
1579 no-binary = ["ruff"]
1580 "#
1581 )]
1582 pub no_binary: Option<Vec<PackageNameSpecifier>>,
1583 #[option(
1593 default = "[]",
1594 value_type = "list[str]",
1595 example = r#"
1596 only-binary = ["ruff"]
1597 "#
1598 )]
1599 pub only_binary: Option<Vec<PackageNameSpecifier>>,
1600 #[option(
1605 default = "false",
1606 value_type = "bool",
1607 example = r#"
1608 no-build-isolation = true
1609 "#
1610 )]
1611 pub no_build_isolation: Option<bool>,
1612 #[option(
1617 default = "[]",
1618 value_type = "list[str]",
1619 example = r#"
1620 no-build-isolation-package = ["package1", "package2"]
1621 "#
1622 )]
1623 pub no_build_isolation_package: Option<Vec<PackageName>>,
1624 #[option(
1630 default = "[]",
1631 value_type = "dict",
1632 example = r#"
1633 extra-build-dependencies = { pytest = ["setuptools"] }
1634 "#
1635 )]
1636 pub extra_build_dependencies: Option<ExtraBuildDependencies>,
1637 #[option(
1642 default = r#"{}"#,
1643 value_type = r#"dict[str, dict[str, str]]"#,
1644 example = r#"
1645 extra-build-variables = { flash-attn = { FLASH_ATTENTION_SKIP_CUDA_BUILD = "TRUE" } }
1646 "#
1647 )]
1648 pub extra_build_variables: Option<ExtraBuildVariables>,
1649 #[option(
1652 default = "false",
1653 value_type = "bool",
1654 example = r#"
1655 strict = true
1656 "#
1657 )]
1658 pub strict: Option<bool>,
1659 #[option(
1663 default = "[]",
1664 value_type = "list[str]",
1665 example = r#"
1666 extra = ["dev", "docs"]
1667 "#
1668 )]
1669 pub extra: Option<Vec<ExtraName>>,
1670 #[option(
1674 default = "false",
1675 value_type = "bool",
1676 example = r#"
1677 all-extras = true
1678 "#
1679 )]
1680 pub all_extras: Option<bool>,
1681 #[option(
1683 default = "[]",
1684 value_type = "list[str]",
1685 example = r#"
1686 all-extras = true
1687 no-extra = ["dev", "docs"]
1688 "#
1689 )]
1690 pub no_extra: Option<Vec<ExtraName>>,
1691 #[option(
1694 default = "false",
1695 value_type = "bool",
1696 example = r#"
1697 no-deps = true
1698 "#
1699 )]
1700 pub no_deps: Option<bool>,
1701 #[option(
1703 default = "None",
1704 value_type = "list[str]",
1705 example = r#"
1706 group = ["dev", "docs"]
1707 "#
1708 )]
1709 pub group: Option<Vec<PipGroupName>>,
1710 #[option(
1713 default = "false",
1714 value_type = "bool",
1715 example = r#"
1716 allow-empty-requirements = true
1717 "#
1718 )]
1719 pub allow_empty_requirements: Option<bool>,
1720 #[option(
1725 default = "\"highest\"",
1726 value_type = "str",
1727 example = r#"
1728 resolution = "lowest-direct"
1729 "#,
1730 possible_values = true
1731 )]
1732 pub resolution: Option<ResolutionMode>,
1733 #[option(
1739 default = "\"if-necessary\"",
1740 value_type = "str",
1741 example = r#"
1742 prerelease = "allow"
1743 "#,
1744 possible_values = true
1745 )]
1746 pub prerelease: Option<PrereleaseMode>,
1747 #[serde(skip)]
1748 #[cfg_attr(feature = "schemars", schemars(skip))]
1749 pub prerelease_package: Option<PrereleasePackage>,
1750 #[option(
1761 default = "\"requires-python\"",
1762 value_type = "str",
1763 example = r#"
1764 fork-strategy = "fewest"
1765 "#,
1766 possible_values = true
1767 )]
1768 pub fork_strategy: Option<ForkStrategy>,
1769 #[option(
1783 default = r#"[]"#,
1784 value_type = "list[dict]",
1785 example = r#"
1786 dependency-metadata = [
1787 { name = "flask", version = "1.0.0", requires-dist = ["werkzeug"], requires-python = ">=3.6" },
1788 ]
1789 "#
1790 )]
1791 pub dependency_metadata: Option<Vec<StaticMetadata>>,
1792 #[option(
1797 default = "None",
1798 value_type = "str",
1799 example = r#"
1800 output-file = "requirements.txt"
1801 "#
1802 )]
1803 pub output_file: Option<PathBuf>,
1804 #[option(
1810 default = "false",
1811 value_type = "bool",
1812 example = r#"
1813 no-strip-extras = true
1814 "#
1815 )]
1816 pub no_strip_extras: Option<bool>,
1817 #[option(
1822 default = "false",
1823 value_type = "bool",
1824 example = r#"
1825 no-strip-markers = true
1826 "#
1827 )]
1828 pub no_strip_markers: Option<bool>,
1829 #[option(
1832 default = "false",
1833 value_type = "bool",
1834 example = r#"
1835 no-annotate = true
1836 "#
1837 )]
1838 pub no_annotate: Option<bool>,
1839 #[option(
1841 default = r#"false"#,
1842 value_type = "bool",
1843 example = r#"
1844 no-header = true
1845 "#
1846 )]
1847 pub no_header: Option<bool>,
1848 #[option(
1852 default = "None",
1853 value_type = "str",
1854 example = r#"
1855 custom-compile-command = "./custom-uv-compile.sh"
1856 "#
1857 )]
1858 pub custom_compile_command: Option<String>,
1859 #[option(
1861 default = "false",
1862 value_type = "bool",
1863 example = r#"
1864 generate-hashes = true
1865 "#
1866 )]
1867 pub generate_hashes: Option<bool>,
1868 #[option(
1871 default = "{}",
1872 value_type = "dict",
1873 example = r#"
1874 config-settings = { editable_mode = "compat" }
1875 "#
1876 )]
1877 pub config_settings: Option<ConfigSettings>,
1878 #[option(
1881 default = "{}",
1882 value_type = "dict",
1883 example = r#"
1884 config-settings-package = { numpy = { editable_mode = "compat" } }
1885 "#
1886 )]
1887 pub config_settings_package: Option<PackageConfigSettings>,
1888 #[option(
1894 default = "None",
1895 value_type = "str",
1896 example = r#"
1897 python-version = "3.8"
1898 "#
1899 )]
1900 pub python_version: Option<PythonVersion>,
1901 #[option(
1907 default = "None",
1908 value_type = "str",
1909 example = r#"
1910 python-platform = "x86_64-unknown-linux-gnu"
1911 "#
1912 )]
1913 pub python_platform: Option<TargetTriple>,
1914 #[option(
1922 default = "false",
1923 value_type = "bool",
1924 example = r#"
1925 universal = true
1926 "#
1927 )]
1928 pub universal: Option<bool>,
1929 #[option(
1944 default = "None",
1945 value_type = "str | false",
1946 example = r#"
1947 exclude-newer = "2006-12-02T02:07:43Z"
1948 "#
1949 )]
1950 pub exclude_newer: Option<ExcludeNewerOverride>,
1951 #[option(
1964 default = "None",
1965 value_type = "dict",
1966 example = r#"
1967 exclude-newer-package = { tqdm = "2022-04-04T00:00:00Z", markupsafe = false }
1968 "#
1969 )]
1970 pub exclude_newer_package: Option<ExcludeNewerPackage>,
1971 #[option(
1974 default = "[]",
1975 value_type = "list[str]",
1976 example = r#"
1977 no-emit-package = ["ruff"]
1978 "#
1979 )]
1980 pub no_emit_package: Option<Vec<PackageName>>,
1981 #[option(
1983 default = "false",
1984 value_type = "bool",
1985 example = r#"
1986 emit-index-url = true
1987 "#
1988 )]
1989 pub emit_index_url: Option<bool>,
1990 #[option(
1992 default = "false",
1993 value_type = "bool",
1994 example = r#"
1995 emit-find-links = true
1996 "#
1997 )]
1998 pub emit_find_links: Option<bool>,
1999 #[option(
2001 default = "false",
2002 value_type = "bool",
2003 example = r#"
2004 emit-build-options = true
2005 "#
2006 )]
2007 pub emit_build_options: Option<bool>,
2008 #[option(
2015 default = "false",
2016 value_type = "bool",
2017 example = r#"
2018 emit-marker-expression = true
2019 "#
2020 )]
2021 pub emit_marker_expression: Option<bool>,
2022 #[option(
2025 default = "false",
2026 value_type = "bool",
2027 example = r#"
2028 emit-index-annotation = true
2029 "#
2030 )]
2031 pub emit_index_annotation: Option<bool>,
2032 #[option(
2035 default = "\"split\"",
2036 value_type = "str",
2037 example = r#"
2038 annotation-style = "line"
2039 "#,
2040 possible_values = true
2041 )]
2042 pub annotation_style: Option<AnnotationStyle>,
2043 #[option(
2053 default = "\"clone\" (macOS, Linux) or \"hardlink\" (Windows)",
2054 value_type = "str",
2055 example = r#"
2056 link-mode = "copy"
2057 "#,
2058 possible_values = true
2059 )]
2060 pub link_mode: Option<LinkMode>,
2061 #[option(
2072 default = "false",
2073 value_type = "bool",
2074 example = r#"
2075 compile-bytecode = true
2076 "#
2077 )]
2078 pub compile_bytecode: Option<bool>,
2079 #[option(
2092 default = "false",
2093 value_type = "bool",
2094 example = r#"
2095 require-hashes = true
2096 "#
2097 )]
2098 pub require_hashes: Option<bool>,
2099 #[option(
2105 default = "true",
2106 value_type = "bool",
2107 example = r#"
2108 verify-hashes = true
2109 "#
2110 )]
2111 pub verify_hashes: Option<bool>,
2112 #[option(
2116 default = "false",
2117 value_type = "bool",
2118 example = r#"
2119 no-sources = true
2120 "#
2121 )]
2122 pub no_sources: Option<bool>,
2123 #[option(
2125 default = "[]",
2126 value_type = "list[str]",
2127 example = r#"
2128 no-sources-package = ["ruff"]
2129 "#
2130 )]
2131 pub no_sources_package: Option<Vec<PackageName>>,
2132 #[option(
2134 default = "false",
2135 value_type = "bool",
2136 example = r#"
2137 upgrade = true
2138 "#
2139 )]
2140 pub upgrade: Option<bool>,
2141 #[option(
2146 default = "[]",
2147 value_type = "list[str]",
2148 example = r#"
2149 upgrade-package = ["ruff"]
2150 "#
2151 )]
2152 pub upgrade_package: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2153 #[option(
2155 default = "false",
2156 value_type = "bool",
2157 example = r#"
2158 reinstall = true
2159 "#
2160 )]
2161 pub reinstall: Option<bool>,
2162 #[option(
2165 default = "[]",
2166 value_type = "list[str]",
2167 example = r#"
2168 reinstall-package = ["ruff"]
2169 "#
2170 )]
2171 pub reinstall_package: Option<Vec<PackageName>>,
2172 #[option(
2187 default = "null",
2188 value_type = "str",
2189 example = r#"
2190 torch-backend = "auto"
2191 "#
2192 )]
2193 pub torch_backend: Option<TorchMode>,
2194}
2195
2196impl PipOptions {
2197 fn relative_to(mut self, root_dir: &Path) -> Result<Self, IndexUrlError> {
2199 rebase_indexes(
2200 root_dir,
2201 &mut self.index,
2202 &mut self.index_url,
2203 &mut self.extra_index_url,
2204 &mut self.find_links,
2205 )?;
2206
2207 Ok(self)
2208 }
2209}
2210
2211impl From<ResolverInstallerSchema> for ResolverOptions {
2212 fn from(value: ResolverInstallerSchema) -> Self {
2213 Self {
2214 indexes: IndexOptions {
2215 index: value.index,
2216 index_url: value.index_url,
2217 extra_index_url: value.extra_index_url,
2218 no_index: value.no_index,
2219 find_links: value.find_links,
2220 },
2221 index_strategy: value.index_strategy,
2222 keyring_provider: value.keyring_provider,
2223 resolution: value.resolution,
2224 prerelease: value.prerelease,
2225 prerelease_package: value.prerelease_package,
2226 fork_strategy: value.fork_strategy,
2227 dependency_metadata: value.dependency_metadata,
2228 config_settings: value.config_settings,
2229 config_settings_package: value.config_settings_package,
2230 exclude_newer: value.exclude_newer,
2231 exclude_newer_package: value.exclude_newer_package,
2232 link_mode: value.link_mode,
2233 upgrade: Upgrade::from_args(
2234 value.upgrade,
2235 value
2236 .upgrade_package
2237 .into_iter()
2238 .flatten()
2239 .map(Into::into)
2240 .collect(),
2241 Vec::new(),
2242 ),
2243 no_build: value.no_build,
2244 no_build_package: value.no_build_package,
2245 no_binary: value.no_binary,
2246 no_binary_package: value.no_binary_package,
2247 build_isolation: BuildIsolation::from_args(
2248 value.no_build_isolation,
2249 value.no_build_isolation_package.unwrap_or_default(),
2250 ),
2251 extra_build_dependencies: value.extra_build_dependencies,
2252 extra_build_variables: value.extra_build_variables,
2253 no_sources: value.no_sources,
2254 no_sources_package: value.no_sources_package,
2255 torch_backend: value.torch_backend,
2256 }
2257 }
2258}
2259
2260impl From<ResolverInstallerSchema> for InstallerOptions {
2261 fn from(value: ResolverInstallerSchema) -> Self {
2262 Self {
2263 index: value.index,
2264 index_url: value.index_url,
2265 extra_index_url: value.extra_index_url,
2266 no_index: value.no_index,
2267 find_links: value.find_links,
2268 index_strategy: value.index_strategy,
2269 keyring_provider: value.keyring_provider,
2270 config_settings: value.config_settings,
2271 exclude_newer: value.exclude_newer,
2272 link_mode: value.link_mode,
2273 compile_bytecode: value.compile_bytecode,
2274 reinstall: Reinstall::from_args(
2275 value.reinstall,
2276 value.reinstall_package.unwrap_or_default(),
2277 ),
2278 build_isolation: BuildIsolation::from_args(
2279 value.no_build_isolation,
2280 value.no_build_isolation_package.unwrap_or_default(),
2281 ),
2282 no_build: value.no_build,
2283 no_build_package: value.no_build_package,
2284 no_binary: value.no_binary,
2285 no_binary_package: value.no_binary_package,
2286 no_sources: value.no_sources,
2287 no_sources_package: value.no_sources_package,
2288 }
2289 }
2290}
2291
2292#[derive(
2297 Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, CombineOptions, OptionsMetadata,
2298)]
2299#[serde(deny_unknown_fields, rename_all = "kebab-case")]
2300#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2301pub struct ToolOptions {
2302 index: Option<Vec<Index>>,
2303 index_url: Option<PipIndex>,
2304 extra_index_url: Option<Vec<PipExtraIndex>>,
2305 no_index: Option<bool>,
2306 find_links: Option<Vec<PipFindLinks>>,
2307 index_strategy: Option<IndexStrategy>,
2308 keyring_provider: Option<KeyringProviderType>,
2309 resolution: Option<ResolutionMode>,
2310 prerelease: Option<PrereleaseMode>,
2311 prerelease_package: Option<PrereleasePackage>,
2312 fork_strategy: Option<ForkStrategy>,
2313 dependency_metadata: Option<Vec<StaticMetadata>>,
2314 config_settings: Option<ConfigSettings>,
2315 config_settings_package: Option<PackageConfigSettings>,
2316 build_isolation: Option<BuildIsolation>,
2317 extra_build_dependencies: Option<ExtraBuildDependencies>,
2318 extra_build_variables: Option<ExtraBuildVariables>,
2319 exclude_newer: Option<ExcludeNewerOverride>,
2320 exclude_newer_package: Option<ExcludeNewerPackage>,
2321 link_mode: Option<LinkMode>,
2322 compile_bytecode: Option<bool>,
2323 no_sources: Option<bool>,
2324 no_sources_package: Option<Vec<PackageName>>,
2325 no_build: Option<bool>,
2326 no_build_package: Option<Vec<PackageName>>,
2327 no_binary: Option<bool>,
2328 no_binary_package: Option<Vec<PackageName>>,
2329 torch_backend: Option<TorchMode>,
2330}
2331
2332#[derive(Debug, Clone, Default, Serialize, Deserialize)]
2334#[serde(deny_unknown_fields, rename_all = "kebab-case")]
2335pub struct ToolOptionsWire {
2336 index: Option<Vec<Index>>,
2337 index_url: Option<PipIndex>,
2338 extra_index_url: Option<Vec<PipExtraIndex>>,
2339 no_index: Option<bool>,
2340 find_links: Option<Vec<PipFindLinks>>,
2341 index_strategy: Option<IndexStrategy>,
2342 keyring_provider: Option<KeyringProviderType>,
2343 resolution: Option<ResolutionMode>,
2344 prerelease: Option<PrereleaseMode>,
2345 prerelease_package: Option<PrereleasePackage>,
2346 fork_strategy: Option<ForkStrategy>,
2347 dependency_metadata: Option<Vec<StaticMetadata>>,
2348 config_settings: Option<ConfigSettings>,
2349 config_settings_package: Option<PackageConfigSettings>,
2350 build_isolation: Option<BuildIsolation>,
2351 extra_build_dependencies: Option<ExtraBuildDependencies>,
2352 extra_build_variables: Option<ExtraBuildVariables>,
2353 exclude_newer: Option<ExcludeNewerOverride>,
2354 exclude_newer_span: Option<ExcludeNewerSpan>,
2355 #[serde(serialize_with = "serialize_exclude_newer_package_with_spans")]
2356 exclude_newer_package: Option<ExcludeNewerPackage>,
2357 link_mode: Option<LinkMode>,
2358 compile_bytecode: Option<bool>,
2359 no_sources: Option<bool>,
2360 no_sources_package: Option<Vec<PackageName>>,
2361 no_build: Option<bool>,
2362 no_build_package: Option<Vec<PackageName>>,
2363 no_binary: Option<bool>,
2364 no_binary_package: Option<Vec<PackageName>>,
2365 torch_backend: Option<TorchMode>,
2366}
2367
2368impl From<ResolverInstallerOptions> for ToolOptions {
2369 fn from(value: ResolverInstallerOptions) -> Self {
2370 Self {
2371 index: value.indexes.index.map(|indexes| {
2372 indexes
2373 .into_iter()
2374 .map(Index::with_promoted_auth_policy)
2375 .collect()
2376 }),
2377 index_url: value.indexes.index_url,
2378 extra_index_url: value.indexes.extra_index_url,
2379 no_index: value.indexes.no_index,
2380 find_links: value.indexes.find_links,
2381 index_strategy: value.index_strategy,
2382 keyring_provider: value.keyring_provider,
2383 resolution: value.resolution,
2384 prerelease: value.prerelease,
2385 prerelease_package: value.prerelease_package,
2386 fork_strategy: value.fork_strategy,
2387 dependency_metadata: value.dependency_metadata,
2388 config_settings: value.config_settings,
2389 config_settings_package: value.config_settings_package,
2390 build_isolation: value.build_isolation,
2391 extra_build_dependencies: value.extra_build_dependencies,
2392 extra_build_variables: value.extra_build_variables,
2393 exclude_newer: value.exclude_newer,
2394 exclude_newer_package: value.exclude_newer_package,
2395 link_mode: value.link_mode,
2396 compile_bytecode: value.compile_bytecode,
2397 no_sources: value.no_sources,
2398 no_sources_package: value.no_sources_package,
2399 no_build: value.no_build,
2400 no_build_package: value.no_build_package,
2401 no_binary: value.no_binary,
2402 no_binary_package: value.no_binary_package,
2403 torch_backend: value.torch_backend,
2404 }
2405 }
2406}
2407
2408impl From<ToolOptionsWire> for ToolOptions {
2409 fn from(value: ToolOptionsWire) -> Self {
2410 let exclude_newer = value
2411 .exclude_newer
2412 .map(|exclude_newer| match exclude_newer {
2413 ExcludeNewerOverride::Disabled => ExcludeNewerOverride::Disabled,
2414 ExcludeNewerOverride::Enabled(exclude_newer) => {
2415 let exclude_newer = *exclude_newer;
2416 if let Some(span) = value.exclude_newer_span
2417 && exclude_newer.span().is_none()
2418 {
2419 ExcludeNewerValue::relative(span).into()
2420 } else {
2421 exclude_newer.into()
2422 }
2423 }
2424 });
2425
2426 Self {
2427 index: value.index,
2428 index_url: value.index_url,
2429 extra_index_url: value.extra_index_url,
2430 no_index: value.no_index,
2431 find_links: value.find_links,
2432 index_strategy: value.index_strategy,
2433 keyring_provider: value.keyring_provider,
2434 resolution: value.resolution,
2435 prerelease: value.prerelease,
2436 prerelease_package: value.prerelease_package,
2437 fork_strategy: value.fork_strategy,
2438 dependency_metadata: value.dependency_metadata,
2439 config_settings: value.config_settings,
2440 config_settings_package: value.config_settings_package,
2441 build_isolation: value.build_isolation,
2442 extra_build_dependencies: value.extra_build_dependencies,
2443 extra_build_variables: value.extra_build_variables,
2444 exclude_newer,
2445 exclude_newer_package: value.exclude_newer_package,
2446 link_mode: value.link_mode,
2447 compile_bytecode: value.compile_bytecode,
2448 no_sources: value.no_sources,
2449 no_sources_package: value.no_sources_package,
2450 no_build: value.no_build,
2451 no_build_package: value.no_build_package,
2452 no_binary: value.no_binary,
2453 no_binary_package: value.no_binary_package,
2454 torch_backend: value.torch_backend,
2455 }
2456 }
2457}
2458
2459impl From<ToolOptions> for ToolOptionsWire {
2460 fn from(value: ToolOptions) -> Self {
2461 let (exclude_newer, exclude_newer_span) = match &value.exclude_newer {
2462 Some(ExcludeNewerOverride::Disabled) => (Some(ExcludeNewerOverride::Disabled), None),
2463 Some(ExcludeNewerOverride::Enabled(value)) => match value.as_ref() {
2464 ExcludeNewerValue::Absolute(_) => {
2465 (Some(ExcludeNewerOverride::Enabled(value.clone())), None)
2466 }
2467 ExcludeNewerValue::Relative(span) => (
2468 Some(ExcludeNewerValue::absolute(value.timestamp()).into()),
2469 Some(*span),
2470 ),
2471 },
2472 None => (None, None),
2473 };
2474
2475 Self {
2476 index: value.index,
2477 index_url: value.index_url,
2478 extra_index_url: value.extra_index_url,
2479 no_index: value.no_index,
2480 find_links: value.find_links,
2481 index_strategy: value.index_strategy,
2482 keyring_provider: value.keyring_provider,
2483 resolution: value.resolution,
2484 prerelease: value.prerelease,
2485 prerelease_package: value.prerelease_package,
2486 fork_strategy: value.fork_strategy,
2487 dependency_metadata: value.dependency_metadata,
2488 config_settings: value.config_settings,
2489 config_settings_package: value.config_settings_package,
2490 build_isolation: value.build_isolation,
2491 extra_build_dependencies: value.extra_build_dependencies,
2492 extra_build_variables: value.extra_build_variables,
2493 exclude_newer,
2494 exclude_newer_span,
2495 exclude_newer_package: value.exclude_newer_package,
2496 link_mode: value.link_mode,
2497 compile_bytecode: value.compile_bytecode,
2498 no_sources: value.no_sources,
2499 no_sources_package: value.no_sources_package,
2500 no_build: value.no_build,
2501 no_build_package: value.no_build_package,
2502 no_binary: value.no_binary,
2503 no_binary_package: value.no_binary_package,
2504 torch_backend: value.torch_backend,
2505 }
2506 }
2507}
2508
2509impl From<ToolOptions> for ResolverInstallerOptions {
2510 fn from(value: ToolOptions) -> Self {
2511 Self {
2512 indexes: IndexOptions {
2513 index: value.index,
2514 index_url: value.index_url,
2515 extra_index_url: value.extra_index_url,
2516 no_index: value.no_index,
2517 find_links: value.find_links,
2518 },
2519 index_strategy: value.index_strategy,
2520 keyring_provider: value.keyring_provider,
2521 resolution: value.resolution,
2522 prerelease: value.prerelease,
2523 prerelease_package: value.prerelease_package,
2524 fork_strategy: value.fork_strategy,
2525 dependency_metadata: value.dependency_metadata,
2526 config_settings: value.config_settings,
2527 config_settings_package: value.config_settings_package,
2528 build_isolation: value.build_isolation,
2529 extra_build_dependencies: value.extra_build_dependencies,
2530 extra_build_variables: value.extra_build_variables,
2531 exclude_newer: value.exclude_newer,
2532 exclude_newer_package: value.exclude_newer_package,
2533 link_mode: value.link_mode,
2534 compile_bytecode: value.compile_bytecode,
2535 no_sources: value.no_sources,
2536 no_sources_package: value.no_sources_package,
2537 upgrade: None,
2538 reinstall: None,
2539 no_build: value.no_build,
2540 no_build_package: value.no_build_package,
2541 no_binary: value.no_binary,
2542 no_binary_package: value.no_binary_package,
2543 torch_backend: value.torch_backend,
2544 }
2545 }
2546}
2547
2548#[derive(Debug, Clone, Default, Deserialize)]
2551#[serde(rename_all = "kebab-case", deny_unknown_fields)]
2552struct OptionsWire {
2553 required_version: Option<RequiredVersion>,
2556 system_certs: Option<bool>,
2557 native_tls: Option<bool>,
2558 offline: Option<bool>,
2559 no_cache: Option<bool>,
2560 cache_dir: Option<PathBuf>,
2561 preview: Option<bool>,
2562 preview_features: Option<PreviewFeaturesOption>,
2563 python_preference: Option<PythonPreference>,
2564 python_downloads: Option<PythonDownloads>,
2565 concurrent_downloads: Option<NonZeroUsize>,
2566 concurrent_builds: Option<NonZeroUsize>,
2567 concurrent_installs: Option<NonZeroUsize>,
2568
2569 index: Option<Vec<Index>>,
2572 index_url: Option<PipIndex>,
2573 extra_index_url: Option<Vec<PipExtraIndex>>,
2574 no_index: Option<bool>,
2575 find_links: Option<Vec<PipFindLinks>>,
2576 index_strategy: Option<IndexStrategy>,
2577 keyring_provider: Option<KeyringProviderType>,
2578 http_proxy: Option<ProxyUrl>,
2579 https_proxy: Option<ProxyUrl>,
2580 no_proxy: Option<Vec<String>>,
2581 allow_insecure_host: Option<Vec<TrustedHost>>,
2582 resolution: Option<ResolutionMode>,
2583 prerelease: Option<PrereleaseMode>,
2584 prerelease_package: Option<PrereleasePackage>,
2585 fork_strategy: Option<ForkStrategy>,
2586 dependency_metadata: Option<Vec<StaticMetadata>>,
2587 config_settings: Option<ConfigSettings>,
2588 config_settings_package: Option<PackageConfigSettings>,
2589 no_build_isolation: Option<bool>,
2590 no_build_isolation_package: Option<Vec<PackageName>>,
2591 extra_build_dependencies: Option<ExtraBuildDependencies>,
2592 extra_build_variables: Option<ExtraBuildVariables>,
2593 exclude_newer: Option<ExcludeNewerOverride>,
2594 exclude_newer_package: Option<ExcludeNewerPackage>,
2595 link_mode: Option<LinkMode>,
2596 compile_bytecode: Option<bool>,
2597 no_sources: Option<bool>,
2598 no_sources_package: Option<Vec<PackageName>>,
2599 upgrade: Option<bool>,
2600 upgrade_package: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2601 reinstall: Option<bool>,
2602 reinstall_package: Option<Vec<PackageName>>,
2603 no_build: Option<bool>,
2604 no_build_package: Option<Vec<PackageName>>,
2605 no_binary: Option<bool>,
2606 no_binary_package: Option<Vec<PackageName>>,
2607 torch_backend: Option<TorchMode>,
2608
2609 python_install_mirror: Option<String>,
2612 pypy_install_mirror: Option<String>,
2613 python_downloads_json_url: Option<String>,
2614
2615 publish_url: Option<DisplaySafeUrl>,
2618 trusted_publishing: Option<TrustedPublishing>,
2619 check_url: Option<IndexUrl>,
2620
2621 add_bounds: Option<AddBoundsKind>,
2624
2625 audit: Option<AuditOptions>,
2626 pip: Option<PipOptions>,
2627 cache_keys: Option<Vec<CacheKey>>,
2628
2629 override_dependencies: Option<Vec<OverrideDependency>>,
2633 exclude_dependencies: Option<Vec<ExcludeDependency>>,
2634 constraint_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2635 build_constraint_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2636 environments: Option<SupportedEnvironments>,
2637 required_environments: Option<SupportedEnvironments>,
2638
2639 conflicts: Option<serde::de::IgnoredAny>,
2643 workspace: Option<serde::de::IgnoredAny>,
2644 sources: Option<serde::de::IgnoredAny>,
2645 managed: Option<serde::de::IgnoredAny>,
2646 r#package: Option<serde::de::IgnoredAny>,
2647 default_groups: Option<serde::de::IgnoredAny>,
2648 dependency_groups: Option<serde::de::IgnoredAny>,
2649 dev_dependencies: Option<serde::de::IgnoredAny>,
2650
2651 build_backend: Option<serde::de::IgnoredAny>,
2653}
2654
2655impl TryFrom<OptionsWire> for Options {
2656 type Error = &'static str;
2657
2658 #[allow(deprecated)]
2659 fn try_from(value: OptionsWire) -> Result<Self, Self::Error> {
2660 let OptionsWire {
2661 required_version,
2662 system_certs,
2663 native_tls,
2664 offline,
2665 no_cache,
2666 cache_dir,
2667 preview,
2668 preview_features,
2669 python_preference,
2670 python_downloads,
2671 python_install_mirror,
2672 pypy_install_mirror,
2673 python_downloads_json_url,
2674 concurrent_downloads,
2675 concurrent_builds,
2676 concurrent_installs,
2677 index,
2678 index_url,
2679 extra_index_url,
2680 no_index,
2681 find_links,
2682 index_strategy,
2683 keyring_provider,
2684 http_proxy,
2685 https_proxy,
2686 no_proxy,
2687 allow_insecure_host,
2688 resolution,
2689 prerelease,
2690 prerelease_package,
2691 fork_strategy,
2692 dependency_metadata,
2693 config_settings,
2694 config_settings_package,
2695 no_build_isolation,
2696 no_build_isolation_package,
2697 exclude_newer,
2698 exclude_newer_package,
2699 link_mode,
2700 compile_bytecode,
2701 no_sources,
2702 no_sources_package,
2703 upgrade,
2704 upgrade_package,
2705 reinstall,
2706 reinstall_package,
2707 no_build,
2708 no_build_package,
2709 no_binary,
2710 no_binary_package,
2711 torch_backend,
2712 audit,
2713 pip,
2714 cache_keys,
2715 override_dependencies,
2716 exclude_dependencies,
2717 constraint_dependencies,
2718 build_constraint_dependencies,
2719 environments,
2720 required_environments,
2721 conflicts,
2722 publish_url,
2723 trusted_publishing,
2724 check_url,
2725 workspace,
2726 sources,
2727 default_groups,
2728 dependency_groups,
2729 extra_build_dependencies,
2730 extra_build_variables,
2731 dev_dependencies,
2732 managed,
2733 package,
2734 add_bounds: bounds,
2735 build_backend,
2737 } = value;
2738
2739 Ok(Self {
2740 globals: GlobalOptions {
2741 required_version,
2742 system_certs,
2743 native_tls,
2744 offline,
2745 no_cache,
2746 cache_dir,
2747 preview: PreviewOption::try_from(preview, preview_features)?,
2748 python_preference,
2749 python_downloads,
2750 concurrent_downloads,
2751 concurrent_builds,
2752 concurrent_installs,
2753 http_proxy,
2754 https_proxy,
2755 no_proxy,
2756 allow_insecure_host: allow_insecure_host.clone(),
2758 },
2759 top_level: ResolverInstallerSchema {
2760 index,
2761 index_url,
2762 extra_index_url,
2763 no_index,
2764 find_links,
2765 index_strategy,
2766 keyring_provider,
2767 resolution,
2768 prerelease,
2769 prerelease_package,
2770 fork_strategy,
2771 dependency_metadata,
2772 config_settings,
2773 config_settings_package,
2774 no_build_isolation,
2775 no_build_isolation_package,
2776 extra_build_dependencies,
2777 extra_build_variables,
2778 exclude_newer,
2779 exclude_newer_package,
2780 link_mode,
2781 compile_bytecode,
2782 no_sources,
2783 no_sources_package,
2784 upgrade,
2785 upgrade_package,
2786 reinstall,
2787 reinstall_package,
2788 no_build,
2789 no_build_package,
2790 no_binary,
2791 no_binary_package,
2792 torch_backend,
2793 },
2794 pip,
2795 cache_keys,
2796 build_backend,
2797 override_dependencies,
2798 exclude_dependencies,
2799 constraint_dependencies,
2800 build_constraint_dependencies,
2801 environments,
2802 required_environments,
2803 install_mirrors: PythonInstallMirrors {
2804 python_install_mirror,
2805 pypy_install_mirror,
2806 python_downloads_json_url,
2807 },
2808 conflicts,
2809 publish: PublishOptions {
2810 publish_url,
2811 trusted_publishing,
2812 check_url,
2813 },
2814 add: AddOptions { add_bounds: bounds },
2815 audit,
2816 workspace,
2817 sources,
2818 dev_dependencies,
2819 default_groups,
2820 dependency_groups,
2821 managed,
2822 package,
2823 })
2824 }
2825}
2826
2827#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
2828#[serde(rename_all = "kebab-case")]
2829#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2830pub struct PublishOptions {
2831 #[option(
2834 default = "\"https://upload.pypi.org/legacy/\"",
2835 value_type = "str",
2836 example = r#"
2837 publish-url = "https://test.pypi.org/legacy/"
2838 "#
2839 )]
2840 pub publish_url: Option<DisplaySafeUrl>,
2841
2842 #[option(
2849 default = "automatic",
2850 value_type = "str",
2851 example = r#"
2852 trusted-publishing = "always"
2853 "#
2854 )]
2855 pub trusted_publishing: Option<TrustedPublishing>,
2856
2857 #[option(
2871 default = "None",
2872 value_type = "str",
2873 example = r#"
2874 check-url = "https://test.pypi.org/simple"
2875 "#
2876 )]
2877 pub check_url: Option<IndexUrl>,
2878}
2879
2880#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
2881#[serde(rename_all = "kebab-case")]
2882#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2883pub struct AddOptions {
2884 #[option(
2895 default = "\"lower\"",
2896 value_type = "str",
2897 example = r#"
2898 add-bounds = "major"
2899 "#,
2900 possible_values = true
2901 )]
2902 pub add_bounds: Option<AddBoundsKind>,
2903}
2904
2905#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
2906#[serde(rename_all = "kebab-case")]
2907#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2908pub struct AuditOptions {
2909 #[option(
2911 default = "false",
2912 value_type = "bool",
2913 example = r#"
2914 malware-check = true
2915 "#
2916 )]
2917 pub malware_check: Option<bool>,
2918
2919 #[option(
2921 default = "\"https://api.osv.dev/\"",
2922 value_type = "str",
2923 example = r#"
2924 malware-check-url = "https://example.com"
2925 "#
2926 )]
2927 pub malware_check_url: Option<DisplaySafeUrl>,
2928
2929 #[option(
2934 default = "[]",
2935 value_type = "list[str]",
2936 example = r#"
2937 ignore = ["PYSEC-2022-43017", "GHSA-5239-wwwm-4pmq"]
2938 "#
2939 )]
2940 pub ignore: Option<Vec<String>>,
2941
2942 #[option(
2948 default = "[]",
2949 value_type = "list[str]",
2950 example = r#"
2951 ignore-until-fixed = ["PYSEC-2022-43017"]
2952 "#
2953 )]
2954 pub ignore_until_fixed: Option<Vec<String>>,
2955}
2956
2957#[derive(Debug, Clone)]
2958pub struct MalwareCheckSettings {
2959 pub enabled: bool,
2961 pub malware_check_url: Option<DisplaySafeUrl>,
2963}
2964
2965impl MalwareCheckSettings {
2966 pub fn resolve(
2967 filesystem: Option<&FilesystemOptions>,
2968 environment: &EnvironmentOptions,
2969 ) -> Self {
2970 let audit = filesystem.and_then(|options| options.audit.as_ref());
2971
2972 Self {
2973 enabled: environment
2974 .malware_check
2975 .value
2976 .or(audit.and_then(|audit| audit.malware_check))
2977 .unwrap_or_default(),
2978 malware_check_url: environment
2979 .malware_check_url
2980 .clone()
2981 .or_else(|| audit.and_then(|audit| audit.malware_check_url.clone())),
2982 }
2983 }
2984}
2985
2986#[derive(Debug, Clone)]
2988#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2989#[cfg_attr(feature = "schemars", schemars(untagged))]
2990pub enum PreviewFeaturesOption {
2991 Toggle(bool),
2992 Features(Vec<MaybePreviewFeature>),
2993}
2994
2995impl<'de> Deserialize<'de> for PreviewFeaturesOption {
2998 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2999 where
3000 D: serde::Deserializer<'de>,
3001 {
3002 serde_untagged::UntaggedEnumVisitor::new()
3003 .expecting("a boolean or a list of preview feature names")
3004 .bool(|value| Ok(Self::Toggle(value)))
3005 .seq(|sequence| sequence.deserialize().map(Self::Features))
3006 .deserialize(deserializer)
3007 }
3008}
3009
3010#[expect(
3011 dead_code,
3012 reason = "Fields are only used by the OptionsMetadata and JsonSchema derives"
3013)]
3014#[derive(OptionsMetadata)]
3015#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3016#[cfg_attr(feature = "schemars", schemars(rename_all = "kebab-case"))]
3017struct PreviewOptionsDefinition {
3018 #[deprecated(note = "use `preview-features` instead")]
3024 preview: Option<bool>,
3025 #[option(
3029 default = "false",
3030 value_type = "bool | list[str]",
3031 example = r#"
3032 preview-features = true
3033 # or
3034 preview-features = ["json-output"]
3035 "#
3036 )]
3037 preview_features: Option<PreviewFeaturesOption>,
3038}
3039
3040#[derive(Debug, Clone)]
3042pub enum PreviewOption {
3043 Preview(bool),
3045 PreviewFeatures(PreviewFeaturesOption),
3047}
3048
3049impl uv_options_metadata::OptionsMetadata for PreviewOption {
3050 fn record(visit: &mut dyn uv_options_metadata::Visit) {
3051 <PreviewOptionsDefinition as uv_options_metadata::OptionsMetadata>::record(visit);
3052 }
3053}
3054
3055#[cfg(feature = "schemars")]
3056struct ConflictingPreviewOptions;
3057
3058#[cfg(feature = "schemars")]
3059impl schemars::JsonSchema for ConflictingPreviewOptions {
3060 fn schema_name() -> Cow<'static, str> {
3061 Cow::Borrowed("ConflictingPreviewOptions")
3062 }
3063
3064 fn json_schema(_generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
3065 schemars::json_schema!({
3066 "type": "object",
3067 "properties": {
3068 "preview": {},
3069 "preview-features": {},
3070 },
3071 "required": ["preview", "preview-features"],
3072 })
3073 }
3074}
3075
3076#[cfg(feature = "schemars")]
3077impl schemars::JsonSchema for PreviewOption {
3078 fn schema_name() -> Cow<'static, str> {
3079 Cow::Borrowed("PreviewOption")
3080 }
3081
3082 fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
3083 let mut schema = <PreviewOptionsDefinition as schemars::JsonSchema>::json_schema(generator);
3084 schema.insert(
3087 "not".to_string(),
3088 generator
3089 .subschema_for::<ConflictingPreviewOptions>()
3090 .into(),
3091 );
3092 schema
3093 }
3094}
3095
3096impl PreviewOption {
3097 fn try_from(
3098 preview: Option<bool>,
3099 preview_features: Option<PreviewFeaturesOption>,
3100 ) -> Result<Option<Self>, &'static str> {
3101 match (preview, preview_features) {
3102 (Some(_), Some(_)) => Err("cannot specify both `preview` and `preview-features`"),
3103 (Some(b), None) => Ok(Some(Self::Preview(b))),
3104 (None, Some(features)) => Ok(Some(Self::PreviewFeatures(features))),
3105 (None, None) => Ok(None),
3106 }
3107 }
3108
3109 pub fn resolve(&self) -> Preview {
3111 use PreviewFeaturesOption::{Features, Toggle};
3112
3113 match self {
3114 Self::Preview(false) | Self::PreviewFeatures(Toggle(false)) => Preview::default(),
3115 Self::Preview(true) | Self::PreviewFeatures(Toggle(true)) => Preview::all(),
3116 Self::PreviewFeatures(Features(features)) => Preview::from_feature_names(features),
3117 }
3118 }
3119}