1#[cfg(feature = "schemars")]
2use std::borrow::Cow;
3use std::{
4 fmt::{self, Debug},
5 num::NonZeroUsize,
6 path::Path,
7 path::PathBuf,
8};
9
10use serde::de::{Error, SeqAccess, Visitor, value::SeqAccessDeserializer};
11use serde::{Deserialize, Deserializer, Serialize};
12
13use uv_cache_info::CacheKey;
14use uv_configuration::{
15 AddBoundsKind, AnnotationStyle, BuildIsolation, ExcludeDependency, ExcludeNewerPackage,
16 ForkStrategy, IndexStrategy, KeyringProviderType, PackageNameSpecifier, PrereleaseMode,
17 PrereleasePackage, ProxyUrl, Reinstall, RequiredVersion, ResolutionMode, TargetTriple,
18 TrustedHost, TrustedPublishing, Upgrade, serialize_exclude_newer_package_with_spans,
19};
20use uv_distribution_types::{
21 ConfigSettings, ExcludeNewerOverride, ExcludeNewerSpan, ExcludeNewerValue, ExtraBuildVariables,
22 Index, IndexLocations, IndexUrl, IndexUrlError, MinimumLibcVersion, Origin,
23 PackageConfigSettings, PipExtraIndex, PipFindLinks, PipIndex, StaticMetadata,
24};
25use uv_install_wheel::LinkMode;
26use uv_macros::{CombineOptions, OptionsMetadata};
27use uv_normalize::{ExtraName, PackageName, PipGroupName};
28use uv_pep508::Requirement;
29use uv_preview::{MaybePreviewFeature, Preview};
30use uv_pypi_types::{SupportedEnvironments, VerbatimParsedUrl};
31use uv_python_types::{PythonDownloadMirrors, PythonDownloads, PythonPreference, PythonVersion};
32use uv_redacted::DisplaySafeUrl;
33use uv_torch::TorchMode;
34use uv_workspace::pyproject::{
35 BuildConstraintDependency, ExtraBuildDependencies, OverrideDependency,
36};
37
38use crate::{EnvironmentOptions, FilesystemOptions};
39
40#[allow(dead_code)]
42#[derive(Debug, Clone, Default, Deserialize)]
43pub(crate) struct PyProjectToml {
44 pub(crate) tool: Option<Tools>,
45}
46
47#[allow(dead_code)]
49#[derive(Debug, Clone, Default, Deserialize)]
50pub(crate) struct Tools {
51 pub(crate) uv: Option<Options>,
52}
53
54#[derive(Debug, Clone, Default, Deserialize)]
56pub(crate) struct PyProjectRequiredVersionToml {
57 pub(crate) tool: Option<RequiredVersionTools>,
58}
59
60#[derive(Debug, Clone, Default, Deserialize)]
62pub(crate) struct RequiredVersionTools {
63 pub(crate) uv: Option<RequiredVersionOptions>,
64}
65
66#[derive(Debug, Clone, Default, Deserialize)]
68#[serde(rename_all = "kebab-case")]
69pub(crate) struct RequiredVersionOptions {
70 pub(crate) required_version: Option<RequiredVersion>,
71}
72
73#[derive(Debug, Clone, Default, Deserialize)]
75#[serde(rename_all = "kebab-case")]
76pub(crate) struct UvRequiredVersionToml {
77 pub(crate) required_version: Option<RequiredVersion>,
78}
79
80#[allow(dead_code)]
82#[derive(Debug, Clone, Default, Deserialize, CombineOptions, OptionsMetadata)]
83#[serde(try_from = "OptionsWire", rename_all = "kebab-case")]
84#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
85#[cfg_attr(feature = "schemars", schemars(!try_from))]
86pub struct Options {
87 #[serde(flatten)]
88 pub globals: GlobalOptions,
89
90 #[serde(flatten)]
91 pub top_level: ResolverInstallerSchema,
92
93 #[serde(flatten)]
94 pub install_mirrors: PythonInstallMirrors,
95
96 #[serde(flatten)]
97 pub publish: PublishOptions,
98
99 #[serde(flatten)]
100 pub add: AddOptions,
101
102 #[option_group]
103 pub audit: Option<AuditOptions>,
104
105 #[option_group]
106 pub pip: Option<PipOptions>,
107
108 #[option(
144 default = r#"[{ file = "pyproject.toml" }, { file = "setup.py" }, { file = "setup.cfg" }]"#,
145 value_type = "list[dict]",
146 example = r#"
147 cache-keys = [{ file = "pyproject.toml" }, { file = "requirements.txt" }, { git = { commit = true } }]
148 "#
149 )]
150 pub cache_keys: Option<Vec<CacheKey>>,
151
152 #[cfg_attr(feature = "schemars", schemars(skip))]
156 pub override_dependencies: Option<Vec<OverrideDependency>>,
157
158 #[cfg_attr(feature = "schemars", schemars(skip))]
159 pub exclude_dependencies: Option<Vec<ExcludeDependency>>,
160
161 #[cfg_attr(feature = "schemars", schemars(skip))]
162 pub constraint_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
163
164 #[cfg_attr(feature = "schemars", schemars(skip))]
165 pub build_constraint_dependencies: Option<Vec<BuildConstraintDependency>>,
166
167 #[cfg_attr(feature = "schemars", schemars(skip))]
168 pub environments: Option<SupportedEnvironments>,
169
170 #[cfg_attr(feature = "schemars", schemars(skip))]
171 pub required_environments: Option<SupportedEnvironments>,
172
173 #[cfg_attr(feature = "schemars", schemars(skip))]
174 pub minimum_libc_version: Option<MinimumLibcVersion>,
175
176 #[cfg_attr(feature = "schemars", schemars(skip))]
180 pub(crate) conflicts: Option<serde::de::IgnoredAny>,
181
182 #[cfg_attr(feature = "schemars", schemars(skip))]
183 pub(crate) workspace: Option<serde::de::IgnoredAny>,
184
185 #[cfg_attr(feature = "schemars", schemars(skip))]
186 pub(crate) sources: Option<serde::de::IgnoredAny>,
187
188 #[cfg_attr(feature = "schemars", schemars(skip))]
189 pub(crate) dev_dependencies: Option<serde::de::IgnoredAny>,
190
191 #[cfg_attr(feature = "schemars", schemars(skip))]
192 pub(crate) default_groups: Option<serde::de::IgnoredAny>,
193
194 #[cfg_attr(feature = "schemars", schemars(skip))]
195 pub(crate) dependency_groups: Option<serde::de::IgnoredAny>,
196
197 #[cfg_attr(feature = "schemars", schemars(skip))]
198 pub(crate) managed: Option<serde::de::IgnoredAny>,
199
200 #[cfg_attr(feature = "schemars", schemars(skip))]
201 pub(crate) r#package: Option<serde::de::IgnoredAny>,
202
203 #[cfg_attr(feature = "schemars", schemars(skip))]
204 pub(crate) build_backend: Option<serde::de::IgnoredAny>,
205}
206
207impl Options {
208 pub fn simple(globals: GlobalOptions, top_level: ResolverInstallerSchema) -> Self {
210 Self {
211 globals,
212 top_level,
213 ..Default::default()
214 }
215 }
216
217 #[must_use]
219 pub(crate) fn with_origin(mut self, origin: Origin) -> Self {
220 if let Some(indexes) = &mut self.top_level.index {
221 for index in indexes {
222 index.origin.get_or_insert(origin);
223 }
224 }
225 if let Some(index_url) = &mut self.top_level.index_url {
226 index_url.try_set_origin(origin);
227 }
228 if let Some(extra_index_urls) = &mut self.top_level.extra_index_url {
229 for index_url in extra_index_urls {
230 index_url.try_set_origin(origin);
231 }
232 }
233 if let Some(pip) = &mut self.pip {
234 if let Some(indexes) = &mut pip.index {
235 for index in indexes {
236 index.origin.get_or_insert(origin);
237 }
238 }
239 if let Some(index_url) = &mut pip.index_url {
240 index_url.try_set_origin(origin);
241 }
242 if let Some(extra_index_urls) = &mut pip.extra_index_url {
243 for index_url in extra_index_urls {
244 index_url.try_set_origin(origin);
245 }
246 }
247 }
248 self
249 }
250
251 pub(crate) fn relative_to(self, root_dir: &Path) -> Result<Self, IndexUrlError> {
253 Ok(Self {
254 top_level: self.top_level.relative_to(root_dir)?,
255 pip: self.pip.map(|pip| pip.relative_to(root_dir)).transpose()?,
256 ..self
257 })
258 }
259}
260
261#[derive(Debug, Clone, Default, Deserialize, CombineOptions, OptionsMetadata)]
263#[serde(try_from = "GlobalOptionsWire", rename_all = "kebab-case")]
264#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
265#[cfg_attr(feature = "schemars", schemars(!try_from))]
266pub struct GlobalOptions {
267 #[option(
274 default = "null",
275 value_type = "str",
276 example = r#"
277 required-version = ">=0.5.0"
278 "#
279 )]
280 pub required_version: Option<RequiredVersion>,
281 #[option(
286 default = "false",
287 value_type = "bool",
288 uv_toml_only = true,
289 example = r#"
290 system-certs = true
291 "#
292 )]
293 pub system_certs: Option<bool>,
294 #[deprecated(note = "use `system-certs` instead")]
301 #[option(
302 default = "false",
303 value_type = "bool",
304 uv_toml_only = true,
305 example = r#"
306 native-tls = true
307 "#
308 )]
309 pub native_tls: Option<bool>,
310 #[option(
312 default = "false",
313 value_type = "bool",
314 example = r#"
315 offline = true
316 "#
317 )]
318 pub offline: Option<bool>,
319 #[option(
322 default = "false",
323 value_type = "bool",
324 example = r#"
325 no-cache = true
326 "#
327 )]
328 pub no_cache: Option<bool>,
329 #[option(
334 default = "None",
335 value_type = "str",
336 uv_toml_only = true,
337 example = r#"
338 cache-dir = "./.uv_cache"
339 "#
340 )]
341 pub cache_dir: Option<PathBuf>,
342
343 #[serde(flatten)]
345 pub preview: Option<PreviewOption>,
346
347 #[option(
350 default = "\"managed\"",
351 value_type = "str",
352 example = r#"
353 python-preference = "managed"
354 "#,
355 possible_values = true
356 )]
357 pub python_preference: Option<PythonPreference>,
358 #[option(
360 default = "\"automatic\"",
361 value_type = "str",
362 example = r#"
363 python-downloads = "manual"
364 "#,
365 possible_values = true
366 )]
367 pub python_downloads: Option<PythonDownloads>,
368 #[option(
371 default = "50",
372 value_type = "int",
373 example = r#"
374 concurrent-downloads = 4
375 "#
376 )]
377 pub concurrent_downloads: Option<NonZeroUsize>,
378 #[option(
383 default = "None",
384 value_type = "int",
385 example = r#"
386 concurrent-builds = 4
387 "#
388 )]
389 pub concurrent_builds: Option<NonZeroUsize>,
390 #[option(
394 default = "None",
395 value_type = "int",
396 example = r#"
397 concurrent-installs = 4
398 "#
399 )]
400 pub concurrent_installs: Option<NonZeroUsize>,
401 #[option(
403 default = "None",
404 value_type = "str",
405 uv_toml_only = true,
406 example = r#"
407 http-proxy = "http://proxy.example.com"
408 "#
409 )]
410 pub http_proxy: Option<ProxyUrl>,
411 #[option(
413 default = "None",
414 value_type = "str",
415 uv_toml_only = true,
416 example = r#"
417 https-proxy = "https://proxy.example.com"
418 "#
419 )]
420 pub https_proxy: Option<ProxyUrl>,
421 #[option(
423 default = "None",
424 value_type = "list[str]",
425 uv_toml_only = true,
426 example = r#"
427 no-proxy = ["localhost", "127.0.0.1"]
428 "#
429 )]
430 pub no_proxy: Option<Vec<String>>,
431 #[option(
440 default = "[]",
441 value_type = "list[str]",
442 example = r#"
443 allow-insecure-host = ["localhost:8080"]
444 "#
445 )]
446 pub allow_insecure_host: Option<Vec<TrustedHost>>,
447}
448
449#[derive(Debug, Clone, Default, Deserialize)]
452#[serde(rename_all = "kebab-case")]
453struct GlobalOptionsWire {
454 required_version: Option<RequiredVersion>,
455 system_certs: Option<bool>,
456 native_tls: Option<bool>,
457 offline: Option<bool>,
458 no_cache: Option<bool>,
459 cache_dir: Option<PathBuf>,
460
461 preview: Option<bool>,
462 preview_features: Option<PreviewFeaturesOption>,
463
464 python_preference: Option<PythonPreference>,
465 python_downloads: Option<PythonDownloads>,
466 concurrent_downloads: Option<NonZeroUsize>,
467 concurrent_builds: Option<NonZeroUsize>,
468 concurrent_installs: Option<NonZeroUsize>,
469 http_proxy: Option<ProxyUrl>,
470 https_proxy: Option<ProxyUrl>,
471 no_proxy: Option<Vec<String>>,
472 allow_insecure_host: Option<Vec<TrustedHost>>,
473}
474
475impl TryFrom<GlobalOptionsWire> for GlobalOptions {
476 type Error = &'static str;
477
478 #[allow(deprecated)]
479 fn try_from(value: GlobalOptionsWire) -> Result<Self, Self::Error> {
480 let GlobalOptionsWire {
481 required_version,
482 system_certs,
483 native_tls,
484 offline,
485 no_cache,
486 cache_dir,
487 preview,
488 preview_features,
489 python_preference,
490 python_downloads,
491 concurrent_downloads,
492 concurrent_builds,
493 concurrent_installs,
494 http_proxy,
495 https_proxy,
496 no_proxy,
497 allow_insecure_host,
498 } = value;
499
500 Ok(Self {
501 required_version,
502 system_certs,
503 native_tls,
504 offline,
505 no_cache,
506 cache_dir,
507 preview: PreviewOption::try_from(preview, preview_features)?,
508 python_preference,
509 python_downloads,
510 concurrent_downloads,
511 concurrent_builds,
512 concurrent_installs,
513 http_proxy,
514 https_proxy,
515 no_proxy,
516 allow_insecure_host,
517 })
518 }
519}
520
521fn rebase_indexes(
523 root_dir: &Path,
524 indexes: &mut Option<Vec<Index>>,
525 index_url: &mut Option<PipIndex>,
526 extra_index_urls: &mut Option<Vec<PipExtraIndex>>,
527 find_links: &mut Option<Vec<PipFindLinks>>,
528) -> Result<(), IndexUrlError> {
529 *indexes = indexes
530 .take()
531 .map(|indexes| {
532 indexes
533 .into_iter()
534 .map(|index| index.relative_to(root_dir))
535 .collect::<Result<Vec<_>, _>>()
536 })
537 .transpose()?;
538 *index_url = index_url
539 .take()
540 .map(|index| index.relative_to(root_dir))
541 .transpose()?;
542 *extra_index_urls = extra_index_urls
543 .take()
544 .map(|indexes| {
545 indexes
546 .into_iter()
547 .map(|index| index.relative_to(root_dir))
548 .collect::<Result<Vec<_>, _>>()
549 })
550 .transpose()?;
551 *find_links = find_links
552 .take()
553 .map(|find_links| {
554 find_links
555 .into_iter()
556 .map(|find_link| find_link.relative_to(root_dir))
557 .collect::<Result<Vec<_>, _>>()
558 })
559 .transpose()?;
560
561 Ok(())
562}
563
564#[derive(Debug, Clone, Default, CombineOptions)]
566pub struct InstallerOptions {
567 index: Option<Vec<Index>>,
568 index_url: Option<PipIndex>,
569 extra_index_url: Option<Vec<PipExtraIndex>>,
570 no_index: Option<bool>,
571 find_links: Option<Vec<PipFindLinks>>,
572 index_strategy: Option<IndexStrategy>,
573 keyring_provider: Option<KeyringProviderType>,
574 config_settings: Option<ConfigSettings>,
575 exclude_newer: Option<ExcludeNewerOverride>,
576 link_mode: Option<LinkMode>,
577 compile_bytecode: Option<bool>,
578 reinstall: Option<Reinstall>,
579 build_isolation: Option<BuildIsolation>,
580 no_build: Option<bool>,
581 no_build_package: Option<Vec<PackageName>>,
582 no_binary: Option<bool>,
583 no_binary_package: Option<Vec<PackageName>>,
584 no_sources: Option<bool>,
585 no_sources_package: Option<Vec<PackageName>>,
586}
587
588#[derive(Debug, Clone, Default, CombineOptions)]
590pub struct IndexOptions {
591 pub index: Option<Vec<Index>>,
592 pub index_url: Option<PipIndex>,
593 pub extra_index_url: Option<Vec<PipExtraIndex>>,
594 pub no_index: Option<bool>,
595 pub find_links: Option<Vec<PipFindLinks>>,
596}
597
598impl IndexOptions {
599 pub fn relative_to(mut self, root_dir: &Path) -> Result<Self, IndexUrlError> {
601 rebase_indexes(
602 root_dir,
603 &mut self.index,
604 &mut self.index_url,
605 &mut self.extra_index_url,
606 &mut self.find_links,
607 )?;
608
609 Ok(self)
610 }
611}
612
613impl From<IndexOptions> for IndexLocations {
614 fn from(value: IndexOptions) -> Self {
615 let IndexOptions {
616 index,
617 index_url,
618 extra_index_url,
619 no_index,
620 find_links,
621 } = value;
622
623 Self::new(
624 index
625 .into_iter()
626 .flatten()
627 .chain(extra_index_url.into_iter().flatten().map(Index::from))
628 .chain(index_url.into_iter().map(Index::from))
629 .collect(),
630 find_links.into_iter().flatten().map(Index::from).collect(),
631 no_index.unwrap_or_default(),
632 )
633 }
634}
635
636impl From<IndexOptions> for PipOptions {
637 fn from(value: IndexOptions) -> Self {
638 let IndexOptions {
639 index,
640 index_url,
641 extra_index_url,
642 no_index,
643 find_links,
644 } = value;
645
646 Self {
647 index,
648 index_url,
649 extra_index_url,
650 no_index,
651 find_links,
652 ..Self::default()
653 }
654 }
655}
656
657#[derive(Debug, Clone, Default, CombineOptions)]
659pub struct ResolverOptions {
660 pub indexes: IndexOptions,
661 pub index_strategy: Option<IndexStrategy>,
662 pub keyring_provider: Option<KeyringProviderType>,
663 pub resolution: Option<ResolutionMode>,
664 pub prerelease: Option<PrereleaseMode>,
665 pub prerelease_package: Option<PrereleasePackage>,
666 pub fork_strategy: Option<ForkStrategy>,
667 pub dependency_metadata: Option<Vec<StaticMetadata>>,
668 pub config_settings: Option<ConfigSettings>,
669 pub config_settings_package: Option<PackageConfigSettings>,
670 pub exclude_newer: Option<ExcludeNewerOverride>,
671 pub exclude_newer_package: Option<ExcludeNewerPackage>,
672 pub link_mode: Option<LinkMode>,
673 pub torch_backend: Option<TorchMode>,
674 pub upgrade: Option<Upgrade>,
675 pub require_build_hashes: Option<bool>,
676 pub build_isolation: Option<BuildIsolation>,
677 pub no_build: Option<bool>,
678 pub no_build_package: Option<Vec<PackageName>>,
679 pub no_binary: Option<bool>,
680 pub no_binary_package: Option<Vec<PackageName>>,
681 pub extra_build_dependencies: Option<ExtraBuildDependencies>,
682 pub extra_build_variables: Option<ExtraBuildVariables>,
683 pub no_sources: Option<bool>,
684 pub no_sources_package: Option<Vec<PackageName>>,
685}
686
687impl ResolverOptions {
688 pub fn relative_to(mut self, root_dir: &Path) -> Result<Self, IndexUrlError> {
690 self.indexes = self.indexes.relative_to(root_dir)?;
691 Ok(self)
692 }
693}
694
695#[derive(Debug, Clone, Default, CombineOptions)]
698pub struct ResolverInstallerOptions {
699 pub indexes: IndexOptions,
700 pub index_strategy: Option<IndexStrategy>,
701 pub keyring_provider: Option<KeyringProviderType>,
702 pub resolution: Option<ResolutionMode>,
703 pub prerelease: Option<PrereleaseMode>,
704 pub prerelease_package: Option<PrereleasePackage>,
705 pub fork_strategy: Option<ForkStrategy>,
706 pub dependency_metadata: Option<Vec<StaticMetadata>>,
707 pub config_settings: Option<ConfigSettings>,
708 pub config_settings_package: Option<PackageConfigSettings>,
709 pub require_build_hashes: Option<bool>,
710 pub build_isolation: Option<BuildIsolation>,
711 pub extra_build_dependencies: Option<ExtraBuildDependencies>,
712 pub extra_build_variables: Option<ExtraBuildVariables>,
713 pub exclude_newer: Option<ExcludeNewerOverride>,
714 pub exclude_newer_package: Option<ExcludeNewerPackage>,
715 pub link_mode: Option<LinkMode>,
716 pub torch_backend: Option<TorchMode>,
717 pub compile_bytecode: Option<bool>,
718 pub no_sources: Option<bool>,
719 pub no_sources_package: Option<Vec<PackageName>>,
720 pub upgrade: Option<Upgrade>,
721 pub reinstall: Option<Reinstall>,
722 pub no_build: Option<bool>,
723 pub no_build_package: Option<Vec<PackageName>>,
724 pub no_binary: Option<bool>,
725 pub no_binary_package: Option<Vec<PackageName>>,
726}
727
728impl ResolverInstallerOptions {
729 pub fn relative_to(mut self, root_dir: &Path) -> Result<Self, IndexUrlError> {
731 self.indexes = self.indexes.relative_to(root_dir)?;
732 Ok(self)
733 }
734}
735
736impl From<ResolverInstallerSchema> for ResolverInstallerOptions {
737 fn from(value: ResolverInstallerSchema) -> Self {
738 let ResolverInstallerSchema {
739 index,
740 index_url,
741 extra_index_url,
742 no_index,
743 find_links,
744 index_strategy,
745 keyring_provider,
746 resolution,
747 prerelease,
748 prerelease_package,
749 fork_strategy,
750 dependency_metadata,
751 config_settings,
752 config_settings_package,
753 require_build_hashes,
754 no_build_isolation,
755 no_build_isolation_package,
756 extra_build_dependencies,
757 extra_build_variables,
758 exclude_newer,
759 exclude_newer_package,
760 link_mode,
761 torch_backend,
762 compile_bytecode,
763 no_sources,
764 no_sources_package,
765 upgrade,
766 upgrade_package,
767 reinstall,
768 reinstall_package,
769 no_build,
770 no_build_package,
771 no_binary,
772 no_binary_package,
773 } = value;
774 Self {
775 indexes: IndexOptions {
776 index,
777 index_url,
778 extra_index_url,
779 no_index,
780 find_links,
781 },
782 index_strategy,
783 keyring_provider,
784 resolution,
785 prerelease,
786 prerelease_package,
787 fork_strategy,
788 dependency_metadata,
789 config_settings,
790 config_settings_package,
791 require_build_hashes,
792 build_isolation: BuildIsolation::from_args(
793 no_build_isolation,
794 no_build_isolation_package.into_iter().flatten().collect(),
795 ),
796 extra_build_dependencies,
797 extra_build_variables,
798 exclude_newer,
799 exclude_newer_package,
800 link_mode,
801 torch_backend,
802 compile_bytecode,
803 no_sources,
804 no_sources_package,
805 upgrade: Upgrade::from_args(
806 upgrade,
807 upgrade_package
808 .into_iter()
809 .flatten()
810 .map(Into::into)
811 .collect(),
812 Vec::new(),
813 ),
814 reinstall: Reinstall::from_args(reinstall, reinstall_package.unwrap_or_default()),
815 no_build,
816 no_build_package,
817 no_binary,
818 no_binary_package,
819 }
820 }
821}
822
823impl ResolverInstallerSchema {
824 fn relative_to(mut self, root_dir: &Path) -> Result<Self, IndexUrlError> {
826 rebase_indexes(
827 root_dir,
828 &mut self.index,
829 &mut self.index_url,
830 &mut self.extra_index_url,
831 &mut self.find_links,
832 )?;
833
834 Ok(self)
835 }
836}
837
838#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
840#[serde(rename_all = "kebab-case")]
841#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
842pub struct ResolverInstallerSchema {
843 #[option(
871 default = "\"[]\"",
872 value_type = "dict",
873 example = r#"
874 [[tool.uv.index]]
875 name = "pytorch"
876 url = "https://download.pytorch.org/whl/cu130"
877 "#
878 )]
879 pub index: Option<Vec<Index>>,
880 #[option(
890 default = "\"https://pypi.org/simple\"",
891 value_type = "str",
892 example = r#"
893 index-url = "https://test.pypi.org/simple"
894 "#
895 )]
896 pub index_url: Option<PipIndex>,
897 #[option(
911 default = "[]",
912 value_type = "list[str]",
913 example = r#"
914 extra-index-url = ["https://download.pytorch.org/whl/cpu"]
915 "#
916 )]
917 pub extra_index_url: Option<Vec<PipExtraIndex>>,
918 #[option(
921 default = "false",
922 value_type = "bool",
923 example = r#"
924 no-index = true
925 "#
926 )]
927 pub no_index: Option<bool>,
928 #[option(
937 default = "[]",
938 value_type = "list[str]",
939 example = r#"
940 find-links = ["https://download.pytorch.org/whl/torch_stable.html"]
941 "#
942 )]
943 pub find_links: Option<Vec<PipFindLinks>>,
944 #[option(
951 default = "\"first-index\"",
952 value_type = "str",
953 example = r#"
954 index-strategy = "unsafe-best-match"
955 "#,
956 possible_values = true
957 )]
958 pub index_strategy: Option<IndexStrategy>,
959 #[option(
964 default = "\"disabled\"",
965 value_type = "str",
966 example = r#"
967 keyring-provider = "subprocess"
968 "#
969 )]
970 pub keyring_provider: Option<KeyringProviderType>,
971 #[option(
976 default = "\"highest\"",
977 value_type = "str",
978 example = r#"
979 resolution = "lowest-direct"
980 "#,
981 possible_values = true
982 )]
983 pub resolution: Option<ResolutionMode>,
984 #[option(
990 default = "\"if-necessary\"",
991 value_type = "str",
992 example = r#"
993 prerelease = "allow"
994 "#,
995 possible_values = true
996 )]
997 pub prerelease: Option<PrereleaseMode>,
998 #[option(
1003 default = "{}",
1004 value_type = "dict",
1005 example = r#"
1006 prerelease-package = { numpy = "allow", scipy = "disallow" }
1007 "#
1008 )]
1009 pub prerelease_package: Option<PrereleasePackage>,
1010 #[option(
1021 default = "\"requires-python\"",
1022 value_type = "str",
1023 example = r#"
1024 fork-strategy = "fewest"
1025 "#,
1026 possible_values = true
1027 )]
1028 pub fork_strategy: Option<ForkStrategy>,
1029 #[option(
1043 default = r#"[]"#,
1044 value_type = "list[dict]",
1045 example = r#"
1046 dependency-metadata = [
1047 { name = "flask", version = "1.0.0", requires-dist = ["werkzeug"], requires-python = ">=3.6" },
1048 ]
1049 "#
1050 )]
1051 pub dependency_metadata: Option<Vec<StaticMetadata>>,
1052 #[option(
1055 default = "{}",
1056 value_type = "dict",
1057 example = r#"
1058 config-settings = { editable_mode = "compat" }
1059 "#
1060 )]
1061 pub config_settings: Option<ConfigSettings>,
1062 #[option(
1067 default = "{}",
1068 value_type = "dict",
1069 example = r#"
1070 config-settings-package = { numpy = { editable_mode = "compat" } }
1071 "#
1072 )]
1073 pub config_settings_package: Option<PackageConfigSettings>,
1074 #[option(
1079 default = "false",
1080 value_type = "bool",
1081 example = r#"
1082 no-build-isolation = true
1083 "#
1084 )]
1085 pub no_build_isolation: Option<bool>,
1086
1087 #[option(
1100 default = "false",
1101 value_type = "bool",
1102 example = "require-build-hashes = true"
1103 )]
1104 pub require_build_hashes: Option<bool>,
1105
1106 #[option(
1111 default = "[]",
1112 value_type = "list[str]",
1113 example = r#"
1114 no-build-isolation-package = ["package1", "package2"]
1115 "#
1116 )]
1117 pub no_build_isolation_package: Option<Vec<PackageName>>,
1118 #[option(
1124 default = "[]",
1125 value_type = "dict",
1126 example = r#"
1127 extra-build-dependencies = { pytest = ["setuptools"] }
1128 "#
1129 )]
1130 pub extra_build_dependencies: Option<ExtraBuildDependencies>,
1131 #[option(
1136 default = r#"{}"#,
1137 value_type = r#"dict[str, dict[str, str]]"#,
1138 example = r#"
1139 extra-build-variables = { flash-attn = { FLASH_ATTENTION_SKIP_CUDA_BUILD = "TRUE" } }
1140 "#
1141 )]
1142 pub extra_build_variables: Option<ExtraBuildVariables>,
1143 #[option(
1158 default = "None",
1159 value_type = "str | false",
1160 example = r#"
1161 exclude-newer = "2006-12-02T02:07:43Z"
1162 "#
1163 )]
1164 pub exclude_newer: Option<ExcludeNewerOverride>,
1165 #[option(
1179 default = "None",
1180 value_type = "dict",
1181 example = r#"
1182 exclude-newer-package = { tqdm = "2022-04-04T00:00:00Z", markupsafe = false }
1183 "#
1184 )]
1185 pub exclude_newer_package: Option<ExcludeNewerPackage>,
1186 #[option(
1196 default = "\"clone\" (macOS, Linux) or \"hardlink\" (Windows)",
1197 value_type = "str",
1198 example = r#"
1199 link-mode = "copy"
1200 "#,
1201 possible_values = true
1202 )]
1203 pub link_mode: Option<LinkMode>,
1204 #[option(
1215 default = "false",
1216 value_type = "bool",
1217 example = r#"
1218 compile-bytecode = true
1219 "#
1220 )]
1221 pub compile_bytecode: Option<bool>,
1222 #[option(
1226 default = "false",
1227 value_type = "bool",
1228 example = r#"
1229 no-sources = true
1230 "#
1231 )]
1232 pub no_sources: Option<bool>,
1233 #[option(
1235 default = "[]",
1236 value_type = "list[str]",
1237 example = r#"
1238 no-sources-package = ["ruff"]
1239 "#
1240 )]
1241 pub no_sources_package: Option<Vec<PackageName>>,
1242 #[option(
1244 default = "false",
1245 value_type = "bool",
1246 example = r#"
1247 upgrade = true
1248 "#
1249 )]
1250 pub upgrade: Option<bool>,
1251 #[option(
1256 default = "[]",
1257 value_type = "list[str]",
1258 example = r#"
1259 upgrade-package = ["ruff"]
1260 "#
1261 )]
1262 pub upgrade_package: Option<Vec<Requirement<VerbatimParsedUrl>>>,
1263 #[option(
1265 default = "false",
1266 value_type = "bool",
1267 example = r#"
1268 reinstall = true
1269 "#
1270 )]
1271 pub reinstall: Option<bool>,
1272 #[option(
1275 default = "[]",
1276 value_type = "list[str]",
1277 example = r#"
1278 reinstall-package = ["ruff"]
1279 "#
1280 )]
1281 pub reinstall_package: Option<Vec<PackageName>>,
1282 #[option(
1289 default = "false",
1290 value_type = "bool",
1291 example = r#"
1292 no-build = true
1293 "#
1294 )]
1295 pub no_build: Option<bool>,
1296 #[option(
1300 default = "[]",
1301 value_type = "list[str]",
1302 example = r#"
1303 no-build-package = ["ruff"]
1304 "#
1305 )]
1306 pub no_build_package: Option<Vec<PackageName>>,
1307 #[option(
1312 default = "false",
1313 value_type = "bool",
1314 example = r#"
1315 no-binary = true
1316 "#
1317 )]
1318 pub no_binary: Option<bool>,
1319 #[option(
1321 default = "[]",
1322 value_type = "list[str]",
1323 example = r#"
1324 no-binary-package = ["ruff"]
1325 "#
1326 )]
1327 pub no_binary_package: Option<Vec<PackageName>>,
1328 #[option(
1343 default = "null",
1344 value_type = "str",
1345 example = r#"
1346 torch-backend = "auto"
1347 "#
1348 )]
1349 pub torch_backend: Option<TorchMode>,
1350}
1351
1352#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
1354#[serde(rename_all = "kebab-case")]
1355#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1356pub struct PythonInstallMirrors {
1357 #[option(
1365 default = "None",
1366 value_type = "str",
1367 uv_toml_only = true,
1368 example = r#"
1369 python-install-mirror = "https://github.com/astral-sh/python-build-standalone/releases/download"
1370 "#
1371 )]
1372 pub python_install_mirror: Option<String>,
1373 #[option(
1382 default = "None",
1383 value_type = "str",
1384 uv_toml_only = true,
1385 example = r#"
1386 pypy-install-mirror = "https://downloads.python.org/pypy"
1387 "#
1388 )]
1389 pub pypy_install_mirror: Option<String>,
1390 #[option(
1398 default = "None",
1399 value_type = "str",
1400 uv_toml_only = true,
1401 example = r#"
1402 graalpy-install-mirror = "https://github.com/oracle/graalpython/releases/download"
1403 "#
1404 )]
1405 pub graalpy_install_mirror: Option<String>,
1406 #[option(
1414 default = "None",
1415 value_type = "str",
1416 uv_toml_only = true,
1417 example = r#"
1418 pyodide-install-mirror = "https://github.com/pyodide/pyodide/releases/download"
1419 "#
1420 )]
1421 pub pyodide_install_mirror: Option<String>,
1422
1423 #[option(
1425 default = "None",
1426 value_type = "str",
1427 uv_toml_only = true,
1428 example = r#"
1429 python-downloads-json-url = "/etc/uv/python-downloads.json"
1430 "#
1431 )]
1432 pub python_downloads_json_url: Option<String>,
1433}
1434
1435impl PythonInstallMirrors {
1436 pub fn mirrors(&self) -> PythonDownloadMirrors<'_> {
1438 PythonDownloadMirrors {
1439 cpython: self.python_install_mirror.as_deref(),
1440 pypy: self.pypy_install_mirror.as_deref(),
1441 graalpy: self.graalpy_install_mirror.as_deref(),
1442 pyodide: self.pyodide_install_mirror.as_deref(),
1443 }
1444 }
1445
1446 #[must_use]
1447 pub fn combine(self, other: Self) -> Self {
1448 Self {
1449 python_install_mirror: self.python_install_mirror.or(other.python_install_mirror),
1450 pypy_install_mirror: self.pypy_install_mirror.or(other.pypy_install_mirror),
1451 graalpy_install_mirror: self.graalpy_install_mirror.or(other.graalpy_install_mirror),
1452 pyodide_install_mirror: self.pyodide_install_mirror.or(other.pyodide_install_mirror),
1453 python_downloads_json_url: self
1454 .python_downloads_json_url
1455 .or(other.python_downloads_json_url),
1456 }
1457 }
1458}
1459
1460#[derive(Debug, Clone, Default, Deserialize, CombineOptions, OptionsMetadata)]
1465#[serde(deny_unknown_fields, rename_all = "kebab-case")]
1466#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1467pub struct PipOptions {
1468 #[option(
1481 default = "None",
1482 value_type = "str",
1483 example = r#"
1484 python = "3.10"
1485 "#
1486 )]
1487 pub python: Option<String>,
1488 #[option(
1497 default = "false",
1498 value_type = "bool",
1499 example = r#"
1500 system = true
1501 "#
1502 )]
1503 pub system: Option<bool>,
1504 #[option(
1511 default = "false",
1512 value_type = "bool",
1513 example = r#"
1514 break-system-packages = true
1515 "#
1516 )]
1517 pub break_system_packages: Option<bool>,
1518 #[option(
1521 default = "None",
1522 value_type = "str",
1523 example = r#"
1524 target = "./target"
1525 "#
1526 )]
1527 pub target: Option<PathBuf>,
1528 #[option(
1536 default = "None",
1537 value_type = "str",
1538 example = r#"
1539 prefix = "./prefix"
1540 "#
1541 )]
1542 pub prefix: Option<PathBuf>,
1543 #[serde(skip)]
1544 #[cfg_attr(feature = "schemars", schemars(skip))]
1545 pub index: Option<Vec<Index>>,
1546 #[option(
1554 default = "\"https://pypi.org/simple\"",
1555 value_type = "str",
1556 example = r#"
1557 index-url = "https://test.pypi.org/simple"
1558 "#
1559 )]
1560 pub index_url: Option<PipIndex>,
1561 #[option(
1572 default = "[]",
1573 value_type = "list[str]",
1574 example = r#"
1575 extra-index-url = ["https://download.pytorch.org/whl/cpu"]
1576 "#
1577 )]
1578 pub extra_index_url: Option<Vec<PipExtraIndex>>,
1579 #[option(
1582 default = "false",
1583 value_type = "bool",
1584 example = r#"
1585 no-index = true
1586 "#
1587 )]
1588 pub no_index: Option<bool>,
1589 #[option(
1598 default = "[]",
1599 value_type = "list[str]",
1600 example = r#"
1601 find-links = ["https://download.pytorch.org/whl/torch_stable.html"]
1602 "#
1603 )]
1604 pub find_links: Option<Vec<PipFindLinks>>,
1605 #[option(
1612 default = "\"first-index\"",
1613 value_type = "str",
1614 example = r#"
1615 index-strategy = "unsafe-best-match"
1616 "#,
1617 possible_values = true
1618 )]
1619 pub index_strategy: Option<IndexStrategy>,
1620 #[option(
1625 default = "disabled",
1626 value_type = "str",
1627 example = r#"
1628 keyring-provider = "subprocess"
1629 "#
1630 )]
1631 pub keyring_provider: Option<KeyringProviderType>,
1632 #[option(
1640 default = "false",
1641 value_type = "bool",
1642 example = r#"
1643 no-build = true
1644 "#
1645 )]
1646 pub no_build: Option<bool>,
1647 #[option(
1655 default = "[]",
1656 value_type = "list[str]",
1657 example = r#"
1658 no-binary = ["ruff"]
1659 "#
1660 )]
1661 pub no_binary: Option<Vec<PackageNameSpecifier>>,
1662 #[option(
1672 default = "[]",
1673 value_type = "list[str]",
1674 example = r#"
1675 only-binary = ["ruff"]
1676 "#
1677 )]
1678 pub only_binary: Option<Vec<PackageNameSpecifier>>,
1679 #[option(
1684 default = "false",
1685 value_type = "bool",
1686 example = r#"
1687 no-build-isolation = true
1688 "#
1689 )]
1690 pub no_build_isolation: Option<bool>,
1691 #[option(
1696 default = "false",
1697 value_type = "bool",
1698 example = r#"
1699 require-build-hashes = true
1700 "#
1701 )]
1702 pub require_build_hashes: Option<bool>,
1703 #[option(
1708 default = "[]",
1709 value_type = "list[str]",
1710 example = r#"
1711 no-build-isolation-package = ["package1", "package2"]
1712 "#
1713 )]
1714 pub no_build_isolation_package: Option<Vec<PackageName>>,
1715 #[option(
1721 default = "[]",
1722 value_type = "dict",
1723 example = r#"
1724 extra-build-dependencies = { pytest = ["setuptools"] }
1725 "#
1726 )]
1727 pub extra_build_dependencies: Option<ExtraBuildDependencies>,
1728 #[option(
1733 default = r#"{}"#,
1734 value_type = r#"dict[str, dict[str, str]]"#,
1735 example = r#"
1736 extra-build-variables = { flash-attn = { FLASH_ATTENTION_SKIP_CUDA_BUILD = "TRUE" } }
1737 "#
1738 )]
1739 pub extra_build_variables: Option<ExtraBuildVariables>,
1740 #[option(
1743 default = "false",
1744 value_type = "bool",
1745 example = r#"
1746 strict = true
1747 "#
1748 )]
1749 pub strict: Option<bool>,
1750 #[option(
1754 default = "[]",
1755 value_type = "list[str]",
1756 example = r#"
1757 extra = ["dev", "docs"]
1758 "#
1759 )]
1760 pub extra: Option<Vec<ExtraName>>,
1761 #[option(
1765 default = "false",
1766 value_type = "bool",
1767 example = r#"
1768 all-extras = true
1769 "#
1770 )]
1771 pub all_extras: Option<bool>,
1772 #[option(
1774 default = "[]",
1775 value_type = "list[str]",
1776 example = r#"
1777 all-extras = true
1778 no-extra = ["dev", "docs"]
1779 "#
1780 )]
1781 pub no_extra: Option<Vec<ExtraName>>,
1782 #[option(
1785 default = "false",
1786 value_type = "bool",
1787 example = r#"
1788 no-deps = true
1789 "#
1790 )]
1791 pub no_deps: Option<bool>,
1792 #[option(
1794 default = "None",
1795 value_type = "list[str]",
1796 example = r#"
1797 group = ["dev", "docs"]
1798 "#
1799 )]
1800 pub group: Option<Vec<PipGroupName>>,
1801 #[option(
1804 default = "false",
1805 value_type = "bool",
1806 example = r#"
1807 allow-empty-requirements = true
1808 "#
1809 )]
1810 pub allow_empty_requirements: Option<bool>,
1811 #[option(
1816 default = "\"highest\"",
1817 value_type = "str",
1818 example = r#"
1819 resolution = "lowest-direct"
1820 "#,
1821 possible_values = true
1822 )]
1823 pub resolution: Option<ResolutionMode>,
1824 #[option(
1830 default = "\"if-necessary\"",
1831 value_type = "str",
1832 example = r#"
1833 prerelease = "allow"
1834 "#,
1835 possible_values = true
1836 )]
1837 pub prerelease: Option<PrereleaseMode>,
1838 #[serde(skip)]
1839 #[cfg_attr(feature = "schemars", schemars(skip))]
1840 pub prerelease_package: Option<PrereleasePackage>,
1841 #[option(
1852 default = "\"requires-python\"",
1853 value_type = "str",
1854 example = r#"
1855 fork-strategy = "fewest"
1856 "#,
1857 possible_values = true
1858 )]
1859 pub fork_strategy: Option<ForkStrategy>,
1860 #[option(
1874 default = r#"[]"#,
1875 value_type = "list[dict]",
1876 example = r#"
1877 dependency-metadata = [
1878 { name = "flask", version = "1.0.0", requires-dist = ["werkzeug"], requires-python = ">=3.6" },
1879 ]
1880 "#
1881 )]
1882 pub dependency_metadata: Option<Vec<StaticMetadata>>,
1883 #[option(
1888 default = "None",
1889 value_type = "str",
1890 example = r#"
1891 output-file = "requirements.txt"
1892 "#
1893 )]
1894 pub output_file: Option<PathBuf>,
1895 #[option(
1901 default = "false",
1902 value_type = "bool",
1903 example = r#"
1904 no-strip-extras = true
1905 "#
1906 )]
1907 pub no_strip_extras: Option<bool>,
1908 #[option(
1913 default = "false",
1914 value_type = "bool",
1915 example = r#"
1916 no-strip-markers = true
1917 "#
1918 )]
1919 pub no_strip_markers: Option<bool>,
1920 #[option(
1923 default = "false",
1924 value_type = "bool",
1925 example = r#"
1926 no-annotate = true
1927 "#
1928 )]
1929 pub no_annotate: Option<bool>,
1930 #[option(
1932 default = r#"false"#,
1933 value_type = "bool",
1934 example = r#"
1935 no-header = true
1936 "#
1937 )]
1938 pub no_header: Option<bool>,
1939 #[option(
1943 default = "None",
1944 value_type = "str",
1945 example = r#"
1946 custom-compile-command = "./custom-uv-compile.sh"
1947 "#
1948 )]
1949 pub custom_compile_command: Option<String>,
1950 #[option(
1952 default = "false",
1953 value_type = "bool",
1954 example = r#"
1955 generate-hashes = true
1956 "#
1957 )]
1958 pub generate_hashes: Option<bool>,
1959 #[option(
1962 default = "{}",
1963 value_type = "dict",
1964 example = r#"
1965 config-settings = { editable_mode = "compat" }
1966 "#
1967 )]
1968 pub config_settings: Option<ConfigSettings>,
1969 #[option(
1972 default = "{}",
1973 value_type = "dict",
1974 example = r#"
1975 config-settings-package = { numpy = { editable_mode = "compat" } }
1976 "#
1977 )]
1978 pub config_settings_package: Option<PackageConfigSettings>,
1979 #[option(
1985 default = "None",
1986 value_type = "str",
1987 example = r#"
1988 python-version = "3.8"
1989 "#
1990 )]
1991 pub python_version: Option<PythonVersion>,
1992 #[option(
1998 default = "None",
1999 value_type = "str",
2000 example = r#"
2001 python-platform = "x86_64-unknown-linux-gnu"
2002 "#
2003 )]
2004 pub python_platform: Option<TargetTriple>,
2005 #[option(
2013 default = "false",
2014 value_type = "bool",
2015 example = r#"
2016 universal = true
2017 "#
2018 )]
2019 pub universal: Option<bool>,
2020 #[option(
2035 default = "None",
2036 value_type = "str | false",
2037 example = r#"
2038 exclude-newer = "2006-12-02T02:07:43Z"
2039 "#
2040 )]
2041 pub exclude_newer: Option<ExcludeNewerOverride>,
2042 #[option(
2055 default = "None",
2056 value_type = "dict",
2057 example = r#"
2058 exclude-newer-package = { tqdm = "2022-04-04T00:00:00Z", markupsafe = false }
2059 "#
2060 )]
2061 pub exclude_newer_package: Option<ExcludeNewerPackage>,
2062 #[option(
2065 default = "[]",
2066 value_type = "list[str]",
2067 example = r#"
2068 no-emit-package = ["ruff"]
2069 "#
2070 )]
2071 pub no_emit_package: Option<Vec<PackageName>>,
2072 #[option(
2074 default = "false",
2075 value_type = "bool",
2076 example = r#"
2077 emit-index-url = true
2078 "#
2079 )]
2080 pub emit_index_url: Option<bool>,
2081 #[option(
2083 default = "false",
2084 value_type = "bool",
2085 example = r#"
2086 emit-find-links = true
2087 "#
2088 )]
2089 pub emit_find_links: Option<bool>,
2090 #[option(
2092 default = "false",
2093 value_type = "bool",
2094 example = r#"
2095 emit-build-options = true
2096 "#
2097 )]
2098 pub emit_build_options: Option<bool>,
2099 #[option(
2106 default = "false",
2107 value_type = "bool",
2108 example = r#"
2109 emit-marker-expression = true
2110 "#
2111 )]
2112 pub emit_marker_expression: Option<bool>,
2113 #[option(
2116 default = "false",
2117 value_type = "bool",
2118 example = r#"
2119 emit-index-annotation = true
2120 "#
2121 )]
2122 pub emit_index_annotation: Option<bool>,
2123 #[option(
2126 default = "\"split\"",
2127 value_type = "str",
2128 example = r#"
2129 annotation-style = "line"
2130 "#,
2131 possible_values = true
2132 )]
2133 pub annotation_style: Option<AnnotationStyle>,
2134 #[option(
2144 default = "\"clone\" (macOS, Linux) or \"hardlink\" (Windows)",
2145 value_type = "str",
2146 example = r#"
2147 link-mode = "copy"
2148 "#,
2149 possible_values = true
2150 )]
2151 pub link_mode: Option<LinkMode>,
2152 #[option(
2163 default = "false",
2164 value_type = "bool",
2165 example = r#"
2166 compile-bytecode = true
2167 "#
2168 )]
2169 pub compile_bytecode: Option<bool>,
2170 #[option(
2183 default = "false",
2184 value_type = "bool",
2185 example = r#"
2186 require-hashes = true
2187 "#
2188 )]
2189 pub require_hashes: Option<bool>,
2190 #[option(
2196 default = "true",
2197 value_type = "bool",
2198 example = r#"
2199 verify-hashes = true
2200 "#
2201 )]
2202 pub verify_hashes: Option<bool>,
2203 #[option(
2207 default = "false",
2208 value_type = "bool",
2209 example = r#"
2210 no-sources = true
2211 "#
2212 )]
2213 pub no_sources: Option<bool>,
2214 #[option(
2216 default = "[]",
2217 value_type = "list[str]",
2218 example = r#"
2219 no-sources-package = ["ruff"]
2220 "#
2221 )]
2222 pub no_sources_package: Option<Vec<PackageName>>,
2223 #[option(
2225 default = "false",
2226 value_type = "bool",
2227 example = r#"
2228 upgrade = true
2229 "#
2230 )]
2231 pub upgrade: Option<bool>,
2232 #[option(
2237 default = "[]",
2238 value_type = "list[str]",
2239 example = r#"
2240 upgrade-package = ["ruff"]
2241 "#
2242 )]
2243 pub upgrade_package: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2244 #[option(
2246 default = "false",
2247 value_type = "bool",
2248 example = r#"
2249 reinstall = true
2250 "#
2251 )]
2252 pub reinstall: Option<bool>,
2253 #[option(
2256 default = "[]",
2257 value_type = "list[str]",
2258 example = r#"
2259 reinstall-package = ["ruff"]
2260 "#
2261 )]
2262 pub reinstall_package: Option<Vec<PackageName>>,
2263 #[option(
2278 default = "null",
2279 value_type = "str",
2280 example = r#"
2281 torch-backend = "auto"
2282 "#
2283 )]
2284 pub torch_backend: Option<TorchMode>,
2285}
2286
2287impl PipOptions {
2288 fn relative_to(mut self, root_dir: &Path) -> Result<Self, IndexUrlError> {
2290 rebase_indexes(
2291 root_dir,
2292 &mut self.index,
2293 &mut self.index_url,
2294 &mut self.extra_index_url,
2295 &mut self.find_links,
2296 )?;
2297
2298 Ok(self)
2299 }
2300}
2301
2302impl From<ResolverInstallerSchema> for ResolverOptions {
2303 fn from(value: ResolverInstallerSchema) -> Self {
2304 Self {
2305 indexes: IndexOptions {
2306 index: value.index,
2307 index_url: value.index_url,
2308 extra_index_url: value.extra_index_url,
2309 no_index: value.no_index,
2310 find_links: value.find_links,
2311 },
2312 index_strategy: value.index_strategy,
2313 keyring_provider: value.keyring_provider,
2314 resolution: value.resolution,
2315 prerelease: value.prerelease,
2316 prerelease_package: value.prerelease_package,
2317 fork_strategy: value.fork_strategy,
2318 dependency_metadata: value.dependency_metadata,
2319 config_settings: value.config_settings,
2320 config_settings_package: value.config_settings_package,
2321 require_build_hashes: value.require_build_hashes,
2322 exclude_newer: value.exclude_newer,
2323 exclude_newer_package: value.exclude_newer_package,
2324 link_mode: value.link_mode,
2325 upgrade: Upgrade::from_args(
2326 value.upgrade,
2327 value
2328 .upgrade_package
2329 .into_iter()
2330 .flatten()
2331 .map(Into::into)
2332 .collect(),
2333 Vec::new(),
2334 ),
2335 no_build: value.no_build,
2336 no_build_package: value.no_build_package,
2337 no_binary: value.no_binary,
2338 no_binary_package: value.no_binary_package,
2339 build_isolation: BuildIsolation::from_args(
2340 value.no_build_isolation,
2341 value.no_build_isolation_package.unwrap_or_default(),
2342 ),
2343 extra_build_dependencies: value.extra_build_dependencies,
2344 extra_build_variables: value.extra_build_variables,
2345 no_sources: value.no_sources,
2346 no_sources_package: value.no_sources_package,
2347 torch_backend: value.torch_backend,
2348 }
2349 }
2350}
2351
2352impl From<ResolverInstallerSchema> for InstallerOptions {
2353 fn from(value: ResolverInstallerSchema) -> Self {
2354 Self {
2355 index: value.index,
2356 index_url: value.index_url,
2357 extra_index_url: value.extra_index_url,
2358 no_index: value.no_index,
2359 find_links: value.find_links,
2360 index_strategy: value.index_strategy,
2361 keyring_provider: value.keyring_provider,
2362 config_settings: value.config_settings,
2363 exclude_newer: value.exclude_newer,
2364 link_mode: value.link_mode,
2365 compile_bytecode: value.compile_bytecode,
2366 reinstall: Reinstall::from_args(
2367 value.reinstall,
2368 value.reinstall_package.unwrap_or_default(),
2369 ),
2370 build_isolation: BuildIsolation::from_args(
2371 value.no_build_isolation,
2372 value.no_build_isolation_package.unwrap_or_default(),
2373 ),
2374 no_build: value.no_build,
2375 no_build_package: value.no_build_package,
2376 no_binary: value.no_binary,
2377 no_binary_package: value.no_binary_package,
2378 no_sources: value.no_sources,
2379 no_sources_package: value.no_sources_package,
2380 }
2381 }
2382}
2383
2384#[derive(
2389 Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, CombineOptions, OptionsMetadata,
2390)]
2391#[serde(deny_unknown_fields, rename_all = "kebab-case")]
2392#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2393pub struct ToolOptions {
2394 index: Option<Vec<Index>>,
2395 index_url: Option<PipIndex>,
2396 extra_index_url: Option<Vec<PipExtraIndex>>,
2397 no_index: Option<bool>,
2398 find_links: Option<Vec<PipFindLinks>>,
2399 index_strategy: Option<IndexStrategy>,
2400 keyring_provider: Option<KeyringProviderType>,
2401 resolution: Option<ResolutionMode>,
2402 prerelease: Option<PrereleaseMode>,
2403 prerelease_package: Option<PrereleasePackage>,
2404 fork_strategy: Option<ForkStrategy>,
2405 dependency_metadata: Option<Vec<StaticMetadata>>,
2406 config_settings: Option<ConfigSettings>,
2407 config_settings_package: Option<PackageConfigSettings>,
2408 build_isolation: Option<BuildIsolation>,
2409 require_build_hashes: Option<bool>,
2410 extra_build_dependencies: Option<ExtraBuildDependencies>,
2411 extra_build_variables: Option<ExtraBuildVariables>,
2412 exclude_newer: Option<ExcludeNewerOverride>,
2413 exclude_newer_package: Option<ExcludeNewerPackage>,
2414 link_mode: Option<LinkMode>,
2415 compile_bytecode: Option<bool>,
2416 no_sources: Option<bool>,
2417 no_sources_package: Option<Vec<PackageName>>,
2418 no_build: Option<bool>,
2419 no_build_package: Option<Vec<PackageName>>,
2420 no_binary: Option<bool>,
2421 no_binary_package: Option<Vec<PackageName>>,
2422 torch_backend: Option<TorchMode>,
2423}
2424
2425#[derive(Debug, Clone, Default, Serialize, Deserialize)]
2427#[serde(deny_unknown_fields, rename_all = "kebab-case")]
2428pub struct ToolOptionsWire {
2429 index: Option<Vec<Index>>,
2430 index_url: Option<PipIndex>,
2431 extra_index_url: Option<Vec<PipExtraIndex>>,
2432 no_index: Option<bool>,
2433 find_links: Option<Vec<PipFindLinks>>,
2434 index_strategy: Option<IndexStrategy>,
2435 keyring_provider: Option<KeyringProviderType>,
2436 resolution: Option<ResolutionMode>,
2437 prerelease: Option<PrereleaseMode>,
2438 prerelease_package: Option<PrereleasePackage>,
2439 fork_strategy: Option<ForkStrategy>,
2440 dependency_metadata: Option<Vec<StaticMetadata>>,
2441 config_settings: Option<ConfigSettings>,
2442 config_settings_package: Option<PackageConfigSettings>,
2443 build_isolation: Option<BuildIsolation>,
2444 require_build_hashes: Option<bool>,
2445 extra_build_dependencies: Option<ExtraBuildDependencies>,
2446 extra_build_variables: Option<ExtraBuildVariables>,
2447 exclude_newer: Option<ExcludeNewerOverride>,
2448 exclude_newer_span: Option<ExcludeNewerSpan>,
2449 #[serde(serialize_with = "serialize_exclude_newer_package_with_spans")]
2450 exclude_newer_package: Option<ExcludeNewerPackage>,
2451 link_mode: Option<LinkMode>,
2452 compile_bytecode: Option<bool>,
2453 no_sources: Option<bool>,
2454 no_sources_package: Option<Vec<PackageName>>,
2455 no_build: Option<bool>,
2456 no_build_package: Option<Vec<PackageName>>,
2457 no_binary: Option<bool>,
2458 no_binary_package: Option<Vec<PackageName>>,
2459 torch_backend: Option<TorchMode>,
2460}
2461
2462impl From<ResolverInstallerOptions> for ToolOptions {
2463 fn from(value: ResolverInstallerOptions) -> Self {
2464 Self {
2465 index: value.indexes.index.map(|indexes| {
2466 indexes
2467 .into_iter()
2468 .map(Index::with_promoted_auth_policy)
2469 .collect()
2470 }),
2471 index_url: value.indexes.index_url,
2472 extra_index_url: value.indexes.extra_index_url,
2473 no_index: value.indexes.no_index,
2474 find_links: value.indexes.find_links,
2475 index_strategy: value.index_strategy,
2476 keyring_provider: value.keyring_provider,
2477 resolution: value.resolution,
2478 prerelease: value.prerelease,
2479 prerelease_package: value.prerelease_package,
2480 fork_strategy: value.fork_strategy,
2481 dependency_metadata: value.dependency_metadata,
2482 config_settings: value.config_settings,
2483 config_settings_package: value.config_settings_package,
2484 build_isolation: value.build_isolation,
2485 require_build_hashes: value.require_build_hashes,
2486 extra_build_dependencies: value.extra_build_dependencies,
2487 extra_build_variables: value.extra_build_variables,
2488 exclude_newer: value.exclude_newer,
2489 exclude_newer_package: value.exclude_newer_package,
2490 link_mode: value.link_mode,
2491 compile_bytecode: value.compile_bytecode,
2492 no_sources: value.no_sources,
2493 no_sources_package: value.no_sources_package,
2494 no_build: value.no_build,
2495 no_build_package: value.no_build_package,
2496 no_binary: value.no_binary,
2497 no_binary_package: value.no_binary_package,
2498 torch_backend: value.torch_backend,
2499 }
2500 }
2501}
2502
2503impl From<ToolOptionsWire> for ToolOptions {
2504 fn from(value: ToolOptionsWire) -> Self {
2505 let exclude_newer = value
2506 .exclude_newer
2507 .map(|exclude_newer| match exclude_newer {
2508 ExcludeNewerOverride::Disabled => ExcludeNewerOverride::Disabled,
2509 ExcludeNewerOverride::Enabled(exclude_newer) => {
2510 let exclude_newer = *exclude_newer;
2511 if let Some(span) = value.exclude_newer_span
2512 && exclude_newer.span().is_none()
2513 {
2514 ExcludeNewerValue::relative(span).into()
2515 } else {
2516 exclude_newer.into()
2517 }
2518 }
2519 });
2520
2521 Self {
2522 index: value.index,
2523 index_url: value.index_url,
2524 extra_index_url: value.extra_index_url,
2525 no_index: value.no_index,
2526 find_links: value.find_links,
2527 index_strategy: value.index_strategy,
2528 keyring_provider: value.keyring_provider,
2529 resolution: value.resolution,
2530 prerelease: value.prerelease,
2531 prerelease_package: value.prerelease_package,
2532 fork_strategy: value.fork_strategy,
2533 dependency_metadata: value.dependency_metadata,
2534 config_settings: value.config_settings,
2535 config_settings_package: value.config_settings_package,
2536 build_isolation: value.build_isolation,
2537 require_build_hashes: value.require_build_hashes,
2538 extra_build_dependencies: value.extra_build_dependencies,
2539 extra_build_variables: value.extra_build_variables,
2540 exclude_newer,
2541 exclude_newer_package: value.exclude_newer_package,
2542 link_mode: value.link_mode,
2543 compile_bytecode: value.compile_bytecode,
2544 no_sources: value.no_sources,
2545 no_sources_package: value.no_sources_package,
2546 no_build: value.no_build,
2547 no_build_package: value.no_build_package,
2548 no_binary: value.no_binary,
2549 no_binary_package: value.no_binary_package,
2550 torch_backend: value.torch_backend,
2551 }
2552 }
2553}
2554
2555impl From<ToolOptions> for ToolOptionsWire {
2556 fn from(value: ToolOptions) -> Self {
2557 let (exclude_newer, exclude_newer_span) = match &value.exclude_newer {
2558 Some(ExcludeNewerOverride::Disabled) => (Some(ExcludeNewerOverride::Disabled), None),
2559 Some(ExcludeNewerOverride::Enabled(value)) => match value.as_ref() {
2560 ExcludeNewerValue::Absolute(_) => {
2561 (Some(ExcludeNewerOverride::Enabled(value.clone())), None)
2562 }
2563 ExcludeNewerValue::Relative(span) => (
2564 Some(ExcludeNewerValue::absolute(value.timestamp()).into()),
2565 Some(*span),
2566 ),
2567 },
2568 None => (None, None),
2569 };
2570
2571 Self {
2572 index: value.index,
2573 index_url: value.index_url,
2574 extra_index_url: value.extra_index_url,
2575 no_index: value.no_index,
2576 find_links: value.find_links,
2577 index_strategy: value.index_strategy,
2578 keyring_provider: value.keyring_provider,
2579 resolution: value.resolution,
2580 prerelease: value.prerelease,
2581 prerelease_package: value.prerelease_package,
2582 fork_strategy: value.fork_strategy,
2583 dependency_metadata: value.dependency_metadata,
2584 config_settings: value.config_settings,
2585 config_settings_package: value.config_settings_package,
2586 build_isolation: value.build_isolation,
2587 require_build_hashes: value.require_build_hashes,
2588 extra_build_dependencies: value.extra_build_dependencies,
2589 extra_build_variables: value.extra_build_variables,
2590 exclude_newer,
2591 exclude_newer_span,
2592 exclude_newer_package: value.exclude_newer_package,
2593 link_mode: value.link_mode,
2594 compile_bytecode: value.compile_bytecode,
2595 no_sources: value.no_sources,
2596 no_sources_package: value.no_sources_package,
2597 no_build: value.no_build,
2598 no_build_package: value.no_build_package,
2599 no_binary: value.no_binary,
2600 no_binary_package: value.no_binary_package,
2601 torch_backend: value.torch_backend,
2602 }
2603 }
2604}
2605
2606impl From<ToolOptions> for ResolverInstallerOptions {
2607 fn from(value: ToolOptions) -> Self {
2608 Self {
2609 indexes: IndexOptions {
2610 index: value.index,
2611 index_url: value.index_url,
2612 extra_index_url: value.extra_index_url,
2613 no_index: value.no_index,
2614 find_links: value.find_links,
2615 },
2616 index_strategy: value.index_strategy,
2617 keyring_provider: value.keyring_provider,
2618 resolution: value.resolution,
2619 prerelease: value.prerelease,
2620 prerelease_package: value.prerelease_package,
2621 fork_strategy: value.fork_strategy,
2622 dependency_metadata: value.dependency_metadata,
2623 config_settings: value.config_settings,
2624 config_settings_package: value.config_settings_package,
2625 build_isolation: value.build_isolation,
2626 require_build_hashes: value.require_build_hashes,
2627 extra_build_dependencies: value.extra_build_dependencies,
2628 extra_build_variables: value.extra_build_variables,
2629 exclude_newer: value.exclude_newer,
2630 exclude_newer_package: value.exclude_newer_package,
2631 link_mode: value.link_mode,
2632 compile_bytecode: value.compile_bytecode,
2633 no_sources: value.no_sources,
2634 no_sources_package: value.no_sources_package,
2635 upgrade: None,
2636 reinstall: None,
2637 no_build: value.no_build,
2638 no_build_package: value.no_build_package,
2639 no_binary: value.no_binary,
2640 no_binary_package: value.no_binary_package,
2641 torch_backend: value.torch_backend,
2642 }
2643 }
2644}
2645
2646#[derive(Debug, Clone, Default, Deserialize)]
2649#[serde(rename_all = "kebab-case", deny_unknown_fields)]
2650struct OptionsWire {
2651 required_version: Option<RequiredVersion>,
2654 system_certs: Option<bool>,
2655 native_tls: Option<bool>,
2656 offline: Option<bool>,
2657 no_cache: Option<bool>,
2658 cache_dir: Option<PathBuf>,
2659 preview: Option<bool>,
2660 preview_features: Option<PreviewFeaturesOption>,
2661 python_preference: Option<PythonPreference>,
2662 python_downloads: Option<PythonDownloads>,
2663 concurrent_downloads: Option<NonZeroUsize>,
2664 concurrent_builds: Option<NonZeroUsize>,
2665 concurrent_installs: Option<NonZeroUsize>,
2666
2667 index: Option<Vec<Index>>,
2670 index_url: Option<PipIndex>,
2671 extra_index_url: Option<Vec<PipExtraIndex>>,
2672 no_index: Option<bool>,
2673 find_links: Option<Vec<PipFindLinks>>,
2674 index_strategy: Option<IndexStrategy>,
2675 keyring_provider: Option<KeyringProviderType>,
2676 http_proxy: Option<ProxyUrl>,
2677 https_proxy: Option<ProxyUrl>,
2678 no_proxy: Option<Vec<String>>,
2679 allow_insecure_host: Option<Vec<TrustedHost>>,
2680 resolution: Option<ResolutionMode>,
2681 prerelease: Option<PrereleaseMode>,
2682 prerelease_package: Option<PrereleasePackage>,
2683 fork_strategy: Option<ForkStrategy>,
2684 dependency_metadata: Option<Vec<StaticMetadata>>,
2685 config_settings: Option<ConfigSettings>,
2686 config_settings_package: Option<PackageConfigSettings>,
2687 no_build_isolation: Option<bool>,
2688 require_build_hashes: Option<bool>,
2689 no_build_isolation_package: Option<Vec<PackageName>>,
2690 extra_build_dependencies: Option<ExtraBuildDependencies>,
2691 extra_build_variables: Option<ExtraBuildVariables>,
2692 exclude_newer: Option<ExcludeNewerOverride>,
2693 exclude_newer_package: Option<ExcludeNewerPackage>,
2694 link_mode: Option<LinkMode>,
2695 compile_bytecode: Option<bool>,
2696 no_sources: Option<bool>,
2697 no_sources_package: Option<Vec<PackageName>>,
2698 upgrade: Option<bool>,
2699 upgrade_package: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2700 reinstall: Option<bool>,
2701 reinstall_package: Option<Vec<PackageName>>,
2702 no_build: Option<bool>,
2703 no_build_package: Option<Vec<PackageName>>,
2704 no_binary: Option<bool>,
2705 no_binary_package: Option<Vec<PackageName>>,
2706 torch_backend: Option<TorchMode>,
2707
2708 python_install_mirror: Option<String>,
2711 pypy_install_mirror: Option<String>,
2712 graalpy_install_mirror: Option<String>,
2713 pyodide_install_mirror: Option<String>,
2714 python_downloads_json_url: Option<String>,
2715
2716 publish_url: Option<DisplaySafeUrl>,
2719 trusted_publishing: Option<TrustedPublishing>,
2720 check_url: Option<IndexUrl>,
2721
2722 add_bounds: Option<AddBoundsKind>,
2725
2726 audit: Option<AuditOptions>,
2727 pip: Option<PipOptions>,
2728 cache_keys: Option<Vec<CacheKey>>,
2729
2730 override_dependencies: Option<Vec<OverrideDependency>>,
2734 exclude_dependencies: Option<Vec<ExcludeDependency>>,
2735 constraint_dependencies: Option<Vec<Requirement<VerbatimParsedUrl>>>,
2736 build_constraint_dependencies: Option<Vec<BuildConstraintDependency>>,
2737 environments: Option<SupportedEnvironments>,
2738 required_environments: Option<SupportedEnvironments>,
2739 minimum_libc_version: Option<MinimumLibcVersion>,
2740
2741 conflicts: Option<serde::de::IgnoredAny>,
2745 workspace: Option<serde::de::IgnoredAny>,
2746 sources: Option<serde::de::IgnoredAny>,
2747 managed: Option<serde::de::IgnoredAny>,
2748 r#package: Option<serde::de::IgnoredAny>,
2749 default_groups: Option<serde::de::IgnoredAny>,
2750 dependency_groups: Option<serde::de::IgnoredAny>,
2751 dev_dependencies: Option<serde::de::IgnoredAny>,
2752
2753 build_backend: Option<serde::de::IgnoredAny>,
2755}
2756
2757impl TryFrom<OptionsWire> for Options {
2758 type Error = &'static str;
2759
2760 #[allow(deprecated)]
2761 fn try_from(value: OptionsWire) -> Result<Self, Self::Error> {
2762 let OptionsWire {
2763 required_version,
2764 system_certs,
2765 native_tls,
2766 offline,
2767 no_cache,
2768 cache_dir,
2769 preview,
2770 preview_features,
2771 python_preference,
2772 python_downloads,
2773 python_install_mirror,
2774 pypy_install_mirror,
2775 graalpy_install_mirror,
2776 pyodide_install_mirror,
2777 python_downloads_json_url,
2778 concurrent_downloads,
2779 concurrent_builds,
2780 concurrent_installs,
2781 index,
2782 index_url,
2783 extra_index_url,
2784 no_index,
2785 find_links,
2786 index_strategy,
2787 keyring_provider,
2788 http_proxy,
2789 https_proxy,
2790 no_proxy,
2791 allow_insecure_host,
2792 resolution,
2793 prerelease,
2794 prerelease_package,
2795 fork_strategy,
2796 dependency_metadata,
2797 config_settings,
2798 config_settings_package,
2799 no_build_isolation,
2800 require_build_hashes,
2801 no_build_isolation_package,
2802 exclude_newer,
2803 exclude_newer_package,
2804 link_mode,
2805 compile_bytecode,
2806 no_sources,
2807 no_sources_package,
2808 upgrade,
2809 upgrade_package,
2810 reinstall,
2811 reinstall_package,
2812 no_build,
2813 no_build_package,
2814 no_binary,
2815 no_binary_package,
2816 torch_backend,
2817 audit,
2818 pip,
2819 cache_keys,
2820 override_dependencies,
2821 exclude_dependencies,
2822 constraint_dependencies,
2823 build_constraint_dependencies,
2824 environments,
2825 required_environments,
2826 minimum_libc_version,
2827 conflicts,
2828 publish_url,
2829 trusted_publishing,
2830 check_url,
2831 workspace,
2832 sources,
2833 default_groups,
2834 dependency_groups,
2835 extra_build_dependencies,
2836 extra_build_variables,
2837 dev_dependencies,
2838 managed,
2839 package,
2840 add_bounds: bounds,
2841 build_backend,
2843 } = value;
2844
2845 Ok(Self {
2846 globals: GlobalOptions {
2847 required_version,
2848 system_certs,
2849 native_tls,
2850 offline,
2851 no_cache,
2852 cache_dir,
2853 preview: PreviewOption::try_from(preview, preview_features)?,
2854 python_preference,
2855 python_downloads,
2856 concurrent_downloads,
2857 concurrent_builds,
2858 concurrent_installs,
2859 http_proxy,
2860 https_proxy,
2861 no_proxy,
2862 allow_insecure_host: allow_insecure_host.clone(),
2864 },
2865 top_level: ResolverInstallerSchema {
2866 index,
2867 index_url,
2868 extra_index_url,
2869 no_index,
2870 find_links,
2871 index_strategy,
2872 keyring_provider,
2873 resolution,
2874 prerelease,
2875 prerelease_package,
2876 fork_strategy,
2877 dependency_metadata,
2878 config_settings,
2879 config_settings_package,
2880 no_build_isolation,
2881 require_build_hashes,
2882 no_build_isolation_package,
2883 extra_build_dependencies,
2884 extra_build_variables,
2885 exclude_newer,
2886 exclude_newer_package,
2887 link_mode,
2888 compile_bytecode,
2889 no_sources,
2890 no_sources_package,
2891 upgrade,
2892 upgrade_package,
2893 reinstall,
2894 reinstall_package,
2895 no_build,
2896 no_build_package,
2897 no_binary,
2898 no_binary_package,
2899 torch_backend,
2900 },
2901 pip,
2902 cache_keys,
2903 build_backend,
2904 override_dependencies,
2905 exclude_dependencies,
2906 constraint_dependencies,
2907 build_constraint_dependencies,
2908 environments,
2909 required_environments,
2910 minimum_libc_version,
2911 install_mirrors: PythonInstallMirrors {
2912 python_install_mirror,
2913 pypy_install_mirror,
2914 graalpy_install_mirror,
2915 pyodide_install_mirror,
2916 python_downloads_json_url,
2917 },
2918 conflicts,
2919 publish: PublishOptions {
2920 publish_url,
2921 trusted_publishing,
2922 check_url,
2923 },
2924 add: AddOptions { add_bounds: bounds },
2925 audit,
2926 workspace,
2927 sources,
2928 dev_dependencies,
2929 default_groups,
2930 dependency_groups,
2931 managed,
2932 package,
2933 })
2934 }
2935}
2936
2937#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
2938#[serde(rename_all = "kebab-case")]
2939#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2940pub struct PublishOptions {
2941 #[option(
2944 default = "\"https://upload.pypi.org/legacy/\"",
2945 value_type = "str",
2946 example = r#"
2947 publish-url = "https://test.pypi.org/legacy/"
2948 "#
2949 )]
2950 pub publish_url: Option<DisplaySafeUrl>,
2951
2952 #[option(
2959 default = "automatic",
2960 value_type = "str",
2961 example = r#"
2962 trusted-publishing = "always"
2963 "#
2964 )]
2965 pub trusted_publishing: Option<TrustedPublishing>,
2966
2967 #[option(
2981 default = "None",
2982 value_type = "str",
2983 example = r#"
2984 check-url = "https://test.pypi.org/simple"
2985 "#
2986 )]
2987 pub check_url: Option<IndexUrl>,
2988}
2989
2990#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
2991#[serde(rename_all = "kebab-case")]
2992#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2993pub struct AddOptions {
2994 #[option(
3005 default = "\"lower\"",
3006 value_type = "str",
3007 example = r#"
3008 add-bounds = "major"
3009 "#,
3010 possible_values = true
3011 )]
3012 pub add_bounds: Option<AddBoundsKind>,
3013}
3014
3015#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
3016#[serde(rename_all = "kebab-case")]
3017#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3018pub struct AuditOptions {
3019 #[option(
3021 default = "false",
3022 value_type = "bool",
3023 example = r#"
3024 malware-check = true
3025 "#
3026 )]
3027 pub malware_check: Option<bool>,
3028
3029 #[option(
3031 default = "\"https://api.osv.dev/\"",
3032 value_type = "str",
3033 example = r#"
3034 malware-check-url = "https://example.com"
3035 "#
3036 )]
3037 pub malware_check_url: Option<DisplaySafeUrl>,
3038
3039 #[option(
3044 default = "[]",
3045 value_type = "list[str]",
3046 example = r#"
3047 ignore = ["PYSEC-2022-43017", "GHSA-5239-wwwm-4pmq"]
3048 "#
3049 )]
3050 pub ignore: Option<Vec<String>>,
3051
3052 #[option(
3058 default = "[]",
3059 value_type = "list[str]",
3060 example = r#"
3061 ignore-until-fixed = ["PYSEC-2022-43017"]
3062 "#
3063 )]
3064 pub ignore_until_fixed: Option<Vec<String>>,
3065}
3066
3067#[derive(Debug, Clone)]
3068pub struct MalwareCheckSettings {
3069 pub enabled: bool,
3071 pub malware_check_url: Option<DisplaySafeUrl>,
3073}
3074
3075impl MalwareCheckSettings {
3076 pub fn resolve(
3077 filesystem: Option<&FilesystemOptions>,
3078 environment: &EnvironmentOptions,
3079 ) -> Self {
3080 let audit = filesystem.and_then(|options| options.audit.as_ref());
3081
3082 Self {
3083 enabled: environment
3084 .malware_check
3085 .value
3086 .or(audit.and_then(|audit| audit.malware_check))
3087 .unwrap_or_default(),
3088 malware_check_url: environment
3089 .malware_check_url
3090 .clone()
3091 .or_else(|| audit.and_then(|audit| audit.malware_check_url.clone())),
3092 }
3093 }
3094}
3095
3096#[derive(Debug, Clone)]
3098#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3099#[cfg_attr(feature = "schemars", schemars(untagged))]
3100pub enum PreviewFeaturesOption {
3101 Toggle(bool),
3102 Features(Vec<MaybePreviewFeature>),
3103}
3104
3105struct PreviewFeaturesVisitor;
3107
3108impl<'de> Visitor<'de> for PreviewFeaturesVisitor {
3109 type Value = PreviewFeaturesOption;
3110
3111 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
3112 formatter.write_str("a boolean or a list of preview feature names")
3113 }
3114
3115 fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E>
3116 where
3117 E: Error,
3118 {
3119 Ok(PreviewFeaturesOption::Toggle(value))
3120 }
3121
3122 fn visit_seq<S>(self, sequence: S) -> Result<Self::Value, S::Error>
3123 where
3124 S: SeqAccess<'de>,
3125 {
3126 Vec::deserialize(SeqAccessDeserializer::new(sequence)).map(PreviewFeaturesOption::Features)
3127 }
3128}
3129
3130impl<'de> Deserialize<'de> for PreviewFeaturesOption {
3131 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
3132 where
3133 D: Deserializer<'de>,
3134 {
3135 deserializer.deserialize_any(PreviewFeaturesVisitor)
3136 }
3137}
3138
3139#[expect(
3140 dead_code,
3141 reason = "Fields are only used by the OptionsMetadata and JsonSchema derives"
3142)]
3143#[derive(OptionsMetadata)]
3144#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3145#[cfg_attr(feature = "schemars", schemars(rename_all = "kebab-case"))]
3146struct PreviewOptionsDefinition {
3147 #[deprecated(note = "use `preview-features` instead")]
3153 preview: Option<bool>,
3154 #[option(
3158 default = "false",
3159 value_type = "bool | list[str]",
3160 example = r#"
3161 preview-features = true
3162 # or
3163 preview-features = ["json-output"]
3164 "#
3165 )]
3166 preview_features: Option<PreviewFeaturesOption>,
3167}
3168
3169#[derive(Debug, Clone)]
3171pub enum PreviewOption {
3172 Preview(bool),
3174 PreviewFeatures(PreviewFeaturesOption),
3176}
3177
3178impl uv_options_metadata::OptionsMetadata for PreviewOption {
3179 fn record(visit: &mut dyn uv_options_metadata::Visit) {
3180 <PreviewOptionsDefinition as uv_options_metadata::OptionsMetadata>::record(visit);
3181 }
3182}
3183
3184#[cfg(feature = "schemars")]
3185struct ConflictingPreviewOptions;
3186
3187#[cfg(feature = "schemars")]
3188impl schemars::JsonSchema for ConflictingPreviewOptions {
3189 fn schema_name() -> Cow<'static, str> {
3190 Cow::Borrowed("ConflictingPreviewOptions")
3191 }
3192
3193 fn json_schema(_generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
3194 schemars::json_schema!({
3195 "type": "object",
3196 "properties": {
3197 "preview": {},
3198 "preview-features": {},
3199 },
3200 "required": ["preview", "preview-features"],
3201 })
3202 }
3203}
3204
3205#[cfg(feature = "schemars")]
3206impl schemars::JsonSchema for PreviewOption {
3207 fn schema_name() -> Cow<'static, str> {
3208 Cow::Borrowed("PreviewOption")
3209 }
3210
3211 fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
3212 let mut schema = <PreviewOptionsDefinition as schemars::JsonSchema>::json_schema(generator);
3213 schema.insert(
3216 "not".to_string(),
3217 generator
3218 .subschema_for::<ConflictingPreviewOptions>()
3219 .into(),
3220 );
3221 schema
3222 }
3223}
3224
3225impl PreviewOption {
3226 fn try_from(
3227 preview: Option<bool>,
3228 preview_features: Option<PreviewFeaturesOption>,
3229 ) -> Result<Option<Self>, &'static str> {
3230 match (preview, preview_features) {
3231 (Some(_), Some(_)) => Err("cannot specify both `preview` and `preview-features`"),
3232 (Some(b), None) => Ok(Some(Self::Preview(b))),
3233 (None, Some(features)) => Ok(Some(Self::PreviewFeatures(features))),
3234 (None, None) => Ok(None),
3235 }
3236 }
3237
3238 pub fn resolve(&self) -> Preview {
3240 use PreviewFeaturesOption::{Features, Toggle};
3241
3242 match self {
3243 Self::Preview(false) | Self::PreviewFeatures(Toggle(false)) => Preview::default(),
3244 Self::Preview(true) | Self::PreviewFeatures(Toggle(true)) => Preview::all(),
3245 Self::PreviewFeatures(Features(features)) => Preview::from_feature_names(features),
3246 }
3247 }
3248}