]>
jfr.im git - dlqueue.git/blob - venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/utils.py
1 # This file is dual licensed under the terms of the Apache License, Version
2 # 2.0, and the BSD License. See the LICENSE file in the root of this repository
3 # for complete details.
6 from typing
import FrozenSet
, NewType
, Tuple
, Union
, cast
8 from .tags
import Tag
, parse_tag
9 from .version
import InvalidVersion
, Version
11 BuildTag
= Union
[Tuple
[()], Tuple
[int, str]]
12 NormalizedName
= NewType("NormalizedName", str)
15 class InvalidWheelFilename(ValueError):
17 An invalid wheel filename was found, users should refer to PEP 427.
21 class InvalidSdistFilename(ValueError):
23 An invalid sdist filename was found, users should refer to the packaging user guide.
27 _canonicalize_regex
= re
.compile(r
"[-_.]+")
28 # PEP 427: The build number must start with a digit.
29 _build_tag_regex
= re
.compile(r
"(\d+)(.*)")
32 def canonicalize_name(name
: str) -> NormalizedName
:
33 # This is taken from PEP 503.
34 value
= _canonicalize_regex
.sub("-", name
).lower()
35 return cast(NormalizedName
, value
)
38 def canonicalize_version(
39 version
: Union
[Version
, str], *, strip_trailing_zero
: bool = True
42 This is very similar to Version.__str__, but has one subtle difference
43 with the way it handles the release segment.
45 if isinstance(version
, str):
47 parsed
= Version(version
)
48 except InvalidVersion
:
49 # Legacy versions cannot be normalized
58 parts
.append(f
"{parsed.epoch}!")
61 release_segment
= ".".join(str(x
) for x
in parsed
.release
)
62 if strip_trailing_zero
:
63 # NB: This strips trailing '.0's to normalize
64 release_segment
= re
.sub(r
"(\.0)+$", "", release_segment
)
65 parts
.append(release_segment
)
68 if parsed
.pre
is not None:
69 parts
.append("".join(str(x
) for x
in parsed
.pre
))
72 if parsed
.post
is not None:
73 parts
.append(f
".post{parsed.post}")
76 if parsed
.dev
is not None:
77 parts
.append(f
".dev{parsed.dev}")
79 # Local version segment
80 if parsed
.local
is not None:
81 parts
.append(f
"+{parsed.local}")
86 def parse_wheel_filename(
88 ) -> Tuple
[NormalizedName
, Version
, BuildTag
, FrozenSet
[Tag
]]:
89 if not filename
.endswith(".whl"):
90 raise InvalidWheelFilename(
91 f
"Invalid wheel filename (extension must be '.whl'): {filename}"
94 filename
= filename
[:-4]
95 dashes
= filename
.count("-")
96 if dashes
not in (4, 5):
97 raise InvalidWheelFilename(
98 f
"Invalid wheel filename (wrong number of parts): {filename}"
101 parts
= filename
.split("-", dashes
- 2)
103 # See PEP 427 for the rules on escaping the project name
104 if "__" in name_part
or re
.match(r
"^[\w\d._]*$", name_part
, re
.UNICODE
) is None:
105 raise InvalidWheelFilename(f
"Invalid project name: {filename}")
106 name
= canonicalize_name(name_part
)
107 version
= Version(parts
[1])
109 build_part
= parts
[2]
110 build_match
= _build_tag_regex
.match(build_part
)
111 if build_match
is None:
112 raise InvalidWheelFilename(
113 f
"Invalid build number: {build_part} in '{filename}'"
115 build
= cast(BuildTag
, (int(build_match
.group(1)), build_match
.group(2)))
118 tags
= parse_tag(parts
[-1])
119 return (name
, version
, build
, tags
)
122 def parse_sdist_filename(filename
: str) -> Tuple
[NormalizedName
, Version
]:
123 if filename
.endswith(".tar.gz"):
124 file_stem
= filename
[: -len(".tar.gz")]
125 elif filename
.endswith(".zip"):
126 file_stem
= filename
[: -len(".zip")]
128 raise InvalidSdistFilename(
129 f
"Invalid sdist filename (extension must be '.tar.gz' or '.zip'):"
133 # We are requiring a PEP 440 version, which cannot contain dashes,
134 # so we split on the last dash.
135 name_part
, sep
, version_part
= file_stem
.rpartition("-")
137 raise InvalidSdistFilename(f
"Invalid sdist filename: {filename}")
139 name
= canonicalize_name(name_part
)
140 version
= Version(version_part
)
141 return (name
, version
)