Skip to content

Commit b11e59e

Browse files
ewiandaaignas
andcommitted
Update CHANGELOG.md
Co-authored-by: Ignas Anikevicius <[email protected]>
1 parent f148ca6 commit b11e59e

File tree

4 files changed

+40
-42
lines changed

4 files changed

+40
-42
lines changed

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ Unreleased changes template.
8181

8282
{#v0-0-0-fixed}
8383
### Fixed
84-
* (pypi) Platform specific markers are now correctly handled when using `requirments_by_platform`
85-
in pip.parse Fixed in [#2766](https://github.com/bazel-contrib/rules_python/pull/2766).
84+
* (pypi) Platform specific extras are now correctly handled when using
85+
universal lock files with environment markers. Fixes [#2690](https://github.com/bazel-contrib/rules_python/pull/2690).
8686
* (runfiles) ({obj}`--bootstrap_impl=script`) Follow symlinks when searching for runfiles.
8787
* (toolchains) Do not try to run `chmod` when downloading non-windows hermetic toolchain
8888
repositories on Windows. Fixes

python/private/pypi/parse_requirements.bzl

Lines changed: 15 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -30,23 +30,9 @@ load("//python/private:normalize_name.bzl", "normalize_name")
3030
load("//python/private:repo_utils.bzl", "repo_utils")
3131
load(":index_sources.bzl", "index_sources")
3232
load(":parse_requirements_txt.bzl", "parse_requirements_txt")
33-
load(":pep508_req.bzl", "requirement")
33+
load(":pep508_requirement.bzl", "requirement")
3434
load(":whl_target_platforms.bzl", "select_whls")
3535

36-
def _extract_version(entry):
37-
"""Extract the version part from the requirement string.
38-
39-
40-
Args:
41-
entry: {type}`str` The requirement string.
42-
"""
43-
version_start = entry.find("==")
44-
if version_start != -1:
45-
# Extract everything after '==' until the next space or end of the string
46-
version, _, _ = entry[version_start + 2:].partition(" ")
47-
return version
48-
return None
49-
5036
def parse_requirements(
5137
ctx,
5238
*,
@@ -113,19 +99,19 @@ def parse_requirements(
11399
# are returned as just the base package name. e.g., `foo[bar]` results
114100
# in an entry like `("foo", "foo[bar] == 1.0 ...")`.
115101
# Lines with different markers are not condidered duplicates.
116-
requirements_dict = {
117-
(normalize_name(entry[0]), _extract_version(entry[1]), requirement(entry[1]).marker): entry
118-
for entry in sorted(
119-
parse_result.requirements,
120-
# Get the longest match and fallback to original WORKSPACE sorting,
121-
# which should get us the entry with most extras.
122-
#
123-
# FIXME @aignas 2024-05-13: The correct behaviour might be to get an
124-
# entry with all aggregated extras, but it is unclear if we
125-
# should do this now.
126-
key = lambda x: (len(x[1].partition("==")[0]), x),
127-
)
128-
}.values()
102+
requirements_dict = {}
103+
for entry in sorted(
104+
parse_result.requirements,
105+
# Get the longest match and fallback to original WORKSPACE sorting,
106+
# which should get us the entry with most extras.
107+
#
108+
# FIXME @aignas 2024-05-13: The correct behaviour might be to get an
109+
# entry with all aggregated extras, but it is unclear if we
110+
# should do this now.
111+
key = lambda x: (len(x[1].partition("==")[0]), x),
112+
):
113+
req = requirement(entry[1])
114+
requirements_dict[(req.name, req.version, req.marker)] = entry
129115

130116
tokenized_options = []
131117
for opt in parse_result.options:
@@ -134,7 +120,7 @@ def parse_requirements(
134120

135121
pip_args = tokenized_options + extra_pip_args
136122
for plat in plats:
137-
requirements[plat] = requirements_dict
123+
requirements[plat] = requirements_dict.values()
138124
options[plat] = pip_args
139125

140126
requirements_by_platform = {}

python/private/pypi/pep508_requirement.bzl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,16 @@ def requirement(spec):
3030
"""
3131
spec = spec.strip()
3232
requires, _, maybe_hashes = spec.partition(";")
33+
34+
version_start = requires.find("==")
35+
version = None
36+
if version_start != -1:
37+
# Extract everything after '==' until the next space or end of the string
38+
version, _, _ = requires[version_start + 2:].partition(" ")
39+
40+
# Remove any trailing characters from the version string
41+
version = version.strip(" ")
42+
3343
marker, _, _ = maybe_hashes.partition("--hash")
3444
requires, _, extras_unparsed = requires.partition("[")
3545
extras_unparsed, _, _ = extras_unparsed.partition("]")
@@ -42,4 +52,5 @@ def requirement(spec):
4252
name = normalize_name(name).replace("_", "-"),
4353
marker = marker.strip(" "),
4454
extras = extras,
55+
version = version,
4556
)

tests/pypi/pep508/requirement_tests.bzl

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,21 @@ _tests = []
2020

2121
def _test_requirement_line_parsing(env):
2222
want = {
23-
" name1[ foo ] ": ("name1", ["foo"]),
24-
"Name[foo]": ("name", ["foo"]),
25-
"name [fred,bar] @ http://foo.com ; python_version=='2.7'": ("name", ["fred", "bar"]),
26-
"name; (os_name=='a' or os_name=='b') and os_name=='c'": ("name", [""]),
27-
"name@http://foo.com": ("name", [""]),
28-
"name[ Foo123 ]": ("name", ["Foo123"]),
29-
"name[extra]@http://foo.com": ("name", ["extra"]),
30-
"name[foo]": ("name", ["foo"]),
31-
"name[quux, strange];python_version<'2.7' and platform_version=='2'": ("name", ["quux", "strange"]),
32-
"name_foo[bar]": ("name-foo", ["bar"]),
23+
" name1[ foo ] ": ("name1", ["foo"], None, ""),
24+
"Name[foo]": ("name", ["foo"], None, ""),
25+
"name [fred,bar] @ http://foo.com ; python_version=='2.7'": ("name", ["fred", "bar"], None, "python_version=='2.7'"),
26+
"name; (os_name=='a' or os_name=='b') and os_name=='c'": ("name", [""], None, "(os_name=='a' or os_name=='b') and os_name=='c'"),
27+
"name@http://foo.com": ("name", [""], None, ""),
28+
"name[ Foo123 ]": ("name", ["Foo123"], None, ""),
29+
"name[extra]@http://foo.com": ("name", ["extra"], None, ""),
30+
"name[foo]": ("name", ["foo"], None, ""),
31+
"name[quux, strange];python_version<'2.7' and platform_version=='2'": ("name", ["quux", "strange"], None, "python_version<'2.7' and platform_version=='2'"),
32+
"name_foo[bar]": ("name-foo", ["bar"], None, ""),
33+
"name_foo[bar]==0.25": ("name-foo", ["bar"], "0.25", ""),
3334
}
3435

3536
got = {
36-
i: (parsed.name, parsed.extras)
37+
i: (parsed.name, parsed.extras, parsed.version, parsed.marker)
3738
for i, parsed in {case: requirement(case) for case in want}.items()
3839
}
3940
env.expect.that_dict(got).contains_exactly(want)

0 commit comments

Comments
 (0)