summaryrefslogtreecommitdiffstats
path: root/third_party/python/setuptools/setuptools/_normalization.py
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/python/setuptools/setuptools/_normalization.py')
-rw-r--r--third_party/python/setuptools/setuptools/_normalization.py114
1 files changed, 114 insertions, 0 deletions
diff --git a/third_party/python/setuptools/setuptools/_normalization.py b/third_party/python/setuptools/setuptools/_normalization.py
new file mode 100644
index 0000000000..31899f7ab1
--- /dev/null
+++ b/third_party/python/setuptools/setuptools/_normalization.py
@@ -0,0 +1,114 @@
+"""
+Helpers for normalization as expected in wheel/sdist/module file names
+and core metadata
+"""
+import re
+from pathlib import Path
+from typing import Union
+
+from .extern import packaging
+from .warnings import SetuptoolsDeprecationWarning
+
+_Path = Union[str, Path]
+
+# https://packaging.python.org/en/latest/specifications/core-metadata/#name
+_VALID_NAME = re.compile(r"^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$", re.I)
+_UNSAFE_NAME_CHARS = re.compile(r"[^A-Z0-9.]+", re.I)
+
+
+def safe_identifier(name: str) -> str:
+ """Make a string safe to be used as Python identifier.
+ >>> safe_identifier("12abc")
+ '_12abc'
+ >>> safe_identifier("__editable__.myns.pkg-78.9.3_local")
+ '__editable___myns_pkg_78_9_3_local'
+ """
+ safe = re.sub(r'\W|^(?=\d)', '_', name)
+ assert safe.isidentifier()
+ return safe
+
+
+def safe_name(component: str) -> str:
+ """Escape a component used as a project name according to Core Metadata.
+ >>> safe_name("hello world")
+ 'hello-world'
+ >>> safe_name("hello?world")
+ 'hello-world'
+ """
+ # See pkg_resources.safe_name
+ return _UNSAFE_NAME_CHARS.sub("-", component)
+
+
+def safe_version(version: str) -> str:
+ """Convert an arbitrary string into a valid version string.
+ >>> safe_version("1988 12 25")
+ '1988.12.25'
+ >>> safe_version("v0.2.1")
+ '0.2.1'
+ >>> safe_version("v0.2?beta")
+ '0.2b0'
+ >>> safe_version("v0.2 beta")
+ '0.2b0'
+ >>> safe_version("ubuntu lts")
+ Traceback (most recent call last):
+ ...
+ setuptools.extern.packaging.version.InvalidVersion: Invalid version: 'ubuntu.lts'
+ """
+ v = version.replace(' ', '.')
+ try:
+ return str(packaging.version.Version(v))
+ except packaging.version.InvalidVersion:
+ attempt = _UNSAFE_NAME_CHARS.sub("-", v)
+ return str(packaging.version.Version(attempt))
+
+
+def best_effort_version(version: str) -> str:
+ """Convert an arbitrary string into a version-like string.
+ >>> best_effort_version("v0.2 beta")
+ '0.2b0'
+
+ >>> import warnings
+ >>> warnings.simplefilter("ignore", category=SetuptoolsDeprecationWarning)
+ >>> best_effort_version("ubuntu lts")
+ 'ubuntu.lts'
+ """
+ # See pkg_resources.safe_version
+ try:
+ return safe_version(version)
+ except packaging.version.InvalidVersion:
+ SetuptoolsDeprecationWarning.emit(
+ f"Invalid version: {version!r}.",
+ f"""
+ Version {version!r} is not valid according to PEP 440.
+
+ Please make sure to specify a valid version for your package.
+ Also note that future releases of setuptools may halt the build process
+ if an invalid version is given.
+ """,
+ see_url="https://peps.python.org/pep-0440/",
+ due_date=(2023, 9, 26), # See setuptools/dist _validate_version
+ )
+ v = version.replace(' ', '.')
+ return safe_name(v)
+
+
+def filename_component(value: str) -> str:
+ """Normalize each component of a filename (e.g. distribution/version part of wheel)
+ Note: ``value`` needs to be already normalized.
+ >>> filename_component("my-pkg")
+ 'my_pkg'
+ """
+ return value.replace("-", "_").strip("_")
+
+
+def safer_name(value: str) -> str:
+ """Like ``safe_name`` but can be used as filename component for wheel"""
+ # See bdist_wheel.safer_name
+ return filename_component(safe_name(value))
+
+
+def safer_best_effort_version(value: str) -> str:
+ """Like ``best_effort_version`` but can be used as filename component for wheel"""
+ # See bdist_wheel.safer_verion
+ # TODO: Replace with only safe_version in the future (no need for best effort)
+ return filename_component(best_effort_version(value))