From 2017969f03d94d325b1d1aa3f5c2bcad807bff18 Mon Sep 17 00:00:00 2001 From: Avasam Date: Mon, 28 Oct 2024 14:24:39 -0400 Subject: [PATCH 1/4] Make reinitialize_command's return type Generic when "command" argument is a Command --- distutils/cmd.py | 17 ++++++++++++++++- distutils/dist.py | 20 +++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/distutils/cmd.py b/distutils/cmd.py index 2bb97956..6ffe7bd4 100644 --- a/distutils/cmd.py +++ b/distutils/cmd.py @@ -4,15 +4,20 @@ in the distutils.command package. """ +from __future__ import annotations + import logging import os import re import sys +from typing import TypeVar, overload from . import _modified, archive_util, dir_util, file_util, util from ._log import log from .errors import DistutilsOptionError +_CommandT = TypeVar("_CommandT", bound="Command") + class Command: """Abstract base class for defining command classes, the "worker bees" @@ -305,7 +310,17 @@ def get_finalized_command(self, command, create=True): # XXX rename to 'get_reinitialized_command()'? (should do the # same in dist.py, if so) - def reinitialize_command(self, command, reinit_subcommands=False): + @overload + def reinitialize_command( + self, command: str, reinit_subcommands: bool = False + ) -> Command: ... + @overload + def reinitialize_command( + self, command: _CommandT, reinit_subcommands: bool = False + ) -> _CommandT: ... + def reinitialize_command( + self, command: str | Command, reinit_subcommands=False + ) -> Command: return self.distribution.reinitialize_command(command, reinit_subcommands) def run_command(self, command): diff --git a/distutils/dist.py b/distutils/dist.py index 8e1e6d0b..a4794598 100644 --- a/distutils/dist.py +++ b/distutils/dist.py @@ -4,6 +4,8 @@ being built/installed/distributed. """ +from __future__ import annotations + import contextlib import logging import os @@ -13,6 +15,7 @@ import warnings from collections.abc import Iterable from email import message_from_file +from typing import TYPE_CHECKING, TypeVar, overload from packaging.utils import canonicalize_name, canonicalize_version @@ -27,6 +30,11 @@ from .fancy_getopt import FancyGetopt, translate_longopt from .util import check_environ, rfc822_escape, strtobool +if TYPE_CHECKING: + from .cmd import Command + +_CommandT = TypeVar("_CommandT", bound="Command") + # Regex to define acceptable Distutils command names. This is not *quite* # the same as a Python NAME -- I don't allow leading underscores. The fact # that they're very similar is no coincidence; the default naming scheme is @@ -900,7 +908,17 @@ def _set_command_options(self, command_obj, option_dict=None): # noqa: C901 except ValueError as msg: raise DistutilsOptionError(msg) - def reinitialize_command(self, command, reinit_subcommands=False): + @overload + def reinitialize_command( + self, command: str, reinit_subcommands: bool = False + ) -> Command: ... + @overload + def reinitialize_command( + self, command: _CommandT, reinit_subcommands: bool = False + ) -> _CommandT: ... + def reinitialize_command( + self, command: str | Command, reinit_subcommands=False + ) -> Command: """Reinitializes a command to the state it was in when first returned by 'get_command_obj()': ie., initialized but not yet finalized. This provides the opportunity to sneak option From ac548562ccc1633ff69b721a1c0ef084ffb011ac Mon Sep 17 00:00:00 2001 From: Avasam Date: Sun, 24 Nov 2024 15:48:15 -0500 Subject: [PATCH 2/4] Remove py38 compat modules --- conftest.py | 2 +- distutils/compat/__init__.py | 4 +-- distutils/compat/py38.py | 34 ------------------ distutils/tests/compat/py38.py | 50 --------------------------- distutils/tests/compat/py39.py | 22 ++++++++++++ distutils/tests/test_bdist_rpm.py | 3 +- distutils/tests/test_build_ext.py | 8 ++--- distutils/tests/test_extension.py | 3 +- distutils/tests/test_filelist.py | 2 +- distutils/tests/test_spawn.py | 2 +- distutils/tests/test_unixccompiler.py | 2 +- distutils/util.py | 12 ++----- ruff.toml | 4 +++ 13 files changed, 37 insertions(+), 111 deletions(-) delete mode 100644 distutils/compat/py38.py delete mode 100644 distutils/tests/compat/py38.py create mode 100644 distutils/tests/compat/py39.py diff --git a/conftest.py b/conftest.py index 98f98d41..3b9444f7 100644 --- a/conftest.py +++ b/conftest.py @@ -48,7 +48,7 @@ def _save_cwd(): @pytest.fixture def distutils_managed_tempdir(request): - from distutils.tests.compat import py38 as os_helper + from distutils.tests.compat import py39 as os_helper self = request.instance self.tempdirs = [] diff --git a/distutils/compat/__init__.py b/distutils/compat/__init__.py index e12534a3..c715ee9c 100644 --- a/distutils/compat/__init__.py +++ b/distutils/compat/__init__.py @@ -1,7 +1,5 @@ from __future__ import annotations -from .py38 import removeprefix - def consolidate_linker_args(args: list[str]) -> list[str] | str: """ @@ -12,4 +10,4 @@ def consolidate_linker_args(args: list[str]) -> list[str] | str: if not all(arg.startswith('-Wl,') for arg in args): return args - return '-Wl,' + ','.join(removeprefix(arg, '-Wl,') for arg in args) + return '-Wl,' + ','.join(arg.removeprefix('-Wl,') for arg in args) diff --git a/distutils/compat/py38.py b/distutils/compat/py38.py deleted file mode 100644 index 03ec73ef..00000000 --- a/distutils/compat/py38.py +++ /dev/null @@ -1,34 +0,0 @@ -import sys - -if sys.version_info < (3, 9): - - def removesuffix(self, suffix): - # suffix='' should not call self[:-0]. - if suffix and self.endswith(suffix): - return self[: -len(suffix)] - else: - return self[:] - - def removeprefix(self, prefix): - if self.startswith(prefix): - return self[len(prefix) :] - else: - return self[:] - -else: - - def removesuffix(self, suffix): - return self.removesuffix(suffix) - - def removeprefix(self, prefix): - return self.removeprefix(prefix) - - -def aix_platform(osname, version, release): - try: - import _aix_support # type: ignore - - return _aix_support.aix_platform() - except ImportError: - pass - return f"{osname}-{version}.{release}" diff --git a/distutils/tests/compat/py38.py b/distutils/tests/compat/py38.py deleted file mode 100644 index 211d3a6c..00000000 --- a/distutils/tests/compat/py38.py +++ /dev/null @@ -1,50 +0,0 @@ -# flake8: noqa - -import contextlib -import builtins -import sys - -from test.support import requires_zlib -import test.support - - -ModuleNotFoundError = getattr(builtins, 'ModuleNotFoundError', ImportError) - -try: - from test.support.warnings_helper import check_warnings -except (ModuleNotFoundError, ImportError): - from test.support import check_warnings - - -try: - from test.support.os_helper import ( - rmtree, - EnvironmentVarGuard, - unlink, - skip_unless_symlink, - temp_dir, - ) -except (ModuleNotFoundError, ImportError): - from test.support import ( - rmtree, - EnvironmentVarGuard, - unlink, - skip_unless_symlink, - temp_dir, - ) - - -try: - from test.support.import_helper import ( - DirsOnSysPath, - CleanImport, - ) -except (ModuleNotFoundError, ImportError): - from test.support import ( - DirsOnSysPath, - CleanImport, - ) - - -if sys.version_info < (3, 9): - requires_zlib = lambda: test.support.requires_zlib diff --git a/distutils/tests/compat/py39.py b/distutils/tests/compat/py39.py new file mode 100644 index 00000000..82468836 --- /dev/null +++ b/distutils/tests/compat/py39.py @@ -0,0 +1,22 @@ +import sys + +if sys.version_info >= (3, 10): + from test.support.import_helper import ( + CleanImport as CleanImport, + DirsOnSysPath as DirsOnSysPath, + ) + from test.support.os_helper import ( + EnvironmentVarGuard as EnvironmentVarGuard, + rmtree as rmtree, + skip_unless_symlink as skip_unless_symlink, + unlink as unlink, + ) +else: + from test.support import ( + CleanImport as CleanImport, + DirsOnSysPath as DirsOnSysPath, + EnvironmentVarGuard as EnvironmentVarGuard, + rmtree as rmtree, + skip_unless_symlink as skip_unless_symlink, + unlink as unlink, + ) diff --git a/distutils/tests/test_bdist_rpm.py b/distutils/tests/test_bdist_rpm.py index 1109fdf1..75051430 100644 --- a/distutils/tests/test_bdist_rpm.py +++ b/distutils/tests/test_bdist_rpm.py @@ -8,8 +8,7 @@ from distutils.tests import support import pytest - -from .compat.py38 import requires_zlib +from test.support import requires_zlib SETUP_PY = """\ from distutils.core import setup diff --git a/distutils/tests/test_build_ext.py b/distutils/tests/test_build_ext.py index 8bd3cef8..8477c9da 100644 --- a/distutils/tests/test_build_ext.py +++ b/distutils/tests/test_build_ext.py @@ -19,11 +19,7 @@ ) from distutils.extension import Extension from distutils.tests import missing_compiler_executable -from distutils.tests.support import ( - TempdirManager, - copy_xxmodule_c, - fixup_build_ext, -) +from distutils.tests.support import TempdirManager, copy_xxmodule_c, fixup_build_ext from io import StringIO import jaraco.path @@ -31,7 +27,7 @@ import pytest from test import support -from .compat import py38 as import_helper +from .compat import py39 as import_helper @pytest.fixture() diff --git a/distutils/tests/test_extension.py b/distutils/tests/test_extension.py index 41872e04..e51c1cd8 100644 --- a/distutils/tests/test_extension.py +++ b/distutils/tests/test_extension.py @@ -6,8 +6,7 @@ from distutils.extension import Extension, read_setup_file import pytest - -from .compat.py38 import check_warnings +from test.support.warnings_helper import check_warnings class TestExtension: diff --git a/distutils/tests/test_filelist.py b/distutils/tests/test_filelist.py index ec7e5cf3..130e6fb5 100644 --- a/distutils/tests/test_filelist.py +++ b/distutils/tests/test_filelist.py @@ -10,7 +10,7 @@ import jaraco.path import pytest -from .compat import py38 as os_helper +from .compat import py39 as os_helper MANIFEST_IN = """\ include ok diff --git a/distutils/tests/test_spawn.py b/distutils/tests/test_spawn.py index fcbc765e..3b9fc926 100644 --- a/distutils/tests/test_spawn.py +++ b/distutils/tests/test_spawn.py @@ -12,7 +12,7 @@ import pytest from test.support import unix_shell -from .compat import py38 as os_helper +from .compat import py39 as os_helper class TestSpawn(support.TempdirManager): diff --git a/distutils/tests/test_unixccompiler.py b/distutils/tests/test_unixccompiler.py index 16953287..2c2f4aae 100644 --- a/distutils/tests/test_unixccompiler.py +++ b/distutils/tests/test_unixccompiler.py @@ -12,7 +12,7 @@ import pytest from . import support -from .compat.py38 import EnvironmentVarGuard +from .compat.py39 import EnvironmentVarGuard @pytest.fixture(autouse=True) diff --git a/distutils/util.py b/distutils/util.py index 8d8260bc..1334e2f7 100644 --- a/distutils/util.py +++ b/distutils/util.py @@ -25,7 +25,7 @@ from .spawn import spawn -def get_host_platform(): +def get_host_platform() -> str: """ Return a string that identifies the current platform. Use this function to distinguish platform-specific build directories and @@ -34,15 +34,7 @@ def get_host_platform(): # This function initially exposed platforms as defined in Python 3.9 # even with older Python versions when distutils was split out. - # Now it delegates to stdlib sysconfig, but maintains compatibility. - - if sys.version_info < (3, 9): - if os.name == "posix" and hasattr(os, 'uname'): - osname, host, release, version, machine = os.uname() - if osname[:3] == "aix": - from .compat.py38 import aix_platform - - return aix_platform(osname, version, release) + # Now it delegates to stdlib sysconfig. return sysconfig.get_platform() diff --git a/ruff.toml b/ruff.toml index 0cc5b267..b0930827 100644 --- a/ruff.toml +++ b/ruff.toml @@ -47,6 +47,10 @@ ignore = [ "TRY400", ] +[lint.isort] +combine-as-imports = true +split-on-trailing-comma = false + [format] # Enable preview to get hugged parenthesis unwrapping and other nice surprises # See https://github.com/jaraco/skeleton/pull/133#issuecomment-2239538373 From 4e6e8fc954fad20d0d869524594d30b12a5aba34 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 26 Dec 2024 20:52:27 -0500 Subject: [PATCH 3/4] Remove UP036 exclusion. --- ruff.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/ruff.toml b/ruff.toml index b0930827..da3e3f8d 100644 --- a/ruff.toml +++ b/ruff.toml @@ -21,7 +21,6 @@ extend-select = [ ignore = [ # TODO: Fix these new violations in Ruff 0.8.0 "UP031", - "UP036", # https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules "W191", From fc15d4575aec0c4adeec367c777bac3b642bdc8a Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 26 Dec 2024 20:54:55 -0500 Subject: [PATCH 4/4] Prefer the standard format for imports, even though it's unnecessarily repetitive. --- distutils/tests/compat/py39.py | 18 ++++++++++++++++++ ruff.toml | 4 ---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/distutils/tests/compat/py39.py b/distutils/tests/compat/py39.py index 82468836..aca3939a 100644 --- a/distutils/tests/compat/py39.py +++ b/distutils/tests/compat/py39.py @@ -3,20 +3,38 @@ if sys.version_info >= (3, 10): from test.support.import_helper import ( CleanImport as CleanImport, + ) + from test.support.import_helper import ( DirsOnSysPath as DirsOnSysPath, ) from test.support.os_helper import ( EnvironmentVarGuard as EnvironmentVarGuard, + ) + from test.support.os_helper import ( rmtree as rmtree, + ) + from test.support.os_helper import ( skip_unless_symlink as skip_unless_symlink, + ) + from test.support.os_helper import ( unlink as unlink, ) else: from test.support import ( CleanImport as CleanImport, + ) + from test.support import ( DirsOnSysPath as DirsOnSysPath, + ) + from test.support import ( EnvironmentVarGuard as EnvironmentVarGuard, + ) + from test.support import ( rmtree as rmtree, + ) + from test.support import ( skip_unless_symlink as skip_unless_symlink, + ) + from test.support import ( unlink as unlink, ) diff --git a/ruff.toml b/ruff.toml index da3e3f8d..0d8179b3 100644 --- a/ruff.toml +++ b/ruff.toml @@ -46,10 +46,6 @@ ignore = [ "TRY400", ] -[lint.isort] -combine-as-imports = true -split-on-trailing-comma = false - [format] # Enable preview to get hugged parenthesis unwrapping and other nice surprises # See https://github.com/jaraco/skeleton/pull/133#issuecomment-2239538373