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 simple type annotations from typeshed #4504

Merged
merged 18 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
14 changes: 8 additions & 6 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
# warn_unused_ignores = True # Disabled until we have distutils stubs for Python 3.12+
warn_redundant_casts = True
enable_error_code = ignore-without-code

Expand Down Expand Up @@ -34,12 +34,14 @@ exclude = (?x)(
# Duplicate module name
| ^pkg_resources/tests/data/my-test-package-source/setup.py$
)

# DistributionMetadata.license_files and DistributionMetadata.license_file
# are dynamically patched in setuptools/_core_metadata.py
# and no DistributionMetadata subclass exists in setuptools
[mypy-setuptools.*]
disable_error_code = attr-defined
disable_error_code =
# DistributionMetadata.license_files and DistributionMetadata.license_file
# are dynamically patched in setuptools/_core_metadata.py
# and no DistributionMetadata subclass exists in setuptools
attr-defined,
# See issue described below about distutils across Python versions
has-type,

# - pkg_resources tests create modules that won't exists statically before the test is run.
# Let's ignore all "import-not-found" since, if an import really wasn't found, then the test would fail.
Expand Down
2 changes: 2 additions & 0 deletions ruff.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ ignore = [
# Only enforcing return type annotations for public modules
"**/tests/**" = ["ANN2"]
"tools/**" = ["ANN2"]
# Temporarily disabling enforced return annotations for the setuptool package to progressively type from Typeshed
"setuptools/**" = ["ANN2"]
# Suppress nuisance warnings about module-import-not-at-top-of-file (E402) due to workaround for #4476
"setuptools/__init__.py" = ["E402"]
"pkg_resources/__init__.py" = ["E402"]
Expand Down
8 changes: 3 additions & 5 deletions setuptools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def finalize_options(self):
_fetch_build_eggs(dist)


def _fetch_build_eggs(dist):
def _fetch_build_eggs(dist: Distribution):
try:
dist.fetch_build_eggs(dist.setup_requires)
except Exception as ex:
Expand Down Expand Up @@ -120,10 +120,8 @@ def setup(**attrs):
setup.__doc__ = distutils.core.setup.__doc__

if TYPE_CHECKING:
from typing_extensions import TypeAlias

# Work around a mypy issue where type[T] can't be used as a base: https://github.com/python/mypy/issues/10962
_Command: TypeAlias = distutils.core.Command
from distutils.core import Command as _Command
else:
_Command = monkey.get_unpatched(distutils.core.Command)

Expand Down Expand Up @@ -188,7 +186,7 @@ def _ensure_stringlike(self, option, what, default=None):
)
return val

def ensure_string_list(self, option):
def ensure_string_list(self, option: str):
r"""Ensure that 'option' is a list of strings. If 'option' is
currently a string, we split it either on /,\s*/ or /\s+/, so
"foo bar baz", "foo,bar,baz", and "foo, bar baz" all become
Expand Down
6 changes: 2 additions & 4 deletions setuptools/_path.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,11 @@
import sys
from typing import TYPE_CHECKING, Union

if TYPE_CHECKING:
from typing_extensions import TypeAlias


from more_itertools import unique_everseen

if TYPE_CHECKING:
from typing_extensions import TypeAlias

StrPath: TypeAlias = Union[str, os.PathLike[str]] # Same as _typeshed.StrPath
else:
# Python 3.8 support
Expand Down
35 changes: 20 additions & 15 deletions setuptools/build_meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
import tokenize
import warnings
from pathlib import Path
from typing import TYPE_CHECKING, Dict, Iterable, Iterator, List, Union
from typing import TYPE_CHECKING, Iterable, Iterator, List, Mapping, Union

import setuptools

Expand All @@ -53,7 +53,6 @@
if TYPE_CHECKING:
from typing_extensions import TypeAlias


__all__ = [
'get_requires_for_build_sdist',
'get_requires_for_build_wheel',
Expand Down Expand Up @@ -147,7 +146,7 @@ def suppress_known_deprecation():
yield


_ConfigSettings: TypeAlias = Union[Dict[str, Union[str, List[str], None]], None]
_ConfigSettings: TypeAlias = Union[Mapping[str, Union[str, List[str], None]], None]
"""
Currently the user can run::

Expand Down Expand Up @@ -291,7 +290,9 @@ def _arbitrary_args(self, config_settings: _ConfigSettings) -> Iterator[str]:


class _BuildMetaBackend(_ConfigSettingsTranslator):
def _get_build_requires(self, config_settings, requirements):
def _get_build_requires(
self, config_settings: _ConfigSettings, requirements: list[str]
):
sys.argv = [
*sys.argv[:1],
*self._global_args(config_settings),
Expand All @@ -305,7 +306,7 @@ def _get_build_requires(self, config_settings, requirements):

return requirements

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

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

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

def _bubble_up_info_directory(self, metadata_directory: str, suffix: str) -> str:
def _bubble_up_info_directory(
self, metadata_directory: StrPath, suffix: str
) -> str:
"""
PEP 517 requires that the .dist-info directory be placed in the
metadata_directory. To comply, we MUST copy the directory to the root.
Expand All @@ -347,7 +350,7 @@ def _bubble_up_info_directory(self, metadata_directory: str, suffix: str) -> str
# PEP 517 allow other files and dirs to exist in metadata_directory
return info_dir.name

def _find_info_directory(self, metadata_directory: str, suffix: str) -> Path:
def _find_info_directory(self, metadata_directory: StrPath, suffix: str) -> Path:
for parent, dirs, _ in os.walk(metadata_directory):
candidates = [f for f in dirs if f.endswith(suffix)]

Expand All @@ -359,14 +362,14 @@ def _find_info_directory(self, metadata_directory: str, suffix: str) -> Path:
raise errors.InternalError(msg)

def prepare_metadata_for_build_wheel(
self, metadata_directory, config_settings=None
self, metadata_directory: StrPath, config_settings: _ConfigSettings = None
):
sys.argv = [
*sys.argv[:1],
*self._global_args(config_settings),
"dist_info",
"--output-dir",
metadata_directory,
str(metadata_directory),
"--keep-egg-info",
]
with no_install_setup_requires():
Expand Down Expand Up @@ -462,7 +465,7 @@ def build_editable(
self,
wheel_directory: StrPath,
config_settings: _ConfigSettings = None,
metadata_directory: str | None = None,
metadata_directory: StrPath | None = None,
):
# XXX can or should we hide our editable_wheel command normally?
info_dir = self._get_dist_info_dir(metadata_directory)
Expand All @@ -473,11 +476,13 @@ def build_editable(
cmd, ".whl", wheel_directory, config_settings
)

def get_requires_for_build_editable(self, config_settings=None):
def get_requires_for_build_editable(
self, config_settings: _ConfigSettings = None
):
return self.get_requires_for_build_wheel(config_settings)

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

def run_setup(self, setup_script='setup.py'):
def run_setup(self, setup_script: str = 'setup.py'):
# 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
16 changes: 15 additions & 1 deletion setuptools/command/bdist_egg.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@

Build .egg distributions"""

from __future__ import annotations

import marshal
import os
import re
import sys
import textwrap
from sysconfig import get_path, get_python_version
from types import CodeType
from typing import TYPE_CHECKING, Literal

from setuptools import Command
from setuptools.extension import Library
Expand All @@ -18,6 +21,12 @@
from distutils import log
from distutils.dir_util import mkpath, remove_tree

if TYPE_CHECKING:
from typing_extensions import TypeAlias

# Same as zipfile._ZipFileMode from typeshed
_ZipFileMode: TypeAlias = Literal["r", "w", "x", "a"]


def _get_purelib():
return get_path("purelib")
Expand Down Expand Up @@ -431,7 +440,12 @@ def can_scan():


def make_zipfile(
zip_filename, base_dir, verbose=False, dry_run=False, compress=True, mode='w'
zip_filename,
base_dir,
verbose: bool = False,
dry_run: bool = False,
compress=True,
mode: _ZipFileMode = 'w',
):
"""Create a zip file from all the files under 'base_dir'. The output
zip file will be named 'base_dir' + ".zip". Uses either the "zipfile"
Expand Down
6 changes: 3 additions & 3 deletions setuptools/command/bdist_wheel.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,9 +257,9 @@ def initialize_options(self) -> None:
self.relative = False
self.owner = None
self.group = None
self.universal: bool = False
self.compression: int | str = "deflated"
self.python_tag: str = python_tag()
self.universal = False
self.compression: str | int = "deflated"
self.python_tag = python_tag()
self.build_number: str | None = None
self.py_limited_api: str | Literal[False] = False
self.plat_name_supplied = False
Expand Down
8 changes: 4 additions & 4 deletions setuptools/command/build_ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ def get_abi3_suffix():

class build_ext(_build_ext):
distribution: Distribution # override distutils.dist.Distribution with setuptools.dist.Distribution
editable_mode: bool = False
inplace: bool = False
editable_mode = False
inplace = False

def run(self):
"""Build extensions in build directory, then copy if --inplace"""
Expand Down Expand Up @@ -410,7 +410,7 @@ def link_shared_object(
library_dirs=None,
runtime_library_dirs=None,
export_symbols=None,
debug=False,
debug: bool = False,
Avasam marked this conversation as resolved.
Show resolved Hide resolved
extra_preargs=None,
extra_postargs=None,
build_temp=None,
Expand Down Expand Up @@ -445,7 +445,7 @@ def link_shared_object(
library_dirs=None,
runtime_library_dirs=None,
export_symbols=None,
debug=False,
debug: bool = False,
extra_preargs=None,
extra_postargs=None,
build_temp=None,
Expand Down
18 changes: 10 additions & 8 deletions setuptools/command/build_py.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

from more_itertools import unique_everseen

from setuptools._path import StrPath

from ..dist import Distribution
from ..warnings import SetuptoolsDeprecationWarning

Expand Down Expand Up @@ -48,14 +50,14 @@ def finalize_options(self):
del self.__dict__['data_files']
self.__updated_files = []

def copy_file(
def copy_file( # type: ignore[override] # No overload, str support only
self,
infile,
outfile,
preserve_mode=True,
preserve_times=True,
link=None,
level=1,
infile: StrPath,
outfile: StrPath,
preserve_mode: bool = True,
preserve_times: bool = True,
link: str | None = None,
level: object = 1,
Copy link
Contributor

Choose a reason for hiding this comment

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

        level: object = 1,

This one looks odd, but I suppose that is because it assumes either int or boolean values elsewhere.

Copy link
Contributor Author

@Avasam Avasam Oct 25, 2024

Choose a reason for hiding this comment

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

object can be used to mean "any parameter type" for unused params, (Typeshed has the alias _typeshed.Unused), but that might lead to LSP violations since subclasses should now support any object.

I should maybe change it to int (Unless you tell me that subclasses of these classes should not support an "optimization level" a depth level on this method)
image
Edit: uh that probably represent a depth level, not optimization ^^" Anyway, it's currently unused all the way down to the base Command class in distutils.

Copy link
Contributor Author

@Avasam Avasam Oct 25, 2024

Choose a reason for hiding this comment

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

I'll need to go fix it in typeshed first (or #4689) I'll leave it "as-is" for this PR. You can squash-merge the whole thing once green.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thank you @Avasam, once the CI finishes running I will squash it.

):
# Overwrite base class to allow using links
if link:
Expand Down Expand Up @@ -141,7 +143,7 @@ def find_data_files(self, package, src_dir):
)
return self.exclude_data_files(package, src_dir, files)

def get_outputs(self, include_bytecode=True) -> list[str]:
def get_outputs(self, include_bytecode: bool = True) -> list[str]: # type: ignore[override] # Using a real boolean instead of 0|1
"""See :class:`setuptools.commands.build.SubCommand`"""
if self.editable_mode:
return list(self.get_output_mapping().keys())
Expand Down
Loading
Loading