Skip to content

Commit 97367d8

Browse files
committed
fix get_supported_tags in cases where the target env has a different platform
1 parent b516801 commit 97367d8

File tree

3 files changed

+64
-5
lines changed

3 files changed

+64
-5
lines changed

src/poetry/utils/env/script_strings.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,29 @@
11
from __future__ import annotations
22

3+
import packaging.tags
4+
5+
6+
GET_PLATFORMS = f"""
7+
import importlib.util
8+
import json
9+
import sys
10+
11+
from pathlib import Path
12+
13+
spec = importlib.util.spec_from_file_location(
14+
"packaging", Path(r"{packaging.__file__}")
15+
)
16+
packaging = importlib.util.module_from_spec(spec)
17+
sys.modules[spec.name] = packaging
18+
19+
spec = importlib.util.spec_from_file_location(
20+
"packaging.tags", Path(r"{packaging.tags.__file__}")
21+
)
22+
packaging_tags = importlib.util.module_from_spec(spec)
23+
spec.loader.exec_module(packaging_tags)
24+
25+
print(json.dumps(list(packaging_tags.platform_tags())))
26+
"""
327

428
GET_ENVIRONMENT_INFO = """\
529
import json
@@ -61,6 +85,7 @@ def _version_nodot(version):
6185
implementation_name, implementation_name
6286
),
6387
"interpreter_version": interpreter_version(),
88+
"sysconfig_platform": sysconfig.get_platform(),
6489
}
6590
6691
print(json.dumps(env))

src/poetry/utils/env/virtual_env.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import json
44
import os
55
import re
6+
import sysconfig
67

78
from contextlib import contextmanager
89
from copy import deepcopy
@@ -15,6 +16,7 @@
1516
from poetry.utils.env.script_strings import GET_BASE_PREFIX
1617
from poetry.utils.env.script_strings import GET_ENVIRONMENT_INFO
1718
from poetry.utils.env.script_strings import GET_PATHS
19+
from poetry.utils.env.script_strings import GET_PLATFORMS
1820
from poetry.utils.env.script_strings import GET_SYS_PATH
1921

2022

@@ -54,6 +56,7 @@ def get_supported_tags(self) -> list[Tag]:
5456
python = self.version_info[:3]
5557
interpreter_name = self.marker_env["interpreter_name"]
5658
interpreter_version = self.marker_env["interpreter_version"]
59+
sysconfig_platform = self.marker_env["sysconfig_platform"]
5760

5861
if interpreter_name == "pp":
5962
interpreter = "pp3"
@@ -62,9 +65,28 @@ def get_supported_tags(self) -> list[Tag]:
6265
else:
6366
interpreter = None
6467

68+
# Why using sysconfig.get_platform() and not ...
69+
# ... platform.machine()
70+
# This one is also different for x86_64 Linux and aarch64 Linux,
71+
# but it is the same for a 32 Bit and a 64 Bit Python on Windows!
72+
# ... platform.architecture()
73+
# This one is also different for a 32 Bit and a 64 Bit Python on Windows,
74+
# but it is the same for x86_64 Linux and aarch64 Linux!
75+
platforms = None
76+
if sysconfig_platform != sysconfig.get_platform():
77+
# Relevant for the following use cases, for example:
78+
# - using a 32 Bit Python on a 64 Bit Windows
79+
# - using an emulated aarch Python on an x86_64 Linux
80+
output = self.run_python_script(GET_PLATFORMS)
81+
platforms = json.loads(output)
82+
6583
return [
66-
*(cpython_tags(python) if interpreter_name == "cp" else generic_tags()),
67-
*compatible_tags(python, interpreter=interpreter),
84+
*(
85+
cpython_tags(python, platforms=platforms)
86+
if interpreter_name == "cp"
87+
else generic_tags(platforms=platforms)
88+
),
89+
*compatible_tags(python, interpreter=interpreter, platforms=platforms),
6890
]
6991

7092
def get_marker_env(self) -> dict[str, Any]:

tests/utils/env/test_env.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from threading import Thread
1010
from typing import TYPE_CHECKING
1111

12+
import packaging.tags
1213
import pytest
1314

1415
from deepdiff.diff import DeepDiff
@@ -92,16 +93,27 @@ def test_env_commands_with_spaces_in_their_arg_work_as_expected(
9293
assert re.match(r"pip \S+ from", output)
9394

9495

96+
@pytest.mark.parametrize("differing_platform", [True, False])
9597
def test_env_get_supported_tags_matches_inside_virtualenv(
96-
tmp_path: Path, manager: EnvManager
98+
tmp_path: Path, manager: EnvManager, mocker: MockerFixture, differing_platform: bool
9799
) -> None:
98100
venv_path = tmp_path / "Virtual Env"
99101
manager.build_venv(venv_path)
100102
venv = VirtualEnv(venv_path)
101103

102-
import packaging.tags
104+
run_python_script_spy = mocker.spy(venv, "run_python_script")
105+
106+
# determine expected tags before patching sysconfig!
107+
expected_tags = list(packaging.tags.sys_tags())
108+
109+
if differing_platform:
110+
mocker.patch("sysconfig.get_platform", return_value="some_other_platform")
111+
expected_call_count = 2
112+
else:
113+
expected_call_count = 1
103114

104-
assert venv.get_supported_tags() == list(packaging.tags.sys_tags())
115+
assert venv.get_supported_tags() == expected_tags
116+
assert run_python_script_spy.call_count == expected_call_count
105117

106118

107119
@pytest.mark.skipif(os.name == "nt", reason="Symlinks are not support for Windows")

0 commit comments

Comments
 (0)