Encode mutually-incompatible pairs of markers (#9444)
## Summary This is an alternative to #9344. If accepted, I need to audit the codebase and call sites to apply it everywhere, but the basic idea is: rather than encoding mutually-incompatible pairs of markers in the representation itself, we have an additional method on `MarkerTree` that expands the false-y definition to take into account assumptions about which markers can be true alongside others. We then check if the the current marker implies that at least one of them is true. So, for example, we know that `sys_platform == 'win32'` and `platform_system == 'Darwin'` are mutually exclusive. When given a marker expression like `python_version >= '3.7'`, we test if `python_version >= '3.7'` and `sys_platform != 'win32' or platform_system != 'Darwin'` are disjoint, i.e., if the following can't be satisfied: ``` python_version >= '3.7' and (sys_platform != 'win32' or platform_system != 'Darwin') ``` Since, if this can't be satisfied, it implies that the left-hand expression requires `sys_platform == 'win32'` and `platform_system == 'Darwin'` to be true at the same time. I think the main downsides here are: 1. We can't _simplify_ markers based on these implications. So we'd still write markers like `sys_platform == 'win32' and platform_system != 'Darwin'`, even though we know the latter expression is redundant. 2. It might be expensive? I'm not sure. I don't think we test for falseness _that_ often though. Closes #7760. Closes #9275.
This commit is contained in:
@@ -44,6 +44,7 @@
|
||||
//! a [`NodeId`], which represents a potentially complemented reference to a [`Node`] in the interner,
|
||||
//! or a terminal `true`/`false` node. Interning allows the reduction rule that isomorphic nodes are
|
||||
//! merged to be applied globally.
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt;
|
||||
use std::ops::Bound;
|
||||
@@ -60,8 +61,9 @@ use crate::marker::lowering::{
|
||||
CanonicalMarkerValueExtra, CanonicalMarkerValueString, CanonicalMarkerValueVersion,
|
||||
};
|
||||
use crate::marker::MarkerValueExtra;
|
||||
use crate::ExtraOperator;
|
||||
use crate::{MarkerExpression, MarkerOperator, MarkerValueVersion};
|
||||
use crate::{
|
||||
ExtraOperator, MarkerExpression, MarkerOperator, MarkerValueString, MarkerValueVersion,
|
||||
};
|
||||
|
||||
/// The global node interner.
|
||||
pub(crate) static INTERNER: LazyLock<Interner> = LazyLock::new(Interner::default);
|
||||
@@ -93,6 +95,9 @@ struct InternerState {
|
||||
/// A cache for `AND` operations between two nodes.
|
||||
/// Note that `OR` is implemented in terms of `AND`.
|
||||
cache: FxHashMap<(NodeId, NodeId), NodeId>,
|
||||
|
||||
/// The [`NodeId`] for the disjunction of known, mutually incompatible markers.
|
||||
exclusions: Option<NodeId>,
|
||||
}
|
||||
|
||||
impl InternerShared {
|
||||
@@ -295,14 +300,14 @@ impl InternerGuard<'_> {
|
||||
self.create_node(var, children)
|
||||
}
|
||||
|
||||
// Returns a decision node representing the disjunction of two nodes.
|
||||
pub(crate) fn or(&mut self, x: NodeId, y: NodeId) -> NodeId {
|
||||
/// Returns a decision node representing the disjunction of two nodes.
|
||||
pub(crate) fn or(&mut self, xi: NodeId, yi: NodeId) -> NodeId {
|
||||
// We take advantage of cheap negation here and implement OR in terms
|
||||
// of it's De Morgan complement.
|
||||
self.and(x.not(), y.not()).not()
|
||||
self.and(xi.not(), yi.not()).not()
|
||||
}
|
||||
|
||||
// Returns a decision node representing the conjunction of two nodes.
|
||||
/// Returns a decision node representing the conjunction of two nodes.
|
||||
pub(crate) fn and(&mut self, xi: NodeId, yi: NodeId) -> NodeId {
|
||||
if xi.is_true() {
|
||||
return yi;
|
||||
@@ -328,6 +333,14 @@ impl InternerGuard<'_> {
|
||||
|
||||
let (x, y) = (self.shared.node(xi), self.shared.node(yi));
|
||||
|
||||
// Determine whether the conjunction _could_ contain a conflict.
|
||||
//
|
||||
// As an optimization, we only have to perform this check at the top-level, since these
|
||||
// variables are given higher priority in the tree. In other words, if they're present, they
|
||||
// _must_ be at the top; and if they're not at the top, we know they aren't present in any
|
||||
// children.
|
||||
let conflicts = x.var.is_conflicting_variable() && y.var.is_conflicting_variable();
|
||||
|
||||
// Perform Shannon Expansion of the higher order variable.
|
||||
let (func, children) = match x.var.cmp(&y.var) {
|
||||
// X is higher order than Y, apply Y to every child of X.
|
||||
@@ -350,6 +363,18 @@ impl InternerGuard<'_> {
|
||||
// Create the output node.
|
||||
let node = self.create_node(func, children);
|
||||
|
||||
// If the node includes known incompatibilities, map it to `false`.
|
||||
let node = if conflicts {
|
||||
let exclusions = self.exclusions();
|
||||
if self.disjointness(node, exclusions.not()) {
|
||||
NodeId::FALSE
|
||||
} else {
|
||||
node
|
||||
}
|
||||
} else {
|
||||
node
|
||||
};
|
||||
|
||||
// Memoize the result of this operation.
|
||||
//
|
||||
// ADDs often contain duplicated subgraphs in distinct branches due to the restricted
|
||||
@@ -380,17 +405,73 @@ impl InternerGuard<'_> {
|
||||
}
|
||||
|
||||
let (x, y) = (self.shared.node(xi), self.shared.node(yi));
|
||||
|
||||
// Determine whether the conjunction _could_ contain a conflict.
|
||||
//
|
||||
// As an optimization, we only have to perform this check at the top-level, since these
|
||||
// variables are given higher priority in the tree. In other words, if they're present, they
|
||||
// _must_ be at the top; and if they're not at the top, we know they aren't present in any
|
||||
// children.
|
||||
if x.var.is_conflicting_variable() && y.var.is_conflicting_variable() {
|
||||
return self.and(xi, yi).is_false();
|
||||
}
|
||||
|
||||
// Perform Shannon Expansion of the higher order variable.
|
||||
match x.var.cmp(&y.var) {
|
||||
// X is higher order than Y, Y must be disjoint with every child of X.
|
||||
Ordering::Less => x
|
||||
.children
|
||||
.nodes()
|
||||
.all(|x| self.is_disjoint(x.negate(xi), yi)),
|
||||
.all(|x| self.disjointness(x.negate(xi), yi)),
|
||||
// Y is higher order than X, X must be disjoint with every child of Y.
|
||||
Ordering::Greater => y
|
||||
.children
|
||||
.nodes()
|
||||
.all(|y| self.is_disjoint(y.negate(yi), xi)),
|
||||
.all(|y| self.disjointness(y.negate(yi), xi)),
|
||||
// X and Y represent the same variable, their merged edges must be unsatisifiable.
|
||||
Ordering::Equal => x.children.is_disjoint(xi, &y.children, yi, self),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if there is no environment in which both marker trees can apply,
|
||||
/// i.e., their conjunction is always `false`.
|
||||
fn disjointness(&mut self, xi: NodeId, yi: NodeId) -> bool {
|
||||
// NOTE(charlie): This is equivalent to `is_disjoint`, with the exception that it doesn't
|
||||
// perform the mutually-incompatible marker check. If it did, we'd create an infinite loop,
|
||||
// since `is_disjoint` calls `and` (when relevant variables are present) which then calls
|
||||
// `disjointness`.
|
||||
|
||||
// `false` is disjoint with any marker.
|
||||
if xi.is_false() || yi.is_false() {
|
||||
return true;
|
||||
}
|
||||
// `true` is not disjoint with any marker except `false`.
|
||||
if xi.is_true() || yi.is_true() {
|
||||
return false;
|
||||
}
|
||||
// `X` and `X` are not disjoint.
|
||||
if xi == yi {
|
||||
return false;
|
||||
}
|
||||
// `X` and `not X` are disjoint by definition.
|
||||
if xi.not() == yi {
|
||||
return true;
|
||||
}
|
||||
|
||||
let (x, y) = (self.shared.node(xi), self.shared.node(yi));
|
||||
|
||||
// Perform Shannon Expansion of the higher order variable.
|
||||
match x.var.cmp(&y.var) {
|
||||
// X is higher order than Y, Y must be disjoint with every child of X.
|
||||
Ordering::Less => x
|
||||
.children
|
||||
.nodes()
|
||||
.all(|x| self.disjointness(x.negate(xi), yi)),
|
||||
// Y is higher order than X, X must be disjoint with every child of Y.
|
||||
Ordering::Greater => y
|
||||
.children
|
||||
.nodes()
|
||||
.all(|y| self.disjointness(y.negate(yi), xi)),
|
||||
// X and Y represent the same variable, their merged edges must be unsatisifiable.
|
||||
Ordering::Equal => x.children.is_disjoint(xi, &y.children, yi, self),
|
||||
}
|
||||
@@ -667,6 +748,245 @@ impl InternerGuard<'_> {
|
||||
self.create_node(node.var.clone(), Edges::Version { edges: new })
|
||||
.negate(i)
|
||||
}
|
||||
|
||||
/// The disjunction of known incompatible conditions.
|
||||
///
|
||||
/// For example, while the marker specification and grammar do not _forbid_ it, we know that
|
||||
/// both `sys_platform == 'win32'` and `platform_system == 'Darwin'` will never true at the
|
||||
/// same time.
|
||||
///
|
||||
/// This method thus encodes assumptions about the environment that are not guaranteed by the
|
||||
/// PEP 508 specification alone.
|
||||
fn exclusions(&mut self) -> NodeId {
|
||||
/// Perform a disjunction operation between two nodes.
|
||||
///
|
||||
/// This is equivalent to [`InternerGuard::or`], with the exception that it does not
|
||||
/// incorporate knowledge from outside the marker algebra.
|
||||
fn disjunction(guard: &mut InternerGuard<'_>, xi: NodeId, yi: NodeId) -> NodeId {
|
||||
// We take advantage of cheap negation here and implement OR in terms
|
||||
// of it's De Morgan complement.
|
||||
conjunction(guard, xi.not(), yi.not()).not()
|
||||
}
|
||||
|
||||
/// Perform a conjunction operation between two nodes.
|
||||
///
|
||||
/// This is equivalent to [`InternerGuard::and`], with the exception that it does not
|
||||
/// incorporate knowledge from outside the marker algebra.
|
||||
fn conjunction(guard: &mut InternerGuard<'_>, xi: NodeId, yi: NodeId) -> NodeId {
|
||||
if xi.is_true() {
|
||||
return yi;
|
||||
}
|
||||
if yi.is_true() {
|
||||
return xi;
|
||||
}
|
||||
if xi == yi {
|
||||
return xi;
|
||||
}
|
||||
if xi.is_false() || yi.is_false() {
|
||||
return NodeId::FALSE;
|
||||
}
|
||||
// `X and not X` is `false` by definition.
|
||||
if xi.not() == yi {
|
||||
return NodeId::FALSE;
|
||||
}
|
||||
|
||||
let (x, y) = (guard.shared.node(xi), guard.shared.node(yi));
|
||||
|
||||
// Perform Shannon Expansion of the higher order variable.
|
||||
let (func, children) = match x.var.cmp(&y.var) {
|
||||
// X is higher order than Y, apply Y to every child of X.
|
||||
Ordering::Less => {
|
||||
let children = x.children.map(xi, |node| conjunction(guard, node, yi));
|
||||
(x.var.clone(), children)
|
||||
}
|
||||
// Y is higher order than X, apply X to every child of Y.
|
||||
Ordering::Greater => {
|
||||
let children = y.children.map(yi, |node| conjunction(guard, node, xi));
|
||||
(y.var.clone(), children)
|
||||
}
|
||||
// X and Y represent the same variable, merge their children.
|
||||
Ordering::Equal => {
|
||||
let children = x
|
||||
.children
|
||||
.apply(xi, &y.children, yi, |x, y| conjunction(guard, x, y));
|
||||
(x.var.clone(), children)
|
||||
}
|
||||
};
|
||||
|
||||
// Create the output node.
|
||||
guard.create_node(func, children)
|
||||
}
|
||||
|
||||
if let Some(exclusions) = self.state.exclusions {
|
||||
return exclusions;
|
||||
}
|
||||
let mut tree = NodeId::FALSE;
|
||||
for (a, b) in [
|
||||
// sys_platform == 'darwin' and platform_system == 'Windows'
|
||||
(
|
||||
MarkerExpression::String {
|
||||
key: MarkerValueString::SysPlatform,
|
||||
operator: MarkerOperator::Equal,
|
||||
value: "darwin".to_string(),
|
||||
},
|
||||
MarkerExpression::String {
|
||||
key: MarkerValueString::PlatformSystem,
|
||||
operator: MarkerOperator::Equal,
|
||||
value: "Windows".to_string(),
|
||||
},
|
||||
),
|
||||
// sys_platform == 'darwin' and platform_system == 'Linux'
|
||||
(
|
||||
MarkerExpression::String {
|
||||
key: MarkerValueString::SysPlatform,
|
||||
operator: MarkerOperator::Equal,
|
||||
value: "darwin".to_string(),
|
||||
},
|
||||
MarkerExpression::String {
|
||||
key: MarkerValueString::PlatformSystem,
|
||||
operator: MarkerOperator::Equal,
|
||||
value: "Linux".to_string(),
|
||||
},
|
||||
),
|
||||
// sys_platform == 'win32' and platform_system == 'Darwin'
|
||||
(
|
||||
MarkerExpression::String {
|
||||
key: MarkerValueString::SysPlatform,
|
||||
operator: MarkerOperator::Equal,
|
||||
value: "win32".to_string(),
|
||||
},
|
||||
MarkerExpression::String {
|
||||
key: MarkerValueString::PlatformSystem,
|
||||
operator: MarkerOperator::Equal,
|
||||
value: "Darwin".to_string(),
|
||||
},
|
||||
),
|
||||
// sys_platform == 'win32' and platform_system == 'Linux'
|
||||
(
|
||||
MarkerExpression::String {
|
||||
key: MarkerValueString::SysPlatform,
|
||||
operator: MarkerOperator::Equal,
|
||||
value: "win32".to_string(),
|
||||
},
|
||||
MarkerExpression::String {
|
||||
key: MarkerValueString::PlatformSystem,
|
||||
operator: MarkerOperator::Equal,
|
||||
value: "Linux".to_string(),
|
||||
},
|
||||
),
|
||||
// sys_platform == 'linux' and platform_system == 'Darwin'
|
||||
(
|
||||
MarkerExpression::String {
|
||||
key: MarkerValueString::SysPlatform,
|
||||
operator: MarkerOperator::Equal,
|
||||
value: "linux".to_string(),
|
||||
},
|
||||
MarkerExpression::String {
|
||||
key: MarkerValueString::PlatformSystem,
|
||||
operator: MarkerOperator::Equal,
|
||||
value: "Darwin".to_string(),
|
||||
},
|
||||
),
|
||||
// sys_platform == 'linux' and platform_system == 'Windows'
|
||||
(
|
||||
MarkerExpression::String {
|
||||
key: MarkerValueString::SysPlatform,
|
||||
operator: MarkerOperator::Equal,
|
||||
value: "linux".to_string(),
|
||||
},
|
||||
MarkerExpression::String {
|
||||
key: MarkerValueString::PlatformSystem,
|
||||
operator: MarkerOperator::Equal,
|
||||
value: "Windows".to_string(),
|
||||
},
|
||||
),
|
||||
// os_name == 'nt' and sys_platform == 'darwin'
|
||||
(
|
||||
MarkerExpression::String {
|
||||
key: MarkerValueString::OsName,
|
||||
operator: MarkerOperator::Equal,
|
||||
value: "nt".to_string(),
|
||||
},
|
||||
MarkerExpression::String {
|
||||
key: MarkerValueString::SysPlatform,
|
||||
operator: MarkerOperator::Equal,
|
||||
value: "darwin".to_string(),
|
||||
},
|
||||
),
|
||||
// os_name == 'nt' and sys_platform == 'linux'
|
||||
(
|
||||
MarkerExpression::String {
|
||||
key: MarkerValueString::OsName,
|
||||
operator: MarkerOperator::Equal,
|
||||
value: "nt".to_string(),
|
||||
},
|
||||
MarkerExpression::String {
|
||||
key: MarkerValueString::SysPlatform,
|
||||
operator: MarkerOperator::Equal,
|
||||
value: "linux".to_string(),
|
||||
},
|
||||
),
|
||||
// os_name == 'posix' and sys_platform == 'win32'
|
||||
(
|
||||
MarkerExpression::String {
|
||||
key: MarkerValueString::OsName,
|
||||
operator: MarkerOperator::Equal,
|
||||
value: "posix".to_string(),
|
||||
},
|
||||
MarkerExpression::String {
|
||||
key: MarkerValueString::SysPlatform,
|
||||
operator: MarkerOperator::Equal,
|
||||
value: "win32".to_string(),
|
||||
},
|
||||
),
|
||||
// os_name == 'nt' and platform_system == 'Darwin'
|
||||
(
|
||||
MarkerExpression::String {
|
||||
key: MarkerValueString::OsName,
|
||||
operator: MarkerOperator::Equal,
|
||||
value: "nt".to_string(),
|
||||
},
|
||||
MarkerExpression::String {
|
||||
key: MarkerValueString::PlatformSystem,
|
||||
operator: MarkerOperator::Equal,
|
||||
value: "Darwin".to_string(),
|
||||
},
|
||||
),
|
||||
// os_name == 'nt' and platform_system == 'Linux'
|
||||
(
|
||||
MarkerExpression::String {
|
||||
key: MarkerValueString::OsName,
|
||||
operator: MarkerOperator::Equal,
|
||||
value: "nt".to_string(),
|
||||
},
|
||||
MarkerExpression::String {
|
||||
key: MarkerValueString::PlatformSystem,
|
||||
operator: MarkerOperator::Equal,
|
||||
value: "Linux".to_string(),
|
||||
},
|
||||
),
|
||||
// os_name == 'posix' and platform_system == 'Windows'
|
||||
(
|
||||
MarkerExpression::String {
|
||||
key: MarkerValueString::OsName,
|
||||
operator: MarkerOperator::Equal,
|
||||
value: "posix".to_string(),
|
||||
},
|
||||
MarkerExpression::String {
|
||||
key: MarkerValueString::PlatformSystem,
|
||||
operator: MarkerOperator::Equal,
|
||||
value: "Windows".to_string(),
|
||||
},
|
||||
),
|
||||
] {
|
||||
let a = self.expression(a);
|
||||
let b = self.expression(b);
|
||||
let a_and_b = conjunction(self, a, b);
|
||||
tree = disjunction(self, tree, a_and_b);
|
||||
}
|
||||
self.state.exclusions = Some(tree);
|
||||
tree
|
||||
}
|
||||
}
|
||||
|
||||
/// A unique variable for a decision node.
|
||||
@@ -681,13 +1001,13 @@ impl InternerGuard<'_> {
|
||||
/// impact.
|
||||
#[derive(PartialOrd, Ord, PartialEq, Eq, Hash, Clone, Debug)]
|
||||
pub(crate) enum Variable {
|
||||
/// A string marker, such as `os_name`.
|
||||
String(CanonicalMarkerValueString),
|
||||
/// A version marker, such as `python_version`.
|
||||
///
|
||||
/// This is the highest order variable as it typically contains the most complex
|
||||
/// ranges, allowing us to merge ranges at the top-level.
|
||||
Version(CanonicalMarkerValueVersion),
|
||||
/// A string marker, such as `os_name`.
|
||||
String(CanonicalMarkerValueString),
|
||||
/// A variable representing a `<key> in <value>` expression for a particular
|
||||
/// string marker and value.
|
||||
In {
|
||||
@@ -707,6 +1027,20 @@ pub(crate) enum Variable {
|
||||
Extra(CanonicalMarkerValueExtra),
|
||||
}
|
||||
|
||||
impl Variable {
|
||||
/// Returns `true` if the variable is known to be involved in _at least_ one conflicting
|
||||
/// marker pair.
|
||||
///
|
||||
/// For example, `sys_platform == 'win32'` and `platform_system == 'Darwin'` are known to
|
||||
/// never be true at the same time.
|
||||
fn is_conflicting_variable(&self) -> bool {
|
||||
let Variable::String(marker) = self else {
|
||||
return false;
|
||||
};
|
||||
marker.is_conflicting()
|
||||
}
|
||||
}
|
||||
|
||||
/// A decision node in an Algebraic Decision Diagram.
|
||||
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
|
||||
pub(crate) struct Node {
|
||||
@@ -1072,8 +1406,8 @@ impl Edges {
|
||||
low: right_low,
|
||||
},
|
||||
) => {
|
||||
interner.is_disjoint(high.negate(parent), right_high.negate(right_parent))
|
||||
&& interner.is_disjoint(low.negate(parent), right_low.negate(right_parent))
|
||||
interner.disjointness(high.negate(parent), right_high.negate(right_parent))
|
||||
&& interner.disjointness(low.negate(parent), right_low.negate(right_parent))
|
||||
}
|
||||
_ => unreachable!("cannot merge two `Edges` of different types"),
|
||||
}
|
||||
@@ -1100,7 +1434,7 @@ impl Edges {
|
||||
}
|
||||
|
||||
// Ensure the intersection is disjoint.
|
||||
if !interner.is_disjoint(
|
||||
if !interner.disjointness(
|
||||
left_child.negate(left_parent),
|
||||
right_child.negate(right_parent),
|
||||
) {
|
||||
|
||||
@@ -32,13 +32,22 @@ impl From<CanonicalMarkerValueVersion> for 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`.
|
||||
///
|
||||
/// As in [`crate::marker::algebra::Variable`], this `enum` also defines the variable ordering for
|
||||
/// all ADDs, which is in turn used when translating the ADD to DNF. As such, modifying the ordering
|
||||
/// will modify the output of marker expressions.
|
||||
///
|
||||
/// Critically, any variants that could be involved in a known-incompatible marker pair should
|
||||
/// be at the top of the ordering, i.e., given the maximum priority.
|
||||
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
||||
pub enum CanonicalMarkerValueString {
|
||||
/// `implementation_name`
|
||||
ImplementationName,
|
||||
/// `os_name`
|
||||
OsName,
|
||||
/// `sys_platform`
|
||||
SysPlatform,
|
||||
/// `platform_system`
|
||||
PlatformSystem,
|
||||
/// `platform_machine`
|
||||
PlatformMachine,
|
||||
/// Deprecated `platform.machine` from <https://peps.python.org/pep-0345/#environment-markers>
|
||||
@@ -46,12 +55,21 @@ pub enum CanonicalMarkerValueString {
|
||||
PlatformPythonImplementation,
|
||||
/// `platform_release`
|
||||
PlatformRelease,
|
||||
/// `platform_system`
|
||||
PlatformSystem,
|
||||
/// `platform_version`
|
||||
PlatformVersion,
|
||||
/// `sys_platform`
|
||||
SysPlatform,
|
||||
/// `implementation_name`
|
||||
ImplementationName,
|
||||
}
|
||||
|
||||
impl CanonicalMarkerValueString {
|
||||
/// Returns `true` if the marker is known to be involved in _at least_ one conflicting
|
||||
/// marker pair.
|
||||
///
|
||||
/// For example, `sys_platform == 'win32'` and `platform_system == 'Darwin'` are known to
|
||||
/// never be true at the same time.
|
||||
pub(crate) fn is_conflicting(self) -> bool {
|
||||
self <= Self::PlatformSystem
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MarkerValueString> for CanonicalMarkerValueString {
|
||||
|
||||
@@ -21,6 +21,7 @@ pub(crate) fn to_dnf(tree: MarkerTree) -> Vec<Vec<MarkerExpression>> {
|
||||
let mut dnf = Vec::new();
|
||||
collect_dnf(tree, &mut dnf, &mut Vec::new());
|
||||
simplify(&mut dnf);
|
||||
sort(&mut dnf);
|
||||
dnf
|
||||
}
|
||||
|
||||
@@ -278,6 +279,22 @@ fn simplify(dnf: &mut Vec<Vec<MarkerExpression>>) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Sort the clauses in a DNF expression, for backwards compatibility. The goal is to avoid
|
||||
/// unnecessary churn in the display output of the marker expressions, e.g., when modifying the
|
||||
/// internal representations used in the marker algebra.
|
||||
fn sort(dnf: &mut [Vec<MarkerExpression>]) {
|
||||
// Sort each clause.
|
||||
for clause in dnf.iter_mut() {
|
||||
clause.sort_by_key(MarkerExpression::kind);
|
||||
}
|
||||
// Sort the clauses.
|
||||
dnf.sort_by(|a, b| {
|
||||
a.iter()
|
||||
.map(MarkerExpression::kind)
|
||||
.cmp(b.iter().map(MarkerExpression::kind))
|
||||
});
|
||||
}
|
||||
|
||||
/// Merge any edges that lead to identical subtrees into a single range.
|
||||
pub(crate) fn collect_edges<'a, T>(
|
||||
map: impl ExactSizeIterator<Item = (&'a Ranges<T>, MarkerTree)>,
|
||||
|
||||
@@ -5,9 +5,10 @@ use std::str::FromStr;
|
||||
|
||||
use itertools::Itertools;
|
||||
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
||||
use version_ranges::Ranges;
|
||||
|
||||
use uv_normalize::ExtraName;
|
||||
use uv_pep440::{Version, VersionParseError, VersionSpecifier};
|
||||
use version_ranges::Ranges;
|
||||
|
||||
use super::algebra::{Edges, NodeId, Variable, INTERNER};
|
||||
use super::simplify;
|
||||
@@ -493,6 +494,19 @@ pub enum MarkerExpression {
|
||||
},
|
||||
}
|
||||
|
||||
/// The kind of a [`MarkerExpression`].
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
||||
pub(crate) enum MarkerExpressionKind {
|
||||
/// A version expression, e.g. `<version key> <version op> <quoted PEP 440 version>`.
|
||||
Version(MarkerValueVersion),
|
||||
/// A version "in" expression, e.g. `<version key> in <quoted list of PEP 440 versions>`.
|
||||
VersionIn(MarkerValueVersion),
|
||||
/// A string marker comparison, e.g. `sys_platform == '...'`.
|
||||
String(MarkerValueString),
|
||||
/// An extra expression, e.g. `extra == '...'`.
|
||||
Extra,
|
||||
}
|
||||
|
||||
/// The operator for an extra expression, either '==' or '!='.
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
||||
pub enum ExtraOperator {
|
||||
@@ -563,6 +577,16 @@ impl MarkerExpression {
|
||||
pub fn from_str(s: &str) -> Result<Option<Self>, Pep508Error> {
|
||||
MarkerExpression::parse_reporter(s, &mut TracingReporter)
|
||||
}
|
||||
|
||||
/// Return the kind of this marker expression.
|
||||
pub(crate) fn kind(&self) -> MarkerExpressionKind {
|
||||
match self {
|
||||
MarkerExpression::Version { key, .. } => MarkerExpressionKind::Version(*key),
|
||||
MarkerExpression::VersionIn { key, .. } => MarkerExpressionKind::VersionIn(*key),
|
||||
MarkerExpression::String { key, .. } => MarkerExpressionKind::String(*key),
|
||||
MarkerExpression::Extra { .. } => MarkerExpressionKind::Extra,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for MarkerExpression {
|
||||
@@ -691,13 +715,11 @@ impl MarkerTree {
|
||||
}
|
||||
|
||||
/// Combine this marker tree with the one given via a conjunction.
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn and(&mut self, tree: MarkerTree) {
|
||||
self.0 = INTERNER.lock().and(self.0, tree.0);
|
||||
}
|
||||
|
||||
/// Combine this marker tree with the one given via a disjunction.
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn or(&mut self, tree: MarkerTree) {
|
||||
self.0 = INTERNER.lock().or(self.0, tree.0);
|
||||
}
|
||||
@@ -707,7 +729,6 @@ impl MarkerTree {
|
||||
///
|
||||
/// If the marker set is always `true`, then it can be said that `self`
|
||||
/// implies `consequent`.
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn implies(&mut self, consequent: MarkerTree) {
|
||||
// This could probably be optimized, but is clearly
|
||||
// correct, since logical implication is `-P or Q`.
|
||||
@@ -1014,7 +1035,6 @@ impl MarkerTree {
|
||||
/// results of that simplification. (If `requires-python` changes, then one
|
||||
/// should reconstitute all relevant markers from the source data.)
|
||||
#[must_use]
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn simplify_python_versions(
|
||||
self,
|
||||
lower: Bound<&Version>,
|
||||
@@ -1035,7 +1055,6 @@ impl MarkerTree {
|
||||
/// `python_full_version <= '3.10'`, this would result in a marker of
|
||||
/// `python_full_version >= '3.8' and python_full_version <= '3.10'`.
|
||||
#[must_use]
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn complexify_python_versions(
|
||||
self,
|
||||
lower: Bound<&Version>,
|
||||
@@ -2353,7 +2372,7 @@ mod test {
|
||||
|
||||
assert_simplifies(
|
||||
"((extra == 'a' or extra == 'b') and extra == 'c') or extra == 'b'",
|
||||
"(extra == 'a' and extra == 'c') or extra == 'b'",
|
||||
"extra == 'b' or (extra == 'a' and extra == 'c')",
|
||||
);
|
||||
|
||||
// post-normalization filtering
|
||||
@@ -2575,13 +2594,13 @@ mod test {
|
||||
or (implementation_name != 'pypy' and sys_platform == 'win32')
|
||||
or (sys_platform == 'win32' and os_name != 'nt')
|
||||
or (sys_platform != 'win32' and os_name == 'nt')",
|
||||
"(os_name != 'nt' and sys_platform == 'win32') \
|
||||
or (implementation_name != 'pypy' and os_name == 'nt') \
|
||||
or (implementation_name == 'pypy' and os_name != 'nt') \
|
||||
"(implementation_name == 'pypy' and sys_platform != 'win32') \
|
||||
or (implementation_name != 'pypy' and sys_platform == 'win32') \
|
||||
or (os_name != 'nt' and sys_platform == 'win32') \
|
||||
or (os_name == 'nt' and sys_platform != 'win32')",
|
||||
);
|
||||
|
||||
// This is another case we cannot simplify fully, depending on the variable order.
|
||||
// This is a case we can simplify fully, but it's dependent on the variable order.
|
||||
// The expression is equivalent to `sys_platform == 'x' or (os_name == 'Linux' and platform_system == 'win32')`.
|
||||
assert_simplifies(
|
||||
"(os_name == 'Linux' and platform_system == 'win32')
|
||||
@@ -2590,14 +2609,14 @@ mod test {
|
||||
or (os_name != 'Linux' and platform_system == 'win32' and sys_platform == 'x')
|
||||
or (os_name == 'Linux' and platform_system != 'win32' and sys_platform == 'x')
|
||||
or (os_name != 'Linux' and platform_system != 'win32' and sys_platform == 'x')",
|
||||
"(os_name != 'Linux' and sys_platform == 'x') or (platform_system != 'win32' and sys_platform == 'x') or (os_name == 'Linux' and platform_system == 'win32')",
|
||||
"(os_name == 'Linux' and platform_system == 'win32') or sys_platform == 'x'",
|
||||
);
|
||||
|
||||
assert_simplifies("python_version > '3.7'", "python_full_version >= '3.8'");
|
||||
|
||||
assert_simplifies(
|
||||
"(python_version <= '3.7' and os_name == 'Linux') or python_version > '3.7'",
|
||||
"os_name == 'Linux' or python_full_version >= '3.8'",
|
||||
"python_full_version >= '3.8' or os_name == 'Linux'",
|
||||
);
|
||||
|
||||
// Again, the extra `<3.7` and `>=3.9` expressions cannot be seen as redundant due to them being interdependent.
|
||||
@@ -2606,34 +2625,31 @@ mod test {
|
||||
"(os_name == 'Linux' and sys_platform == 'win32') \
|
||||
or (os_name != 'Linux' and sys_platform == 'win32' and python_version == '3.7') \
|
||||
or (os_name != 'Linux' and sys_platform == 'win32' and python_version == '3.8')",
|
||||
"(python_full_version < '3.7' and os_name == 'Linux' and sys_platform == 'win32') \
|
||||
or (python_full_version >= '3.9' and os_name == 'Linux' and sys_platform == 'win32') \
|
||||
or (python_full_version >= '3.7' and python_full_version < '3.9' and sys_platform == 'win32')",
|
||||
"(python_full_version >= '3.7' and python_full_version < '3.9' and sys_platform == 'win32') or (os_name == 'Linux' and sys_platform == 'win32')",
|
||||
);
|
||||
|
||||
assert_simplifies(
|
||||
"(implementation_name != 'pypy' and os_name == 'nt' and sys_platform == 'darwin') or (os_name == 'nt' and sys_platform == 'win32')",
|
||||
"(implementation_name != 'pypy' and os_name == 'nt' and sys_platform == 'darwin') or (os_name == 'nt' and sys_platform == 'win32')",
|
||||
"os_name == 'nt' and sys_platform == 'win32'",
|
||||
);
|
||||
|
||||
assert_simplifies(
|
||||
"(sys_platform == 'darwin' or sys_platform == 'win32')
|
||||
and ((implementation_name != 'pypy' and os_name == 'nt' and sys_platform == 'darwin') or (os_name == 'nt' and sys_platform == 'win32'))",
|
||||
"(implementation_name != 'pypy' and os_name == 'nt' and sys_platform == 'darwin') or (os_name == 'nt' and sys_platform == 'win32')",
|
||||
"(sys_platform == 'darwin' or sys_platform == 'win32') and ((implementation_name != 'pypy' and os_name == 'nt' and sys_platform == 'darwin') or (os_name == 'nt' and sys_platform == 'win32'))",
|
||||
"os_name == 'nt' and sys_platform == 'win32'",
|
||||
);
|
||||
|
||||
assert_simplifies(
|
||||
"(sys_platform == 'darwin' or sys_platform == 'win32')
|
||||
and ((platform_version != '1' and os_name == 'nt' and sys_platform == 'darwin') or (os_name == 'nt' and sys_platform == 'win32'))",
|
||||
"(os_name == 'nt' and platform_version != '1' and sys_platform == 'darwin') or (os_name == 'nt' and sys_platform == 'win32')",
|
||||
"os_name == 'nt' and sys_platform == 'win32'",
|
||||
);
|
||||
|
||||
assert_simplifies(
|
||||
"(os_name == 'nt' and sys_platform == 'win32') \
|
||||
or (os_name != 'nt' and platform_version == '1' and (sys_platform == 'win32' or sys_platform == 'win64'))",
|
||||
"(platform_version == '1' and sys_platform == 'win32') \
|
||||
or (os_name != 'nt' and platform_version == '1' and sys_platform == 'win64') \
|
||||
or (os_name == 'nt' and sys_platform == 'win32')",
|
||||
"(os_name != 'nt' and platform_version == '1' and sys_platform == 'win64') \
|
||||
or (os_name == 'nt' and sys_platform == 'win32') \
|
||||
or (platform_version == '1' and sys_platform == 'win32')",
|
||||
);
|
||||
|
||||
assert_simplifies(
|
||||
|
||||
+173
-11
@@ -439,10 +439,10 @@ fn dependency_multiple_markers() -> Result<()> {
|
||||
# This file was autogenerated by uv via the following command:
|
||||
# uv export --cache-dir [CACHE_DIR]
|
||||
-e .
|
||||
attrs==23.2.0 ; sys_platform == 'win32' or python_full_version >= '3.12' \
|
||||
attrs==23.2.0 ; python_full_version >= '3.12' or sys_platform == 'win32' \
|
||||
--hash=sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30 \
|
||||
--hash=sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1
|
||||
cffi==1.16.0 ; (implementation_name != 'pypy' and os_name == 'nt' and sys_platform == 'win32') or (python_full_version >= '3.12' and implementation_name != 'pypy' and os_name == 'nt') \
|
||||
cffi==1.16.0 ; (python_full_version >= '3.12' and implementation_name != 'pypy' and os_name == 'nt') or (implementation_name != 'pypy' and os_name == 'nt' and sys_platform == 'win32') \
|
||||
--hash=sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab \
|
||||
--hash=sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235 \
|
||||
--hash=sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a \
|
||||
@@ -453,22 +453,22 @@ fn dependency_multiple_markers() -> Result<()> {
|
||||
exceptiongroup==1.2.0 ; python_full_version < '3.11' and sys_platform == 'win32' \
|
||||
--hash=sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14 \
|
||||
--hash=sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68
|
||||
idna==3.6 ; sys_platform == 'win32' or python_full_version >= '3.12' \
|
||||
idna==3.6 ; python_full_version >= '3.12' or sys_platform == 'win32' \
|
||||
--hash=sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca \
|
||||
--hash=sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f
|
||||
outcome==1.3.0.post0 ; sys_platform == 'win32' or python_full_version >= '3.12' \
|
||||
outcome==1.3.0.post0 ; python_full_version >= '3.12' or sys_platform == 'win32' \
|
||||
--hash=sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8 \
|
||||
--hash=sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b
|
||||
pycparser==2.21 ; (implementation_name != 'pypy' and os_name == 'nt' and sys_platform == 'win32') or (python_full_version >= '3.12' and implementation_name != 'pypy' and os_name == 'nt') \
|
||||
pycparser==2.21 ; (python_full_version >= '3.12' and implementation_name != 'pypy' and os_name == 'nt') or (implementation_name != 'pypy' and os_name == 'nt' and sys_platform == 'win32') \
|
||||
--hash=sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9 \
|
||||
--hash=sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206
|
||||
sniffio==1.3.1 ; sys_platform == 'win32' or python_full_version >= '3.12' \
|
||||
sniffio==1.3.1 ; python_full_version >= '3.12' or sys_platform == 'win32' \
|
||||
--hash=sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2 \
|
||||
--hash=sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc
|
||||
sortedcontainers==2.4.0 ; sys_platform == 'win32' or python_full_version >= '3.12' \
|
||||
sortedcontainers==2.4.0 ; python_full_version >= '3.12' or sys_platform == 'win32' \
|
||||
--hash=sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88 \
|
||||
--hash=sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0
|
||||
trio==0.25.0 ; sys_platform == 'win32' or python_full_version >= '3.12' \
|
||||
trio==0.25.0 ; python_full_version >= '3.12' or sys_platform == 'win32' \
|
||||
--hash=sha256:9b41f5993ad2c0e5f62d0acca320ec657fdb6b2a2c22b8c7aed6caf154475c4e \
|
||||
--hash=sha256:e6458efe29cc543e557a91e614e2b51710eba2961669329ce9c862d50c6e8e81
|
||||
|
||||
@@ -501,7 +501,169 @@ fn dependency_conflicting_markers() -> Result<()> {
|
||||
"#,
|
||||
)?;
|
||||
|
||||
context.lock().assert().success();
|
||||
uv_snapshot!(context.filters(), context.lock(), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Resolved 11 packages in [TIME]
|
||||
"###);
|
||||
|
||||
let lock = context.read("uv.lock");
|
||||
|
||||
insta::with_settings!(
|
||||
{
|
||||
filters => context.filters(),
|
||||
},
|
||||
{
|
||||
insta::assert_snapshot!(
|
||||
lock, @r###"
|
||||
version = 1
|
||||
requires-python = ">=3.12"
|
||||
resolution-markers = [
|
||||
"sys_platform == 'darwin'",
|
||||
"sys_platform == 'win32'",
|
||||
"sys_platform != 'darwin' and sys_platform != 'win32'",
|
||||
]
|
||||
|
||||
[options]
|
||||
exclude-newer = "2024-03-25T00:00:00Z"
|
||||
|
||||
[[package]]
|
||||
name = "async-generator"
|
||||
version = "1.10"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ce/b6/6fa6b3b598a03cba5e80f829e0dadbb49d7645f523d209b2fb7ea0bbb02a/async_generator-1.10.tar.gz", hash = "sha256:6ebb3d106c12920aaae42ccb6f787ef5eefdcdd166ea3d628fa8476abe712144", size = 29870 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/71/52/39d20e03abd0ac9159c162ec24b93fbcaa111e8400308f2465432495ca2b/async_generator-1.10-py3-none-any.whl", hash = "sha256:01c7bf666359b4967d2cda0000cc2e4af16a0ae098cbffcb8472fb9e8ad6585b", size = 18857 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "attrs"
|
||||
version = "23.2.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e3/fc/f800d51204003fa8ae392c4e8278f256206e7a919b708eef054f5f4b650d/attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30", size = 780820 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e0/44/827b2a91a5816512fcaf3cc4ebc465ccd5d598c45cefa6703fcf4a79018f/attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1", size = 60752 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cffi"
|
||||
version = "1.16.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pycparser", marker = "sys_platform == 'win32'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/68/ce/95b0bae7968c65473e1298efb042e10cafc7bafc14d9e4f154008241c91d/cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0", size = 512873 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/6e/751437067affe7ac0944b1ad4856ec11650da77f0dd8f305fae1117ef7bb/cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b", size = 173564 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/63/e285470a4880a4f36edabe4810057bd4b562c6ddcc165eacf9c3c7210b40/cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235", size = 181956 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "3.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/bf/3f/ea4b9117521a1e9c50344b909be7886dd00a519552724809bb1f486986c2/idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca", size = 175426 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f", size = 61567 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "outcome"
|
||||
version = "1.3.0.post0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "attrs", marker = "sys_platform == 'darwin' or sys_platform == 'win32'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/98/df/77698abfac98571e65ffeb0c1fba8ffd692ab8458d617a0eed7d9a8d38f2/outcome-1.3.0.post0.tar.gz", hash = "sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8", size = 21060 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/55/8b/5ab7257531a5d830fc8000c476e63c935488d74609b50f9384a643ec0a62/outcome-1.3.0.post0-py2.py3-none-any.whl", hash = "sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b", size = 10692 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "project"
|
||||
version = "0.1.0"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "trio", version = "0.10.0", source = { registry = "https://pypi.org/simple" }, marker = "sys_platform == 'win32'" },
|
||||
{ name = "trio", version = "0.25.0", source = { registry = "https://pypi.org/simple" }, marker = "sys_platform == 'darwin'" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "trio", marker = "sys_platform == 'darwin'", specifier = "==0.25.0" },
|
||||
{ name = "trio", marker = "sys_platform == 'win32'", specifier = "==0.10.0" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pycparser"
|
||||
version = "2.21"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/5e/0b/95d387f5f4433cb0f53ff7ad859bd2c6051051cebbb564f139a999ab46de/pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206", size = 170877 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/62/d5/5f610ebe421e85889f2e55e33b7f9a6795bd982198517d912eb1c76e1a53/pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9", size = 118697 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sniffio"
|
||||
version = "1.3.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sortedcontainers"
|
||||
version = "2.4.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e8/c4/ba2f8066cceb6f23394729afe52f3bf7adec04bf9ed2c820b39e19299111/sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", size = 30594 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "trio"
|
||||
version = "0.10.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"sys_platform == 'win32'",
|
||||
]
|
||||
dependencies = [
|
||||
{ name = "async-generator", marker = "sys_platform == 'win32'" },
|
||||
{ name = "attrs", marker = "sys_platform == 'win32'" },
|
||||
{ name = "cffi", marker = "os_name == 'nt' and sys_platform == 'win32'" },
|
||||
{ name = "idna", marker = "sys_platform == 'win32'" },
|
||||
{ name = "outcome", marker = "sys_platform == 'win32'" },
|
||||
{ name = "sniffio", marker = "sys_platform == 'win32'" },
|
||||
{ name = "sortedcontainers", marker = "sys_platform == 'win32'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e6/20/37be7b5f47db6a9fbf905b5de5386e5b7193c45d07becb750db6f03cd117/trio-0.10.0.tar.gz", hash = "sha256:d323cc15f6406d15954af91e5e34af2001cc24163fdde29e3f88a227a1b53ab0", size = 402511 }
|
||||
|
||||
[[package]]
|
||||
name = "trio"
|
||||
version = "0.25.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"sys_platform == 'darwin'",
|
||||
]
|
||||
dependencies = [
|
||||
{ name = "attrs", marker = "sys_platform == 'darwin'" },
|
||||
{ name = "idna", marker = "sys_platform == 'darwin'" },
|
||||
{ name = "outcome", marker = "sys_platform == 'darwin'" },
|
||||
{ name = "sniffio", marker = "sys_platform == 'darwin'" },
|
||||
{ name = "sortedcontainers", marker = "sys_platform == 'darwin'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b4/51/4f5ae37ec58768b9c30e5bc5b89431a7baf3fa9d0dda98983af6ef55eb47/trio-0.25.0.tar.gz", hash = "sha256:9b41f5993ad2c0e5f62d0acca320ec657fdb6b2a2c22b8c7aed6caf154475c4e", size = 551863 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/17/c9/f86f89f14d52f9f2f652ce24cb2f60141a51d087db1563f3fba94ba07346/trio-0.25.0-py3-none-any.whl", hash = "sha256:e6458efe29cc543e557a91e614e2b51710eba2961669329ce9c862d50c6e8e81", size = 467161 },
|
||||
]
|
||||
"###
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
uv_snapshot!(context.filters(), context.export(), @r###"
|
||||
success: true
|
||||
@@ -516,7 +678,7 @@ fn dependency_conflicting_markers() -> Result<()> {
|
||||
attrs==23.2.0 ; sys_platform == 'darwin' or sys_platform == 'win32' \
|
||||
--hash=sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30 \
|
||||
--hash=sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1
|
||||
cffi==1.16.0 ; (implementation_name != 'pypy' and os_name == 'nt' and sys_platform == 'darwin') or (os_name == 'nt' and sys_platform == 'win32') \
|
||||
cffi==1.16.0 ; os_name == 'nt' and sys_platform == 'win32' \
|
||||
--hash=sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235 \
|
||||
--hash=sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b \
|
||||
--hash=sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0
|
||||
@@ -526,7 +688,7 @@ fn dependency_conflicting_markers() -> Result<()> {
|
||||
outcome==1.3.0.post0 ; sys_platform == 'darwin' or sys_platform == 'win32' \
|
||||
--hash=sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8 \
|
||||
--hash=sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b
|
||||
pycparser==2.21 ; (implementation_name != 'pypy' and os_name == 'nt' and sys_platform == 'darwin') or (os_name == 'nt' and sys_platform == 'win32') \
|
||||
pycparser==2.21 ; os_name == 'nt' and sys_platform == 'win32' \
|
||||
--hash=sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9 \
|
||||
--hash=sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206
|
||||
sniffio==1.3.1 ; sys_platform == 'darwin' or sys_platform == 'win32' \
|
||||
|
||||
@@ -16539,7 +16539,6 @@ fn lock_multiple_sources_conflict() -> Result<()> {
|
||||
Source markers must be disjoint, but the following markers overlap: `python_full_version == '3.12.*' and sys_platform == 'win32'` and `sys_platform == 'win32'`.
|
||||
|
||||
hint: replace `sys_platform == 'win32'` with `python_full_version != '3.12.*' and sys_platform == 'win32'`.
|
||||
|
||||
"###);
|
||||
|
||||
Ok(())
|
||||
@@ -17138,7 +17137,7 @@ fn lock_multiple_sources_respect_marker() -> Result<()> {
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Resolved 3 packages in [TIME]
|
||||
Resolved 2 packages in [TIME]
|
||||
"###);
|
||||
|
||||
let lock = context.read("uv.lock");
|
||||
@@ -17150,11 +17149,6 @@ fn lock_multiple_sources_respect_marker() -> Result<()> {
|
||||
lock, @r###"
|
||||
version = 1
|
||||
requires-python = ">=3.12"
|
||||
resolution-markers = [
|
||||
"platform_system == 'Windows' and sys_platform == 'darwin'",
|
||||
"platform_system == 'Windows' and sys_platform != 'darwin'",
|
||||
"platform_system != 'Windows'",
|
||||
]
|
||||
|
||||
[options]
|
||||
exclude-newer = "2024-03-25T00:00:00Z"
|
||||
@@ -17163,39 +17157,21 @@ fn lock_multiple_sources_respect_marker() -> Result<()> {
|
||||
name = "iniconfig"
|
||||
version = "2.0.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"platform_system == 'Windows' and sys_platform != 'darwin'",
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iniconfig"
|
||||
version = "2.0.0"
|
||||
source = { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl" }
|
||||
resolution-markers = [
|
||||
"platform_system == 'Windows' and sys_platform == 'darwin'",
|
||||
]
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "project"
|
||||
version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "iniconfig", version = "2.0.0", source = { registry = "https://pypi.org/simple" }, marker = "platform_system == 'Windows' and sys_platform != 'darwin'" },
|
||||
{ name = "iniconfig", version = "2.0.0", source = { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl" }, marker = "platform_system == 'Windows' and sys_platform == 'darwin'" },
|
||||
{ name = "iniconfig", marker = "platform_system == 'Windows' and sys_platform != 'darwin'" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "iniconfig", marker = "platform_system == 'Windows' and sys_platform != 'darwin'" },
|
||||
{ name = "iniconfig", marker = "platform_system == 'Windows' and sys_platform == 'darwin'", url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl" },
|
||||
]
|
||||
requires-dist = [{ name = "iniconfig", marker = "platform_system == 'Windows' and sys_platform != 'darwin'" }]
|
||||
"###
|
||||
);
|
||||
});
|
||||
@@ -17207,7 +17183,7 @@ fn lock_multiple_sources_respect_marker() -> Result<()> {
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Resolved 3 packages in [TIME]
|
||||
Resolved 2 packages in [TIME]
|
||||
"###);
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -7221,13 +7221,13 @@ fn universal_conflicting() -> Result<()> {
|
||||
# via
|
||||
# outcome
|
||||
# trio
|
||||
cffi==1.16.0 ; (implementation_name != 'pypy' and os_name == 'nt' and sys_platform == 'darwin') or (os_name == 'nt' and sys_platform == 'win32')
|
||||
cffi==1.16.0 ; os_name == 'nt' and sys_platform == 'win32'
|
||||
# via trio
|
||||
idna==3.6 ; sys_platform == 'darwin' or sys_platform == 'win32'
|
||||
# via trio
|
||||
outcome==1.3.0.post0 ; sys_platform == 'darwin' or sys_platform == 'win32'
|
||||
# via trio
|
||||
pycparser==2.21 ; (implementation_name != 'pypy' and os_name == 'nt' and sys_platform == 'darwin') or (os_name == 'nt' and sys_platform == 'win32')
|
||||
pycparser==2.21 ; os_name == 'nt' and sys_platform == 'win32'
|
||||
# via cffi
|
||||
sniffio==1.3.1 ; sys_platform == 'darwin' or sys_platform == 'win32'
|
||||
# via trio
|
||||
@@ -7823,7 +7823,7 @@ fn universal_disjoint_base_or_local_requirement() -> Result<()> {
|
||||
----- stdout -----
|
||||
# This file was autogenerated by uv via the following command:
|
||||
# uv pip compile --cache-dir [CACHE_DIR] requirements.in --universal
|
||||
cmake==3.28.4 ; python_full_version < '3.11' or (python_full_version < '3.13' and platform_machine == 'x86_64' and platform_system == 'Linux')
|
||||
cmake==3.28.4 ; (python_full_version < '3.11' and platform_machine != 'x86_64') or (python_full_version < '3.13' and platform_machine == 'x86_64' and platform_system == 'Linux') or (python_full_version < '3.11' and platform_system != 'Linux')
|
||||
# via
|
||||
# pytorch-triton-rocm
|
||||
# triton
|
||||
@@ -7836,7 +7836,7 @@ fn universal_disjoint_base_or_local_requirement() -> Result<()> {
|
||||
# triton
|
||||
jinja2==3.1.3
|
||||
# via torch
|
||||
lit==18.1.2 ; python_full_version < '3.11' or (python_full_version < '3.13' and platform_machine == 'x86_64' and platform_system == 'Linux')
|
||||
lit==18.1.2 ; (python_full_version < '3.11' and platform_machine != 'x86_64') or (python_full_version < '3.13' and platform_machine == 'x86_64' and platform_system == 'Linux') or (python_full_version < '3.11' and platform_system != 'Linux')
|
||||
# via
|
||||
# pytorch-triton-rocm
|
||||
# triton
|
||||
@@ -8954,8 +8954,6 @@ fn universal_disjoint_extra() -> Result<()> {
|
||||
# via flask
|
||||
click==8.1.7 ; sys_platform == 'darwin' or sys_platform == 'linux'
|
||||
# via flask
|
||||
colorama==0.4.6 ; (platform_system == 'Windows' and sys_platform == 'darwin') or (platform_system == 'Windows' and sys_platform == 'linux')
|
||||
# via click
|
||||
flask==3.0.2 ; sys_platform == 'linux'
|
||||
# via -r requirements.in
|
||||
itsdangerous==2.1.2 ; sys_platform == 'darwin' or sys_platform == 'linux'
|
||||
@@ -8972,7 +8970,7 @@ fn universal_disjoint_extra() -> Result<()> {
|
||||
# via flask
|
||||
|
||||
----- stderr -----
|
||||
Resolved 10 packages in [TIME]
|
||||
Resolved 9 packages in [TIME]
|
||||
"###
|
||||
);
|
||||
|
||||
@@ -9003,8 +9001,6 @@ fn universal_disjoint_extra_no_strip() -> Result<()> {
|
||||
# via flask
|
||||
click==8.1.7 ; sys_platform == 'darwin' or sys_platform == 'linux'
|
||||
# via flask
|
||||
colorama==0.4.6 ; (platform_system == 'Windows' and sys_platform == 'darwin') or (platform_system == 'Windows' and sys_platform == 'linux')
|
||||
# via click
|
||||
flask==3.0.2 ; sys_platform == 'darwin' or sys_platform == 'linux'
|
||||
# via -r requirements.in
|
||||
flask[async]==3.0.2 ; sys_platform == 'linux'
|
||||
@@ -9025,7 +9021,7 @@ fn universal_disjoint_extra_no_strip() -> Result<()> {
|
||||
# via flask
|
||||
|
||||
----- stderr -----
|
||||
Resolved 10 packages in [TIME]
|
||||
Resolved 9 packages in [TIME]
|
||||
"###
|
||||
);
|
||||
|
||||
@@ -9053,7 +9049,7 @@ fn universal_overlap_extra_base() -> Result<()> {
|
||||
# via flask
|
||||
click==8.1.7
|
||||
# via flask
|
||||
colorama==0.4.6 ; platform_system == 'Windows'
|
||||
colorama==0.4.6 ; platform_system == 'Windows' and sys_platform != 'darwin'
|
||||
# via click
|
||||
flask==3.0.2
|
||||
# via -r requirements.in
|
||||
@@ -9100,7 +9096,7 @@ fn universal_overlap_extra_base_no_strip() -> Result<()> {
|
||||
# via flask
|
||||
click==8.1.7
|
||||
# via flask
|
||||
colorama==0.4.6 ; platform_system == 'Windows'
|
||||
colorama==0.4.6 ; platform_system == 'Windows' and sys_platform != 'darwin'
|
||||
# via click
|
||||
flask==3.0.2
|
||||
# via -r requirements.in
|
||||
@@ -9150,8 +9146,6 @@ fn universal_overlap_extras() -> Result<()> {
|
||||
# via flask
|
||||
click==8.1.7 ; sys_platform == 'darwin' or sys_platform == 'linux'
|
||||
# via flask
|
||||
colorama==0.4.6 ; (platform_system == 'Windows' and sys_platform == 'darwin') or (platform_system == 'Windows' and sys_platform == 'linux')
|
||||
# via click
|
||||
flask==3.0.2 ; sys_platform == 'darwin' or sys_platform == 'linux'
|
||||
# via -r requirements.in
|
||||
itsdangerous==2.1.2 ; sys_platform == 'darwin' or sys_platform == 'linux'
|
||||
@@ -9168,7 +9162,7 @@ fn universal_overlap_extras() -> Result<()> {
|
||||
# via flask
|
||||
|
||||
----- stderr -----
|
||||
Resolved 10 packages in [TIME]
|
||||
Resolved 9 packages in [TIME]
|
||||
"###
|
||||
);
|
||||
|
||||
@@ -9199,8 +9193,6 @@ fn universal_overlap_extras_no_strip() -> Result<()> {
|
||||
# via flask
|
||||
click==8.1.7 ; sys_platform == 'darwin' or sys_platform == 'linux'
|
||||
# via flask
|
||||
colorama==0.4.6 ; (platform_system == 'Windows' and sys_platform == 'darwin') or (platform_system == 'Windows' and sys_platform == 'linux')
|
||||
# via click
|
||||
flask[async]==3.0.2 ; sys_platform == 'darwin' or sys_platform == 'linux'
|
||||
# via -r requirements.in
|
||||
flask[dotenv]==3.0.2 ; sys_platform == 'darwin'
|
||||
@@ -9219,7 +9211,7 @@ fn universal_overlap_extras_no_strip() -> Result<()> {
|
||||
# via flask
|
||||
|
||||
----- stderr -----
|
||||
Resolved 10 packages in [TIME]
|
||||
Resolved 9 packages in [TIME]
|
||||
"###
|
||||
);
|
||||
|
||||
@@ -9249,8 +9241,6 @@ fn universal_identical_extras() -> Result<()> {
|
||||
# via flask
|
||||
click==8.1.7 ; sys_platform == 'darwin'
|
||||
# via flask
|
||||
colorama==0.4.6 ; platform_system == 'Windows' and sys_platform == 'darwin'
|
||||
# via click
|
||||
flask==3.0.2 ; sys_platform == 'darwin'
|
||||
# via -r requirements.in
|
||||
itsdangerous==2.1.2 ; sys_platform == 'darwin'
|
||||
@@ -9267,7 +9257,7 @@ fn universal_identical_extras() -> Result<()> {
|
||||
# via flask
|
||||
|
||||
----- stderr -----
|
||||
Resolved 10 packages in [TIME]
|
||||
Resolved 9 packages in [TIME]
|
||||
"###
|
||||
);
|
||||
|
||||
@@ -9298,8 +9288,6 @@ fn universal_identical_extras_no_strip() -> Result<()> {
|
||||
# via flask
|
||||
click==8.1.7 ; sys_platform == 'darwin'
|
||||
# via flask
|
||||
colorama==0.4.6 ; platform_system == 'Windows' and sys_platform == 'darwin'
|
||||
# via click
|
||||
flask[async, dotenv]==3.0.2 ; sys_platform == 'darwin'
|
||||
# via -r requirements.in
|
||||
itsdangerous==2.1.2 ; sys_platform == 'darwin'
|
||||
@@ -9316,7 +9304,7 @@ fn universal_identical_extras_no_strip() -> Result<()> {
|
||||
# via flask
|
||||
|
||||
----- stderr -----
|
||||
Resolved 10 packages in [TIME]
|
||||
Resolved 9 packages in [TIME]
|
||||
"###
|
||||
);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
source: crates/uv/tests/ecosystem.rs
|
||||
source: crates/uv/tests/it/ecosystem.rs
|
||||
expression: lock
|
||||
---
|
||||
version = 1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
source: crates/uv/tests/ecosystem.rs
|
||||
source: crates/uv/tests/it/ecosystem.rs
|
||||
expression: lock
|
||||
---
|
||||
version = 1
|
||||
|
||||
@@ -7,19 +7,19 @@ requires-python = ">=3.9.0"
|
||||
resolution-markers = [
|
||||
"python_full_version < '3.10' and platform_machine == 'arm64' and platform_system == 'Darwin'",
|
||||
"python_full_version < '3.10' and platform_machine == 'aarch64' and platform_system == 'Linux'",
|
||||
"(python_full_version < '3.10' and platform_machine != 'aarch64' and platform_machine != 'arm64') or (python_full_version < '3.10' and platform_machine == 'aarch64' and platform_system != 'Linux') or (python_full_version < '3.10' and platform_machine == 'arm64' and platform_system != 'Darwin')",
|
||||
"(python_full_version < '3.10' and platform_machine != 'arm64' and platform_system == 'Darwin') or (python_full_version < '3.10' and platform_machine != 'aarch64' and platform_system == 'Linux') or (python_full_version < '3.10' and platform_system != 'Darwin' and platform_system != 'Linux')",
|
||||
"python_full_version == '3.10.*' and platform_system == 'Darwin'",
|
||||
"python_full_version == '3.10.*' and platform_machine == 'aarch64' and platform_system == 'Linux'",
|
||||
"(python_full_version == '3.10.*' and platform_machine != 'aarch64' and platform_system != 'Darwin') or (python_full_version == '3.10.*' and platform_system != 'Darwin' and platform_system != 'Linux')",
|
||||
"(python_full_version == '3.10.*' and platform_machine != 'aarch64' and platform_system == 'Linux') or (python_full_version == '3.10.*' and platform_system != 'Darwin' and platform_system != 'Linux')",
|
||||
"python_full_version == '3.11.*' and platform_system == 'Darwin'",
|
||||
"python_full_version == '3.11.*' and platform_machine == 'aarch64' and platform_system == 'Linux'",
|
||||
"(python_full_version == '3.11.*' and platform_machine != 'aarch64' and platform_system != 'Darwin') or (python_full_version == '3.11.*' and platform_system != 'Darwin' and platform_system != 'Linux')",
|
||||
"(python_full_version == '3.11.*' and platform_machine != 'aarch64' and platform_system == 'Linux') or (python_full_version == '3.11.*' and platform_system != 'Darwin' and platform_system != 'Linux')",
|
||||
"python_full_version == '3.12.*' and platform_system == 'Darwin'",
|
||||
"python_full_version == '3.12.*' and platform_machine == 'aarch64' and platform_system == 'Linux'",
|
||||
"(python_full_version == '3.12.*' and platform_machine != 'aarch64' and platform_system != 'Darwin') or (python_full_version == '3.12.*' and platform_system != 'Darwin' and platform_system != 'Linux')",
|
||||
"(python_full_version == '3.12.*' and platform_machine != 'aarch64' and platform_system == 'Linux') or (python_full_version == '3.12.*' and platform_system != 'Darwin' and platform_system != 'Linux')",
|
||||
"python_full_version >= '3.13' and platform_system == 'Darwin'",
|
||||
"python_full_version >= '3.13' and platform_machine == 'aarch64' and platform_system == 'Linux'",
|
||||
"(python_full_version >= '3.13' and platform_machine != 'aarch64' and platform_system != 'Darwin') or (python_full_version >= '3.13' and platform_system != 'Darwin' and platform_system != 'Linux')",
|
||||
"(python_full_version >= '3.13' and platform_machine != 'aarch64' and platform_system == 'Linux') or (python_full_version >= '3.13' and platform_system != 'Darwin' and platform_system != 'Linux')",
|
||||
]
|
||||
|
||||
[options]
|
||||
@@ -660,7 +660,7 @@ name = "colorlog"
|
||||
version = "6.8.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
{ name = "colorama", marker = "(python_full_version < '3.10' and platform_machine != 'arm64' and platform_system == 'Darwin' and sys_platform == 'win32') or (platform_machine != 'aarch64' and platform_system == 'Linux' and sys_platform == 'win32') or (platform_system != 'Darwin' and platform_system != 'Linux' and sys_platform == 'win32')" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/db/38/2992ff192eaa7dd5a793f8b6570d6bbe887c4fbbf7e72702eb0a693a01c8/colorlog-6.8.2.tar.gz", hash = "sha256:3e3e079a41feb5a1b64f978b5ea4f46040a94f11f0e8bbb8261e3dbbeca64d44", size = 16529 }
|
||||
wheels = [
|
||||
@@ -875,7 +875,7 @@ name = "docker"
|
||||
version = "7.1.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pywin32", marker = "sys_platform == 'win32'" },
|
||||
{ name = "pywin32", marker = "(python_full_version < '3.10' and platform_machine != 'arm64' and platform_system == 'Darwin' and sys_platform == 'win32') or (platform_machine != 'aarch64' and platform_system == 'Linux' and sys_platform == 'win32') or (platform_system != 'Darwin' and platform_system != 'Linux' and sys_platform == 'win32')" },
|
||||
{ name = "requests" },
|
||||
{ name = "urllib3" },
|
||||
]
|
||||
@@ -1440,7 +1440,7 @@ name = "humanfriendly"
|
||||
version = "10.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pyreadline3", marker = "sys_platform == 'win32'" },
|
||||
{ name = "pyreadline3", marker = "(python_full_version < '3.10' and platform_machine != 'arm64' and platform_system == 'Darwin' and sys_platform == 'win32') or (platform_machine != 'aarch64' and platform_system == 'Linux' and sys_platform == 'win32') or (platform_system != 'Darwin' and platform_system != 'Linux' and sys_platform == 'win32')" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/cc/3f/2c29224acb2e2df4d2046e4c73ee2662023c58ff5b113c4c1adac0886c43/humanfriendly-10.0.tar.gz", hash = "sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc", size = 360702 }
|
||||
wheels = [
|
||||
@@ -1652,7 +1652,7 @@ version = "5.7.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "platformdirs" },
|
||||
{ name = "pywin32", marker = "platform_python_implementation != 'PyPy' and sys_platform == 'win32'" },
|
||||
{ name = "pywin32", marker = "(python_full_version < '3.10' and platform_machine != 'arm64' and platform_python_implementation != 'PyPy' and platform_system == 'Darwin' and sys_platform == 'win32') or (platform_machine != 'aarch64' and platform_python_implementation != 'PyPy' and platform_system == 'Linux' and sys_platform == 'win32') or (platform_python_implementation != 'PyPy' and platform_system != 'Darwin' and platform_system != 'Linux' and sys_platform == 'win32')" },
|
||||
{ name = "traitlets" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/00/11/b56381fa6c3f4cc5d2cf54a7dbf98ad9aa0b339ef7a601d6053538b079a7/jupyter_core-5.7.2.tar.gz", hash = "sha256:aa5f8d32bbf6b431ac830496da7392035d6f61b4f54872f15c4bd2a9c3f536d9", size = 87629 }
|
||||
@@ -3204,7 +3204,7 @@ name = "pytest"
|
||||
version = "7.4.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
{ name = "colorama", marker = "(python_full_version < '3.10' and platform_machine != 'arm64' and platform_system == 'Darwin' and sys_platform == 'win32') or (platform_machine != 'aarch64' and platform_system == 'Linux' and sys_platform == 'win32') or (platform_system != 'Darwin' and platform_system != 'Linux' and sys_platform == 'win32')" },
|
||||
{ name = "exceptiongroup", marker = "python_full_version < '3.11'" },
|
||||
{ name = "iniconfig" },
|
||||
{ name = "packaging" },
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
source: crates/uv/tests/ecosystem.rs
|
||||
source: crates/uv/tests/it/ecosystem.rs
|
||||
expression: lock
|
||||
---
|
||||
version = 1
|
||||
|
||||
Reference in New Issue
Block a user