forked from python-poetry/poetry-plugin-bundle
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathplatforms.py
More file actions
158 lines (123 loc) · 4.91 KB
/
platforms.py
File metadata and controls
158 lines (123 loc) · 4.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
from __future__ import annotations
from dataclasses import dataclass
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from packaging.tags import Tag
from poetry.utils.env import Env
@dataclass
class PlatformTagParseResult:
platform: str
version_major: int
version_minor: int
arch: str
@staticmethod
def parse(tag: str) -> PlatformTagParseResult:
import re
match = re.match("([a-z]+)_([0-9]+)_([0-9]+)_(.*)", tag)
if not match:
raise ValueError(f"Invalid platform tag: {tag}")
platform, version_major_str, version_minor_str, arch = match.groups()
return PlatformTagParseResult(
platform=platform,
version_major=int(version_major_str),
version_minor=int(version_minor_str),
arch=arch,
)
def to_tag(self) -> str:
return "_".join(
[self.platform, str(self.version_major), str(self.version_minor), self.arch]
)
def create_supported_tags(platform: str, env: Env) -> list[Tag]:
"""
Given a platform specifier string, generate a list of compatible tags
for the argument environment's interpreter.
Refer to:
https://packaging.python.org/en/latest/specifications/platform-compatibility-tags/#platform-tag
https://pip.pypa.io/en/stable/cli/pip_install/#cmdoption-platform
"""
from packaging.tags import INTERPRETER_SHORT_NAMES
from packaging.tags import compatible_tags
from packaging.tags import cpython_tags
from packaging.tags import generic_tags
if platform.startswith("manylinux"):
supported_platforms = create_supported_manylinux_platforms(platform)
elif platform.startswith("musllinux"):
supported_platforms = create_supported_musllinux_platforms(platform)
elif platform.startswith("macosx"):
supported_platforms = create_supported_macosx_platforms(platform)
else:
raise NotImplementedError(f"Platform {platform} not supported")
python_implementation = env.python_implementation.lower()
python_version = env.version_info[:2]
interpreter_name = INTERPRETER_SHORT_NAMES.get(
python_implementation, python_implementation
)
interpreter = None
if interpreter_name == "cp":
tags = list(
cpython_tags(python_version=python_version, platforms=supported_platforms)
)
interpreter = f"{interpreter_name}{python_version[0]}{python_version[1]}"
else:
tags = list(
generic_tags(
interpreter=interpreter, abis=[], platforms=supported_platforms
)
)
tags.extend(
compatible_tags(
interpreter=interpreter,
python_version=python_version,
platforms=supported_platforms,
)
)
return tags
def create_supported_manylinux_platforms(platform: str) -> list[str]:
"""
https://peps.python.org/pep-0600/
manylinux_${GLIBCMAJOR}_${GLIBCMINOR}_${ARCH}
For now, only GLIBCMAJOR "2" is supported. It is unclear if there will be a need to support a future major
version like "3" and if specified, how generate the compatible 2.x version tags.
"""
# Implementation based on https://peps.python.org/pep-0600/#package-installers
tag = normalize_legacy_manylinux_alias(platform)
parsed = PlatformTagParseResult.parse(tag)
return [
f"{parsed.platform}_{parsed.version_major}_{tag_minor}_{parsed.arch}"
for tag_minor in range(parsed.version_minor, -1, -1)
]
LEGACY_MANYLINUX_ALIASES = {
"manylinux1": "manylinux_2_5",
"manylinux2010": "manylinux_2_12",
"manylinux2014": "manylinux_2_17",
}
def normalize_legacy_manylinux_alias(tag: str) -> str:
tag_os_index_end = tag.index("_")
tag_os = tag[:tag_os_index_end]
tag_arch_suffix = tag[tag_os_index_end:]
os_replacement = LEGACY_MANYLINUX_ALIASES.get(tag_os)
if not os_replacement:
return tag
return os_replacement + tag_arch_suffix
def create_supported_macosx_platforms(platform: str) -> list[str]:
import re
from packaging.tags import mac_platforms
match = re.match("macosx_([0-9]+)_([0-9]+)_(.*)", platform)
if not match:
raise ValueError(f"Invalid macosx tag: {platform}")
tag_major_str, tag_minor_str, tag_arch = match.groups()
tag_major_max = int(tag_major_str)
tag_minor_max = int(tag_minor_str)
return list(mac_platforms(version=(tag_major_max, tag_minor_max), arch=tag_arch))
def create_supported_musllinux_platforms(platform: str) -> list[str]:
import re
match = re.match("musllinux_([0-9]+)_([0-9]+)_(.*)", platform)
if not match:
raise ValueError(f"Invalid musllinux tag: {platform}")
tag_major_str, tag_minor_str, tag_arch = match.groups()
tag_major_max = int(tag_major_str)
tag_minor_max = int(tag_minor_str)
return [
f"musllinux_{tag_major_max}_{minor}_{tag_arch}"
for minor in range(tag_minor_max, -1, -1)
]