Skip to content

Commit 343da20

Browse files
committed
feat(pypi): add a standards compliant python_tag creator
This will be needed when we start selecting wheels entirely in the bzlmod extension evaluation phase (bazel-contrib#3058). This adds a few unit tests to just ensure that we conform to the spec even though the code is very simple. Work towards bazel-contrib#2747 Work towards bazel-contrib#2759 Work towards bazel-contrib#2849
1 parent 5c09732 commit 343da20

File tree

4 files changed

+86
-0
lines changed

4 files changed

+86
-0
lines changed

python/private/pypi/BUILD.bazel

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,14 @@ bzl_library(
336336
],
337337
)
338338

339+
bzl_library(
340+
name = "python_tag_bzl",
341+
srcs = ["python_tag.bzl"],
342+
deps = [
343+
"//python/private:version_bzl",
344+
],
345+
)
346+
339347
bzl_library(
340348
name = "render_pkg_aliases_bzl",
341349
srcs = ["render_pkg_aliases.bzl"],

python/private/pypi/python_tag.bzl

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
"A simple utility function to get the python_tag from the implementation name"
2+
3+
load("//python/private:version.bzl", "version")
4+
5+
# Taken from
6+
# https://packaging.python.org/en/latest/specifications/platform-compatibility-tags/#python-tag
7+
_PY_TAGS = {
8+
# "py": Generic Python (does not require implementation-specific features)
9+
"cpython": "cp",
10+
"ironpython": "ip",
11+
"jython": "jy",
12+
"pypy": "pp",
13+
"python": "py",
14+
}
15+
PY_TAG_GENERIC = "py"
16+
17+
def python_tag(implementation_name, python_version = ""):
18+
"""Get the python_tag from the implementation_name.
19+
20+
Args:
21+
implementation_name: {type}`str` the implementation name, e.g. "cpython"
22+
python_version: {type}`str` a version who can be parsed using PEP440 compliant
23+
parser.
24+
25+
Returns:
26+
A {type}`str` that represents the python_tag with a version if the
27+
python_version is given.
28+
"""
29+
if python_version:
30+
v = version.parse(python_version, strict = True)
31+
suffix = "{}{}".format(
32+
v.release[0],
33+
v.release[1] if len(v.release) > 1 else "",
34+
)
35+
else:
36+
suffix = ""
37+
38+
return "{}{}".format(
39+
_PY_TAGS.get(implementation_name, implementation_name),
40+
suffix,
41+
)

tests/pypi/python_tag/BUILD.bazel

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
load(":python_tag_tests.bzl", "python_tag_test_suite")
2+
3+
python_tag_test_suite(name = "python_tag_tests")
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
""
2+
3+
load("@rules_testing//lib:test_suite.bzl", "test_suite")
4+
load("//python/private/pypi:python_tag.bzl", "python_tag") # buildifier: disable=bzl-visibility
5+
6+
_tests = []
7+
8+
def _test_without_version(env):
9+
for give, expect in {
10+
"cpython": "cp",
11+
"ironpython": "ip",
12+
"jython": "jy",
13+
"pypy": "pp",
14+
"python": "py",
15+
"something_else": "something_else",
16+
}.items():
17+
got = python_tag(give)
18+
env.expect.that_str(got).equals(expect)
19+
20+
_tests.append(_test_without_version)
21+
22+
def _test_with_version(env):
23+
got = python_tag("cpython", "3.1.15")
24+
env.expect.that_str(got).equals("cp31")
25+
26+
_tests.append(_test_with_version)
27+
28+
def python_tag_test_suite(name):
29+
"""Create the test suite.
30+
31+
Args:
32+
name: the name of the test suite
33+
"""
34+
test_suite(name = name, basic_tests = _tests)

0 commit comments

Comments
 (0)