b6ed9a78e552806cb23d8ac48ada6d41db5b4de5
[SubU] /
1 """Generate and work with PEP 425 Compatibility Tags.
2 """
3
4 import re
5 from typing import List, Optional, Tuple
6
7 from pip._vendor.packaging.tags import (
8     PythonVersion,
9     Tag,
10     compatible_tags,
11     cpython_tags,
12     generic_tags,
13     interpreter_name,
14     interpreter_version,
15     mac_platforms,
16 )
17
18 _osx_arch_pat = re.compile(r"(.+)_(\d+)_(\d+)_(.+)")
19
20
21 def version_info_to_nodot(version_info: Tuple[int, ...]) -> str:
22     # Only use up to the first two numbers.
23     return "".join(map(str, version_info[:2]))
24
25
26 def _mac_platforms(arch: str) -> List[str]:
27     match = _osx_arch_pat.match(arch)
28     if match:
29         name, major, minor, actual_arch = match.groups()
30         mac_version = (int(major), int(minor))
31         arches = [
32             # Since we have always only checked that the platform starts
33             # with "macosx", for backwards-compatibility we extract the
34             # actual prefix provided by the user in case they provided
35             # something like "macosxcustom_". It may be good to remove
36             # this as undocumented or deprecate it in the future.
37             "{}_{}".format(name, arch[len("macosx_") :])
38             for arch in mac_platforms(mac_version, actual_arch)
39         ]
40     else:
41         # arch pattern didn't match (?!)
42         arches = [arch]
43     return arches
44
45
46 def _custom_manylinux_platforms(arch: str) -> List[str]:
47     arches = [arch]
48     arch_prefix, arch_sep, arch_suffix = arch.partition("_")
49     if arch_prefix == "manylinux2014":
50         # manylinux1/manylinux2010 wheels run on most manylinux2014 systems
51         # with the exception of wheels depending on ncurses. PEP 599 states
52         # manylinux1/manylinux2010 wheels should be considered
53         # manylinux2014 wheels:
54         # https://www.python.org/dev/peps/pep-0599/#backwards-compatibility-with-manylinux2010-wheels
55         if arch_suffix in {"i686", "x86_64"}:
56             arches.append("manylinux2010" + arch_sep + arch_suffix)
57             arches.append("manylinux1" + arch_sep + arch_suffix)
58     elif arch_prefix == "manylinux2010":
59         # manylinux1 wheels run on most manylinux2010 systems with the
60         # exception of wheels depending on ncurses. PEP 571 states
61         # manylinux1 wheels should be considered manylinux2010 wheels:
62         # https://www.python.org/dev/peps/pep-0571/#backwards-compatibility-with-manylinux1-wheels
63         arches.append("manylinux1" + arch_sep + arch_suffix)
64     return arches
65
66
67 def _get_custom_platforms(arch: str) -> List[str]:
68     arch_prefix, arch_sep, arch_suffix = arch.partition("_")
69     if arch.startswith("macosx"):
70         arches = _mac_platforms(arch)
71     elif arch_prefix in ["manylinux2014", "manylinux2010"]:
72         arches = _custom_manylinux_platforms(arch)
73     else:
74         arches = [arch]
75     return arches
76
77
78 def _expand_allowed_platforms(platforms: Optional[List[str]]) -> Optional[List[str]]:
79     if not platforms:
80         return None
81
82     seen = set()
83     result = []
84
85     for p in platforms:
86         if p in seen:
87             continue
88         additions = [c for c in _get_custom_platforms(p) if c not in seen]
89         seen.update(additions)
90         result.extend(additions)
91
92     return result
93
94
95 def _get_python_version(version: str) -> PythonVersion:
96     if len(version) > 1:
97         return int(version[0]), int(version[1:])
98     else:
99         return (int(version[0]),)
100
101
102 def _get_custom_interpreter(
103     implementation: Optional[str] = None, version: Optional[str] = None
104 ) -> str:
105     if implementation is None:
106         implementation = interpreter_name()
107     if version is None:
108         version = interpreter_version()
109     return f"{implementation}{version}"
110
111
112 def get_supported(
113     version: Optional[str] = None,
114     platforms: Optional[List[str]] = None,
115     impl: Optional[str] = None,
116     abis: Optional[List[str]] = None,
117 ) -> List[Tag]:
118     """Return a list of supported tags for each version specified in
119     `versions`.
120
121     :param version: a string version, of the form "33" or "32",
122         or None. The version will be assumed to support our ABI.
123     :param platform: specify a list of platforms you want valid
124         tags for, or None. If None, use the local system platform.
125     :param impl: specify the exact implementation you want valid
126         tags for, or None. If None, use the local interpreter impl.
127     :param abis: specify a list of abis you want valid
128         tags for, or None. If None, use the local interpreter abi.
129     """
130     supported: List[Tag] = []
131
132     python_version: Optional[PythonVersion] = None
133     if version is not None:
134         python_version = _get_python_version(version)
135
136     interpreter = _get_custom_interpreter(impl, version)
137
138     platforms = _expand_allowed_platforms(platforms)
139
140     is_cpython = (impl or interpreter_name()) == "cp"
141     if is_cpython:
142         supported.extend(
143             cpython_tags(
144                 python_version=python_version,
145                 abis=abis,
146                 platforms=platforms,
147             )
148         )
149     else:
150         supported.extend(
151             generic_tags(
152                 interpreter=interpreter,
153                 abis=abis,
154                 platforms=platforms,
155             )
156         )
157     supported.extend(
158         compatible_tags(
159             python_version=python_version,
160             interpreter=interpreter,
161             platforms=platforms,
162         )
163     )
164
165     return supported