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

Vendor distutils stubs #4691

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
10 changes: 4 additions & 6 deletions mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ disable_error_code =

## local

# Use our custom stubs for distutils
mypy_path = $MYPY_CONFIG_FILE_DIR/typings
Comment on lines +21 to +22
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I used pyright's default of typings so that I didn't have to configure it there. But that folder name can be arbitrary.


# 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.8
Expand Down Expand Up @@ -46,11 +49,6 @@ disable_error_code = attr-defined
[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
# - 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 All @@ -60,7 +58,7 @@ disable_error_code = import-not-found
# - jaraco.test: https://github.com/jaraco/jaraco.test/issues/7
# - jaraco.text: https://github.com/jaraco/jaraco.text/issues/17
# - wheel: does not intend on exposing a programmatic API https://github.com/pypa/wheel/pull/610#issuecomment-2081687671
[mypy-distutils.*,jaraco,jaraco.develop,jaraco.envs,jaraco.packaging.*,jaraco.path,jaraco.test.*,jaraco.text,wheel.*]
[mypy-jaraco,jaraco.develop,jaraco.envs,jaraco.packaging.*,jaraco.path,jaraco.test.*,jaraco.text,wheel.*]
ignore_missing_imports = True

# Even when excluding a module, import issues can show up due to following import
Expand Down
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,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 @@ -203,6 +205,8 @@ include-package-data = true
include = [
"setuptools*",
"pkg_resources*",
# TODO: Include distutils stubs with package once we're confident in them
# "typings/distutils-stubs",
Comment on lines +208 to +209
Copy link
Contributor Author

@Avasam Avasam Oct 17, 2024

Choose a reason for hiding this comment

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

We don't need to ship anything as long as typeshed provides stubs for setuptools/_distutils. We can synchronize once ready.
As I mentioned in the issue, there's also always the option to ship it as a different package (in which case it could live completely separately from setuptools and pypa/distutils)

"_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.8",
// 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 @@ -32,6 +32,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
7 changes: 1 addition & 6 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 Expand Up @@ -215,7 +210,7 @@ def ensure_string_list(self, option):
"'%s' must be a list of strings (got %r)" % (option, val)
)

@overload
@overload # type: ignore[override] # Has an extra **kw param that distutils doesn't have
def reinitialize_command(
self, command: str, reinit_subcommands: bool = False, **kw
) -> _Command: ...
Expand Down
1 change: 0 additions & 1 deletion setuptools/command/editable_wheel.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,6 @@ def _set_editable_mode(self):
"""Set the ``editable_mode`` flag in the build sub-commands"""
dist = self.distribution
build = dist.get_command_obj("build")
# TODO: Update typeshed distutils stubs to overload non-None return type by default
for cmd_name in build.get_sub_commands():
cmd = dist.get_command_obj(cmd_name)
if hasattr(cmd, "editable_mode"):
Expand Down
5 changes: 1 addition & 4 deletions setuptools/config/setupcfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,8 @@
Generic,
Iterable,
Iterator,
List,
Tuple,
TypeVar,
cast,
)

from packaging.markers import default_environment as marker_env
Expand Down Expand Up @@ -109,8 +107,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
Empty file.
25 changes: 25 additions & 0 deletions typings/distutils-stubs/_modified.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from collections.abc import Callable, Iterable
from typing import Literal, TypeVar

from _typeshed import StrOrBytesPath

_SourcesT = TypeVar("_SourcesT", bound=StrOrBytesPath)
_TargetsT = TypeVar("_TargetsT", bound=StrOrBytesPath)

def newer(source: StrOrBytesPath, target: StrOrBytesPath) -> bool: ...
def newer_pairwise(
sources: Iterable[_SourcesT],
targets: Iterable[_TargetsT],
newer: Callable[[_SourcesT, _TargetsT], bool] = newer,
) -> tuple[list[_SourcesT], list[_TargetsT]]: ...
def newer_group(
sources: Iterable[StrOrBytesPath],
target: StrOrBytesPath,
missing: Literal["error", "ignore", "newer"] = "error",
) -> bool: ...
def newer_pairwise_group(
sources: Iterable[_SourcesT],
targets: Iterable[_TargetsT],
*,
newer: Callable[[_SourcesT, _TargetsT], bool] = newer,
) -> tuple[list[_SourcesT], list[_TargetsT]]: ...
38 changes: 38 additions & 0 deletions typings/distutils-stubs/archive_util.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from typing import Literal, overload

from _typeshed import StrOrBytesPath, StrPath

@overload
def make_archive(
base_name: str,
format: str,
root_dir: StrOrBytesPath | None = None,
base_dir: str | None = None,
verbose: bool = False,
dry_run: bool = False,
owner: str | None = None,
group: str | None = None,
) -> str: ...
@overload
def make_archive(
base_name: StrPath,
format: str,
root_dir: StrOrBytesPath,
base_dir: str | None = None,
verbose: bool = False,
dry_run: bool = False,
owner: str | None = None,
group: str | None = None,
) -> str: ...
def make_tarball(
base_name: str,
base_dir: StrPath,
compress: Literal["gzip", "bzip2", "xz"] | None = "gzip",
verbose: bool = False,
dry_run: bool = False,
owner: str | None = None,
group: str | None = None,
) -> str: ...
def make_zipfile(
base_name: str, base_dir: str, verbose: bool = False, dry_run: bool = False
) -> str: ...
3 changes: 3 additions & 0 deletions typings/distutils-stubs/bcppcompiler.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .ccompiler import CCompiler

class BCPPCompiler(CCompiler): ...
Loading
Loading