Skip to content

Commit 96e9a67

Browse files
authored
Merge branch 'main' into update-ruff
2 parents 79ae47e + 4d4efe5 commit 96e9a67

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+307
-250
lines changed

.github/workflows/main.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ jobs:
6363
- platform: ubuntu-latest
6464
python: "3.10"
6565
distutils: stdlib
66+
# TODO: Re-evaluate the need for the following workaround
67+
exclude:
68+
- {python: "3.9", platform: "macos-latest"} # actions/setup-python#981
6669
runs-on: ${{ matrix.platform }}
6770
continue-on-error: ${{ matrix.python == '3.14' }}
6871
env:

docs/userguide/quickstart.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ Package discovery
199199
-----------------
200200
For projects that follow a simple directory structure, ``setuptools`` should be
201201
able to automatically detect all :term:`packages <package>` and
202-
:term:`namespaces <namespace>`. However, complex projects might include
202+
:term:`namespaces <namespace package>`. However, complex projects might include
203203
additional folders and supporting files that not necessarily should be
204204
distributed (or that can confuse ``setuptools`` auto discovery algorithm).
205205

mypy.ini

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,16 @@ ignore_missing_imports = True
5858

5959
# - wheel: does not intend on exposing a programmatic API https://github.com/pypa/wheel/pull/610#issuecomment-2081687671
6060
[mypy-wheel.*]
61-
ignore_missing_imports = True
61+
follow_untyped_imports = True
6262
# - The following are not marked as py.typed:
6363
# - jaraco: Since mypy 1.12, the root name of the untyped namespace package gets called-out too
6464
# - jaraco.develop: https://github.com/jaraco/jaraco.develop/issues/22
6565
# - jaraco.envs: https://github.com/jaraco/jaraco.envs/issues/7
6666
# - jaraco.packaging: https://github.com/jaraco/jaraco.packaging/issues/20
6767
# - jaraco.path: https://github.com/jaraco/jaraco.path/issues/2
6868
# - jaraco.text: https://github.com/jaraco/jaraco.text/issues/17
69-
[mypy-jaraco,jaraco.develop,jaraco.envs,jaraco.packaging.*,jaraco.path,jaraco.text]
70-
ignore_missing_imports = True
69+
[mypy-jaraco,jaraco.develop.*,jaraco.envs,jaraco.packaging.*,jaraco.path,jaraco.text]
70+
follow_untyped_imports = True
7171

7272
# Even when excluding a module, import issues can show up due to following import
7373
# https://github.com/python/mypy/issues/11936#issuecomment-1466764006

newsfragments/4478.feature.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Synced with pypa/distutils@c97a3db2f including better support for free threaded Python on Windows (pypa/distutils#310), improved typing support, and linter accommodations.

pyproject.toml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ test = [
4444
"packaging>=24.2",
4545
"jaraco.envs>=2.2",
4646
"pytest-xdist>=3", # Dropped dependency on pytest-fork and py
47-
"jaraco.path>=3.2.0",
47+
"jaraco.path>=3.7.2", # Typing fixes
4848
"build[virtualenv]>=1.0.3",
4949
"filelock>=3.4.0",
5050
"ini2toml[lite]>=0.14",
@@ -102,7 +102,7 @@ core = [
102102

103103
# for distutils
104104
"jaraco.collections",
105-
"jaraco.functools>=4",
105+
"jaraco.functools >= 4",
106106
"packaging",
107107
"more_itertools",
108108
]
@@ -135,7 +135,7 @@ type = [
135135
# pin mypy version so a new version doesn't suddenly cause the CI to fail,
136136
# until types-setuptools is removed from typeshed.
137137
# For help with static-typing issues, or mypy update, ping @Avasam
138-
"mypy>=1.12,<1.14",
138+
"mypy==1.14.*",
139139
# Typing fixes in version newer than we require at runtime
140140
"importlib_metadata>=7.0.2; python_version < '3.10'",
141141
# Imported unconditionally in tools/finalize.py
@@ -210,6 +210,10 @@ exclude = [
210210
]
211211
namespaces = true
212212

213+
[tool.setuptools.exclude-package-data]
214+
# Remove ruff.toml when installing vendored packages (#4652)
215+
"*" = ["ruff.toml"]
216+
213217
[tool.distutils.sdist]
214218
formats = "zip"
215219

setuptools/_distutils/cmd.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,21 @@
44
in the distutils.command package.
55
"""
66

7+
from __future__ import annotations
8+
79
import logging
810
import os
911
import re
1012
import sys
13+
from collections.abc import Callable
14+
from typing import Any, ClassVar, TypeVar, overload
1115

1216
from . import _modified, archive_util, dir_util, file_util, util
1317
from ._log import log
1418
from .errors import DistutilsOptionError
1519

20+
_CommandT = TypeVar("_CommandT", bound="Command")
21+
1622

1723
class Command:
1824
"""Abstract base class for defining command classes, the "worker bees"
@@ -44,7 +50,14 @@ class Command:
4450
# 'sub_commands' is usually defined at the *end* of a class, because
4551
# predicates can be unbound methods, so they must already have been
4652
# defined. The canonical example is the "install" command.
47-
sub_commands = []
53+
sub_commands: ClassVar[ # Any to work around variance issues
54+
list[tuple[str, Callable[[Any], bool] | None]]
55+
] = []
56+
57+
user_options: ClassVar[
58+
# Specifying both because list is invariant. Avoids mypy override assignment issues
59+
list[tuple[str, str, str]] | list[tuple[str, str | None, str]]
60+
] = []
4861

4962
# -- Creation/initialization methods -------------------------------
5063

@@ -305,7 +318,17 @@ def get_finalized_command(self, command, create=True):
305318

306319
# XXX rename to 'get_reinitialized_command()'? (should do the
307320
# same in dist.py, if so)
308-
def reinitialize_command(self, command, reinit_subcommands=False):
321+
@overload
322+
def reinitialize_command(
323+
self, command: str, reinit_subcommands: bool = False
324+
) -> Command: ...
325+
@overload
326+
def reinitialize_command(
327+
self, command: _CommandT, reinit_subcommands: bool = False
328+
) -> _CommandT: ...
329+
def reinitialize_command(
330+
self, command: str | Command, reinit_subcommands=False
331+
) -> Command:
309332
return self.distribution.reinitialize_command(command, reinit_subcommands)
310333

311334
def run_command(self, command):

setuptools/_distutils/command/bdist.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import os
77
import warnings
8+
from typing import ClassVar
89

910
from ..core import Command
1011
from ..errors import DistutilsOptionError, DistutilsPlatformError
@@ -23,7 +24,7 @@ def show_formats():
2324
pretty_printer.print_help("List of available distribution formats:")
2425

2526

26-
class ListCompat(dict):
27+
class ListCompat(dict[str, tuple[str, str]]):
2728
# adapter to allow for Setuptools compatibility in format_commands
2829
def append(self, item):
2930
warnings.warn(
@@ -70,7 +71,7 @@ class bdist(Command):
7071
]
7172

7273
# The following commands do not take a format option from bdist
73-
no_format_option = ('bdist_rpm',)
74+
no_format_option: ClassVar[tuple[str, ...]] = ('bdist_rpm',)
7475

7576
# This won't do in reality: will need to distinguish RPM-ish Linux,
7677
# Debian-ish Linux, Solaris, FreeBSD, ..., Windows, Mac OS.

setuptools/_distutils/command/build.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@ def finalize_options(self): # noqa: C901
113113
self.build_temp = os.path.join(self.build_base, 'temp' + plat_specifier)
114114
if self.build_scripts is None:
115115
self.build_scripts = os.path.join(
116-
self.build_base, 'scripts-%d.%d' % sys.version_info[:2]
116+
self.build_base,
117+
f'scripts-{sys.version_info.major}.{sys.version_info.minor}',
117118
)
118119

119120
if self.executable is None and sys.executable:

setuptools/_distutils/command/build_clib.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import os
1818
from distutils._log import log
19+
from typing import ClassVar
1920

2021
from ..core import Command
2122
from ..errors import DistutilsSetupError
@@ -31,7 +32,7 @@ def show_compilers():
3132
class build_clib(Command):
3233
description = "build C/C++ libraries used by Python extensions"
3334

34-
user_options = [
35+
user_options: ClassVar[list[tuple[str, str, str]]] = [
3536
('build-clib=', 'b', "directory to build C/C++ libraries to"),
3637
('build-temp=', 't', "directory to put temporary build by-products"),
3738
('debug', 'g', "compile with debugging information"),
@@ -138,8 +139,7 @@ def check_library_list(self, libraries):
138139

139140
if '/' in name or (os.sep != '/' and os.sep in name):
140141
raise DistutilsSetupError(
141-
f"bad library name '{lib[0]}': "
142-
"may not contain directory separators"
142+
f"bad library name '{lib[0]}': may not contain directory separators"
143143
)
144144

145145
if not isinstance(build_info, dict):

setuptools/_distutils/command/build_ext.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
)
2424
from ..extension import Extension
2525
from ..sysconfig import customize_compiler, get_config_h_filename, get_python_version
26-
from ..util import get_platform, is_mingw
26+
from ..util import get_platform, is_freethreaded, is_mingw
2727

2828
# An extension name is just a dot-separated list of Python NAMEs (ie.
2929
# the same as a fully-qualified module name).
@@ -333,6 +333,12 @@ def run(self): # noqa: C901
333333
if os.name == 'nt' and self.plat_name != get_platform():
334334
self.compiler.initialize(self.plat_name)
335335

336+
# The official Windows free threaded Python installer doesn't set
337+
# Py_GIL_DISABLED because its pyconfig.h is shared with the
338+
# default build, so define it here (pypa/setuptools#4662).
339+
if os.name == 'nt' and is_freethreaded():
340+
self.compiler.define_macro('Py_GIL_DISABLED', '1')
341+
336342
# And make sure that any compile/link-related options (which might
337343
# come from the command-line or from the setup script) are set in
338344
# that CCompiler object -- that way, they automatically apply to
@@ -437,8 +443,7 @@ def check_extensions_list(self, extensions): # noqa: C901
437443
for macro in macros:
438444
if not (isinstance(macro, tuple) and len(macro) in (1, 2)):
439445
raise DistutilsSetupError(
440-
"'macros' element of build info dict "
441-
"must be 1- or 2-tuple"
446+
"'macros' element of build info dict must be 1- or 2-tuple"
442447
)
443448
if len(macro) == 1:
444449
ext.undef_macros.append(macro[0])
@@ -666,8 +671,7 @@ def find_swig(self):
666671
return "swig.exe"
667672
else:
668673
raise DistutilsPlatformError(
669-
"I don't know how to find (much less run) SWIG "
670-
f"on platform '{os.name}'"
674+
f"I don't know how to find (much less run) SWIG on platform '{os.name}'"
671675
)
672676

673677
# -- Name generators -----------------------------------------------

0 commit comments

Comments
 (0)