Skip to content

Commit 94ac34e

Browse files
authored
Merge typeshed return annotations (#4744)
2 parents f9bf422 + 3f7d6c2 commit 94ac34e

18 files changed

+114
-81
lines changed

setuptools/__init__.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,13 @@ def _fetch_build_eggs(dist: Distribution):
108108
raise
109109

110110

111-
def setup(**attrs):
111+
def setup(**attrs) -> Distribution:
112112
logging.configure()
113113
# Make sure we have any requirements needed to interpret 'attrs'.
114114
_install_setup_requires(attrs)
115-
return distutils.core.setup(**attrs)
115+
# Override return type of distutils.core.Distribution with setuptools.dist.Distribution
116+
# (implicitly implemented via `setuptools.monkey.patch_all`).
117+
return distutils.core.setup(**attrs) # type: ignore[return-value]
116118

117119

118120
setup.__doc__ = distutils.core.setup.__doc__
@@ -176,14 +178,14 @@ def __init__(self, dist: Distribution, **kw) -> None:
176178
@overload
177179
def reinitialize_command(
178180
self, command: str, reinit_subcommands: bool = False, **kw
179-
) -> _Command: ...
181+
) -> Command: ... # override distutils.cmd.Command with setuptools.Command
180182
@overload
181183
def reinitialize_command(
182184
self, command: _CommandT, reinit_subcommands: bool = False, **kw
183185
) -> _CommandT: ...
184186
def reinitialize_command(
185187
self, command: str | _Command, reinit_subcommands: bool = False, **kw
186-
) -> _Command:
188+
) -> Command | _Command:
187189
cmd = _Command.reinitialize_command(self, command, reinit_subcommands)
188190
vars(cmd).update(kw)
189191
return cmd # pyright: ignore[reportReturnType] # pypa/distutils#307

setuptools/build_meta.py

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
import warnings
4040
from collections.abc import Iterable, Iterator, Mapping
4141
from pathlib import Path
42-
from typing import TYPE_CHECKING, Union
42+
from typing import TYPE_CHECKING, NoReturn, Union
4343

4444
import setuptools
4545

@@ -74,14 +74,14 @@ def __init__(self, specifiers) -> None:
7474

7575

7676
class Distribution(setuptools.dist.Distribution):
77-
def fetch_build_eggs(self, specifiers):
77+
def fetch_build_eggs(self, specifiers) -> NoReturn:
7878
specifier_list = list(parse_strings(specifiers))
7979

8080
raise SetupRequirementsError(specifier_list)
8181

8282
@classmethod
8383
@contextlib.contextmanager
84-
def patch(cls):
84+
def patch(cls) -> Iterator[None]:
8585
"""
8686
Replace
8787
distutils.dist.Distribution with this class
@@ -304,7 +304,7 @@ def _get_build_requires(
304304

305305
return requirements
306306

307-
def run_setup(self, setup_script: str = 'setup.py'):
307+
def run_setup(self, setup_script: str = 'setup.py') -> None:
308308
# Note that we can reuse our build directory between calls
309309
# Correctness comes first, then optimization later
310310
__file__ = os.path.abspath(setup_script)
@@ -327,10 +327,14 @@ def run_setup(self, setup_script: str = 'setup.py'):
327327
"setup-py-deprecated.html",
328328
)
329329

330-
def get_requires_for_build_wheel(self, config_settings: _ConfigSettings = None):
330+
def get_requires_for_build_wheel(
331+
self, config_settings: _ConfigSettings = None
332+
) -> list[str]:
331333
return self._get_build_requires(config_settings, requirements=[])
332334

333-
def get_requires_for_build_sdist(self, config_settings: _ConfigSettings = None):
335+
def get_requires_for_build_sdist(
336+
self, config_settings: _ConfigSettings = None
337+
) -> list[str]:
334338
return self._get_build_requires(config_settings, requirements=[])
335339

336340
def _bubble_up_info_directory(
@@ -361,7 +365,7 @@ def _find_info_directory(self, metadata_directory: StrPath, suffix: str) -> Path
361365

362366
def prepare_metadata_for_build_wheel(
363367
self, metadata_directory: StrPath, config_settings: _ConfigSettings = None
364-
):
368+
) -> str:
365369
sys.argv = [
366370
*sys.argv[:1],
367371
*self._global_args(config_settings),
@@ -417,7 +421,7 @@ def build_wheel(
417421
wheel_directory: StrPath,
418422
config_settings: _ConfigSettings = None,
419423
metadata_directory: StrPath | None = None,
420-
):
424+
) -> str:
421425
def _build(cmd: list[str]):
422426
with suppress_known_deprecation():
423427
return self._build_with_temp_dir(
@@ -442,7 +446,7 @@ def _build(cmd: list[str]):
442446

443447
def build_sdist(
444448
self, sdist_directory: StrPath, config_settings: _ConfigSettings = None
445-
):
449+
) -> str:
446450
return self._build_with_temp_dir(
447451
['sdist', '--formats', 'gztar'], '.tar.gz', sdist_directory, config_settings
448452
)
@@ -459,7 +463,7 @@ def build_editable(
459463
wheel_directory: StrPath,
460464
config_settings: _ConfigSettings = None,
461465
metadata_directory: StrPath | None = None,
462-
):
466+
) -> str:
463467
# XXX can or should we hide our editable_wheel command normally?
464468
info_dir = self._get_dist_info_dir(metadata_directory)
465469
opts = ["--dist-info-dir", info_dir] if info_dir else []
@@ -469,12 +473,14 @@ def build_editable(
469473
cmd, ".whl", wheel_directory, config_settings
470474
)
471475

472-
def get_requires_for_build_editable(self, config_settings: _ConfigSettings = None):
476+
def get_requires_for_build_editable(
477+
self, config_settings: _ConfigSettings = None
478+
) -> list[str]:
473479
return self.get_requires_for_build_wheel(config_settings)
474480

475481
def prepare_metadata_for_build_editable(
476482
self, metadata_directory: StrPath, config_settings: _ConfigSettings = None
477-
):
483+
) -> str:
478484
return self.prepare_metadata_for_build_wheel(
479485
metadata_directory, config_settings
480486
)
@@ -492,7 +498,7 @@ class _BuildMetaLegacyBackend(_BuildMetaBackend):
492498
and will eventually be removed.
493499
"""
494500

495-
def run_setup(self, setup_script: str = 'setup.py'):
501+
def run_setup(self, setup_script: str = 'setup.py') -> None:
496502
# In order to maintain compatibility with scripts assuming that
497503
# the setup.py script is in a directory on the PYTHONPATH, inject
498504
# '' into sys.path. (pypa/setuptools#1642)

setuptools/command/bdist_egg.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,21 @@
99
import re
1010
import sys
1111
import textwrap
12+
from collections.abc import Iterator
1213
from sysconfig import get_path, get_platform, get_python_version
1314
from types import CodeType
14-
from typing import TYPE_CHECKING, Literal
15+
from typing import TYPE_CHECKING, AnyStr, Literal
1516

1617
from setuptools import Command
1718
from setuptools.extension import Library
1819

19-
from .._path import StrPathT, ensure_directory
20+
from .._path import StrPath, StrPathT, ensure_directory
2021

2122
from distutils import log
2223
from distutils.dir_util import mkpath, remove_tree
2324

2425
if TYPE_CHECKING:
26+
from _typeshed import GenericPath
2527
from typing_extensions import TypeAlias
2628

2729
# Same as zipfile._ZipFileMode from typeshed
@@ -40,7 +42,9 @@ def strip_module(filename):
4042
return filename
4143

4244

43-
def sorted_walk(dir):
45+
def sorted_walk(
46+
dir: GenericPath[AnyStr],
47+
) -> Iterator[tuple[AnyStr, list[AnyStr], list[AnyStr]]]:
4448
"""Do os.walk in a reproducible way,
4549
independent of indeterministic filesystem readdir order
4650
"""
@@ -161,7 +165,7 @@ def call_command(self, cmdname, **kw):
161165
self.run_command(cmdname)
162166
return cmd
163167

164-
def run(self): # noqa: C901 # is too complex (14) # FIXME
168+
def run(self) -> None: # noqa: C901 # is too complex (14) # FIXME
165169
# Generate metadata first
166170
self.run_command("egg_info")
167171
# We run install_lib before install_data, because some data hacks
@@ -232,7 +236,7 @@ def run(self): # noqa: C901 # is too complex (14) # FIXME
232236
self.egg_output,
233237
archive_root,
234238
verbose=self.verbose,
235-
dry_run=self.dry_run,
239+
dry_run=self.dry_run, # type: ignore[arg-type] # Is an actual boolean in vendored _distutils
236240
mode=self.gen_header(),
237241
)
238242
if not self.keep_temp:
@@ -245,7 +249,7 @@ def run(self): # noqa: C901 # is too complex (14) # FIXME
245249
self.egg_output,
246250
))
247251

248-
def zap_pyfiles(self):
252+
def zap_pyfiles(self) -> None:
249253
log.info("Removing .py files from temporary directory")
250254
for base, dirs, files in walk_egg(self.bdist_dir):
251255
for name in files:
@@ -260,6 +264,8 @@ def zap_pyfiles(self):
260264

261265
pattern = r'(?P<name>.+)\.(?P<magic>[^.]+)\.pyc'
262266
m = re.match(pattern, name)
267+
# We shouldn't find any non-pyc files in __pycache__
268+
assert m is not None
263269
path_new = os.path.join(base, os.pardir, m.group('name') + '.pyc')
264270
log.info(f"Renaming file from [{path_old}] to [{path_new}]")
265271
try:
@@ -323,7 +329,7 @@ def get_ext_outputs(self):
323329
NATIVE_EXTENSIONS: dict[str, None] = dict.fromkeys('.dll .so .dylib .pyd'.split())
324330

325331

326-
def walk_egg(egg_dir):
332+
def walk_egg(egg_dir: StrPath) -> Iterator[tuple[str, list[str], list[str]]]:
327333
"""Walk an unpacked egg's contents, skipping the metadata directory"""
328334
walker = sorted_walk(egg_dir)
329335
base, dirs, files = next(walker)
@@ -409,7 +415,7 @@ def scan_module(egg_dir, base, name, stubs):
409415
return safe
410416

411417

412-
def iter_symbols(code):
418+
def iter_symbols(code: CodeType) -> Iterator[str]:
413419
"""Yield names and strings used by `code` and its nested code objects"""
414420
yield from code.co_names
415421
for const in code.co_consts:

setuptools/command/build_ext.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ class build_ext(_build_ext):
9090
editable_mode = False
9191
inplace = False
9292

93-
def run(self):
93+
def run(self) -> None:
9494
"""Build extensions in build directory, then copy if --inplace"""
9595
old_inplace, self.inplace = self.inplace, False
9696
_build_ext.run(self)
@@ -220,7 +220,7 @@ def finalize_options(self) -> None:
220220
if self.editable_mode:
221221
self.inplace = True
222222

223-
def setup_shlib_compiler(self):
223+
def setup_shlib_compiler(self) -> None:
224224
compiler = self.shlib_compiler = new_compiler(
225225
compiler=self.compiler, dry_run=self.dry_run, force=self.force
226226
)

setuptools/command/build_py.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class build_py(orig.build_py):
4141
editable_mode: bool = False
4242
existing_egg_info_dir: StrPath | None = None #: Private API, internal use only.
4343

44-
def finalize_options(self):
44+
def finalize_options(self) -> None:
4545
orig.build_py.finalize_options(self)
4646
self.package_data = self.distribution.package_data
4747
self.exclude_package_data = self.distribution.exclude_package_data or {}
@@ -93,7 +93,7 @@ def _get_data_files(self):
9393
self.analyze_manifest()
9494
return list(map(self._get_pkg_data_files, self.packages or ()))
9595

96-
def get_data_files_without_manifest(self):
96+
def get_data_files_without_manifest(self) -> list[tuple[str, str, str, list[str]]]:
9797
"""
9898
Generate list of ``(package,src_dir,build_dir,filenames)`` tuples,
9999
but without triggering any attempt to analyze or build the manifest.
@@ -103,7 +103,7 @@ def get_data_files_without_manifest(self):
103103
self.__dict__.setdefault('manifest_files', {})
104104
return list(map(self._get_pkg_data_files, self.packages or ()))
105105

106-
def _get_pkg_data_files(self, package):
106+
def _get_pkg_data_files(self, package: str) -> tuple[str, str, str, list[str]]:
107107
# Locate package source directory
108108
src_dir = self.get_package_dir(package)
109109

@@ -272,7 +272,7 @@ def initialize_options(self):
272272
self.editable_mode = False
273273
self.existing_egg_info_dir = None
274274

275-
def get_package_dir(self, package):
275+
def get_package_dir(self, package: str) -> str:
276276
res = orig.build_py.get_package_dir(self, package)
277277
if self.distribution.src_root is not None:
278278
return os.path.join(self.distribution.src_root, res)

setuptools/command/develop.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import site
22
import subprocess
33
import sys
4+
from typing import cast
45

56
from setuptools import Command
67
from setuptools.warnings import SetuptoolsDeprecationWarning
@@ -27,18 +28,20 @@ class develop(Command):
2728
prefix = None
2829
index_url = None
2930

30-
def run(self):
31-
cmd = (
31+
def run(self) -> None:
32+
# Casting because mypy doesn't understand bool mult conditionals
33+
cmd = cast(
34+
list[str],
3235
[sys.executable, '-m', 'pip', 'install', '-e', '.', '--use-pep517']
3336
+ ['--target', self.install_dir] * bool(self.install_dir)
3437
+ ['--no-deps'] * self.no_deps
3538
+ ['--user'] * self.user
3639
+ ['--prefix', self.prefix] * bool(self.prefix)
37-
+ ['--index-url', self.index_url] * bool(self.index_url)
40+
+ ['--index-url', self.index_url] * bool(self.index_url),
3841
)
3942
subprocess.check_call(cmd)
4043

41-
def initialize_options(self):
44+
def initialize_options(self) -> None:
4245
DevelopDeprecationWarning.emit()
4346

4447
def finalize_options(self) -> None:

setuptools/command/egg_info.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
33
Create a distribution's .egg-info directory and contents"""
44

5+
from __future__ import annotations
6+
57
import functools
68
import os
79
import re
@@ -196,11 +198,11 @@ def initialize_options(self):
196198
# allow the 'tag_svn_revision' to be detected and
197199
# set, supporting sdists built on older Setuptools.
198200
@property
199-
def tag_svn_revision(self) -> None:
201+
def tag_svn_revision(self) -> int | None:
200202
pass
201203

202204
@tag_svn_revision.setter
203-
def tag_svn_revision(self, value):
205+
def tag_svn_revision(self, value) -> None:
204206
pass
205207

206208
####################################

setuptools/command/sdist.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import contextlib
44
import os
55
import re
6+
from collections.abc import Iterator
67
from itertools import chain
78
from typing import ClassVar
89

@@ -16,7 +17,7 @@
1617
_default_revctrl = list
1718

1819

19-
def walk_revctrl(dirname=''):
20+
def walk_revctrl(dirname='') -> Iterator:
2021
"""Find all files under revision control"""
2122
for ep in metadata.entry_points(group='setuptools.file_finders'):
2223
yield from ep.load()(dirname)
@@ -195,7 +196,7 @@ def _manifest_is_not_generated(self):
195196
first_line = fp.readline()
196197
return first_line != b'# file GENERATED by distutils, do NOT edit\n'
197198

198-
def read_manifest(self):
199+
def read_manifest(self) -> None:
199200
"""Read the manifest file (named by 'self.manifest') and use it to
200201
fill in 'self.filelist', the list of files to include in the source
201202
distribution.

setuptools/command/setopt.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def config_file(kind="local"):
2727
raise ValueError("config_file() type must be 'local', 'global', or 'user'", kind)
2828

2929

30-
def edit_config(filename, settings, dry_run=False):
30+
def edit_config(filename, settings, dry_run=False) -> None:
3131
"""Edit a configuration file to include `settings`
3232
3333
`settings` is a dictionary of dictionaries or ``None`` values, keyed by
@@ -88,7 +88,7 @@ def initialize_options(self):
8888
self.user_config = None
8989
self.filename = None
9090

91-
def finalize_options(self):
91+
def finalize_options(self) -> None:
9292
filenames = []
9393
if self.global_config:
9494
filenames.append(config_file('global'))

0 commit comments

Comments
 (0)