diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 571c1ed5f7..5c6cc311fd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -41,21 +41,21 @@ jobs: # https://blog.jaraco.com/efficient-use-of-ci-resources/ matrix: python: - - "3.9" + - "3.10" - ">=3.13.5" # temporary bound until it becomes the default, python/cpython#135151 platform: - ubuntu-latest - macos-latest - windows-latest include: - - python: "3.10" - platform: ubuntu-latest - python: "3.11" platform: ubuntu-latest - python: "3.12" platform: ubuntu-latest - python: "3.14" platform: ubuntu-latest + - python: "3.15" + platform: ubuntu-latest - python: pypy3.10 platform: ubuntu-latest distutils: stdlib @@ -63,7 +63,7 @@ jobs: python: "3.10" distutils: stdlib runs-on: ${{ matrix.platform }} - continue-on-error: ${{ matrix.python == '3.14' || matrix.python == 'pypy3.10' }} + continue-on-error: ${{ matrix.python == '3.15' || matrix.python == 'pypy3.10' }} # XXX: pypy seems to be flaky with unrelated tests in #6345 env: SETUPTOOLS_USE_DISTUTILS: ${{ matrix.distutils || 'local' }} @@ -73,7 +73,7 @@ jobs: - name: Install build dependencies # Install dependencies for building packages on pre-release Pythons # jaraco/skeleton#161 - if: matrix.python == '3.14' && matrix.platform == 'ubuntu-latest' + if: matrix.python == '3.15' && matrix.platform == 'ubuntu-latest' run: | sudo apt update sudo apt install -y libxml2-dev libxslt-dev @@ -187,7 +187,7 @@ jobs: strategy: matrix: python: - - 39 + - 312 platform: - windows-latest runs-on: ${{ matrix.platform }} diff --git a/.github/workflows/pyright.yml b/.github/workflows/pyright.yml index 42d0164ff1..785bd2f198 100644 --- a/.github/workflows/pyright.yml +++ b/.github/workflows/pyright.yml @@ -42,8 +42,8 @@ jobs: # https://blog.jaraco.com/efficient-use-of-ci-resources/ matrix: python: - - "3.9" - - "3.13" + - "3.10" + - "3.14" platform: - ubuntu-latest runs-on: ${{ matrix.platform }} diff --git a/README.rst b/README.rst index d677b70387..80dce9520c 100644 --- a/README.rst +++ b/README.rst @@ -14,7 +14,7 @@ .. |docs-badge| image:: https://img.shields.io/readthedocs/setuptools/latest.svg :target: https://setuptools.pypa.io -.. |skeleton-badge| image:: https://img.shields.io/badge/skeleton-2025-informational +.. |skeleton-badge| image:: https://img.shields.io/badge/skeleton-2026-informational :target: https://blog.jaraco.com/skeleton .. |codecov-badge| image:: https://img.shields.io/codecov/c/github/pypa/setuptools/master.svg?logo=codecov&logoColor=white diff --git a/newsfragments/+0af71c41.feature.rst b/newsfragments/+0af71c41.feature.rst new file mode 100644 index 0000000000..d8c8faf72f --- /dev/null +++ b/newsfragments/+0af71c41.feature.rst @@ -0,0 +1 @@ +Require Python 3.10 or later. diff --git a/pyproject.toml b/pyproject.toml index 3439f861bc..bbfa0dd0ca 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,7 +26,7 @@ classifiers = [ "Topic :: System :: Systems Administration", "Topic :: Utilities", ] -requires-python = ">=3.9" +requires-python = ">=3.10" license = "MIT" dependencies = [ ] @@ -109,7 +109,7 @@ core = [ check = [ # upstream - "pytest-checkdocs >= 2.4", + "pytest-checkdocs >= 2.14", "pytest-ruff >= 0.2.1; sys_platform != 'cygwin'", # local @@ -123,12 +123,14 @@ cover = [ ] enabler = [ - "pytest-enabler >= 2.2", + "pytest-enabler >= 3.4", ] type = [ # upstream - "pytest-mypy", + + # Exclude PyPy from type checks (python/mypy#20454 jaraco/skeleton#187) + "pytest-mypy >= 1.0.1; platform_python_implementation != 'PyPy'", # local diff --git a/setuptools/_importlib.py b/setuptools/_importlib.py index ce0fd52653..2b27bc10cd 100644 --- a/setuptools/_importlib.py +++ b/setuptools/_importlib.py @@ -1,9 +1,2 @@ -import sys - -if sys.version_info < (3, 10): - import importlib_metadata as metadata # pragma: no cover -else: - import importlib.metadata as metadata # noqa: F401 - - +import importlib.metadata as metadata # noqa: F401 import importlib.resources as resources # noqa: F401 diff --git a/setuptools/_path.py b/setuptools/_path.py index 2b78022934..0a5b26ea4b 100644 --- a/setuptools/_path.py +++ b/setuptools/_path.py @@ -3,15 +3,15 @@ import contextlib import os import sys -from typing import TYPE_CHECKING, TypeVar, Union +from typing import TYPE_CHECKING, TypeVar from more_itertools import unique_everseen if TYPE_CHECKING: - from typing_extensions import TypeAlias + from typing import TypeAlias -StrPath: TypeAlias = Union[str, os.PathLike[str]] # Same as _typeshed.StrPath -StrPathT = TypeVar("StrPathT", bound=Union[str, os.PathLike[str]]) +StrPath: TypeAlias = str | os.PathLike[str] # Same as _typeshed.StrPath +StrPathT = TypeVar("StrPathT", bound=str | os.PathLike[str]) def ensure_directory(path): diff --git a/setuptools/_reqs.py b/setuptools/_reqs.py index 7be56cbf35..19ef375cf1 100644 --- a/setuptools/_reqs.py +++ b/setuptools/_reqs.py @@ -1,17 +1,17 @@ from __future__ import annotations -from collections.abc import Iterable, Iterator +from collections.abc import Callable, Iterable, Iterator from functools import lru_cache -from typing import TYPE_CHECKING, Callable, TypeVar, Union, overload +from typing import TYPE_CHECKING, TypeVar, overload import jaraco.text as text from packaging.requirements import Requirement if TYPE_CHECKING: - from typing_extensions import TypeAlias + from typing import TypeAlias _T = TypeVar("_T") -_StrOrIter: TypeAlias = Union[str, Iterable[str]] +_StrOrIter: TypeAlias = str | Iterable[str] parse_req: Callable[[str], Requirement] = lru_cache()(Requirement) diff --git a/setuptools/_shutil.py b/setuptools/_shutil.py index 660459a110..b9a514efcc 100644 --- a/setuptools/_shutil.py +++ b/setuptools/_shutil.py @@ -2,7 +2,8 @@ import os import stat -from typing import Callable, TypeVar +from collections.abc import Callable +from typing import TypeVar from .compat import py311 diff --git a/setuptools/build_meta.py b/setuptools/build_meta.py index 1d93b6193b..c80f53321c 100644 --- a/setuptools/build_meta.py +++ b/setuptools/build_meta.py @@ -39,7 +39,7 @@ import warnings from collections.abc import Iterable, Iterator, Mapping from pathlib import Path -from typing import TYPE_CHECKING, NoReturn, Union +from typing import TYPE_CHECKING, NoReturn import setuptools @@ -52,7 +52,7 @@ from distutils.util import strtobool if TYPE_CHECKING: - from typing_extensions import TypeAlias + from typing import TypeAlias __all__ = [ 'get_requires_for_build_sdist', @@ -144,7 +144,7 @@ def suppress_known_deprecation(): yield -_ConfigSettings: TypeAlias = Union[Mapping[str, Union[str, list[str], None]], None] +_ConfigSettings: TypeAlias = Mapping[str, str | list[str] | None] | None """ Currently the user can run:: diff --git a/setuptools/command/bdist_egg.py b/setuptools/command/bdist_egg.py index dbabeccb9d..02c94faff0 100644 --- a/setuptools/command/bdist_egg.py +++ b/setuptools/command/bdist_egg.py @@ -23,8 +23,9 @@ from distutils.dir_util import mkpath, remove_tree if TYPE_CHECKING: + from typing import TypeAlias + from _typeshed import GenericPath - from typing_extensions import TypeAlias # Same as zipfile._ZipFileMode from typeshed _ZipFileMode: TypeAlias = Literal["r", "w", "x", "a"] diff --git a/setuptools/compat/py311.py b/setuptools/compat/py311.py index 52b58af32a..2aec70b8cc 100644 --- a/setuptools/compat/py311.py +++ b/setuptools/compat/py311.py @@ -2,11 +2,13 @@ import shutil import sys -from typing import TYPE_CHECKING, Any, Callable +from collections.abc import Callable +from typing import TYPE_CHECKING, Any if TYPE_CHECKING: + from typing import TypeAlias + from _typeshed import ExcInfo, StrOrBytesPath - from typing_extensions import TypeAlias # Same as shutil._OnExcCallback from typeshed _OnExcCallback: TypeAlias = Callable[[Callable[..., Any], str, BaseException], object] diff --git a/setuptools/config/__init__.py b/setuptools/config/__init__.py index fcc7d008d6..76754b0ced 100644 --- a/setuptools/config/__init__.py +++ b/setuptools/config/__init__.py @@ -2,8 +2,9 @@ ``setuptools.config.setupcfg`` """ +from collections.abc import Callable from functools import wraps -from typing import Callable, TypeVar, cast +from typing import TypeVar, cast from ..warnings import SetuptoolsDeprecationWarning from . import setupcfg diff --git a/setuptools/config/_apply_pyprojecttoml.py b/setuptools/config/_apply_pyprojecttoml.py index 4559193774..140969feee 100644 --- a/setuptools/config/_apply_pyprojecttoml.py +++ b/setuptools/config/_apply_pyprojecttoml.py @@ -12,13 +12,13 @@ import logging import os -from collections.abc import Mapping +from collections.abc import Callable, Mapping from email.headerregistry import Address from functools import partial, reduce from inspect import cleandoc from itertools import chain from types import MappingProxyType -from typing import TYPE_CHECKING, Any, Callable, TypeVar, Union +from typing import TYPE_CHECKING, Any, TypeVar from .. import _static from .._path import StrPath @@ -27,7 +27,7 @@ from ..warnings import SetuptoolsDeprecationWarning, SetuptoolsWarning if TYPE_CHECKING: - from typing_extensions import TypeAlias + from typing import TypeAlias from setuptools._importlib import metadata from setuptools.dist import Distribution @@ -36,8 +36,8 @@ EMPTY: Mapping = MappingProxyType({}) # Immutable dict-like -_ProjectReadmeValue: TypeAlias = Union[str, dict[str, str]] -_Correspondence: TypeAlias = Callable[["Distribution", Any, Union[StrPath, None]], None] +_ProjectReadmeValue: TypeAlias = str | dict[str, str] +_Correspondence: TypeAlias = Callable[["Distribution", Any, StrPath | None], None] _T = TypeVar("_T") _logger = logging.getLogger(__name__) diff --git a/setuptools/config/expand.py b/setuptools/config/expand.py index d9a2ded430..fd29ddd6db 100644 --- a/setuptools/config/expand.py +++ b/setuptools/config/expand.py @@ -25,14 +25,14 @@ import os import pathlib import sys -from collections.abc import Iterable, Iterator, Mapping +from collections.abc import Callable, Iterable, Iterator, Mapping from configparser import ConfigParser from glob import iglob from importlib.machinery import ModuleSpec, all_suffixes from itertools import chain from pathlib import Path from types import ModuleType, TracebackType -from typing import TYPE_CHECKING, Any, Callable, TypeVar +from typing import TYPE_CHECKING, Any, TypeVar from .. import _static from .._path import StrPath, same_path as _same_path diff --git a/setuptools/config/pyprojecttoml.py b/setuptools/config/pyprojecttoml.py index 3dfc46dd97..9e2b16c2e5 100644 --- a/setuptools/config/pyprojecttoml.py +++ b/setuptools/config/pyprojecttoml.py @@ -13,11 +13,11 @@ import logging import os -from collections.abc import Mapping +from collections.abc import Callable, Mapping from contextlib import contextmanager from functools import partial from types import TracebackType -from typing import TYPE_CHECKING, Any, Callable +from typing import TYPE_CHECKING, Any from .._path import StrPath from ..errors import FileError, InvalidConfigError diff --git a/setuptools/config/setupcfg.py b/setuptools/config/setupcfg.py index 121a0febda..96aeb9a3c5 100644 --- a/setuptools/config/setupcfg.py +++ b/setuptools/config/setupcfg.py @@ -16,9 +16,9 @@ import os from abc import abstractmethod from collections import defaultdict -from collections.abc import Iterable, Iterator +from collections.abc import Callable, Iterable, Iterator from functools import partial, wraps -from typing import TYPE_CHECKING, Any, Callable, ClassVar, Generic, TypeVar, cast +from typing import TYPE_CHECKING, Any, ClassVar, Generic, TypeVar, cast from packaging.markers import default_environment as marker_env from packaging.requirements import InvalidRequirement, Requirement @@ -31,7 +31,7 @@ from . import expand if TYPE_CHECKING: - from typing_extensions import TypeAlias + from typing import TypeAlias from setuptools.dist import Distribution diff --git a/setuptools/dist.py b/setuptools/dist.py index a224b3ee44..e600404198 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -10,7 +10,7 @@ from collections.abc import Iterable, Iterator, MutableMapping, Sequence from glob import glob from pathlib import Path -from typing import TYPE_CHECKING, Any, Union +from typing import TYPE_CHECKING, Any from more_itertools import partition, unique_everseen from packaging.markers import InvalidMarker, Marker @@ -44,7 +44,7 @@ from distutils.util import strtobool if TYPE_CHECKING: - from typing_extensions import TypeAlias + from typing import TypeAlias __all__ = ['Distribution'] @@ -59,10 +59,10 @@ - not imply a nested type (like `dict`) for use with `isinstance`. """ -_Sequence: TypeAlias = Union[tuple[str, ...], list[str]] +_Sequence: TypeAlias = tuple[str, ...] | list[str] # This is how stringifying _Sequence would look in Python 3.10 _sequence_type_repr = "tuple[str, ...] | list[str]" -_OrderedStrSequence: TypeAlias = Union[str, dict[str, Any], Sequence[str]] +_OrderedStrSequence: TypeAlias = str | dict[str, Any] | Sequence[str] """ :meta private: Avoid single-use iterable. Disallow sets. diff --git a/setuptools/tests/test_build_meta.py b/setuptools/tests/test_build_meta.py index 2cd0a0a8ed..8237bf64a5 100644 --- a/setuptools/tests/test_build_meta.py +++ b/setuptools/tests/test_build_meta.py @@ -7,9 +7,10 @@ import sys import tarfile import warnings +from collections.abc import Callable from concurrent import futures from pathlib import Path -from typing import Any, Callable +from typing import Any from zipfile import ZipFile import pytest diff --git a/setuptools/warnings.py b/setuptools/warnings.py index 96467787c2..97f6971cf7 100644 --- a/setuptools/warnings.py +++ b/setuptools/warnings.py @@ -15,7 +15,7 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: - from typing_extensions import TypeAlias + from typing import TypeAlias _DueDate: TypeAlias = tuple[int, int, int] # time tuple _INDENT = 8 * " " diff --git a/towncrier.toml b/towncrier.toml index 9505e57db6..577e87a793 100644 --- a/towncrier.toml +++ b/towncrier.toml @@ -1,4 +1,3 @@ [tool.towncrier] title_format = "{version}" -# workaround for sphinx-contrib/sphinxcontrib-towncrier#83 -directory = "newsfragments" +directory = "newsfragments" # jaraco/skeleton#184 diff --git a/tox.ini b/tox.ini index 6562ac7778..bcee70d589 100644 --- a/tox.ini +++ b/tox.ini @@ -44,7 +44,7 @@ deps = diff-cover commands = pytest {posargs} --cov-report xml - diff-cover coverage.xml --compare-branch=origin/main --html-report diffcov.html + diff-cover coverage.xml --compare-branch=origin/main --format html:diffcov.html diff-cover coverage.xml --compare-branch=origin/main --fail-under=100 [testenv:docs]