Skip to content

Commit

Permalink
Config changes to use our custom stubs
Browse files Browse the repository at this point in the history
  • Loading branch information
Avasam committed Nov 20, 2024
1 parent a06b7a9 commit 662d663
Show file tree
Hide file tree
Showing 18 changed files with 41 additions and 45 deletions.
14 changes: 5 additions & 9 deletions mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
strict = False

# Early opt-in even when strict = False
# warn_unused_ignores = True # Disabled until we have distutils stubs for Python 3.12+
warn_unused_ignores = True
warn_redundant_casts = True
enable_error_code = ignore-without-code

Expand All @@ -18,6 +18,9 @@ disable_error_code =

## local

# Use our custom stubs for distutils
mypy_path = $MYPY_CONFIG_FILE_DIR/typings

# CI should test for all versions, local development gets hints for oldest supported
# But our testing setup doesn't allow passing CLI arguments, so local devs have to set this manually.
# python_version = 3.9
Expand Down Expand Up @@ -48,17 +51,10 @@ disable_error_code =
[mypy-pkg_resources.tests.*]
disable_error_code = import-not-found

# - distutils doesn't exist on Python 3.12, unfortunately, this means typing
# will be missing for subclasses of distutils on Python 3.12 until either:
# - support for `SETUPTOOLS_USE_DISTUTILS=stdlib` is dropped (#3625)
# for setuptools to import `_distutils` directly
# - or non-stdlib distutils typings are exposed
[mypy-distutils.*]
ignore_missing_imports = True

# - wheel: does not intend on exposing a programmatic API https://github.com/pypa/wheel/pull/610#issuecomment-2081687671
[mypy-wheel.*]
ignore_missing_imports = True

# - The following are not marked as py.typed:
# - jaraco: Since mypy 1.12, the root name of the untyped namespace package gets called-out too
# - jaraco.develop: https://github.com/jaraco/jaraco.develop/issues/22
Expand Down
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ type = [

# local

# Referenced in distutils-stubs
"types-docutils",
# pin mypy version so a new version doesn't suddenly cause the CI to fail,
# until types-setuptools is removed from typeshed.
# For help with static-typing issues, or mypy update, ping @Avasam
Expand Down Expand Up @@ -202,6 +204,8 @@ include-package-data = true
include = [
"setuptools*",
"pkg_resources*",
# TODO: Include distutils stubs with package once we're confident in them
# "typings/distutils-stubs",
"_distutils_hack*",
]
exclude = [
Expand Down
2 changes: 2 additions & 0 deletions pyrightconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
],
// Our testing setup doesn't allow passing CLI arguments, so local devs have to set this manually.
// "pythonVersion": "3.9",
// Allow using distutils-stubs on Python 3.12+
"reportMissingModuleSource": false,
// For now we don't mind if mypy's `type: ignore` comments accidentally suppresses pyright issues
"enableTypeIgnoreComments": true,
"typeCheckingMode": "basic",
Expand Down
3 changes: 3 additions & 0 deletions ruff.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ ignore = [
# Only enforcing return type annotations for public functions
"ANN202", # missing-return-type-private-function
"ANN204", # missing-return-type-special-method
# Typeshed doesn't want complex or non-literal defaults for maintenance and testing reasons.
# This doesn't affect us, let's have more complete stubs.
"PYI011", # typed-argument-default-in-stub

# https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules
"W191",
Expand Down
5 changes: 0 additions & 5 deletions setuptools/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
"""Extensions to the 'distutils' for large or complex distributions"""
# mypy: disable_error_code=override
# Command.reinitialize_command has an extra **kw param that distutils doesn't have
# Can't disable on the exact line because distutils doesn't exists on Python 3.12
# and mypy isn't aware of distutils_hack, causing distutils.core.Command to be Any,
# and a [unused-ignore] to be raised on 3.12+

from __future__ import annotations

Expand Down
4 changes: 2 additions & 2 deletions setuptools/build_meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,11 @@ def patch(cls):
for the duration of this context.
"""
orig = distutils.core.Distribution
distutils.core.Distribution = cls # type: ignore[misc] # monkeypatching
distutils.core.Distribution = cls
try:
yield
finally:
distutils.core.Distribution = orig # type: ignore[misc] # monkeypatching
distutils.core.Distribution = orig


@contextlib.contextmanager
Expand Down
2 changes: 1 addition & 1 deletion setuptools/command/build_ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ def setup_shlib_compiler(self):
compiler.set_link_objects(self.link_objects)

# hack so distutils' build_extension() builds a library instead
compiler.link_shared_object = link_shared_object.__get__(compiler) # type: ignore[method-assign]
compiler.link_shared_object = link_shared_object.__get__(compiler)

def get_export_symbols(self, ext):
if isinstance(ext, Library):
Expand Down
4 changes: 2 additions & 2 deletions setuptools/command/build_py.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def finalize_options(self):
if 'data_files' in self.__dict__:
del self.__dict__['data_files']

def copy_file( # type: ignore[override] # No overload, no bytes support
def copy_file(
self,
infile: StrPath,
outfile: StrPathT,
Expand Down Expand Up @@ -135,7 +135,7 @@ def find_data_files(self, package, src_dir):
)
return self.exclude_data_files(package, src_dir, files)

def get_outputs(self, include_bytecode: bool = True) -> list[str]: # type: ignore[override] # Using a real boolean instead of 0|1
def get_outputs(self, include_bytecode: bool = True) -> list[str]:
"""See :class:`setuptools.commands.build.SubCommand`"""
if self.editable_mode:
return list(self.get_output_mapping().keys())
Expand Down
3 changes: 2 additions & 1 deletion setuptools/command/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,4 +180,5 @@ def do_egg_install(self) -> None:
# XXX Python 3.1 doesn't see _nc if this is inside the class
install.sub_commands = [
cmd for cmd in orig.install.sub_commands if cmd[0] not in install._nc
] + install.new_commands
] + install.new_commands # type: ignore[operator]
# TODO: Type sub_commands/new_commands to avoid variance issues in pypa/distutils (like python/typeshed#11951)
7 changes: 3 additions & 4 deletions setuptools/command/install_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,9 @@ def copy_tree(
self,
infile: StrPath,
outfile: str,
# override: Using actual booleans
preserve_mode: bool = True, # type: ignore[override]
preserve_times: bool = True, # type: ignore[override]
preserve_symlinks: bool = False, # type: ignore[override]
preserve_mode: bool = True,
preserve_times: bool = True,
preserve_symlinks: bool = False,
level: object = 1,
) -> list[str]:
assert preserve_mode
Expand Down
6 changes: 4 additions & 2 deletions setuptools/command/sdist.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,12 @@ class sdist(orig.sdist):
]

distribution: Distribution # override distutils.dist.Distribution with setuptools.dist.Distribution
negative_opt: ClassVar[dict[str, str]] = {}
# TODO: Mark class-level mutables as ClassVars in pypa/distutils (like python/typeshed#12403)
negative_opt: ClassVar[dict[str, str]] = {} # type: ignore[misc]

README_EXTENSIONS = ['', '.rst', '.txt', '.md']
READMES = tuple('README{0}'.format(ext) for ext in README_EXTENSIONS)
# TODO: Mark some class-level tuples as as not fixed-length pypa/distutils (like python/typeshed#12403)
READMES = tuple('README{0}'.format(ext) for ext in README_EXTENSIONS) # type: ignore[assignment]

def run(self) -> None:
self.run_command('egg_info')
Expand Down
2 changes: 1 addition & 1 deletion setuptools/command/setopt.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def edit_config(filename, settings, dry_run=False):
"""
log.debug("Reading configuration from %s", filename)
opts = configparser.RawConfigParser()
opts.optionxform = lambda optionstr: optionstr # type: ignore[method-assign] # overriding method
opts.optionxform = lambda optionstr: optionstr
_cfg_read_utf8_with_fallback(opts, filename)

for section, options in settings.items():
Expand Down
5 changes: 2 additions & 3 deletions setuptools/config/setupcfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from collections import defaultdict
from collections.abc import Iterable, Iterator
from functools import partial, wraps
from typing import TYPE_CHECKING, Any, Callable, ClassVar, Generic, TypeVar, cast
from typing import TYPE_CHECKING, Any, Callable, ClassVar, Generic, TypeVar

from packaging.markers import default_environment as marker_env
from packaging.requirements import InvalidRequirement, Requirement
Expand Down Expand Up @@ -101,8 +101,7 @@ def _apply(
filenames = [*other_files, filepath]

try:
# TODO: Temporary cast until mypy 1.12 is released with upstream fixes from typeshed
_Distribution.parse_config_files(dist, filenames=cast(list[str], filenames))
_Distribution.parse_config_files(dist, filenames=filenames)
handlers = parse_configuration(
dist, dist.command_options, ignore_option_errors=ignore_option_errors
)
Expand Down
2 changes: 1 addition & 1 deletion setuptools/dist.py
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,7 @@ def fetch_build_egg(self, req):

return fetch_build_egg(self, req)

def get_command_class(self, command: str) -> type[distutils.cmd.Command]: # type: ignore[override] # Not doing complex overrides yet
def get_command_class(self, command: str) -> type[distutils.cmd.Command]:
"""Pluggable version of get_command_class()"""
if command in self.cmdclass:
return self.cmdclass[command]
Expand Down
8 changes: 4 additions & 4 deletions setuptools/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@
BaseError = _distutils_errors.DistutilsError


class InvalidConfigError(OptionError): # type: ignore[valid-type, misc] # distutils imports are `Any` on python 3.12+
class InvalidConfigError(OptionError):
"""Error used for invalid configurations."""


class RemovedConfigError(OptionError): # type: ignore[valid-type, misc] # distutils imports are `Any` on python 3.12+
class RemovedConfigError(OptionError):
"""Error used for configurations that were deprecated and removed."""


class RemovedCommandError(BaseError, RuntimeError): # type: ignore[valid-type, misc] # distutils imports are `Any` on python 3.12+
class RemovedCommandError(BaseError, RuntimeError):
"""Error used for commands that have been removed in setuptools.
Since ``setuptools`` is built on ``distutils``, simply removing a command
Expand All @@ -48,7 +48,7 @@ class RemovedCommandError(BaseError, RuntimeError): # type: ignore[valid-type,
"""


class PackageDiscoveryError(BaseError, RuntimeError): # type: ignore[valid-type, misc] # distutils imports are `Any` on python 3.12+
class PackageDiscoveryError(BaseError, RuntimeError):
"""Impossible to perform automatic discovery of packages and/or modules.
The current project layout or given discovery options can lead to problems when
Expand Down
7 changes: 1 addition & 6 deletions setuptools/extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,12 +151,7 @@ def __init__(
# The *args is needed for compatibility as calls may use positional
# arguments. py_limited_api may be set only via keyword.
self.py_limited_api = py_limited_api
super().__init__(
name,
sources, # type: ignore[arg-type] # Vendored version of setuptools supports PathLike
*args,
**kw,
)
super().__init__(name, sources, *args, **kw)

def _convert_pyx_sources_to_lang(self):
"""
Expand Down
2 changes: 1 addition & 1 deletion setuptools/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def configure() -> None:
# and then loaded again when patched,
# implying: id(distutils.log) != id(distutils.dist.log).
# Make sure the same module object is used everywhere:
distutils.dist.log = distutils.log
distutils.dist.log = distutils.log # type: ignore[assignment]


def set_threshold(level: int) -> int:
Expand Down
6 changes: 3 additions & 3 deletions setuptools/monkey.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def patch_all():
import setuptools

# we can't patch distutils.cmd, alas
distutils.core.Command = setuptools.Command # type: ignore[misc,assignment] # monkeypatching
distutils.core.Command = setuptools.Command

_patch_distribution_metadata()

Expand All @@ -82,8 +82,8 @@ def patch_all():
module.Distribution = setuptools.dist.Distribution

# Install the patched Extension
distutils.core.Extension = setuptools.extension.Extension # type: ignore[misc,assignment] # monkeypatching
distutils.extension.Extension = setuptools.extension.Extension # type: ignore[misc,assignment] # monkeypatching
distutils.core.Extension = setuptools.extension.Extension
distutils.extension.Extension = setuptools.extension.Extension
if 'distutils.command.build_ext' in sys.modules:
sys.modules[
'distutils.command.build_ext'
Expand Down

0 comments on commit 662d663

Please sign in to comment.