Skip to content

Commit 263c321

Browse files
authored
Merge pull request #4778 from pypa/feature/distutils-c97a3db2f
Merge with pypa/distutils@c97a3db2f
2 parents 0ebc351 + 2296e9f commit 263c321

Some content is hidden

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

43 files changed

+290
-240
lines changed

newsfragments/4478.feature.rst

+1
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

+1-1
Original file line numberDiff line numberDiff line change
@@ -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
]

setuptools/_distutils/cmd.py

+25-2
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

+3-2
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

+2-1
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

+3-3
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

+9-5
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 -----------------------------------------------

setuptools/_distutils/command/build_scripts.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from distutils import sysconfig
99
from distutils._log import log
1010
from stat import ST_MODE
11+
from typing import ClassVar
1112

1213
from .._modified import newer
1314
from ..core import Command
@@ -25,7 +26,7 @@
2526
class build_scripts(Command):
2627
description = "\"build\" scripts (copy and fixup #! line)"
2728

28-
user_options = [
29+
user_options: ClassVar[list[tuple[str, str, str]]] = [
2930
('build-dir=', 'd', "directory to \"build\" (copy) to"),
3031
('force', 'f', "forcibly build everything (ignore file timestamps"),
3132
('executable=', 'e', "specify final destination interpreter path"),

setuptools/_distutils/command/check.py

+3-5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"""
55

66
import contextlib
7+
from typing import ClassVar
78

89
from ..core import Command
910
from ..errors import DistutilsSetupError
@@ -41,15 +42,12 @@ class check(Command):
4142
"""This command checks the meta-data of the package."""
4243

4344
description = "perform some checks on the package"
44-
user_options = [
45+
user_options: ClassVar[list[tuple[str, str, str]]] = [
4546
('metadata', 'm', 'Verify meta-data'),
4647
(
4748
'restructuredtext',
4849
'r',
49-
(
50-
'Checks if long string meta-data syntax '
51-
'are reStructuredText-compliant'
52-
),
50+
'Checks if long string meta-data syntax are reStructuredText-compliant',
5351
),
5452
('strict', 's', 'Will exit with an error if a check fails'),
5553
]

setuptools/_distutils/command/command_template

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,18 @@ Implements the Distutils 'x' command.
88
__revision__ = "$Id$"
99

1010
from distutils.core import Command
11+
from typing import ClassVar
1112

1213

1314
class x(Command):
14-
1515
# Brief (40-50 characters) description of the command
1616
description = ""
1717

1818
# List of option tuples: long name, short name (None if no short
1919
# name), and help string.
20-
user_options = [('', '',
21-
""),
22-
]
20+
user_options: ClassVar[list[tuple[str, str, str]]] = [
21+
('', '', ""),
22+
]
2323

2424
def initialize_options(self):
2525
self. = None

setuptools/_distutils/command/install.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -407,8 +407,8 @@ def finalize_options(self): # noqa: C901
407407
'dist_version': self.distribution.get_version(),
408408
'dist_fullname': self.distribution.get_fullname(),
409409
'py_version': py_version,
410-
'py_version_short': '%d.%d' % sys.version_info[:2],
411-
'py_version_nodot': '%d%d' % sys.version_info[:2],
410+
'py_version_short': f'{sys.version_info.major}.{sys.version_info.minor}',
411+
'py_version_nodot': f'{sys.version_info.major}{sys.version_info.minor}',
412412
'sys_prefix': prefix,
413413
'prefix': prefix,
414414
'sys_exec_prefix': exec_prefix,

setuptools/_distutils/command/install_data.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
import functools
1111
import os
12-
from typing import Iterable
12+
from collections.abc import Iterable
1313

1414
from ..core import Command
1515
from ..util import change_root, convert_path
@@ -22,8 +22,7 @@ class install_data(Command):
2222
(
2323
'install-dir=',
2424
'd',
25-
"base directory for installing data files "
26-
"[default: installation base dir]",
25+
"base directory for installing data files [default: installation base dir]",
2726
),
2827
('root=', None, "install everything relative to this alternate root directory"),
2928
('force', 'f', "force installation (overwrite existing files)"),

setuptools/_distutils/command/install_egg_info.py

+5-6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import os
99
import re
1010
import sys
11+
from typing import ClassVar
1112

1213
from .. import dir_util
1314
from .._log import log
@@ -18,7 +19,7 @@ class install_egg_info(Command):
1819
"""Install an .egg-info file for the package"""
1920

2021
description = "Install package's PKG-INFO metadata as an .egg-info file"
21-
user_options = [
22+
user_options: ClassVar[list[tuple[str, str, str]]] = [
2223
('install-dir=', 'd', "directory to install to"),
2324
]
2425

@@ -31,11 +32,9 @@ def basename(self):
3132
Allow basename to be overridden by child class.
3233
Ref pypa/distutils#2.
3334
"""
34-
return "%s-%s-py%d.%d.egg-info" % (
35-
to_filename(safe_name(self.distribution.get_name())),
36-
to_filename(safe_version(self.distribution.get_version())),
37-
*sys.version_info[:2],
38-
)
35+
name = to_filename(safe_name(self.distribution.get_name()))
36+
version = to_filename(safe_version(self.distribution.get_version()))
37+
return f"{name}-{version}-py{sys.version_info.major}.{sys.version_info.minor}.egg-info"
3938

4039
def finalize_options(self):
4140
self.set_undefined_options('install_lib', ('install_dir', 'install_dir'))

setuptools/_distutils/command/install_headers.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,16 @@
33
Implements the Distutils 'install_headers' command, to install C/C++ header
44
files to the Python include directory."""
55

6+
from typing import ClassVar
7+
68
from ..core import Command
79

810

911
# XXX force is never used
1012
class install_headers(Command):
1113
description = "install C/C++ header files"
1214

13-
user_options = [
15+
user_options: ClassVar[list[tuple[str, str, str]]] = [
1416
('install-dir=', 'd', "directory to install header files to"),
1517
('force', 'f', "force installation (overwrite existing files)"),
1618
]

setuptools/_distutils/command/sdist.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from distutils._log import log
99
from glob import glob
1010
from itertools import filterfalse
11+
from typing import ClassVar
1112

1213
from ..core import Command
1314
from ..errors import DistutilsOptionError, DistutilsTemplateError
@@ -114,7 +115,7 @@ def checking_metadata(self):
114115

115116
sub_commands = [('check', checking_metadata)]
116117

117-
READMES = ('README', 'README.txt', 'README.rst')
118+
READMES: ClassVar[tuple[str, ...]] = ('README', 'README.txt', 'README.rst')
118119

119120
def initialize_options(self):
120121
# 'template' and 'manifest' are, respectively, the names of
@@ -362,8 +363,7 @@ def read_template(self):
362363
# convert_path function
363364
except (DistutilsTemplateError, ValueError) as msg:
364365
self.warn(
365-
"%s, line %d: %s"
366-
% (template.filename, template.current_line, msg)
366+
f"{template.filename}, line {int(template.current_line)}: {msg}"
367367
)
368368
finally:
369369
template.close()
+1-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
from __future__ import annotations
22

3-
from .py38 import removeprefix
4-
53

64
def consolidate_linker_args(args: list[str]) -> list[str] | str:
75
"""
@@ -12,4 +10,4 @@ def consolidate_linker_args(args: list[str]) -> list[str] | str:
1210

1311
if not all(arg.startswith('-Wl,') for arg in args):
1412
return args
15-
return '-Wl,' + ','.join(removeprefix(arg, '-Wl,') for arg in args)
13+
return '-Wl,' + ','.join(arg.removeprefix('-Wl,') for arg in args)

setuptools/_distutils/compat/py38.py

-34
This file was deleted.

0 commit comments

Comments
 (0)