summaryrefslogtreecommitdiff
path: root/setuptools/command
diff options
context:
space:
mode:
authorAnderson Bravalheri <andersonbravalheri@gmail.com>2023-02-13 20:32:19 +0000
committerAnderson Bravalheri <andersonbravalheri@gmail.com>2023-02-13 20:32:19 +0000
commit52c605573716db3100543be728addf1bce965802 (patch)
treeb35e3eb73a3dcb07a6249a576d5a95c53f214d8f /setuptools/command
parentbc5f3c306d328a6d3a54fa4172dc62b5d5dddc80 (diff)
parent51bf7563d1513ec3a2edbbcf00a533f85cf26d66 (diff)
downloadpython-setuptools-git-52c605573716db3100543be728addf1bce965802.tar.gz
Reduce usage of pkg_resources (#3792)
Diffstat (limited to 'setuptools/command')
-rw-r--r--setuptools/command/bdist_egg.py15
-rw-r--r--setuptools/command/develop.py17
-rw-r--r--setuptools/command/dist_info.py40
-rw-r--r--setuptools/command/editable_wheel.py43
-rw-r--r--setuptools/command/egg_info.py37
-rw-r--r--setuptools/command/install_egg_info.py5
-rw-r--r--setuptools/command/install_scripts.py9
7 files changed, 70 insertions, 96 deletions
diff --git a/setuptools/command/bdist_egg.py b/setuptools/command/bdist_egg.py
index 11a1c6be..33f483cf 100644
--- a/setuptools/command/bdist_egg.py
+++ b/setuptools/command/bdist_egg.py
@@ -11,7 +11,6 @@ import re
import textwrap
import marshal
-from pkg_resources import get_build_platform, Distribution
from setuptools.extension import Library
from setuptools import Command
from .._path import ensure_directory
@@ -64,7 +63,7 @@ class bdist_egg(Command):
('bdist-dir=', 'b',
"temporary directory for creating the distribution"),
('plat-name=', 'p', "platform name to embed in generated filenames "
- "(default: %s)" % get_build_platform()),
+ "(by default uses `pkg_resources.get_build_platform()`)"),
('exclude-source-files', None,
"remove all .py files from the generated egg"),
('keep-temp', 'k',
@@ -98,18 +97,18 @@ class bdist_egg(Command):
self.bdist_dir = os.path.join(bdist_base, 'egg')
if self.plat_name is None:
+ from pkg_resources import get_build_platform
+
self.plat_name = get_build_platform()
self.set_undefined_options('bdist', ('dist_dir', 'dist_dir'))
if self.egg_output is None:
-
# Compute filename of the output egg
- basename = Distribution(
- None, None, ei_cmd.egg_name, ei_cmd.egg_version,
- get_python_version(),
- self.distribution.has_ext_modules() and self.plat_name
- ).egg_name()
+ basename = ei_cmd._get_egg_basename(
+ py_version=get_python_version(),
+ platform=self.distribution.has_ext_modules() and self.plat_name,
+ )
self.egg_output = os.path.join(self.dist_dir, basename + '.egg')
diff --git a/setuptools/command/develop.py b/setuptools/command/develop.py
index 24fb0a7c..5630ca4c 100644
--- a/setuptools/command/develop.py
+++ b/setuptools/command/develop.py
@@ -5,8 +5,8 @@ import os
import glob
import io
-import pkg_resources
from setuptools.command.easy_install import easy_install
+from setuptools import _path
from setuptools import namespaces
import setuptools
@@ -42,6 +42,8 @@ class develop(namespaces.DevelopInstaller, easy_install):
self.always_copy_from = '.' # always copy eggs installed in curdir
def finalize_options(self):
+ import pkg_resources
+
ei = self.get_finalized_command("egg_info")
if ei.broken_egg_info:
template = "Please rename %r to %r before using 'develop'"
@@ -61,10 +63,8 @@ class develop(namespaces.DevelopInstaller, easy_install):
if self.egg_path is None:
self.egg_path = os.path.abspath(ei.egg_base)
- target = pkg_resources.normalize_path(self.egg_base)
- egg_path = pkg_resources.normalize_path(
- os.path.join(self.install_dir, self.egg_path)
- )
+ target = _path.normpath(self.egg_base)
+ egg_path = _path.normpath(os.path.join(self.install_dir, self.egg_path))
if egg_path != target:
raise DistutilsOptionError(
"--egg-path must be a relative path from the install"
@@ -94,15 +94,16 @@ class develop(namespaces.DevelopInstaller, easy_install):
path_to_setup = egg_base.replace(os.sep, '/').rstrip('/')
if path_to_setup != os.curdir:
path_to_setup = '../' * (path_to_setup.count('/') + 1)
- resolved = pkg_resources.normalize_path(
+ resolved = _path.normpath(
os.path.join(install_dir, egg_path, path_to_setup)
)
- if resolved != pkg_resources.normalize_path(os.curdir):
+ curdir = _path.normpath(os.curdir)
+ if resolved != curdir:
raise DistutilsOptionError(
"Can't get a consistent path to setup script from"
" installation directory",
resolved,
- pkg_resources.normalize_path(os.curdir),
+ curdir,
)
return path_to_setup
diff --git a/setuptools/command/dist_info.py b/setuptools/command/dist_info.py
index 4966d852..545e9995 100644
--- a/setuptools/command/dist_info.py
+++ b/setuptools/command/dist_info.py
@@ -4,18 +4,16 @@ As defined in the wheel specification
"""
import os
-import re
import shutil
import sys
import warnings
from contextlib import contextmanager
-from inspect import cleandoc
+from distutils import log
+from distutils.core import Command
from pathlib import Path
-from distutils.core import Command
-from distutils import log
-from setuptools.extern import packaging
-from setuptools._deprecation_warning import SetuptoolsDeprecationWarning
+from .. import _normalization
+from .._deprecation_warning import SetuptoolsDeprecationWarning
class dist_info(Command):
@@ -76,8 +74,8 @@ class dist_info(Command):
egg_info.finalize_options()
self.egg_info = egg_info
- name = _safe(dist.get_name())
- version = _version(dist.get_version())
+ name = _normalization.safer_name(dist.get_name())
+ version = _normalization.safer_best_effort_version(dist.get_version())
self.name = f"{name}-{version}"
self.dist_info_dir = os.path.join(self.output_dir, f"{self.name}.dist-info")
@@ -109,32 +107,6 @@ class dist_info(Command):
bdist_wheel.egg2dist(egg_info_dir, self.dist_info_dir)
-def _safe(component: str) -> str:
- """Escape a component used to form a wheel name according to PEP 491"""
- return re.sub(r"[^\w\d.]+", "_", component)
-
-
-def _version(version: str) -> str:
- """Convert an arbitrary string to a version string."""
- v = version.replace(' ', '.')
- try:
- return str(packaging.version.Version(v)).replace("-", "_")
- except packaging.version.InvalidVersion:
- msg = f"""Invalid version: {version!r}.
- !!\n\n
- ###################
- # Invalid version #
- ###################
- {version!r} is not valid according to PEP 440.\n
- Please make sure 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.
- \n\n!!
- """
- warnings.warn(cleandoc(msg))
- return _safe(v).strip("_")
-
-
def _rm(dir_name, **opts):
if os.path.isdir(dir_name):
shutil.rmtree(dir_name, **opts)
diff --git a/setuptools/command/editable_wheel.py b/setuptools/command/editable_wheel.py
index 083ef185..5e532a7f 100644
--- a/setuptools/command/editable_wheel.py
+++ b/setuptools/command/editable_wheel.py
@@ -12,7 +12,6 @@ Create a wheel that, when installed, will make the source package 'editable'
import logging
import os
-import re
import shutil
import sys
import traceback
@@ -36,10 +35,17 @@ from typing import (
Union,
)
-from setuptools import Command, SetuptoolsDeprecationWarning, errors, namespaces
-from setuptools.command.build_py import build_py as build_py_cls
-from setuptools.discovery import find_package_path
-from setuptools.dist import Distribution
+from .. import (
+ Command,
+ SetuptoolsDeprecationWarning,
+ _normalization,
+ _path,
+ errors,
+ namespaces,
+)
+from ..discovery import find_package_path
+from ..dist import Distribution
+from .build_py import build_py as build_py_cls
if TYPE_CHECKING:
from wheel.wheelfile import WheelFile # noqa
@@ -482,7 +488,7 @@ class _TopLevelFinder:
))
name = f"__editable__.{self.name}.finder"
- finder = _make_identifier(name)
+ finder = _normalization.safe_identifier(name)
content = bytes(_finder_template(name, roots, namespaces_), "utf-8")
wheel.writestr(f"{finder}.py", content)
@@ -561,7 +567,7 @@ def _simple_layout(
return set(package_dir) in ({}, {""})
parent = os.path.commonpath([_parent_path(k, v) for k, v in layout.items()])
return all(
- _normalize_path(Path(parent, *key.split('.'))) == _normalize_path(value)
+ _path.same_path(Path(parent, *key.split('.')), value)
for key, value in layout.items()
)
@@ -690,21 +696,14 @@ def _is_nested(pkg: str, pkg_path: str, parent: str, parent_path: str) -> bool:
>>> _is_nested("b.a", "path/b/a", "a", "path/a")
False
"""
- norm_pkg_path = _normalize_path(pkg_path)
+ norm_pkg_path = _path.normpath(pkg_path)
rest = pkg.replace(parent, "", 1).strip(".").split(".")
return (
pkg.startswith(parent)
- and norm_pkg_path == _normalize_path(Path(parent_path, *rest))
+ and norm_pkg_path == _path.normpath(Path(parent_path, *rest))
)
-def _normalize_path(filename: _Path) -> str:
- """Normalize a file/dir name for comparison purposes"""
- # See pkg_resources.normalize_path
- file = os.path.abspath(filename) if sys.platform == 'cygwin' else filename
- return os.path.normcase(os.path.realpath(os.path.normpath(file)))
-
-
def _empty_dir(dir_: _P) -> _P:
"""Create a directory ensured to be empty. Existing files may be removed."""
shutil.rmtree(dir_, ignore_errors=True)
@@ -712,18 +711,6 @@ def _empty_dir(dir_: _P) -> _P:
return dir_
-def _make_identifier(name: str) -> str:
- """Make a string safe to be used as Python identifier.
- >>> _make_identifier("12abc")
- '_12abc'
- >>> _make_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
-
-
class _NamespaceInstaller(namespaces.Installer):
def __init__(self, distribution, installation_dir, editable_name, src_root):
self.distribution = distribution
diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py
index 86e99dd2..afcde5a2 100644
--- a/setuptools/command/egg_info.py
+++ b/setuptools/command/egg_info.py
@@ -18,16 +18,13 @@ import time
import collections
from .._importlib import metadata
-from .. import _entry_points
+from .. import _entry_points, _normalization
from setuptools import Command
from setuptools.command.sdist import sdist
from setuptools.command.sdist import walk_revctrl
from setuptools.command.setopt import edit_config
from setuptools.command import bdist_egg
-from pkg_resources import (
- Requirement, safe_name, parse_version,
- safe_version, to_filename)
import setuptools.unicode_utils as unicode_utils
from setuptools.glob import glob
@@ -36,6 +33,9 @@ from setuptools.extern.jaraco.text import yield_lines
from setuptools import SetuptoolsDeprecationWarning
+PY_MAJOR = '{}.{}'.format(*sys.version_info)
+
+
def translate_pattern(glob): # noqa: C901 # is too complex (14) # FIXME
"""
Translate a file path glob like '*.txt' in to a regular expression.
@@ -125,10 +125,11 @@ class InfoCommon:
@property
def name(self):
- return safe_name(self.distribution.get_name())
+ return _normalization.safe_name(self.distribution.get_name())
def tagged_version(self):
- return safe_version(self._maybe_tag(self.distribution.get_version()))
+ tagged = self._maybe_tag(self.distribution.get_version())
+ return _normalization.best_effort_version(tagged)
def _maybe_tag(self, version):
"""
@@ -148,7 +149,7 @@ class InfoCommon:
def _safe_tags(self) -> str:
# To implement this we can rely on `safe_version` pretending to be version 0
# followed by tags. Then we simply discard the starting 0 (fake version number)
- return safe_version(f"0{self.vtags}")[1:]
+ return _normalization.best_effort_version(f"0{self.vtags}")[1:]
def tags(self) -> str:
version = ''
@@ -216,12 +217,12 @@ class egg_info(InfoCommon, Command):
# repercussions.
self.egg_name = self.name
self.egg_version = self.tagged_version()
- parsed_version = parse_version(self.egg_version)
+ parsed_version = packaging.version.Version(self.egg_version)
try:
is_version = isinstance(parsed_version, packaging.version.Version)
spec = "%s==%s" if is_version else "%s===%s"
- Requirement(spec % (self.egg_name, self.egg_version))
+ packaging.requirements.Requirement(spec % (self.egg_name, self.egg_version))
except ValueError as e:
raise distutils.errors.DistutilsOptionError(
"Invalid distribution name or version syntax: %s-%s" %
@@ -233,7 +234,7 @@ class egg_info(InfoCommon, Command):
self.egg_base = (dirs or {}).get('', os.curdir)
self.ensure_dirname('egg_base')
- self.egg_info = to_filename(self.egg_name) + '.egg-info'
+ self.egg_info = _normalization.filename_component(self.egg_name) + '.egg-info'
if self.egg_base != os.curdir:
self.egg_info = os.path.join(self.egg_base, self.egg_info)
if '-' in self.egg_name:
@@ -251,9 +252,13 @@ class egg_info(InfoCommon, Command):
pd = self.distribution._patched_dist
if pd is not None and pd.key == self.egg_name.lower():
pd._version = self.egg_version
- pd._parsed_version = parse_version(self.egg_version)
+ pd._parsed_version = packaging.version.Version(self.egg_version)
self.distribution._patched_dist = None
+ def _get_egg_basename(self, py_version=PY_MAJOR, platform=None):
+ """Compute filename of the output egg. Private API."""
+ return _egg_basename(self.egg_name, self.egg_version, py_version, platform)
+
def write_or_delete_file(self, what, filename, data, force=False):
"""Write `data` to `filename` or delete if empty
@@ -771,5 +776,15 @@ def get_pkg_info_revision():
return 0
+def _egg_basename(egg_name, egg_version, py_version=None, platform=None):
+ """Compute filename of the output egg. Private API."""
+ name = _normalization.filename_component(egg_name)
+ version = _normalization.filename_component(egg_version)
+ egg = f"{name}-{version}-py{py_version or PY_MAJOR}"
+ if platform:
+ egg += f"-{platform}"
+ return egg
+
+
class EggInfoDeprecationWarning(SetuptoolsDeprecationWarning):
"""Deprecated behavior warning for EggInfo, bypassing suppression."""
diff --git a/setuptools/command/install_egg_info.py b/setuptools/command/install_egg_info.py
index 65ede406..1c549c98 100644
--- a/setuptools/command/install_egg_info.py
+++ b/setuptools/command/install_egg_info.py
@@ -5,7 +5,6 @@ from setuptools import Command
from setuptools import namespaces
from setuptools.archive_util import unpack_archive
from .._path import ensure_directory
-import pkg_resources
class install_egg_info(namespaces.Installer, Command):
@@ -24,9 +23,7 @@ class install_egg_info(namespaces.Installer, Command):
self.set_undefined_options('install_lib',
('install_dir', 'install_dir'))
ei_cmd = self.get_finalized_command("egg_info")
- basename = pkg_resources.Distribution(
- None, None, ei_cmd.egg_name, ei_cmd.egg_version
- ).egg_name() + '.egg-info'
+ basename = f"{ei_cmd._get_egg_basename()}.egg-info"
self.source = ei_cmd.egg_info
self.target = os.path.join(self.install_dir, basename)
self.outputs = []
diff --git a/setuptools/command/install_scripts.py b/setuptools/command/install_scripts.py
index aeb0e424..8b3133f1 100644
--- a/setuptools/command/install_scripts.py
+++ b/setuptools/command/install_scripts.py
@@ -4,7 +4,6 @@ from distutils.errors import DistutilsModuleError
import os
import sys
-from pkg_resources import Distribution, PathMetadata
from .._path import ensure_directory
@@ -16,8 +15,6 @@ class install_scripts(orig.install_scripts):
self.no_ep = False
def run(self):
- import setuptools.command.easy_install as ei
-
self.run_command("egg_info")
if self.distribution.scripts:
orig.install_scripts.run(self) # run first to set up self.outfiles
@@ -26,6 +23,12 @@ class install_scripts(orig.install_scripts):
if self.no_ep:
# don't install entry point scripts into .egg file!
return
+ self._install_ep_scripts()
+
+ def _install_ep_scripts(self):
+ # Delay import side-effects
+ from pkg_resources import Distribution, PathMetadata
+ from . import easy_install as ei
ei_cmd = self.get_finalized_command("egg_info")
dist = Distribution(