Skip to content

Commit

Permalink
Merge branch 'main' into fix-incorrect-implicit-return-types
Browse files Browse the repository at this point in the history
  • Loading branch information
Avasam authored Jun 17, 2024
2 parents 91da8a1 + 8aa9855 commit 7b6d6ee
Show file tree
Hide file tree
Showing 12 changed files with 111 additions and 74 deletions.
1 change: 1 addition & 0 deletions newsfragments/4382.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Prevent a ``TypeError: 'NoneType' object is not callable`` when ``shutil_rmtree`` is called without an ``onexc`` parameter on Python<=3.11 -- by :user:`Avasam`
2 changes: 2 additions & 0 deletions newsfragments/4405.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Improvement for ``attr:`` directives in configuration to handle
more edge cases related to complex ``package_dir``.
1 change: 1 addition & 0 deletions newsfragments/4411.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix accidental implicit string concatenation.
42 changes: 28 additions & 14 deletions pkg_resources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
MutableSequence,
NamedTuple,
NoReturn,
Sequence,
Set,
Tuple,
Type,
Expand All @@ -50,6 +49,7 @@
Iterable,
Optional,
TypeVar,
overload,
)
import zipfile
import zipimport
Expand Down Expand Up @@ -101,7 +101,7 @@

if TYPE_CHECKING:
from typing_extensions import Self
from _typeshed import StrPath, StrOrBytesPath
from _typeshed import StrPath, StrOrBytesPath, BytesPath

warnings.warn(
"pkg_resources is deprecated as an API. "
Expand Down Expand Up @@ -1047,7 +1047,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,
):
Expand Down Expand Up @@ -1090,7 +1090,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.
Expand Down Expand Up @@ -1294,7 +1294,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
Expand Down Expand Up @@ -1346,7 +1346,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
Expand Down Expand Up @@ -2473,12 +2473,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
Expand All @@ -2489,9 +2493,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):
Expand Down Expand Up @@ -2745,7 +2759,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
) -> "Distribution":
Expand Down Expand Up @@ -3005,7 +3019,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
):
Expand Down Expand Up @@ -3343,7 +3357,7 @@ def _find_adapter(registry: Mapping[type, _AdapterT], ob: object) -> _AdapterT:
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)
Expand Down
34 changes: 22 additions & 12 deletions setuptools/build_meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@
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, 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
Expand Down Expand Up @@ -113,7 +113,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
Expand Down Expand Up @@ -370,11 +370,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)

Expand Down Expand Up @@ -404,7 +404,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(
Expand All @@ -415,12 +418,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"))
Expand All @@ -433,7 +440,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)
Expand Down
3 changes: 2 additions & 1 deletion setuptools/command/bdist_egg.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,8 +382,9 @@ def scan_module(egg_dir, base, name, stubs):
for bad in [
'getsource',
'getabsfile',
'getfile',
'getsourcefile',
'getfile' 'getsourcelines',
'getsourcelines',
'findsource',
'getcomments',
'getframeinfo',
Expand Down
7 changes: 4 additions & 3 deletions setuptools/command/install_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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,
Expand All @@ -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

Expand Down
5 changes: 3 additions & 2 deletions setuptools/command/install_scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import distutils.command.install_scripts as orig
import os
import sys
from typing import List

from .._path import ensure_directory

Expand All @@ -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
Expand Down
22 changes: 18 additions & 4 deletions setuptools/compat/py311.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
import sys
from __future__ import annotations

import shutil
import sys
from typing import Any, Callable, TYPE_CHECKING

if TYPE_CHECKING:
from _typeshed import StrOrBytesPath, ExcInfo

# Same as shutil._OnExcCallback from typeshed
_OnExcCallback = Callable[[Callable[..., Any], str, BaseException], object]


def shutil_rmtree(path, ignore_errors=False, onexc=None):
def shutil_rmtree(
path: StrOrBytesPath,
ignore_errors: bool = False,
onexc: _OnExcCallback | None = None,
) -> None:
if sys.version_info >= (3, 12):
return shutil.rmtree(path, ignore_errors, onexc=onexc)

def _handler(fn, path, excinfo):
return onexc(fn, path, excinfo[1])
def _handler(fn: Callable[..., Any], path: str, excinfo: ExcInfo) -> None:
if onexc:
onexc(fn, path, excinfo[1])

return shutil.rmtree(path, ignore_errors, onerror=_handler)
Loading

0 comments on commit 7b6d6ee

Please sign in to comment.