diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index aa07602eb..8c61be9de 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -41,7 +41,7 @@ jobs: python_version: ['3.11'] include: - os: ubuntu-22.04 - python_version: '3.7' + python_version: '3.8' timeout-minutes: 180 steps: - uses: actions/checkout@v3 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 27642812a..b1de3c5bb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -34,9 +34,9 @@ repos: rev: v1.4.1 hooks: - id: mypy - name: mypy 3.7 on cibuildwheel/ + name: mypy 3.8 on cibuildwheel/ exclude: ^cibuildwheel/resources/.*py$ - args: ["--python-version=3.7"] + args: ["--python-version=3.8"] additional_dependencies: &mypy-dependencies - nox - packaging @@ -50,7 +50,6 @@ repos: - types-pyyaml - types-requests - bracex - - markdown-it-py<3 - id: mypy name: mypy 3.11 exclude: ^cibuildwheel/resources/.*py$ diff --git a/.travis.yml b/.travis.yml index cf45e94e1..e47886b56 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,21 +8,21 @@ branches: jobs: include: - - name: Linux | x86_64 + i686 | Python 3.7 - python: 3.7 + - name: Linux | x86_64 + i686 | Python 3.9 + python: 3.9 services: docker env: PYTHON=python - - name: Linux | arm64 | Python 3.7 - python: 3.7 + - name: Linux | arm64 | Python 3.9 + python: 3.9 services: docker arch: arm64-graviton2 group: edge virt: vm env: PYTHON=python - - name: Linux | ppc64le | Python 3.7 - python: 3.7 + - name: Linux | ppc64le | Python 3.9 + python: 3.9 services: docker arch: ppc64le allow_failure: True @@ -32,16 +32,16 @@ jobs: # c.f. https://travis-ci.community/t/running-out-of-disk-space-quota-when-using-docker-on-ppc64le/11634 - PYTEST_ADDOPTS='-k "not test_manylinuxXXXX_only"' - - name: Windows | x86_64 | Python 3.7 + - name: Windows | x86_64 | Python 3.9 os: windows language: shell before_install: - - choco upgrade python3 -y --version 3.7.9 --limit-output + - choco upgrade python3 -y --version 3.9.13 --limit-output --params "/InstallDir:C:\\Python39" env: - - PYTHON=C:\\Python37\\python + - PYTHON=C:\\Python39\\python - - name: Linux | s390x | Python 3.7 - python: 3.7 + - name: Linux | s390x | Python 3.9 + python: 3.9 services: docker arch: s390x env: PYTHON=python diff --git a/CI.md b/CI.md index 98d36c738..596a70b7d 100644 --- a/CI.md +++ b/CI.md @@ -1,11 +1,11 @@ This is a summary of the Python versions and platforms covered by the different CI platforms: -| | 3.7 | 3.8 | 3.9 | 3.10 | 3.11 | -|---------|-----------|---------------------------------------|-----------|-----------|----------------| -| Linux | Travis CI | AppVeyor¹ / Azure Pipelines / GitLab¹ | CircleCI¹ | Cirrus CI | GitHub Actions | -| macOS | Travis CI | AppVeyor¹ / Azure Pipelines | CircleCI¹ | Cirrus CI | GitHub Actions | -| Windows | Travis CI | AppVeyor¹ / Azure Pipelines / GitLab¹ | | Cirrus CI | GitHub Actions | +| | 3.8 | 3.9 | 3.10 | 3.11 | +|---------|--------------------------------------------------------|-----------------------|-----------|----------------| +| Linux | AppVeyor¹ / Azure Pipelines / GitLab¹ / GitHub Actions | CircleCI¹ / Travis CI | Cirrus CI | GitHub Actions | +| macOS | AppVeyor¹ / Azure Pipelines | CircleCI¹ / Travis CI | Cirrus CI | GitHub Actions | +| Windows | AppVeyor¹ / Azure Pipelines / GitLab¹ | Travis CI | Cirrus CI | GitHub Actions | > ¹ Runs a reduced set of tests to reduce CI load -Non-x86 architectures are covered on Travis CI using Python 3.7. +Non-x86 architectures are covered on Travis CI using Python 3.9. diff --git a/action.yml b/action.yml index 9ce2e2577..cbf301548 100644 --- a/action.yml +++ b/action.yml @@ -28,7 +28,7 @@ runs: - uses: actions/setup-python@v4 id: python with: - python-version: "3.7 - 3.11" + python-version: "3.8 - 3.11" update-environment: false # Redirecting stderr to stdout to fix interleaving issue in Actions. diff --git a/bin/update_pythons.py b/bin/update_pythons.py index c491371fb..cfda890df 100755 --- a/bin/update_pythons.py +++ b/bin/update_pythons.py @@ -7,7 +7,7 @@ import logging from collections.abc import Mapping, MutableMapping from pathlib import Path -from typing import Any, Union +from typing import Any, Final, Literal, TypedDict, Union import click import requests @@ -18,7 +18,6 @@ from rich.syntax import Syntax from cibuildwheel._compat import tomllib -from cibuildwheel._compat.typing import Final, Literal, TypedDict from cibuildwheel.extra import dump_python_configurations log = logging.getLogger("cibw") diff --git a/bin/update_virtualenv.py b/bin/update_virtualenv.py index c4c70f294..d5c86d25c 100755 --- a/bin/update_virtualenv.py +++ b/bin/update_virtualenv.py @@ -7,6 +7,7 @@ import subprocess from dataclasses import dataclass from pathlib import Path +from typing import Final import click import rich @@ -15,7 +16,6 @@ from rich.syntax import Syntax from cibuildwheel._compat import tomllib -from cibuildwheel._compat.typing import Final log = logging.getLogger("cibw") diff --git a/cibuildwheel/__main__.py b/cibuildwheel/__main__.py index 0575f4e13..c6a2fdeaa 100644 --- a/cibuildwheel/__main__.py +++ b/cibuildwheel/__main__.py @@ -10,13 +10,14 @@ from collections.abc import Iterable, Sequence, Set from pathlib import Path from tempfile import mkdtemp +from typing import Protocol import cibuildwheel import cibuildwheel.linux import cibuildwheel.macos import cibuildwheel.util import cibuildwheel.windows -from cibuildwheel._compat.typing import Protocol, assert_never +from cibuildwheel._compat.typing import assert_never from cibuildwheel.architecture import Architecture, allowed_architectures_check from cibuildwheel.logger import log from cibuildwheel.options import CommandLineArguments, Options, compute_options diff --git a/cibuildwheel/_compat/_functools_cached_property_38.py b/cibuildwheel/_compat/_functools_cached_property_38.py deleted file mode 100644 index 134564b5c..000000000 --- a/cibuildwheel/_compat/_functools_cached_property_38.py +++ /dev/null @@ -1,66 +0,0 @@ -from __future__ import annotations - -import typing -from collections.abc import Callable -from threading import RLock -from typing import Any, Generic, TypeVar - -__all__ = ["cached_property"] - -_NOT_FOUND = object() - -_T = TypeVar("_T") - - -class cached_property(Generic[_T]): - def __init__(self, func: Callable[[Any], _T]): - self.func = func - self.attrname: str | None = None - self.__doc__ = func.__doc__ - self.lock = RLock() - - def __set_name__(self, owner: type[Any], name: str) -> None: - if self.attrname is None: - self.attrname = name - elif name != self.attrname: - msg = f"Cannot assign the same cached_property to two different names ({self.attrname!r} and {name!r})." - raise TypeError(msg) - - @typing.overload - def __get__(self, instance: None, owner: type[Any] | None = ...) -> cached_property[_T]: - ... - - @typing.overload - def __get__(self, instance: object, owner: type[Any] | None = ...) -> _T: - ... - - def __get__(self, instance: object | None, owner: type[Any] | None = None) -> Any: - if instance is None: - return self - if self.attrname is None: - msg = "Cannot use cached_property instance without calling __set_name__ on it." - raise TypeError(msg) - try: - cache = instance.__dict__ - except AttributeError: # not all objects have __dict__ (e.g. class defines slots) - msg = ( - f"No '__dict__' attribute on {type(instance).__name__!r} " - f"instance to cache {self.attrname!r} property." - ) - raise TypeError(msg) from None - val = cache.get(self.attrname, _NOT_FOUND) - if val is _NOT_FOUND: - with self.lock: - # check if another thread filled cache while we awaited lock - val = cache.get(self.attrname, _NOT_FOUND) - if val is _NOT_FOUND: - val = self.func(instance) - try: - cache[self.attrname] = val - except TypeError: - msg = ( - f"The '__dict__' attribute on {type(instance).__name__!r} instance " - f"does not support item assignment for caching {self.attrname!r} property." - ) - raise TypeError(msg) from None - return val diff --git a/cibuildwheel/_compat/functools.py b/cibuildwheel/_compat/functools.py deleted file mode 100644 index 8fe86a3e4..000000000 --- a/cibuildwheel/_compat/functools.py +++ /dev/null @@ -1,10 +0,0 @@ -from __future__ import annotations - -import sys - -if sys.version_info >= (3, 8): - from functools import cached_property -else: - from ._functools_cached_property_38 import cached_property - -__all__ = ("cached_property",) diff --git a/cibuildwheel/_compat/typing.py b/cibuildwheel/_compat/typing.py index 62495adf9..a66b1abb5 100644 --- a/cibuildwheel/_compat/typing.py +++ b/cibuildwheel/_compat/typing.py @@ -2,23 +2,12 @@ import sys -if sys.version_info < (3, 8): - from typing_extensions import Final, Literal, OrderedDict, Protocol, TypedDict -else: - from typing import Final, Literal, OrderedDict, Protocol, TypedDict # noqa: TID251 - if sys.version_info < (3, 11): from typing_extensions import NotRequired, assert_never else: from typing import NotRequired, assert_never # noqa: TID251 __all__ = ( - "Final", - "Literal", - "Protocol", - "Protocol", - "TypedDict", - "OrderedDict", "assert_never", "NotRequired", ) diff --git a/cibuildwheel/architecture.py b/cibuildwheel/architecture.py index a891ca2a5..8515621fd 100644 --- a/cibuildwheel/architecture.py +++ b/cibuildwheel/architecture.py @@ -6,8 +6,9 @@ import sys from collections.abc import Set from enum import Enum +from typing import Final, Literal -from ._compat.typing import Final, Literal, assert_never +from ._compat.typing import assert_never from .typing import PlatformName PRETTY_NAMES: Final[dict[PlatformName, str]] = { diff --git a/cibuildwheel/environment.py b/cibuildwheel/environment.py index 3117b54ed..d7727ae48 100644 --- a/cibuildwheel/environment.py +++ b/cibuildwheel/environment.py @@ -2,13 +2,12 @@ import dataclasses from collections.abc import Mapping, Sequence -from typing import Any +from typing import Any, Protocol import bashlex import bashlex.errors from . import bashlex_eval -from ._compat.typing import Protocol class EnvironmentParseError(Exception): diff --git a/cibuildwheel/extra.py b/cibuildwheel/extra.py index 5ac9ea1ff..a87ddfbd0 100644 --- a/cibuildwheel/extra.py +++ b/cibuildwheel/extra.py @@ -6,8 +6,7 @@ from collections.abc import Mapping, Sequence from io import StringIO - -from ._compat.typing import Protocol +from typing import Protocol __all__ = ("Printable", "dump_python_configurations") diff --git a/cibuildwheel/linux.py b/cibuildwheel/linux.py index ca8fa3638..88bd201b5 100644 --- a/cibuildwheel/linux.py +++ b/cibuildwheel/linux.py @@ -6,9 +6,9 @@ from collections.abc import Iterable, Iterator, Sequence, Set from dataclasses import dataclass from pathlib import Path, PurePath, PurePosixPath -from typing import Tuple +from typing import OrderedDict, Tuple -from ._compat.typing import OrderedDict, assert_never +from ._compat.typing import assert_never from .architecture import Architecture from .logger import log from .oci_container import OCIContainer diff --git a/cibuildwheel/logger.py b/cibuildwheel/logger.py index 9a546c973..0aa5263f5 100644 --- a/cibuildwheel/logger.py +++ b/cibuildwheel/logger.py @@ -5,9 +5,8 @@ import re import sys import time -from typing import IO, AnyStr, Tuple +from typing import IO, AnyStr, Final, Tuple -from ._compat.typing import Final from .util import CIProvider, detect_ci_provider FoldPattern = Tuple[str, str] diff --git a/cibuildwheel/macos.py b/cibuildwheel/macos.py index 5401e3818..ddc7c4697 100644 --- a/cibuildwheel/macos.py +++ b/cibuildwheel/macos.py @@ -12,11 +12,11 @@ from collections.abc import Sequence, Set from dataclasses import dataclass from pathlib import Path -from typing import Tuple +from typing import Literal, Tuple from filelock import FileLock -from ._compat.typing import Literal, assert_never +from ._compat.typing import assert_never from .architecture import Architecture from .environment import ParsedEnvironment from .logger import log diff --git a/cibuildwheel/oci_container.py b/cibuildwheel/oci_container.py index e07001268..1ea22edd9 100644 --- a/cibuildwheel/oci_container.py +++ b/cibuildwheel/oci_container.py @@ -14,9 +14,8 @@ from dataclasses import dataclass from pathlib import Path, PurePath, PurePosixPath from types import TracebackType -from typing import IO, Dict +from typing import IO, Dict, Literal -from ._compat.typing import Literal from .typing import PathOrStr, PopenBytes from .util import CIProvider, detect_ci_provider, parse_key_value_string diff --git a/cibuildwheel/options.py b/cibuildwheel/options.py index 80ddd8d50..fd6fabfe1 100644 --- a/cibuildwheel/options.py +++ b/cibuildwheel/options.py @@ -12,12 +12,12 @@ import traceback from collections.abc import Callable, Generator, Iterable, Iterator, Mapping, Set from pathlib import Path -from typing import Any, Dict, List, Union +from typing import Any, Dict, List, Literal, TypedDict, Union from packaging.specifiers import SpecifierSet from ._compat import tomllib -from ._compat.typing import Literal, NotRequired, TypedDict +from ._compat.typing import NotRequired from .architecture import Architecture from .environment import EnvironmentParseError, ParsedEnvironment, parse_environment from .logger import log diff --git a/cibuildwheel/projectfiles.py b/cibuildwheel/projectfiles.py index 95dc150d8..e006aca4c 100644 --- a/cibuildwheel/projectfiles.py +++ b/cibuildwheel/projectfiles.py @@ -3,24 +3,10 @@ import ast import configparser import contextlib -import sys from pathlib import Path -from typing import Any from ._compat import tomllib -if sys.version_info < (3, 8): - Constant = ast.Str - - def get_constant(x: ast.Str) -> str: - return x.s - -else: - Constant = ast.Constant - - def get_constant(x: ast.Constant) -> Any: - return x.value - class Analyzer(ast.NodeVisitor): def __init__(self) -> None: @@ -39,9 +25,9 @@ def visit_keyword(self, node: ast.keyword) -> None: if ( node.arg == "python_requires" and not hasattr(node.parent.parent.parent, "parent") # type: ignore[attr-defined] - and isinstance(node.value, Constant) + and isinstance(node.value, ast.Constant) ): - self.requires_python = get_constant(node.value) + self.requires_python = node.value.value def setup_py_python_requires(content: str) -> str | None: diff --git a/cibuildwheel/typing.py b/cibuildwheel/typing.py index 7abd9e3cf..870cf9fcc 100644 --- a/cibuildwheel/typing.py +++ b/cibuildwheel/typing.py @@ -3,9 +3,7 @@ import os import subprocess import typing -from typing import Union - -from ._compat.typing import Final, Literal, Protocol +from typing import Final, Literal, Protocol, Union __all__ = ( "PLATFORMS", diff --git a/cibuildwheel/util.py b/cibuildwheel/util.py index dfc6e65cf..93aad1860 100644 --- a/cibuildwheel/util.py +++ b/cibuildwheel/util.py @@ -17,10 +17,10 @@ from collections.abc import Generator, Iterable, Mapping, Sequence from dataclasses import dataclass from enum import Enum -from functools import lru_cache +from functools import cached_property, lru_cache from pathlib import Path, PurePath from time import sleep -from typing import Any, ClassVar, TextIO, TypeVar +from typing import Any, ClassVar, Final, Literal, TextIO, TypeVar import bracex import certifi @@ -32,8 +32,6 @@ from platformdirs import user_cache_path from ._compat import tomllib -from ._compat.functools import cached_property -from ._compat.typing import Final, Literal from .typing import PathOrStr, PlatformName __all__ = [ diff --git a/pyproject.toml b/pyproject.toml index 592385f54..4368cd33a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta" [tool.black] line-length = 100 -target-version = ['py37', 'py38', 'py39', 'py310', 'py311'] +target-version = ['py38', 'py39', 'py310', 'py311'] [tool.pytest.ini_options] @@ -20,7 +20,7 @@ log_cli_level = "info" [tool.mypy] -python_version = 3.7 +python_version = 3.8 files = [ "cibuildwheel/*.py", "test/**/*.py", @@ -79,7 +79,7 @@ ignore = [ ] [tool.pylint] -py-version = "3.7" +py-version = "3.8" jobs = "0" fail-on = ["E", "F"] fail-under = "9.8" @@ -144,7 +144,7 @@ extend-ignore = [ "PT004", # Rename suggested for returnless fixtures "PT007", # False positive (fixed upstream) ] -target-version = "py37" +target-version = "py38" typing-modules = ["cibuildwheel._compat.typing"] flake8-unused-arguments.ignore-variadic-names = true @@ -154,11 +154,6 @@ flake8-unused-arguments.ignore-variadic-names = true "typing.Iterator".msg = "Use collections.abc.Iterator instead." "typing.Sequence".msg = "Use collections.abc.Sequence instead." "typing.Set".msg = "Use collections.abc.Set instead." -"typing.Protocol".msg = "Use cibuildwheel._compat.typing.Protocol instead." -"typing.Final".msg = "Use cibuildwheel._compat.typing.Final instead." -"typing.Literal".msg = "Use cibuildwheel._compat.typing.Literal instead." -"typing.OrderedDict".msg = "Use cibuildwheel._compat.typing.OrderedDict instead." -"typing.TypedDict".msg = "Use cibuildwheel._compat.typing.TypedDict instead." "typing.NotRequired".msg = "Use cibuildwheel._compat.typing.NotRequired instead." "typing.assert_never".msg = "Use cibuildwheel._compat.typing.assert_never instead." "tomllib".msg = "Use cibuildwheel._compat.tomllib instead." diff --git a/setup.cfg b/setup.cfg index 1330b72a6..8275e8795 100644 --- a/setup.cfg +++ b/setup.cfg @@ -16,7 +16,6 @@ classifiers = Natural Language :: English Programming Language :: Python :: 3 Programming Language :: Python :: 3 :: Only - Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 @@ -39,7 +38,7 @@ install_requires = platformdirs tomli;python_version < '3.11' typing-extensions>=4.1.0;python_version < '3.11' -python_requires = >=3.7 +python_requires = >=3.8 include_package_data = True zip_safe = False