-
Notifications
You must be signed in to change notification settings - Fork 928
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
uv-resolver: use Requires-Python to filter dependencies during universal resolution #4273
Changes from all commits
dbca9b0
df460b1
c490424
c2c1ccf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,6 +47,7 @@ use crate::pubgrub::{ | |
PubGrubPriorities, PubGrubPython, PubGrubSpecifier, | ||
}; | ||
use crate::python_requirement::PythonRequirement; | ||
use crate::requires_python::RequiresPython; | ||
use crate::resolution::ResolutionGraph; | ||
pub(crate) use crate::resolver::availability::{ | ||
IncompletePackage, ResolverVersion, UnavailablePackage, UnavailableReason, UnavailableVersion, | ||
|
@@ -94,6 +95,14 @@ struct ResolverState<InstalledPackages: InstalledPackagesProvider> { | |
/// When not set, the resolver is in "universal" mode. | ||
markers: Option<MarkerEnvironment>, | ||
python_requirement: PythonRequirement, | ||
/// This is derived from `PythonRequirement` once at initialization | ||
/// time. It's used in universal mode to filter our dependencies with | ||
/// a `python_version` marker expression that has no overlap with the | ||
/// `Requires-Python` specifier. | ||
/// | ||
/// This is non-None if and only if the resolver is operating in | ||
/// universal mode. (i.e., when `markers` is `None`.) | ||
requires_python: Option<MarkerTree>, | ||
selector: CandidateSelector, | ||
index: InMemoryIndex, | ||
installed_packages: InstalledPackages, | ||
|
@@ -181,6 +190,16 @@ impl<Provider: ResolverProvider, InstalledPackages: InstalledPackagesProvider> | |
provider: Provider, | ||
installed_packages: InstalledPackages, | ||
) -> Result<Self, ResolveError> { | ||
let requires_python = if markers.is_some() { | ||
None | ||
} else { | ||
Some( | ||
python_requirement | ||
.requires_python() | ||
.map(RequiresPython::to_marker_tree) | ||
.unwrap_or_else(|| MarkerTree::And(vec![])), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this evaluate to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe it would be correct for this to be /// This is derived from `PythonRequirement` once at initialization
/// time. It's used in universal mode to filter our dependencies with
/// a `python_version` marker expression that has no overlap with the
/// `Requires-Python` specifier.
///
/// This is non-None if and only if the resolver is operating in
/// universal mode. (i.e., when `markers` is `None`.)
requires_python: Option<MarkerTree>, If we used I don't have a strong opinion here or anything, but this just made the most sense to me at the time. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (I sometimes wonder if we could get away with not having There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess I was hoping to avoid ever allowing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah I had similar hopes for |
||
) | ||
}; | ||
let state = ResolverState { | ||
index: index.clone(), | ||
git: git.clone(), | ||
|
@@ -200,6 +219,7 @@ impl<Provider: ResolverProvider, InstalledPackages: InstalledPackagesProvider> | |
hasher: hasher.clone(), | ||
markers: markers.cloned(), | ||
python_requirement: python_requirement.clone(), | ||
requires_python, | ||
reporter: None, | ||
installed_packages, | ||
}; | ||
|
@@ -959,6 +979,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag | |
&self.locals, | ||
&self.git, | ||
self.markers.as_ref(), | ||
self.requires_python.as_ref(), | ||
); | ||
|
||
let dependencies = match dependencies { | ||
|
@@ -1109,6 +1130,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag | |
&self.locals, | ||
&self.git, | ||
self.markers.as_ref(), | ||
self.requires_python.as_ref(), | ||
)?; | ||
|
||
for (dep_package, dep_version) in dependencies.iter() { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why can this one unwrap?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same reason as the one above. I duplicated the comment to make this clearer.
Although I suppose the constructor of
RequiresPython
permits anyVersion
which means it could technically have a local segment. Likely a logic error, but I addedwithout_local()
to strip it from the version anyway.