Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
utils.py159 linesDownload Raw Back to packaging
1# This file is dual licensed under the terms of the Apache License, Version2# 2.0, and the BSD License. See the LICENSE file in the root of this repository3# for complete details.4 5from __future__ import annotations6 7import re8from typing import NewType, Tuple, Union, cast9 10from .tags import Tag, parse_tag11from .version import InvalidVersion, Version, _TrimmedRelease12 13BuildTag = Union[Tuple[()], Tuple[int, str]]14NormalizedName = NewType("NormalizedName", str)15 16 17class InvalidName(ValueError):18    """19    An invalid distribution name; users should refer to the packaging user guide.20    """21 22 23class InvalidWheelFilename(ValueError):24    """25    An invalid wheel filename was found, users should refer to PEP 427.26    """27 28 29class InvalidSdistFilename(ValueError):30    """31    An invalid sdist filename was found, users should refer to the packaging user guide.32    """33 34 35# Core metadata spec for `Name`36_validate_regex = re.compile(r"[A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9]", re.IGNORECASE)37_normalized_regex = re.compile(r"[a-z0-9]|[a-z0-9]([a-z0-9-](?!--))*[a-z0-9]")38# PEP 427: The build number must start with a digit.39_build_tag_regex = re.compile(r"(\d+)(.*)")40 41 42def canonicalize_name(name: str, *, validate: bool = False) -> NormalizedName:43    if validate and not _validate_regex.fullmatch(name):44        raise InvalidName(f"name is invalid: {name!r}")45    # Ensure all ``.`` and ``_`` are ``-``46    # Emulates ``re.sub(r"[-_.]+", "-", name).lower()`` from PEP 50347    # Much faster than re, and even faster than str.translate48    value = name.lower().replace("_", "-").replace(".", "-")49    # Condense repeats (faster than regex)50    while "--" in value:51        value = value.replace("--", "-")52    return cast("NormalizedName", value)53 54 55def is_normalized_name(name: str) -> bool:56    return _normalized_regex.fullmatch(name) is not None57 58 59def canonicalize_version(60    version: Version | str, *, strip_trailing_zero: bool = True61) -> str:62    """63    Return a canonical form of a version as a string.64 65    >>> canonicalize_version('1.0.1')66    '1.0.1'67 68    Per PEP 625, versions may have multiple canonical forms, differing69    only by trailing zeros.70 71    >>> canonicalize_version('1.0.0')72    '1'73    >>> canonicalize_version('1.0.0', strip_trailing_zero=False)74    '1.0.0'75 76    Invalid versions are returned unaltered.77 78    >>> canonicalize_version('foo bar baz')79    'foo bar baz'80    """81    if isinstance(version, str):82        try:83            version = Version(version)84        except InvalidVersion:85            return str(version)86    return str(_TrimmedRelease(version) if strip_trailing_zero else version)87 88 89def parse_wheel_filename(90    filename: str,91) -> tuple[NormalizedName, Version, BuildTag, frozenset[Tag]]:92    if not filename.endswith(".whl"):93        raise InvalidWheelFilename(94            f"Invalid wheel filename (extension must be '.whl'): {filename!r}"95        )96 97    filename = filename[:-4]98    dashes = filename.count("-")99    if dashes not in (4, 5):100        raise InvalidWheelFilename(101            f"Invalid wheel filename (wrong number of parts): {filename!r}"102        )103 104    parts = filename.split("-", dashes - 2)105    name_part = parts[0]106    # See PEP 427 for the rules on escaping the project name.107    if "__" in name_part or re.match(r"^[\w\d._]*$", name_part, re.UNICODE) is None:108        raise InvalidWheelFilename(f"Invalid project name: {filename!r}")109    name = canonicalize_name(name_part)110 111    try:112        version = Version(parts[1])113    except InvalidVersion as e:114        raise InvalidWheelFilename(115            f"Invalid wheel filename (invalid version): {filename!r}"116        ) from e117 118    if dashes == 5:119        build_part = parts[2]120        build_match = _build_tag_regex.match(build_part)121        if build_match is None:122            raise InvalidWheelFilename(123                f"Invalid build number: {build_part} in {filename!r}"124            )125        build = cast("BuildTag", (int(build_match.group(1)), build_match.group(2)))126    else:127        build = ()128    tags = parse_tag(parts[-1])129    return (name, version, build, tags)130 131 132def parse_sdist_filename(filename: str) -> tuple[NormalizedName, Version]:133    if filename.endswith(".tar.gz"):134        file_stem = filename[: -len(".tar.gz")]135    elif filename.endswith(".zip"):136        file_stem = filename[: -len(".zip")]137    else:138        raise InvalidSdistFilename(139            f"Invalid sdist filename (extension must be '.tar.gz' or '.zip'):"140            f" {filename!r}"141        )142 143    # We are requiring a PEP 440 version, which cannot contain dashes,144    # so we split on the last dash.145    name_part, sep, version_part = file_stem.rpartition("-")146    if not sep:147        raise InvalidSdistFilename(f"Invalid sdist filename: {filename!r}")148 149    name = canonicalize_name(name_part)150 151    try:152        version = Version(version_part)153    except InvalidVersion as e:154        raise InvalidSdistFilename(155            f"Invalid sdist filename (invalid version): {filename!r}"156        ) from e157 158    return (name, version)159 
codekingpro/portable-devtools · Team Ai