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(
1257 default = "false",
1258 value_type = "bool",
1259 example = r#"
1260 no-build = true
1261 "#
1262 )]
1263 pub no_build: Option<bool>,
1264 #[option(
1268 default = "[]",
1269 value_type = "list[str]",
1270 example = r#"
1271 no-build-package = ["ruff"]
1272 "#
1273 )]
1274 pub no_build_package: Option<Vec<PackageName>>,
1275 #[option(
1280 default = "false",
1281 value_type = "bool",
1282 example = r#"
1283 no-binary = true
1284 "#
1285 )]
1286 pub no_binary: Option<bool>,
1287 #[option(
1289 default = "[]",
1290 value_type = "list[str]",
1291 example = r#"
1292 no-binary-package = ["ruff"]
1293 "#
1294 )]
1295 pub no_binary_package: Option<Vec<PackageName>>,
1296 #[option(
1311 default = "null",
1312 value_type = "str",
1313 example = r#"
1314 torch-backend = "auto"
1315 "#
1316 )]
1317 pub torch_backend: Option<TorchMode>,
1318}
1319
1320#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
1322#[serde(rename_all = "kebab-case")]
1323#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1324pub struct PythonInstallMirrors {
1325 #[option(
1333 default = "None",
1334 value_type = "str",
1335 uv_toml_only = true,
1336 example = r#"
1337 python-install-mirror = "https://github.com/astral-sh/python-build-standalone/releases/download"
1338 "#
1339 )]
1340 pub python_install_mirror: Option<String>,
1341 #[option(
1350 default = "None",
1351 value_type = "str",
1352 uv_toml_only = true,
1353 example = r#"
1354 pypy-install-mirror = "https://downloads.python.org/pypy"
1355 "#
1356 )]
1357 pub pypy_install_mirror: Option<String>,
1358
1359 #[option(
1361 default = "None",
1362 value_type = "str",
1363 uv_toml_only = true,
1364 example = r#"
1365 python-downloads-json-url = "/etc/uv/python-downloads.json"
1366 "#
1367 )]
1368 pub python_downloads_json_url: Option<String>,
1369}
1370
1371impl PythonInstallMirrors {
1372 #[must_use]
1373 pub fn combine(self, other: Self) -> Self {
1374 Self {
1375 python_install_mirror: self.python_install_mirror.or(other.python_install_mirror),
1376 pypy_install_mirror: self.pypy_install_mirror.or(other.pypy_install_mirror),
1377 python_downloads_json_url: self
1378 .python_downloads_json_url
1379 .or(other.python_downloads_json_url),
1380 }
1381 }
1382}
1383
1384#[derive(Debug, Clone, Default, Deserialize, CombineOptions, OptionsMetadata)]
1389#[serde(deny_unknown_fields, rename_all = "kebab-case")]
1390#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1391pub struct PipOptions {
1392 #[option(
1405 default = "None",
1406 value_type = "str",
1407 example = r#"
1408 python = "3.10"
1409 "#
1410 )]
1411 pub python: Option<String>,
1412 #[option(
1421 default = "false",
1422 value_type = "bool",
1423 example = r#"
1424 system = true
1425 "#
1426 )]
1427 pub system: Option<bool>,
1428 #[option(
1435 default = "false",
1436 value_type = "bool",
1437 example = r#"
1438 break-system-packages = true
1439 "#
1440 )]
1441 pub break_system_packages: Option<bool>,
1442 #[option(
1445 default = "None",
1446 value_type = "str",
1447 example = r#"
1448 target = "./target"
1449 "#
1450 )]
1451 pub target: Option<PathBuf>,
1452 #[option(
1460 default = "None",
1461 value_type = "str",
1462 example = r#"
1463 prefix = "./prefix"
1464 "#
1465 )]
1466 pub prefix: Option<PathBuf>,
1467 #[serde(skip)]
1468 #[cfg_attr(feature = "schemars", schemars(skip))]
1469 pub index: Option<Vec<Index>>,
1470 #[option(
1478 default = "\"https://pypi.org/simple\"",
1479 value_type = "str",
1480 example = r#"
1481 index-url = "https://test.pypi.org/simple"
1482 "#
1483 )]
1484 pub index_url: Option<PipIndex>,
1485 #[option(
1496 default = "[]",
1497 value_type = "list[str]",
1498 example = r#"
1499 extra-index-url = ["https://download.pytorch.org/whl/cpu"]
1500 "#
1501 )]
1502 pub extra_index_url: Option<Vec<PipExtraIndex>>,
1503 #[option(
1506 default = "false",
1507 value_type = "bool",
1508 example = r#"
1509 no-index = true
1510 "#
1511 )]
1512 pub no_index: Option<bool>,
1513 #[option(
1522 default = "[]",
1523 value_type = "list[str]",
1524 example = r#"
1525 find-links = ["https://download.pytorch.org/whl/torch_stable.html"]
1526 "#
1527 )]
1528 pub find_links: Option<Vec<PipFindLinks>>,
1529 #[option(
1536 default = "\"first-index\"",
1537 value_type = "str",
1538 example = r#"
1539 index-strategy = "unsafe-best-match"
1540 "#,
1541 possible_values = true
1542 )]
1543 pub index_strategy: Option<IndexStrategy>,
1544 #[option(
1549 default = "disabled",
1550 value_type = "str",
1551 example = r#"
1552 keyring-provider = "subprocess"
1553 "#
1554 )]
1555 pub keyring_provider: Option<KeyringProviderType>,
1556 #[option(
1564 default = "false",
1565 value_type = "bool",
1566 example = r#"
1567 no-build = true
1568 "#
1569 )]
1570 pub no_build: Option<bool>,
1571 #[option(
1579 default = "[]",
1580 value_type = "list[str]",
1581 example = r#"
1582 no-binary = ["ruff"]
1583 "#
1584 )]
1585 pub no_binary: Option<Vec<PackageNameSpecifier>>,
1586 #[option(
1596 default = "[]",
1597 value_type = "list[str]",
1598 example = r#"
1599 only-binary = ["ruff"]
1600 "#
1601 )]
1602 pub only_binary: Option<Vec<PackageNameSpecifier>>,
1603 #[option(
1608 default = "false",
1609 value_type = "bool",
1610 example = r#"
1611 no-build-isolation = true
1612 "#
1613 )]
1614 pub no_build_isolation: Option<bool>,
1615 #[option(
1620 default = "[]",
1621 value_type = "list[str]",
1622 example = r#"
1623 no-build-isolation-package = ["package1", "package2"]
1624 "#
1625 )]
1626 pub no_build_isolation_package: Option<Vec<PackageName>>,
1627 #[option(
1633 default = "[]",
1634 value_type = "dict",
1635 example = r#"
1636 extra-build-dependencies = { pytest = ["setuptools"] }
1637 "#
1638 )]
1639 pub extra_build_dependencies: Option<ExtraBuildDependencies>,
1640 #[option(
1645 default = r#"{}"#,
1646 value_type = r#"dict[str, dict[str, str]]"#,
1647 example = r#"
1648 extra-build-variables = { flash-attn = { FLASH_ATTENTION_SKIP_CUDA_BUILD = "TRUE" } }
1649 "#
1650 )]
1651 pub extra_build_variables: Option<ExtraBuildVariables>,
1652 #[option(
1655 default = "false",
1656 value_type = "bool",
1657 example = r#"
1658 strict = true
1659 "#
1660 )]
1661 pub strict: Option<bool>,
1662 #[option(
1666 default = "[]",
1667 value_type = "list[str]",
1668 example = r#"
1669 extra = ["dev", "docs"]
1670 "#
1671 )]
1672 pub extra: Option<Vec<ExtraName>>,
1673 #[option(
1677 default = "false",
1678 value_type = "bool",
1679 example = r#"
1680 all-extras = true
1681 "#
1682 )]
1683 pub all_extras: Option<bool>,
1684 #[option(
1686 default = "[]",
1687 value_type = "list[str]",
1688 example = r#"
1689 all-extras = true
1690 no-extra = ["dev", "docs"]
1691 "#
1692 )]
1693 pub no_extra: Option<Vec<ExtraName>>,
1694 #[option(
1697 default = "false",
1698 value_type = "bool",
1699 example = r#"
1700 no-deps = true
1701 "#
1702 )]
1703 pub no_deps: Option<bool>,
1704 #[option(
1706 default = "None",
1707 value_type = "list[str]",
1708 example = r#"
1709 group = ["dev", "docs"]
1710 "#
1711 )]
1712 pub group: Option<Vec<PipGroupName>>,
1713 #[option(
1716 default = "false",
1717 value_type = "bool",
1718 example = r#"
1719 allow-empty-requirements = true
1720 "#
1721 )]
1722 pub allow_empty_requirements: Option<bool>,
1723 #[option(
1728 default = "\"highest\"",
1729 value_type = "str",
1730 example = r#"
1731 resolution = "lowest-direct"
1732 "#,
1733 possible_values = true
1734 )]
1735 pub resolution: Option<ResolutionMode>,
1736 #[option(
1742 default = "\"if-necessary\"",
1743 value_type = "str",
1744 example = r#"
1745 prerelease = "allow"
1746 "#,
1747 possible_values = true
1748 )]
1749 pub prerelease: Option<PrereleaseMode>,
1750 #[serde(skip)]
1751 #[cfg_attr(feature = "schemars", schemars(skip))]
1752 pub prerelease_package: Option<PrereleasePackage>,
1753 #[option(
1764 default = "\"requires-python\"",
1765 value_type = "str",
1766 example = r#"
1767 fork-strategy = "fewest"
1768 "#,
1769 possible_values = true
1770 )]
1771 pub fork_strategy: Option<ForkStrategy>,
1772 #[option(
1786 default = r#"[]"#,
1787 value_type = "list[dict]",
1788 example = r#"
1789 dependency-metadata = [
1790 { name = "flask", version = "1.0.0", requires-dist = ["werkzeug"], requires-python = ">=3.6" },
1791 ]
1792 "#
1793 )]
1794 pub dependency_metadata: Option<Vec<StaticMetadata>>,
1795 #[option(
1800 default = "None",
1801 value_type = "str",
1802 example = r#"
1803 output-file = "requirements.txt"
1804 "#
1805 )]
1806 pub output_file: Option<PathBuf>,
1807 #[option(
1813 default = "false",
1814 value_type = "bool",
1815 example = r#"
1816 no-strip-extras = true
1817 "#
1818 )]
1819 pub no_strip_extras: Option<bool>,
1820 #[option(
1825 default = "false",
1826 value_type = "bool",
1827 example = r#"
1828 no-strip-markers = true
1829 "#
1830 )]
1831 pub no_strip_markers: Option<bool>,
1832 #[option(
1835 default = "false",
1836 value_type = "bool",
1837 example = r#"
1838 no-annotate = true
1839 "#
1840 )]
1841 pub no_annotate: Option<bool>,
1842 #[option(
1844 default = r#"false"#,
1845 value_type = "bool",
1846 example = r#"
1847 no-header = true
1848 "#
1849 )]
1850 pub no_header: Option<bool>,
1851 #[option(
1855 default = "None",
1856 value_type = "str",
1857 example = r#"
1858 custom-compile-command = "./custom-uv-compile.sh"
1859 "#
1860 )]
1861 pub custom_compile_command: Option<String>,
1862 #[option(
1864 default = "false",
1865 value_type = "bool",
1866 example = r#"
1867 generate-hashes = true
1868 "#
1869 )]
1870 pub generate_hashes: Option<bool>,
1871 #[option(
1874 default = "{}",
1875 value_type = "dict",
1876 example = r#"
1877 config-settings = { editable_mode = "compat" }
1878 "#
1879 )]
1880 pub config_settings: Option<ConfigSettings>,
1881 #[option(
1884 default = "{}",
1885 value_type = "dict",
1886 example = r#"
1887 config-settings-package = { numpy = { editable_mode = "compat" } }
1888 "#
1889 )]
1890 pub config_settings_package: Option<PackageConfigSettings>,
1891 #[option(
1897 default = "None",
1898 value_type = "str",
1899 example = r#"
1900 python-version = "3.8"
1901 "#
1902 )]
1903 pub python_version: Option<PythonVersion>,
1904 #[option(
1910 default = "None",
1911 value_type = "str",
1912 example = r#"
1913 python-platform = "x86_64-unknown-linux-gnu"
1914 "#
1915 )]
1916 pub python_platform: Option<TargetTriple>,
1917 #[option(
1925 default = "false",
1926 value_type = "bool",
1927 example = r#"
1928 universal = true
1929 "#
1930 )]
1931 pub universal: Option<bool>,
1932 #[option(
1947 default = "None",
1948 value_type = "str | false",
1949 example = r#"
1950 exclude-newer = "2006-12-02T02:07:43Z"
1951 "#
1952 )]
1953 pub exclude_newer: Option<ExcludeNewerOverride>,
1954 #[option(
1967 default = "None",
1968 value_type = "dict",
1969 example = r#"
1970 exclude-newer-package = { tqdm = "2022-04-04T00:00:00Z", markupsafe = false }
1971 "#
1972 )]
1973 pub exclude_newer_package: Option<ExcludeNewerPackage>,
1974 #[option(
1977 default = "[]",
1978 value_type = "list[str]",
1979 example = r#"
1980 no-emit-package = ["ruff"]
1981 "#
1982 )]
1983 pub no_emit_package: Option<Vec<PackageName>>,
1984 #[option(
1986 default = "false",
1987 value_type = "bool",
1988 example = r#"
1989 emit-index-url = true
1990 "#
1991 )]
1992 pub emit_index_url: Option<bool>,
1993 #[option(
1995 default = "false",
1996 value_type = "bool",
1997 example = r#"
1998 emit-find-links = true
1999 "#
2000 )]
2001 pub emit_find_links: Option<bool>,
2002 #[option(
2004 default = "false",
2005 value_type = "bool",
2006 example = r#"
2007 emit-build-options = true
2008 "#
2009 )]
2010 pub emit_build_options: Option<bool>,
2011 #[option(
2018 default = "false",
2019 value_type = "bool",
2020 example = r#"
2021 emit-marker-expression = true
2022 "#
2023 )]
2024 pub emit_marker_expression: Option<bool>,
2025 #[option(
2028 default = "false",
2029 value_type = "bool",
2030 example = r#"
2031 emit-index-annotation = true
2032 "#
2033 )]
2034 pub emit_index_annotation: Option<bool>,
2035 #[option(
2038 default = "\"split\"",
2039 value_type = "str",
2040 example = r#"
2041 annotation-style = "line"
2042 "#,
2043 possible_values = true
2044 )]
2045 pub annotation_style: Option<AnnotationStyle>,
2046 #[option(
2056 default = "\"clone\" (macOS, Linux) or \"hardlink\" (Windows)",
2057 value_type = "str",
2058 example = r#"
2059 link-mode = "copy"
2060 "#,
2061 possible_values = true
2062 )]
2063 pub link_mode: Option<LinkMode>,
2064 #[option(
2075 default = "false",
2076 value_type = "bool",
2077 example = r#"
2078 compile-bytecode = true
2079 "#
2080 )]
2081 pub compile_bytecode: Option<bool>,
2082 #[option(
2095 default = "false",
2096 value_type = "bool",
2097 example = r#"
2098 require-hashes = true
2099 "#
2100 )]
2101 pub require_hashes: Option<bool>,
2102 #[option(
2108 default = "true",
2109 value_type = "bool",
2110 example = r#"
2111 verify-hashes = true
2112 "#
2113 )]
2114 pub verify_hashes: Option<bool>,
2115 #[option(
2119 default = "false",
2120 value_type = "bool",
2121 example = r#"
2122 no-sources = true
2123 "#
2124 )]
2125 pub no_sources: Option<bool>,
2126 #[option(
2128 default = "[]",
2129 value_type = "list[str]",
2130 example = r#"
2131 no-sources-package = ["ruff"]
2132 "#
2133 )]
2134 pub no_sources_package: Option<Vec<PackageName>>,
2135 #[option(
2137 default = "false",
2138 value_type = "bool",
2139 example = r#"
2140 upgrade = true
2141 "#
2142 )]
2143 pub upgrade: Option<bool>,
2144 #[option(
2149 default = "[]",
2150 value_type = "list[str]",
2151 example = r#"
2152 upgrade-package = ["ruff"]
2153 "#
2154 )]
2155 pub upgrade_package: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2156 #[option(
2158 default = "false",
2159 value_type = "bool",
2160 example = r#"
2161 reinstall = true
2162 "#
2163 )]
2164 pub reinstall: Option<bool>,
2165 #[option(
2168 default = "[]",
2169 value_type = "list[str]",
2170 example = r#"
2171 reinstall-package = ["ruff"]
2172 "#
2173 )]
2174 pub reinstall_package: Option<Vec<PackageName>>,
2175 #[option(
2190 default = "null",
2191 value_type = "str",
2192 example = r#"
2193 torch-backend = "auto"
2194 "#
2195 )]
2196 pub torch_backend: Option<TorchMode>,
2197}
2198
2199impl PipOptions {
2200 fn relative_to(mut self, root_dir: &Path) -> Result<Self, IndexUrlError> {
2202 rebase_indexes(
2203 root_dir,
2204 &mut self.index,
2205 &mut self.index_url,
2206 &mut self.extra_index_url,
2207 &mut self.find_links,
2208 )?;
2209
2210 Ok(self)
2211 }
2212}
2213
2214impl From<ResolverInstallerSchema> for ResolverOptions {
2215 fn from(value: ResolverInstallerSchema) -> Self {
2216 Self {
2217 indexes: IndexOptions {
2218 index: value.index,
2219 index_url: value.index_url,
2220 extra_index_url: value.extra_index_url,
2221 no_index: value.no_index,
2222 find_links: value.find_links,
2223 },
2224 index_strategy: value.index_strategy,
2225 keyring_provider: value.keyring_provider,
2226 resolution: value.resolution,
2227 prerelease: value.prerelease,
2228 prerelease_package: value.prerelease_package,
2229 fork_strategy: value.fork_strategy,
2230 dependency_metadata: value.dependency_metadata,
2231 config_settings: value.config_settings,
2232 config_settings_package: value.config_settings_package,
2233 exclude_newer: value.exclude_newer,
2234 exclude_newer_package: value.exclude_newer_package,
2235 link_mode: value.link_mode,
2236 upgrade: Upgrade::from_args(
2237 value.upgrade,
2238 value
2239 .upgrade_package
2240 .into_iter()
2241 .flatten()
2242 .map(Into::into)
2243 .collect(),
2244 Vec::new(),
2245 ),
2246 no_build: value.no_build,
2247 no_build_package: value.no_build_package,
2248 no_binary: value.no_binary,
2249 no_binary_package: value.no_binary_package,
2250 build_isolation: BuildIsolation::from_args(
2251 value.no_build_isolation,
2252 value.no_build_isolation_package.unwrap_or_default(),
2253 ),
2254 extra_build_dependencies: value.extra_build_dependencies,
2255 extra_build_variables: value.extra_build_variables,
2256 no_sources: value.no_sources,
2257 no_sources_package: value.no_sources_package,
2258 torch_backend: value.torch_backend,
2259 }
2260 }
2261}
2262
2263impl From<ResolverInstallerSchema> for InstallerOptions {
2264 fn from(value: ResolverInstallerSchema) -> Self {
2265 Self {
2266 index: value.index,
2267 index_url: value.index_url,
2268 extra_index_url: value.extra_index_url,
2269 no_index: value.no_index,
2270 find_links: value.find_links,
2271 index_strategy: value.index_strategy,
2272 keyring_provider: value.keyring_provider,
2273 config_settings: value.config_settings,
2274 exclude_newer: value.exclude_newer,
2275 link_mode: value.link_mode,
2276 compile_bytecode: value.compile_bytecode,
2277 reinstall: Reinstall::from_args(
2278 value.reinstall,
2279 value.reinstall_package.unwrap_or_default(),
2280 ),
2281 build_isolation: BuildIsolation::from_args(
2282 value.no_build_isolation,
2283 value.no_build_isolation_package.unwrap_or_default(),
2284 ),
2285 no_build: value.no_build,
2286 no_build_package: value.no_build_package,
2287 no_binary: value.no_binary,
2288 no_binary_package: value.no_binary_package,
2289 no_sources: value.no_sources,
2290 no_sources_package: value.no_sources_package,
2291 }
2292 }
2293}
2294
2295#[derive(
2300 Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, CombineOptions, OptionsMetadata,
2301)]
2302#[serde(deny_unknown_fields, rename_all = "kebab-case")]
2303#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2304pub struct ToolOptions {
2305 index: Option<Vec<Index>>,
2306 index_url: Option<PipIndex>,
2307 extra_index_url: Option<Vec<PipExtraIndex>>,
2308 no_index: Option<bool>,
2309 find_links: Option<Vec<PipFindLinks>>,
2310 index_strategy: Option<IndexStrategy>,
2311 keyring_provider: Option<KeyringProviderType>,
2312 resolution: Option<ResolutionMode>,
2313 prerelease: Option<PrereleaseMode>,
2314 prerelease_package: Option<PrereleasePackage>,
2315 fork_strategy: Option<ForkStrategy>,
2316 dependency_metadata: Option<Vec<StaticMetadata>>,
2317 config_settings: Option<ConfigSettings>,
2318 config_settings_package: Option<PackageConfigSettings>,
2319 build_isolation: Option<BuildIsolation>,
2320 extra_build_dependencies: Option<ExtraBuildDependencies>,
2321 extra_build_variables: Option<ExtraBuildVariables>,
2322 exclude_newer: Option<ExcludeNewerOverride>,
2323 exclude_newer_package: Option<ExcludeNewerPackage>,
2324 link_mode: Option<LinkMode>,
2325 compile_bytecode: Option<bool>,
2326 no_sources: Option<bool>,
2327 no_sources_package: Option<Vec<PackageName>>,
2328 no_build: Option<bool>,
2329 no_build_package: Option<Vec<PackageName>>,
2330 no_binary: Option<bool>,
2331 no_binary_package: Option<Vec<PackageName>>,
2332 torch_backend: Option<TorchMode>,
2333}
2334
2335#[derive(Debug, Clone, Default, Serialize, Deserialize)]
2337#[serde(deny_unknown_fields, rename_all = "kebab-case")]
2338pub struct ToolOptionsWire {
2339 index: Option<Vec<Index>>,
2340 index_url: Option<PipIndex>,
2341 extra_index_url: Option<Vec<PipExtraIndex>>,
2342 no_index: Option<bool>,
2343 find_links: Option<Vec<PipFindLinks>>,
2344 index_strategy: Option<IndexStrategy>,
2345 keyring_provider: Option<KeyringProviderType>,
2346 resolution: Option<ResolutionMode>,
2347 prerelease: Option<PrereleaseMode>,
2348 prerelease_package: Option<PrereleasePackage>,
2349 fork_strategy: Option<ForkStrategy>,
2350 dependency_metadata: Option<Vec<StaticMetadata>>,
2351 config_settings: Option<ConfigSettings>,
2352 config_settings_package: Option<PackageConfigSettings>,
2353 build_isolation: Option<BuildIsolation>,
2354 extra_build_dependencies: Option<ExtraBuildDependencies>,
2355 extra_build_variables: Option<ExtraBuildVariables>,
2356 exclude_newer: Option<ExcludeNewerOverride>,
2357 exclude_newer_span: Option<ExcludeNewerSpan>,
2358 #[serde(serialize_with = "serialize_exclude_newer_package_with_spans")]
2359 exclude_newer_package: Option<ExcludeNewerPackage>,
2360 link_mode: Option<LinkMode>,
2361 compile_bytecode: Option<bool>,
2362 no_sources: Option<bool>,
2363 no_sources_package: Option<Vec<PackageName>>,
2364 no_build: Option<bool>,
2365 no_build_package: Option<Vec<PackageName>>,
2366 no_binary: Option<bool>,
2367 no_binary_package: Option<Vec<PackageName>>,
2368 torch_backend: Option<TorchMode>,
2369}
2370
2371impl From<ResolverInstallerOptions> for ToolOptions {
2372 fn from(value: ResolverInstallerOptions) -> Self {
2373 Self {
2374 index: value.indexes.index.map(|indexes| {
2375 indexes
2376 .into_iter()
2377 .map(Index::with_promoted_auth_policy)
2378 .collect()
2379 }),
2380 index_url: value.indexes.index_url,
2381 extra_index_url: value.indexes.extra_index_url,
2382 no_index: value.indexes.no_index,
2383 find_links: value.indexes.find_links,
2384 index_strategy: value.index_strategy,
2385 keyring_provider: value.keyring_provider,
2386 resolution: value.resolution,
2387 prerelease: value.prerelease,
2388 prerelease_package: value.prerelease_package,
2389 fork_strategy: value.fork_strategy,
2390 dependency_metadata: value.dependency_metadata,
2391 config_settings: value.config_settings,
2392 config_settings_package: value.config_settings_package,
2393 build_isolation: value.build_isolation,
2394 extra_build_dependencies: value.extra_build_dependencies,
2395 extra_build_variables: value.extra_build_variables,
2396 exclude_newer: value.exclude_newer,
2397 exclude_newer_package: value.exclude_newer_package,
2398 link_mode: value.link_mode,
2399 compile_bytecode: value.compile_bytecode,
2400 no_sources: value.no_sources,
2401 no_sources_package: value.no_sources_package,
2402 no_build: value.no_build,
2403 no_build_package: value.no_build_package,
2404 no_binary: value.no_binary,
2405 no_binary_package: value.no_binary_package,
2406 torch_backend: value.torch_backend,
2407 }
2408 }
2409}
2410
2411impl From<ToolOptionsWire> for ToolOptions {
2412 fn from(value: ToolOptionsWire) -> Self {
2413 let exclude_newer = value
2414 .exclude_newer
2415 .map(|exclude_newer| match exclude_newer {
2416 ExcludeNewerOverride::Disabled => ExcludeNewerOverride::Disabled,
2417 ExcludeNewerOverride::Enabled(exclude_newer) => {
2418 let exclude_newer = *exclude_newer;
2419 if let Some(span) = value.exclude_newer_span
2420 && exclude_newer.span().is_none()
2421 {
2422 ExcludeNewerValue::relative(span).into()
2423 } else {
2424 exclude_newer.into()
2425 }
2426 }
2427 });
2428
2429 Self {
2430 index: value.index,
2431 index_url: value.index_url,
2432 extra_index_url: value.extra_index_url,
2433 no_index: value.no_index,
2434 find_links: value.find_links,
2435 index_strategy: value.index_strategy,
2436 keyring_provider: value.keyring_provider,
2437 resolution: value.resolution,
2438 prerelease: value.prerelease,
2439 prerelease_package: value.prerelease_package,
2440 fork_strategy: value.fork_strategy,
2441 dependency_metadata: value.dependency_metadata,
2442 config_settings: value.config_settings,
2443 config_settings_package: value.config_settings_package,
2444 build_isolation: value.build_isolation,
2445 extra_build_dependencies: value.extra_build_dependencies,
2446 extra_build_variables: value.extra_build_variables,
2447 exclude_newer,
2448 exclude_newer_package: value.exclude_newer_package,
2449 link_mode: value.link_mode,
2450 compile_bytecode: value.compile_bytecode,
2451 no_sources: value.no_sources,
2452 no_sources_package: value.no_sources_package,
2453 no_build: value.no_build,
2454 no_build_package: value.no_build_package,
2455 no_binary: value.no_binary,
2456 no_binary_package: value.no_binary_package,
2457 torch_backend: value.torch_backend,
2458 }
2459 }
2460}
2461
2462impl From<ToolOptions> for ToolOptionsWire {
2463 fn from(value: ToolOptions) -> Self {
2464 let (exclude_newer, exclude_newer_span) = match &value.exclude_newer {
2465 Some(ExcludeNewerOverride::Disabled) => (Some(ExcludeNewerOverride::Disabled), None),
2466 Some(ExcludeNewerOverride::Enabled(value)) => match value.as_ref() {
2467 ExcludeNewerValue::Absolute(_) => {
2468 (Some(ExcludeNewerOverride::Enabled(value.clone())), None)
2469 }
2470 ExcludeNewerValue::Relative(span) => (
2471 Some(ExcludeNewerValue::absolute(value.timestamp()).into()),
2472 Some(*span),
2473 ),
2474 },
2475 None => (None, None),
2476 };
2477
2478 Self {
2479 index: value.index,
2480 index_url: value.index_url,
2481 extra_index_url: value.extra_index_url,
2482 no_index: value.no_index,
2483 find_links: value.find_links,
2484 index_strategy: value.index_strategy,
2485 keyring_provider: value.keyring_provider,
2486 resolution: value.resolution,
2487 prerelease: value.prerelease,
2488 prerelease_package: value.prerelease_package,
2489 fork_strategy: value.fork_strategy,
2490 dependency_metadata: value.dependency_metadata,
2491 config_settings: value.config_settings,
2492 config_settings_package: value.config_settings_package,
2493 build_isolation: value.build_isolation,
2494 extra_build_dependencies: value.extra_build_dependencies,
2495 extra_build_variables: value.extra_build_variables,
2496 exclude_newer,
2497 exclude_newer_span,
2498 exclude_newer_package: value.exclude_newer_package,
2499 link_mode: value.link_mode,
2500 compile_bytecode: value.compile_bytecode,
2501 no_sources: value.no_sources,
2502 no_sources_package: value.no_sources_package,
2503 no_build: value.no_build,
2504 no_build_package: value.no_build_package,
2505 no_binary: value.no_binary,
2506 no_binary_package: value.no_binary_package,
2507 torch_backend: value.torch_backend,
2508 }
2509 }
2510}
2511
2512impl From<ToolOptions> for ResolverInstallerOptions {
2513 fn from(value: ToolOptions) -> Self {
2514 Self {
2515 indexes: IndexOptions {
2516 index: value.index,
2517 index_url: value.index_url,
2518 extra_index_url: value.extra_index_url,
2519 no_index: value.no_index,
2520 find_links: value.find_links,
2521 },
2522 index_strategy: value.index_strategy,
2523 keyring_provider: value.keyring_provider,
2524 resolution: value.resolution,
2525 prerelease: value.prerelease,
2526 prerelease_package: value.prerelease_package,
2527 fork_strategy: value.fork_strategy,
2528 dependency_metadata: value.dependency_metadata,
2529 config_settings: value.config_settings,
2530 config_settings_package: value.config_settings_package,
2531 build_isolation: value.build_isolation,
2532 extra_build_dependencies: value.extra_build_dependencies,
2533 extra_build_variables: value.extra_build_variables,
2534 exclude_newer: value.exclude_newer,
2535 exclude_newer_package: value.exclude_newer_package,
2536 link_mode: value.link_mode,
2537 compile_bytecode: value.compile_bytecode,
2538 no_sources: value.no_sources,
2539 no_sources_package: value.no_sources_package,
2540 upgrade: None,
2541 reinstall: None,
2542 no_build: value.no_build,
2543 no_build_package: value.no_build_package,
2544 no_binary: value.no_binary,
2545 no_binary_package: value.no_binary_package,
2546 torch_backend: value.torch_backend,
2547 }
2548 }
2549}
2550
2551#[derive(Debug, Clone, Default, Deserialize)]
2554#[serde(rename_all = "kebab-case", deny_unknown_fields)]
2555struct OptionsWire {
2556 required_version: Option<RequiredVersion>,
2559 system_certs: Option<bool>,
2560 native_tls: Option<bool>,
2561 offline: Option<bool>,
2562 no_cache: Option<bool>,
2563 cache_dir: Option<PathBuf>,
2564 preview: Option<bool>,
2565 preview_features: Option<PreviewFeaturesOption>,
2566 python_preference: Option<PythonPreference>,
2567 python_downloads: Option<PythonDownloads>,
2568 concurrent_downloads: Option<NonZeroUsize>,
2569 concurrent_builds: Option<NonZeroUsize>,
2570 concurrent_installs: Option<NonZeroUsize>,
2571
2572 index: Option<Vec<Index>>,
2575 index_url: Option<PipIndex>,
2576 extra_index_url: Option<Vec<PipExtraIndex>>,
2577 no_index: Option<bool>,
2578 find_links: Option<Vec<PipFindLinks>>,
2579 index_strategy: Option<IndexStrategy>,
2580 keyring_provider: Option<KeyringProviderType>,
2581 http_proxy: Option<ProxyUrl>,
2582 https_proxy: Option<ProxyUrl>,
2583 no_proxy: Option<Vec<String>>,
2584 allow_insecure_host: Option<Vec<TrustedHost>>,
2585 resolution: Option<ResolutionMode>,
2586 prerelease: Option<PrereleaseMode>,
2587 prerelease_package: Option<PrereleasePackage>,
2588 fork_strategy: Option<ForkStrategy>,
2589 dependency_metadata: Option<Vec<StaticMetadata>>,
2590 config_settings: Option<ConfigSettings>,
2591 config_settings_package: Option<PackageConfigSettings>,
2592 no_build_isolation: Option<bool>,
2593 no_build_isolation_package: Option<Vec<PackageName>>,
2594 extra_build_dependencies: Option<ExtraBuildDependencies>,
2595 extra_build_variables: Option<ExtraBuildVariables>,
2596 exclude_newer: Option<ExcludeNewerOverride>,
2597 exclude_newer_package: Option<ExcludeNewerPackage>,
2598 link_mode: Option<LinkMode>,
2599 compile_bytecode: Option<bool>,
2600 no_sources: Option<bool>,
2601 no_sources_package: Option<Vec<PackageName>>,
2602 upgrade: Option<bool>,
2603 upgrade_package: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2604 reinstall: Option<bool>,
2605 reinstall_package: Option<Vec<PackageName>>,
2606 no_build: Option<bool>,
2607 no_build_package: Option<Vec<PackageName>>,
2608 no_binary: Option<bool>,
2609 no_binary_package: Option<Vec<PackageName>>,
2610 torch_backend: Option<TorchMode>,
2611
2612 python_install_mirror: Option<String>,
2615 pypy_install_mirror: Option<String>,
2616 python_downloads_json_url: Option<String>,
2617
2618 publish_url: Option<DisplaySafeUrl>,
2621 trusted_publishing: Option<TrustedPublishing>,
2622 check_url: Option<IndexUrl>,
2623
2624 add_bounds: Option<AddBoundsKind>,
2627
2628 audit: Option<AuditOptions>,
2629 pip: Option<PipOptions>,
2630 cache_keys: Option<Vec<CacheKey>>,
2631
2632 override_dependencies: Option<Vec<OverrideDependency>>,
2636 exclude_dependencies: Option<Vec<ExcludeDependency>>,
2637 constraint_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2638 build_constraint_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2639 environments: Option<SupportedEnvironments>,
2640 required_environments: Option<SupportedEnvironments>,
2641
2642 conflicts: Option<serde::de::IgnoredAny>,
2646 workspace: Option<serde::de::IgnoredAny>,
2647 sources: Option<serde::de::IgnoredAny>,
2648 managed: Option<serde::de::IgnoredAny>,
2649 r#package: Option<serde::de::IgnoredAny>,
2650 default_groups: Option<serde::de::IgnoredAny>,
2651 dependency_groups: Option<serde::de::IgnoredAny>,
2652 dev_dependencies: Option<serde::de::IgnoredAny>,
2653
2654 build_backend: Option<serde::de::IgnoredAny>,
2656}
2657
2658impl TryFrom<OptionsWire> for Options {
2659 type Error = &'static str;
2660
2661 #[allow(deprecated)]
2662 fn try_from(value: OptionsWire) -> Result<Self, Self::Error> {
2663 let OptionsWire {
2664 required_version,
2665 system_certs,
2666 native_tls,
2667 offline,
2668 no_cache,
2669 cache_dir,
2670 preview,
2671 preview_features,
2672 python_preference,
2673 python_downloads,
2674 python_install_mirror,
2675 pypy_install_mirror,
2676 python_downloads_json_url,
2677 concurrent_downloads,
2678 concurrent_builds,
2679 concurrent_installs,
2680 index,
2681 index_url,
2682 extra_index_url,
2683 no_index,
2684 find_links,
2685 index_strategy,
2686 keyring_provider,
2687 http_proxy,
2688 https_proxy,
2689 no_proxy,
2690 allow_insecure_host,
2691 resolution,
2692 prerelease,
2693 prerelease_package,
2694 fork_strategy,
2695 dependency_metadata,
2696 config_settings,
2697 config_settings_package,
2698 no_build_isolation,
2699 no_build_isolation_package,
2700 exclude_newer,
2701 exclude_newer_package,
2702 link_mode,
2703 compile_bytecode,
2704 no_sources,
2705 no_sources_package,
2706 upgrade,
2707 upgrade_package,
2708 reinstall,
2709 reinstall_package,
2710 no_build,
2711 no_build_package,
2712 no_binary,
2713 no_binary_package,
2714 torch_backend,
2715 audit,
2716 pip,
2717 cache_keys,
2718 override_dependencies,
2719 exclude_dependencies,
2720 constraint_dependencies,
2721 build_constraint_dependencies,
2722 environments,
2723 required_environments,
2724 conflicts,
2725 publish_url,
2726 trusted_publishing,
2727 check_url,
2728 workspace,
2729 sources,
2730 default_groups,
2731 dependency_groups,
2732 extra_build_dependencies,
2733 extra_build_variables,
2734 dev_dependencies,
2735 managed,
2736 package,
2737 add_bounds: bounds,
2738 build_backend,
2740 } = value;
2741
2742 Ok(Self {
2743 globals: GlobalOptions {
2744 required_version,
2745 system_certs,
2746 native_tls,
2747 offline,
2748 no_cache,
2749 cache_dir,
2750 preview: PreviewOption::try_from(preview, preview_features)?,
2751 python_preference,
2752 python_downloads,
2753 concurrent_downloads,
2754 concurrent_builds,
2755 concurrent_installs,
2756 http_proxy,
2757 https_proxy,
2758 no_proxy,
2759 allow_insecure_host: allow_insecure_host.clone(),
2761 },
2762 top_level: ResolverInstallerSchema {
2763 index,
2764 index_url,
2765 extra_index_url,
2766 no_index,
2767 find_links,
2768 index_strategy,
2769 keyring_provider,
2770 resolution,
2771 prerelease,
2772 prerelease_package,
2773 fork_strategy,
2774 dependency_metadata,
2775 config_settings,
2776 config_settings_package,
2777 no_build_isolation,
2778 no_build_isolation_package,
2779 extra_build_dependencies,
2780 extra_build_variables,
2781 exclude_newer,
2782 exclude_newer_package,
2783 link_mode,
2784 compile_bytecode,
2785 no_sources,
2786 no_sources_package,
2787 upgrade,
2788 upgrade_package,
2789 reinstall,
2790 reinstall_package,
2791 no_build,
2792 no_build_package,
2793 no_binary,
2794 no_binary_package,
2795 torch_backend,
2796 },
2797 pip,
2798 cache_keys,
2799 build_backend,
2800 override_dependencies,
2801 exclude_dependencies,
2802 constraint_dependencies,
2803 build_constraint_dependencies,
2804 environments,
2805 required_environments,
2806 install_mirrors: PythonInstallMirrors {
2807 python_install_mirror,
2808 pypy_install_mirror,
2809 python_downloads_json_url,
2810 },
2811 conflicts,
2812 publish: PublishOptions {
2813 publish_url,
2814 trusted_publishing,
2815 check_url,
2816 },
2817 add: AddOptions { add_bounds: bounds },
2818 audit,
2819 workspace,
2820 sources,
2821 dev_dependencies,
2822 default_groups,
2823 dependency_groups,
2824 managed,
2825 package,
2826 })
2827 }
2828}
2829
2830#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
2831#[serde(rename_all = "kebab-case")]
2832#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2833pub struct PublishOptions {
2834 #[option(
2837 default = "\"https://upload.pypi.org/legacy/\"",
2838 value_type = "str",
2839 example = r#"
2840 publish-url = "https://test.pypi.org/legacy/"
2841 "#
2842 )]
2843 pub publish_url: Option<DisplaySafeUrl>,
2844
2845 #[option(
2852 default = "automatic",
2853 value_type = "str",
2854 example = r#"
2855 trusted-publishing = "always"
2856 "#
2857 )]
2858 pub trusted_publishing: Option<TrustedPublishing>,
2859
2860 #[option(
2874 default = "None",
2875 value_type = "str",
2876 example = r#"
2877 check-url = "https://test.pypi.org/simple"
2878 "#
2879 )]
2880 pub check_url: Option<IndexUrl>,
2881}
2882
2883#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
2884#[serde(rename_all = "kebab-case")]
2885#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2886pub struct AddOptions {
2887 #[option(
2898 default = "\"lower\"",
2899 value_type = "str",
2900 example = r#"
2901 add-bounds = "major"
2902 "#,
2903 possible_values = true
2904 )]
2905 pub add_bounds: Option<AddBoundsKind>,
2906}
2907
2908#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
2909#[serde(rename_all = "kebab-case")]
2910#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2911pub struct AuditOptions {
2912 #[option(
2914 default = "false",
2915 value_type = "bool",
2916 example = r#"
2917 malware-check = true
2918 "#
2919 )]
2920 pub malware_check: Option<bool>,
2921
2922 #[option(
2924 default = "\"https://api.osv.dev/\"",
2925 value_type = "str",
2926 example = r#"
2927 malware-check-url = "https://example.com"
2928 "#
2929 )]
2930 pub malware_check_url: Option<DisplaySafeUrl>,
2931
2932 #[option(
2937 default = "[]",
2938 value_type = "list[str]",
2939 example = r#"
2940 ignore = ["PYSEC-2022-43017", "GHSA-5239-wwwm-4pmq"]
2941 "#
2942 )]
2943 pub ignore: Option<Vec<String>>,
2944
2945 #[option(
2951 default = "[]",
2952 value_type = "list[str]",
2953 example = r#"
2954 ignore-until-fixed = ["PYSEC-2022-43017"]
2955 "#
2956 )]
2957 pub ignore_until_fixed: Option<Vec<String>>,
2958}
2959
2960#[derive(Debug, Clone)]
2961pub struct MalwareCheckSettings {
2962 pub enabled: bool,
2964 pub malware_check_url: Option<DisplaySafeUrl>,
2966}
2967
2968impl MalwareCheckSettings {
2969 pub fn resolve(
2970 filesystem: Option<&FilesystemOptions>,
2971 environment: &EnvironmentOptions,
2972 ) -> Self {
2973 let audit = filesystem.and_then(|options| options.audit.as_ref());
2974
2975 Self {
2976 enabled: environment
2977 .malware_check
2978 .value
2979 .or(audit.and_then(|audit| audit.malware_check))
2980 .unwrap_or_default(),
2981 malware_check_url: environment
2982 .malware_check_url
2983 .clone()
2984 .or_else(|| audit.and_then(|audit| audit.malware_check_url.clone())),
2985 }
2986 }
2987}
2988
2989#[derive(Debug, Clone)]
2991#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2992#[cfg_attr(feature = "schemars", schemars(untagged))]
2993pub enum PreviewFeaturesOption {
2994 Toggle(bool),
2995 Features(Vec<MaybePreviewFeature>),
2996}
2997
2998impl<'de> Deserialize<'de> for PreviewFeaturesOption {
3001 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
3002 where
3003 D: serde::Deserializer<'de>,
3004 {
3005 serde_untagged::UntaggedEnumVisitor::new()
3006 .expecting("a boolean or a list of preview feature names")
3007 .bool(|value| Ok(Self::Toggle(value)))
3008 .seq(|sequence| sequence.deserialize().map(Self::Features))
3009 .deserialize(deserializer)
3010 }
3011}
3012
3013#[expect(
3014 dead_code,
3015 reason = "Fields are only used by the OptionsMetadata and JsonSchema derives"
3016)]
3017#[derive(OptionsMetadata)]
3018#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3019#[cfg_attr(feature = "schemars", schemars(rename_all = "kebab-case"))]
3020struct PreviewOptionsDefinition {
3021 #[deprecated(note = "use `preview-features` instead")]
3027 preview: Option<bool>,
3028 #[option(
3032 default = "false",
3033 value_type = "bool | list[str]",
3034 example = r#"
3035 preview-features = true
3036 # or
3037 preview-features = ["json-output"]
3038 "#
3039 )]
3040 preview_features: Option<PreviewFeaturesOption>,
3041}
3042
3043#[derive(Debug, Clone)]
3045pub enum PreviewOption {
3046 Preview(bool),
3048 PreviewFeatures(PreviewFeaturesOption),
3050}
3051
3052impl uv_options_metadata::OptionsMetadata for PreviewOption {
3053 fn record(visit: &mut dyn uv_options_metadata::Visit) {
3054 <PreviewOptionsDefinition as uv_options_metadata::OptionsMetadata>::record(visit);
3055 }
3056}
3057
3058#[cfg(feature = "schemars")]
3059struct ConflictingPreviewOptions;
3060
3061#[cfg(feature = "schemars")]
3062impl schemars::JsonSchema for ConflictingPreviewOptions {
3063 fn schema_name() -> Cow<'static, str> {
3064 Cow::Borrowed("ConflictingPreviewOptions")
3065 }
3066
3067 fn json_schema(_generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
3068 schemars::json_schema!({
3069 "type": "object",
3070 "properties": {
3071 "preview": {},
3072 "preview-features": {},
3073 },
3074 "required": ["preview", "preview-features"],
3075 })
3076 }
3077}
3078
3079#[cfg(feature = "schemars")]
3080impl schemars::JsonSchema for PreviewOption {
3081 fn schema_name() -> Cow<'static, str> {
3082 Cow::Borrowed("PreviewOption")
3083 }
3084
3085 fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
3086 let mut schema = <PreviewOptionsDefinition as schemars::JsonSchema>::json_schema(generator);
3087 schema.insert(
3090 "not".to_string(),
3091 generator
3092 .subschema_for::<ConflictingPreviewOptions>()
3093 .into(),
3094 );
3095 schema
3096 }
3097}
3098
3099impl PreviewOption {
3100 fn try_from(
3101 preview: Option<bool>,
3102 preview_features: Option<PreviewFeaturesOption>,
3103 ) -> Result<Option<Self>, &'static str> {
3104 match (preview, preview_features) {
3105 (Some(_), Some(_)) => Err("cannot specify both `preview` and `preview-features`"),
3106 (Some(b), None) => Ok(Some(Self::Preview(b))),
3107 (None, Some(features)) => Ok(Some(Self::PreviewFeatures(features))),
3108 (None, None) => Ok(None),
3109 }
3110 }
3111
3112 pub fn resolve(&self) -> Preview {
3114 use PreviewFeaturesOption::{Features, Toggle};
3115
3116 match self {
3117 Self::Preview(false) | Self::PreviewFeatures(Toggle(false)) => Preview::default(),
3118 Self::Preview(true) | Self::PreviewFeatures(Toggle(true)) => Preview::all(),
3119 Self::PreviewFeatures(Features(features)) => Preview::from_feature_names(features),
3120 }
3121 }
3122}