From 9ca45e30fd3624dbd1d64f26db683d092c668101 Mon Sep 17 00:00:00 2001 From: Anton Agestam Date: Sun, 15 Sep 2024 14:36:33 +0200 Subject: [PATCH] chore: Bump version matrix - Drop support for Python 3.8, which has imminent EOL. - Add support for Python 3.13. --- .github/workflows/ci.yaml | 2 +- .pre-commit-config.yaml | 2 -- pyproject.toml | 4 ++-- setup.cfg | 6 +++--- src/phantom/_base.py | 4 ++-- src/phantom/_utils/misc.py | 9 ++++----- src/phantom/bounds.py | 4 ++-- src/phantom/negated.py | 2 +- src/phantom/predicates/boolean.py | 2 +- src/phantom/predicates/collection.py | 6 +++--- src/phantom/predicates/generic.py | 3 +-- src/phantom/predicates/re.py | 2 +- src/phantom/re.py | 2 +- src/phantom/schema.py | 2 +- src/phantom/sized.py | 5 +++-- tests/predicates/test_boolean.py | 2 +- tests/predicates/test_collection.py | 6 +++--- tests/predicates/test_generic.py | 10 ++++++---- tests/predicates/test_interval.py | 5 ++--- tests/pydantic/test_schemas.py | 9 --------- tests/test_fn.py | 2 +- tests/test_fn.yaml | 2 +- 22 files changed, 40 insertions(+), 51 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 38e98ac..12962b8 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -44,7 +44,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13-dev"] steps: - uses: actions/checkout@v3 - name: Set up Python diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 06ca843..4cfe855 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,3 @@ -default_language_version: - python: python3.11 repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: "v4.4.0" diff --git a/pyproject.toml b/pyproject.toml index 52d89be..5ec701c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ requires = ["setuptools>=67.4.0", "wheel"] build-backend = "setuptools.build_meta" [tool.black] -target-version = ["py38"] +target-version = ["py39"] [tool.pytest.ini_options] testpaths = ["tests", "src", "docs"] @@ -15,7 +15,7 @@ markers = [ [tool.ruff] fix = true -target-version = "py38" +target-version = "py39" extend-select = [ # bugbear "B", diff --git a/setup.cfg b/setup.cfg index fb85638..f5ddb8c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -12,11 +12,11 @@ classifiers = Programming Language :: Python Programming Language :: Python :: 3 Programming Language :: Python :: 3 :: Only - Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 Programming Language :: Python :: 3.12 + Programming Language :: Python :: 3.13 Development Status :: 5 - Production/Stable author = Anton Agestam author_email = git@antonagestam.se @@ -30,7 +30,7 @@ include_package_data = True package_dir = =src packages = find: -python_requires = >=3.8 +python_requires = >=3.9 install_requires = # typeguard 4.3.0 breaks "intersection" protocols, see linked issue. I didn't figure # out a way to work around this at the moment, so it needs to be pinned. @@ -66,7 +66,7 @@ test = coverage [mypy] -python_version = 3.8 +python_version = 3.9 show_error_codes = True pretty = True files = src, tests diff --git a/src/phantom/_base.py b/src/phantom/_base.py index 58e643e..361de96 100644 --- a/src/phantom/_base.py +++ b/src/phantom/_base.py @@ -1,12 +1,12 @@ from __future__ import annotations import abc +from collections.abc import Iterable +from collections.abc import Iterator from typing import Any from typing import Callable from typing import ClassVar from typing import Generic -from typing import Iterable -from typing import Iterator from typing import Protocol from typing import TypeVar from typing import runtime_checkable diff --git a/src/phantom/_utils/misc.py b/src/phantom/_utils/misc.py index 0743dba..0c3eb6f 100644 --- a/src/phantom/_utils/misc.py +++ b/src/phantom/_utils/misc.py @@ -3,14 +3,13 @@ from __future__ import annotations import types +from collections.abc import MutableMapping +from collections.abc import MutableSequence +from collections.abc import MutableSet from dataclasses import is_dataclass from itertools import product from typing import Final -from typing import MutableMapping -from typing import MutableSequence -from typing import MutableSet from typing import NewType -from typing import Tuple from typing import Union from typing_extensions import TypeAlias @@ -39,7 +38,7 @@ def resolve_class_attr( ) -BoundType: TypeAlias = Union[type, Tuple[type, ...]] +BoundType: TypeAlias = Union[type, tuple[type, ...]] def _is_union(type_: BoundType) -> bool: diff --git a/src/phantom/bounds.py b/src/phantom/bounds.py index 460d5f0..488c44c 100644 --- a/src/phantom/bounds.py +++ b/src/phantom/bounds.py @@ -1,10 +1,10 @@ from __future__ import annotations +from collections.abc import Iterable +from collections.abc import Sequence from typing import Any from typing import Callable from typing import Final -from typing import Iterable -from typing import Sequence from typing import TypeVar from typing import cast diff --git a/src/phantom/negated.py b/src/phantom/negated.py index a89b715..b6b8674 100644 --- a/src/phantom/negated.py +++ b/src/phantom/negated.py @@ -7,8 +7,8 @@ """ from __future__ import annotations +from collections.abc import Sequence from typing import Generic -from typing import Sequence from typing import TypeVar from typing_extensions import get_args diff --git a/src/phantom/predicates/boolean.py b/src/phantom/predicates/boolean.py index dac0788..51cb421 100644 --- a/src/phantom/predicates/boolean.py +++ b/src/phantom/predicates/boolean.py @@ -1,4 +1,4 @@ -from typing import Iterable +from collections.abc import Iterable from typing import Literal from typing import TypeVar diff --git a/src/phantom/predicates/collection.py b/src/phantom/predicates/collection.py index f1f63a8..92c9dc5 100644 --- a/src/phantom/predicates/collection.py +++ b/src/phantom/predicates/collection.py @@ -1,6 +1,6 @@ -from typing import Container -from typing import Iterable -from typing import Sized +from collections.abc import Container +from collections.abc import Iterable +from collections.abc import Sized from typing import TypeVar from . import Predicate diff --git a/src/phantom/predicates/generic.py b/src/phantom/predicates/generic.py index 9c1bd9d..099e59c 100644 --- a/src/phantom/predicates/generic.py +++ b/src/phantom/predicates/generic.py @@ -1,4 +1,3 @@ -from typing import Tuple from typing import Union import typeguard @@ -29,7 +28,7 @@ def check(b: object) -> bool: return check -def of_type(t: Union[type, Tuple[type, ...]]) -> Predicate[object]: +def of_type(t: Union[type, tuple[type, ...]]) -> Predicate[object]: """ Create a new predicate that succeeds when its argument is an instance of ``t``. """ diff --git a/src/phantom/predicates/re.py b/src/phantom/predicates/re.py index d87fbf6..37456b3 100644 --- a/src/phantom/predicates/re.py +++ b/src/phantom/predicates/re.py @@ -1,4 +1,4 @@ -from typing import Pattern +from re import Pattern from . import Predicate from ._utils import bind_name diff --git a/src/phantom/re.py b/src/phantom/re.py index 82bb3cb..3ba05f5 100644 --- a/src/phantom/re.py +++ b/src/phantom/re.py @@ -12,8 +12,8 @@ class Greeting(Match, pattern=r"^(Hi|Hello)"): from __future__ import annotations import re +from re import Pattern from typing import Any -from typing import Pattern from . import Phantom from . import _hypothesis diff --git a/src/phantom/schema.py b/src/phantom/schema.py index 0e742ea..35996e2 100644 --- a/src/phantom/schema.py +++ b/src/phantom/schema.py @@ -1,6 +1,6 @@ +from collections.abc import Sequence from typing import Literal from typing import Optional -from typing import Sequence from typing_extensions import TypedDict from typing_extensions import final diff --git a/src/phantom/sized.py b/src/phantom/sized.py index 486feaa..0719138 100644 --- a/src/phantom/sized.py +++ b/src/phantom/sized.py @@ -26,13 +26,14 @@ class SizedStr(str, PhantomBound[str], max=255): """ from __future__ import annotations +from collections.abc import Iterable +from collections.abc import Sized + # This is the closest I could find to documentation of _ProtocolMeta. # https://github.com/python/cpython/commit/74d7f76e2c953fbfdb7ce01b7319d91d471cc5ef from typing import Any from typing import Generic -from typing import Iterable from typing import Protocol -from typing import Sized from typing import TypeVar from typing import _ProtocolMeta from typing import runtime_checkable diff --git a/tests/predicates/test_boolean.py b/tests/predicates/test_boolean.py index f5c58b0..7afb5be 100644 --- a/tests/predicates/test_boolean.py +++ b/tests/predicates/test_boolean.py @@ -1,4 +1,4 @@ -from typing import Iterable +from collections.abc import Iterable import pytest diff --git a/tests/predicates/test_collection.py b/tests/predicates/test_collection.py index f5daba2..5922262 100644 --- a/tests/predicates/test_collection.py +++ b/tests/predicates/test_collection.py @@ -1,6 +1,6 @@ -from typing import Container -from typing import Iterable -from typing import Sized +from collections.abc import Container +from collections.abc import Iterable +from collections.abc import Sized import pytest diff --git a/tests/predicates/test_generic.py b/tests/predicates/test_generic.py index abdccc3..baf6357 100644 --- a/tests/predicates/test_generic.py +++ b/tests/predicates/test_generic.py @@ -1,5 +1,3 @@ -from typing import Tuple -from typing import Type from typing import Union import pytest @@ -44,13 +42,17 @@ def test_repr_contains_bound_parameter(self): class TestOfType: @pytest.mark.parametrize("instance,types", [(1, int), (1, (int, float))]) def test_returns_true_for_instance_of_types( - self, instance: object, types: Union[Type, Tuple[Type, ...]] + self, + instance: object, + types: Union[type, tuple[type, ...]], ) -> None: assert generic.of_type(types)(instance) is True @pytest.mark.parametrize("instance,types", [(1, float), ("", (int, float))]) def test_returns_false_for_instance_of_other_type( - self, instance: object, types: Union[Type, Tuple[Type, ...]] + self, + instance: object, + types: Union[type, tuple[type, ...]], ) -> None: assert generic.of_type(types)(instance) is False diff --git a/tests/predicates/test_interval.py b/tests/predicates/test_interval.py index 24ba48f..59fb7f7 100644 --- a/tests/predicates/test_interval.py +++ b/tests/predicates/test_interval.py @@ -1,12 +1,11 @@ -from typing import Tuple - import pytest +from typing_extensions import TypeAlias from phantom.predicates import interval from .utils import assert_predicate_name_equals -Boundaries = Tuple[float, float] +Boundaries: TypeAlias = tuple[float, float] parametrize_inside = pytest.mark.parametrize( "value, boundaries", [ diff --git a/tests/pydantic/test_schemas.py b/tests/pydantic/test_schemas.py index 6ba7686..cebc39c 100644 --- a/tests/pydantic/test_schemas.py +++ b/tests/pydantic/test_schemas.py @@ -1,5 +1,3 @@ -import sys - import pydantic import pytest @@ -229,13 +227,6 @@ def test_formatted_phone_number_implements_schema(self): "format": "E.164", } - @pytest.mark.skipif( - sys.version_info < (3, 9), - reason=( - "Pydantic behavior oddly differs for Python 3.8 and below, where it " - "instead of using the class name, uses the name of the field as title." - ), - ) def test_sequence_not_str_implements_schema(self): assert DataModel.schema()["properties"]["sequence_not_str"] == { "title": "SequenceNotStr", diff --git a/tests/test_fn.py b/tests/test_fn.py index 858dc6e..506cfc7 100644 --- a/tests/test_fn.py +++ b/tests/test_fn.py @@ -1,12 +1,12 @@ from __future__ import annotations +from collections.abc import Sequence from functools import partial from operator import add from operator import attrgetter from operator import itemgetter from operator import mul from typing import Callable -from typing import Sequence from typing import TypeVar import pytest diff --git a/tests/test_fn.yaml b/tests/test_fn.yaml index ddc0621..3260122 100644 --- a/tests/test_fn.yaml +++ b/tests/test_fn.yaml @@ -24,7 +24,7 @@ out: | main:6: note: Revealed type is "def \(builtins\.str\*?\) -> builtins\.bool\*?" main:7: error: Argument 1 has incompatible type "int"; expected "str" \[arg-type\] - main:8: error: Argument 1 has incompatible type "List\[Never\]"; expected "str" \[arg-type\] + main:8: error: Argument 1 has incompatible type "list\[Never\]"; expected "str" \[arg-type\] main:9: note: Revealed type is "builtins.bool\*?" main:13: note: Revealed type is "builtins.int\*?" main:17: note: Revealed type is "builtins.str\*?"