Skip to content

Commit

Permalink
refactor tags._generic_api to use EXT_SUFFIX (#607)
Browse files Browse the repository at this point in the history
Co-authored-by: Brett Cannon <brett@python.org>
  • Loading branch information
mattip and brettcannon committed Dec 23, 2022
1 parent 97db717 commit 30554f5
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 19 deletions.
49 changes: 44 additions & 5 deletions src/packaging/tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,10 +225,45 @@ def cpython_tags(
yield Tag(interpreter, "abi3", platform_)


def _generic_abi() -> Iterator[str]:
abi = sysconfig.get_config_var("SOABI")
if abi:
yield _normalize_string(abi)
def _generic_abi() -> List[str]:
"""
Return the ABI tag based on EXT_SUFFIX.
"""
# The following are examples of `EXT_SUFFIX`.
# We want to keep the parts which are related to the ABI and remove the
# parts which are related to the platform:
# - linux: '.cpython-310-x86_64-linux-gnu.so' => cp310
# - mac: '.cpython-310-darwin.so' => cp310
# - win: '.cp310-win_amd64.pyd' => cp310
# - win: '.pyd' => cp37 (uses _cpython_abis())
# - pypy: '.pypy38-pp73-x86_64-linux-gnu.so' => pypy38_pp73
# - graalpy: '.graalpy-38-native-x86_64-darwin.dylib'
# => graalpy_38_native

ext_suffix = _get_config_var("EXT_SUFFIX", warn=True)
if not isinstance(ext_suffix, str) or ext_suffix[0] != ".":
raise SystemError("invalid sysconfig.get_config_var('EXT_SUFFIX')")
parts = ext_suffix.split(".")
if len(parts) < 3:
# CPython3.7 and earlier uses ".pyd" on Windows.
return _cpython_abis(sys.version_info[:2])
soabi = parts[1]
if soabi.startswith("cpython"):
# non-windows
abi = "cp" + soabi.split("-")[1]
elif soabi.startswith("cp"):
# windows
abi = soabi.split("-")[0]
elif soabi.startswith("pypy"):
abi = "-".join(soabi.split("-")[:2])
elif soabi.startswith("graalpy"):
abi = "-".join(soabi.split("-")[:3])
elif soabi:
# pyston, ironpython, others?
abi = soabi
else:
return []
return [_normalize_string(abi)]


def generic_tags(
Expand All @@ -252,8 +287,9 @@ def generic_tags(
interpreter = "".join([interp_name, interp_version])
if abis is None:
abis = _generic_abi()
else:
abis = list(abis)
platforms = list(platforms or platform_tags())
abis = list(abis)
if "none" not in abis:
abis.append("none")
for abi in abis:
Expand Down Expand Up @@ -463,6 +499,9 @@ def platform_tags() -> Iterator[str]:
def interpreter_name() -> str:
"""
Returns the name of the running interpreter.
Some implementations have a reserved, two-letter abbreviation which will
be returned when appropriate.
"""
name = sys.implementation.name
return INTERPRETER_SHORT_NAMES.get(name) or name
Expand Down
84 changes: 70 additions & 14 deletions tests/test_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -823,22 +823,78 @@ def test_no_abi3_python27(self):


class TestGenericTags:
@pytest.mark.skipif(
not sysconfig.get_config_var("SOABI"), reason="SOABI not defined"
)
def test__generic_abi_soabi_provided(self):
abi = sysconfig.get_config_var("SOABI").replace(".", "_").replace("-", "_")
assert [abi] == list(tags._generic_abi())

def test__generic_abi(self, monkeypatch):
def test__generic_abi_macos(self, monkeypatch):
monkeypatch.setattr(
sysconfig, "get_config_var", lambda key: "cpython-37m-darwin"
sysconfig, "get_config_var", lambda key: ".cpython-37m-darwin.so"
)
assert list(tags._generic_abi()) == ["cpython_37m_darwin"]
monkeypatch.setattr(tags, "interpreter_name", lambda: "cp")
assert tags._generic_abi() == ["cp37m"]

def test__generic_abi_linux_cpython(self, monkeypatch):
config = {
"Py_DEBUG": False,
"WITH_PYMALLOC": True,
"EXT_SUFFIX": ".cpython-37m-x86_64-linux-gnu.so",
}
monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__)
monkeypatch.setattr(tags, "interpreter_name", lambda: "cp")
# They are identical
assert tags._cpython_abis((3, 7)) == ["cp37m"]
assert tags._generic_abi() == ["cp37m"]

def test__generic_abi_jp(self, monkeypatch):
config = {"EXT_SUFFIX": ".return exactly this.so"}
monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__)
assert tags._generic_abi() == ["return exactly this"]

def test__generic_abi_graal(self, monkeypatch):
config = {"EXT_SUFFIX": ".graalpy-38-native-x86_64-darwin.so"}
monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__)
assert tags._generic_abi() == ["graalpy_38_native"]

def test__generic_abi_none(self, monkeypatch):
config = {"EXT_SUFFIX": "..so"}
monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__)
assert tags._generic_abi() == []

@pytest.mark.parametrize("ext_suffix", ["invalid", None])
def test__generic_abi_error(self, ext_suffix, monkeypatch):
config = {"EXT_SUFFIX": ext_suffix}
monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__)
with pytest.raises(SystemError) as e:
tags._generic_abi()
assert "EXT_SUFFIX" in str(e.value)

def test__generic_abi_linux_pypy(self, monkeypatch):
# issue gh-606
config = {
"Py_DEBUG": False,
"EXT_SUFFIX": ".pypy39-pp73-x86_64-linux-gnu.so",
}
monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__)
monkeypatch.setattr(tags, "interpreter_name", lambda: "pp")
assert tags._generic_abi() == ["pypy39_pp73"]

def test__generic_abi_old_windows(self, monkeypatch):
config = {
"EXT_SUFFIX": ".pyd",
"Py_DEBUG": 0,
"WITH_PYMALLOC": 0,
}
monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__)
assert tags._generic_abi() == tags._cpython_abis(sys.version_info[:2])

def test__generic_abi_windows(self, monkeypatch):
config = {
"EXT_SUFFIX": ".cp310-win_amd64.pyd",
}
monkeypatch.setattr(sysconfig, "get_config_var", config.__getitem__)
assert tags._generic_abi() == ["cp310"]

def test__generic_abi_no_soabi(self, monkeypatch):
monkeypatch.setattr(sysconfig, "get_config_var", lambda key: None)
assert not list(tags._generic_abi())
@pytest.mark.skipif(sys.implementation.name != "cpython", reason="CPython-only")
def test__generic_abi_agree(self):
"""Test that the two methods of finding the abi tag agree"""
assert tags._generic_abi() == tags._cpython_abis(sys.version_info[:2])

def test_generic_platforms(self):
platform = sysconfig.get_platform().replace("-", "_")
Expand Down Expand Up @@ -874,7 +930,7 @@ def test_interpreter_default(self, monkeypatch):
assert result == [tags.Tag("sillywalkNN", "none", "any")]

def test_abis_default(self, monkeypatch):
monkeypatch.setattr(tags, "_generic_abi", lambda: iter(["abi"]))
monkeypatch.setattr(tags, "_generic_abi", lambda: ["abi"])
result = list(tags.generic_tags(interpreter="sillywalk", platforms=["any"]))
assert result == [
tags.Tag("sillywalk", "abi", "any"),
Expand Down

0 comments on commit 30554f5

Please sign in to comment.