diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index c86d9f095cc..647654fbb14 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -36,7 +36,6 @@ MutableSequence, NamedTuple, NoReturn, - Sequence, Set, Tuple, Type, @@ -49,6 +48,7 @@ Iterable, Optional, TypeVar, + overload, ) import zipfile import zipimport @@ -99,7 +99,7 @@ from pkg_resources.extern.platformdirs import user_cache_dir as _user_cache_dir if TYPE_CHECKING: - from _typeshed import StrPath + from _typeshed import StrPath, StrOrBytesPath, BytesPath warnings.warn( "pkg_resources is deprecated as an API. " @@ -1041,7 +1041,7 @@ class Environment: def __init__( self, - search_path: Optional[Sequence[str]] = None, + search_path: Optional[Iterable[str]] = None, platform: Optional[str] = get_supported_platform(), python: Optional[str] = PY_MAJOR, ): @@ -1084,7 +1084,7 @@ def remove(self, dist: "Distribution"): """Remove `dist` from the environment""" self._distmap[dist.key].remove(dist) - def scan(self, search_path: Optional[Sequence[str]] = None): + def scan(self, search_path: Optional[Iterable[str]] = None): """Scan `search_path` for distributions usable in this environment Any distributions found are added to the environment. @@ -1288,7 +1288,7 @@ def extraction_error(self) -> NoReturn: err.original_error = old_exc raise err - def get_cache_path(self, archive_name: str, names: Iterable[str] = ()): + def get_cache_path(self, archive_name: str, names: Iterable["StrPath"] = ()): """Return absolute location in cache for `archive_name` and `names` The parent directory of the resulting path will be created if it does @@ -1340,7 +1340,7 @@ def _warn_unsafe_extraction_path(path): ).format(**locals()) warnings.warn(msg, UserWarning) - def postprocess(self, tempname: str, filename: str): + def postprocess(self, tempname: "StrOrBytesPath", filename: "StrOrBytesPath"): """Perform any platform-specific postprocessing of `tempname` This is where Mac header rewrites should be done; other platforms don't @@ -2465,12 +2465,16 @@ def null_ns_handler( register_namespace_handler(object, null_ns_handler) -def normalize_path(filename: "StrPath"): +@overload +def normalize_path(filename: "StrPath") -> str: ... +@overload +def normalize_path(filename: "BytesPath") -> bytes: ... +def normalize_path(filename: "StrOrBytesPath"): """Normalize a file/dir name for comparison purposes""" return os.path.normcase(os.path.realpath(os.path.normpath(_cygwin_patch(filename)))) -def _cygwin_patch(filename: "StrPath"): # pragma: nocover +def _cygwin_patch(filename: "StrOrBytesPath"): # pragma: nocover """ Contrary to POSIX 2008, on Cygwin, getcwd (3) contains symlink components. Using @@ -2481,9 +2485,19 @@ def _cygwin_patch(filename: "StrPath"): # pragma: nocover return os.path.abspath(filename) if sys.platform == 'cygwin' else filename -@functools.lru_cache(maxsize=None) -def _normalize_cached(filename): - return normalize_path(filename) +if TYPE_CHECKING: + # https://github.com/python/mypy/issues/16261 + # https://github.com/python/typeshed/issues/6347 + @overload + def _normalize_cached(filename: "StrPath") -> str: ... + @overload + def _normalize_cached(filename: "BytesPath") -> bytes: ... + def _normalize_cached(filename: "StrOrBytesPath") -> Union[str, bytes]: ... +else: + + @functools.lru_cache(maxsize=None) + def _normalize_cached(filename): + return normalize_path(filename) def _is_egg_path(path): @@ -2736,7 +2750,7 @@ def __init__( def from_location( cls, location: str, - basename: str, + basename: StrPath, metadata: _MetadataType = None, **kw: int, # We could set `precedence` explicitly, but keeping this as `**kw` for full backwards and subclassing compatibility ): @@ -2996,7 +3010,7 @@ def __dir__(self): @classmethod def from_filename( cls, - filename: str, + filename: "StrPath", metadata: _MetadataType = None, **kw: int, # We could set `precedence` explicitly, but keeping this as `**kw` for full backwards and subclassing compatibility ): @@ -3332,7 +3346,7 @@ def _find_adapter(registry: Mapping[type, _AdapterType], ob: object): raise TypeError(f"Could not find adapter for {registry} and {ob}") -def ensure_directory(path: str): +def ensure_directory(path: "StrOrBytesPath"): """Ensure that the parent directory of `path` exists""" dirname = os.path.dirname(path) os.makedirs(dirname, exist_ok=True) diff --git a/setuptools/build_meta.py b/setuptools/build_meta.py index 5799c06ed63..91c176b47e5 100644 --- a/setuptools/build_meta.py +++ b/setuptools/build_meta.py @@ -36,12 +36,13 @@ import tempfile import warnings from pathlib import Path -from typing import Dict, Iterator, List, Optional, Union +from typing import Dict, Iterator, List, Optional, Tuple, Union +from collections.abc import Iterable import setuptools import distutils from . import errors -from ._path import same_path +from ._path import same_path, StrPath from ._reqs import parse_strings from .warnings import SetuptoolsDeprecationWarning from distutils.util import strtobool @@ -113,7 +114,7 @@ def _get_immediate_subdirectories(a_dir): ] -def _file_with_extension(directory, extension): +def _file_with_extension(directory: StrPath, extension: Union[str, Tuple[str, ...]]): matching = (f for f in os.listdir(directory) if f.endswith(extension)) try: (file,) = matching @@ -370,11 +371,11 @@ def prepare_metadata_for_build_wheel( def _build_with_temp_dir( self, - setup_command, - result_extension, - result_directory, - config_settings, - arbitrary_args=(), + setup_command: Iterable[str], + result_extension: Union[str, Tuple[str, ...]], + result_directory: StrPath, + config_settings: _ConfigSettings, + arbitrary_args: Iterable[str] = (), ): result_directory = os.path.abspath(result_directory) @@ -404,7 +405,10 @@ def _build_with_temp_dir( return result_basename def build_wheel( - self, wheel_directory, config_settings=None, metadata_directory=None + self, + wheel_directory: StrPath, + config_settings: _ConfigSettings = None, + metadata_directory: Optional[StrPath] = None, ): with suppress_known_deprecation(): return self._build_with_temp_dir( @@ -415,12 +419,16 @@ def build_wheel( self._arbitrary_args(config_settings), ) - def build_sdist(self, sdist_directory, config_settings=None): + def build_sdist( + self, sdist_directory: StrPath, config_settings: _ConfigSettings = None + ): return self._build_with_temp_dir( ['sdist', '--formats', 'gztar'], '.tar.gz', sdist_directory, config_settings ) - def _get_dist_info_dir(self, metadata_directory: Optional[str]) -> Optional[str]: + def _get_dist_info_dir( + self, metadata_directory: Optional[StrPath] + ) -> Optional[str]: if not metadata_directory: return None dist_info_candidates = list(Path(metadata_directory).glob("*.dist-info")) @@ -433,7 +441,10 @@ def _get_dist_info_dir(self, metadata_directory: Optional[str]) -> Optional[str] # get_requires_for_build_editable # prepare_metadata_for_build_editable def build_editable( - self, wheel_directory, config_settings=None, metadata_directory=None + self, + wheel_directory: StrPath, + config_settings: _ConfigSettings = None, + metadata_directory: Optional[str] = None, ): # XXX can or should we hide our editable_wheel command normally? info_dir = self._get_dist_info_dir(metadata_directory) diff --git a/setuptools/command/install_lib.py b/setuptools/command/install_lib.py index 32ff65e783b..9d76e429e82 100644 --- a/setuptools/command/install_lib.py +++ b/setuptools/command/install_lib.py @@ -2,6 +2,7 @@ import sys from itertools import product, starmap import distutils.command.install_lib as orig +from .._path import StrPath class install_lib(orig.install_lib): @@ -85,8 +86,8 @@ def _gen_exclusion_paths(): def copy_tree( self, - infile, - outfile, + infile: StrPath, + outfile: str, preserve_mode=1, preserve_times=1, preserve_symlinks=0, @@ -96,7 +97,7 @@ def copy_tree( exclude = self.get_exclusions() if not exclude: - return orig.install_lib.copy_tree(self, infile, outfile) + return orig.install_lib.copy_tree(self, infile, outfile) # type: ignore[arg-type] # Fixed upstream # Exclude namespace package __init__.py* files from the output diff --git a/setuptools/command/install_scripts.py b/setuptools/command/install_scripts.py index d79a4ab7b03..e9b0a0fe022 100644 --- a/setuptools/command/install_scripts.py +++ b/setuptools/command/install_scripts.py @@ -2,6 +2,7 @@ import distutils.command.install_scripts as orig import os import sys +from typing import List from .._path import ensure_directory @@ -13,12 +14,12 @@ def initialize_options(self): orig.install_scripts.initialize_options(self) self.no_ep = False - def run(self): + def run(self) -> None: self.run_command("egg_info") if self.distribution.scripts: orig.install_scripts.run(self) # run first to set up self.outfiles else: - self.outfiles = [] + self.outfiles: List[str] = [] if self.no_ep: # don't install entry point scripts into .egg file! return diff --git a/setuptools/config/expand.py b/setuptools/config/expand.py index 0d8d58add82..3dc156a8d7f 100644 --- a/setuptools/config/expand.py +++ b/setuptools/config/expand.py @@ -119,7 +119,9 @@ def glob_relative( return expanded_values -def read_files(filepaths: Union[str, bytes, Iterable[StrPath]], root_dir=None) -> str: +def read_files( + filepaths: Union[StrPath, Iterable[StrPath]], root_dir: Optional[StrPath] = None +) -> str: """Return the content of the files concatenated using ``\n`` as str This function is sandboxed and won't reach anything outside ``root_dir``