Skip to content

Commit f160c70

Browse files
committed
Re-enable ANN2 for setuptools
1 parent c032a5b commit f160c70

20 files changed

+119
-78
lines changed

ruff.toml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,6 @@ ignore = [
5656
]
5757

5858
[lint.per-file-ignores]
59-
# Only enforcing return type annotations for public modules
60-
"**/tests/**" = ["ANN2"]
61-
"tools/**" = ["ANN2"]
62-
# Temporarily disabling enforced return annotations for the setuptool package to progressively type from Typeshed
63-
"setuptools/**" = ["ANN2"]
6459
# Suppress nuisance warnings about module-import-not-at-top-of-file (E402) due to workaround for #4476
6560
"setuptools/__init__.py" = ["E402"]
6661
"pkg_resources/__init__.py" = ["E402"]

setuptools/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ def _ensure_stringlike(self, option, what, default=None):
186186
)
187187
return val
188188

189-
def ensure_string_list(self, option: str):
189+
def ensure_string_list(self, option: str) -> None:
190190
r"""Ensure that 'option' is a list of strings. If 'option' is
191191
currently a string, we split it either on /,\s*/ or /\s+/, so
192192
"foo bar baz", "foo,bar,baz", and "foo, bar baz" all become
@@ -226,7 +226,7 @@ def reinitialize_command(
226226
) -> _Command:
227227
cmd = _Command.reinitialize_command(self, command, reinit_subcommands)
228228
vars(cmd).update(kw)
229-
return cmd
229+
return cmd # pyright: ignore[reportReturnType] # pypa/distutils#307
230230

231231
@abstractmethod
232232
def initialize_options(self) -> None:

setuptools/_path.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
import contextlib
44
import os
55
import sys
6-
from typing import TYPE_CHECKING, Union
6+
from typing import TYPE_CHECKING, TypeVar, Union
77

88
from more_itertools import unique_everseen
99

1010
if TYPE_CHECKING:
1111
from typing_extensions import TypeAlias
1212

13-
1413
StrPath: TypeAlias = Union[str, os.PathLike[str]] # Same as _typeshed.StrPath
14+
StrPathT = TypeVar("StrPathT", bound=Union[str, os.PathLike[str]])
1515

1616

1717
def ensure_directory(path):

setuptools/command/bdist_egg.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from setuptools import Command
1717
from setuptools.extension import Library
1818

19-
from .._path import ensure_directory
19+
from .._path import StrPathT, ensure_directory
2020

2121
from distutils import log
2222
from distutils.dir_util import mkpath, remove_tree
@@ -440,13 +440,13 @@ def can_scan():
440440

441441

442442
def make_zipfile(
443-
zip_filename,
443+
zip_filename: StrPathT,
444444
base_dir,
445445
verbose: bool = False,
446446
dry_run: bool = False,
447447
compress=True,
448448
mode: _ZipFileMode = 'w',
449-
):
449+
) -> StrPathT:
450450
"""Create a zip file from all the files under 'base_dir'. The output
451451
zip file will be named 'base_dir' + ".zip". Uses either the "zipfile"
452452
Python module (if available) or the InfoZIP "zip" utility (if installed
@@ -455,7 +455,7 @@ def make_zipfile(
455455
"""
456456
import zipfile
457457

458-
mkpath(os.path.dirname(zip_filename), dry_run=dry_run)
458+
mkpath(os.path.dirname(zip_filename), dry_run=dry_run) # type: ignore[arg-type] # python/mypy#18075
459459
log.info("creating '%s' and adding '%s' to it", zip_filename, base_dir)
460460

461461
def visit(z, dirname, names):

setuptools/command/build_ext.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,7 @@ def link_shared_object(
415415
extra_postargs=None,
416416
build_temp=None,
417417
target_lang=None,
418-
):
418+
) -> None:
419419
self.link(
420420
self.SHARED_LIBRARY,
421421
objects,
@@ -450,7 +450,7 @@ def link_shared_object(
450450
extra_postargs=None,
451451
build_temp=None,
452452
target_lang=None,
453-
):
453+
) -> None:
454454
# XXX we need to either disallow these attrs on Library instances,
455455
# or warn/abort here if set, or something...
456456
# libraries=None, library_dirs=None, runtime_library_dirs=None,

setuptools/command/build_py.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@
1212

1313
from more_itertools import unique_everseen
1414

15-
from setuptools._path import StrPath
16-
15+
from .._path import StrPath, StrPathT
1716
from ..dist import Distribution
1817
from ..warnings import SetuptoolsDeprecationWarning
1918

@@ -50,20 +49,20 @@ def finalize_options(self):
5049
del self.__dict__['data_files']
5150
self.__updated_files = []
5251

53-
def copy_file( # type: ignore[override] # No overload, str support only
52+
def copy_file( # type: ignore[override] # No overload, no bytes support
5453
self,
5554
infile: StrPath,
56-
outfile: StrPath,
55+
outfile: StrPathT,
5756
preserve_mode: bool = True,
5857
preserve_times: bool = True,
5958
link: str | None = None,
6059
level: object = 1,
61-
):
60+
) -> tuple[StrPathT | str, bool]:
6261
# Overwrite base class to allow using links
6362
if link:
6463
infile = str(Path(infile).resolve())
65-
outfile = str(Path(outfile).resolve())
66-
return super().copy_file(
64+
outfile = str(Path(outfile).resolve()) # type: ignore[assignment] # Re-assigning a str when outfile is StrPath is ok
65+
return super().copy_file( # pyright: ignore[reportReturnType] # pypa/distutils#309
6766
infile, outfile, preserve_mode, preserve_times, link, level
6867
)
6968

setuptools/command/easy_install.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@ def expand_dirs(self):
424424
]
425425
self._expand_attrs(dirs)
426426

427-
def run(self, show_deprecation: bool = True):
427+
def run(self, show_deprecation: bool = True) -> None:
428428
if show_deprecation:
429429
self.announce(
430430
"WARNING: The easy_install command is deprecated "
@@ -673,7 +673,7 @@ def _tmpdir(self):
673673
finally:
674674
os.path.exists(tmpdir) and _rmtree(tmpdir)
675675

676-
def easy_install(self, spec, deps: bool = False):
676+
def easy_install(self, spec, deps: bool = False) -> Distribution | None:
677677
with self._tmpdir() as tmpdir:
678678
if not isinstance(spec, Requirement):
679679
if URL_SCHEME(spec):
@@ -710,7 +710,9 @@ def easy_install(self, spec, deps: bool = False):
710710
else:
711711
return self.install_item(spec, dist.location, tmpdir, deps)
712712

713-
def install_item(self, spec, download, tmpdir, deps, install_needed: bool = False):
713+
def install_item(
714+
self, spec, download, tmpdir, deps, install_needed: bool = False
715+
) -> Distribution | None:
714716
# Installation is also needed if file in tmpdir or is not an egg
715717
install_needed = install_needed or bool(self.always_copy)
716718
install_needed = install_needed or os.path.dirname(download) == tmpdir
@@ -760,7 +762,7 @@ def process_distribution( # noqa: C901
760762
dist,
761763
deps: bool = True,
762764
*info,
763-
):
765+
) -> None:
764766
self.update_pth(dist)
765767
self.package_index.add(dist)
766768
if dist in self.local_index[dist.key]:
@@ -859,7 +861,7 @@ def _load_template(dev_path):
859861
raw_bytes = resource_string('setuptools', name)
860862
return raw_bytes.decode('utf-8')
861863

862-
def write_script(self, script_name, contents, mode: str = "t", blockers=()):
864+
def write_script(self, script_name, contents, mode: str = "t", blockers=()) -> None:
863865
"""Write an executable file to the scripts directory"""
864866
self.delete_blockers( # clean up old .py/.pyw w/o a script
865867
[os.path.join(self.script_dir, x) for x in blockers]
@@ -881,7 +883,7 @@ def write_script(self, script_name, contents, mode: str = "t", blockers=()):
881883
f.write(contents)
882884
chmod(target, 0o777 - mask)
883885

884-
def install_eggs(self, spec, dist_filename, tmpdir):
886+
def install_eggs(self, spec, dist_filename, tmpdir) -> list[Distribution]:
885887
# .egg dirs or files are already built, so just return them
886888
installer_map = {
887889
'.egg': self.install_egg,
@@ -1142,7 +1144,7 @@ def install_wheel(self, wheel_path, tmpdir):
11421144
"""
11431145
)
11441146

1145-
def installation_report(self, req, dist, what: str = "Installed"):
1147+
def installation_report(self, req, dist, what: str = "Installed") -> str:
11461148
"""Helpful installation message for display to package users"""
11471149
msg = "\n%(what)s %(eggloc)s%(extras)s"
11481150
if self.multi_version and not self.no_report:
@@ -2079,7 +2081,7 @@ def from_environment(cls):
20792081
return cls([cls._sys_executable()])
20802082

20812083
@classmethod
2082-
def from_string(cls, string: str):
2084+
def from_string(cls, string: str) -> Self:
20832085
"""
20842086
Construct a command spec from a simple string representing a command
20852087
line parseable by shlex.split.
@@ -2221,7 +2223,7 @@ def get_header(
22212223
cls,
22222224
script_text: str = "",
22232225
executable: str | CommandSpec | Iterable[str] | None = None,
2224-
):
2226+
) -> str:
22252227
"""Create a #! line, getting options (if any) from script_text"""
22262228
cmd = cls.command_spec_class.best().from_param(executable)
22272229
cmd.install_options(script_text)

setuptools/command/egg_info.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ def _get_egg_basename(self, py_version=PY_MAJOR, platform=None):
252252
"""Compute filename of the output egg. Private API."""
253253
return _egg_basename(self.egg_name, self.egg_version, py_version, platform)
254254

255-
def write_or_delete_file(self, what, filename, data, force: bool = False):
255+
def write_or_delete_file(self, what, filename, data, force: bool = False) -> None:
256256
"""Write `data` to `filename` or delete if empty
257257
258258
If `data` is non-empty, this routine is the same as ``write_file()``.
@@ -690,7 +690,7 @@ def overwrite_arg(cmd, basename, filename):
690690
write_arg(cmd, basename, filename, True)
691691

692692

693-
def write_arg(cmd, basename, filename, force: bool = False):
693+
def write_arg(cmd, basename, filename, force: bool = False) -> None:
694694
argname = os.path.splitext(basename)[0]
695695
value = getattr(cmd.distribution, argname, None)
696696
if value is not None:

setuptools/command/install_scripts.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def _install_ep_scripts(self):
5656
for args in writer.get_args(dist, cmd.as_header()):
5757
self.write_script(*args)
5858

59-
def write_script(self, script_name, contents, mode: str = "t", *ignored):
59+
def write_script(self, script_name, contents, mode: str = "t", *ignored) -> None:
6060
"""Write an executable file to the scripts directory"""
6161
from setuptools.command.easy_install import chmod, current_umask
6262

setuptools/depends.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@
44
import dis
55
import marshal
66
import sys
7+
from types import CodeType
8+
from typing import Any, Literal, TypeVar
79

810
from packaging.version import Version
911

1012
from . import _imp
1113
from ._imp import PY_COMPILED, PY_FROZEN, PY_SOURCE, find_module
1214

15+
_T = TypeVar("_T")
16+
1317
__all__ = ['Require', 'find_module']
1418

1519

@@ -51,7 +55,9 @@ def version_ok(self, version):
5155
and self.format(version) >= self.requested_version
5256
)
5357

54-
def get_version(self, paths=None, default: str = "unknown"):
58+
def get_version(
59+
self, paths=None, default: _T | Literal["unknown"] = "unknown"
60+
) -> _T | Literal["unknown"] | None | Any:
5561
"""Get version number of installed module, 'None', or 'default'
5662
5763
Search 'paths' for module. If not found, return 'None'. If found,
@@ -106,7 +112,9 @@ def empty():
106112
# XXX it'd be better to test assertions about bytecode instead.
107113
if not sys.platform.startswith('java') and sys.platform != 'cli':
108114

109-
def get_module_constant(module, symbol, default: str | int = -1, paths=None):
115+
def get_module_constant(
116+
module, symbol, default: _T | int = -1, paths=None
117+
) -> _T | int | None | Any:
110118
"""Find 'module' by searching 'paths', and extract 'symbol'
111119
112120
Return 'None' if 'module' does not exist on 'paths', or it does not define
@@ -134,7 +142,9 @@ def get_module_constant(module, symbol, default: str | int = -1, paths=None):
134142

135143
return extract_constant(code, symbol, default)
136144

137-
def extract_constant(code, symbol, default: str | int = -1):
145+
def extract_constant(
146+
code: CodeType, symbol: str, default: _T | int = -1
147+
) -> _T | int | None | Any:
138148
"""Extract the constant value of 'symbol' from 'code'
139149
140150
If the name 'symbol' is bound to a constant value by the Python code
@@ -163,6 +173,7 @@ def extract_constant(code, symbol, default: str | int = -1):
163173
arg = byte_code.arg
164174

165175
if op == LOAD_CONST:
176+
assert arg is not None
166177
const = code.co_consts[arg]
167178
elif arg == name_idx and (op == STORE_NAME or op == STORE_GLOBAL):
168179
return const

0 commit comments

Comments
 (0)