Skip to content

Commit 0af9537

Browse files
committed
fix(pypi): reuse select dicts for constructing the env
Before this PR we would be constructing slightly different environments when the `env_marker_setting` is doing it in the analysis phase and when we are doing it in the repo phase due to how the defaults are handled. In this change we simply reuse the same select statements and add an extra helper that is allowing us to process that. Work towards bazel-contrib#2949 Prep for bazel-contrib#3058
1 parent f02c9c7 commit 0af9537

File tree

7 files changed

+154
-108
lines changed

7 files changed

+154
-108
lines changed

python/private/pypi/BUILD.bazel

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,9 @@ bzl_library(
252252
bzl_library(
253253
name = "pep508_env_bzl",
254254
srcs = ["pep508_env.bzl"],
255+
deps = [
256+
"//python/private:version_bzl",
257+
],
255258
)
256259

257260
bzl_library(
@@ -263,11 +266,6 @@ bzl_library(
263266
],
264267
)
265268

266-
bzl_library(
267-
name = "pep508_platform_bzl",
268-
srcs = ["pep508_platform.bzl"],
269-
)
270-
271269
bzl_library(
272270
name = "pep508_requirement_bzl",
273271
srcs = ["pep508_requirement.bzl"],

python/private/pypi/extension.bzl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,12 @@ def _platforms(*, python_version, minor_mapping, config):
7676

7777
for platform, values in config.platforms.items():
7878
key = "{}_{}".format(abi, platform)
79-
platforms[key] = env(struct(
80-
abi = abi,
79+
platforms[key] = env(
80+
env = values.env,
8181
os = values.os_name,
8282
arch = values.arch_name,
83-
)) | values.env
83+
python_version = python_version,
84+
)
8485
return platforms
8586

8687
def _create_whl_repos(

python/private/pypi/pep508_env.bzl

Lines changed: 57 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,20 @@
1515
"""This module is for implementing PEP508 environment definition.
1616
"""
1717

18+
load("//python/private:version.bzl", "version")
19+
20+
_DEFAULT = "//conditions:default"
21+
22+
# Here we store the aliases in the platform so that the users can specify any valid target in
23+
# there.
24+
_cpu_aliases = {
25+
"arm": "aarch32",
26+
"arm64": "aarch64",
27+
}
28+
_os_aliases = {
29+
"macos": "osx",
30+
}
31+
1832
# See https://stackoverflow.com/a/45125525
1933
platform_machine_aliases = {
2034
# These pairs mean the same hardware, but different values may be used
@@ -59,7 +73,7 @@ platform_machine_select_map = {
5973
"@platforms//cpu:x86_64": "x86_64",
6074
# The value is empty string if it cannot be determined:
6175
# https://docs.python.org/3/library/platform.html#platform.machine
62-
"//conditions:default": "",
76+
_DEFAULT: "",
6377
}
6478

6579
# Platform system returns results from the `uname` call.
@@ -73,17 +87,17 @@ _platform_system_values = {
7387
"linux": "Linux",
7488
"netbsd": "NetBSD",
7589
"openbsd": "OpenBSD",
76-
"osx": "Darwin",
90+
"osx": "Darwin", # NOTE: macos is an alias to osx, we handle it through _os_aliases
7791
"windows": "Windows",
7892
}
7993

8094
platform_system_select_map = {
81-
"@platforms//os:{}".format(bazel_os): py_system
82-
for bazel_os, py_system in _platform_system_values.items()
95+
"@platforms//os:{}".format(os): value
96+
for os, value in _platform_system_values.items()
8397
} | {
8498
# The value is empty string if it cannot be determined:
8599
# https://docs.python.org/3/library/platform.html#platform.machine
86-
"//conditions:default": "",
100+
_DEFAULT: "",
87101
}
88102

89103
# The copy of SO [answer](https://stackoverflow.com/a/13874620) containing
@@ -123,72 +137,78 @@ _sys_platform_values = {
123137
"ios": "ios",
124138
"linux": "linux",
125139
"openbsd": "openbsd",
126-
"osx": "darwin",
140+
"osx": "darwin", # NOTE: macos is an alias to osx, we handle it through _os_aliases
127141
"wasi": "wasi",
128142
"windows": "win32",
129143
}
130144

131145
sys_platform_select_map = {
132-
"@platforms//os:{}".format(bazel_os): py_platform
133-
for bazel_os, py_platform in _sys_platform_values.items()
146+
# These values are decided by the sys.platform docs.
147+
"@platforms//os:{}".format(os): value
148+
for os, value in _sys_platform_values.items()
134149
} | {
135150
# For lack of a better option, use empty string. No standard doc/spec
136151
# about sys_platform value.
137-
"//conditions:default": "",
152+
_DEFAULT: "",
138153
}
139154

140155
# The "java" value is documented, but with Jython defunct,
141156
# shouldn't occur in practice.
142157
# The os.name value is technically a property of the runtime, not the
143158
# targetted runtime OS, but the distinction shouldn't matter if
144159
# things are properly configured.
145-
_os_name_values = {
146-
"linux": "posix",
147-
"osx": "posix",
148-
"windows": "nt",
149-
}
150-
151160
os_name_select_map = {
152-
"@platforms//os:{}".format(bazel_os): py_os
153-
for bazel_os, py_os in _os_name_values.items()
154-
} | {
155-
"//conditions:default": "posix",
161+
"@platforms//os:windows": "nt",
162+
_DEFAULT: "posix",
156163
}
157164

158-
def env(target_platform, *, extra = None):
165+
def _set_default(env, env_key, m, key):
166+
"""Set the default value in the env if it is not already set."""
167+
default = m.get(key, m[_DEFAULT])
168+
env.setdefault(env_key, default)
169+
170+
def env(*, env = None, os, arch, python_version = "", extra = None):
159171
"""Return an env target platform
160172
161173
NOTE: This is for use during the loading phase. For the analysis phase,
162174
`env_marker_setting()` constructs the env dict.
163175
164176
Args:
165-
target_platform: {type}`str` the target platform identifier, e.g.
166-
`cp33_linux_aarch64`
177+
env: {type}`str` the environment.
178+
os: {type}`str` the OS name.
179+
arch: {type}`str` the CPU name.
180+
python_version: {type}`str` the full python version.
167181
extra: {type}`str` the extra value to be added into the env.
168182
169183
Returns:
170184
A dict that can be used as `env` in the marker evaluation.
171185
"""
172-
env = create_env()
186+
env = env or {}
187+
env = env | create_env()
173188
if extra != None:
174189
env["extra"] = extra
175190

176-
if target_platform.abi:
177-
minor_version, _, micro_version = target_platform.abi[3:].partition(".")
178-
micro_version = micro_version or "0"
179-
env = env | {
180-
"implementation_version": "3.{}.{}".format(minor_version, micro_version),
181-
"python_full_version": "3.{}.{}".format(minor_version, micro_version),
182-
"python_version": "3.{}".format(minor_version),
183-
}
184-
if target_platform.os and target_platform.arch:
185-
os = target_platform.os
191+
if python_version:
192+
v = version.parse(python_version)
193+
major = v.release[0]
194+
minor = v.release[1]
195+
micro = v.release[2] if len(v.release) > 2 else 0
186196
env = env | {
187-
"os_name": _os_name_values.get(os, ""),
188-
"platform_machine": target_platform.arch,
189-
"platform_system": _platform_system_values.get(os, ""),
190-
"sys_platform": _sys_platform_values.get(os, ""),
197+
"implementation_version": "{}.{}.{}".format(major, minor, micro),
198+
"python_full_version": "{}.{}.{}".format(major, minor, micro),
199+
"python_version": "{}.{}".format(major, minor),
191200
}
201+
202+
if os:
203+
os = "@platforms//os:{}".format(_os_aliases.get(os, os))
204+
_set_default(env, "os_name", os_name_select_map, os)
205+
_set_default(env, "platform_system", platform_system_select_map, os)
206+
_set_default(env, "sys_platform", sys_platform_select_map, os)
207+
208+
if arch:
209+
arch = "@platforms//cpu:{}".format(_cpu_aliases.get(arch, arch))
210+
_set_default(env, "platform_machine", platform_machine_select_map, arch)
211+
192212
set_missing_env_defaults(env)
193213

194214
return env

python/private/pypi/pep508_platform.bzl

Lines changed: 0 additions & 57 deletions
This file was deleted.

tests/pypi/pep508/BUILD.bazel

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
load(":deps_tests.bzl", "deps_test_suite")
2+
load(":env_tests.bzl", "env_test_suite")
23
load(":evaluate_tests.bzl", "evaluate_test_suite")
34
load(":requirement_tests.bzl", "requirement_test_suite")
45

56
deps_test_suite(
67
name = "deps_tests",
78
)
89

10+
env_test_suite(
11+
name = "env_tests",
12+
)
13+
914
evaluate_test_suite(
1015
name = "evaluate_tests",
1116
)

tests/pypi/pep508/env_tests.bzl

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
"""Tests to check for env construction."""
2+
3+
load("@rules_testing//lib:test_suite.bzl", "test_suite")
4+
load("//python/private/pypi:pep508_env.bzl", pep508_env = "env") # buildifier: disable=bzl-visibility
5+
6+
_tests = []
7+
8+
def _test_env_defaults(env):
9+
got = pep508_env(os = "exotic", arch = "exotic", python_version = "3.1.1")
10+
got.pop("_aliases")
11+
env.expect.that_dict(got).contains_exactly({
12+
"implementation_name": "cpython",
13+
"implementation_version": "3.1.1",
14+
"os_name": "posix",
15+
"platform_machine": "",
16+
"platform_python_implementation": "CPython",
17+
"platform_release": "",
18+
"platform_system": "",
19+
"platform_version": "0",
20+
"python_full_version": "3.1.1",
21+
"python_version": "3.1",
22+
"sys_platform": "",
23+
})
24+
25+
_tests.append(_test_env_defaults)
26+
27+
def _test_env_freebsd(env):
28+
got = pep508_env(os = "freebsd", arch = "arm64", python_version = "3.1.1")
29+
got.pop("_aliases")
30+
env.expect.that_dict(got).contains_exactly({
31+
"implementation_name": "cpython",
32+
"implementation_version": "3.1.1",
33+
"os_name": "posix",
34+
"platform_machine": "aarch64",
35+
"platform_python_implementation": "CPython",
36+
"platform_release": "",
37+
"platform_system": "FreeBSD",
38+
"platform_version": "0",
39+
"python_full_version": "3.1.1",
40+
"python_version": "3.1",
41+
"sys_platform": "freebsd",
42+
})
43+
44+
_tests.append(_test_env_freebsd)
45+
46+
def _test_env_macos(env):
47+
got = pep508_env(os = "macos", arch = "arm64", python_version = "3.1.1")
48+
got.pop("_aliases")
49+
env.expect.that_dict(got).contains_exactly({
50+
"implementation_name": "cpython",
51+
"implementation_version": "3.1.1",
52+
"os_name": "posix",
53+
"platform_machine": "aarch64",
54+
"platform_python_implementation": "CPython",
55+
"platform_release": "",
56+
"platform_system": "Darwin",
57+
"platform_version": "0",
58+
"python_full_version": "3.1.1",
59+
"python_version": "3.1",
60+
"sys_platform": "darwin",
61+
})
62+
63+
_tests.append(_test_env_macos)
64+
65+
def env_test_suite(name): # buildifier: disable=function-docstring
66+
test_suite(
67+
name = name,
68+
basic_tests = _tests,
69+
)

tests/pypi/pep508/evaluate_tests.bzl

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
load("@rules_testing//lib:test_suite.bzl", "test_suite")
1717
load("//python/private/pypi:pep508_env.bzl", pep508_env = "env") # buildifier: disable=bzl-visibility
1818
load("//python/private/pypi:pep508_evaluate.bzl", "evaluate", "tokenize") # buildifier: disable=bzl-visibility
19-
load("//python/private/pypi:pep508_platform.bzl", "platform_from_str") # buildifier: disable=bzl-visibility
2019

2120
_tests = []
2221

@@ -244,26 +243,37 @@ _tests.append(_evaluate_partial_only_extra)
244243

245244
def _evaluate_with_aliases(env):
246245
# When
247-
for target_platform, tests in {
246+
for (os, cpu), tests in {
248247
# buildifier: @unsorted-dict-items
249-
"osx_aarch64": {
248+
("osx", "aarch64"): {
250249
"platform_system == 'Darwin' and platform_machine == 'arm64'": True,
251250
"platform_system == 'Darwin' and platform_machine == 'aarch64'": True,
252251
"platform_system == 'Darwin' and platform_machine == 'amd64'": False,
253252
},
254-
"osx_x86_64": {
253+
("osx", "x86_64"): {
255254
"platform_system == 'Darwin' and platform_machine == 'amd64'": True,
256255
"platform_system == 'Darwin' and platform_machine == 'x86_64'": True,
257256
},
258-
"osx_x86_32": {
257+
("osx", "x86_32"): {
259258
"platform_system == 'Darwin' and platform_machine == 'i386'": True,
260259
"platform_system == 'Darwin' and platform_machine == 'i686'": True,
261260
"platform_system == 'Darwin' and platform_machine == 'x86_32'": True,
262261
"platform_system == 'Darwin' and platform_machine == 'x86_64'": False,
263262
},
263+
("freebsd", "x86_32"): {
264+
"platform_system == 'FreeBSD' and platform_machine == 'i386'": True,
265+
"platform_system == 'FreeBSD' and platform_machine == 'i686'": True,
266+
"platform_system == 'FreeBSD' and platform_machine == 'x86_32'": True,
267+
"platform_system == 'FreeBSD' and platform_machine == 'x86_64'": False,
268+
"platform_system == 'FreeBSD' and os_name == 'posix'": True,
269+
},
264270
}.items(): # buildifier: @unsorted-dict-items
265271
for input, want in tests.items():
266-
_check_evaluate(env, input, want, pep508_env(platform_from_str(target_platform, "")))
272+
_check_evaluate(env, input, want, pep508_env(
273+
os = os,
274+
arch = cpu,
275+
python_version = "3.2",
276+
))
267277

268278
_tests.append(_evaluate_with_aliases)
269279

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy