mirror of https://github.com/astral-sh/uv
Introduce a generic type for list operations (#14792)
We currently have two marker keys that a list, `extras` and `dependency_groups`, both from PEP 751. With the variants PEP, we will add three more. This change is broken out of the wheel variants PR to introduce generic marker list support, plus a change to use `ContainerOperator` in more places.
This commit is contained in:
parent
d052427c37
commit
f3dc457d2a
|
|
@ -32,8 +32,8 @@ pub use marker::{
|
||||||
CanonicalMarkerValueExtra, CanonicalMarkerValueString, CanonicalMarkerValueVersion,
|
CanonicalMarkerValueExtra, CanonicalMarkerValueString, CanonicalMarkerValueVersion,
|
||||||
ContainsMarkerTree, ExtraMarkerTree, ExtraOperator, InMarkerTree, MarkerEnvironment,
|
ContainsMarkerTree, ExtraMarkerTree, ExtraOperator, InMarkerTree, MarkerEnvironment,
|
||||||
MarkerEnvironmentBuilder, MarkerExpression, MarkerOperator, MarkerTree, MarkerTreeContents,
|
MarkerEnvironmentBuilder, MarkerExpression, MarkerOperator, MarkerTree, MarkerTreeContents,
|
||||||
MarkerTreeKind, MarkerValue, MarkerValueExtra, MarkerValueString, MarkerValueVersion,
|
MarkerTreeKind, MarkerValue, MarkerValueExtra, MarkerValueList, MarkerValueString,
|
||||||
MarkerWarningKind, StringMarkerTree, StringVersion, VersionMarkerTree,
|
MarkerValueVersion, MarkerWarningKind, StringMarkerTree, StringVersion, VersionMarkerTree,
|
||||||
};
|
};
|
||||||
pub use origin::RequirementOrigin;
|
pub use origin::RequirementOrigin;
|
||||||
#[cfg(feature = "non-pep508-extensions")]
|
#[cfg(feature = "non-pep508-extensions")]
|
||||||
|
|
|
||||||
|
|
@ -59,10 +59,10 @@ use uv_pep440::{Operator, Version, VersionSpecifier, release_specifier_to_range}
|
||||||
|
|
||||||
use crate::marker::MarkerValueExtra;
|
use crate::marker::MarkerValueExtra;
|
||||||
use crate::marker::lowering::{
|
use crate::marker::lowering::{
|
||||||
CanonicalMarkerValueDependencyGroup, CanonicalMarkerValueExtra, CanonicalMarkerValueString,
|
CanonicalMarkerListPair, CanonicalMarkerValueExtra, CanonicalMarkerValueString,
|
||||||
CanonicalMarkerValueVersion,
|
CanonicalMarkerValueVersion,
|
||||||
};
|
};
|
||||||
use crate::marker::tree::{ContainerOperator, MarkerValueDependencyGroup};
|
use crate::marker::tree::ContainerOperator;
|
||||||
use crate::{
|
use crate::{
|
||||||
ExtraOperator, MarkerExpression, MarkerOperator, MarkerValueString, MarkerValueVersion,
|
ExtraOperator, MarkerExpression, MarkerOperator, MarkerValueString, MarkerValueVersion,
|
||||||
};
|
};
|
||||||
|
|
@ -188,19 +188,19 @@ impl InternerGuard<'_> {
|
||||||
MarkerExpression::VersionIn {
|
MarkerExpression::VersionIn {
|
||||||
key,
|
key,
|
||||||
versions,
|
versions,
|
||||||
negated,
|
operator,
|
||||||
} => match key {
|
} => match key {
|
||||||
MarkerValueVersion::ImplementationVersion => (
|
MarkerValueVersion::ImplementationVersion => (
|
||||||
Variable::Version(CanonicalMarkerValueVersion::ImplementationVersion),
|
Variable::Version(CanonicalMarkerValueVersion::ImplementationVersion),
|
||||||
Edges::from_versions(&versions, negated),
|
Edges::from_versions(&versions, operator),
|
||||||
),
|
),
|
||||||
MarkerValueVersion::PythonFullVersion => (
|
MarkerValueVersion::PythonFullVersion => (
|
||||||
Variable::Version(CanonicalMarkerValueVersion::PythonFullVersion),
|
Variable::Version(CanonicalMarkerValueVersion::PythonFullVersion),
|
||||||
Edges::from_versions(&versions, negated),
|
Edges::from_versions(&versions, operator),
|
||||||
),
|
),
|
||||||
// Normalize `python_version` markers to `python_full_version` nodes.
|
// Normalize `python_version` markers to `python_full_version` nodes.
|
||||||
MarkerValueVersion::PythonVersion => {
|
MarkerValueVersion::PythonVersion => {
|
||||||
match Edges::from_python_versions(versions, negated) {
|
match Edges::from_python_versions(versions, operator) {
|
||||||
Ok(edges) => (
|
Ok(edges) => (
|
||||||
Variable::Version(CanonicalMarkerValueVersion::PythonFullVersion),
|
Variable::Version(CanonicalMarkerValueVersion::PythonFullVersion),
|
||||||
edges,
|
edges,
|
||||||
|
|
@ -315,6 +315,10 @@ impl InternerGuard<'_> {
|
||||||
};
|
};
|
||||||
(Variable::String(key), Edges::from_string(operator, value))
|
(Variable::String(key), Edges::from_string(operator, value))
|
||||||
}
|
}
|
||||||
|
MarkerExpression::List { pair, operator } => (
|
||||||
|
Variable::List(pair),
|
||||||
|
Edges::from_bool(operator == ContainerOperator::In),
|
||||||
|
),
|
||||||
// A variable representing the existence or absence of a particular extra.
|
// A variable representing the existence or absence of a particular extra.
|
||||||
MarkerExpression::Extra {
|
MarkerExpression::Extra {
|
||||||
name: MarkerValueExtra::Extra(extra),
|
name: MarkerValueExtra::Extra(extra),
|
||||||
|
|
@ -335,48 +339,6 @@ impl InternerGuard<'_> {
|
||||||
name: MarkerValueExtra::Arbitrary(_),
|
name: MarkerValueExtra::Arbitrary(_),
|
||||||
..
|
..
|
||||||
} => return NodeId::FALSE,
|
} => return NodeId::FALSE,
|
||||||
// A variable representing the existence or absence of a particular extra, in the
|
|
||||||
// context of a PEP 751 lockfile.
|
|
||||||
MarkerExpression::Extras {
|
|
||||||
name: MarkerValueExtra::Extra(extra),
|
|
||||||
operator: ContainerOperator::In,
|
|
||||||
} => (
|
|
||||||
Variable::Extras(CanonicalMarkerValueExtra::Extra(extra)),
|
|
||||||
Edges::from_bool(true),
|
|
||||||
),
|
|
||||||
MarkerExpression::Extras {
|
|
||||||
name: MarkerValueExtra::Extra(extra),
|
|
||||||
operator: ContainerOperator::NotIn,
|
|
||||||
} => (
|
|
||||||
Variable::Extras(CanonicalMarkerValueExtra::Extra(extra)),
|
|
||||||
Edges::from_bool(false),
|
|
||||||
),
|
|
||||||
// Invalid `extras` names are always `false`.
|
|
||||||
MarkerExpression::Extras {
|
|
||||||
name: MarkerValueExtra::Arbitrary(_),
|
|
||||||
..
|
|
||||||
} => return NodeId::FALSE,
|
|
||||||
// A variable representing the existence or absence of a particular extra, in the
|
|
||||||
// context of a PEP 751 lockfile.
|
|
||||||
MarkerExpression::DependencyGroups {
|
|
||||||
name: MarkerValueDependencyGroup::Group(group),
|
|
||||||
operator: ContainerOperator::In,
|
|
||||||
} => (
|
|
||||||
Variable::DependencyGroups(CanonicalMarkerValueDependencyGroup::Group(group)),
|
|
||||||
Edges::from_bool(true),
|
|
||||||
),
|
|
||||||
MarkerExpression::DependencyGroups {
|
|
||||||
name: MarkerValueDependencyGroup::Group(group),
|
|
||||||
operator: ContainerOperator::NotIn,
|
|
||||||
} => (
|
|
||||||
Variable::DependencyGroups(CanonicalMarkerValueDependencyGroup::Group(group)),
|
|
||||||
Edges::from_bool(false),
|
|
||||||
),
|
|
||||||
// Invalid `dependency_group` names are always `false`.
|
|
||||||
MarkerExpression::DependencyGroups {
|
|
||||||
name: MarkerValueDependencyGroup::Arbitrary(_),
|
|
||||||
..
|
|
||||||
} => return NodeId::FALSE,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.create_node(var, children)
|
self.create_node(var, children)
|
||||||
|
|
@ -1090,18 +1052,12 @@ pub(crate) enum Variable {
|
||||||
/// We keep extras at the leaves of the tree, so when simplifying extras we can
|
/// We keep extras at the leaves of the tree, so when simplifying extras we can
|
||||||
/// trivially remove the leaves without having to reconstruct the entire tree.
|
/// trivially remove the leaves without having to reconstruct the entire tree.
|
||||||
Extra(CanonicalMarkerValueExtra),
|
Extra(CanonicalMarkerValueExtra),
|
||||||
/// A variable representing the existence or absence of a given extra, in the context of a
|
/// A variable representing whether a `<value> in <key>` or `<value> not in <key>`
|
||||||
/// PEP 751 lockfile marker.
|
/// expression, where the key is a list.
|
||||||
///
|
///
|
||||||
/// We keep extras at the leaves of the tree, so when simplifying extras we can
|
/// We keep extras and groups at the leaves of the tree, so when simplifying extras we can
|
||||||
/// trivially remove the leaves without having to reconstruct the entire tree.
|
/// trivially remove the leaves without having to reconstruct the entire tree.
|
||||||
Extras(CanonicalMarkerValueExtra),
|
List(CanonicalMarkerListPair),
|
||||||
/// A variable representing the existence or absence of a given dependency group, in the context of a
|
|
||||||
/// PEP 751 lockfile marker.
|
|
||||||
///
|
|
||||||
/// We keep groups at the leaves of the tree, so when simplifying groups we can
|
|
||||||
/// trivially remove the leaves without having to reconstruct the entire tree.
|
|
||||||
DependencyGroups(CanonicalMarkerValueDependencyGroup),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Variable {
|
impl Variable {
|
||||||
|
|
@ -1279,7 +1235,10 @@ impl Edges {
|
||||||
/// Returns an [`Edges`] where values in the given range are `true`.
|
/// Returns an [`Edges`] where values in the given range are `true`.
|
||||||
///
|
///
|
||||||
/// Only for use when the `key` is a `PythonVersion`. Normalizes to `PythonFullVersion`.
|
/// Only for use when the `key` is a `PythonVersion`. Normalizes to `PythonFullVersion`.
|
||||||
fn from_python_versions(versions: Vec<Version>, negated: bool) -> Result<Edges, NodeId> {
|
fn from_python_versions(
|
||||||
|
versions: Vec<Version>,
|
||||||
|
operator: ContainerOperator,
|
||||||
|
) -> Result<Edges, NodeId> {
|
||||||
let mut range: Ranges<Version> = versions
|
let mut range: Ranges<Version> = versions
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|version| {
|
.map(|version| {
|
||||||
|
|
@ -1290,7 +1249,7 @@ impl Edges {
|
||||||
.flatten_ok()
|
.flatten_ok()
|
||||||
.collect::<Result<Ranges<_>, NodeId>>()?;
|
.collect::<Result<Ranges<_>, NodeId>>()?;
|
||||||
|
|
||||||
if negated {
|
if operator == ContainerOperator::NotIn {
|
||||||
range = range.complement();
|
range = range.complement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1300,7 +1259,7 @@ impl Edges {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an [`Edges`] where values in the given range are `true`.
|
/// Returns an [`Edges`] where values in the given range are `true`.
|
||||||
fn from_versions(versions: &[Version], negated: bool) -> Edges {
|
fn from_versions(versions: &[Version], operator: ContainerOperator) -> Edges {
|
||||||
let mut range: Ranges<Version> = versions
|
let mut range: Ranges<Version> = versions
|
||||||
.iter()
|
.iter()
|
||||||
.map(|version| {
|
.map(|version| {
|
||||||
|
|
@ -1311,7 +1270,7 @@ impl Edges {
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if negated {
|
if operator == ContainerOperator::NotIn {
|
||||||
range = range.complement();
|
range = range.complement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
use uv_normalize::{ExtraName, GroupName};
|
use uv_normalize::{ExtraName, GroupName};
|
||||||
|
|
||||||
use crate::marker::tree::MarkerValueDependencyGroup;
|
use crate::marker::tree::MarkerValueList;
|
||||||
use crate::{MarkerValueExtra, MarkerValueString, MarkerValueVersion};
|
use crate::{MarkerValueExtra, MarkerValueString, MarkerValueVersion};
|
||||||
|
|
||||||
/// Those environment markers with a PEP 440 version as value such as `python_version`
|
/// Those environment markers with a PEP 440 version as value such as `python_version`
|
||||||
|
|
@ -161,34 +161,35 @@ impl Display for CanonicalMarkerValueExtra {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The [`GroupName`] value used in `dependency_group` markers.
|
/// A key-value pair for `<value> in <key>` or `<value> not in <key>`, where the key is a list.
|
||||||
|
///
|
||||||
|
/// Used for PEP 751 markers.
|
||||||
#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
||||||
pub enum CanonicalMarkerValueDependencyGroup {
|
pub enum CanonicalMarkerListPair {
|
||||||
|
/// A valid [`ExtraName`].
|
||||||
|
Extras(ExtraName),
|
||||||
/// A valid [`GroupName`].
|
/// A valid [`GroupName`].
|
||||||
Group(GroupName),
|
DependencyGroup(GroupName),
|
||||||
|
/// For leniency, preserve invalid values.
|
||||||
|
Arbitrary { key: MarkerValueList, value: String },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CanonicalMarkerValueDependencyGroup {
|
impl CanonicalMarkerListPair {
|
||||||
/// Returns the [`GroupName`] value.
|
/// The key (RHS) of the marker expression.
|
||||||
pub fn group(&self) -> &GroupName {
|
pub(crate) fn key(&self) -> MarkerValueList {
|
||||||
match self {
|
match self {
|
||||||
Self::Group(group) => group,
|
Self::Extras(_) => MarkerValueList::Extras,
|
||||||
}
|
Self::DependencyGroup(_) => MarkerValueList::DependencyGroups,
|
||||||
|
Self::Arbitrary { key, .. } => *key,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<CanonicalMarkerValueDependencyGroup> for MarkerValueDependencyGroup {
|
/// The value (LHS) of the marker expression.
|
||||||
fn from(value: CanonicalMarkerValueDependencyGroup) -> Self {
|
pub(crate) fn value(&self) -> String {
|
||||||
match value {
|
|
||||||
CanonicalMarkerValueDependencyGroup::Group(group) => Self::Group(group),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for CanonicalMarkerValueDependencyGroup {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
match self {
|
||||||
Self::Group(group) => group.fmt(f),
|
Self::Extras(extra) => extra.to_string(),
|
||||||
|
Self::DependencyGroup(group) => group.to_string(),
|
||||||
|
Self::Arbitrary { value, .. } => value.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@ pub use lowering::{
|
||||||
pub use tree::{
|
pub use tree::{
|
||||||
ContainsMarkerTree, ExtraMarkerTree, ExtraOperator, InMarkerTree, MarkerExpression,
|
ContainsMarkerTree, ExtraMarkerTree, ExtraOperator, InMarkerTree, MarkerExpression,
|
||||||
MarkerOperator, MarkerTree, MarkerTreeContents, MarkerTreeDebugGraph, MarkerTreeKind,
|
MarkerOperator, MarkerTree, MarkerTreeContents, MarkerTreeDebugGraph, MarkerTreeKind,
|
||||||
MarkerValue, MarkerValueExtra, MarkerValueString, MarkerValueVersion, MarkerWarningKind,
|
MarkerValue, MarkerValueExtra, MarkerValueList, MarkerValueString, MarkerValueVersion,
|
||||||
StringMarkerTree, StringVersion, VersionMarkerTree,
|
MarkerWarningKind, StringMarkerTree, StringVersion, VersionMarkerTree,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// `serde` helpers for [`MarkerTree`].
|
/// `serde` helpers for [`MarkerTree`].
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,8 @@ use uv_pep440::{Version, VersionPattern, VersionSpecifier};
|
||||||
|
|
||||||
use crate::cursor::Cursor;
|
use crate::cursor::Cursor;
|
||||||
use crate::marker::MarkerValueExtra;
|
use crate::marker::MarkerValueExtra;
|
||||||
use crate::marker::tree::{ContainerOperator, MarkerValueContains, MarkerValueDependencyGroup};
|
use crate::marker::lowering::CanonicalMarkerListPair;
|
||||||
|
use crate::marker::tree::{ContainerOperator, MarkerValueList};
|
||||||
use crate::{
|
use crate::{
|
||||||
ExtraOperator, MarkerExpression, MarkerOperator, MarkerTree, MarkerValue, MarkerValueString,
|
ExtraOperator, MarkerExpression, MarkerOperator, MarkerTree, MarkerValue, MarkerValueString,
|
||||||
MarkerValueVersion, MarkerWarningKind, Pep508Error, Pep508ErrorSource, Pep508Url, Reporter,
|
MarkerValueVersion, MarkerWarningKind, Pep508Error, Pep508ErrorSource, Pep508Url, Reporter,
|
||||||
|
|
@ -169,6 +170,7 @@ pub(crate) fn parse_marker_key_op_value<T: Pep508Url>(
|
||||||
reporter: &mut impl Reporter,
|
reporter: &mut impl Reporter,
|
||||||
) -> Result<Option<MarkerExpression>, Pep508Error<T>> {
|
) -> Result<Option<MarkerExpression>, Pep508Error<T>> {
|
||||||
cursor.eat_whitespace();
|
cursor.eat_whitespace();
|
||||||
|
let start = cursor.pos();
|
||||||
let l_value = parse_marker_value(cursor, reporter)?;
|
let l_value = parse_marker_value(cursor, reporter)?;
|
||||||
cursor.eat_whitespace();
|
cursor.eat_whitespace();
|
||||||
// "not in" and "in" must be preceded by whitespace. We must already have matched a whitespace
|
// "not in" and "in" must be preceded by whitespace. We must already have matched a whitespace
|
||||||
|
|
@ -177,6 +179,7 @@ pub(crate) fn parse_marker_key_op_value<T: Pep508Url>(
|
||||||
let operator = parse_marker_operator(cursor)?;
|
let operator = parse_marker_operator(cursor)?;
|
||||||
cursor.eat_whitespace();
|
cursor.eat_whitespace();
|
||||||
let r_value = parse_marker_value(cursor, reporter)?;
|
let r_value = parse_marker_value(cursor, reporter)?;
|
||||||
|
let len = cursor.pos() - start;
|
||||||
|
|
||||||
// Convert a `<marker_value> <marker_op> <marker_value>` expression into its
|
// Convert a `<marker_value> <marker_op> <marker_value>` expression into its
|
||||||
// typed equivalent.
|
// typed equivalent.
|
||||||
|
|
@ -211,7 +214,7 @@ pub(crate) fn parse_marker_key_op_value<T: Pep508Url>(
|
||||||
MarkerValue::Extra
|
MarkerValue::Extra
|
||||||
| MarkerValue::MarkerEnvVersion(_)
|
| MarkerValue::MarkerEnvVersion(_)
|
||||||
| MarkerValue::MarkerEnvString(_)
|
| MarkerValue::MarkerEnvString(_)
|
||||||
| MarkerValue::MarkerEnvContains(_) => {
|
| MarkerValue::MarkerEnvList(_) => {
|
||||||
reporter.report(
|
reporter.report(
|
||||||
MarkerWarningKind::MarkerMarkerComparison,
|
MarkerWarningKind::MarkerMarkerComparison,
|
||||||
"Comparing two markers with each other doesn't make any sense,
|
"Comparing two markers with each other doesn't make any sense,
|
||||||
|
|
@ -239,12 +242,23 @@ pub(crate) fn parse_marker_key_op_value<T: Pep508Url>(
|
||||||
value,
|
value,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// `extras in "test"` or `dependency_groups not in "dev"` are invalid.
|
||||||
|
MarkerValue::MarkerEnvList(key) => {
|
||||||
|
return Err(Pep508Error {
|
||||||
|
message: Pep508ErrorSource::String(format!(
|
||||||
|
"The marker {key} must be on the right hand side of the expression"
|
||||||
|
)),
|
||||||
|
start,
|
||||||
|
len,
|
||||||
|
input: cursor.to_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
// `extra == '...'`
|
// `extra == '...'`
|
||||||
MarkerValue::Extra => {
|
MarkerValue::Extra => {
|
||||||
let value = match r_value {
|
let value = match r_value {
|
||||||
MarkerValue::MarkerEnvVersion(_)
|
MarkerValue::MarkerEnvVersion(_)
|
||||||
| MarkerValue::MarkerEnvString(_)
|
| MarkerValue::MarkerEnvString(_)
|
||||||
| MarkerValue::MarkerEnvContains(_)
|
| MarkerValue::MarkerEnvList(_)
|
||||||
| MarkerValue::Extra => {
|
| MarkerValue::Extra => {
|
||||||
reporter.report(
|
reporter.report(
|
||||||
MarkerWarningKind::ExtraInvalidComparison,
|
MarkerWarningKind::ExtraInvalidComparison,
|
||||||
|
|
@ -274,16 +288,56 @@ pub(crate) fn parse_marker_key_op_value<T: Pep508Url>(
|
||||||
operator: operator.invert(),
|
operator: operator.invert(),
|
||||||
value: l_string,
|
value: l_string,
|
||||||
}),
|
}),
|
||||||
|
// `"test" in extras` or `"dev" in dependency_groups`
|
||||||
|
MarkerValue::MarkerEnvList(key) => {
|
||||||
|
let operator =
|
||||||
|
ContainerOperator::from_marker_operator(operator).ok_or_else(|| {
|
||||||
|
Pep508Error {
|
||||||
|
message: Pep508ErrorSource::String(format!(
|
||||||
|
"The operator {operator} is not supported with the marker {key}, only the `in` and `not in` operators are supported"
|
||||||
|
)),
|
||||||
|
start,
|
||||||
|
len,
|
||||||
|
input: cursor.to_string(),
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
let pair = match key {
|
||||||
|
// `'...' in extras`
|
||||||
|
MarkerValueList::Extras => match ExtraName::from_str(&l_string) {
|
||||||
|
Ok(name) => CanonicalMarkerListPair::Extras(name),
|
||||||
|
Err(err) => {
|
||||||
|
reporter.report(
|
||||||
|
MarkerWarningKind::ExtrasInvalidComparison,
|
||||||
|
format!("Expected extra name (found `{l_string}`): {err}"),
|
||||||
|
);
|
||||||
|
CanonicalMarkerListPair::Arbitrary {
|
||||||
|
key,
|
||||||
|
value: l_string.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// `'...' in dependency_groups`
|
||||||
|
MarkerValueList::DependencyGroups => {
|
||||||
|
match GroupName::from_str(&l_string) {
|
||||||
|
Ok(name) => CanonicalMarkerListPair::DependencyGroup(name),
|
||||||
|
Err(err) => {
|
||||||
|
reporter.report(
|
||||||
|
MarkerWarningKind::ExtrasInvalidComparison,
|
||||||
|
format!("Expected dependency group name (found `{l_string}`): {err}"),
|
||||||
|
);
|
||||||
|
CanonicalMarkerListPair::Arbitrary {
|
||||||
|
key,
|
||||||
|
value: l_string.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(MarkerExpression::List { pair, operator })
|
||||||
|
}
|
||||||
// `'...' == extra`
|
// `'...' == extra`
|
||||||
MarkerValue::Extra => parse_extra_expr(operator, &l_string, reporter),
|
MarkerValue::Extra => parse_extra_expr(operator, &l_string, reporter),
|
||||||
// `'...' in extras`
|
|
||||||
MarkerValue::MarkerEnvContains(MarkerValueContains::Extras) => {
|
|
||||||
parse_extras_expr(operator, &l_string, reporter)
|
|
||||||
}
|
|
||||||
// `'...' in dependency_groups`
|
|
||||||
MarkerValue::MarkerEnvContains(MarkerValueContains::DependencyGroups) => {
|
|
||||||
parse_dependency_groups_expr(operator, &l_string, reporter)
|
|
||||||
}
|
|
||||||
// `'...' == '...'`, doesn't make much sense
|
// `'...' == '...'`, doesn't make much sense
|
||||||
MarkerValue::QuotedString(_) => {
|
MarkerValue::QuotedString(_) => {
|
||||||
// Not even pypa/packaging 22.0 supports this
|
// Not even pypa/packaging 22.0 supports this
|
||||||
|
|
@ -300,16 +354,6 @@ pub(crate) fn parse_marker_key_op_value<T: Pep508Url>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MarkerValue::MarkerEnvContains(key) => {
|
|
||||||
reporter.report(
|
|
||||||
MarkerWarningKind::Pep440Error,
|
|
||||||
format!(
|
|
||||||
"The `{key}` marker must be used as '...' in {key}' or '... not in {key}',
|
|
||||||
found `{key} {operator} {r_value}`, will be ignored"
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(expr)
|
Ok(expr)
|
||||||
|
|
@ -340,10 +384,7 @@ fn parse_version_in_expr(
|
||||||
value: &str,
|
value: &str,
|
||||||
reporter: &mut impl Reporter,
|
reporter: &mut impl Reporter,
|
||||||
) -> Option<MarkerExpression> {
|
) -> Option<MarkerExpression> {
|
||||||
if !matches!(operator, MarkerOperator::In | MarkerOperator::NotIn) {
|
let operator = ContainerOperator::from_marker_operator(operator)?;
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let negated = matches!(operator, MarkerOperator::NotIn);
|
|
||||||
|
|
||||||
let mut cursor = Cursor::new(value);
|
let mut cursor = Cursor::new(value);
|
||||||
let mut versions = Vec::new();
|
let mut versions = Vec::new();
|
||||||
|
|
@ -379,7 +420,7 @@ fn parse_version_in_expr(
|
||||||
Some(MarkerExpression::VersionIn {
|
Some(MarkerExpression::VersionIn {
|
||||||
key,
|
key,
|
||||||
versions,
|
versions,
|
||||||
negated,
|
operator,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -519,68 +560,6 @@ fn parse_extra_expr(
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates an instance of [`MarkerExpression::Extras`] with the given values, falling back to
|
|
||||||
/// [`MarkerExpression::Arbitrary`] on failure.
|
|
||||||
fn parse_extras_expr(
|
|
||||||
operator: MarkerOperator,
|
|
||||||
value: &str,
|
|
||||||
reporter: &mut impl Reporter,
|
|
||||||
) -> Option<MarkerExpression> {
|
|
||||||
let name = match ExtraName::from_str(value) {
|
|
||||||
Ok(name) => MarkerValueExtra::Extra(name),
|
|
||||||
Err(err) => {
|
|
||||||
reporter.report(
|
|
||||||
MarkerWarningKind::ExtrasInvalidComparison,
|
|
||||||
format!("Expected extra name (found `{value}`): {err}"),
|
|
||||||
);
|
|
||||||
MarkerValueExtra::Arbitrary(value.to_string())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(operator) = ContainerOperator::from_marker_operator(operator) {
|
|
||||||
return Some(MarkerExpression::Extras { operator, name });
|
|
||||||
}
|
|
||||||
|
|
||||||
reporter.report(
|
|
||||||
MarkerWarningKind::ExtrasInvalidComparison,
|
|
||||||
"Comparing `extras` with any operator other than `in` or `not in` is wrong and will be ignored"
|
|
||||||
.to_string(),
|
|
||||||
);
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates an instance of [`MarkerExpression::DependencyGroups`] with the given values, falling
|
|
||||||
/// back to [`MarkerExpression::Arbitrary`] on failure.
|
|
||||||
fn parse_dependency_groups_expr(
|
|
||||||
operator: MarkerOperator,
|
|
||||||
value: &str,
|
|
||||||
reporter: &mut impl Reporter,
|
|
||||||
) -> Option<MarkerExpression> {
|
|
||||||
let name = match GroupName::from_str(value) {
|
|
||||||
Ok(name) => MarkerValueDependencyGroup::Group(name),
|
|
||||||
Err(err) => {
|
|
||||||
reporter.report(
|
|
||||||
MarkerWarningKind::ExtrasInvalidComparison,
|
|
||||||
format!("Expected extra name (found `{value}`): {err}"),
|
|
||||||
);
|
|
||||||
MarkerValueDependencyGroup::Arbitrary(value.to_string())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(operator) = ContainerOperator::from_marker_operator(operator) {
|
|
||||||
return Some(MarkerExpression::DependencyGroups { operator, name });
|
|
||||||
}
|
|
||||||
|
|
||||||
reporter.report(
|
|
||||||
MarkerWarningKind::ExtrasInvalidComparison,
|
|
||||||
"Comparing `extras` with any operator other than `in` or `not in` is wrong and will be ignored"
|
|
||||||
.to_string(),
|
|
||||||
);
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ```text
|
/// ```text
|
||||||
/// marker_expr = marker_var:l marker_op:o marker_var:r -> (o, l, r)
|
/// marker_expr = marker_var:l marker_op:o marker_var:r -> (o, l, r)
|
||||||
/// | wsp* '(' marker:m wsp* ')' -> m
|
/// | wsp* '(' marker:m wsp* ')' -> m
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,22 @@ fn collect_dnf(
|
||||||
path.pop();
|
path.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
MarkerTreeKind::List(marker) => {
|
||||||
|
for (is_high, tree) in marker.children() {
|
||||||
|
let expr = MarkerExpression::List {
|
||||||
|
pair: marker.pair().clone(),
|
||||||
|
operator: if is_high {
|
||||||
|
ContainerOperator::In
|
||||||
|
} else {
|
||||||
|
ContainerOperator::NotIn
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
path.push(expr);
|
||||||
|
collect_dnf(tree, dnf, path);
|
||||||
|
path.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
MarkerTreeKind::Extra(marker) => {
|
MarkerTreeKind::Extra(marker) => {
|
||||||
for (value, tree) in marker.children() {
|
for (value, tree) in marker.children() {
|
||||||
let operator = if value {
|
let operator = if value {
|
||||||
|
|
@ -175,42 +191,6 @@ fn collect_dnf(
|
||||||
operator,
|
operator,
|
||||||
};
|
};
|
||||||
|
|
||||||
path.push(expr);
|
|
||||||
collect_dnf(tree, dnf, path);
|
|
||||||
path.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MarkerTreeKind::Extras(marker) => {
|
|
||||||
for (value, tree) in marker.children() {
|
|
||||||
let operator = if value {
|
|
||||||
ContainerOperator::In
|
|
||||||
} else {
|
|
||||||
ContainerOperator::NotIn
|
|
||||||
};
|
|
||||||
|
|
||||||
let expr = MarkerExpression::Extras {
|
|
||||||
name: marker.name().clone().into(),
|
|
||||||
operator,
|
|
||||||
};
|
|
||||||
|
|
||||||
path.push(expr);
|
|
||||||
collect_dnf(tree, dnf, path);
|
|
||||||
path.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MarkerTreeKind::DependencyGroups(marker) => {
|
|
||||||
for (value, tree) in marker.children() {
|
|
||||||
let operator = if value {
|
|
||||||
ContainerOperator::In
|
|
||||||
} else {
|
|
||||||
ContainerOperator::NotIn
|
|
||||||
};
|
|
||||||
|
|
||||||
let expr = MarkerExpression::DependencyGroups {
|
|
||||||
name: marker.name().clone().into(),
|
|
||||||
operator,
|
|
||||||
};
|
|
||||||
|
|
||||||
path.push(expr);
|
path.push(expr);
|
||||||
collect_dnf(tree, dnf, path);
|
collect_dnf(tree, dnf, path);
|
||||||
path.pop();
|
path.pop();
|
||||||
|
|
@ -433,18 +413,18 @@ fn is_negation(left: &MarkerExpression, right: &MarkerExpression) -> bool {
|
||||||
MarkerExpression::VersionIn {
|
MarkerExpression::VersionIn {
|
||||||
key,
|
key,
|
||||||
versions,
|
versions,
|
||||||
negated,
|
operator,
|
||||||
} => {
|
} => {
|
||||||
let MarkerExpression::VersionIn {
|
let MarkerExpression::VersionIn {
|
||||||
key: key2,
|
key: key2,
|
||||||
versions: versions2,
|
versions: versions2,
|
||||||
negated: negated2,
|
operator: operator2,
|
||||||
} = right
|
} = right
|
||||||
else {
|
else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
key == key2 && versions == versions2 && negated != negated2
|
key == key2 && versions == versions2 && operator != operator2
|
||||||
}
|
}
|
||||||
MarkerExpression::String {
|
MarkerExpression::String {
|
||||||
key,
|
key,
|
||||||
|
|
@ -477,27 +457,16 @@ fn is_negation(left: &MarkerExpression, right: &MarkerExpression) -> bool {
|
||||||
|
|
||||||
name == name2 && operator.negate() == *operator2
|
name == name2 && operator.negate() == *operator2
|
||||||
}
|
}
|
||||||
MarkerExpression::Extras { name, operator } => {
|
MarkerExpression::List { pair, operator } => {
|
||||||
let MarkerExpression::Extras {
|
let MarkerExpression::List {
|
||||||
name: name2,
|
pair: pair2,
|
||||||
operator: operator2,
|
operator: operator2,
|
||||||
} = right
|
} = right
|
||||||
else {
|
else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
name == name2 && *operator == operator2.negate()
|
pair == pair2 && operator != operator2
|
||||||
}
|
|
||||||
MarkerExpression::DependencyGroups { name, operator } => {
|
|
||||||
let MarkerExpression::DependencyGroups {
|
|
||||||
name: name2,
|
|
||||||
operator: operator2,
|
|
||||||
} = right
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
name == name2 && *operator == operator2.negate()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,12 @@ use super::algebra::{Edges, INTERNER, NodeId, Variable};
|
||||||
use super::simplify;
|
use super::simplify;
|
||||||
use crate::cursor::Cursor;
|
use crate::cursor::Cursor;
|
||||||
use crate::marker::lowering::{
|
use crate::marker::lowering::{
|
||||||
CanonicalMarkerValueDependencyGroup, CanonicalMarkerValueExtra, CanonicalMarkerValueString,
|
CanonicalMarkerListPair, CanonicalMarkerValueString, CanonicalMarkerValueVersion,
|
||||||
CanonicalMarkerValueVersion,
|
|
||||||
};
|
};
|
||||||
use crate::marker::parse;
|
use crate::marker::parse;
|
||||||
use crate::{
|
use crate::{
|
||||||
MarkerEnvironment, Pep508Error, Pep508ErrorSource, Pep508Url, Reporter, TracingReporter,
|
CanonicalMarkerValueExtra, MarkerEnvironment, Pep508Error, Pep508ErrorSource, Pep508Url,
|
||||||
|
Reporter, TracingReporter,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Ways in which marker evaluation can fail
|
/// Ways in which marker evaluation can fail
|
||||||
|
|
@ -126,16 +126,18 @@ impl Display for MarkerValueString {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Those markers with exclusively `in` and `not in` operators (PEP 751)
|
/// Those markers with exclusively `in` and `not in` operators.
|
||||||
#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
///
|
||||||
pub enum MarkerValueContains {
|
/// Contains PEP 751 lockfile markers.
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
||||||
|
pub enum MarkerValueList {
|
||||||
/// `extras`. This one is special because it's a list, and user-provided
|
/// `extras`. This one is special because it's a list, and user-provided
|
||||||
Extras,
|
Extras,
|
||||||
/// `dependency_groups`. This one is special because it's a list, and user-provided
|
/// `dependency_groups`. This one is special because it's a list, and user-provided
|
||||||
DependencyGroups,
|
DependencyGroups,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for MarkerValueContains {
|
impl Display for MarkerValueList {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::Extras => f.write_str("extras"),
|
Self::Extras => f.write_str("extras"),
|
||||||
|
|
@ -153,10 +155,10 @@ pub enum MarkerValue {
|
||||||
MarkerEnvVersion(MarkerValueVersion),
|
MarkerEnvVersion(MarkerValueVersion),
|
||||||
/// Those environment markers with an arbitrary string as value such as `sys_platform`
|
/// Those environment markers with an arbitrary string as value such as `sys_platform`
|
||||||
MarkerEnvString(MarkerValueString),
|
MarkerEnvString(MarkerValueString),
|
||||||
|
/// Those markers with exclusively `in` and `not in` operators
|
||||||
|
MarkerEnvList(MarkerValueList),
|
||||||
/// `extra`. This one is special because it's a list, and user-provided
|
/// `extra`. This one is special because it's a list, and user-provided
|
||||||
Extra,
|
Extra,
|
||||||
/// Those markers with exclusively `in` and `not in` operators (PEP 751)
|
|
||||||
MarkerEnvContains(MarkerValueContains),
|
|
||||||
/// Not a constant, but a user given quoted string with a value inside such as '3.8' or "windows"
|
/// Not a constant, but a user given quoted string with a value inside such as '3.8' or "windows"
|
||||||
QuotedString(ArcStr),
|
QuotedString(ArcStr),
|
||||||
}
|
}
|
||||||
|
|
@ -196,9 +198,9 @@ impl FromStr for MarkerValue {
|
||||||
"python_version" => Self::MarkerEnvVersion(MarkerValueVersion::PythonVersion),
|
"python_version" => Self::MarkerEnvVersion(MarkerValueVersion::PythonVersion),
|
||||||
"sys_platform" => Self::MarkerEnvString(MarkerValueString::SysPlatform),
|
"sys_platform" => Self::MarkerEnvString(MarkerValueString::SysPlatform),
|
||||||
"sys.platform" => Self::MarkerEnvString(MarkerValueString::SysPlatformDeprecated),
|
"sys.platform" => Self::MarkerEnvString(MarkerValueString::SysPlatformDeprecated),
|
||||||
|
"extras" => Self::MarkerEnvList(MarkerValueList::Extras),
|
||||||
|
"dependency_groups" => Self::MarkerEnvList(MarkerValueList::DependencyGroups),
|
||||||
"extra" => Self::Extra,
|
"extra" => Self::Extra,
|
||||||
"extras" => Self::MarkerEnvContains(MarkerValueContains::Extras),
|
|
||||||
"dependency_groups" => Self::MarkerEnvContains(MarkerValueContains::DependencyGroups),
|
|
||||||
_ => return Err(format!("Invalid key: {s}")),
|
_ => return Err(format!("Invalid key: {s}")),
|
||||||
};
|
};
|
||||||
Ok(value)
|
Ok(value)
|
||||||
|
|
@ -210,8 +212,8 @@ impl Display for MarkerValue {
|
||||||
match self {
|
match self {
|
||||||
Self::MarkerEnvVersion(marker_value_version) => marker_value_version.fmt(f),
|
Self::MarkerEnvVersion(marker_value_version) => marker_value_version.fmt(f),
|
||||||
Self::MarkerEnvString(marker_value_string) => marker_value_string.fmt(f),
|
Self::MarkerEnvString(marker_value_string) => marker_value_string.fmt(f),
|
||||||
|
Self::MarkerEnvList(marker_value_contains) => marker_value_contains.fmt(f),
|
||||||
Self::Extra => f.write_str("extra"),
|
Self::Extra => f.write_str("extra"),
|
||||||
Self::MarkerEnvContains(marker_value_contains) => marker_value_contains.fmt(f),
|
|
||||||
Self::QuotedString(value) => write!(f, "'{value}'"),
|
Self::QuotedString(value) => write!(f, "'{value}'"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -499,24 +501,6 @@ impl Display for MarkerValueExtra {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The [`GroupName`] value used in `dependency_group` markers.
|
|
||||||
#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
|
||||||
pub enum MarkerValueDependencyGroup {
|
|
||||||
/// A valid [`GroupName`].
|
|
||||||
Group(GroupName),
|
|
||||||
/// An invalid name, preserved as an arbitrary string.
|
|
||||||
Arbitrary(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for MarkerValueDependencyGroup {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::Group(group) => group.fmt(f),
|
|
||||||
Self::Arbitrary(string) => string.fmt(f),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Represents one clause such as `python_version > "3.8"`.
|
/// Represents one clause such as `python_version > "3.8"`.
|
||||||
#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
|
|
@ -540,7 +524,7 @@ pub enum MarkerExpression {
|
||||||
VersionIn {
|
VersionIn {
|
||||||
key: MarkerValueVersion,
|
key: MarkerValueVersion,
|
||||||
versions: Vec<Version>,
|
versions: Vec<Version>,
|
||||||
negated: bool,
|
operator: ContainerOperator,
|
||||||
},
|
},
|
||||||
/// An string marker comparison, e.g. `sys_platform == '...'`.
|
/// An string marker comparison, e.g. `sys_platform == '...'`.
|
||||||
///
|
///
|
||||||
|
|
@ -550,21 +534,16 @@ pub enum MarkerExpression {
|
||||||
operator: MarkerOperator,
|
operator: MarkerOperator,
|
||||||
value: ArcStr,
|
value: ArcStr,
|
||||||
},
|
},
|
||||||
|
/// `'...' in <key>`, a PEP 751 expression.
|
||||||
|
List {
|
||||||
|
pair: CanonicalMarkerListPair,
|
||||||
|
operator: ContainerOperator,
|
||||||
|
},
|
||||||
/// `extra <extra op> '...'` or `'...' <extra op> extra`.
|
/// `extra <extra op> '...'` or `'...' <extra op> extra`.
|
||||||
Extra {
|
Extra {
|
||||||
name: MarkerValueExtra,
|
name: MarkerValueExtra,
|
||||||
operator: ExtraOperator,
|
operator: ExtraOperator,
|
||||||
},
|
},
|
||||||
/// `'...' in extras`
|
|
||||||
Extras {
|
|
||||||
name: MarkerValueExtra,
|
|
||||||
operator: ContainerOperator,
|
|
||||||
},
|
|
||||||
/// `'...' in dependency_groups`
|
|
||||||
DependencyGroups {
|
|
||||||
name: MarkerValueDependencyGroup,
|
|
||||||
operator: ContainerOperator,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The kind of a [`MarkerExpression`].
|
/// The kind of a [`MarkerExpression`].
|
||||||
|
|
@ -572,16 +551,14 @@ pub enum MarkerExpression {
|
||||||
pub(crate) enum MarkerExpressionKind {
|
pub(crate) enum MarkerExpressionKind {
|
||||||
/// A version expression, e.g. `<version key> <version op> <quoted PEP 440 version>`.
|
/// A version expression, e.g. `<version key> <version op> <quoted PEP 440 version>`.
|
||||||
Version(MarkerValueVersion),
|
Version(MarkerValueVersion),
|
||||||
/// A version "in" expression, e.g. `<version key> in <quoted list of PEP 440 versions>`.
|
/// A version `in` expression, e.g. `<version key> in <quoted list of PEP 440 versions>`.
|
||||||
VersionIn(MarkerValueVersion),
|
VersionIn(MarkerValueVersion),
|
||||||
/// A string marker comparison, e.g. `sys_platform == '...'`.
|
/// A string marker comparison, e.g. `sys_platform == '...'`.
|
||||||
String(MarkerValueString),
|
String(MarkerValueString),
|
||||||
|
/// A list `in` or `not in` expression, e.g. `'...' in dependency_groups`.
|
||||||
|
List(MarkerValueList),
|
||||||
/// An extra expression, e.g. `extra == '...'`.
|
/// An extra expression, e.g. `extra == '...'`.
|
||||||
Extra,
|
Extra,
|
||||||
/// An extras expression, e.g. `'...' in extras`.
|
|
||||||
Extras,
|
|
||||||
/// A dependency groups expression, e.g. `'...' in dependency_groups`.
|
|
||||||
DependencyGroups,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The operator for an extra expression, either '==' or '!='.
|
/// The operator for an extra expression, either '==' or '!='.
|
||||||
|
|
@ -624,7 +601,7 @@ impl Display for ExtraOperator {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The operator for a container expression, either 'in' or 'not in'.
|
/// The operator for a container expression, either 'in' or 'not in'.
|
||||||
#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
||||||
pub enum ContainerOperator {
|
pub enum ContainerOperator {
|
||||||
/// `in`
|
/// `in`
|
||||||
In,
|
In,
|
||||||
|
|
@ -643,14 +620,6 @@ impl ContainerOperator {
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Negates this operator.
|
|
||||||
pub(crate) fn negate(&self) -> ContainerOperator {
|
|
||||||
match *self {
|
|
||||||
ContainerOperator::In => ContainerOperator::NotIn,
|
|
||||||
ContainerOperator::NotIn => ContainerOperator::In,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for ContainerOperator {
|
impl Display for ContainerOperator {
|
||||||
|
|
@ -700,9 +669,8 @@ impl MarkerExpression {
|
||||||
MarkerExpression::Version { key, .. } => MarkerExpressionKind::Version(*key),
|
MarkerExpression::Version { key, .. } => MarkerExpressionKind::Version(*key),
|
||||||
MarkerExpression::VersionIn { key, .. } => MarkerExpressionKind::VersionIn(*key),
|
MarkerExpression::VersionIn { key, .. } => MarkerExpressionKind::VersionIn(*key),
|
||||||
MarkerExpression::String { key, .. } => MarkerExpressionKind::String(*key),
|
MarkerExpression::String { key, .. } => MarkerExpressionKind::String(*key),
|
||||||
|
MarkerExpression::List { pair, .. } => MarkerExpressionKind::List(pair.key()),
|
||||||
MarkerExpression::Extra { .. } => MarkerExpressionKind::Extra,
|
MarkerExpression::Extra { .. } => MarkerExpressionKind::Extra,
|
||||||
MarkerExpression::Extras { .. } => MarkerExpressionKind::Extras,
|
|
||||||
MarkerExpression::DependencyGroups { .. } => MarkerExpressionKind::DependencyGroups,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -721,11 +689,10 @@ impl Display for MarkerExpression {
|
||||||
MarkerExpression::VersionIn {
|
MarkerExpression::VersionIn {
|
||||||
key,
|
key,
|
||||||
versions,
|
versions,
|
||||||
negated,
|
operator,
|
||||||
} => {
|
} => {
|
||||||
let op = if *negated { "not in" } else { "in" };
|
|
||||||
let versions = versions.iter().map(ToString::to_string).join(" ");
|
let versions = versions.iter().map(ToString::to_string).join(" ");
|
||||||
write!(f, "{key} {op} '{versions}'")
|
write!(f, "{key} {operator} '{versions}'")
|
||||||
}
|
}
|
||||||
MarkerExpression::String {
|
MarkerExpression::String {
|
||||||
key,
|
key,
|
||||||
|
|
@ -741,15 +708,12 @@ impl Display for MarkerExpression {
|
||||||
|
|
||||||
write!(f, "{key} {operator} '{value}'")
|
write!(f, "{key} {operator} '{value}'")
|
||||||
}
|
}
|
||||||
|
MarkerExpression::List { pair, operator } => {
|
||||||
|
write!(f, "'{}' {} {}", pair.value(), operator, pair.key())
|
||||||
|
}
|
||||||
MarkerExpression::Extra { operator, name } => {
|
MarkerExpression::Extra { operator, name } => {
|
||||||
write!(f, "extra {operator} '{name}'")
|
write!(f, "extra {operator} '{name}'")
|
||||||
}
|
}
|
||||||
MarkerExpression::Extras { operator, name } => {
|
|
||||||
write!(f, "'{name}' {operator} extras")
|
|
||||||
}
|
|
||||||
MarkerExpression::DependencyGroups { operator, name } => {
|
|
||||||
write!(f, "'{name}' {operator} dependency_groups")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -777,24 +741,24 @@ impl<'a> ExtrasEnvironment<'a> {
|
||||||
/// Returns the `extra` names in this environment.
|
/// Returns the `extra` names in this environment.
|
||||||
fn extra(&self) -> &[ExtraName] {
|
fn extra(&self) -> &[ExtraName] {
|
||||||
match self {
|
match self {
|
||||||
ExtrasEnvironment::Extras(extra) => extra,
|
Self::Extras(extra) => extra,
|
||||||
ExtrasEnvironment::Pep751(..) => &[],
|
Self::Pep751(..) => &[],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `extras` names in this environment, as in a PEP 751 lockfile.
|
/// Returns the `extras` names in this environment, as in a PEP 751 lockfile.
|
||||||
fn extras(&self) -> &[ExtraName] {
|
fn extras(&self) -> &[ExtraName] {
|
||||||
match self {
|
match self {
|
||||||
ExtrasEnvironment::Extras(..) => &[],
|
Self::Extras(..) => &[],
|
||||||
ExtrasEnvironment::Pep751(extras, ..) => extras,
|
Self::Pep751(extras, ..) => extras,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `dependency_group` group names in this environment, as in a PEP 751 lockfile.
|
/// Returns the `dependency_group` group names in this environment, as in a PEP 751 lockfile.
|
||||||
fn dependency_groups(&self) -> &[GroupName] {
|
fn dependency_groups(&self) -> &[GroupName] {
|
||||||
match self {
|
match self {
|
||||||
ExtrasEnvironment::Extras(..) => &[],
|
Self::Extras(..) => &[],
|
||||||
ExtrasEnvironment::Pep751(.., groups) => groups,
|
Self::Pep751(.., groups) => groups,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1006,6 +970,16 @@ impl MarkerTree {
|
||||||
low: low.negate(self.0),
|
low: low.negate(self.0),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Variable::List(key) => {
|
||||||
|
let Edges::Boolean { low, high } = node.children else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
MarkerTreeKind::List(ListMarkerTree {
|
||||||
|
pair: key,
|
||||||
|
high: high.negate(self.0),
|
||||||
|
low: low.negate(self.0),
|
||||||
|
})
|
||||||
|
}
|
||||||
Variable::Extra(name) => {
|
Variable::Extra(name) => {
|
||||||
let Edges::Boolean { low, high } = node.children else {
|
let Edges::Boolean { low, high } = node.children else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
|
|
@ -1016,26 +990,6 @@ impl MarkerTree {
|
||||||
low: low.negate(self.0),
|
low: low.negate(self.0),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Variable::Extras(name) => {
|
|
||||||
let Edges::Boolean { low, high } = node.children else {
|
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
MarkerTreeKind::Extras(ExtrasMarkerTree {
|
|
||||||
name,
|
|
||||||
high: high.negate(self.0),
|
|
||||||
low: low.negate(self.0),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
Variable::DependencyGroups(name) => {
|
|
||||||
let Edges::Boolean { low, high } = node.children else {
|
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
MarkerTreeKind::DependencyGroups(DependencyGroupsMarkerTree {
|
|
||||||
name,
|
|
||||||
high: high.negate(self.0),
|
|
||||||
low: low.negate(self.0),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1160,14 +1114,18 @@ impl MarkerTree {
|
||||||
.edge(extras.extra().contains(marker.name().extra()))
|
.edge(extras.extra().contains(marker.name().extra()))
|
||||||
.evaluate_reporter_impl(env, extras, reporter);
|
.evaluate_reporter_impl(env, extras, reporter);
|
||||||
}
|
}
|
||||||
MarkerTreeKind::Extras(marker) => {
|
MarkerTreeKind::List(marker) => {
|
||||||
return marker
|
let edge = match marker.pair() {
|
||||||
.edge(extras.extras().contains(marker.name().extra()))
|
CanonicalMarkerListPair::Extras(extra) => extras.extras().contains(extra),
|
||||||
.evaluate_reporter_impl(env, extras, reporter);
|
CanonicalMarkerListPair::DependencyGroup(dependency_group) => {
|
||||||
|
extras.dependency_groups().contains(dependency_group)
|
||||||
}
|
}
|
||||||
MarkerTreeKind::DependencyGroups(marker) => {
|
// Invalid marker expression
|
||||||
|
CanonicalMarkerListPair::Arbitrary { .. } => return false,
|
||||||
|
};
|
||||||
|
|
||||||
return marker
|
return marker
|
||||||
.edge(extras.dependency_groups().contains(marker.name().group()))
|
.edge(edge)
|
||||||
.evaluate_reporter_impl(env, extras, reporter);
|
.evaluate_reporter_impl(env, extras, reporter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1194,15 +1152,12 @@ impl MarkerTree {
|
||||||
MarkerTreeKind::Contains(marker) => marker
|
MarkerTreeKind::Contains(marker) => marker
|
||||||
.children()
|
.children()
|
||||||
.any(|(_, tree)| tree.evaluate_extras(extras)),
|
.any(|(_, tree)| tree.evaluate_extras(extras)),
|
||||||
|
MarkerTreeKind::List(marker) => marker
|
||||||
|
.children()
|
||||||
|
.any(|(_, tree)| tree.evaluate_extras(extras)),
|
||||||
MarkerTreeKind::Extra(marker) => marker
|
MarkerTreeKind::Extra(marker) => marker
|
||||||
.edge(extras.contains(marker.name().extra()))
|
.edge(extras.contains(marker.name().extra()))
|
||||||
.evaluate_extras(extras),
|
.evaluate_extras(extras),
|
||||||
MarkerTreeKind::Extras(marker) => marker
|
|
||||||
.children()
|
|
||||||
.any(|(_, tree)| tree.evaluate_extras(extras)),
|
|
||||||
MarkerTreeKind::DependencyGroups(marker) => marker
|
|
||||||
.children()
|
|
||||||
.any(|(_, tree)| tree.evaluate_extras(extras)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1430,6 +1385,11 @@ impl MarkerTree {
|
||||||
imp(tree, f);
|
imp(tree, f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
MarkerTreeKind::List(kind) => {
|
||||||
|
for (_, tree) in kind.children() {
|
||||||
|
imp(tree, f);
|
||||||
|
}
|
||||||
|
}
|
||||||
MarkerTreeKind::Extra(kind) => {
|
MarkerTreeKind::Extra(kind) => {
|
||||||
if kind.low.is_false() {
|
if kind.low.is_false() {
|
||||||
f(MarkerOperator::Equal, kind.name().extra());
|
f(MarkerOperator::Equal, kind.name().extra());
|
||||||
|
|
@ -1440,16 +1400,6 @@ impl MarkerTree {
|
||||||
imp(tree, f);
|
imp(tree, f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MarkerTreeKind::Extras(kind) => {
|
|
||||||
for (_, tree) in kind.children() {
|
|
||||||
imp(tree, f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MarkerTreeKind::DependencyGroups(kind) => {
|
|
||||||
for (_, tree) in kind.children() {
|
|
||||||
imp(tree, f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
imp(self, &mut f);
|
imp(self, &mut f);
|
||||||
|
|
@ -1557,6 +1507,21 @@ impl MarkerTree {
|
||||||
write!(f, "{} not in {} -> ", kind.value(), kind.key())?;
|
write!(f, "{} not in {} -> ", kind.value(), kind.key())?;
|
||||||
kind.edge(false).fmt_graph(f, level + 1)?;
|
kind.edge(false).fmt_graph(f, level + 1)?;
|
||||||
}
|
}
|
||||||
|
MarkerTreeKind::List(kind) => {
|
||||||
|
writeln!(f)?;
|
||||||
|
for _ in 0..level {
|
||||||
|
write!(f, " ")?;
|
||||||
|
}
|
||||||
|
write!(f, "{} in {} -> ", kind.value(), kind.key())?;
|
||||||
|
kind.edge(true).fmt_graph(f, level + 1)?;
|
||||||
|
|
||||||
|
writeln!(f)?;
|
||||||
|
for _ in 0..level {
|
||||||
|
write!(f, " ")?;
|
||||||
|
}
|
||||||
|
write!(f, "{} not in {} -> ", kind.value(), kind.key())?;
|
||||||
|
kind.edge(false).fmt_graph(f, level + 1)?;
|
||||||
|
}
|
||||||
MarkerTreeKind::Extra(kind) => {
|
MarkerTreeKind::Extra(kind) => {
|
||||||
writeln!(f)?;
|
writeln!(f)?;
|
||||||
for _ in 0..level {
|
for _ in 0..level {
|
||||||
|
|
@ -1572,36 +1537,6 @@ impl MarkerTree {
|
||||||
write!(f, "extra != {} -> ", kind.name())?;
|
write!(f, "extra != {} -> ", kind.name())?;
|
||||||
kind.edge(false).fmt_graph(f, level + 1)?;
|
kind.edge(false).fmt_graph(f, level + 1)?;
|
||||||
}
|
}
|
||||||
MarkerTreeKind::Extras(kind) => {
|
|
||||||
writeln!(f)?;
|
|
||||||
for _ in 0..level {
|
|
||||||
write!(f, " ")?;
|
|
||||||
}
|
|
||||||
write!(f, "{} in extras -> ", kind.name())?;
|
|
||||||
kind.edge(true).fmt_graph(f, level + 1)?;
|
|
||||||
|
|
||||||
writeln!(f)?;
|
|
||||||
for _ in 0..level {
|
|
||||||
write!(f, " ")?;
|
|
||||||
}
|
|
||||||
write!(f, "{} not in extras -> ", kind.name())?;
|
|
||||||
kind.edge(false).fmt_graph(f, level + 1)?;
|
|
||||||
}
|
|
||||||
MarkerTreeKind::DependencyGroups(kind) => {
|
|
||||||
writeln!(f)?;
|
|
||||||
for _ in 0..level {
|
|
||||||
write!(f, " ")?;
|
|
||||||
}
|
|
||||||
write!(f, "{} in dependency_groups -> ", kind.name())?;
|
|
||||||
kind.edge(true).fmt_graph(f, level + 1)?;
|
|
||||||
|
|
||||||
writeln!(f)?;
|
|
||||||
for _ in 0..level {
|
|
||||||
write!(f, " ")?;
|
|
||||||
}
|
|
||||||
write!(f, "{} not in dependency_groups -> ", kind.name())?;
|
|
||||||
kind.edge(false).fmt_graph(f, level + 1)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -1671,12 +1606,10 @@ pub enum MarkerTreeKind<'a> {
|
||||||
In(InMarkerTree<'a>),
|
In(InMarkerTree<'a>),
|
||||||
/// A string expression with the `contains` operator.
|
/// A string expression with the `contains` operator.
|
||||||
Contains(ContainsMarkerTree<'a>),
|
Contains(ContainsMarkerTree<'a>),
|
||||||
/// A string expression (e.g., `extra == 'dev'`).
|
/// A `in` or `not in` expression.
|
||||||
|
List(ListMarkerTree<'a>),
|
||||||
|
/// An extra expression (e.g., `extra == 'dev'`).
|
||||||
Extra(ExtraMarkerTree<'a>),
|
Extra(ExtraMarkerTree<'a>),
|
||||||
/// A string expression (e.g., `'dev' in extras`).
|
|
||||||
Extras(ExtrasMarkerTree<'a>),
|
|
||||||
/// A string expression (e.g., `'dev' in dependency_groups`).
|
|
||||||
DependencyGroups(DependencyGroupsMarkerTree<'a>),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A version marker node, such as `python_version < '3.7'`.
|
/// A version marker node, such as `python_version < '3.7'`.
|
||||||
|
|
@ -1851,6 +1784,59 @@ impl Ord for ContainsMarkerTree<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||||
|
pub struct ListMarkerTree<'a> {
|
||||||
|
// No separate canonical type, the type is already canonical.
|
||||||
|
pair: &'a CanonicalMarkerListPair,
|
||||||
|
high: NodeId,
|
||||||
|
low: NodeId,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ListMarkerTree<'_> {
|
||||||
|
/// The key-value pair for this expression
|
||||||
|
pub fn pair(&self) -> &CanonicalMarkerListPair {
|
||||||
|
self.pair
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The key (RHS) for this expression.
|
||||||
|
pub fn key(&self) -> MarkerValueList {
|
||||||
|
self.pair.key()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The value (LHS) for this expression.
|
||||||
|
pub fn value(&self) -> String {
|
||||||
|
self.pair.value()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The edges of this node, corresponding to the boolean evaluation of the expression.
|
||||||
|
pub fn children(&self) -> impl Iterator<Item = (bool, MarkerTree)> {
|
||||||
|
[(true, MarkerTree(self.high)), (false, MarkerTree(self.low))].into_iter()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the subtree associated with the given edge value.
|
||||||
|
pub fn edge(&self, value: bool) -> MarkerTree {
|
||||||
|
if value {
|
||||||
|
MarkerTree(self.high)
|
||||||
|
} else {
|
||||||
|
MarkerTree(self.low)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for ListMarkerTree<'_> {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for ListMarkerTree<'_> {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
self.pair()
|
||||||
|
.cmp(other.pair())
|
||||||
|
.then_with(|| self.children().cmp(other.children()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A node representing the existence or absence of a given extra, such as `extra == 'bar'`.
|
/// A node representing the existence or absence of a given extra, such as `extra == 'bar'`.
|
||||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||||
pub struct ExtraMarkerTree<'a> {
|
pub struct ExtraMarkerTree<'a> {
|
||||||
|
|
@ -1894,93 +1880,6 @@ impl Ord for ExtraMarkerTree<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A node representing the existence or absence of a given extra, such as `'bar' in extras`.
|
|
||||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
|
||||||
pub struct ExtrasMarkerTree<'a> {
|
|
||||||
name: &'a CanonicalMarkerValueExtra,
|
|
||||||
high: NodeId,
|
|
||||||
low: NodeId,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ExtrasMarkerTree<'_> {
|
|
||||||
/// Returns the name of the extra in this expression.
|
|
||||||
pub fn name(&self) -> &CanonicalMarkerValueExtra {
|
|
||||||
self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The edges of this node, corresponding to the boolean evaluation of the expression.
|
|
||||||
pub fn children(&self) -> impl Iterator<Item = (bool, MarkerTree)> {
|
|
||||||
[(true, MarkerTree(self.high)), (false, MarkerTree(self.low))].into_iter()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the subtree associated with the given edge value.
|
|
||||||
pub fn edge(&self, value: bool) -> MarkerTree {
|
|
||||||
if value {
|
|
||||||
MarkerTree(self.high)
|
|
||||||
} else {
|
|
||||||
MarkerTree(self.low)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialOrd for ExtrasMarkerTree<'_> {
|
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
||||||
Some(self.cmp(other))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Ord for ExtrasMarkerTree<'_> {
|
|
||||||
fn cmp(&self, other: &Self) -> Ordering {
|
|
||||||
self.name()
|
|
||||||
.cmp(other.name())
|
|
||||||
.then_with(|| self.children().cmp(other.children()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A node representing the existence or absence of a given dependency group, such as
|
|
||||||
/// `'bar' in dependency_groups`.
|
|
||||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
|
||||||
pub struct DependencyGroupsMarkerTree<'a> {
|
|
||||||
name: &'a CanonicalMarkerValueDependencyGroup,
|
|
||||||
high: NodeId,
|
|
||||||
low: NodeId,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DependencyGroupsMarkerTree<'_> {
|
|
||||||
/// Returns the name of the group in this expression.
|
|
||||||
pub fn name(&self) -> &CanonicalMarkerValueDependencyGroup {
|
|
||||||
self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The edges of this node, corresponding to the boolean evaluation of the expression.
|
|
||||||
pub fn children(&self) -> impl Iterator<Item = (bool, MarkerTree)> {
|
|
||||||
[(true, MarkerTree(self.high)), (false, MarkerTree(self.low))].into_iter()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the subtree associated with the given edge value.
|
|
||||||
pub fn edge(&self, value: bool) -> MarkerTree {
|
|
||||||
if value {
|
|
||||||
MarkerTree(self.high)
|
|
||||||
} else {
|
|
||||||
MarkerTree(self.low)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialOrd for DependencyGroupsMarkerTree<'_> {
|
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
||||||
Some(self.cmp(other))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Ord for DependencyGroupsMarkerTree<'_> {
|
|
||||||
fn cmp(&self, other: &Self) -> Ordering {
|
|
||||||
self.name()
|
|
||||||
.cmp(other.name())
|
|
||||||
.then_with(|| self.children().cmp(other.children()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A marker tree that contains at least one expression.
|
/// A marker tree that contains at least one expression.
|
||||||
///
|
///
|
||||||
/// See [`MarkerTree::contents`] for details.
|
/// See [`MarkerTree::contents`] for details.
|
||||||
|
|
@ -2090,7 +1989,7 @@ mod test {
|
||||||
implementation_name: "",
|
implementation_name: "",
|
||||||
implementation_version: "3.7",
|
implementation_version: "3.7",
|
||||||
os_name: "linux",
|
os_name: "linux",
|
||||||
platform_machine: "",
|
platform_machine: "x86_64",
|
||||||
platform_python_implementation: "",
|
platform_python_implementation: "",
|
||||||
platform_release: "",
|
platform_release: "",
|
||||||
platform_system: "",
|
platform_system: "",
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,7 @@ impl VerbatimUrl {
|
||||||
///
|
///
|
||||||
/// If no root directory is provided, relative paths are resolved against the current working
|
/// If no root directory is provided, relative paths are resolved against the current working
|
||||||
/// directory.
|
/// directory.
|
||||||
|
#[cfg(feature = "non-pep508-extensions")] // PEP 508 arguably only allows absolute file URLs.
|
||||||
pub fn from_url_or_path(
|
pub fn from_url_or_path(
|
||||||
input: &str,
|
input: &str,
|
||||||
root_dir: Option<&Path>,
|
root_dir: Option<&Path>,
|
||||||
|
|
|
||||||
|
|
@ -54,12 +54,7 @@ pub(crate) fn requires_python(tree: MarkerTree) -> Option<RequiresPythonRange> {
|
||||||
collect_python_markers(tree, markers, range);
|
collect_python_markers(tree, markers, range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MarkerTreeKind::Extras(marker) => {
|
MarkerTreeKind::List(marker) => {
|
||||||
for (_, tree) in marker.children() {
|
|
||||||
collect_python_markers(tree, markers, range);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MarkerTreeKind::DependencyGroups(marker) => {
|
|
||||||
for (_, tree) in marker.children() {
|
for (_, tree) in marker.children() {
|
||||||
collect_python_markers(tree, markers, range);
|
collect_python_markers(tree, markers, range);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -698,12 +698,7 @@ impl ResolverOutput {
|
||||||
add_marker_params_from_tree(tree, set);
|
add_marker_params_from_tree(tree, set);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MarkerTreeKind::Extras(marker) => {
|
MarkerTreeKind::List(marker) => {
|
||||||
for (_, tree) in marker.children() {
|
|
||||||
add_marker_params_from_tree(tree, set);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MarkerTreeKind::DependencyGroups(marker) => {
|
|
||||||
for (_, tree) in marker.children() {
|
for (_, tree) in marker.children() {
|
||||||
add_marker_params_from_tree(tree, set);
|
add_marker_params_from_tree(tree, set);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue