Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions setuptools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,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 @@ -176,14 +177,14 @@ def __init__(self, dist: Distribution, **kw) -> 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
32 changes: 19 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 @@ -74,14 +74,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 @@ -304,7 +304,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 @@ -327,10 +327,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 @@ -361,7 +365,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 @@ -417,7 +421,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 @@ -442,7 +446,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 @@ -459,7 +463,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 @@ -469,12 +473,14 @@ def build_editable(
cmd, ".whl", wheel_directory, config_settings
)

def get_requires_for_build_editable(self, config_settings: _ConfigSettings = None):
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 @@ -492,7 +498,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_platform, 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 @@ -161,7 +165,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 @@ -232,7 +236,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 @@ -245,7 +249,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 @@ -260,6 +264,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 +267 to +268
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(f"Renaming file from [{path_old}] to [{path_new}]")
try:
Expand Down Expand Up @@ -323,7 +329,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 @@ -409,7 +415,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 @@ -90,7 +90,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 @@ -220,7 +220,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
11 changes: 7 additions & 4 deletions setuptools/command/develop.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import site
import subprocess
import sys
from typing import cast

from setuptools import Command
from setuptools.warnings import SetuptoolsDeprecationWarning
Expand All @@ -27,18 +28,20 @@ class develop(Command):
prefix = None
index_url = None

def run(self):
cmd = (
def run(self) -> None: # type: ignore[override] # Not including easy_install's show_deprecation argument
Copy link
Contributor

Choose a reason for hiding this comment

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

I am trying to understand this comment.

Maybe it is also a left over from merge/rebase from a time that develop extended easy_install before the recent removal in #4955?

Copy link
Contributor Author

@Avasam Avasam May 28, 2025

Choose a reason for hiding this comment

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

Indeed, this type-ignore no longer applies. This used to break the Liskov Substitution Principle.
I think we're not currently checking for unused type-ignores because of some inconsistent error codes with Python 3.8 and/or distutils.

# Casting because mypy doesn't understand bool mult conditionals
cmd = cast(
list[str],
[sys.executable, '-m', 'pip', 'install', '-e', '.', '--use-pep517']
+ ['--target', self.install_dir] * bool(self.install_dir)
+ ['--no-deps'] * self.no_deps
+ ['--user'] * self.user
+ ['--prefix', self.prefix] * bool(self.prefix)
+ ['--index-url', self.index_url] * bool(self.index_url)
+ ['--index-url', self.index_url] * bool(self.index_url),
)
subprocess.check_call(cmd)

def initialize_options(self):
def initialize_options(self) -> None:
DevelopDeprecationWarning.emit()

def finalize_options(self) -> None:
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