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 AnnotationStyle, BuildIsolation, ExcludeDependency, ExcludeNewerPackage, ForkStrategy,
10 IndexStrategy, KeyringProviderType, PackageNameSpecifier, PrereleaseMode, PrereleasePackage,
11 ProxyUrl, Reinstall, RequiredVersion, ResolutionMode, TargetTriple, TrustedHost,
12 TrustedPublishing, Upgrade, serialize_exclude_newer_package_with_spans,
13};
14use uv_distribution_types::{
15 ConfigSettings, ExcludeNewerOverride, ExcludeNewerSpan, ExcludeNewerValue, ExtraBuildVariables,
16 Index, IndexLocations, IndexUrl, IndexUrlError, MinimumLibcVersion, Origin,
17 PackageConfigSettings, PipExtraIndex, PipFindLinks, PipIndex, StaticMetadata,
18};
19use uv_install_wheel::LinkMode;
20use uv_macros::{CombineOptions, OptionsMetadata};
21use uv_normalize::{ExtraName, PackageName, PipGroupName};
22use uv_pep508::Requirement;
23use uv_preview::{MaybePreviewFeature, Preview};
24use uv_pypi_types::{SupportedEnvironments, VerbatimParsedUrl};
25use uv_python::{PythonDownloads, PythonPreference, PythonVersion};
26use uv_redacted::DisplaySafeUrl;
27use uv_torch::TorchMode;
28use uv_workspace::pyproject::{
29 BuildConstraintDependency, ExtraBuildDependencies, OverrideDependency,
30};
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<BuildConstraintDependency>>,
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))]
169 pub minimum_libc_version: Option<MinimumLibcVersion>,
170
171 #[cfg_attr(feature = "schemars", schemars(skip))]
175 pub(crate) conflicts: Option<serde::de::IgnoredAny>,
176
177 #[cfg_attr(feature = "schemars", schemars(skip))]
178 pub(crate) workspace: Option<serde::de::IgnoredAny>,
179
180 #[cfg_attr(feature = "schemars", schemars(skip))]
181 pub(crate) sources: Option<serde::de::IgnoredAny>,
182
183 #[cfg_attr(feature = "schemars", schemars(skip))]
184 pub(crate) dev_dependencies: Option<serde::de::IgnoredAny>,
185
186 #[cfg_attr(feature = "schemars", schemars(skip))]
187 pub(crate) default_groups: Option<serde::de::IgnoredAny>,
188
189 #[cfg_attr(feature = "schemars", schemars(skip))]
190 pub(crate) dependency_groups: Option<serde::de::IgnoredAny>,
191
192 #[cfg_attr(feature = "schemars", schemars(skip))]
193 pub(crate) managed: Option<serde::de::IgnoredAny>,
194
195 #[cfg_attr(feature = "schemars", schemars(skip))]
196 pub(crate) r#package: Option<serde::de::IgnoredAny>,
197
198 #[cfg_attr(feature = "schemars", schemars(skip))]
199 pub(crate) build_backend: Option<serde::de::IgnoredAny>,
200}
201
202impl Options {
203 pub fn simple(globals: GlobalOptions, top_level: ResolverInstallerSchema) -> Self {
205 Self {
206 globals,
207 top_level,
208 ..Default::default()
209 }
210 }
211
212 #[must_use]
214 pub(crate) fn with_origin(mut self, origin: Origin) -> Self {
215 if let Some(indexes) = &mut self.top_level.index {
216 for index in indexes {
217 index.origin.get_or_insert(origin);
218 }
219 }
220 if let Some(index_url) = &mut self.top_level.index_url {
221 index_url.try_set_origin(origin);
222 }
223 if let Some(extra_index_urls) = &mut self.top_level.extra_index_url {
224 for index_url in extra_index_urls {
225 index_url.try_set_origin(origin);
226 }
227 }
228 if let Some(pip) = &mut self.pip {
229 if let Some(indexes) = &mut pip.index {
230 for index in indexes {
231 index.origin.get_or_insert(origin);
232 }
233 }
234 if let Some(index_url) = &mut pip.index_url {
235 index_url.try_set_origin(origin);
236 }
237 if let Some(extra_index_urls) = &mut pip.extra_index_url {
238 for index_url in extra_index_urls {
239 index_url.try_set_origin(origin);
240 }
241 }
242 }
243 self
244 }
245
246 pub(crate) fn relative_to(self, root_dir: &Path) -> Result<Self, IndexUrlError> {
248 Ok(Self {
249 top_level: self.top_level.relative_to(root_dir)?,
250 pip: self.pip.map(|pip| pip.relative_to(root_dir)).transpose()?,
251 ..self
252 })
253 }
254}
255
256#[derive(Debug, Clone, Default, Deserialize, CombineOptions, OptionsMetadata)]
258#[serde(try_from = "GlobalOptionsWire", rename_all = "kebab-case")]
259#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
260#[cfg_attr(feature = "schemars", schemars(!try_from))]
261pub struct GlobalOptions {
262 #[option(
269 default = "null",
270 value_type = "str",
271 example = r#"
272 required-version = ">=0.5.0"
273 "#
274 )]
275 pub required_version: Option<RequiredVersion>,
276 #[option(
281 default = "false",
282 value_type = "bool",
283 uv_toml_only = true,
284 example = r#"
285 system-certs = true
286 "#
287 )]
288 pub system_certs: Option<bool>,
289 #[deprecated(note = "use `system-certs` instead")]
296 #[option(
297 default = "false",
298 value_type = "bool",
299 uv_toml_only = true,
300 example = r#"
301 native-tls = true
302 "#
303 )]
304 pub native_tls: Option<bool>,
305 #[option(
307 default = "false",
308 value_type = "bool",
309 example = r#"
310 offline = true
311 "#
312 )]
313 pub offline: Option<bool>,
314 #[option(
317 default = "false",
318 value_type = "bool",
319 example = r#"
320 no-cache = true
321 "#
322 )]
323 pub no_cache: Option<bool>,
324 #[option(
329 default = "None",
330 value_type = "str",
331 uv_toml_only = true,
332 example = r#"
333 cache-dir = "./.uv_cache"
334 "#
335 )]
336 pub cache_dir: Option<PathBuf>,
337
338 #[serde(flatten)]
340 pub preview: Option<PreviewOption>,
341
342 #[option(
345 default = "\"managed\"",
346 value_type = "str",
347 example = r#"
348 python-preference = "managed"
349 "#,
350 possible_values = true
351 )]
352 pub python_preference: Option<PythonPreference>,
353 #[option(
355 default = "\"automatic\"",
356 value_type = "str",
357 example = r#"
358 python-downloads = "manual"
359 "#,
360 possible_values = true
361 )]
362 pub python_downloads: Option<PythonDownloads>,
363 #[option(
366 default = "50",
367 value_type = "int",
368 example = r#"
369 concurrent-downloads = 4
370 "#
371 )]
372 pub concurrent_downloads: Option<NonZeroUsize>,
373 #[option(
378 default = "None",
379 value_type = "int",
380 example = r#"
381 concurrent-builds = 4
382 "#
383 )]
384 pub concurrent_builds: Option<NonZeroUsize>,
385 #[option(
389 default = "None",
390 value_type = "int",
391 example = r#"
392 concurrent-installs = 4
393 "#
394 )]
395 pub concurrent_installs: Option<NonZeroUsize>,
396 #[option(
398 default = "None",
399 value_type = "str",
400 uv_toml_only = true,
401 example = r#"
402 http-proxy = "http://proxy.example.com"
403 "#
404 )]
405 pub http_proxy: Option<ProxyUrl>,
406 #[option(
408 default = "None",
409 value_type = "str",
410 uv_toml_only = true,
411 example = r#"
412 https-proxy = "https://proxy.example.com"
413 "#
414 )]
415 pub https_proxy: Option<ProxyUrl>,
416 #[option(
418 default = "None",
419 value_type = "list[str]",
420 uv_toml_only = true,
421 example = r#"
422 no-proxy = ["localhost", "127.0.0.1"]
423 "#
424 )]
425 pub no_proxy: Option<Vec<String>>,
426 #[option(
435 default = "[]",
436 value_type = "list[str]",
437 example = r#"
438 allow-insecure-host = ["localhost:8080"]
439 "#
440 )]
441 pub allow_insecure_host: Option<Vec<TrustedHost>>,
442}
443
444#[derive(Debug, Clone, Default, Deserialize)]
447#[serde(rename_all = "kebab-case")]
448struct GlobalOptionsWire {
449 required_version: Option<RequiredVersion>,
450 system_certs: Option<bool>,
451 native_tls: Option<bool>,
452 offline: Option<bool>,
453 no_cache: Option<bool>,
454 cache_dir: Option<PathBuf>,
455
456 preview: Option<bool>,
457 preview_features: Option<PreviewFeaturesOption>,
458
459 python_preference: Option<PythonPreference>,
460 python_downloads: Option<PythonDownloads>,
461 concurrent_downloads: Option<NonZeroUsize>,
462 concurrent_builds: Option<NonZeroUsize>,
463 concurrent_installs: Option<NonZeroUsize>,
464 http_proxy: Option<ProxyUrl>,
465 https_proxy: Option<ProxyUrl>,
466 no_proxy: Option<Vec<String>>,
467 allow_insecure_host: Option<Vec<TrustedHost>>,
468}
469
470impl TryFrom<GlobalOptionsWire> for GlobalOptions {
471 type Error = &'static str;
472
473 #[allow(deprecated)]
474 fn try_from(value: GlobalOptionsWire) -> Result<Self, Self::Error> {
475 let GlobalOptionsWire {
476 required_version,
477 system_certs,
478 native_tls,
479 offline,
480 no_cache,
481 cache_dir,
482 preview,
483 preview_features,
484 python_preference,
485 python_downloads,
486 concurrent_downloads,
487 concurrent_builds,
488 concurrent_installs,
489 http_proxy,
490 https_proxy,
491 no_proxy,
492 allow_insecure_host,
493 } = value;
494
495 Ok(Self {
496 required_version,
497 system_certs,
498 native_tls,
499 offline,
500 no_cache,
501 cache_dir,
502 preview: PreviewOption::try_from(preview, preview_features)?,
503 python_preference,
504 python_downloads,
505 concurrent_downloads,
506 concurrent_builds,
507 concurrent_installs,
508 http_proxy,
509 https_proxy,
510 no_proxy,
511 allow_insecure_host,
512 })
513 }
514}
515
516fn rebase_indexes(
518 root_dir: &Path,
519 indexes: &mut Option<Vec<Index>>,
520 index_url: &mut Option<PipIndex>,
521 extra_index_urls: &mut Option<Vec<PipExtraIndex>>,
522 find_links: &mut Option<Vec<PipFindLinks>>,
523) -> Result<(), IndexUrlError> {
524 *indexes = indexes
525 .take()
526 .map(|indexes| {
527 indexes
528 .into_iter()
529 .map(|index| index.relative_to(root_dir))
530 .collect::<Result<Vec<_>, _>>()
531 })
532 .transpose()?;
533 *index_url = index_url
534 .take()
535 .map(|index| index.relative_to(root_dir))
536 .transpose()?;
537 *extra_index_urls = extra_index_urls
538 .take()
539 .map(|indexes| {
540 indexes
541 .into_iter()
542 .map(|index| index.relative_to(root_dir))
543 .collect::<Result<Vec<_>, _>>()
544 })
545 .transpose()?;
546 *find_links = find_links
547 .take()
548 .map(|find_links| {
549 find_links
550 .into_iter()
551 .map(|find_link| find_link.relative_to(root_dir))
552 .collect::<Result<Vec<_>, _>>()
553 })
554 .transpose()?;
555
556 Ok(())
557}
558
559#[derive(Debug, Clone, Default, CombineOptions)]
561pub struct InstallerOptions {
562 index: Option<Vec<Index>>,
563 index_url: Option<PipIndex>,
564 extra_index_url: Option<Vec<PipExtraIndex>>,
565 no_index: Option<bool>,
566 find_links: Option<Vec<PipFindLinks>>,
567 index_strategy: Option<IndexStrategy>,
568 keyring_provider: Option<KeyringProviderType>,
569 config_settings: Option<ConfigSettings>,
570 exclude_newer: Option<ExcludeNewerOverride>,
571 link_mode: Option<LinkMode>,
572 compile_bytecode: Option<bool>,
573 reinstall: Option<Reinstall>,
574 build_isolation: Option<BuildIsolation>,
575 no_build: Option<bool>,
576 no_build_package: Option<Vec<PackageName>>,
577 no_binary: Option<bool>,
578 no_binary_package: Option<Vec<PackageName>>,
579 no_sources: Option<bool>,
580 no_sources_package: Option<Vec<PackageName>>,
581}
582
583#[derive(Debug, Clone, Default, CombineOptions)]
585pub struct IndexOptions {
586 pub index: Option<Vec<Index>>,
587 pub index_url: Option<PipIndex>,
588 pub extra_index_url: Option<Vec<PipExtraIndex>>,
589 pub no_index: Option<bool>,
590 pub find_links: Option<Vec<PipFindLinks>>,
591}
592
593impl IndexOptions {
594 pub fn relative_to(mut self, root_dir: &Path) -> Result<Self, IndexUrlError> {
596 rebase_indexes(
597 root_dir,
598 &mut self.index,
599 &mut self.index_url,
600 &mut self.extra_index_url,
601 &mut self.find_links,
602 )?;
603
604 Ok(self)
605 }
606}
607
608impl From<IndexOptions> for IndexLocations {
609 fn from(value: IndexOptions) -> Self {
610 let IndexOptions {
611 index,
612 index_url,
613 extra_index_url,
614 no_index,
615 find_links,
616 } = value;
617
618 Self::new(
619 index
620 .into_iter()
621 .flatten()
622 .chain(extra_index_url.into_iter().flatten().map(Index::from))
623 .chain(index_url.into_iter().map(Index::from))
624 .collect(),
625 find_links.into_iter().flatten().map(Index::from).collect(),
626 no_index.unwrap_or_default(),
627 )
628 }
629}
630
631impl From<IndexOptions> for PipOptions {
632 fn from(value: IndexOptions) -> Self {
633 let IndexOptions {
634 index,
635 index_url,
636 extra_index_url,
637 no_index,
638 find_links,
639 } = value;
640
641 Self {
642 index,
643 index_url,
644 extra_index_url,
645 no_index,
646 find_links,
647 ..Self::default()
648 }
649 }
650}
651
652#[derive(Debug, Clone, Default, CombineOptions)]
654pub struct ResolverOptions {
655 pub indexes: IndexOptions,
656 pub index_strategy: Option<IndexStrategy>,
657 pub keyring_provider: Option<KeyringProviderType>,
658 pub resolution: Option<ResolutionMode>,
659 pub prerelease: Option<PrereleaseMode>,
660 pub prerelease_package: Option<PrereleasePackage>,
661 pub fork_strategy: Option<ForkStrategy>,
662 pub dependency_metadata: Option<Vec<StaticMetadata>>,
663 pub config_settings: Option<ConfigSettings>,
664 pub config_settings_package: Option<PackageConfigSettings>,
665 pub exclude_newer: Option<ExcludeNewerOverride>,
666 pub exclude_newer_package: Option<ExcludeNewerPackage>,
667 pub link_mode: Option<LinkMode>,
668 pub torch_backend: Option<TorchMode>,
669 pub upgrade: Option<Upgrade>,
670 pub build_isolation: Option<BuildIsolation>,
671 pub no_build: Option<bool>,
672 pub no_build_package: Option<Vec<PackageName>>,
673 pub no_binary: Option<bool>,
674 pub no_binary_package: Option<Vec<PackageName>>,
675 pub extra_build_dependencies: Option<ExtraBuildDependencies>,
676 pub extra_build_variables: Option<ExtraBuildVariables>,
677 pub no_sources: Option<bool>,
678 pub no_sources_package: Option<Vec<PackageName>>,
679}
680
681impl ResolverOptions {
682 pub fn relative_to(mut self, root_dir: &Path) -> Result<Self, IndexUrlError> {
684 self.indexes = self.indexes.relative_to(root_dir)?;
685 Ok(self)
686 }
687}
688
689#[derive(Debug, Clone, Default, CombineOptions)]
692pub struct ResolverInstallerOptions {
693 pub indexes: IndexOptions,
694 pub index_strategy: Option<IndexStrategy>,
695 pub keyring_provider: Option<KeyringProviderType>,
696 pub resolution: Option<ResolutionMode>,
697 pub prerelease: Option<PrereleaseMode>,
698 pub prerelease_package: Option<PrereleasePackage>,
699 pub fork_strategy: Option<ForkStrategy>,
700 pub dependency_metadata: Option<Vec<StaticMetadata>>,
701 pub config_settings: Option<ConfigSettings>,
702 pub config_settings_package: Option<PackageConfigSettings>,
703 pub build_isolation: Option<BuildIsolation>,
704 pub extra_build_dependencies: Option<ExtraBuildDependencies>,
705 pub extra_build_variables: Option<ExtraBuildVariables>,
706 pub exclude_newer: Option<ExcludeNewerOverride>,
707 pub exclude_newer_package: Option<ExcludeNewerPackage>,
708 pub link_mode: Option<LinkMode>,
709 pub torch_backend: Option<TorchMode>,
710 pub compile_bytecode: Option<bool>,
711 pub no_sources: Option<bool>,
712 pub no_sources_package: Option<Vec<PackageName>>,
713 pub upgrade: Option<Upgrade>,
714 pub reinstall: Option<Reinstall>,
715 pub no_build: Option<bool>,
716 pub no_build_package: Option<Vec<PackageName>>,
717 pub no_binary: Option<bool>,
718 pub no_binary_package: Option<Vec<PackageName>>,
719}
720
721impl ResolverInstallerOptions {
722 pub fn relative_to(mut self, root_dir: &Path) -> Result<Self, IndexUrlError> {
724 self.indexes = self.indexes.relative_to(root_dir)?;
725 Ok(self)
726 }
727}
728
729impl From<ResolverInstallerSchema> for ResolverInstallerOptions {
730 fn from(value: ResolverInstallerSchema) -> Self {
731 let ResolverInstallerSchema {
732 index,
733 index_url,
734 extra_index_url,
735 no_index,
736 find_links,
737 index_strategy,
738 keyring_provider,
739 resolution,
740 prerelease,
741 prerelease_package,
742 fork_strategy,
743 dependency_metadata,
744 config_settings,
745 config_settings_package,
746 no_build_isolation,
747 no_build_isolation_package,
748 extra_build_dependencies,
749 extra_build_variables,
750 exclude_newer,
751 exclude_newer_package,
752 link_mode,
753 torch_backend,
754 compile_bytecode,
755 no_sources,
756 no_sources_package,
757 upgrade,
758 upgrade_package,
759 reinstall,
760 reinstall_package,
761 no_build,
762 no_build_package,
763 no_binary,
764 no_binary_package,
765 } = value;
766 Self {
767 indexes: IndexOptions {
768 index,
769 index_url,
770 extra_index_url,
771 no_index,
772 find_links,
773 },
774 index_strategy,
775 keyring_provider,
776 resolution,
777 prerelease,
778 prerelease_package,
779 fork_strategy,
780 dependency_metadata,
781 config_settings,
782 config_settings_package,
783 build_isolation: BuildIsolation::from_args(
784 no_build_isolation,
785 no_build_isolation_package.into_iter().flatten().collect(),
786 ),
787 extra_build_dependencies,
788 extra_build_variables,
789 exclude_newer,
790 exclude_newer_package,
791 link_mode,
792 torch_backend,
793 compile_bytecode,
794 no_sources,
795 no_sources_package,
796 upgrade: Upgrade::from_args(
797 upgrade,
798 upgrade_package
799 .into_iter()
800 .flatten()
801 .map(Into::into)
802 .collect(),
803 Vec::new(),
804 ),
805 reinstall: Reinstall::from_args(reinstall, reinstall_package.unwrap_or_default()),
806 no_build,
807 no_build_package,
808 no_binary,
809 no_binary_package,
810 }
811 }
812}
813
814impl ResolverInstallerSchema {
815 fn relative_to(mut self, root_dir: &Path) -> Result<Self, IndexUrlError> {
817 rebase_indexes(
818 root_dir,
819 &mut self.index,
820 &mut self.index_url,
821 &mut self.extra_index_url,
822 &mut self.find_links,
823 )?;
824
825 Ok(self)
826 }
827}
828
829#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
831#[serde(rename_all = "kebab-case")]
832#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
833pub struct ResolverInstallerSchema {
834 #[option(
862 default = "\"[]\"",
863 value_type = "dict",
864 example = r#"
865 [[tool.uv.index]]
866 name = "pytorch"
867 url = "https://download.pytorch.org/whl/cu130"
868 "#
869 )]
870 pub index: Option<Vec<Index>>,
871 #[option(
881 default = "\"https://pypi.org/simple\"",
882 value_type = "str",
883 example = r#"
884 index-url = "https://test.pypi.org/simple"
885 "#
886 )]
887 pub index_url: Option<PipIndex>,
888 #[option(
902 default = "[]",
903 value_type = "list[str]",
904 example = r#"
905 extra-index-url = ["https://download.pytorch.org/whl/cpu"]
906 "#
907 )]
908 pub extra_index_url: Option<Vec<PipExtraIndex>>,
909 #[option(
912 default = "false",
913 value_type = "bool",
914 example = r#"
915 no-index = true
916 "#
917 )]
918 pub no_index: Option<bool>,
919 #[option(
928 default = "[]",
929 value_type = "list[str]",
930 example = r#"
931 find-links = ["https://download.pytorch.org/whl/torch_stable.html"]
932 "#
933 )]
934 pub find_links: Option<Vec<PipFindLinks>>,
935 #[option(
942 default = "\"first-index\"",
943 value_type = "str",
944 example = r#"
945 index-strategy = "unsafe-best-match"
946 "#,
947 possible_values = true
948 )]
949 pub index_strategy: Option<IndexStrategy>,
950 #[option(
955 default = "\"disabled\"",
956 value_type = "str",
957 example = r#"
958 keyring-provider = "subprocess"
959 "#
960 )]
961 pub keyring_provider: Option<KeyringProviderType>,
962 #[option(
967 default = "\"highest\"",
968 value_type = "str",
969 example = r#"
970 resolution = "lowest-direct"
971 "#,
972 possible_values = true
973 )]
974 pub resolution: Option<ResolutionMode>,
975 #[option(
981 default = "\"if-necessary\"",
982 value_type = "str",
983 example = r#"
984 prerelease = "allow"
985 "#,
986 possible_values = true
987 )]
988 pub prerelease: Option<PrereleaseMode>,
989 #[option(
994 default = "{}",
995 value_type = "dict",
996 example = r#"
997 prerelease-package = { numpy = "allow", scipy = "disallow" }
998 "#
999 )]
1000 pub prerelease_package: Option<PrereleasePackage>,
1001 #[option(
1012 default = "\"requires-python\"",
1013 value_type = "str",
1014 example = r#"
1015 fork-strategy = "fewest"
1016 "#,
1017 possible_values = true
1018 )]
1019 pub fork_strategy: Option<ForkStrategy>,
1020 #[option(
1034 default = r#"[]"#,
1035 value_type = "list[dict]",
1036 example = r#"
1037 dependency-metadata = [
1038 { name = "flask", version = "1.0.0", requires-dist = ["werkzeug"], requires-python = ">=3.6" },
1039 ]
1040 "#
1041 )]
1042 pub dependency_metadata: Option<Vec<StaticMetadata>>,
1043 #[option(
1046 default = "{}",
1047 value_type = "dict",
1048 example = r#"
1049 config-settings = { editable_mode = "compat" }
1050 "#
1051 )]
1052 pub config_settings: Option<ConfigSettings>,
1053 #[option(
1058 default = "{}",
1059 value_type = "dict",
1060 example = r#"
1061 config-settings-package = { numpy = { editable_mode = "compat" } }
1062 "#
1063 )]
1064 pub config_settings_package: Option<PackageConfigSettings>,
1065 #[option(
1070 default = "false",
1071 value_type = "bool",
1072 example = r#"
1073 no-build-isolation = true
1074 "#
1075 )]
1076 pub no_build_isolation: Option<bool>,
1077 #[option(
1082 default = "[]",
1083 value_type = "list[str]",
1084 example = r#"
1085 no-build-isolation-package = ["package1", "package2"]
1086 "#
1087 )]
1088 pub no_build_isolation_package: Option<Vec<PackageName>>,
1089 #[option(
1095 default = "[]",
1096 value_type = "dict",
1097 example = r#"
1098 extra-build-dependencies = { pytest = ["setuptools"] }
1099 "#
1100 )]
1101 pub extra_build_dependencies: Option<ExtraBuildDependencies>,
1102 #[option(
1107 default = r#"{}"#,
1108 value_type = r#"dict[str, dict[str, str]]"#,
1109 example = r#"
1110 extra-build-variables = { flash-attn = { FLASH_ATTENTION_SKIP_CUDA_BUILD = "TRUE" } }
1111 "#
1112 )]
1113 pub extra_build_variables: Option<ExtraBuildVariables>,
1114 #[option(
1129 default = "None",
1130 value_type = "str | false",
1131 example = r#"
1132 exclude-newer = "2006-12-02T02:07:43Z"
1133 "#
1134 )]
1135 pub exclude_newer: Option<ExcludeNewerOverride>,
1136 #[option(
1150 default = "None",
1151 value_type = "dict",
1152 example = r#"
1153 exclude-newer-package = { tqdm = "2022-04-04T00:00:00Z", markupsafe = false }
1154 "#
1155 )]
1156 pub exclude_newer_package: Option<ExcludeNewerPackage>,
1157 #[option(
1167 default = "\"clone\" (macOS, Linux) or \"hardlink\" (Windows)",
1168 value_type = "str",
1169 example = r#"
1170 link-mode = "copy"
1171 "#,
1172 possible_values = true
1173 )]
1174 pub link_mode: Option<LinkMode>,
1175 #[option(
1186 default = "false",
1187 value_type = "bool",
1188 example = r#"
1189 compile-bytecode = true
1190 "#
1191 )]
1192 pub compile_bytecode: Option<bool>,
1193 #[option(
1197 default = "false",
1198 value_type = "bool",
1199 example = r#"
1200 no-sources = true
1201 "#
1202 )]
1203 pub no_sources: Option<bool>,
1204 #[option(
1206 default = "[]",
1207 value_type = "list[str]",
1208 example = r#"
1209 no-sources-package = ["ruff"]
1210 "#
1211 )]
1212 pub no_sources_package: Option<Vec<PackageName>>,
1213 #[option(
1215 default = "false",
1216 value_type = "bool",
1217 example = r#"
1218 upgrade = true
1219 "#
1220 )]
1221 pub upgrade: Option<bool>,
1222 #[option(
1227 default = "[]",
1228 value_type = "list[str]",
1229 example = r#"
1230 upgrade-package = ["ruff"]
1231 "#
1232 )]
1233 pub upgrade_package: Option<Vec<Requirement<VerbatimParsedUrl>>>,
1234 #[option(
1236 default = "false",
1237 value_type = "bool",
1238 example = r#"
1239 reinstall = true
1240 "#
1241 )]
1242 pub reinstall: Option<bool>,
1243 #[option(
1246 default = "[]",
1247 value_type = "list[str]",
1248 example = r#"
1249 reinstall-package = ["ruff"]
1250 "#
1251 )]
1252 pub reinstall_package: Option<Vec<PackageName>>,
1253 #[option(
1260 default = "false",
1261 value_type = "bool",
1262 example = r#"
1263 no-build = true
1264 "#
1265 )]
1266 pub no_build: Option<bool>,
1267 #[option(
1271 default = "[]",
1272 value_type = "list[str]",
1273 example = r#"
1274 no-build-package = ["ruff"]
1275 "#
1276 )]
1277 pub no_build_package: Option<Vec<PackageName>>,
1278 #[option(
1283 default = "false",
1284 value_type = "bool",
1285 example = r#"
1286 no-binary = true
1287 "#
1288 )]
1289 pub no_binary: Option<bool>,
1290 #[option(
1292 default = "[]",
1293 value_type = "list[str]",
1294 example = r#"
1295 no-binary-package = ["ruff"]
1296 "#
1297 )]
1298 pub no_binary_package: Option<Vec<PackageName>>,
1299 #[option(
1314 default = "null",
1315 value_type = "str",
1316 example = r#"
1317 torch-backend = "auto"
1318 "#
1319 )]
1320 pub torch_backend: Option<TorchMode>,
1321}
1322
1323#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
1325#[serde(rename_all = "kebab-case")]
1326#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1327pub struct PythonInstallMirrors {
1328 #[option(
1336 default = "None",
1337 value_type = "str",
1338 uv_toml_only = true,
1339 example = r#"
1340 python-install-mirror = "https://github.com/astral-sh/python-build-standalone/releases/download"
1341 "#
1342 )]
1343 pub python_install_mirror: Option<String>,
1344 #[option(
1353 default = "None",
1354 value_type = "str",
1355 uv_toml_only = true,
1356 example = r#"
1357 pypy-install-mirror = "https://downloads.python.org/pypy"
1358 "#
1359 )]
1360 pub pypy_install_mirror: Option<String>,
1361
1362 #[option(
1364 default = "None",
1365 value_type = "str",
1366 uv_toml_only = true,
1367 example = r#"
1368 python-downloads-json-url = "/etc/uv/python-downloads.json"
1369 "#
1370 )]
1371 pub python_downloads_json_url: Option<String>,
1372}
1373
1374impl PythonInstallMirrors {
1375 #[must_use]
1376 pub fn combine(self, other: Self) -> Self {
1377 Self {
1378 python_install_mirror: self.python_install_mirror.or(other.python_install_mirror),
1379 pypy_install_mirror: self.pypy_install_mirror.or(other.pypy_install_mirror),
1380 python_downloads_json_url: self
1381 .python_downloads_json_url
1382 .or(other.python_downloads_json_url),
1383 }
1384 }
1385}
1386
1387#[derive(Debug, Clone, Default, Deserialize, CombineOptions, OptionsMetadata)]
1392#[serde(deny_unknown_fields, rename_all = "kebab-case")]
1393#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1394pub struct PipOptions {
1395 #[option(
1408 default = "None",
1409 value_type = "str",
1410 example = r#"
1411 python = "3.10"
1412 "#
1413 )]
1414 pub python: Option<String>,
1415 #[option(
1424 default = "false",
1425 value_type = "bool",
1426 example = r#"
1427 system = true
1428 "#
1429 )]
1430 pub system: Option<bool>,
1431 #[option(
1438 default = "false",
1439 value_type = "bool",
1440 example = r#"
1441 break-system-packages = true
1442 "#
1443 )]
1444 pub break_system_packages: Option<bool>,
1445 #[option(
1448 default = "None",
1449 value_type = "str",
1450 example = r#"
1451 target = "./target"
1452 "#
1453 )]
1454 pub target: Option<PathBuf>,
1455 #[option(
1463 default = "None",
1464 value_type = "str",
1465 example = r#"
1466 prefix = "./prefix"
1467 "#
1468 )]
1469 pub prefix: Option<PathBuf>,
1470 #[serde(skip)]
1471 #[cfg_attr(feature = "schemars", schemars(skip))]
1472 pub index: Option<Vec<Index>>,
1473 #[option(
1481 default = "\"https://pypi.org/simple\"",
1482 value_type = "str",
1483 example = r#"
1484 index-url = "https://test.pypi.org/simple"
1485 "#
1486 )]
1487 pub index_url: Option<PipIndex>,
1488 #[option(
1499 default = "[]",
1500 value_type = "list[str]",
1501 example = r#"
1502 extra-index-url = ["https://download.pytorch.org/whl/cpu"]
1503 "#
1504 )]
1505 pub extra_index_url: Option<Vec<PipExtraIndex>>,
1506 #[option(
1509 default = "false",
1510 value_type = "bool",
1511 example = r#"
1512 no-index = true
1513 "#
1514 )]
1515 pub no_index: Option<bool>,
1516 #[option(
1525 default = "[]",
1526 value_type = "list[str]",
1527 example = r#"
1528 find-links = ["https://download.pytorch.org/whl/torch_stable.html"]
1529 "#
1530 )]
1531 pub find_links: Option<Vec<PipFindLinks>>,
1532 #[option(
1539 default = "\"first-index\"",
1540 value_type = "str",
1541 example = r#"
1542 index-strategy = "unsafe-best-match"
1543 "#,
1544 possible_values = true
1545 )]
1546 pub index_strategy: Option<IndexStrategy>,
1547 #[option(
1552 default = "disabled",
1553 value_type = "str",
1554 example = r#"
1555 keyring-provider = "subprocess"
1556 "#
1557 )]
1558 pub keyring_provider: Option<KeyringProviderType>,
1559 #[option(
1567 default = "false",
1568 value_type = "bool",
1569 example = r#"
1570 no-build = true
1571 "#
1572 )]
1573 pub no_build: Option<bool>,
1574 #[option(
1582 default = "[]",
1583 value_type = "list[str]",
1584 example = r#"
1585 no-binary = ["ruff"]
1586 "#
1587 )]
1588 pub no_binary: Option<Vec<PackageNameSpecifier>>,
1589 #[option(
1599 default = "[]",
1600 value_type = "list[str]",
1601 example = r#"
1602 only-binary = ["ruff"]
1603 "#
1604 )]
1605 pub only_binary: Option<Vec<PackageNameSpecifier>>,
1606 #[option(
1611 default = "false",
1612 value_type = "bool",
1613 example = r#"
1614 no-build-isolation = true
1615 "#
1616 )]
1617 pub no_build_isolation: Option<bool>,
1618 #[option(
1623 default = "[]",
1624 value_type = "list[str]",
1625 example = r#"
1626 no-build-isolation-package = ["package1", "package2"]
1627 "#
1628 )]
1629 pub no_build_isolation_package: Option<Vec<PackageName>>,
1630 #[option(
1636 default = "[]",
1637 value_type = "dict",
1638 example = r#"
1639 extra-build-dependencies = { pytest = ["setuptools"] }
1640 "#
1641 )]
1642 pub extra_build_dependencies: Option<ExtraBuildDependencies>,
1643 #[option(
1648 default = r#"{}"#,
1649 value_type = r#"dict[str, dict[str, str]]"#,
1650 example = r#"
1651 extra-build-variables = { flash-attn = { FLASH_ATTENTION_SKIP_CUDA_BUILD = "TRUE" } }
1652 "#
1653 )]
1654 pub extra_build_variables: Option<ExtraBuildVariables>,
1655 #[option(
1658 default = "false",
1659 value_type = "bool",
1660 example = r#"
1661 strict = true
1662 "#
1663 )]
1664 pub strict: Option<bool>,
1665 #[option(
1669 default = "[]",
1670 value_type = "list[str]",
1671 example = r#"
1672 extra = ["dev", "docs"]
1673 "#
1674 )]
1675 pub extra: Option<Vec<ExtraName>>,
1676 #[option(
1680 default = "false",
1681 value_type = "bool",
1682 example = r#"
1683 all-extras = true
1684 "#
1685 )]
1686 pub all_extras: Option<bool>,
1687 #[option(
1689 default = "[]",
1690 value_type = "list[str]",
1691 example = r#"
1692 all-extras = true
1693 no-extra = ["dev", "docs"]
1694 "#
1695 )]
1696 pub no_extra: Option<Vec<ExtraName>>,
1697 #[option(
1700 default = "false",
1701 value_type = "bool",
1702 example = r#"
1703 no-deps = true
1704 "#
1705 )]
1706 pub no_deps: Option<bool>,
1707 #[option(
1709 default = "None",
1710 value_type = "list[str]",
1711 example = r#"
1712 group = ["dev", "docs"]
1713 "#
1714 )]
1715 pub group: Option<Vec<PipGroupName>>,
1716 #[option(
1719 default = "false",
1720 value_type = "bool",
1721 example = r#"
1722 allow-empty-requirements = true
1723 "#
1724 )]
1725 pub allow_empty_requirements: Option<bool>,
1726 #[option(
1731 default = "\"highest\"",
1732 value_type = "str",
1733 example = r#"
1734 resolution = "lowest-direct"
1735 "#,
1736 possible_values = true
1737 )]
1738 pub resolution: Option<ResolutionMode>,
1739 #[option(
1745 default = "\"if-necessary\"",
1746 value_type = "str",
1747 example = r#"
1748 prerelease = "allow"
1749 "#,
1750 possible_values = true
1751 )]
1752 pub prerelease: Option<PrereleaseMode>,
1753 #[serde(skip)]
1754 #[cfg_attr(feature = "schemars", schemars(skip))]
1755 pub prerelease_package: Option<PrereleasePackage>,
1756 #[option(
1767 default = "\"requires-python\"",
1768 value_type = "str",
1769 example = r#"
1770 fork-strategy = "fewest"
1771 "#,
1772 possible_values = true
1773 )]
1774 pub fork_strategy: Option<ForkStrategy>,
1775 #[option(
1789 default = r#"[]"#,
1790 value_type = "list[dict]",
1791 example = r#"
1792 dependency-metadata = [
1793 { name = "flask", version = "1.0.0", requires-dist = ["werkzeug"], requires-python = ">=3.6" },
1794 ]
1795 "#
1796 )]
1797 pub dependency_metadata: Option<Vec<StaticMetadata>>,
1798 #[option(
1803 default = "None",
1804 value_type = "str",
1805 example = r#"
1806 output-file = "requirements.txt"
1807 "#
1808 )]
1809 pub output_file: Option<PathBuf>,
1810 #[option(
1816 default = "false",
1817 value_type = "bool",
1818 example = r#"
1819 no-strip-extras = true
1820 "#
1821 )]
1822 pub no_strip_extras: Option<bool>,
1823 #[option(
1828 default = "false",
1829 value_type = "bool",
1830 example = r#"
1831 no-strip-markers = true
1832 "#
1833 )]
1834 pub no_strip_markers: Option<bool>,
1835 #[option(
1838 default = "false",
1839 value_type = "bool",
1840 example = r#"
1841 no-annotate = true
1842 "#
1843 )]
1844 pub no_annotate: Option<bool>,
1845 #[option(
1847 default = r#"false"#,
1848 value_type = "bool",
1849 example = r#"
1850 no-header = true
1851 "#
1852 )]
1853 pub no_header: Option<bool>,
1854 #[option(
1858 default = "None",
1859 value_type = "str",
1860 example = r#"
1861 custom-compile-command = "./custom-uv-compile.sh"
1862 "#
1863 )]
1864 pub custom_compile_command: Option<String>,
1865 #[option(
1867 default = "false",
1868 value_type = "bool",
1869 example = r#"
1870 generate-hashes = true
1871 "#
1872 )]
1873 pub generate_hashes: Option<bool>,
1874 #[option(
1877 default = "{}",
1878 value_type = "dict",
1879 example = r#"
1880 config-settings = { editable_mode = "compat" }
1881 "#
1882 )]
1883 pub config_settings: Option<ConfigSettings>,
1884 #[option(
1887 default = "{}",
1888 value_type = "dict",
1889 example = r#"
1890 config-settings-package = { numpy = { editable_mode = "compat" } }
1891 "#
1892 )]
1893 pub config_settings_package: Option<PackageConfigSettings>,
1894 #[option(
1900 default = "None",
1901 value_type = "str",
1902 example = r#"
1903 python-version = "3.8"
1904 "#
1905 )]
1906 pub python_version: Option<PythonVersion>,
1907 #[option(
1913 default = "None",
1914 value_type = "str",
1915 example = r#"
1916 python-platform = "x86_64-unknown-linux-gnu"
1917 "#
1918 )]
1919 pub python_platform: Option<TargetTriple>,
1920 #[option(
1928 default = "false",
1929 value_type = "bool",
1930 example = r#"
1931 universal = true
1932 "#
1933 )]
1934 pub universal: Option<bool>,
1935 #[option(
1950 default = "None",
1951 value_type = "str | false",
1952 example = r#"
1953 exclude-newer = "2006-12-02T02:07:43Z"
1954 "#
1955 )]
1956 pub exclude_newer: Option<ExcludeNewerOverride>,
1957 #[option(
1970 default = "None",
1971 value_type = "dict",
1972 example = r#"
1973 exclude-newer-package = { tqdm = "2022-04-04T00:00:00Z", markupsafe = false }
1974 "#
1975 )]
1976 pub exclude_newer_package: Option<ExcludeNewerPackage>,
1977 #[option(
1980 default = "[]",
1981 value_type = "list[str]",
1982 example = r#"
1983 no-emit-package = ["ruff"]
1984 "#
1985 )]
1986 pub no_emit_package: Option<Vec<PackageName>>,
1987 #[option(
1989 default = "false",
1990 value_type = "bool",
1991 example = r#"
1992 emit-index-url = true
1993 "#
1994 )]
1995 pub emit_index_url: Option<bool>,
1996 #[option(
1998 default = "false",
1999 value_type = "bool",
2000 example = r#"
2001 emit-find-links = true
2002 "#
2003 )]
2004 pub emit_find_links: Option<bool>,
2005 #[option(
2007 default = "false",
2008 value_type = "bool",
2009 example = r#"
2010 emit-build-options = true
2011 "#
2012 )]
2013 pub emit_build_options: Option<bool>,
2014 #[option(
2021 default = "false",
2022 value_type = "bool",
2023 example = r#"
2024 emit-marker-expression = true
2025 "#
2026 )]
2027 pub emit_marker_expression: Option<bool>,
2028 #[option(
2031 default = "false",
2032 value_type = "bool",
2033 example = r#"
2034 emit-index-annotation = true
2035 "#
2036 )]
2037 pub emit_index_annotation: Option<bool>,
2038 #[option(
2041 default = "\"split\"",
2042 value_type = "str",
2043 example = r#"
2044 annotation-style = "line"
2045 "#,
2046 possible_values = true
2047 )]
2048 pub annotation_style: Option<AnnotationStyle>,
2049 #[option(
2059 default = "\"clone\" (macOS, Linux) or \"hardlink\" (Windows)",
2060 value_type = "str",
2061 example = r#"
2062 link-mode = "copy"
2063 "#,
2064 possible_values = true
2065 )]
2066 pub link_mode: Option<LinkMode>,
2067 #[option(
2078 default = "false",
2079 value_type = "bool",
2080 example = r#"
2081 compile-bytecode = true
2082 "#
2083 )]
2084 pub compile_bytecode: Option<bool>,
2085 #[option(
2098 default = "false",
2099 value_type = "bool",
2100 example = r#"
2101 require-hashes = true
2102 "#
2103 )]
2104 pub require_hashes: Option<bool>,
2105 #[option(
2111 default = "true",
2112 value_type = "bool",
2113 example = r#"
2114 verify-hashes = true
2115 "#
2116 )]
2117 pub verify_hashes: Option<bool>,
2118 #[option(
2122 default = "false",
2123 value_type = "bool",
2124 example = r#"
2125 no-sources = true
2126 "#
2127 )]
2128 pub no_sources: Option<bool>,
2129 #[option(
2131 default = "[]",
2132 value_type = "list[str]",
2133 example = r#"
2134 no-sources-package = ["ruff"]
2135 "#
2136 )]
2137 pub no_sources_package: Option<Vec<PackageName>>,
2138 #[option(
2140 default = "false",
2141 value_type = "bool",
2142 example = r#"
2143 upgrade = true
2144 "#
2145 )]
2146 pub upgrade: Option<bool>,
2147 #[option(
2152 default = "[]",
2153 value_type = "list[str]",
2154 example = r#"
2155 upgrade-package = ["ruff"]
2156 "#
2157 )]
2158 pub upgrade_package: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2159 #[option(
2161 default = "false",
2162 value_type = "bool",
2163 example = r#"
2164 reinstall = true
2165 "#
2166 )]
2167 pub reinstall: Option<bool>,
2168 #[option(
2171 default = "[]",
2172 value_type = "list[str]",
2173 example = r#"
2174 reinstall-package = ["ruff"]
2175 "#
2176 )]
2177 pub reinstall_package: Option<Vec<PackageName>>,
2178 #[option(
2193 default = "null",
2194 value_type = "str",
2195 example = r#"
2196 torch-backend = "auto"
2197 "#
2198 )]
2199 pub torch_backend: Option<TorchMode>,
2200}
2201
2202impl PipOptions {
2203 fn relative_to(mut self, root_dir: &Path) -> Result<Self, IndexUrlError> {
2205 rebase_indexes(
2206 root_dir,
2207 &mut self.index,
2208 &mut self.index_url,
2209 &mut self.extra_index_url,
2210 &mut self.find_links,
2211 )?;
2212
2213 Ok(self)
2214 }
2215}
2216
2217impl From<ResolverInstallerSchema> for ResolverOptions {
2218 fn from(value: ResolverInstallerSchema) -> Self {
2219 Self {
2220 indexes: IndexOptions {
2221 index: value.index,
2222 index_url: value.index_url,
2223 extra_index_url: value.extra_index_url,
2224 no_index: value.no_index,
2225 find_links: value.find_links,
2226 },
2227 index_strategy: value.index_strategy,
2228 keyring_provider: value.keyring_provider,
2229 resolution: value.resolution,
2230 prerelease: value.prerelease,
2231 prerelease_package: value.prerelease_package,
2232 fork_strategy: value.fork_strategy,
2233 dependency_metadata: value.dependency_metadata,
2234 config_settings: value.config_settings,
2235 config_settings_package: value.config_settings_package,
2236 exclude_newer: value.exclude_newer,
2237 exclude_newer_package: value.exclude_newer_package,
2238 link_mode: value.link_mode,
2239 upgrade: Upgrade::from_args(
2240 value.upgrade,
2241 value
2242 .upgrade_package
2243 .into_iter()
2244 .flatten()
2245 .map(Into::into)
2246 .collect(),
2247 Vec::new(),
2248 ),
2249 no_build: value.no_build,
2250 no_build_package: value.no_build_package,
2251 no_binary: value.no_binary,
2252 no_binary_package: value.no_binary_package,
2253 build_isolation: BuildIsolation::from_args(
2254 value.no_build_isolation,
2255 value.no_build_isolation_package.unwrap_or_default(),
2256 ),
2257 extra_build_dependencies: value.extra_build_dependencies,
2258 extra_build_variables: value.extra_build_variables,
2259 no_sources: value.no_sources,
2260 no_sources_package: value.no_sources_package,
2261 torch_backend: value.torch_backend,
2262 }
2263 }
2264}
2265
2266impl From<ResolverInstallerSchema> for InstallerOptions {
2267 fn from(value: ResolverInstallerSchema) -> Self {
2268 Self {
2269 index: value.index,
2270 index_url: value.index_url,
2271 extra_index_url: value.extra_index_url,
2272 no_index: value.no_index,
2273 find_links: value.find_links,
2274 index_strategy: value.index_strategy,
2275 keyring_provider: value.keyring_provider,
2276 config_settings: value.config_settings,
2277 exclude_newer: value.exclude_newer,
2278 link_mode: value.link_mode,
2279 compile_bytecode: value.compile_bytecode,
2280 reinstall: Reinstall::from_args(
2281 value.reinstall,
2282 value.reinstall_package.unwrap_or_default(),
2283 ),
2284 build_isolation: BuildIsolation::from_args(
2285 value.no_build_isolation,
2286 value.no_build_isolation_package.unwrap_or_default(),
2287 ),
2288 no_build: value.no_build,
2289 no_build_package: value.no_build_package,
2290 no_binary: value.no_binary,
2291 no_binary_package: value.no_binary_package,
2292 no_sources: value.no_sources,
2293 no_sources_package: value.no_sources_package,
2294 }
2295 }
2296}
2297
2298#[derive(
2303 Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, CombineOptions, OptionsMetadata,
2304)]
2305#[serde(deny_unknown_fields, rename_all = "kebab-case")]
2306#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2307pub struct ToolOptions {
2308 index: Option<Vec<Index>>,
2309 index_url: Option<PipIndex>,
2310 extra_index_url: Option<Vec<PipExtraIndex>>,
2311 no_index: Option<bool>,
2312 find_links: Option<Vec<PipFindLinks>>,
2313 index_strategy: Option<IndexStrategy>,
2314 keyring_provider: Option<KeyringProviderType>,
2315 resolution: Option<ResolutionMode>,
2316 prerelease: Option<PrereleaseMode>,
2317 prerelease_package: Option<PrereleasePackage>,
2318 fork_strategy: Option<ForkStrategy>,
2319 dependency_metadata: Option<Vec<StaticMetadata>>,
2320 config_settings: Option<ConfigSettings>,
2321 config_settings_package: Option<PackageConfigSettings>,
2322 build_isolation: Option<BuildIsolation>,
2323 extra_build_dependencies: Option<ExtraBuildDependencies>,
2324 extra_build_variables: Option<ExtraBuildVariables>,
2325 exclude_newer: Option<ExcludeNewerOverride>,
2326 exclude_newer_package: Option<ExcludeNewerPackage>,
2327 link_mode: Option<LinkMode>,
2328 compile_bytecode: Option<bool>,
2329 no_sources: Option<bool>,
2330 no_sources_package: Option<Vec<PackageName>>,
2331 no_build: Option<bool>,
2332 no_build_package: Option<Vec<PackageName>>,
2333 no_binary: Option<bool>,
2334 no_binary_package: Option<Vec<PackageName>>,
2335 torch_backend: Option<TorchMode>,
2336}
2337
2338#[derive(Debug, Clone, Default, Serialize, Deserialize)]
2340#[serde(deny_unknown_fields, rename_all = "kebab-case")]
2341pub struct ToolOptionsWire {
2342 index: Option<Vec<Index>>,
2343 index_url: Option<PipIndex>,
2344 extra_index_url: Option<Vec<PipExtraIndex>>,
2345 no_index: Option<bool>,
2346 find_links: Option<Vec<PipFindLinks>>,
2347 index_strategy: Option<IndexStrategy>,
2348 keyring_provider: Option<KeyringProviderType>,
2349 resolution: Option<ResolutionMode>,
2350 prerelease: Option<PrereleaseMode>,
2351 prerelease_package: Option<PrereleasePackage>,
2352 fork_strategy: Option<ForkStrategy>,
2353 dependency_metadata: Option<Vec<StaticMetadata>>,
2354 config_settings: Option<ConfigSettings>,
2355 config_settings_package: Option<PackageConfigSettings>,
2356 build_isolation: Option<BuildIsolation>,
2357 extra_build_dependencies: Option<ExtraBuildDependencies>,
2358 extra_build_variables: Option<ExtraBuildVariables>,
2359 exclude_newer: Option<ExcludeNewerOverride>,
2360 exclude_newer_span: Option<ExcludeNewerSpan>,
2361 #[serde(serialize_with = "serialize_exclude_newer_package_with_spans")]
2362 exclude_newer_package: Option<ExcludeNewerPackage>,
2363 link_mode: Option<LinkMode>,
2364 compile_bytecode: Option<bool>,
2365 no_sources: Option<bool>,
2366 no_sources_package: Option<Vec<PackageName>>,
2367 no_build: Option<bool>,
2368 no_build_package: Option<Vec<PackageName>>,
2369 no_binary: Option<bool>,
2370 no_binary_package: Option<Vec<PackageName>>,
2371 torch_backend: Option<TorchMode>,
2372}
2373
2374impl From<ResolverInstallerOptions> for ToolOptions {
2375 fn from(value: ResolverInstallerOptions) -> Self {
2376 Self {
2377 index: value.indexes.index.map(|indexes| {
2378 indexes
2379 .into_iter()
2380 .map(Index::with_promoted_auth_policy)
2381 .collect()
2382 }),
2383 index_url: value.indexes.index_url,
2384 extra_index_url: value.indexes.extra_index_url,
2385 no_index: value.indexes.no_index,
2386 find_links: value.indexes.find_links,
2387 index_strategy: value.index_strategy,
2388 keyring_provider: value.keyring_provider,
2389 resolution: value.resolution,
2390 prerelease: value.prerelease,
2391 prerelease_package: value.prerelease_package,
2392 fork_strategy: value.fork_strategy,
2393 dependency_metadata: value.dependency_metadata,
2394 config_settings: value.config_settings,
2395 config_settings_package: value.config_settings_package,
2396 build_isolation: value.build_isolation,
2397 extra_build_dependencies: value.extra_build_dependencies,
2398 extra_build_variables: value.extra_build_variables,
2399 exclude_newer: value.exclude_newer,
2400 exclude_newer_package: value.exclude_newer_package,
2401 link_mode: value.link_mode,
2402 compile_bytecode: value.compile_bytecode,
2403 no_sources: value.no_sources,
2404 no_sources_package: value.no_sources_package,
2405 no_build: value.no_build,
2406 no_build_package: value.no_build_package,
2407 no_binary: value.no_binary,
2408 no_binary_package: value.no_binary_package,
2409 torch_backend: value.torch_backend,
2410 }
2411 }
2412}
2413
2414impl From<ToolOptionsWire> for ToolOptions {
2415 fn from(value: ToolOptionsWire) -> Self {
2416 let exclude_newer = value
2417 .exclude_newer
2418 .map(|exclude_newer| match exclude_newer {
2419 ExcludeNewerOverride::Disabled => ExcludeNewerOverride::Disabled,
2420 ExcludeNewerOverride::Enabled(exclude_newer) => {
2421 let exclude_newer = *exclude_newer;
2422 if let Some(span) = value.exclude_newer_span
2423 && exclude_newer.span().is_none()
2424 {
2425 ExcludeNewerValue::relative(span).into()
2426 } else {
2427 exclude_newer.into()
2428 }
2429 }
2430 });
2431
2432 Self {
2433 index: value.index,
2434 index_url: value.index_url,
2435 extra_index_url: value.extra_index_url,
2436 no_index: value.no_index,
2437 find_links: value.find_links,
2438 index_strategy: value.index_strategy,
2439 keyring_provider: value.keyring_provider,
2440 resolution: value.resolution,
2441 prerelease: value.prerelease,
2442 prerelease_package: value.prerelease_package,
2443 fork_strategy: value.fork_strategy,
2444 dependency_metadata: value.dependency_metadata,
2445 config_settings: value.config_settings,
2446 config_settings_package: value.config_settings_package,
2447 build_isolation: value.build_isolation,
2448 extra_build_dependencies: value.extra_build_dependencies,
2449 extra_build_variables: value.extra_build_variables,
2450 exclude_newer,
2451 exclude_newer_package: value.exclude_newer_package,
2452 link_mode: value.link_mode,
2453 compile_bytecode: value.compile_bytecode,
2454 no_sources: value.no_sources,
2455 no_sources_package: value.no_sources_package,
2456 no_build: value.no_build,
2457 no_build_package: value.no_build_package,
2458 no_binary: value.no_binary,
2459 no_binary_package: value.no_binary_package,
2460 torch_backend: value.torch_backend,
2461 }
2462 }
2463}
2464
2465impl From<ToolOptions> for ToolOptionsWire {
2466 fn from(value: ToolOptions) -> Self {
2467 let (exclude_newer, exclude_newer_span) = match &value.exclude_newer {
2468 Some(ExcludeNewerOverride::Disabled) => (Some(ExcludeNewerOverride::Disabled), None),
2469 Some(ExcludeNewerOverride::Enabled(value)) => match value.as_ref() {
2470 ExcludeNewerValue::Absolute(_) => {
2471 (Some(ExcludeNewerOverride::Enabled(value.clone())), None)
2472 }
2473 ExcludeNewerValue::Relative(span) => (
2474 Some(ExcludeNewerValue::absolute(value.timestamp()).into()),
2475 Some(*span),
2476 ),
2477 },
2478 None => (None, None),
2479 };
2480
2481 Self {
2482 index: value.index,
2483 index_url: value.index_url,
2484 extra_index_url: value.extra_index_url,
2485 no_index: value.no_index,
2486 find_links: value.find_links,
2487 index_strategy: value.index_strategy,
2488 keyring_provider: value.keyring_provider,
2489 resolution: value.resolution,
2490 prerelease: value.prerelease,
2491 prerelease_package: value.prerelease_package,
2492 fork_strategy: value.fork_strategy,
2493 dependency_metadata: value.dependency_metadata,
2494 config_settings: value.config_settings,
2495 config_settings_package: value.config_settings_package,
2496 build_isolation: value.build_isolation,
2497 extra_build_dependencies: value.extra_build_dependencies,
2498 extra_build_variables: value.extra_build_variables,
2499 exclude_newer,
2500 exclude_newer_span,
2501 exclude_newer_package: value.exclude_newer_package,
2502 link_mode: value.link_mode,
2503 compile_bytecode: value.compile_bytecode,
2504 no_sources: value.no_sources,
2505 no_sources_package: value.no_sources_package,
2506 no_build: value.no_build,
2507 no_build_package: value.no_build_package,
2508 no_binary: value.no_binary,
2509 no_binary_package: value.no_binary_package,
2510 torch_backend: value.torch_backend,
2511 }
2512 }
2513}
2514
2515impl From<ToolOptions> for ResolverInstallerOptions {
2516 fn from(value: ToolOptions) -> Self {
2517 Self {
2518 indexes: IndexOptions {
2519 index: value.index,
2520 index_url: value.index_url,
2521 extra_index_url: value.extra_index_url,
2522 no_index: value.no_index,
2523 find_links: value.find_links,
2524 },
2525 index_strategy: value.index_strategy,
2526 keyring_provider: value.keyring_provider,
2527 resolution: value.resolution,
2528 prerelease: value.prerelease,
2529 prerelease_package: value.prerelease_package,
2530 fork_strategy: value.fork_strategy,
2531 dependency_metadata: value.dependency_metadata,
2532 config_settings: value.config_settings,
2533 config_settings_package: value.config_settings_package,
2534 build_isolation: value.build_isolation,
2535 extra_build_dependencies: value.extra_build_dependencies,
2536 extra_build_variables: value.extra_build_variables,
2537 exclude_newer: value.exclude_newer,
2538 exclude_newer_package: value.exclude_newer_package,
2539 link_mode: value.link_mode,
2540 compile_bytecode: value.compile_bytecode,
2541 no_sources: value.no_sources,
2542 no_sources_package: value.no_sources_package,
2543 upgrade: None,
2544 reinstall: None,
2545 no_build: value.no_build,
2546 no_build_package: value.no_build_package,
2547 no_binary: value.no_binary,
2548 no_binary_package: value.no_binary_package,
2549 torch_backend: value.torch_backend,
2550 }
2551 }
2552}
2553
2554#[derive(Debug, Clone, Default, Deserialize)]
2557#[serde(rename_all = "kebab-case", deny_unknown_fields)]
2558struct OptionsWire {
2559 required_version: Option<RequiredVersion>,
2562 system_certs: Option<bool>,
2563 native_tls: Option<bool>,
2564 offline: Option<bool>,
2565 no_cache: Option<bool>,
2566 cache_dir: Option<PathBuf>,
2567 preview: Option<bool>,
2568 preview_features: Option<PreviewFeaturesOption>,
2569 python_preference: Option<PythonPreference>,
2570 python_downloads: Option<PythonDownloads>,
2571 concurrent_downloads: Option<NonZeroUsize>,
2572 concurrent_builds: Option<NonZeroUsize>,
2573 concurrent_installs: Option<NonZeroUsize>,
2574
2575 index: Option<Vec<Index>>,
2578 index_url: Option<PipIndex>,
2579 extra_index_url: Option<Vec<PipExtraIndex>>,
2580 no_index: Option<bool>,
2581 find_links: Option<Vec<PipFindLinks>>,
2582 index_strategy: Option<IndexStrategy>,
2583 keyring_provider: Option<KeyringProviderType>,
2584 http_proxy: Option<ProxyUrl>,
2585 https_proxy: Option<ProxyUrl>,
2586 no_proxy: Option<Vec<String>>,
2587 allow_insecure_host: Option<Vec<TrustedHost>>,
2588 resolution: Option<ResolutionMode>,
2589 prerelease: Option<PrereleaseMode>,
2590 prerelease_package: Option<PrereleasePackage>,
2591 fork_strategy: Option<ForkStrategy>,
2592 dependency_metadata: Option<Vec<StaticMetadata>>,
2593 config_settings: Option<ConfigSettings>,
2594 config_settings_package: Option<PackageConfigSettings>,
2595 no_build_isolation: Option<bool>,
2596 no_build_isolation_package: Option<Vec<PackageName>>,
2597 extra_build_dependencies: Option<ExtraBuildDependencies>,
2598 extra_build_variables: Option<ExtraBuildVariables>,
2599 exclude_newer: Option<ExcludeNewerOverride>,
2600 exclude_newer_package: Option<ExcludeNewerPackage>,
2601 link_mode: Option<LinkMode>,
2602 compile_bytecode: Option<bool>,
2603 no_sources: Option<bool>,
2604 no_sources_package: Option<Vec<PackageName>>,
2605 upgrade: Option<bool>,
2606 upgrade_package: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2607 reinstall: Option<bool>,
2608 reinstall_package: Option<Vec<PackageName>>,
2609 no_build: Option<bool>,
2610 no_build_package: Option<Vec<PackageName>>,
2611 no_binary: Option<bool>,
2612 no_binary_package: Option<Vec<PackageName>>,
2613 torch_backend: Option<TorchMode>,
2614
2615 python_install_mirror: Option<String>,
2618 pypy_install_mirror: Option<String>,
2619 python_downloads_json_url: Option<String>,
2620
2621 publish_url: Option<DisplaySafeUrl>,
2624 trusted_publishing: Option<TrustedPublishing>,
2625 check_url: Option<IndexUrl>,
2626
2627 add_bounds: Option<AddBoundsKind>,
2630
2631 audit: Option<AuditOptions>,
2632 pip: Option<PipOptions>,
2633 cache_keys: Option<Vec<CacheKey>>,
2634
2635 override_dependencies: Option<Vec<OverrideDependency>>,
2639 exclude_dependencies: Option<Vec<ExcludeDependency>>,
2640 constraint_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2641 build_constraint_dependencies: Option<Vec<BuildConstraintDependency>>,
2642 environments: Option<SupportedEnvironments>,
2643 required_environments: Option<SupportedEnvironments>,
2644 minimum_libc_version: Option<MinimumLibcVersion>,
2645
2646 conflicts: Option<serde::de::IgnoredAny>,
2650 workspace: Option<serde::de::IgnoredAny>,
2651 sources: Option<serde::de::IgnoredAny>,
2652 managed: Option<serde::de::IgnoredAny>,
2653 r#package: Option<serde::de::IgnoredAny>,
2654 default_groups: Option<serde::de::IgnoredAny>,
2655 dependency_groups: Option<serde::de::IgnoredAny>,
2656 dev_dependencies: Option<serde::de::IgnoredAny>,
2657
2658 build_backend: Option<serde::de::IgnoredAny>,
2660}
2661
2662impl TryFrom<OptionsWire> for Options {
2663 type Error = &'static str;
2664
2665 #[allow(deprecated)]
2666 fn try_from(value: OptionsWire) -> Result<Self, Self::Error> {
2667 let OptionsWire {
2668 required_version,
2669 system_certs,
2670 native_tls,
2671 offline,
2672 no_cache,
2673 cache_dir,
2674 preview,
2675 preview_features,
2676 python_preference,
2677 python_downloads,
2678 python_install_mirror,
2679 pypy_install_mirror,
2680 python_downloads_json_url,
2681 concurrent_downloads,
2682 concurrent_builds,
2683 concurrent_installs,
2684 index,
2685 index_url,
2686 extra_index_url,
2687 no_index,
2688 find_links,
2689 index_strategy,
2690 keyring_provider,
2691 http_proxy,
2692 https_proxy,
2693 no_proxy,
2694 allow_insecure_host,
2695 resolution,
2696 prerelease,
2697 prerelease_package,
2698 fork_strategy,
2699 dependency_metadata,
2700 config_settings,
2701 config_settings_package,
2702 no_build_isolation,
2703 no_build_isolation_package,
2704 exclude_newer,
2705 exclude_newer_package,
2706 link_mode,
2707 compile_bytecode,
2708 no_sources,
2709 no_sources_package,
2710 upgrade,
2711 upgrade_package,
2712 reinstall,
2713 reinstall_package,
2714 no_build,
2715 no_build_package,
2716 no_binary,
2717 no_binary_package,
2718 torch_backend,
2719 audit,
2720 pip,
2721 cache_keys,
2722 override_dependencies,
2723 exclude_dependencies,
2724 constraint_dependencies,
2725 build_constraint_dependencies,
2726 environments,
2727 required_environments,
2728 minimum_libc_version,
2729 conflicts,
2730 publish_url,
2731 trusted_publishing,
2732 check_url,
2733 workspace,
2734 sources,
2735 default_groups,
2736 dependency_groups,
2737 extra_build_dependencies,
2738 extra_build_variables,
2739 dev_dependencies,
2740 managed,
2741 package,
2742 add_bounds: bounds,
2743 build_backend,
2745 } = value;
2746
2747 Ok(Self {
2748 globals: GlobalOptions {
2749 required_version,
2750 system_certs,
2751 native_tls,
2752 offline,
2753 no_cache,
2754 cache_dir,
2755 preview: PreviewOption::try_from(preview, preview_features)?,
2756 python_preference,
2757 python_downloads,
2758 concurrent_downloads,
2759 concurrent_builds,
2760 concurrent_installs,
2761 http_proxy,
2762 https_proxy,
2763 no_proxy,
2764 allow_insecure_host: allow_insecure_host.clone(),
2766 },
2767 top_level: ResolverInstallerSchema {
2768 index,
2769 index_url,
2770 extra_index_url,
2771 no_index,
2772 find_links,
2773 index_strategy,
2774 keyring_provider,
2775 resolution,
2776 prerelease,
2777 prerelease_package,
2778 fork_strategy,
2779 dependency_metadata,
2780 config_settings,
2781 config_settings_package,
2782 no_build_isolation,
2783 no_build_isolation_package,
2784 extra_build_dependencies,
2785 extra_build_variables,
2786 exclude_newer,
2787 exclude_newer_package,
2788 link_mode,
2789 compile_bytecode,
2790 no_sources,
2791 no_sources_package,
2792 upgrade,
2793 upgrade_package,
2794 reinstall,
2795 reinstall_package,
2796 no_build,
2797 no_build_package,
2798 no_binary,
2799 no_binary_package,
2800 torch_backend,
2801 },
2802 pip,
2803 cache_keys,
2804 build_backend,
2805 override_dependencies,
2806 exclude_dependencies,
2807 constraint_dependencies,
2808 build_constraint_dependencies,
2809 environments,
2810 required_environments,
2811 minimum_libc_version,
2812 install_mirrors: PythonInstallMirrors {
2813 python_install_mirror,
2814 pypy_install_mirror,
2815 python_downloads_json_url,
2816 },
2817 conflicts,
2818 publish: PublishOptions {
2819 publish_url,
2820 trusted_publishing,
2821 check_url,
2822 },
2823 add: AddOptions { add_bounds: bounds },
2824 audit,
2825 workspace,
2826 sources,
2827 dev_dependencies,
2828 default_groups,
2829 dependency_groups,
2830 managed,
2831 package,
2832 })
2833 }
2834}
2835
2836#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
2837#[serde(rename_all = "kebab-case")]
2838#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2839pub struct PublishOptions {
2840 #[option(
2843 default = "\"https://upload.pypi.org/legacy/\"",
2844 value_type = "str",
2845 example = r#"
2846 publish-url = "https://test.pypi.org/legacy/"
2847 "#
2848 )]
2849 pub publish_url: Option<DisplaySafeUrl>,
2850
2851 #[option(
2858 default = "automatic",
2859 value_type = "str",
2860 example = r#"
2861 trusted-publishing = "always"
2862 "#
2863 )]
2864 pub trusted_publishing: Option<TrustedPublishing>,
2865
2866 #[option(
2880 default = "None",
2881 value_type = "str",
2882 example = r#"
2883 check-url = "https://test.pypi.org/simple"
2884 "#
2885 )]
2886 pub check_url: Option<IndexUrl>,
2887}
2888
2889#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
2890#[serde(rename_all = "kebab-case")]
2891#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2892pub struct AddOptions {
2893 #[option(
2904 default = "\"lower\"",
2905 value_type = "str",
2906 example = r#"
2907 add-bounds = "major"
2908 "#,
2909 possible_values = true
2910 )]
2911 pub add_bounds: Option<AddBoundsKind>,
2912}
2913
2914#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
2915#[serde(rename_all = "kebab-case")]
2916#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2917pub struct AuditOptions {
2918 #[option(
2920 default = "false",
2921 value_type = "bool",
2922 example = r#"
2923 malware-check = true
2924 "#
2925 )]
2926 pub malware_check: Option<bool>,
2927
2928 #[option(
2930 default = "\"https://api.osv.dev/\"",
2931 value_type = "str",
2932 example = r#"
2933 malware-check-url = "https://example.com"
2934 "#
2935 )]
2936 pub malware_check_url: Option<DisplaySafeUrl>,
2937
2938 #[option(
2943 default = "[]",
2944 value_type = "list[str]",
2945 example = r#"
2946 ignore = ["PYSEC-2022-43017", "GHSA-5239-wwwm-4pmq"]
2947 "#
2948 )]
2949 pub ignore: Option<Vec<String>>,
2950
2951 #[option(
2957 default = "[]",
2958 value_type = "list[str]",
2959 example = r#"
2960 ignore-until-fixed = ["PYSEC-2022-43017"]
2961 "#
2962 )]
2963 pub ignore_until_fixed: Option<Vec<String>>,
2964}
2965
2966#[derive(Debug, Clone)]
2967pub struct MalwareCheckSettings {
2968 pub enabled: bool,
2970 pub malware_check_url: Option<DisplaySafeUrl>,
2972}
2973
2974impl MalwareCheckSettings {
2975 pub fn resolve(
2976 filesystem: Option<&FilesystemOptions>,
2977 environment: &EnvironmentOptions,
2978 ) -> Self {
2979 let audit = filesystem.and_then(|options| options.audit.as_ref());
2980
2981 Self {
2982 enabled: environment
2983 .malware_check
2984 .value
2985 .or(audit.and_then(|audit| audit.malware_check))
2986 .unwrap_or_default(),
2987 malware_check_url: environment
2988 .malware_check_url
2989 .clone()
2990 .or_else(|| audit.and_then(|audit| audit.malware_check_url.clone())),
2991 }
2992 }
2993}
2994
2995#[derive(Debug, Clone)]
2997#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2998#[cfg_attr(feature = "schemars", schemars(untagged))]
2999pub enum PreviewFeaturesOption {
3000 Toggle(bool),
3001 Features(Vec<MaybePreviewFeature>),
3002}
3003
3004impl<'de> Deserialize<'de> for PreviewFeaturesOption {
3007 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
3008 where
3009 D: serde::Deserializer<'de>,
3010 {
3011 serde_untagged::UntaggedEnumVisitor::new()
3012 .expecting("a boolean or a list of preview feature names")
3013 .bool(|value| Ok(Self::Toggle(value)))
3014 .seq(|sequence| sequence.deserialize().map(Self::Features))
3015 .deserialize(deserializer)
3016 }
3017}
3018
3019#[expect(
3020 dead_code,
3021 reason = "Fields are only used by the OptionsMetadata and JsonSchema derives"
3022)]
3023#[derive(OptionsMetadata)]
3024#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3025#[cfg_attr(feature = "schemars", schemars(rename_all = "kebab-case"))]
3026struct PreviewOptionsDefinition {
3027 #[deprecated(note = "use `preview-features` instead")]
3033 preview: Option<bool>,
3034 #[option(
3038 default = "false",
3039 value_type = "bool | list[str]",
3040 example = r#"
3041 preview-features = true
3042 # or
3043 preview-features = ["json-output"]
3044 "#
3045 )]
3046 preview_features: Option<PreviewFeaturesOption>,
3047}
3048
3049#[derive(Debug, Clone)]
3051pub enum PreviewOption {
3052 Preview(bool),
3054 PreviewFeatures(PreviewFeaturesOption),
3056}
3057
3058impl uv_options_metadata::OptionsMetadata for PreviewOption {
3059 fn record(visit: &mut dyn uv_options_metadata::Visit) {
3060 <PreviewOptionsDefinition as uv_options_metadata::OptionsMetadata>::record(visit);
3061 }
3062}
3063
3064#[cfg(feature = "schemars")]
3065struct ConflictingPreviewOptions;
3066
3067#[cfg(feature = "schemars")]
3068impl schemars::JsonSchema for ConflictingPreviewOptions {
3069 fn schema_name() -> Cow<'static, str> {
3070 Cow::Borrowed("ConflictingPreviewOptions")
3071 }
3072
3073 fn json_schema(_generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
3074 schemars::json_schema!({
3075 "type": "object",
3076 "properties": {
3077 "preview": {},
3078 "preview-features": {},
3079 },
3080 "required": ["preview", "preview-features"],
3081 })
3082 }
3083}
3084
3085#[cfg(feature = "schemars")]
3086impl schemars::JsonSchema for PreviewOption {
3087 fn schema_name() -> Cow<'static, str> {
3088 Cow::Borrowed("PreviewOption")
3089 }
3090
3091 fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
3092 let mut schema = <PreviewOptionsDefinition as schemars::JsonSchema>::json_schema(generator);
3093 schema.insert(
3096 "not".to_string(),
3097 generator
3098 .subschema_for::<ConflictingPreviewOptions>()
3099 .into(),
3100 );
3101 schema
3102 }
3103}
3104
3105impl PreviewOption {
3106 fn try_from(
3107 preview: Option<bool>,
3108 preview_features: Option<PreviewFeaturesOption>,
3109 ) -> Result<Option<Self>, &'static str> {
3110 match (preview, preview_features) {
3111 (Some(_), Some(_)) => Err("cannot specify both `preview` and `preview-features`"),
3112 (Some(b), None) => Ok(Some(Self::Preview(b))),
3113 (None, Some(features)) => Ok(Some(Self::PreviewFeatures(features))),
3114 (None, None) => Ok(None),
3115 }
3116 }
3117
3118 pub fn resolve(&self) -> Preview {
3120 use PreviewFeaturesOption::{Features, Toggle};
3121
3122 match self {
3123 Self::Preview(false) | Self::PreviewFeatures(Toggle(false)) => Preview::default(),
3124 Self::Preview(true) | Self::PreviewFeatures(Toggle(true)) => Preview::all(),
3125 Self::PreviewFeatures(Features(features)) => Preview::from_feature_names(features),
3126 }
3127 }
3128}