Skip to content

Commit 400a0f7

Browse files
Evaluate PEP 508 environment markers when parsing requirements (closes #517)
1 parent 7d7b240 commit 400a0f7

4 files changed

Lines changed: 42 additions & 2 deletions

File tree

CHANGELOG.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ Changelog
66
This makes builds with uv about nine times faster, since uv runs the backend natively, without creating a build environment or spawning a Python process.
77
Additionally, source distributions no longer include test files, which setuptools previously included incompletely, missing the files needed to actually run them.
88

9+
* Evaluate PEP 508 environment markers when parsing requirements, so a
10+
requirement whose marker does not apply to the current environment (for
11+
example ``colorama==0.4.6 ; sys_platform == 'win32'`` on Linux) no longer
12+
produces a false-positive mismatch.
13+
914
* Drop Python 3.9 support.
1015

1116
2.13.0 (2025-09-09)

pyproject.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ classifiers = [
3535
"Topic :: Utilities",
3636
"Typing :: Typed",
3737
]
38-
dependencies = []
38+
dependencies = [
39+
"packaging",
40+
]
3941
urls = { Changelog = "https://github.com/adamchainz/pip-lock/blob/main/CHANGELOG.rst", Funding = "https://adamj.eu/books/", Repository = "https://github.com/adamchainz/pip-lock" }
4042

4143
[dependency-groups]

src/pip_lock/__init__.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
from collections.abc import Iterable
77
from importlib.metadata import distributions as get_distributions
88

9+
from packaging.markers import InvalidMarker, Marker
10+
911

1012
def read_pip(filename: str) -> list[str]:
1113
"""Return lines in pip file, concatenating included requirement files."""
@@ -38,7 +40,18 @@ def parse_pip(lines: Iterable[str]) -> dict[str, str]:
3840
if VCS_RE.match(line):
3941
continue
4042

41-
full_name, version_and_extras = line.split("==", 1)
43+
# PEP 508 environment marker: skip requirements that don't apply to this environment
44+
# (e.g. ``colorama==0.4.6 ; sys_platform == 'win32'`` on non-Windows).
45+
requirement, _, marker = line.partition(";")
46+
if marker.strip():
47+
try:
48+
if not Marker(marker).evaluate():
49+
continue
50+
except InvalidMarker:
51+
# Leave a malformed marker to pip; don't silently drop the requirement.
52+
pass
53+
54+
full_name, version_and_extras = requirement.split("==", 1)
4255
# Strip extras and normalize
4356
name = normalize_name(full_name.split("[", 1)[0])
4457
version = version_and_extras.split(" ", 1)[0]

tests/test_pip_lock.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,26 @@ def test_ignore_at_git_ssh_urls(self):
104104
def test_ignore_at_https_urls(self):
105105
assert parse_pip(["foo @ https://example.com"]) == {}
106106

107+
def test_marker_matching_environment_is_kept(self):
108+
assert parse_pip(["package==1.0 ; python_version >= '3'"]) == {
109+
"package": "1.0",
110+
}
111+
112+
def test_marker_not_matching_environment_is_skipped(self):
113+
assert parse_pip(["package==1.0 ; python_version < '3'"]) == {}
114+
115+
def test_marker_without_surrounding_spaces(self):
116+
assert parse_pip(["package==1.0;python_version<'3'"]) == {}
117+
118+
def test_marker_with_extras(self):
119+
assert parse_pip(["package[extra]==1.0 ; python_version < '3'"]) == {}
120+
121+
def test_invalid_marker_is_kept(self):
122+
# A malformed marker is left for pip to report, not silently dropped.
123+
assert parse_pip(["package==1.0 ; not a valid marker"]) == {
124+
"package": "1.0",
125+
}
126+
107127

108128
class TestGetInstalled:
109129
def test_single(self):

0 commit comments

Comments
 (0)