uv_configuration/
dependency_modifier.rs1use std::borrow::Cow;
2
3use uv_distribution_types::{Requirement, ResolutionRecorder};
4use uv_normalize::PackageName;
5use uv_pep440::Version;
6
7use crate::{Excludes, Overrides};
8
9#[derive(Debug, Default, Clone)]
11pub struct DependencyModifiers {
12 overrides: Overrides,
13 excludes: Excludes,
14}
15
16#[derive(Debug, Clone, Copy)]
18pub enum DependencyModifierScope<'a> {
19 Global,
21 Package(&'a PackageName, &'a Version),
23 DependencyGroup(&'a PackageName, &'a Version),
25}
26
27impl DependencyModifiers {
28 #[must_use]
30 pub fn with_recorder(mut self, recorder: Option<ResolutionRecorder>) -> Self {
31 self.overrides = self.overrides.with_recorder(recorder.clone());
32 self.excludes = self.excludes.with_recorder(recorder);
33 self
34 }
35
36 pub fn new(overrides: Overrides, excludes: Excludes) -> Self {
37 Self {
38 overrides,
39 excludes,
40 }
41 }
42
43 pub fn has_scoped_package(&self, package: &PackageName) -> bool {
45 self.overrides.has_scoped_package(package) || self.excludes.has_scoped_package(package)
46 }
47
48 pub fn global_overrides(&self) -> impl Iterator<Item = &Requirement> {
50 self.overrides
51 .global_requirements()
52 .filter(|requirement| !self.excludes.contains(&requirement.name))
53 }
54
55 pub fn scoped_overrides(&self) -> impl Iterator<Item = &Requirement> {
57 self.overrides
58 .scoped_requirements()
59 .filter(|(package, version, requirement)| {
60 !self.excludes.contains_for_scope(
61 &self.overrides,
62 package,
63 *version,
64 &requirement.name,
65 )
66 })
67 .map(|(_, _, requirement)| requirement)
68 }
69
70 pub fn scoped_overrides_for(
72 &self,
73 package: &PackageName,
74 version: &Version,
75 ) -> impl Iterator<Item = &Requirement> {
76 self.overrides
77 .scoped_requirements_for(package, version)
78 .filter(|requirement| {
79 !self
80 .excludes
81 .contains_for(package, version, &requirement.name)
82 })
83 }
84
85 pub fn is_excluded(&self, dependency: &PackageName) -> bool {
87 self.excludes.contains(dependency)
88 }
89
90 pub fn is_excluded_for(
92 &self,
93 package: &PackageName,
94 version: &Version,
95 dependency: &PackageName,
96 ) -> bool {
97 self.excludes.contains_for(package, version, dependency)
98 }
99
100 pub fn apply<'a, 'scope, I>(
102 &'a self,
103 scope: DependencyModifierScope<'scope>,
104 requirements: I,
105 ) -> impl Iterator<Item = Cow<'a, Requirement>> + use<'a, 'scope, I>
106 where
107 I: IntoIterator<Item = &'a Requirement>,
108 {
109 let (overrides, excludes) = match scope {
110 DependencyModifierScope::Global => (None, None),
111 DependencyModifierScope::Package(package, version) => {
112 (Some((package, version)), Some((package, version)))
113 }
114 DependencyModifierScope::DependencyGroup(package, version) => {
115 (None, Some((package, version)))
116 }
117 };
118 self.overrides
119 .apply_for_package(overrides, requirements)
120 .filter(move |requirement| {
121 !self
122 .excludes
123 .contains_for_package(excludes, &requirement.name)
124 })
125 }
126}