mirror of
https://github.com/astral-sh/uv
synced 2026-06-21 13:47:25 +00:00
use let chains in various crates (#19908)
Now that uv’s MSRV is Rust 1.94, use Rust 2024 let chains where they make nested guards clearer in the parser, configuration, and data-model crates. This flattens related pattern matches and predicates while preserving evaluation order, short-circuiting, borrow scopes, and mutation behavior. Guards involving effects, staged work, or non-obvious lifetimes remain nested.
This commit is contained in:
committed by
GitHub
parent
ac8a4615da
commit
14855e023d
@@ -17,10 +17,10 @@ impl Constraints {
|
||||
let mut constraints: FxHashMap<PackageName, Vec<Requirement>> = FxHashMap::default();
|
||||
for requirement in requirements {
|
||||
// Skip empty constraints.
|
||||
if let RequirementSource::Registry { specifier, .. } = &requirement.source {
|
||||
if specifier.is_empty() {
|
||||
continue;
|
||||
}
|
||||
if let RequirementSource::Registry { specifier, .. } = &requirement.source
|
||||
&& specifier.is_empty()
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
constraints
|
||||
|
||||
@@ -87,10 +87,10 @@ impl InstallOptions {
|
||||
// If `--only-install-workspace` is set, only include the project and workspace members.
|
||||
if self.only_install_workspace {
|
||||
// Check if it's the project itself
|
||||
if let Some(project_name) = project_name {
|
||||
if package_name == project_name {
|
||||
return true;
|
||||
}
|
||||
if let Some(project_name) = project_name
|
||||
&& package_name == project_name
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if it's a workspace member
|
||||
@@ -105,25 +105,22 @@ impl InstallOptions {
|
||||
|
||||
// If `--only-install-project` is set, only include the project itself.
|
||||
if self.only_install_project {
|
||||
if let Some(project_name) = project_name {
|
||||
if package_name == project_name {
|
||||
return true;
|
||||
}
|
||||
if let Some(project_name) = project_name
|
||||
&& package_name == project_name
|
||||
{
|
||||
return true;
|
||||
}
|
||||
debug!("Omitting `{package_name}` from resolution due to `--only-install-project`");
|
||||
return false;
|
||||
}
|
||||
|
||||
// If `--no-install-project` is set, remove the project itself.
|
||||
if self.no_install_project {
|
||||
if let Some(project_name) = project_name {
|
||||
if package_name == project_name {
|
||||
debug!(
|
||||
"Omitting `{package_name}` from resolution due to `--no-install-project`"
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if self.no_install_project
|
||||
&& let Some(project_name) = project_name
|
||||
&& package_name == project_name
|
||||
{
|
||||
debug!("Omitting `{package_name}` from resolution due to `--no-install-project`");
|
||||
return false;
|
||||
}
|
||||
|
||||
// If `--no-install-workspace` is set, remove the project and any workspace members.
|
||||
@@ -131,15 +128,12 @@ impl InstallOptions {
|
||||
// In some cases, the project root might be omitted from the list of workspace members
|
||||
// encoded in the lockfile. (But we already checked this above if `--no-install-project`
|
||||
// is set.)
|
||||
if !self.no_install_project {
|
||||
if let Some(project_name) = project_name {
|
||||
if package_name == project_name {
|
||||
debug!(
|
||||
"Omitting `{package_name}` from resolution due to `--no-install-workspace`"
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if !self.no_install_project
|
||||
&& let Some(project_name) = project_name
|
||||
&& package_name == project_name
|
||||
{
|
||||
debug!("Omitting `{package_name}` from resolution due to `--no-install-workspace`");
|
||||
return false;
|
||||
}
|
||||
|
||||
if members.contains(package_name) {
|
||||
|
||||
@@ -190,10 +190,10 @@ impl Upgrade {
|
||||
let mut constraints: FxHashMap<PackageName, Vec<Requirement>> = FxHashMap::default();
|
||||
for requirement in upgrade_package {
|
||||
// Skip any "empty" constraints.
|
||||
if let RequirementSource::Registry { specifier, .. } = &requirement.source {
|
||||
if specifier.is_empty() {
|
||||
continue;
|
||||
}
|
||||
if let RequirementSource::Registry { specifier, .. } = &requirement.source
|
||||
&& specifier.is_empty()
|
||||
{
|
||||
continue;
|
||||
}
|
||||
constraints
|
||||
.entry(requirement.name.clone())
|
||||
|
||||
@@ -503,10 +503,10 @@ impl Index {
|
||||
|
||||
/// Resolve the index relative to the given root directory.
|
||||
pub fn relative_to(mut self, root_dir: &Path) -> Result<Self, IndexUrlError> {
|
||||
if let IndexUrl::Path(ref url) = self.url {
|
||||
if let Some(given) = url.given() {
|
||||
self.url = IndexUrl::parse(given, Some(root_dir))?;
|
||||
}
|
||||
if let IndexUrl::Path(ref url) = self.url
|
||||
&& let Some(given) = url.given()
|
||||
{
|
||||
self.url = IndexUrl::parse(given, Some(root_dir))?;
|
||||
}
|
||||
Ok(self)
|
||||
}
|
||||
@@ -565,24 +565,24 @@ impl FromStr for Index {
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
// Determine whether the source is prefixed with a name, as in `name=https://pypi.org/simple`.
|
||||
if let Some((name, url)) = s.split_once('=') {
|
||||
if !name.chars().any(|c| c == ':') {
|
||||
let name = IndexName::from_str(name)?;
|
||||
let url = IndexUrl::from_str(url)?;
|
||||
return Ok(Self {
|
||||
name: Some(name),
|
||||
url,
|
||||
explicit: false,
|
||||
default: false,
|
||||
origin: None,
|
||||
format: IndexFormat::Simple,
|
||||
publish_url: None,
|
||||
authenticate: AuthPolicy::default(),
|
||||
ignore_error_codes: None,
|
||||
cache_control: None,
|
||||
exclude_newer: None,
|
||||
});
|
||||
}
|
||||
if let Some((name, url)) = s.split_once('=')
|
||||
&& !name.chars().any(|c| c == ':')
|
||||
{
|
||||
let name = IndexName::from_str(name)?;
|
||||
let url = IndexUrl::from_str(url)?;
|
||||
return Ok(Self {
|
||||
name: Some(name),
|
||||
url,
|
||||
explicit: false,
|
||||
default: false,
|
||||
origin: None,
|
||||
format: IndexFormat::Simple,
|
||||
publish_url: None,
|
||||
authenticate: AuthPolicy::default(),
|
||||
ignore_error_codes: None,
|
||||
cache_control: None,
|
||||
exclude_newer: None,
|
||||
});
|
||||
}
|
||||
|
||||
// Otherwise, assume the source is a URL.
|
||||
|
||||
@@ -121,17 +121,17 @@ impl IndexUrl {
|
||||
return;
|
||||
};
|
||||
|
||||
if let Some(path) = verbatim_url.given() {
|
||||
if !is_disambiguated_path(path) {
|
||||
if cfg!(windows) {
|
||||
warn_user!(
|
||||
"Relative paths passed to `--index` or `--default-index` should be disambiguated from index names (use `.\\{path}` or `./{path}`). Support for ambiguous values will be removed in the future"
|
||||
);
|
||||
} else {
|
||||
warn_user!(
|
||||
"Relative paths passed to `--index` or `--default-index` should be disambiguated from index names (use `./{path}`). Support for ambiguous values will be removed in the future"
|
||||
);
|
||||
}
|
||||
if let Some(path) = verbatim_url.given()
|
||||
&& !is_disambiguated_path(path)
|
||||
{
|
||||
if cfg!(windows) {
|
||||
warn_user!(
|
||||
"Relative paths passed to `--index` or `--default-index` should be disambiguated from index names (use `.\\{path}` or `./{path}`). Support for ambiguous values will be removed in the future"
|
||||
);
|
||||
} else {
|
||||
warn_user!(
|
||||
"Relative paths passed to `--index` or `--default-index` should be disambiguated from index names (use `./{path}`). Support for ambiguous values will be removed in the future"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,16 +67,16 @@ impl LoweredRequirement {
|
||||
sources
|
||||
.iter()
|
||||
.filter(|source| {
|
||||
if let Some(target) = source.extra() {
|
||||
if extra != Some(target) {
|
||||
return false;
|
||||
}
|
||||
if let Some(target) = source.extra()
|
||||
&& extra != Some(target)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if let Some(target) = source.group() {
|
||||
if group != Some(target) {
|
||||
return false;
|
||||
}
|
||||
if let Some(target) = source.group()
|
||||
&& group != Some(target)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
|
||||
@@ -55,14 +55,12 @@ fn get_doc_comment(attrs: &[Attribute]) -> String {
|
||||
attrs
|
||||
.iter()
|
||||
.filter_map(|attr| {
|
||||
if attr.path().is_ident("doc") {
|
||||
if let syn::Meta::NameValue(meta) = &attr.meta {
|
||||
if let syn::Expr::Lit(expr) = &meta.value {
|
||||
if let syn::Lit::Str(str) = &expr.lit {
|
||||
return Some(str.value().trim().to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
if attr.path().is_ident("doc")
|
||||
&& let syn::Meta::NameValue(meta) = &attr.meta
|
||||
&& let syn::Expr::Lit(expr) = &meta.value
|
||||
&& let syn::Lit::Str(str) = &expr.lit
|
||||
{
|
||||
return Some(str.value().trim().to_string());
|
||||
}
|
||||
None
|
||||
})
|
||||
|
||||
@@ -49,14 +49,14 @@ pub(crate) fn derive_impl(input: DeriveInput) -> syn::Result<TokenStream> {
|
||||
// by calling `Type::record` instead of `visitor.visit_set`
|
||||
if let (Type::Path(ty), Meta::List(list)) = (&field.ty, &serde.meta) {
|
||||
for token in list.tokens.clone() {
|
||||
if let TokenTree::Ident(ident) = token {
|
||||
if ident == "flatten" {
|
||||
output.push(quote_spanned!(
|
||||
ty.span() => (<#ty>::record(visit))
|
||||
));
|
||||
if let TokenTree::Ident(ident) = token
|
||||
&& ident == "flatten"
|
||||
{
|
||||
output.push(quote_spanned!(
|
||||
ty.span() => (<#ty>::record(visit))
|
||||
));
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -361,18 +361,15 @@ fn parse_deprecated_attribute(attribute: &Attribute) -> syn::Result<DeprecatedAt
|
||||
}
|
||||
|
||||
fn get_inner_type_if_option(ty: &Type) -> Option<&Type> {
|
||||
if let Type::Path(type_path) = ty {
|
||||
if type_path.path.segments.len() == 1 && type_path.path.segments[0].ident == "Option" {
|
||||
if let PathArguments::AngleBracketed(angle_bracketed_args) =
|
||||
&type_path.path.segments[0].arguments
|
||||
{
|
||||
if angle_bracketed_args.args.len() == 1 {
|
||||
if let GenericArgument::Type(inner_type) = &angle_bracketed_args.args[0] {
|
||||
return Some(inner_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Type::Path(type_path) = ty
|
||||
&& type_path.path.segments.len() == 1
|
||||
&& type_path.path.segments[0].ident == "Option"
|
||||
&& let PathArguments::AngleBracketed(angle_bracketed_args) =
|
||||
&type_path.path.segments[0].arguments
|
||||
&& angle_bracketed_args.args.len() == 1
|
||||
&& let GenericArgument::Type(inner_type) = &angle_bracketed_args.args[0]
|
||||
{
|
||||
return Some(inner_type);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
@@ -741,11 +741,11 @@ impl Version {
|
||||
});
|
||||
} else {
|
||||
// Either bump the matching kind or set to 1
|
||||
if let Some(prerelease) = &mut full.pre {
|
||||
if prerelease.kind == kind {
|
||||
prerelease.number += 1;
|
||||
return;
|
||||
}
|
||||
if let Some(prerelease) = &mut full.pre
|
||||
&& prerelease.kind == kind
|
||||
{
|
||||
prerelease.number += 1;
|
||||
return;
|
||||
}
|
||||
full.pre = Some(Prerelease { kind, number: 1 });
|
||||
}
|
||||
|
||||
@@ -1051,21 +1051,20 @@ impl MarkerTree {
|
||||
CanonicalMarkerValueString::PlatformRelease
|
||||
| CanonicalMarkerValueString::PlatformVersion
|
||||
) && range.as_singleton().is_none()
|
||||
&& let Some((start, end)) = range.bounding_range()
|
||||
{
|
||||
if let Some((start, end)) = range.bounding_range() {
|
||||
if let Bound::Included(value) | Bound::Excluded(value) = start {
|
||||
reporter.report(
|
||||
MarkerWarningKind::LexicographicComparison,
|
||||
format!("Comparing {l_string} and {value} lexicographically"),
|
||||
);
|
||||
}
|
||||
if let Bound::Included(value) | Bound::Excluded(value) = start {
|
||||
reporter.report(
|
||||
MarkerWarningKind::LexicographicComparison,
|
||||
format!("Comparing {l_string} and {value} lexicographically"),
|
||||
);
|
||||
}
|
||||
|
||||
if let Bound::Included(value) | Bound::Excluded(value) = end {
|
||||
reporter.report(
|
||||
MarkerWarningKind::LexicographicComparison,
|
||||
format!("Comparing {l_string} and {value} lexicographically"),
|
||||
);
|
||||
}
|
||||
if let Bound::Included(value) | Bound::Excluded(value) = end {
|
||||
reporter.report(
|
||||
MarkerWarningKind::LexicographicComparison,
|
||||
format!("Comparing {l_string} and {value} lexicographically"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1201,11 +1200,11 @@ impl MarkerTree {
|
||||
/// main conjunction.
|
||||
pub fn top_level_extra_name(self) -> Option<Cow<'static, ExtraName>> {
|
||||
// Fast path: The marker is only a `extra == "..."`.
|
||||
if let MarkerTreeKind::Extra(marker) = self.kind() {
|
||||
if marker.edge(true).is_true() {
|
||||
let CanonicalMarkerValueExtra::Extra(extra) = marker.name;
|
||||
return Some(Cow::Borrowed(extra));
|
||||
}
|
||||
if let MarkerTreeKind::Extra(marker) = self.kind()
|
||||
&& marker.edge(true).is_true()
|
||||
{
|
||||
let CanonicalMarkerValueExtra::Extra(extra) = marker.name;
|
||||
return Some(Cow::Borrowed(extra));
|
||||
}
|
||||
|
||||
let extra_expression = self.top_level_extra()?;
|
||||
|
||||
@@ -822,14 +822,14 @@ impl FromStr for PlatformTag {
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(release_arch) = rest.strip_suffix("_64bit") {
|
||||
if !release_arch.is_empty() {
|
||||
return Ok(Self::Solaris {
|
||||
release_arch: release_arch.parse::<ReleaseArch>().map_err(|_| {
|
||||
ParsePlatformTagError::InvalidCharacters { tag: s.to_string() }
|
||||
})?,
|
||||
});
|
||||
}
|
||||
if let Some(release_arch) = rest.strip_suffix("_64bit")
|
||||
&& !release_arch.is_empty()
|
||||
{
|
||||
return Ok(Self::Solaris {
|
||||
release_arch: release_arch.parse::<ReleaseArch>().map_err(|_| {
|
||||
ParsePlatformTagError::InvalidCharacters { tag: s.to_string() }
|
||||
})?,
|
||||
});
|
||||
}
|
||||
|
||||
return Err(ParsePlatformTagError::InvalidArch {
|
||||
|
||||
@@ -140,10 +140,10 @@ impl Conflicts {
|
||||
for (group, specifiers) in groups {
|
||||
if let Some(includer) = group_node_idxs.get(group) {
|
||||
for specifier in specifiers {
|
||||
if let DependencyGroupSpecifier::IncludeGroup { include_group } = specifier {
|
||||
if let Some(included) = group_node_idxs.get(include_group) {
|
||||
graph.add_edge(*included, *includer, ());
|
||||
}
|
||||
if let DependencyGroupSpecifier::IncludeGroup { include_group } = specifier
|
||||
&& let Some(included) = group_node_idxs.get(include_group)
|
||||
{
|
||||
graph.add_edge(*included, *includer, ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1216,10 +1216,10 @@ fn find_python_installations_with_strategy<'a>(
|
||||
})
|
||||
}
|
||||
PythonRequest::Key(request) => {
|
||||
if let Some(version) = request.version() {
|
||||
if let Err(err) = version.check_supported() {
|
||||
return Box::new(iter::once(Err(Error::InvalidVersionRequest(err))));
|
||||
}
|
||||
if let Some(version) = request.version()
|
||||
&& let Err(err) = version.check_supported()
|
||||
{
|
||||
return Box::new(iter::once(Err(Error::InvalidVersionRequest(err))));
|
||||
}
|
||||
|
||||
Box::new({
|
||||
@@ -1292,10 +1292,10 @@ pub(crate) fn find_python_installation(
|
||||
// Iterate until the first critical error or happy result
|
||||
if !result.as_ref().err().is_none_or(Error::is_critical) {
|
||||
// Track the first non-critical error
|
||||
if first_error.is_none() {
|
||||
if let Err(err) = result {
|
||||
first_error = Some(err);
|
||||
}
|
||||
if first_error.is_none()
|
||||
&& let Err(err) = result
|
||||
{
|
||||
first_error = Some(err);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -2711,12 +2711,11 @@ impl VersionRequest {
|
||||
/// If the specifiers consist of a single `==` constraint, the version is parsed as a
|
||||
/// concrete version request (e.g., `MajorMinorPatch`) rather than a range.
|
||||
pub fn from_specifiers(specifiers: VersionSpecifiers, variant: PythonVariant) -> Self {
|
||||
if let [specifier] = specifiers.iter().as_slice() {
|
||||
if specifier.operator() == &uv_pep440::Operator::Equal {
|
||||
if let Ok(request) = Self::from_str(&specifier.version().to_string()) {
|
||||
return request;
|
||||
}
|
||||
}
|
||||
if let [specifier] = specifiers.iter().as_slice()
|
||||
&& specifier.operator() == &uv_pep440::Operator::Equal
|
||||
&& let Ok(request) = Self::from_str(&specifier.version().to_string())
|
||||
{
|
||||
return request;
|
||||
}
|
||||
Self::Range(specifiers, variant)
|
||||
}
|
||||
@@ -2820,12 +2819,12 @@ impl VersionRequest {
|
||||
}
|
||||
|
||||
// Include free-threaded variants
|
||||
if let Some(variant) = self.variant() {
|
||||
if variant != PythonVariant::Default {
|
||||
for i in 0..names.len() {
|
||||
let name = names[i].with_variant(variant);
|
||||
names.push(name);
|
||||
}
|
||||
if let Some(variant) = self.variant()
|
||||
&& variant != PythonVariant::Default
|
||||
{
|
||||
for i in 0..names.len() {
|
||||
let name = names[i].with_variant(variant);
|
||||
names.push(name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2928,14 +2927,13 @@ impl VersionRequest {
|
||||
Self::Range(_, _) => (),
|
||||
}
|
||||
|
||||
if self.is_freethreaded() {
|
||||
if let Self::MajorMinor(major, minor, _) = self.clone().without_patch() {
|
||||
if (major, minor) < (3, 13) {
|
||||
return Err(format!(
|
||||
"Python <3.13 does not support free-threading but {self} was requested."
|
||||
));
|
||||
}
|
||||
}
|
||||
if self.is_freethreaded()
|
||||
&& let Self::MajorMinor(major, minor, _) = self.clone().without_patch()
|
||||
&& (major, minor) < (3, 13)
|
||||
{
|
||||
return Err(format!(
|
||||
"Python <3.13 does not support free-threading but {self} was requested."
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -236,22 +236,22 @@ pub struct PlatformRequest {
|
||||
impl PlatformRequest {
|
||||
/// Check if this platform request is satisfied by a platform.
|
||||
pub(crate) fn matches(&self, platform: &Platform) -> bool {
|
||||
if let Some(os) = self.os {
|
||||
if !platform.os.supports(os) {
|
||||
return false;
|
||||
}
|
||||
if let Some(os) = self.os
|
||||
&& !platform.os.supports(os)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if let Some(arch) = self.arch {
|
||||
if !arch.satisfied_by(platform) {
|
||||
return false;
|
||||
}
|
||||
if let Some(arch) = self.arch
|
||||
&& !arch.satisfied_by(platform)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if let Some(libc) = self.libc {
|
||||
if platform.libc != libc {
|
||||
return false;
|
||||
}
|
||||
if let Some(libc) = self.libc
|
||||
&& platform.libc != libc
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
@@ -555,10 +555,10 @@ impl PythonDownloadRequest {
|
||||
return false;
|
||||
}
|
||||
|
||||
if let Some(implementation) = &self.implementation {
|
||||
if key.implementation != LenientImplementationName::from(*implementation) {
|
||||
return false;
|
||||
}
|
||||
if let Some(implementation) = &self.implementation
|
||||
&& key.implementation != LenientImplementationName::from(*implementation)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// If we don't allow pre-releases, don't match a key with a pre-release tag
|
||||
if !self.allows_prereleases() && key.prerelease.is_some() {
|
||||
@@ -573,10 +573,10 @@ impl PythonDownloadRequest {
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if let Some(variant) = version.variant() {
|
||||
if variant != key.variant {
|
||||
return false;
|
||||
}
|
||||
if let Some(variant) = version.variant()
|
||||
&& variant != key.variant
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
@@ -634,14 +634,14 @@ impl PythonDownloadRequest {
|
||||
|
||||
pub(crate) fn satisfied_by_interpreter(&self, interpreter: &Interpreter) -> bool {
|
||||
let executable = interpreter.sys_executable().display();
|
||||
if let Some(version) = self.version() {
|
||||
if !version.matches_interpreter(interpreter) {
|
||||
let interpreter_version = interpreter.python_version();
|
||||
debug!(
|
||||
"Skipping interpreter at `{executable}`: version `{interpreter_version}` does not match request `{version}`"
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if let Some(version) = self.version()
|
||||
&& !version.matches_interpreter(interpreter)
|
||||
{
|
||||
let interpreter_version = interpreter.python_version();
|
||||
debug!(
|
||||
"Skipping interpreter at `{executable}`: version `{interpreter_version}` does not match request `{version}`"
|
||||
);
|
||||
return false;
|
||||
}
|
||||
let platform = self.platform();
|
||||
let interpreter_platform = Platform::from(interpreter.platform());
|
||||
@@ -651,14 +651,14 @@ impl PythonDownloadRequest {
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if let Some(implementation) = self.implementation() {
|
||||
if !implementation.matches_interpreter(interpreter) {
|
||||
debug!(
|
||||
"Skipping interpreter at `{executable}`: implementation `{}` does not match request `{implementation}`",
|
||||
interpreter.implementation_name(),
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if let Some(implementation) = self.implementation()
|
||||
&& !implementation.matches_interpreter(interpreter)
|
||||
{
|
||||
debug!(
|
||||
"Skipping interpreter at `{executable}`: implementation `{}` does not match request `{implementation}`",
|
||||
interpreter.implementation_name(),
|
||||
);
|
||||
return false;
|
||||
}
|
||||
true
|
||||
}
|
||||
@@ -997,13 +997,12 @@ impl ManagedPythonDownloadList {
|
||||
return Ok(download);
|
||||
}
|
||||
|
||||
if !request.allows_prereleases() {
|
||||
if let Some(download) = self
|
||||
if !request.allows_prereleases()
|
||||
&& let Some(download) = self
|
||||
.iter_matching(&request.clone().with_prereleases(true))
|
||||
.next()
|
||||
{
|
||||
return Ok(download);
|
||||
}
|
||||
{
|
||||
return Ok(download);
|
||||
}
|
||||
|
||||
Err(Error::NoDownloadFound(request.clone()))
|
||||
|
||||
@@ -52,26 +52,26 @@ impl FromStr for PythonVersion {
|
||||
if version.epoch() != 0 {
|
||||
return Err(format!("Python version `{s}` has a non-zero epoch"));
|
||||
}
|
||||
if let Some(major) = version.release().first() {
|
||||
if u8::try_from(*major).is_err() {
|
||||
return Err(format!(
|
||||
"Python version `{s}` has an invalid major version ({major})"
|
||||
));
|
||||
}
|
||||
if let Some(major) = version.release().first()
|
||||
&& u8::try_from(*major).is_err()
|
||||
{
|
||||
return Err(format!(
|
||||
"Python version `{s}` has an invalid major version ({major})"
|
||||
));
|
||||
}
|
||||
if let Some(minor) = version.release().get(1) {
|
||||
if u8::try_from(*minor).is_err() {
|
||||
return Err(format!(
|
||||
"Python version `{s}` has an invalid minor version ({minor})"
|
||||
));
|
||||
}
|
||||
if let Some(minor) = version.release().get(1)
|
||||
&& u8::try_from(*minor).is_err()
|
||||
{
|
||||
return Err(format!(
|
||||
"Python version `{s}` has an invalid minor version ({minor})"
|
||||
));
|
||||
}
|
||||
if let Some(patch) = version.release().get(2) {
|
||||
if u8::try_from(*patch).is_err() {
|
||||
return Err(format!(
|
||||
"Python version `{s}` has an invalid patch version ({patch})"
|
||||
));
|
||||
}
|
||||
if let Some(patch) = version.release().get(2)
|
||||
&& u8::try_from(*patch).is_err()
|
||||
{
|
||||
return Err(format!(
|
||||
"Python version `{s}` has an invalid patch version ({patch})"
|
||||
));
|
||||
}
|
||||
|
||||
Ok(Self(version))
|
||||
|
||||
@@ -317,12 +317,12 @@ impl PyVenvConfiguration {
|
||||
let mut lines = content.lines().map(Cow::Borrowed).collect::<Vec<_>>();
|
||||
let mut found = false;
|
||||
for line in &mut lines {
|
||||
if let Some((lhs, _)) = line.split_once('=') {
|
||||
if lhs.trim() == key {
|
||||
*line = Cow::Owned(format!("{key} = {value}"));
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if let Some((lhs, _)) = line.split_once('=')
|
||||
&& lhs.trim() == key
|
||||
{
|
||||
*line = Cow::Owned(format!("{key} = {value}"));
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
|
||||
@@ -565,12 +565,12 @@ impl RequirementsSpecification {
|
||||
}
|
||||
|
||||
if let Some(index_url) = source.index_url {
|
||||
if let Some(existing) = spec.index_url {
|
||||
if CanonicalUrl::new(index_url.url()) != CanonicalUrl::new(existing.url()) {
|
||||
return Err(anyhow::anyhow!(
|
||||
"Multiple index URLs specified: `{existing}` vs. `{index_url}`",
|
||||
));
|
||||
}
|
||||
if let Some(existing) = spec.index_url
|
||||
&& CanonicalUrl::new(index_url.url()) != CanonicalUrl::new(existing.url())
|
||||
{
|
||||
return Err(anyhow::anyhow!(
|
||||
"Multiple index URLs specified: `{existing}` vs. `{index_url}`",
|
||||
));
|
||||
}
|
||||
spec.index_url = Some(index_url);
|
||||
}
|
||||
@@ -603,12 +603,12 @@ impl RequirementsSpecification {
|
||||
spec.constraints.extend(source.constraints);
|
||||
|
||||
if let Some(index_url) = source.index_url {
|
||||
if let Some(existing) = spec.index_url {
|
||||
if CanonicalUrl::new(index_url.url()) != CanonicalUrl::new(existing.url()) {
|
||||
return Err(anyhow::anyhow!(
|
||||
"Multiple index URLs specified: `{existing}` vs. `{index_url}`",
|
||||
));
|
||||
}
|
||||
if let Some(existing) = spec.index_url
|
||||
&& CanonicalUrl::new(index_url.url()) != CanonicalUrl::new(existing.url())
|
||||
{
|
||||
return Err(anyhow::anyhow!(
|
||||
"Multiple index URLs specified: `{existing}` vs. `{index_url}`",
|
||||
));
|
||||
}
|
||||
spec.index_url = Some(index_url);
|
||||
}
|
||||
@@ -627,12 +627,12 @@ impl RequirementsSpecification {
|
||||
spec.overrides.extend(source.overrides);
|
||||
|
||||
if let Some(index_url) = source.index_url {
|
||||
if let Some(existing) = spec.index_url {
|
||||
if CanonicalUrl::new(index_url.url()) != CanonicalUrl::new(existing.url()) {
|
||||
return Err(anyhow::anyhow!(
|
||||
"Multiple index URLs specified: `{existing}` vs. `{index_url}`",
|
||||
));
|
||||
}
|
||||
if let Some(existing) = spec.index_url
|
||||
&& CanonicalUrl::new(index_url.url()) != CanonicalUrl::new(existing.url())
|
||||
{
|
||||
return Err(anyhow::anyhow!(
|
||||
"Multiple index URLs specified: `{existing}` vs. `{index_url}`",
|
||||
));
|
||||
}
|
||||
spec.index_url = Some(index_url);
|
||||
}
|
||||
|
||||
@@ -190,23 +190,22 @@ impl<'a, Context: BuildContext> NamedRequirementsResolver<'a, Context> {
|
||||
}
|
||||
|
||||
// Read Poetry-specific metadata from the `pyproject.toml`.
|
||||
if let Some(tool) = pyproject.tool {
|
||||
if let Some(poetry) = tool.poetry {
|
||||
if let Some(name) = poetry.name {
|
||||
debug!(
|
||||
"Found Poetry metadata for {path} in `pyproject.toml` ({name})",
|
||||
path = parsed_directory_url.install_path.display(),
|
||||
name = name
|
||||
);
|
||||
return Ok(uv_pep508::Requirement {
|
||||
name,
|
||||
extras: requirement.extras,
|
||||
version_or_url: Some(VersionOrUrl::Url(requirement.url)),
|
||||
marker: requirement.marker,
|
||||
origin: requirement.origin,
|
||||
});
|
||||
}
|
||||
}
|
||||
if let Some(tool) = pyproject.tool
|
||||
&& let Some(poetry) = tool.poetry
|
||||
&& let Some(name) = poetry.name
|
||||
{
|
||||
debug!(
|
||||
"Found Poetry metadata for {path} in `pyproject.toml` ({name})",
|
||||
path = parsed_directory_url.install_path.display(),
|
||||
name = name
|
||||
);
|
||||
return Ok(uv_pep508::Requirement {
|
||||
name,
|
||||
extras: requirement.extras,
|
||||
version_or_url: Some(VersionOrUrl::Url(requirement.url)),
|
||||
marker: requirement.marker,
|
||||
origin: requirement.origin,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,23 +219,22 @@ impl<'a, Context: BuildContext> NamedRequirementsResolver<'a, Context> {
|
||||
ini.read(contents).ok()
|
||||
})
|
||||
{
|
||||
if let Some(section) = setup_cfg.get("metadata") {
|
||||
if let Some(Some(name)) = section.get("name") {
|
||||
if let Ok(name) = PackageName::from_str(name) {
|
||||
debug!(
|
||||
"Found setuptools metadata for {path} in `setup.cfg` ({name})",
|
||||
path = parsed_directory_url.install_path.display(),
|
||||
name = name
|
||||
);
|
||||
return Ok(uv_pep508::Requirement {
|
||||
name,
|
||||
extras: requirement.extras,
|
||||
version_or_url: Some(VersionOrUrl::Url(requirement.url)),
|
||||
marker: requirement.marker,
|
||||
origin: requirement.origin,
|
||||
});
|
||||
}
|
||||
}
|
||||
if let Some(section) = setup_cfg.get("metadata")
|
||||
&& let Some(Some(name)) = section.get("name")
|
||||
&& let Ok(name) = PackageName::from_str(name)
|
||||
{
|
||||
debug!(
|
||||
"Found setuptools metadata for {path} in `setup.cfg` ({name})",
|
||||
path = parsed_directory_url.install_path.display(),
|
||||
name = name
|
||||
);
|
||||
return Ok(uv_pep508::Requirement {
|
||||
name,
|
||||
extras: requirement.extras,
|
||||
version_or_url: Some(VersionOrUrl::Url(requirement.url)),
|
||||
marker: requirement.marker,
|
||||
origin: requirement.origin,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -123,14 +123,12 @@ impl CandidateSelector {
|
||||
};
|
||||
|
||||
// If we're not upgrading, we should prefer the already-installed distribution.
|
||||
if !upgrade {
|
||||
if let Some(installed) = installed {
|
||||
trace!(
|
||||
"Using installed {} {} that satisfies {range}",
|
||||
installed.name, installed.version
|
||||
);
|
||||
return Some(installed);
|
||||
}
|
||||
if !upgrade && let Some(installed) = installed {
|
||||
trace!(
|
||||
"Using installed {} {} that satisfies {range}",
|
||||
installed.name, installed.version
|
||||
);
|
||||
return Some(installed);
|
||||
}
|
||||
|
||||
// Otherwise, find the best candidate from the version maps.
|
||||
@@ -140,21 +138,21 @@ impl CandidateSelector {
|
||||
//
|
||||
// If the already-installed version is _more_ compatible than the best candidate
|
||||
// from the version maps, use the installed version.
|
||||
if let Some(installed) = installed {
|
||||
if compatible.as_ref().is_none_or(|compatible| {
|
||||
if let Some(installed) = installed
|
||||
&& compatible.as_ref().is_none_or(|compatible| {
|
||||
let highest = self.use_highest_version(package_name, env);
|
||||
if highest {
|
||||
installed.version() >= compatible.version()
|
||||
} else {
|
||||
installed.version() <= compatible.version()
|
||||
}
|
||||
}) {
|
||||
trace!(
|
||||
"Using installed {} {} that satisfies {range}",
|
||||
installed.name, installed.version
|
||||
);
|
||||
return Some(installed);
|
||||
}
|
||||
})
|
||||
{
|
||||
trace!(
|
||||
"Using installed {} {} that satisfies {range}",
|
||||
installed.name, installed.version
|
||||
);
|
||||
return Some(installed);
|
||||
}
|
||||
|
||||
compatible
|
||||
|
||||
@@ -1671,32 +1671,32 @@ impl Source {
|
||||
|| rev.is_some()
|
||||
|| matches!(lfs, GitLfsSetting::Enabled { .. }))
|
||||
{
|
||||
if let Some(sources) = existing_sources {
|
||||
if let Some(package_sources) = sources.get(name) {
|
||||
for existing_source in package_sources.iter() {
|
||||
if let Self::Git {
|
||||
git,
|
||||
subdirectory,
|
||||
path,
|
||||
marker,
|
||||
extra,
|
||||
group,
|
||||
..
|
||||
} = existing_source
|
||||
{
|
||||
return Ok(Some(Self::Git {
|
||||
git: git.clone(),
|
||||
subdirectory: subdirectory.clone(),
|
||||
rev,
|
||||
tag,
|
||||
branch,
|
||||
lfs: lfs.into(),
|
||||
marker: *marker,
|
||||
path: path.clone(),
|
||||
extra: extra.clone(),
|
||||
group: group.clone(),
|
||||
}));
|
||||
}
|
||||
if let Some(sources) = existing_sources
|
||||
&& let Some(package_sources) = sources.get(name)
|
||||
{
|
||||
for existing_source in package_sources.iter() {
|
||||
if let Self::Git {
|
||||
git,
|
||||
subdirectory,
|
||||
path,
|
||||
marker,
|
||||
extra,
|
||||
group,
|
||||
..
|
||||
} = existing_source
|
||||
{
|
||||
return Ok(Some(Self::Git {
|
||||
git: git.clone(),
|
||||
subdirectory: subdirectory.clone(),
|
||||
rev,
|
||||
tag,
|
||||
branch,
|
||||
lfs: lfs.into(),
|
||||
marker: *marker,
|
||||
path: path.clone(),
|
||||
extra: extra.clone(),
|
||||
group: group.clone(),
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -450,14 +450,13 @@ impl PyProjectTomlMut {
|
||||
.iter()
|
||||
.find(|table| {
|
||||
// If the index has the same name, reuse it.
|
||||
if let Some(index) = index.name.as_deref() {
|
||||
if table
|
||||
if let Some(index) = index.name.as_deref()
|
||||
&& table
|
||||
.get("name")
|
||||
.and_then(|name| name.as_str())
|
||||
.is_some_and(|name| name == index)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the index is the default, and there's another default index, reuse it.
|
||||
@@ -487,23 +486,22 @@ impl PyProjectTomlMut {
|
||||
.unwrap_or_default();
|
||||
|
||||
// If necessary, update the name.
|
||||
if let Some(index) = index.name.as_deref() {
|
||||
if table
|
||||
if let Some(index) = index.name.as_deref()
|
||||
&& table
|
||||
.get("name")
|
||||
.and_then(|name| name.as_str())
|
||||
.is_none_or(|name| name != index)
|
||||
{
|
||||
let mut formatted = Formatted::new(index.to_string());
|
||||
if let Some(value) = table.get("name").and_then(Item::as_value) {
|
||||
if let Some(prefix) = value.decor().prefix() {
|
||||
formatted.decor_mut().set_prefix(prefix.clone());
|
||||
}
|
||||
if let Some(suffix) = value.decor().suffix() {
|
||||
formatted.decor_mut().set_suffix(suffix.clone());
|
||||
}
|
||||
{
|
||||
let mut formatted = Formatted::new(index.to_string());
|
||||
if let Some(value) = table.get("name").and_then(Item::as_value) {
|
||||
if let Some(prefix) = value.decor().prefix() {
|
||||
formatted.decor_mut().set_prefix(prefix.clone());
|
||||
}
|
||||
if let Some(suffix) = value.decor().suffix() {
|
||||
formatted.decor_mut().set_suffix(suffix.clone());
|
||||
}
|
||||
table.insert("name", Value::String(formatted).into());
|
||||
}
|
||||
table.insert("name", Value::String(formatted).into());
|
||||
}
|
||||
|
||||
// If necessary, update the URL.
|
||||
@@ -547,14 +545,13 @@ impl PyProjectTomlMut {
|
||||
// Remove any replaced tables.
|
||||
existing.retain(|table| {
|
||||
// If the index has the same name, skip it.
|
||||
if let Some(index) = index.name.as_deref() {
|
||||
if table
|
||||
if let Some(index) = index.name.as_deref()
|
||||
&& table
|
||||
.get("name")
|
||||
.and_then(|name| name.as_str())
|
||||
.is_some_and(|name| name == index)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// If there's another default index, skip it.
|
||||
@@ -1168,10 +1165,10 @@ impl PyProjectTomlMut {
|
||||
|
||||
if let Some(project) = self.doc.get("project").and_then(Item::as_table) {
|
||||
// Check `project.dependencies`.
|
||||
if let Some(dependencies) = project.get("dependencies").and_then(Item::as_array) {
|
||||
if !find_dependencies(name, marker, dependencies).is_empty() {
|
||||
types.push(DependencyType::Production);
|
||||
}
|
||||
if let Some(dependencies) = project.get("dependencies").and_then(Item::as_array)
|
||||
&& !find_dependencies(name, marker, dependencies).is_empty()
|
||||
{
|
||||
types.push(DependencyType::Production);
|
||||
}
|
||||
|
||||
// Check `project.optional-dependencies`.
|
||||
@@ -1219,10 +1216,9 @@ impl PyProjectTomlMut {
|
||||
.and_then(Item::as_table)
|
||||
.and_then(|uv| uv.get("dev-dependencies"))
|
||||
.and_then(Item::as_array)
|
||||
&& !find_dependencies(name, marker, dev_dependencies).is_empty()
|
||||
{
|
||||
if !find_dependencies(name, marker, dev_dependencies).is_empty() {
|
||||
types.push(DependencyType::Dev);
|
||||
}
|
||||
types.push(DependencyType::Dev);
|
||||
}
|
||||
|
||||
types
|
||||
@@ -1648,10 +1644,11 @@ fn find_dependencies(
|
||||
) -> Vec<(usize, Requirement)> {
|
||||
let mut to_replace = Vec::new();
|
||||
for (i, dep) in deps.iter().enumerate() {
|
||||
if let Some(req) = dep.as_str().and_then(try_parse_requirement) {
|
||||
if marker.is_none_or(|m| *m == req.marker) && *name == req.name {
|
||||
to_replace.push((i, req));
|
||||
}
|
||||
if let Some(req) = dep.as_str().and_then(try_parse_requirement)
|
||||
&& marker.is_none_or(|m| *m == req.marker)
|
||||
&& *name == req.name
|
||||
{
|
||||
to_replace.push((i, req));
|
||||
}
|
||||
}
|
||||
to_replace
|
||||
|
||||
@@ -664,17 +664,16 @@ impl Workspace {
|
||||
/// Returns the set of conflicts for the workspace.
|
||||
pub fn conflicts(&self) -> Result<Conflicts, WorkspaceError> {
|
||||
let mut conflicting = Conflicts::empty();
|
||||
if self.is_non_project() {
|
||||
if let Some(root_conflicts) = self
|
||||
if self.is_non_project()
|
||||
&& let Some(root_conflicts) = self
|
||||
.pyproject_toml
|
||||
.tool
|
||||
.as_ref()
|
||||
.and_then(|tool| tool.uv.as_ref())
|
||||
.and_then(|uv| uv.conflicts.as_ref())
|
||||
{
|
||||
let mut root_conflicts = root_conflicts.to_conflicts()?;
|
||||
conflicting.append(&mut root_conflicts);
|
||||
}
|
||||
{
|
||||
let mut root_conflicts = root_conflicts.to_conflicts()?;
|
||||
conflicting.append(&mut root_conflicts);
|
||||
}
|
||||
for member in self.packages.values() {
|
||||
conflicting.append(&mut member.pyproject_toml.conflicts()?);
|
||||
@@ -979,20 +978,20 @@ impl Workspace {
|
||||
let mut workspace_members = Arc::new(workspace_members);
|
||||
|
||||
// For the cases such as `MemberDiscovery::None`, add the current project if missing.
|
||||
if let Some(root_member) = current_project {
|
||||
if !workspace_members.contains_key(&root_member.project.name) {
|
||||
assert!(matches!(
|
||||
options.members,
|
||||
MemberDiscovery::None | MemberDiscovery::Ignore(_)
|
||||
));
|
||||
debug!(
|
||||
"Adding current workspace member: `{}`",
|
||||
root_member.root.simplified_display()
|
||||
);
|
||||
if let Some(root_member) = current_project
|
||||
&& !workspace_members.contains_key(&root_member.project.name)
|
||||
{
|
||||
assert!(matches!(
|
||||
options.members,
|
||||
MemberDiscovery::None | MemberDiscovery::Ignore(_)
|
||||
));
|
||||
debug!(
|
||||
"Adding current workspace member: `{}`",
|
||||
root_member.root.simplified_display()
|
||||
);
|
||||
|
||||
Arc::make_mut(&mut workspace_members)
|
||||
.insert(root_member.project.name.clone(), root_member);
|
||||
}
|
||||
Arc::make_mut(&mut workspace_members)
|
||||
.insert(root_member.project.name.clone(), root_member);
|
||||
}
|
||||
|
||||
let workspace_sources = workspace_pyproject_toml
|
||||
|
||||
Reference in New Issue
Block a user