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