diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index e8d4816..b995b7f 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -20,11 +20,11 @@ jobs: fail-fast: false matrix: python-version: - - '3.8' - '3.9' - '3.10' - '3.11' - '3.12' + - '3.13' steps: - name: "🗃 Cache" diff --git a/Makefile b/Makefile index b67a61d..8a3daf2 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ clean: .PHONY: install install: - poetry install --all-extras --with=dev + poetry install --sync --all-extras --with=dev .PHONY: lint lint: lint/ruff lint/mypy diff --git a/poetry.lock b/poetry.lock index bb09c3b..17dbc4e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -11,9 +11,6 @@ files = [ {file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"}, ] -[package.dependencies] -typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.9\""} - [[package]] name = "babel" version = "2.12.1" @@ -25,9 +22,6 @@ files = [ {file = "Babel-2.12.1.tar.gz", hash = "sha256:cc2d99999cd01d44420ae725a21c9e3711b3aadc7976d6147f622d8581963455"}, ] -[package.dependencies] -pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""} - [[package]] name = "black" version = "24.8.0" @@ -1654,5 +1648,5 @@ test = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-it [metadata] lock-version = "2.0" -python-versions = "^3.8.0" -content-hash = "a18b956343a1d3e4f8dbab194eea8ae36518acbb0c852ccc4e25554514821bb6" +python-versions = "^3.9.0" +content-hash = "b191d012f39c343bdbb1c50178e7d9644a3aad4119cecaebc46e90d00ea7abf8" diff --git a/pure_protobuf/_accumulators.py b/pure_protobuf/_accumulators.py index f5d00be..f16f52a 100644 --- a/pure_protobuf/_accumulators.py +++ b/pure_protobuf/_accumulators.py @@ -1,4 +1,5 @@ -from typing import Generic, Iterable, List, Optional, Type +from collections.abc import Iterable +from typing import Generic, Optional from pure_protobuf.interfaces._repr import ReprWithInner from pure_protobuf.interfaces._vars import MessageT, RecordT @@ -21,12 +22,12 @@ def __call__(self, accumulator: Optional[RecordT], other: Iterable[RecordT]) -> return accumulator -class AccumulateAppend(Accumulate[List[RecordT], RecordT]): +class AccumulateAppend(Accumulate[list[RecordT], RecordT]): def __call__( self, - accumulator: Optional[List[RecordT]], + accumulator: Optional[list[RecordT]], other: Iterable[RecordT], - ) -> List[RecordT]: + ) -> list[RecordT]: """Append all items from the `other` into the accumulator.""" if accumulator is None: accumulator = [] @@ -35,12 +36,12 @@ def __call__( class AccumulateMessages(Accumulate[MessageT, MessageT], ReprWithInner): - inner: Type[MessageT] + inner: type[MessageT] __slots__ = ("inner",) # noinspection PyProtocol - def __init__(self, inner: Type[MessageT]) -> None: + def __init__(self, inner: type[MessageT]) -> None: self.inner = inner def __call__(self, lhs: Optional[MessageT], rhs: Iterable[MessageT]) -> MessageT: diff --git a/pure_protobuf/_mergers.py b/pure_protobuf/_mergers.py index 02c94a9..98b21aa 100644 --- a/pure_protobuf/_mergers.py +++ b/pure_protobuf/_mergers.py @@ -1,4 +1,4 @@ -from typing import Generic, List, Optional +from typing import Generic, Optional from pure_protobuf._accumulators import AccumulateMessages from pure_protobuf.interfaces._repr import ReprWithInner @@ -18,12 +18,12 @@ def __call__(self, _lhs: Optional[FieldT], rhs: Optional[FieldT]) -> Optional[Fi return rhs -class MergeConcatenate(Merge[List[RecordT]], Generic[RecordT]): +class MergeConcatenate(Merge[list[RecordT]], Generic[RecordT]): def __call__( self, - lhs: Optional[List[RecordT]], - rhs: Optional[List[RecordT]], - ) -> Optional[List[RecordT]]: + lhs: Optional[list[RecordT]], + rhs: Optional[list[RecordT]], + ) -> Optional[list[RecordT]]: if lhs is None: return rhs if rhs is None: diff --git a/pure_protobuf/descriptors/_field.py b/pure_protobuf/descriptors/_field.py index b88fcf9..db6b62f 100644 --- a/pure_protobuf/descriptors/_field.py +++ b/pure_protobuf/descriptors/_field.py @@ -1,9 +1,8 @@ from __future__ import annotations from dataclasses import dataclass -from typing import TYPE_CHECKING, Any, Generic, Optional, Type, cast +from typing import TYPE_CHECKING, Annotated, Any, Generic, Optional, cast -from typing_extensions import Annotated from typing_extensions import get_args as get_type_args from typing_extensions import get_origin as get_type_origin @@ -64,7 +63,7 @@ class _FieldDescriptor(Generic[FieldT, RecordT]): @classmethod def from_attribute( cls, - message_type: Type[BaseMessage], + message_type: type[BaseMessage], attribute_hint: Any, ) -> Optional[_FieldDescriptor[Any, Any]]: """ diff --git a/pure_protobuf/descriptors/record.py b/pure_protobuf/descriptors/record.py index 8437b98..6e73ef9 100644 --- a/pure_protobuf/descriptors/record.py +++ b/pure_protobuf/descriptors/record.py @@ -1,8 +1,9 @@ from __future__ import annotations +from collections.abc import ByteString, Mapping from dataclasses import dataclass from enum import IntEnum -from typing import TYPE_CHECKING, Any, ByteString, ClassVar, Dict, Generic, Type +from typing import TYPE_CHECKING, Any, ClassVar, Generic from urllib.parse import ParseResult from typing_extensions import Self @@ -69,13 +70,13 @@ class RecordDescriptor(Generic[RecordT]): merge: Merge[RecordT] = MergeLastOneWins() """Merge two values of the same field from different messages. Only called in a message merger.""" - __PREDEFINED__: ClassVar[Dict[Any, RecordDescriptor]] + __PREDEFINED__: ClassVar[Mapping[Any, RecordDescriptor]] """Pre-defined descriptors for primitive types.""" @classmethod def _from_inner_type_hint( cls, - message_type: Type[BaseMessage], + message_type: type[BaseMessage], inner_hint: Any, ) -> RecordDescriptor[Any]: """ diff --git a/pure_protobuf/helpers/_dataclasses.py b/pure_protobuf/helpers/_dataclasses.py index 3a4f47c..e364a39 100644 --- a/pure_protobuf/helpers/_dataclasses.py +++ b/pure_protobuf/helpers/_dataclasses.py @@ -1,4 +1,4 @@ -"""Backwards compatibility for Python 3.8 and 3.9.""" +"""Backwards compatibility with Python 3.9.""" from sys import version_info diff --git a/pure_protobuf/helpers/_typing.py b/pure_protobuf/helpers/_typing.py index 06ae3cd..101aa0d 100644 --- a/pure_protobuf/helpers/_typing.py +++ b/pure_protobuf/helpers/_typing.py @@ -1,5 +1,5 @@ from collections.abc import Iterable -from typing import Any, List, Tuple, Union +from typing import Any, Union from typing_extensions import TypeGuard, get_args, get_origin @@ -22,7 +22,7 @@ def __repr__(self) -> str: # pragma: no cover DEFAULT = Sentinel() -def extract_repeated(hint: Any) -> Tuple[Any, TypeGuard[List]]: +def extract_repeated(hint: Any) -> tuple[Any, TypeGuard[list]]: """Extract a possible repeated flag.""" origin = get_origin(hint) if isinstance(origin, type) and (origin is Iterable or issubclass(origin, list)): @@ -30,7 +30,7 @@ def extract_repeated(hint: Any) -> Tuple[Any, TypeGuard[List]]: return hint, False -def extract_optional(hint: Any) -> Tuple[Any, bool]: +def extract_optional(hint: Any) -> tuple[Any, bool]: """Extract a possible optional flag.""" if get_origin(hint) is Union: cleaned_args = tuple(arg for arg in get_args(hint) if arg is not NoneType) diff --git a/pure_protobuf/helpers/datetime.py b/pure_protobuf/helpers/datetime.py index ef6fb8d..a5bc782 100644 --- a/pure_protobuf/helpers/datetime.py +++ b/pure_protobuf/helpers/datetime.py @@ -1,8 +1,7 @@ from math import modf -from typing import Tuple -def split_seconds(seconds: float) -> Tuple[int, int]: +def split_seconds(seconds: float) -> tuple[int, int]: """Split seconds into whole seconds and nanoseconds.""" fraction, whole = modf(seconds) return int(whole), int(fraction * 1_000_000_000.0) diff --git a/pure_protobuf/helpers/itertools.py b/pure_protobuf/helpers/itertools.py index b523abc..da06241 100644 --- a/pure_protobuf/helpers/itertools.py +++ b/pure_protobuf/helpers/itertools.py @@ -1,4 +1,5 @@ -from typing import Callable, Generic, Iterator, TypeVar +from collections.abc import Iterator +from typing import Callable, Generic, TypeVar from typing_extensions import ParamSpec diff --git a/pure_protobuf/interfaces/accumulate.py b/pure_protobuf/interfaces/accumulate.py index 5001660..60a4591 100644 --- a/pure_protobuf/interfaces/accumulate.py +++ b/pure_protobuf/interfaces/accumulate.py @@ -1,5 +1,6 @@ from abc import abstractmethod -from typing import Iterable, Optional, Protocol +from collections.abc import Iterable +from typing import Optional, Protocol from pure_protobuf.interfaces._repr import Repr from pure_protobuf.interfaces._vars import FieldT, RecordT_contra diff --git a/pure_protobuf/interfaces/read.py b/pure_protobuf/interfaces/read.py index e16a4c2..a2cc435 100644 --- a/pure_protobuf/interfaces/read.py +++ b/pure_protobuf/interfaces/read.py @@ -1,5 +1,6 @@ from abc import abstractmethod -from typing import IO, Iterator, Protocol +from collections.abc import Iterator +from typing import IO, Protocol from pure_protobuf.interfaces._repr import Repr from pure_protobuf.interfaces._vars import RecordT_co diff --git a/pure_protobuf/io/struct_.py b/pure_protobuf/io/struct_.py index 6bccb38..5ffade3 100644 --- a/pure_protobuf/io/struct_.py +++ b/pure_protobuf/io/struct_.py @@ -1,5 +1,6 @@ +from collections.abc import Iterator from struct import Struct -from typing import IO, Generic, Iterator +from typing import IO, Generic from pure_protobuf.helpers.io import read_checked from pure_protobuf.interfaces._repr import ReprWithInner diff --git a/pure_protobuf/io/url.py b/pure_protobuf/io/url.py index 3e2004f..141c365 100644 --- a/pure_protobuf/io/url.py +++ b/pure_protobuf/io/url.py @@ -1,6 +1,7 @@ """Reading and writing parsed URLs.""" -from typing import IO, Iterator +from collections.abc import Iterator +from typing import IO from urllib.parse import ParseResult, urlparse, urlunparse from pure_protobuf.interfaces.read import Read diff --git a/pure_protobuf/io/varint.py b/pure_protobuf/io/varint.py index 21a8204..9610085 100644 --- a/pure_protobuf/io/varint.py +++ b/pure_protobuf/io/varint.py @@ -6,10 +6,11 @@ """ +from collections.abc import Iterator from enum import IntEnum from itertools import count from sys import byteorder -from typing import IO, Iterator, Type, TypeVar +from typing import IO, TypeVar from pure_protobuf.exceptions import IncorrectValueError from pure_protobuf.helpers.io import read_byte_checked @@ -127,7 +128,7 @@ class ReadEnum(Read[EnumT]): __slots__ = ("enum_type",) # noinspection PyProtocol - def __init__(self, enum_type: Type[EnumT]) -> None: + def __init__(self, enum_type: type[EnumT]) -> None: self.enum_type = enum_type def __call__(self, io: IO[bytes]) -> Iterator[EnumT]: diff --git a/pure_protobuf/io/wrappers.py b/pure_protobuf/io/wrappers.py index 2ab631b..4268e2e 100644 --- a/pure_protobuf/io/wrappers.py +++ b/pure_protobuf/io/wrappers.py @@ -1,5 +1,6 @@ +from collections.abc import Iterable, Iterator from io import BytesIO -from typing import IO, Generic, Iterable, Iterator, Optional, cast +from typing import IO, Generic, Optional, cast from pure_protobuf.exceptions import UnexpectedWireTypeError from pure_protobuf.interfaces._repr import ReprWithInner diff --git a/pure_protobuf/message.py b/pure_protobuf/message.py index fc2f8b8..cf4867b 100644 --- a/pure_protobuf/message.py +++ b/pure_protobuf/message.py @@ -1,8 +1,9 @@ from __future__ import annotations from abc import ABC +from collections.abc import Mapping from io import BytesIO -from typing import IO, Any, ClassVar, Dict, Tuple +from typing import IO, Any, ClassVar from typing_extensions import Self @@ -36,10 +37,10 @@ class BaseMessage(ABC): __slots__ = () - __PROTOBUF_FIELDS_BY_NUMBER__: ClassVar[Dict[int, Tuple[str, _FieldDescriptor]]] - __PROTOBUF_FIELDS_BY_NAME__: ClassVar[Dict[str, _FieldDescriptor]] + __PROTOBUF_FIELDS_BY_NUMBER__: ClassVar[dict[int, tuple[str, _FieldDescriptor]]] + __PROTOBUF_FIELDS_BY_NAME__: ClassVar[dict[str, _FieldDescriptor]] - __PROTOBUF_SKIP__: ClassVar[Dict[WireType, Skip]] = { + __PROTOBUF_SKIP__: ClassVar[Mapping[WireType, Skip]] = { WireType.VARINT: skip_varint, WireType.I64: skip_fixed_64, WireType.LEN: skip_bytes, @@ -53,7 +54,7 @@ def __init_subclass__(cls) -> None: # noqa: D105 cls.__PROTOBUF_FIELDS_BY_NUMBER__ = {} cls.__PROTOBUF_FIELDS_BY_NAME__ = {} - type_hints: Dict[str, Any] = get_annotations(cls, eval_str=True) + type_hints: dict[str, Any] = get_annotations(cls, eval_str=True) for name, hint in type_hints.items(): descriptor = _FieldDescriptor.from_attribute(cls, hint) if descriptor is not None: @@ -67,7 +68,7 @@ def __init_subclass__(cls) -> None: # noqa: D105 def read_from(cls, io: IO[bytes]) -> Self: """Read a message from the file.""" - values: Dict[str, Any] = {} + values: dict[str, Any] = {} while True: try: tag = Tag.read_from(io) diff --git a/pure_protobuf/one_of.py b/pure_protobuf/one_of.py index cff29a5..954be6b 100644 --- a/pure_protobuf/one_of.py +++ b/pure_protobuf/one_of.py @@ -1,6 +1,7 @@ from __future__ import annotations -from typing import Any, Callable, Generic, List, MutableMapping, Optional, Tuple, Type, TypeVar +from collections.abc import MutableMapping +from typing import Any, Callable, Generic, Optional, TypeVar from pure_protobuf.message import BaseMessage @@ -22,7 +23,7 @@ def __init__(self) -> None: A [`Field`][pure_protobuf.annotations.Field] then should be assigned to the group via the [`one_of`][pure_protobuf.annotations.Field.one_of] parameter. """ - self._fields: List[Tuple[int, str]] = [] + self._fields: list[tuple[int, str]] = [] def _add_field(self, number: int, name: str) -> None: self._fields.append((number, name)) @@ -41,7 +42,7 @@ def _keep_attribute(self, message: BaseMessage, keep_number: int) -> None: if other_number != keep_number: super(BaseMessage, message).__setattr__(other_name, None) - def __get__(self, instance: Any, type_: Type[Any]) -> Optional[OneOfT]: # noqa: D105 + def __get__(self, instance: Any, type_: type[Any]) -> Optional[OneOfT]: # noqa: D105 if not isinstance(instance, BaseMessage): # Allows passing the descriptor by reference, and we need to move the descriptor from # the corresponding annotation. diff --git a/pure_protobuf/well_known.py b/pure_protobuf/well_known.py index 8e58c00..929a3f1 100644 --- a/pure_protobuf/well_known.py +++ b/pure_protobuf/well_known.py @@ -2,14 +2,13 @@ from __future__ import annotations +from collections.abc import Mapping from dataclasses import dataclass from datetime import datetime, timedelta, timezone from io import BytesIO -from typing import Any, Mapping, Optional, Type, cast +from typing import Annotated, Any, Optional, cast from urllib.parse import ParseResult -from typing_extensions import Annotated - from pure_protobuf.annotations import Field from pure_protobuf.helpers._dataclasses import KW_ONLY, SLOTS from pure_protobuf.helpers.datetime import split_seconds, unsplit_seconds @@ -112,5 +111,5 @@ def into_message( locals=locals_, globals=globals_, ) - class_ = cast(Type[BaseMessage], getattr(module, self.type_url.path)) + class_ = cast(type[BaseMessage], getattr(module, self.type_url.path)) return class_.read_from(BytesIO(self.value)) diff --git a/pyproject.toml b/pyproject.toml index e3423f4..604e4e1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,11 +21,11 @@ classifiers = [ "Topic :: Software Development :: Libraries", "Topic :: Software Development :: Libraries :: Python Modules", "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", "License :: OSI Approved :: MIT License", "Typing :: Typed", ] @@ -36,7 +36,7 @@ build-backend = "poetry_dynamic_versioning.backend" [tool.poetry.dependencies] get-annotations = { version = "^0.1.2", python = "<3.10" } -python = "^3.8.0" +python = "^3.9.0" typing-extensions = "^4.4.0" [tool.poetry.group.dev] @@ -95,11 +95,11 @@ exclude_lines = [ [tool.black] line-length = 120 -target-version = ["py38", "py39", "py310", "py311", "py312"] +target-version = ["py39", "py310", "py311", "py312", "py313"] [tool.ruff] line-length = 120 -target-version = "py38" +target-version = "py39" [tool.ruff.lint] select = [ diff --git a/tests/conftest.py b/tests/conftest.py index eaf0f67..c166b34 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,15 +1,15 @@ from io import BytesIO -from typing import Callable, Dict, Tuple +from typing import Callable from pytest import fixture @fixture -def bytes_io() -> Callable[[bytes], Callable[[], Tuple[Tuple[BytesIO], Dict]]]: - def make_setup(bytes_: bytes) -> Callable[[], Tuple[Tuple[BytesIO], Dict]]: +def bytes_io() -> Callable[[bytes], Callable[[], tuple[tuple[BytesIO], dict]]]: + def make_setup(bytes_: bytes) -> Callable[[], tuple[tuple[BytesIO], dict]]: """Make `setup` function for `pytest-benchmark`.""" - def setup() -> Tuple[Tuple[BytesIO], Dict]: + def setup() -> tuple[tuple[BytesIO], dict]: return (BytesIO(bytes_),), {} return setup diff --git a/tests/definitions.py b/tests/definitions.py index ba1a55b..e1c03df 100644 --- a/tests/definitions.py +++ b/tests/definitions.py @@ -4,9 +4,9 @@ from dataclasses import dataclass from enum import IntEnum -from typing import Optional +from typing import Annotated, Optional -from typing_extensions import Annotated, Self +from typing_extensions import Self from pure_protobuf.annotations import Field from pure_protobuf.message import BaseMessage diff --git a/tests/descriptors/test_field.py b/tests/descriptors/test_field.py index c943259..2aaf301 100644 --- a/tests/descriptors/test_field.py +++ b/tests/descriptors/test_field.py @@ -1,7 +1,7 @@ -from typing import Any, ByteString, List, Optional +from collections.abc import ByteString +from typing import Annotated, Any, Optional from pytest import mark, raises -from typing_extensions import Annotated from pure_protobuf.annotations import Field, uint from pure_protobuf.descriptors._field import _FieldDescriptor @@ -35,8 +35,8 @@ def test_from_inner_hint_incorrect(hint: Any) -> None: [ (Annotated[int, Field(1)], 150, b"\x08\x96\x01"), (Annotated[uint, Field(1)], 150, b"\x08\x96\x01"), - (Annotated[List[int], Field(1)], [1, 150, 2], b"\x0a\x04\x01\x96\x01\x02"), - (Annotated[List[bytes], Field(1)], [b"B", b"C"], b"\x0a\x01B\x0a\x01C"), + (Annotated[list[int], Field(1)], [1, 150, 2], b"\x0a\x04\x01\x96\x01\x02"), + (Annotated[list[bytes], Field(1)], [b"B", b"C"], b"\x0a\x01B\x0a\x01C"), (Annotated[Optional[bytes], Field(1)], None, b""), (Annotated[ByteString, Field(1)], b"Testing", b"\x0a\x07Testing"), (Annotated[ExampleEnum, Field(1)], ExampleEnum.BAR, b"\x08\x02"), @@ -45,7 +45,7 @@ def test_from_inner_hint_incorrect(hint: Any) -> None: RecursiveMessage(payload=1, inner=RecursiveMessage(payload=2)), b"\xd2\x02\x06\x08\x01\x12\x02\x08\x02", ), - (Annotated[List[int], Field(1, packed=False)], [1, 2], b"\x08\x01\x08\x02"), + (Annotated[list[int], Field(1, packed=False)], [1, 2], b"\x08\x01\x08\x02"), (Annotated[int, Field(1)], -2, b"\x08\xfe\xff\xff\xff\xff\xff\xff\xff\xff\x01"), # TODO: cyclic dependencies, https://github.com/eigenein/protobuf/issues/108. ], diff --git a/tests/descriptors/test_record.py b/tests/descriptors/test_record.py index 05c1d7d..e22f48e 100644 --- a/tests/descriptors/test_record.py +++ b/tests/descriptors/test_record.py @@ -1,5 +1,5 @@ from io import BytesIO -from typing import Any, Tuple +from typing import Any from urllib.parse import ParseResult from pytest import mark, raises @@ -18,7 +18,7 @@ @mark.parametrize( "inner_hint", [ - Tuple[int, str], + tuple[int, str], ], ) def test_from_inner_hint_unsupported(inner_hint: Any) -> None: diff --git a/tests/helpers/test_typing.py b/tests/helpers/test_typing.py index 2d3b41b..874e020 100644 --- a/tests/helpers/test_typing.py +++ b/tests/helpers/test_typing.py @@ -1,4 +1,5 @@ -from typing import Any, Iterable, List, Optional, Union +from collections.abc import Iterable +from typing import Any, Optional, Union from pytest import mark @@ -21,7 +22,7 @@ def test_extract_optional(hint: Any, expected_flag: bool, expected_inner: Any) - ("hint", "expected_flag", "expected_inner"), [ (int, False, int), - (List[int], True, int), + (list[int], True, int), (Iterable[int], True, int), ], ) diff --git a/tests/message/test_dataclass.py b/tests/message/test_dataclass.py index 619fa77..d7a50ae 100644 --- a/tests/message/test_dataclass.py +++ b/tests/message/test_dataclass.py @@ -1,7 +1,5 @@ from dataclasses import dataclass, field -from typing import List, Optional - -from typing_extensions import Annotated +from typing import Annotated, Optional from pure_protobuf.annotations import Field, ZigZagInt, uint from pure_protobuf.message import BaseMessage @@ -94,7 +92,7 @@ def test_merge_embedded_messages_repeated() -> None: @dataclass class Inner(BaseMessage): - foo: Annotated[Optional[List[int]], Field(1, packed=False)] = field(default=None) + foo: Annotated[Optional[list[int]], Field(1, packed=False)] = field(default=None) @dataclass class Outer(BaseMessage): @@ -146,7 +144,7 @@ def test_read_unpacked_repeated_as_packed() -> None: @dataclass class Test(BaseMessage): - foo: Annotated[List[int], Field(1, packed=True)] + foo: Annotated[list[int], Field(1, packed=True)] assert Test.loads(b"\x08\x01\x08\x02") == Test(foo=[1, 2]) @@ -162,7 +160,7 @@ def test_read_packed_repeated_as_unpacked() -> None: @dataclass class Test(BaseMessage): - foo: Annotated[List[int], Field(1, packed=False)] + foo: Annotated[list[int], Field(1, packed=False)] assert Test.loads(b"\x0a\x04\x01\x96\x01\x02") == Test( foo=[1, 150, 2], @@ -176,7 +174,7 @@ class Child(BaseMessage): @dataclass class Parent(BaseMessage): - children: Annotated[List[Child], Field(1)] + children: Annotated[list[Child], Field(1)] message = Parent(children=[Child(payload=42), Child(payload=43)]) encoded = bytes(message) @@ -219,7 +217,7 @@ def test_concatenated_packed_repeated() -> None: @dataclass class Message(BaseMessage): - field: Annotated[List[int], Field(1, packed=True)] + field: Annotated[list[int], Field(1, packed=True)] part_1 = bytes(Message(field=[42, 43])) part_2 = bytes(Message(field=[100500, 100501])) diff --git a/tests/message/test_pydantic.py b/tests/message/test_pydantic.py index 8288dcb..f5fa412 100644 --- a/tests/message/test_pydantic.py +++ b/tests/message/test_pydantic.py @@ -1,8 +1,7 @@ from io import BytesIO -from typing import ClassVar, Optional +from typing import Annotated, ClassVar, Optional from pydantic import BaseModel -from typing_extensions import Annotated from pure_protobuf.annotations import Field, ZigZagInt from pure_protobuf.message import BaseMessage diff --git a/tests/test_docs.py b/tests/test_docs.py index 04a2725..12e6c43 100644 --- a/tests/test_docs.py +++ b/tests/test_docs.py @@ -1,10 +1,11 @@ """Tests code snippets in the `README.md` and `docs`.""" import re +from collections.abc import Iterator from itertools import chain from pathlib import Path from textwrap import dedent -from typing import Iterator, NamedTuple +from typing import NamedTuple from pytest import mark, param diff --git a/tests/test_message.py b/tests/test_message.py index 9e0ab44..7f6433e 100644 --- a/tests/test_message.py +++ b/tests/test_message.py @@ -1,7 +1,5 @@ from dataclasses import dataclass -from typing import ClassVar, Optional - -from typing_extensions import Annotated +from typing import Annotated, ClassVar, Optional from pure_protobuf.annotations import Field from pure_protobuf.message import BaseMessage diff --git a/tests/test_well_known.py b/tests/test_well_known.py index cac09a2..4b832f5 100644 --- a/tests/test_well_known.py +++ b/tests/test_well_known.py @@ -1,8 +1,7 @@ from dataclasses import dataclass +from typing import Annotated from urllib.parse import urlunparse -from typing_extensions import Annotated - from pure_protobuf.annotations import Field from pure_protobuf.message import BaseMessage from pure_protobuf.well_known import Any_