Skip to content

Commit 882bd43

Browse files
authored
Merge branch 'main' into Use-set-instead-of-True-only-dict-non-public
2 parents 0ab0a4d + 8aa9855 commit 882bd43

File tree

17 files changed

+149
-110
lines changed

17 files changed

+149
-110
lines changed

newsfragments/4382.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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`

newsfragments/4403.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Replace use of mktemp with can_symlink from the stdlib test suite.

newsfragments/4405.bugfix.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Improvement for ``attr:`` directives in configuration to handle
2+
more edge cases related to complex ``package_dir``.

newsfragments/4411.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix accidental implicit string concatenation.

pkg_resources/__init__.py

Lines changed: 54 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
MutableSequence,
3737
NamedTuple,
3838
NoReturn,
39-
Sequence,
4039
Set,
4140
Tuple,
4241
Type,
@@ -49,6 +48,7 @@
4948
Iterable,
5049
Optional,
5150
TypeVar,
51+
overload,
5252
)
5353
import zipfile
5454
import zipimport
@@ -99,7 +99,7 @@
9999
from pkg_resources.extern.platformdirs import user_cache_dir as _user_cache_dir
100100

101101
if TYPE_CHECKING:
102-
from _typeshed import StrPath
102+
from _typeshed import StrPath, StrOrBytesPath, BytesPath
103103

104104
warnings.warn(
105105
"pkg_resources is deprecated as an API. "
@@ -109,7 +109,7 @@
109109
)
110110

111111

112-
T = TypeVar("T")
112+
_T = TypeVar("_T")
113113
# Type aliases
114114
_NestedStr = Union[str, Iterable[Union[str, Iterable["_NestedStr"]]]]
115115
_InstallerType = Callable[["Requirement"], Optional["Distribution"]]
@@ -118,7 +118,12 @@
118118
_MetadataType = Optional["IResourceProvider"]
119119
# Any object works, but let's indicate we expect something like a module (optionally has __loader__ or __file__)
120120
_ModuleLike = Union[object, types.ModuleType]
121-
_AdapterType = Callable[..., Any] # Incomplete
121+
_ProviderFactoryType = Callable[[_ModuleLike], "IResourceProvider"]
122+
_DistFinderType = Callable[[_T, str, bool], Iterable["Distribution"]]
123+
_NSHandlerType = Callable[[_T, str, str, types.ModuleType], Optional[str]]
124+
_AdapterT = TypeVar(
125+
"_AdapterT", _DistFinderType[Any], _ProviderFactoryType, _NSHandlerType[Any]
126+
)
122127

123128

124129
# Use _typeshed.importlib.LoaderProtocol once available https://github.com/python/typeshed/pull/11890
@@ -142,7 +147,7 @@ class PEP440Warning(RuntimeWarning):
142147
_state_vars: Dict[str, str] = {}
143148

144149

145-
def _declare_state(vartype: str, varname: str, initial_value: T) -> T:
150+
def _declare_state(vartype: str, varname: str, initial_value: _T) -> _T:
146151
_state_vars[varname] = vartype
147152
return initial_value
148153

@@ -377,7 +382,7 @@ class UnknownExtra(ResolutionError):
377382
"""Distribution doesn't have an "extra feature" of the given name"""
378383

379384

380-
_provider_factories: Dict[Type[_ModuleLike], _AdapterType] = {}
385+
_provider_factories: Dict[Type[_ModuleLike], _ProviderFactoryType] = {}
381386

382387
PY_MAJOR = '{}.{}'.format(*sys.version_info)
383388
EGG_DIST = 3
@@ -388,7 +393,7 @@ class UnknownExtra(ResolutionError):
388393

389394

390395
def register_loader_type(
391-
loader_type: Type[_ModuleLike], provider_factory: _AdapterType
396+
loader_type: Type[_ModuleLike], provider_factory: _ProviderFactoryType
392397
):
393398
"""Register `provider_factory` to make providers for `loader_type`
394399
@@ -1041,7 +1046,7 @@ class Environment:
10411046

10421047
def __init__(
10431048
self,
1044-
search_path: Optional[Sequence[str]] = None,
1049+
search_path: Optional[Iterable[str]] = None,
10451050
platform: Optional[str] = get_supported_platform(),
10461051
python: Optional[str] = PY_MAJOR,
10471052
):
@@ -1084,7 +1089,7 @@ def remove(self, dist: "Distribution"):
10841089
"""Remove `dist` from the environment"""
10851090
self._distmap[dist.key].remove(dist)
10861091

1087-
def scan(self, search_path: Optional[Sequence[str]] = None):
1092+
def scan(self, search_path: Optional[Iterable[str]] = None):
10881093
"""Scan `search_path` for distributions usable in this environment
10891094
10901095
Any distributions found are added to the environment.
@@ -1288,7 +1293,7 @@ def extraction_error(self) -> NoReturn:
12881293
err.original_error = old_exc
12891294
raise err
12901295

1291-
def get_cache_path(self, archive_name: str, names: Iterable[str] = ()):
1296+
def get_cache_path(self, archive_name: str, names: Iterable["StrPath"] = ()):
12921297
"""Return absolute location in cache for `archive_name` and `names`
12931298
12941299
The parent directory of the resulting path will be created if it does
@@ -1340,7 +1345,7 @@ def _warn_unsafe_extraction_path(path):
13401345
).format(**locals())
13411346
warnings.warn(msg, UserWarning)
13421347

1343-
def postprocess(self, tempname: str, filename: str):
1348+
def postprocess(self, tempname: "StrOrBytesPath", filename: "StrOrBytesPath"):
13441349
"""Perform any platform-specific postprocessing of `tempname`
13451350
13461351
This is where Mac header rewrites should be done; other platforms don't
@@ -2097,12 +2102,12 @@ def __init__(self, importer: zipimport.zipimporter):
20972102
self._setup_prefix()
20982103

20992104

2100-
_distribution_finders: Dict[
2101-
type, Callable[[object, str, bool], Iterable["Distribution"]]
2102-
] = _declare_state('dict', '_distribution_finders', {})
2105+
_distribution_finders: Dict[type, _DistFinderType[Any]] = _declare_state(
2106+
'dict', '_distribution_finders', {}
2107+
)
21032108

21042109

2105-
def register_finder(importer_type: type, distribution_finder: _AdapterType):
2110+
def register_finder(importer_type: Type[_T], distribution_finder: _DistFinderType[_T]):
21062111
"""Register `distribution_finder` to find distributions in sys.path items
21072112
21082113
`importer_type` is the type or class of a PEP 302 "Importer" (sys.path item
@@ -2276,15 +2281,17 @@ def resolve_egg_link(path):
22762281

22772282
register_finder(importlib.machinery.FileFinder, find_on_path)
22782283

2279-
_namespace_handlers: Dict[
2280-
type, Callable[[object, str, str, types.ModuleType], Optional[str]]
2281-
] = _declare_state('dict', '_namespace_handlers', {})
2284+
_namespace_handlers: Dict[type, _NSHandlerType[Any]] = _declare_state(
2285+
'dict', '_namespace_handlers', {}
2286+
)
22822287
_namespace_packages: Dict[Optional[str], List[str]] = _declare_state(
22832288
'dict', '_namespace_packages', {}
22842289
)
22852290

22862291

2287-
def register_namespace_handler(importer_type: type, namespace_handler: _AdapterType):
2292+
def register_namespace_handler(
2293+
importer_type: Type[_T], namespace_handler: _NSHandlerType[_T]
2294+
):
22882295
"""Register `namespace_handler` to declare namespace packages
22892296
22902297
`importer_type` is the type or class of a PEP 302 "Importer" (sys.path item
@@ -2429,9 +2436,9 @@ def fixup_namespace_packages(path_item: str, parent: Optional[str] = None):
24292436

24302437

24312438
def file_ns_handler(
2432-
importer: Optional[importlib.abc.PathEntryFinder],
2433-
path_item,
2434-
packageName,
2439+
importer: object,
2440+
path_item: "StrPath",
2441+
packageName: str,
24352442
module: types.ModuleType,
24362443
):
24372444
"""Compute an ns-package subpath for a filesystem or zipfile importer"""
@@ -2454,7 +2461,7 @@ def file_ns_handler(
24542461

24552462

24562463
def null_ns_handler(
2457-
importer: Optional[importlib.abc.PathEntryFinder],
2464+
importer: object,
24582465
path_item: Optional[str],
24592466
packageName: Optional[str],
24602467
module: Optional[_ModuleLike],
@@ -2465,12 +2472,16 @@ def null_ns_handler(
24652472
register_namespace_handler(object, null_ns_handler)
24662473

24672474

2468-
def normalize_path(filename: "StrPath"):
2475+
@overload
2476+
def normalize_path(filename: "StrPath") -> str: ...
2477+
@overload
2478+
def normalize_path(filename: "BytesPath") -> bytes: ...
2479+
def normalize_path(filename: "StrOrBytesPath"):
24692480
"""Normalize a file/dir name for comparison purposes"""
24702481
return os.path.normcase(os.path.realpath(os.path.normpath(_cygwin_patch(filename))))
24712482

24722483

2473-
def _cygwin_patch(filename: "StrPath"): # pragma: nocover
2484+
def _cygwin_patch(filename: "StrOrBytesPath"): # pragma: nocover
24742485
"""
24752486
Contrary to POSIX 2008, on Cygwin, getcwd (3) contains
24762487
symlink components. Using
@@ -2481,9 +2492,19 @@ def _cygwin_patch(filename: "StrPath"): # pragma: nocover
24812492
return os.path.abspath(filename) if sys.platform == 'cygwin' else filename
24822493

24832494

2484-
@functools.lru_cache(maxsize=None)
2485-
def _normalize_cached(filename):
2486-
return normalize_path(filename)
2495+
if TYPE_CHECKING:
2496+
# https://github.com/python/mypy/issues/16261
2497+
# https://github.com/python/typeshed/issues/6347
2498+
@overload
2499+
def _normalize_cached(filename: "StrPath") -> str: ...
2500+
@overload
2501+
def _normalize_cached(filename: "BytesPath") -> bytes: ...
2502+
def _normalize_cached(filename: "StrOrBytesPath") -> Union[str, bytes]: ...
2503+
else:
2504+
2505+
@functools.lru_cache(maxsize=None)
2506+
def _normalize_cached(filename):
2507+
return normalize_path(filename)
24872508

24882509

24892510
def _is_egg_path(path):
@@ -2680,7 +2701,7 @@ def parse_map(
26802701
_data = data.items()
26812702
else:
26822703
_data = split_sections(data)
2683-
maps: Dict[str, Dict[str, "EntryPoint"]] = {}
2704+
maps: Dict[str, Dict[str, EntryPoint]] = {}
26842705
for group, lines in _data:
26852706
if group is None:
26862707
if not lines:
@@ -2736,7 +2757,7 @@ def __init__(
27362757
def from_location(
27372758
cls,
27382759
location: str,
2739-
basename: str,
2760+
basename: "StrPath",
27402761
metadata: _MetadataType = None,
27412762
**kw: int, # We could set `precedence` explicitly, but keeping this as `**kw` for full backwards and subclassing compatibility
27422763
):
@@ -2996,7 +3017,7 @@ def __dir__(self):
29963017
@classmethod
29973018
def from_filename(
29983019
cls,
2999-
filename: str,
3020+
filename: "StrPath",
30003021
metadata: _MetadataType = None,
30013022
**kw: int, # We could set `precedence` explicitly, but keeping this as `**kw` for full backwards and subclassing compatibility
30023023
):
@@ -3321,7 +3342,7 @@ def _always_object(classes):
33213342
return classes
33223343

33233344

3324-
def _find_adapter(registry: Mapping[type, _AdapterType], ob: object):
3345+
def _find_adapter(registry: Mapping[type, _AdapterT], ob: object) -> _AdapterT:
33253346
"""Return an adapter factory for `ob` from `registry`"""
33263347
types = _always_object(inspect.getmro(getattr(ob, '__class__', type(ob))))
33273348
for t in types:
@@ -3332,7 +3353,7 @@ def _find_adapter(registry: Mapping[type, _AdapterType], ob: object):
33323353
raise TypeError(f"Could not find adapter for {registry} and {ob}")
33333354

33343355

3335-
def ensure_directory(path: str):
3356+
def ensure_directory(path: "StrOrBytesPath"):
33363357
"""Ensure that the parent directory of `path` exists"""
33373358
dirname = os.path.dirname(path)
33383359
os.makedirs(dirname, exist_ok=True)

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ testing = [
6868

6969
# workaround for pypa/setuptools#4333
7070
"pyproject-hooks!=1.1",
71+
72+
"jaraco.test",
7173
]
7274
docs = [
7375
# upstream

setuptools/build_meta.py

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@
3636
import tempfile
3737
import warnings
3838
from pathlib import Path
39-
from typing import Dict, Iterator, List, Optional, Union
39+
from typing import Dict, Iterator, List, Optional, Tuple, Union, Iterable
4040

4141
import setuptools
4242
import distutils
4343
from . import errors
44-
from ._path import same_path
44+
from ._path import same_path, StrPath
4545
from ._reqs import parse_strings
4646
from .warnings import SetuptoolsDeprecationWarning
4747
from distutils.util import strtobool
@@ -113,7 +113,7 @@ def _get_immediate_subdirectories(a_dir):
113113
]
114114

115115

116-
def _file_with_extension(directory, extension):
116+
def _file_with_extension(directory: StrPath, extension: Union[str, Tuple[str, ...]]):
117117
matching = (f for f in os.listdir(directory) if f.endswith(extension))
118118
try:
119119
(file,) = matching
@@ -370,11 +370,11 @@ def prepare_metadata_for_build_wheel(
370370

371371
def _build_with_temp_dir(
372372
self,
373-
setup_command,
374-
result_extension,
375-
result_directory,
376-
config_settings,
377-
arbitrary_args=(),
373+
setup_command: Iterable[str],
374+
result_extension: Union[str, Tuple[str, ...]],
375+
result_directory: StrPath,
376+
config_settings: _ConfigSettings,
377+
arbitrary_args: Iterable[str] = (),
378378
):
379379
result_directory = os.path.abspath(result_directory)
380380

@@ -404,7 +404,10 @@ def _build_with_temp_dir(
404404
return result_basename
405405

406406
def build_wheel(
407-
self, wheel_directory, config_settings=None, metadata_directory=None
407+
self,
408+
wheel_directory: StrPath,
409+
config_settings: _ConfigSettings = None,
410+
metadata_directory: Optional[StrPath] = None,
408411
):
409412
with suppress_known_deprecation():
410413
return self._build_with_temp_dir(
@@ -415,12 +418,16 @@ def build_wheel(
415418
self._arbitrary_args(config_settings),
416419
)
417420

418-
def build_sdist(self, sdist_directory, config_settings=None):
421+
def build_sdist(
422+
self, sdist_directory: StrPath, config_settings: _ConfigSettings = None
423+
):
419424
return self._build_with_temp_dir(
420425
['sdist', '--formats', 'gztar'], '.tar.gz', sdist_directory, config_settings
421426
)
422427

423-
def _get_dist_info_dir(self, metadata_directory: Optional[str]) -> Optional[str]:
428+
def _get_dist_info_dir(
429+
self, metadata_directory: Optional[StrPath]
430+
) -> Optional[str]:
424431
if not metadata_directory:
425432
return None
426433
dist_info_candidates = list(Path(metadata_directory).glob("*.dist-info"))
@@ -433,7 +440,10 @@ def _get_dist_info_dir(self, metadata_directory: Optional[str]) -> Optional[str]
433440
# get_requires_for_build_editable
434441
# prepare_metadata_for_build_editable
435442
def build_editable(
436-
self, wheel_directory, config_settings=None, metadata_directory=None
443+
self,
444+
wheel_directory: StrPath,
445+
config_settings: _ConfigSettings = None,
446+
metadata_directory: Optional[str] = None,
437447
):
438448
# XXX can or should we hide our editable_wheel command normally?
439449
info_dir = self._get_dist_info_dir(metadata_directory)

setuptools/command/bdist_egg.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,8 +382,9 @@ def scan_module(egg_dir, base, name, stubs):
382382
for bad in [
383383
'getsource',
384384
'getabsfile',
385+
'getfile',
385386
'getsourcefile',
386-
'getfile' 'getsourcelines',
387+
'getsourcelines',
387388
'findsource',
388389
'getcomments',
389390
'getframeinfo',

0 commit comments

Comments
 (0)