xref: /aosp_15_r20/external/bazelbuild-rules_python/python/private/pypi/parse_whl_name.bzl (revision 60517a1edbc8ecf509223e9af94a7adec7d736b8)
1# Copyright 2023 The Bazel Authors. All rights reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15"""
16A starlark implementation of a Wheel filename parsing.
17"""
18
19# Taken from https://peps.python.org/pep-0600/
20_LEGACY_ALIASES = {
21    "manylinux1_i686": "manylinux_2_5_i686",
22    "manylinux1_x86_64": "manylinux_2_5_x86_64",
23    "manylinux2010_i686": "manylinux_2_12_i686",
24    "manylinux2010_x86_64": "manylinux_2_12_x86_64",
25    "manylinux2014_aarch64": "manylinux_2_17_aarch64",
26    "manylinux2014_armv7l": "manylinux_2_17_armv7l",
27    "manylinux2014_i686": "manylinux_2_17_i686",
28    "manylinux2014_ppc64": "manylinux_2_17_ppc64",
29    "manylinux2014_ppc64le": "manylinux_2_17_ppc64le",
30    "manylinux2014_s390x": "manylinux_2_17_s390x",
31    "manylinux2014_x86_64": "manylinux_2_17_x86_64",
32}
33
34def normalize_platform_tag(tag):
35    """Resolve legacy aliases to modern equivalents for easier parsing elsewhere."""
36    return ".".join(list({
37        # The `list({})` usage here is to use it as a string set, where we will
38        # deduplicate, but otherwise retain the order of the tags.
39        _LEGACY_ALIASES.get(p, p): None
40        for p in tag.split(".")
41    }))
42
43def parse_whl_name(file):
44    """Parse whl file name into a struct of constituents.
45
46    Args:
47        file (str): The file name of a wheel
48
49    Returns:
50        A struct with the following attributes:
51            distribution: the distribution name
52            version: the version of the distribution
53            build_tag: the build tag for the wheel. None if there was no
54              build_tag in the given string.
55            python_tag: the python tag for the wheel
56            abi_tag: the ABI tag for the wheel
57            platform_tag: the platform tag
58    """
59    if not file.endswith(".whl"):
60        fail("not a valid wheel: {}".format(file))
61
62    file = file[:-len(".whl")]
63
64    # Parse the following
65    # {distribution}-{version}(-{build tag})?-{python tag}-{abi tag}-{platform tag}.whl
66    #
67    # For more info, see the following standards:
68    # https://packaging.python.org/en/latest/specifications/binary-distribution-format/#binary-distribution-format
69    # https://packaging.python.org/en/latest/specifications/platform-compatibility-tags/
70    head, _, platform_tag = file.rpartition("-")
71    if not platform_tag:
72        fail("cannot extract platform tag from the whl filename: {}".format(file))
73    head, _, abi_tag = head.rpartition("-")
74    if not abi_tag:
75        fail("cannot extract abi tag from the whl filename: {}".format(file))
76    head, _, python_tag = head.rpartition("-")
77    if not python_tag:
78        fail("cannot extract python tag from the whl filename: {}".format(file))
79    head, _, version = head.rpartition("-")
80    if not version:
81        fail("cannot extract version from the whl filename: {}".format(file))
82    distribution, _, maybe_version = head.partition("-")
83
84    if maybe_version:
85        version, build_tag = maybe_version, version
86    else:
87        build_tag = None
88
89    return struct(
90        distribution = distribution,
91        version = version,
92        build_tag = build_tag,
93        python_tag = python_tag,
94        abi_tag = abi_tag,
95        platform_tag = normalize_platform_tag(platform_tag),
96    )
97