Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge typeshed return annotations #4744

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from
9 changes: 5 additions & 4 deletions setuptools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,12 @@ def _fetch_build_eggs(dist: Distribution):
raise


def setup(**attrs):
def setup(**attrs) -> Distribution:
logging.configure()
# Make sure we have any requirements needed to interpret 'attrs'.
_install_setup_requires(attrs)
return distutils.core.setup(**attrs)
# Override return type of distutils.core.Distribution with setuptools.dist.Distribution
return distutils.core.setup(**attrs) # type: ignore[return-value]


setup.__doc__ = distutils.core.setup.__doc__
Expand Down Expand Up @@ -216,14 +217,14 @@ def ensure_string_list(self, option: str) -> None:
@overload
def reinitialize_command(
self, command: str, reinit_subcommands: bool = False, **kw
) -> _Command: ...
) -> Command: ... # override distutils.cmd.Command with setuptools.Command
@overload
def reinitialize_command(
self, command: _CommandT, reinit_subcommands: bool = False, **kw
) -> _CommandT: ...
def reinitialize_command(
self, command: str | _Command, reinit_subcommands: bool = False, **kw
) -> _Command:
) -> Command | _Command:
cmd = _Command.reinitialize_command(self, command, reinit_subcommands)
vars(cmd).update(kw)
return cmd # pyright: ignore[reportReturnType] # pypa/distutils#307
Expand Down
30 changes: 17 additions & 13 deletions setuptools/build_meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
import warnings
from collections.abc import Iterable, Iterator, Mapping
from pathlib import Path
from typing import TYPE_CHECKING, Union
from typing import TYPE_CHECKING, NoReturn, Union

import setuptools

Expand Down Expand Up @@ -77,14 +77,14 @@ def __init__(self, specifiers) -> None:


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

raise SetupRequirementsError(specifier_list)

@classmethod
@contextlib.contextmanager
def patch(cls):
def patch(cls) -> Iterator[None]:
"""
Replace
distutils.dist.Distribution with this class
Expand Down Expand Up @@ -307,7 +307,7 @@ def _get_build_requires(

return requirements

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

def get_requires_for_build_wheel(self, config_settings: _ConfigSettings = None):
def get_requires_for_build_wheel(
self, config_settings: _ConfigSettings = None
) -> list[str]:
return self._get_build_requires(config_settings, requirements=[])

def get_requires_for_build_sdist(self, config_settings: _ConfigSettings = None):
def get_requires_for_build_sdist(
self, config_settings: _ConfigSettings = None
) -> list[str]:
return self._get_build_requires(config_settings, requirements=[])

def _bubble_up_info_directory(
Expand Down Expand Up @@ -364,7 +368,7 @@ def _find_info_directory(self, metadata_directory: StrPath, suffix: str) -> Path

def prepare_metadata_for_build_wheel(
self, metadata_directory: StrPath, config_settings: _ConfigSettings = None
):
) -> str:
sys.argv = [
*sys.argv[:1],
*self._global_args(config_settings),
Expand Down Expand Up @@ -420,7 +424,7 @@ def build_wheel(
wheel_directory: StrPath,
config_settings: _ConfigSettings = None,
metadata_directory: StrPath | None = None,
):
) -> str:
def _build(cmd: list[str]):
with suppress_known_deprecation():
return self._build_with_temp_dir(
Expand All @@ -445,7 +449,7 @@ def _build(cmd: list[str]):

def build_sdist(
self, sdist_directory: StrPath, config_settings: _ConfigSettings = None
):
) -> str:
return self._build_with_temp_dir(
['sdist', '--formats', 'gztar'], '.tar.gz', sdist_directory, config_settings
)
Expand All @@ -467,7 +471,7 @@ def build_editable(
wheel_directory: StrPath,
config_settings: _ConfigSettings = None,
metadata_directory: StrPath | None = None,
):
) -> str:
# XXX can or should we hide our editable_wheel command normally?
info_dir = self._get_dist_info_dir(metadata_directory)
opts = ["--dist-info-dir", info_dir] if info_dir else []
Expand All @@ -479,12 +483,12 @@ def build_editable(

def get_requires_for_build_editable(
self, config_settings: _ConfigSettings = None
):
) -> list[str]:
return self.get_requires_for_build_wheel(config_settings)

def prepare_metadata_for_build_editable(
self, metadata_directory: StrPath, config_settings: _ConfigSettings = None
):
) -> str:
return self.prepare_metadata_for_build_wheel(
metadata_directory, config_settings
)
Expand All @@ -502,7 +506,7 @@ class _BuildMetaLegacyBackend(_BuildMetaBackend):
and will eventually be removed.
"""

def run_setup(self, setup_script: str = 'setup.py'):
def run_setup(self, setup_script: str = 'setup.py') -> None:
# In order to maintain compatibility with scripts assuming that
# the setup.py script is in a directory on the PYTHONPATH, inject
# '' into sys.path. (pypa/setuptools#1642)
Expand Down
22 changes: 14 additions & 8 deletions setuptools/command/bdist_egg.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,21 @@
import re
import sys
import textwrap
from collections.abc import Iterator
from sysconfig import get_path, get_python_version
from types import CodeType
from typing import TYPE_CHECKING, Literal
from typing import TYPE_CHECKING, AnyStr, Literal

from setuptools import Command
from setuptools.extension import Library

from .._path import StrPathT, ensure_directory
from .._path import StrPath, StrPathT, ensure_directory

from distutils import log
from distutils.dir_util import mkpath, remove_tree

if TYPE_CHECKING:
from _typeshed import GenericPath
from typing_extensions import TypeAlias

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


def sorted_walk(dir):
def sorted_walk(
dir: GenericPath[AnyStr],
) -> Iterator[tuple[AnyStr, list[AnyStr], list[AnyStr]]]:
"""Do os.walk in a reproducible way,
independent of indeterministic filesystem readdir order
"""
Expand Down Expand Up @@ -163,7 +167,7 @@ def call_command(self, cmdname, **kw):
self.run_command(cmdname)
return cmd

def run(self): # noqa: C901 # is too complex (14) # FIXME
def run(self) -> None: # noqa: C901 # is too complex (14) # FIXME
# Generate metadata first
self.run_command("egg_info")
# We run install_lib before install_data, because some data hacks
Expand Down Expand Up @@ -234,7 +238,7 @@ def run(self): # noqa: C901 # is too complex (14) # FIXME
self.egg_output,
archive_root,
verbose=self.verbose,
dry_run=self.dry_run,
dry_run=self.dry_run, # type: ignore[arg-type] # Is an actual boolean in vendored _distutils
mode=self.gen_header(),
)
if not self.keep_temp:
Expand All @@ -247,7 +251,7 @@ def run(self): # noqa: C901 # is too complex (14) # FIXME
self.egg_output,
))

def zap_pyfiles(self):
def zap_pyfiles(self) -> None:
log.info("Removing .py files from temporary directory")
for base, dirs, files in walk_egg(self.bdist_dir):
for name in files:
Expand All @@ -262,6 +266,8 @@ def zap_pyfiles(self):

pattern = r'(?P<name>.+)\.(?P<magic>[^.]+)\.pyc'
m = re.match(pattern, name)
# We shouldn't find any non-pyc files in __pycache__
assert m is not None
Comment on lines +269 to +270
Copy link
Contributor Author

@Avasam Avasam Nov 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not strictly an annotation change, but I included it here because it didn't feel worth doing a PR just for this
Would've been included in #4753 if I realised sooner this was an easy fix

path_new = os.path.join(base, os.pardir, m.group('name') + '.pyc')
log.info("Renaming file from [%s] to [%s]" % (path_old, path_new))
try:
Expand Down Expand Up @@ -325,7 +331,7 @@ def get_ext_outputs(self):
NATIVE_EXTENSIONS: dict[str, None] = dict.fromkeys('.dll .so .dylib .pyd'.split())


def walk_egg(egg_dir):
def walk_egg(egg_dir: StrPath) -> Iterator[tuple[str, list[str], list[str]]]:
"""Walk an unpacked egg's contents, skipping the metadata directory"""
walker = sorted_walk(egg_dir)
base, dirs, files = next(walker)
Expand Down Expand Up @@ -411,7 +417,7 @@ def scan_module(egg_dir, base, name, stubs):
return safe


def iter_symbols(code):
def iter_symbols(code: CodeType) -> Iterator[str]:
"""Yield names and strings used by `code` and its nested code objects"""
yield from code.co_names
for const in code.co_consts:
Expand Down
4 changes: 2 additions & 2 deletions setuptools/command/build_ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ class build_ext(_build_ext):
editable_mode = False
inplace = False

def run(self):
def run(self) -> None:
"""Build extensions in build directory, then copy if --inplace"""
old_inplace, self.inplace = self.inplace, False
_build_ext.run(self)
Expand Down Expand Up @@ -223,7 +223,7 @@ def finalize_options(self) -> None:
if self.editable_mode:
self.inplace = True

def setup_shlib_compiler(self):
def setup_shlib_compiler(self) -> None:
compiler = self.shlib_compiler = new_compiler(
compiler=self.compiler, dry_run=self.dry_run, force=self.force
)
Expand Down
8 changes: 4 additions & 4 deletions setuptools/command/build_py.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class build_py(orig.build_py):
editable_mode: bool = False
existing_egg_info_dir: StrPath | None = None #: Private API, internal use only.

def finalize_options(self):
def finalize_options(self) -> None:
orig.build_py.finalize_options(self)
self.package_data = self.distribution.package_data
self.exclude_package_data = self.distribution.exclude_package_data or {}
Expand Down Expand Up @@ -93,7 +93,7 @@ def _get_data_files(self):
self.analyze_manifest()
return list(map(self._get_pkg_data_files, self.packages or ()))

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

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

Expand Down Expand Up @@ -272,7 +272,7 @@ def initialize_options(self):
self.editable_mode = False
self.existing_egg_info_dir = None

def get_package_dir(self, package):
def get_package_dir(self, package: str) -> str:
res = orig.build_py.get_package_dir(self, package)
if self.distribution.src_root is not None:
return os.path.join(self.distribution.src_root, res)
Expand Down
2 changes: 1 addition & 1 deletion setuptools/command/develop.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class develop(namespaces.DevelopInstaller, easy_install):

command_consumes_arguments = False # override base

def run(self):
def run(self) -> None: # type: ignore[override] # Not including easy_install's show_deprecation argument
if self.uninstall:
self.multi_version = True
self.uninstall_link()
Expand Down
7 changes: 5 additions & 2 deletions setuptools/command/easy_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -747,12 +747,15 @@ def install_item(
return dist
return None

def select_scheme(self, name):
def select_scheme(self, name) -> None:
try:
install._select_scheme(self, name)
except AttributeError:
# stdlib distutils
install.install.select_scheme(self, name.replace('posix', 'unix'))
install.install.select_scheme(
self, # type: ignore[arg-type] # Pretend it's the correct type for stdlib compatibility
name.replace('posix', 'unix'),
)

# FIXME: 'easy_install.process_distribution' is too complex (12)
def process_distribution( # noqa: C901
Expand Down
6 changes: 4 additions & 2 deletions setuptools/command/egg_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

Create a distribution's .egg-info directory and contents"""

from __future__ import annotations

import functools
import os
import re
Expand Down Expand Up @@ -196,11 +198,11 @@ def initialize_options(self):
# allow the 'tag_svn_revision' to be detected and
# set, supporting sdists built on older Setuptools.
@property
def tag_svn_revision(self) -> None:
def tag_svn_revision(self) -> int | None:
pass

@tag_svn_revision.setter
def tag_svn_revision(self, value):
def tag_svn_revision(self, value) -> None:
pass

####################################
Expand Down
5 changes: 3 additions & 2 deletions setuptools/command/sdist.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import contextlib
import os
import re
from collections.abc import Iterator
from itertools import chain
from typing import ClassVar

Expand All @@ -16,7 +17,7 @@
_default_revctrl = list


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

def read_manifest(self):
def read_manifest(self) -> None:
"""Read the manifest file (named by 'self.manifest') and use it to
fill in 'self.filelist', the list of files to include in the source
distribution.
Expand Down
4 changes: 2 additions & 2 deletions setuptools/command/setopt.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def config_file(kind="local"):
raise ValueError("config_file() type must be 'local', 'global', or 'user'", kind)


def edit_config(filename, settings, dry_run=False):
def edit_config(filename, settings, dry_run=False) -> None:
"""Edit a configuration file to include `settings`

`settings` is a dictionary of dictionaries or ``None`` values, keyed by
Expand Down Expand Up @@ -88,7 +88,7 @@ def initialize_options(self):
self.user_config = None
self.filename = None

def finalize_options(self):
def finalize_options(self) -> None:
filenames = []
if self.global_config:
filenames.append(config_file('global'))
Expand Down
Loading
Loading