Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit f157444

Browse files
committedNov 29, 2024·
Move into algebra
1 parent 801b71c commit f157444

18 files changed

+506
-373
lines changed
 

‎crates/uv-pep508/src/marker/algebra.rs

+338-12
Large diffs are not rendered by default.

‎crates/uv-pep508/src/marker/lowering.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -35,23 +35,23 @@ impl From<CanonicalMarkerValueVersion> for MarkerValueVersion {
3535
/// Those environment markers with an arbitrary string as value such as `sys_platform`
3636
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
3737
pub enum CanonicalMarkerValueString {
38-
/// `implementation_name`
39-
ImplementationName,
4038
/// `os_name`
4139
OsName,
40+
/// `sys_platform`
41+
SysPlatform,
42+
/// `platform_system`
43+
PlatformSystem,
4244
/// `platform_machine`
4345
PlatformMachine,
4446
/// Deprecated `platform.machine` from <https://peps.python.org/pep-0345/#environment-markers>
4547
/// `platform_python_implementation`
4648
PlatformPythonImplementation,
4749
/// `platform_release`
4850
PlatformRelease,
49-
/// `platform_system`
50-
PlatformSystem,
5151
/// `platform_version`
5252
PlatformVersion,
53-
/// `sys_platform`
54-
SysPlatform,
53+
/// `implementation_name`
54+
ImplementationName,
5555
}
5656

5757
impl From<MarkerValueString> for CanonicalMarkerValueString {

‎crates/uv-pep508/src/marker/tree.rs

+11-204
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use std::cmp::Ordering;
22
use std::fmt::{self, Display, Formatter};
33
use std::ops::{Bound, Deref};
44
use std::str::FromStr;
5-
use std::sync::LazyLock;
65

76
use itertools::Itertools;
87
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
@@ -697,14 +696,12 @@ impl MarkerTree {
697696
#[allow(clippy::needless_pass_by_value)]
698697
pub fn and(&mut self, tree: MarkerTree) {
699698
self.0 = INTERNER.lock().and(self.0, tree.0);
700-
self.simplify();
701699
}
702700

703701
/// Combine this marker tree with the one given via a disjunction.
704702
#[allow(clippy::needless_pass_by_value)]
705703
pub fn or(&mut self, tree: MarkerTree) {
706704
self.0 = INTERNER.lock().or(self.0, tree.0);
707-
self.simplify();
708705
}
709706

710707
/// Sets this to a marker equivalent to the implication of this one and the
@@ -720,23 +717,6 @@ impl MarkerTree {
720717
self.or(consequent);
721718
}
722719

723-
/// Simplify the marker, namely, by detecting known impossible conditions.
724-
///
725-
/// For example, while the marker specification and grammar do not _forbid_ it, we know that
726-
/// both `sys_platform == 'win32'` and `platform_system == 'Darwin'` will never true at the
727-
/// same time.
728-
///
729-
/// This method thus encodes assumptions about the environment that are not guaranteed by the
730-
/// PEP 508 specification alone.
731-
fn simplify(&mut self) {
732-
if !self.0.is_false() {
733-
let mutex = &*MUTUAL_EXCLUSIONS;
734-
if INTERNER.lock().is_disjoint(self.0, mutex.0) {
735-
*self = MarkerTree::FALSE;
736-
}
737-
}
738-
}
739-
740720
/// Returns `true` if there is no environment in which both marker trees can apply,
741721
/// i.e. their conjunction is always `false`.
742722
///
@@ -745,9 +725,7 @@ impl MarkerTree {
745725
/// false negatives, i.e. it may not be able to detect that two markers are disjoint for
746726
/// complex expressions.
747727
pub fn is_disjoint(&self, other: &MarkerTree) -> bool {
748-
let mutex = &*MUTUAL_EXCLUSIONS;
749-
let node = INTERNER.lock().and(self.0, other.0);
750-
node.is_false() || INTERNER.lock().is_disjoint(node, mutex.0)
728+
INTERNER.lock().is_disjoint(self.0, other.0)
751729
}
752730

753731
/// Returns the contents of this marker tree, if it contains at least one expression.
@@ -1595,175 +1573,6 @@ impl schemars::JsonSchema for MarkerTree {
15951573
}
15961574
}
15971575

1598-
static MUTUAL_EXCLUSIONS: LazyLock<MarkerTree> = LazyLock::new(|| {
1599-
let mut tree = NodeId::FALSE;
1600-
for (a, b) in [
1601-
// sys_platform == 'darwin' and platform_system == 'Windows'
1602-
(
1603-
MarkerExpression::String {
1604-
key: MarkerValueString::SysPlatform,
1605-
operator: MarkerOperator::Equal,
1606-
value: "darwin".to_string(),
1607-
},
1608-
MarkerExpression::String {
1609-
key: MarkerValueString::PlatformSystem,
1610-
operator: MarkerOperator::Equal,
1611-
value: "Windows".to_string(),
1612-
},
1613-
),
1614-
// sys_platform == 'darwin' and platform_system == 'Linux'
1615-
(
1616-
MarkerExpression::String {
1617-
key: MarkerValueString::SysPlatform,
1618-
operator: MarkerOperator::Equal,
1619-
value: "darwin".to_string(),
1620-
},
1621-
MarkerExpression::String {
1622-
key: MarkerValueString::PlatformSystem,
1623-
operator: MarkerOperator::Equal,
1624-
value: "Linux".to_string(),
1625-
},
1626-
),
1627-
// sys_platform == 'win32' and platform_system == 'Darwin'
1628-
(
1629-
MarkerExpression::String {
1630-
key: MarkerValueString::SysPlatform,
1631-
operator: MarkerOperator::Equal,
1632-
value: "win32".to_string(),
1633-
},
1634-
MarkerExpression::String {
1635-
key: MarkerValueString::PlatformSystem,
1636-
operator: MarkerOperator::Equal,
1637-
value: "Darwin".to_string(),
1638-
},
1639-
),
1640-
// sys_platform == 'win32' and platform_system == 'Linux'
1641-
(
1642-
MarkerExpression::String {
1643-
key: MarkerValueString::SysPlatform,
1644-
operator: MarkerOperator::Equal,
1645-
value: "win32".to_string(),
1646-
},
1647-
MarkerExpression::String {
1648-
key: MarkerValueString::PlatformSystem,
1649-
operator: MarkerOperator::Equal,
1650-
value: "Linux".to_string(),
1651-
},
1652-
),
1653-
// sys_platform == 'linux' and platform_system == 'Darwin'
1654-
(
1655-
MarkerExpression::String {
1656-
key: MarkerValueString::SysPlatform,
1657-
operator: MarkerOperator::Equal,
1658-
value: "linux".to_string(),
1659-
},
1660-
MarkerExpression::String {
1661-
key: MarkerValueString::PlatformSystem,
1662-
operator: MarkerOperator::Equal,
1663-
value: "Darwin".to_string(),
1664-
},
1665-
),
1666-
// sys_platform == 'linux' and platform_system == 'Windows'
1667-
(
1668-
MarkerExpression::String {
1669-
key: MarkerValueString::SysPlatform,
1670-
operator: MarkerOperator::Equal,
1671-
value: "linux".to_string(),
1672-
},
1673-
MarkerExpression::String {
1674-
key: MarkerValueString::PlatformSystem,
1675-
operator: MarkerOperator::Equal,
1676-
value: "Windows".to_string(),
1677-
},
1678-
),
1679-
// os_name == 'nt' and sys_platform == 'darwin'
1680-
(
1681-
MarkerExpression::String {
1682-
key: MarkerValueString::OsName,
1683-
operator: MarkerOperator::Equal,
1684-
value: "nt".to_string(),
1685-
},
1686-
MarkerExpression::String {
1687-
key: MarkerValueString::SysPlatform,
1688-
operator: MarkerOperator::Equal,
1689-
value: "darwin".to_string(),
1690-
},
1691-
),
1692-
// os_name == 'nt' and sys_platform == 'linux'
1693-
(
1694-
MarkerExpression::String {
1695-
key: MarkerValueString::OsName,
1696-
operator: MarkerOperator::Equal,
1697-
value: "nt".to_string(),
1698-
},
1699-
MarkerExpression::String {
1700-
key: MarkerValueString::SysPlatform,
1701-
operator: MarkerOperator::Equal,
1702-
value: "linux".to_string(),
1703-
},
1704-
),
1705-
// os_name == 'posix' and sys_platform == 'win32'
1706-
(
1707-
MarkerExpression::String {
1708-
key: MarkerValueString::OsName,
1709-
operator: MarkerOperator::Equal,
1710-
value: "posix".to_string(),
1711-
},
1712-
MarkerExpression::String {
1713-
key: MarkerValueString::SysPlatform,
1714-
operator: MarkerOperator::Equal,
1715-
value: "win32".to_string(),
1716-
},
1717-
),
1718-
// os_name == 'nt' and platform_system == 'Darwin'
1719-
(
1720-
MarkerExpression::String {
1721-
key: MarkerValueString::OsName,
1722-
operator: MarkerOperator::Equal,
1723-
value: "nt".to_string(),
1724-
},
1725-
MarkerExpression::String {
1726-
key: MarkerValueString::PlatformSystem,
1727-
operator: MarkerOperator::Equal,
1728-
value: "Darwin".to_string(),
1729-
},
1730-
),
1731-
// os_name == 'nt' and platform_system == 'Linux'
1732-
(
1733-
MarkerExpression::String {
1734-
key: MarkerValueString::OsName,
1735-
operator: MarkerOperator::Equal,
1736-
value: "nt".to_string(),
1737-
},
1738-
MarkerExpression::String {
1739-
key: MarkerValueString::PlatformSystem,
1740-
operator: MarkerOperator::Equal,
1741-
value: "Linux".to_string(),
1742-
},
1743-
),
1744-
// os_name == 'posix' and platform_system == 'Windows'
1745-
(
1746-
MarkerExpression::String {
1747-
key: MarkerValueString::OsName,
1748-
operator: MarkerOperator::Equal,
1749-
value: "posix".to_string(),
1750-
},
1751-
MarkerExpression::String {
1752-
key: MarkerValueString::PlatformSystem,
1753-
operator: MarkerOperator::Equal,
1754-
value: "Windows".to_string(),
1755-
},
1756-
),
1757-
] {
1758-
let mut interner = INTERNER.lock();
1759-
let a = interner.expression(a);
1760-
let b = interner.expression(b);
1761-
let a_and_b = interner.and(a, b);
1762-
tree = interner.or(tree, a_and_b);
1763-
}
1764-
MarkerTree(tree).negate()
1765-
});
1766-
17671576
#[cfg(test)]
17681577
mod test {
17691578
use std::ops::Bound;
@@ -2661,13 +2470,13 @@ mod test {
26612470
or (implementation_name != 'pypy' and sys_platform == 'win32')
26622471
or (sys_platform == 'win32' and os_name != 'nt')
26632472
or (sys_platform != 'win32' and os_name == 'nt')",
2664-
"(os_name != 'nt' and sys_platform == 'win32') \
2665-
or (implementation_name != 'pypy' and os_name == 'nt') \
2666-
or (implementation_name == 'pypy' and os_name != 'nt') \
2667-
or (os_name == 'nt' and sys_platform != 'win32')",
2473+
"(sys_platform != 'win32' and implementation_name == 'pypy') \
2474+
or (os_name != 'nt' and sys_platform == 'win32') \
2475+
or (os_name == 'nt' and sys_platform != 'win32') \
2476+
or (sys_platform == 'win32' and implementation_name != 'pypy')",
26682477
);
26692478

2670-
// This is another case we cannot simplify fully, depending on the variable order.
2479+
// This is a case we can simplify fully, but it's dependent on the variable order.
26712480
// The expression is equivalent to `sys_platform == 'x' or (os_name == 'Linux' and platform_system == 'win32')`.
26722481
assert_simplifies(
26732482
"(os_name == 'Linux' and platform_system == 'win32')
@@ -2676,14 +2485,14 @@ mod test {
26762485
or (os_name != 'Linux' and platform_system == 'win32' and sys_platform == 'x')
26772486
or (os_name == 'Linux' and platform_system != 'win32' and sys_platform == 'x')
26782487
or (os_name != 'Linux' and platform_system != 'win32' and sys_platform == 'x')",
2679-
"(os_name != 'Linux' and sys_platform == 'x') or (platform_system != 'win32' and sys_platform == 'x') or (os_name == 'Linux' and platform_system == 'win32')",
2488+
"(os_name == 'Linux' and platform_system == 'win32') or sys_platform == 'x'",
26802489
);
26812490

26822491
assert_simplifies("python_version > '3.7'", "python_full_version >= '3.8'");
26832492

26842493
assert_simplifies(
26852494
"(python_version <= '3.7' and os_name == 'Linux') or python_version > '3.7'",
2686-
"os_name == 'Linux' or python_full_version >= '3.8'",
2495+
"python_full_version >= '3.8' or os_name == 'Linux'",
26872496
);
26882497

26892498
// Again, the extra `<3.7` and `>=3.9` expressions cannot be seen as redundant due to them being interdependent.
@@ -2692,9 +2501,7 @@ mod test {
26922501
"(os_name == 'Linux' and sys_platform == 'win32') \
26932502
or (os_name != 'Linux' and sys_platform == 'win32' and python_version == '3.7') \
26942503
or (os_name != 'Linux' and sys_platform == 'win32' and python_version == '3.8')",
2695-
"(python_full_version < '3.7' and os_name == 'Linux' and sys_platform == 'win32') \
2696-
or (python_full_version >= '3.9' and os_name == 'Linux' and sys_platform == 'win32') \
2697-
or (python_full_version >= '3.7' and python_full_version < '3.9' and sys_platform == 'win32')",
2504+
"(sys_platform == 'win32' and python_full_version >= '3.7' and python_full_version < '3.9') or (os_name == 'Linux' and sys_platform == 'win32')",
26982505
);
26992506

27002507
assert_simplifies(
@@ -2716,8 +2523,8 @@ mod test {
27162523
assert_simplifies(
27172524
"(os_name == 'nt' and sys_platform == 'win32') \
27182525
or (os_name != 'nt' and platform_version == '1' and (sys_platform == 'win32' or sys_platform == 'win64'))",
2719-
"(platform_version == '1' and sys_platform == 'win32') \
2720-
or (os_name != 'nt' and platform_version == '1' and sys_platform == 'win64') \
2526+
"(sys_platform == 'win32' and platform_version == '1') \
2527+
or (os_name != 'nt' and sys_platform == 'win64' and platform_version == '1') \
27212528
or (os_name == 'nt' and sys_platform == 'win32')",
27222529
);
27232530

‎crates/uv-requirements-txt/src/snapshots/uv_requirements_txt__test__line-endings-poetry-with-hashes.txt.snap

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ RequirementsTxt {
8585
),
8686
),
8787
),
88-
marker: python_full_version >= '3.8' and python_full_version < '4.0' and platform_system == 'Windows',
88+
marker: platform_system == 'Windows' and python_full_version >= '3.8' and python_full_version < '4.0',
8989
origin: Some(
9090
File(
9191
"<REQUIREMENTS_DIR>/poetry-with-hashes.txt",

‎crates/uv-requirements-txt/src/snapshots/uv_requirements_txt__test__parse-poetry-with-hashes.txt.snap

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ RequirementsTxt {
8585
),
8686
),
8787
),
88-
marker: python_full_version >= '3.8' and python_full_version < '4.0' and platform_system == 'Windows',
88+
marker: platform_system == 'Windows' and python_full_version >= '3.8' and python_full_version < '4.0',
8989
origin: Some(
9090
File(
9191
"<REQUIREMENTS_DIR>/poetry-with-hashes.txt",

‎crates/uv-requirements-txt/src/snapshots/uv_requirements_txt__test__parse-unix-editable.txt.snap

+3-3
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ RequirementsTxt {
167167
"dev",
168168
),
169169
],
170-
marker: python_full_version >= '3.9' and os_name == 'posix',
170+
marker: os_name == 'posix' and python_full_version >= '3.9',
171171
origin: Some(
172172
File(
173173
"<REQUIREMENTS_DIR>/editable.txt",
@@ -224,7 +224,7 @@ RequirementsTxt {
224224
"dev",
225225
),
226226
],
227-
marker: python_full_version >= '3.9' and os_name == 'posix',
227+
marker: os_name == 'posix' and python_full_version >= '3.9',
228228
origin: Some(
229229
File(
230230
"<REQUIREMENTS_DIR>/editable.txt",
@@ -274,7 +274,7 @@ RequirementsTxt {
274274
},
275275
},
276276
extras: [],
277-
marker: python_full_version >= '3.9' and os_name == 'posix',
277+
marker: os_name == 'posix' and python_full_version >= '3.9',
278278
origin: Some(
279279
File(
280280
"<REQUIREMENTS_DIR>/editable.txt",

‎crates/uv-requirements-txt/src/snapshots/uv_requirements_txt__test__parse-windows-editable.txt.snap

+3-3
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ RequirementsTxt {
167167
"dev",
168168
),
169169
],
170-
marker: python_full_version >= '3.9' and os_name == 'posix',
170+
marker: os_name == 'posix' and python_full_version >= '3.9',
171171
origin: Some(
172172
File(
173173
"<REQUIREMENTS_DIR>/editable.txt",
@@ -224,7 +224,7 @@ RequirementsTxt {
224224
"dev",
225225
),
226226
],
227-
marker: python_full_version >= '3.9' and os_name == 'posix',
227+
marker: os_name == 'posix' and python_full_version >= '3.9',
228228
origin: Some(
229229
File(
230230
"<REQUIREMENTS_DIR>/editable.txt",
@@ -274,7 +274,7 @@ RequirementsTxt {
274274
},
275275
},
276276
extras: [],
277-
marker: python_full_version >= '3.9' and os_name == 'posix',
277+
marker: os_name == 'posix' and python_full_version >= '3.9',
278278
origin: Some(
279279
File(
280280
"<REQUIREMENTS_DIR>/editable.txt",

0 commit comments

Comments
 (0)
Please sign in to comment.