Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/tags.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ items that applications should need to reference, in order to parse and check ta

.. autofunction:: sys_tags

.. autofunction:: python_tag

.. autofunction:: create_compatible_tags_selector

.. autoexception:: TooManyTagsError
Expand Down
27 changes: 25 additions & 2 deletions src/packaging/tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"mac_platforms",
"parse_tag",
"platform_tags",
"python_tag",
"sys_tags",
]

Expand Down Expand Up @@ -910,6 +911,28 @@ def _version_nodot(version: PythonVersion) -> str:
return "".join(map(str, version))


def python_tag(
*, implementation: bool = True, version: bool = True, warn: bool = False
) -> str:
"""
Returns a :pep:`425` python tag for the running interpreter.

:param bool implementation: Whether the tag should be specific to the
running interpreter (e.g. ``cp311`` or ``pp311``) instead of using the
generic ``py`` prefix (e.g. ``py311``). Defaults to ``True``.
:param bool version: Whether the tag should include the full interpreter
version (e.g. ``cp311``) instead of only the major version
(e.g. ``cp3``). Defaults to ``True``.
:param bool warn: Whether warnings should be logged. Defaults to ``False``.

.. versionadded:: 26.3
"""
prefix = interpreter_name() if implementation else "py"
if version:
return prefix + interpreter_version(warn=warn)
return prefix + str(sys.version_info.major)


def sys_tags(*, warn: bool = False) -> Iterator[Tag]:
"""
Yields the sequence of tag triples that the running interpreter supports.
Expand Down Expand Up @@ -949,9 +972,9 @@ def sys_tags(*, warn: bool = False) -> Iterator[Tag]:
yield from generic_tags(warn=warn)

if interp_name == "pp":
interp = "pp3"
interp = python_tag(version=False)
elif interp_name == "cp":
interp = "cp" + interpreter_version(warn=warn)
interp = python_tag(warn=warn)
else:
interp = None
yield from compatible_tags(interpreter=interp)
Expand Down
38 changes: 38 additions & 0 deletions tests/test_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,44 @@ def test_sys_version_info(
assert tags.interpreter_version() == version_str


class TestPythonTag:
@pytest.mark.parametrize(
("implementation", "version", "expected"),
[
(True, True, "cp311"),
(True, False, "cp3"),
(False, True, "py311"),
(False, False, "py3"),
],
)
def test_python_tag_cpython(
self,
implementation: bool,
version: bool,
expected: str,
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setattr(tags, "interpreter_name", lambda: "cp")
monkeypatch.setattr(tags, "interpreter_version", lambda **kwargs: "311")
assert (
tags.python_tag(implementation=implementation, version=version) == expected
)

def test_python_tag_pypy(self, monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(tags, "interpreter_name", lambda: "pp")
monkeypatch.setattr(tags, "interpreter_version", lambda **kwargs: "311")
assert tags.python_tag() == "pp311"
assert tags.python_tag(version=False) == "pp3"

def test_python_tag_other_interpreter(
self, monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setattr(tags, "interpreter_name", lambda: "graalpy")
monkeypatch.setattr(tags, "interpreter_version", lambda **kwargs: "311")
assert tags.python_tag() == "graalpy311"
assert tags.python_tag(implementation=False) == "py311"


class TestMacOSPlatforms:
@pytest.mark.parametrize(
("arch", "is_32bit", "expected"),
Expand Down
Loading