From 555ca3989a32c65df393efe7202561074d702802 Mon Sep 17 00:00:00 2001 From: Hal Blackburn Date: Sun, 2 Feb 2025 09:26:56 +0000 Subject: [PATCH 1/2] feat: define all the types we use in denokv._pycompat.typing This allows us to import all type annotations/types/functions from here, rather than typing or typing_extensions, which lets us handle the differences between them in one place, without needing if TYPE_CHECKING everywhere. --- pyproject.toml | 1 + src/denokv/_pycompat/dataclasses.py | 17 ++- src/denokv/_pycompat/typing.py | 178 +++++++++++++++++++++++++++- 3 files changed, 194 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index dc4f043..ac52135 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -123,4 +123,5 @@ omit = [ exclude_also = [ "if TYPE_CHECKING:", "^\\s*def .+: [.]{3}$", # def foo(): ... (... instead of pass) + "^\\s*assert_never\\(.*\\)$", # unreachable assertion, expected to not execute ] diff --git a/src/denokv/_pycompat/dataclasses.py b/src/denokv/_pycompat/dataclasses.py index c9482d9..3767436 100644 --- a/src/denokv/_pycompat/dataclasses.py +++ b/src/denokv/_pycompat/dataclasses.py @@ -5,7 +5,7 @@ from dataclasses import dataclass from dataclasses import fields as dataclass_fields from typing import Literal -from typing import TypedDict +from typing import TypedDict # avoid circular reference with _pycompat.typing class NoArg(TypedDict): @@ -27,6 +27,21 @@ def slots_if310() -> SlotsTrue: return SlotsTrue(slots=True) +class KwOnly(TypedDict): + kw_only: Literal[True] + + +if sys.version_info < (3, 10): + + def kw_only_if310() -> NoArg: + return NoArg() + +else: + + def kw_only_if310() -> KwOnly: + return KwOnly(kw_only=True) + + @dataclass class FrozenAfterInitDataclass: """A mixin for dataclasses that disallows changing fields after init. diff --git a/src/denokv/_pycompat/typing.py b/src/denokv/_pycompat/typing.py index e80a179..c2f2e47 100644 --- a/src/denokv/_pycompat/typing.py +++ b/src/denokv/_pycompat/typing.py @@ -1,4 +1,167 @@ -from typing import TYPE_CHECKING +""" +Runtime comparability for typing things that come from typing_extensions. + +We import all type annotations/types/functions from here, rather than typing or +typing_extensions in order to handle the differences between them in one place, +without needing if TYPE_CHECKING everywhere. +""" + +from __future__ import annotations + +from dataclasses import dataclass +from dataclasses import field +from typing import IO as IO +from typing import TYPE_CHECKING as TYPE_CHECKING + +# Everything that exist in typing >=py39 except: +# - ByteString (deprecated) +# - overload (ruff does not recognise it when re-exported) +# - Literal (ruff does not recognise it when re-exported) +# - Handled below due to runtime differences: +# - TypeVar +from typing import AbstractSet as AbstractSet +from typing import Annotated as Annotated +from typing import Any as Any +from typing import AnyStr as AnyStr +from typing import AsyncContextManager as AsyncContextManager +from typing import AsyncGenerator as AsyncGenerator +from typing import AsyncIterable as AsyncIterable +from typing import AsyncIterator as AsyncIterator +from typing import Awaitable as Awaitable +from typing import BinaryIO as BinaryIO +from typing import Callable as Callable +from typing import ChainMap as ChainMap +from typing import ClassVar as ClassVar +from typing import Collection as Collection +from typing import Container as Container +from typing import ContextManager as ContextManager +from typing import Coroutine as Coroutine +from typing import Counter as Counter +from typing import DefaultDict as DefaultDict +from typing import Deque as Deque +from typing import Dict as Dict +from typing import Final as Final +from typing import ForwardRef as ForwardRef +from typing import FrozenSet as FrozenSet +from typing import Generator as Generator +from typing import Generic as Generic +from typing import Hashable as Hashable +from typing import ItemsView as ItemsView +from typing import Iterable as Iterable +from typing import Iterator as Iterator +from typing import KeysView as KeysView +from typing import List as List +from typing import Mapping as Mapping +from typing import MappingView as MappingView +from typing import Match as Match +from typing import MutableMapping as MutableMapping +from typing import MutableSequence as MutableSequence +from typing import MutableSet as MutableSet +from typing import NamedTuple as NamedTuple +from typing import NewType as NewType +from typing import NoReturn as NoReturn +from typing import Optional as Optional +from typing import OrderedDict as OrderedDict +from typing import Pattern as Pattern +from typing import Protocol as Protocol +from typing import Reversible as Reversible +from typing import Sequence as Sequence +from typing import Set as Set +from typing import Sized as Sized +from typing import SupportsAbs as SupportsAbs +from typing import SupportsBytes as SupportsBytes +from typing import SupportsComplex as SupportsComplex +from typing import SupportsFloat as SupportsFloat +from typing import SupportsIndex as SupportsIndex +from typing import SupportsInt as SupportsInt +from typing import SupportsRound as SupportsRound +from typing import Text as Text +from typing import TextIO as TextIO +from typing import Tuple as Tuple +from typing import Type as Type +from typing import TypedDict as TypedDict +from typing import Union as Union +from typing import ValuesView as ValuesView +from typing import cast as cast +from typing import final as final +from typing import get_args as get_args +from typing import get_origin as get_origin +from typing import get_type_hints as get_type_hints +from typing import no_type_check as no_type_check +from typing import no_type_check_decorator as no_type_check_decorator +from typing import runtime_checkable as runtime_checkable + +if TYPE_CHECKING: + from typing_extensions import Never as Never + from typing_extensions import Self as Self + from typing_extensions import TypeAlias as TypeAlias + from typing_extensions import TypeGuard as TypeGuard + from typing_extensions import TypeIs as TypeIs + from typing_extensions import TypeVarTuple as TypeVarTuple + from typing_extensions import Unpack as Unpack +else: + Never = "Never" + ParamSpec = "ParamSpec" + Self = "Self" + TypeAlias = "TypeAlias" + TypeGuard = "TypeGuard" + TypeIs = "TypeIs" + # TypeVarTuple = "TypeVarTuple" + # Unpack = "Unpack" + +if TYPE_CHECKING: + from typing_extensions import TypeVar as TypeVar +else: + from typing import TypeVar as _TypeVar + + def TypeVar( + name: str, + *constraints: Any, + bound: Any | None = None, + covariant: bool = False, + contravariant: bool = False, + default: Any = ..., + infer_variance: bool = False, + ) -> TypeVar: + return _TypeVar( + name, *constraints, covariant=covariant, contravariant=contravariant + ) + + +_T = TypeVar("_T") + +if TYPE_CHECKING: + from typing_extensions import TypeVarTuple as TypeVarTuple +else: + + @dataclass + class TypeVarTuple: + name: str + default: Any = field(default=None) + + +if TYPE_CHECKING: + from typing_extensions import ParamSpec as ParamSpec +else: + from denokv._pycompat.dataclasses import kw_only_if310 + + @dataclass + class ParamSpec: + name: str + bound: type[Any] | str | None = field(default=None, **kw_only_if310()) + contravariant: bool = field(default=False, **kw_only_if310()) + covariant: bool = field(default=False, **kw_only_if310()) + default: Any = field(default=None, **kw_only_if310()) + + +if TYPE_CHECKING: + from typing_extensions import Unpack as Unpack +else: + + @dataclass + class Unpack(Generic[_T]): + pass + if TYPE_CHECKING: from typing_extensions import override as override @@ -6,3 +169,16 @@ def override(method, /): return method + + +def assert_never(value: Never, /) -> Never: + """Assert to the type checker that a line of code is unreachable.""" + raise AssertionError(f"Expected code to be unreachable, but got: {value!r}") + + +if TYPE_CHECKING: + from typing_extensions import assert_type as assert_type +else: + + def assert_type(val: _T, typ: Any, /) -> _T: + pass From 89f6ad55c49b809341f23de6a7d59c00c3cc137d Mon Sep 17 00:00:00 2001 From: Hal Blackburn Date: Sun, 2 Feb 2025 10:24:50 +0000 Subject: [PATCH 2/2] refactor: use denokv._pycompat.typing everywhere --- src/denokv/_pycompat/enum.py | 6 +-- src/denokv/_rfc3339.py | 6 +-- src/denokv/auth.py | 6 +-- src/denokv/backoff.py | 10 ++-- src/denokv/datapath.py | 92 ++++++++++++-------------------- src/denokv/errors.py | 3 +- src/denokv/kv.py | 53 ++++++++---------- src/denokv/kv_keys.py | 67 +++++++++-------------- src/denokv/result.py | 42 +++++++-------- test/advance_time.py | 7 +-- test/denokv_testing.py | 14 ++--- test/pycompat/test_protobuf.py | 3 +- test/test_auth.py | 12 ++--- test/test_datapath.py | 12 ++--- test/test_kv.py | 18 +++---- test/test_kv_keys__kvkey.py | 6 +-- test/test_kv_keys__kvkeyrange.py | 2 +- test/test_result.py | 14 ++--- 18 files changed, 157 insertions(+), 216 deletions(-) diff --git a/src/denokv/_pycompat/enum.py b/src/denokv/_pycompat/enum.py index fe84abe..36b38ff 100644 --- a/src/denokv/_pycompat/enum.py +++ b/src/denokv/_pycompat/enum.py @@ -4,11 +4,9 @@ from enum import EnumMeta from enum import Flag from enum import IntFlag -from typing import TYPE_CHECKING -from typing import Iterator -if TYPE_CHECKING: - from typing_extensions import Self +from denokv._pycompat.typing import Iterator +from denokv._pycompat.typing import Self class ContainsValueEnumMeta(EnumMeta): diff --git a/src/denokv/_rfc3339.py b/src/denokv/_rfc3339.py index 46f8edc..7e08f32 100644 --- a/src/denokv/_rfc3339.py +++ b/src/denokv/_rfc3339.py @@ -4,10 +4,10 @@ from datetime import datetime from datetime import timedelta from datetime import timezone -from typing import Final -from typing import TypedDict -from typing import cast +from denokv._pycompat.typing import Final +from denokv._pycompat.typing import TypedDict +from denokv._pycompat.typing import cast from denokv.result import Err from denokv.result import Ok from denokv.result import Result diff --git a/src/denokv/auth.py b/src/denokv/auth.py index 5dadf21..a18219e 100644 --- a/src/denokv/auth.py +++ b/src/denokv/auth.py @@ -2,9 +2,6 @@ from dataclasses import dataclass from datetime import datetime -from typing import Mapping -from typing import Sequence -from typing import cast from uuid import UUID import aiohttp @@ -13,6 +10,9 @@ from denokv._pycompat.dataclasses import slots_if310 from denokv._pycompat.enum import StrEnum +from denokv._pycompat.typing import Mapping +from denokv._pycompat.typing import Sequence +from denokv._pycompat.typing import cast from denokv._rfc3339 import parse_rfc3339_datetime from denokv.errors import DenoKvError from denokv.errors import DenoKvValidationError diff --git a/src/denokv/backoff.py b/src/denokv/backoff.py index 1c6270c..61380f8 100644 --- a/src/denokv/backoff.py +++ b/src/denokv/backoff.py @@ -6,14 +6,12 @@ from dataclasses import dataclass from enum import IntEnum from itertools import count -from typing import TYPE_CHECKING -from typing import Callable -from typing import Iterable -from typing import Iterator from typing import Literal -if TYPE_CHECKING: - from typing_extensions import TypeAlias +from denokv._pycompat.typing import Callable +from denokv._pycompat.typing import Iterable +from denokv._pycompat.typing import Iterator +from denokv._pycompat.typing import TypeAlias Backoff: TypeAlias = Iterable[float] """ diff --git a/src/denokv/datapath.py b/src/denokv/datapath.py index 94ba7ab..fd8372a 100644 --- a/src/denokv/datapath.py +++ b/src/denokv/datapath.py @@ -9,17 +9,7 @@ from dataclasses import dataclass from enum import Enum from enum import auto -from typing import TYPE_CHECKING -from typing import Awaitable -from typing import Callable -from typing import Container -from typing import Final -from typing import Protocol -from typing import Type -from typing import TypedDict -from typing import Union from typing import overload -from typing import runtime_checkable import aiohttp import aiohttp.client_exceptions @@ -34,6 +24,19 @@ from denokv._datapath_pb2 import SnapshotReadOutput from denokv._datapath_pb2 import SnapshotReadStatus from denokv._datapath_pb2 import ValueEncoding +from denokv._pycompat.typing import Awaitable +from denokv._pycompat.typing import Callable +from denokv._pycompat.typing import Container +from denokv._pycompat.typing import Final +from denokv._pycompat.typing import Protocol +from denokv._pycompat.typing import Type +from denokv._pycompat.typing import TypeAlias +from denokv._pycompat.typing import TypedDict +from denokv._pycompat.typing import TypeGuard +from denokv._pycompat.typing import TypeVar +from denokv._pycompat.typing import Union +from denokv._pycompat.typing import Unpack +from denokv._pycompat.typing import runtime_checkable from denokv.auth import ConsistencyLevel from denokv.auth import DatabaseMetadata from denokv.auth import EndpointInfo @@ -45,55 +48,30 @@ KV_KEY_PIECE_TYPES: Final = (str, bytes, int, float, bool) -if TYPE_CHECKING: - from typing_extensions import TypeAlias - from typing_extensions import TypeGuard - from typing_extensions import TypeVar - from typing_extensions import Unpack +KvKeyPiece: TypeAlias = Union[str, bytes, int, float, bool] +KvKeyPieceT = TypeVar("KvKeyPieceT", bound=KvKeyPiece, default=KvKeyPiece) - KvKeyPiece: TypeAlias = Union[str, bytes, int, float, bool] - KvKeyPieceT = TypeVar("KvKeyPieceT", bound=KvKeyPiece, default=KvKeyPiece) - - KvKeyTuple: TypeAlias = tuple[KvKeyPieceT, ...] - KvKeyTupleT = TypeVar("KvKeyTupleT", bound=KvKeyTuple, default=KvKeyTuple) - KvKeyTupleT_co = TypeVar( - "KvKeyTupleT_co", bound=KvKeyTuple, default=KvKeyTuple, covariant=True - ) - - @runtime_checkable - class KvKeyEncodable(Protocol): - __slots__ = () - - def kv_key_bytes(self) -> bytes: ... +KvKeyTuple: TypeAlias = tuple[KvKeyPieceT, ...] +KvKeyTupleT = TypeVar("KvKeyTupleT", bound=KvKeyTuple, default=KvKeyTuple) +KvKeyTupleT_co = TypeVar( + "KvKeyTupleT_co", bound=KvKeyTuple, default=KvKeyTuple, covariant=True +) - KvKeyEncodableT = TypeVar("KvKeyEncodableT", bound=KvKeyEncodable) - AnyKvKey: TypeAlias = "KvKeyEncodable | KvKeyTuple" - AnyKvKeyT = TypeVar("AnyKvKeyT", bound=AnyKvKey, default=AnyKvKey) - AnyKvKeyT_co = TypeVar( - "AnyKvKeyT_co", bound=AnyKvKey, default=AnyKvKey, covariant=True - ) - AnyKvKeyT_con = TypeVar( - "AnyKvKeyT_con", bound=AnyKvKey, default=AnyKvKey, contravariant=True - ) -else: - from typing import TypeVar - KvKeyPiece: TypeAlias = "str | bytes | int | float | bool" - KvKeyPieceT = TypeVar("KvKeyPieceT", bound=KvKeyPiece) +@runtime_checkable +class KvKeyEncodable(Protocol): + __slots__ = () - KvKeyTuple: TypeAlias = tuple[KvKeyPieceT, ...] - KvKeyTupleT = TypeVar("KvKeyTupleT", bound=KvKeyTuple) - KvKeyTupleT_co = TypeVar("KvKeyTupleT_co", bound=KvKeyTuple, covariant=True) + def kv_key_bytes(self) -> bytes: ... - @runtime_checkable - class KvKeyEncodable(Protocol): - def kv_key_bytes(self) -> bytes: ... - KvKeyEncodableT = TypeVar("KvKeyEncodableT", bound=KvKeyEncodable) - AnyKvKey: TypeAlias = "KvKeyEncodable | KvKeyTuple" - AnyKvKeyT = TypeVar("AnyKvKeyT", bound=AnyKvKey) - AnyKvKeyT_co = TypeVar("AnyKvKeyT", bound=AnyKvKey, covariant=True) - AnyKvKeyT_con = TypeVar("AnyKvKeyT_con", bound=AnyKvKey, contravariant=True) +KvKeyEncodableT = TypeVar("KvKeyEncodableT", bound=KvKeyEncodable) +AnyKvKey: TypeAlias = Union[KvKeyEncodable, KvKeyTuple] +AnyKvKeyT = TypeVar("AnyKvKeyT", bound=AnyKvKey, default=AnyKvKey) +AnyKvKeyT_co = TypeVar("AnyKvKeyT_co", bound=AnyKvKey, default=AnyKvKey, covariant=True) +AnyKvKeyT_con = TypeVar( + "AnyKvKeyT_con", bound=AnyKvKey, default=AnyKvKey, contravariant=True +) _T = TypeVar("_T") @@ -196,9 +174,9 @@ class RequestUnsuccessful(DataPathDenoKvError): pass -DataPathError: TypeAlias = ( - "EndpointNotUsable | RequestUnsuccessful | ResponseUnsuccessful | ProtocolViolation" -) +DataPathError: TypeAlias = Union[ + EndpointNotUsable, RequestUnsuccessful, ResponseUnsuccessful, ProtocolViolation +] class _DataPathRequestKind(Enum): @@ -300,7 +278,7 @@ async def _response_body_bytes(response: aiohttp.ClientResponse) -> Ok[bytes]: return Ok(await response.read()) -SnapshotReadResult: TypeAlias = "Result[SnapshotReadOutput, DataPathError]" +SnapshotReadResult: TypeAlias = Result[SnapshotReadOutput, DataPathError] async def snapshot_read( diff --git a/src/denokv/errors.py b/src/denokv/errors.py index 199be0f..83734a0 100644 --- a/src/denokv/errors.py +++ b/src/denokv/errors.py @@ -1,5 +1,6 @@ from dataclasses import dataclass -from typing import cast + +from denokv._pycompat.typing import cast @dataclass(init=False) diff --git a/src/denokv/kv.py b/src/denokv/kv.py index ce53323..cde6e88 100644 --- a/src/denokv/kv.py +++ b/src/denokv/kv.py @@ -12,18 +12,7 @@ from enum import auto from os import environ from types import TracebackType -from typing import TYPE_CHECKING -from typing import AsyncIterator -from typing import Awaitable -from typing import Callable -from typing import ClassVar -from typing import Final -from typing import Generic -from typing import Iterable from typing import Literal -from typing import Protocol -from typing import Sequence -from typing import TypedDict from typing import overload import aiohttp @@ -36,6 +25,21 @@ from denokv._datapath_pb2 import SnapshotRead from denokv._datapath_pb2 import SnapshotReadOutput from denokv._pycompat.dataclasses import slots_if310 +from denokv._pycompat.typing import AsyncIterator +from denokv._pycompat.typing import Awaitable +from denokv._pycompat.typing import Callable +from denokv._pycompat.typing import ClassVar +from denokv._pycompat.typing import Final +from denokv._pycompat.typing import Generic +from denokv._pycompat.typing import Iterable +from denokv._pycompat.typing import Protocol +from denokv._pycompat.typing import Self +from denokv._pycompat.typing import Sequence +from denokv._pycompat.typing import TypeAlias +from denokv._pycompat.typing import TypedDict +from denokv._pycompat.typing import TypeVar +from denokv._pycompat.typing import TypeVarTuple +from denokv._pycompat.typing import Unpack from denokv._pycompat.typing import override from denokv.asyncio import loop_time from denokv.auth import ConsistencyLevel @@ -66,23 +70,10 @@ from denokv.result import Ok from denokv.result import Result -if TYPE_CHECKING: - from typing_extensions import Self - from typing_extensions import TypeAlias - from typing_extensions import TypeVar - from typing_extensions import TypeVarTuple - from typing_extensions import Unpack - - T = TypeVar("T", default=object) - # Note that the default arg doesn't seem to work with MyPy yet. The - # DefaultKvKey alias is what this should behave as when defaulted. - Pieces = TypeVarTuple("Pieces", default=Unpack[tuple[KvKeyPiece, ...]]) -else: - from typing import TypeVar - - T = TypeVar("T") - Unpack = tuple # hack to support py39 at runtime w/o typing_extensions - Pieces = TypeVar("Pieces") # hack to support py39 at runtime w/o typing_extensions +T = TypeVar("T", default=object) +# Note that the default arg doesn't seem to work with MyPy yet. The +# DefaultKvKey alias is what this should behave as when defaulted. +Pieces = TypeVarTuple("Pieces", default=Unpack[tuple[KvKeyPiece, ...]]) SAFE_FLOAT_INT_RANGE: Final = range(-(2**53 - 1), 2**53) # 2**53 - 1 is max safe @@ -860,9 +851,9 @@ async def _snapshot_read( return Ok((result.value, endpoint)) -_KvSnapshotReadResult: TypeAlias = ( - "Result[tuple[SnapshotReadOutput, EndpointInfo], DataPathError]" -) +_KvSnapshotReadResult: TypeAlias = Result[ + tuple[SnapshotReadOutput, EndpointInfo], DataPathError +] @dataclass(frozen=True) diff --git a/src/denokv/kv_keys.py b/src/denokv/kv_keys.py index cba2dad..0221c5d 100644 --- a/src/denokv/kv_keys.py +++ b/src/denokv/kv_keys.py @@ -4,20 +4,26 @@ import sys from dataclasses import dataclass from dataclasses import field -from typing import TYPE_CHECKING -from typing import Any -from typing import Final -from typing import Generic -from typing import Iterator -from typing import Sequence -from typing import Union -from typing import cast from typing import overload from fdb.tuple import pack from fdb.tuple import unpack from denokv._pycompat.dataclasses import slots_if310 +from denokv._pycompat.typing import TYPE_CHECKING +from denokv._pycompat.typing import Any +from denokv._pycompat.typing import Final +from denokv._pycompat.typing import Generic +from denokv._pycompat.typing import Iterator +from denokv._pycompat.typing import Self +from denokv._pycompat.typing import Sequence +from denokv._pycompat.typing import SupportsIndex +from denokv._pycompat.typing import TypeAlias +from denokv._pycompat.typing import TypeVar +from denokv._pycompat.typing import TypeVarTuple +from denokv._pycompat.typing import Union +from denokv._pycompat.typing import Unpack +from denokv._pycompat.typing import cast from denokv._pycompat.typing import override from denokv.datapath import KV_KEY_PIECE_TYPES from denokv.datapath import AnyKvKey @@ -36,24 +42,10 @@ from denokv.result import Nothing from denokv.result import Some -if TYPE_CHECKING: - from typing_extensions import Self - from typing_extensions import SupportsIndex - from typing_extensions import TypeAlias - from typing_extensions import TypeVar - from typing_extensions import TypeVarTuple - from typing_extensions import Unpack - - T = TypeVar("T", default=object) - # Note that the default arg doesn't seem to work with MyPy yet. The - # DefaultKvKey alias is what this should behave as when defaulted. - Pieces = TypeVarTuple("Pieces", default=Unpack[tuple[KvKeyPiece, ...]]) -else: - from typing import TypeVar - - T = TypeVar("T") - Unpack = tuple # hack to support py39 at runtime w/o typing_extensions - Pieces = TypeVar("Pieces") # hack to support py39 at runtime w/o typing_extensions +T = TypeVar("T", default=object) +# Note that the default arg doesn't seem to work with MyPy yet. The +# DefaultKvKey alias is what this should behave as when defaulted. +Pieces = TypeVarTuple("Pieces", default=Unpack[tuple[KvKeyPiece, ...]]) _T_co = TypeVar("_T_co", covariant=True) @@ -447,23 +439,12 @@ def range(cls) -> KvKeyRange[IncludeAll, IncludeAll]: StopBoundary: TypeAlias = Union[ IncludeAll, Include[AnyKvKeyT], IncludePrefix[AnyKvKeyT], Exclude[AnyKvKeyT] ] - -if TYPE_CHECKING: - StartT = TypeVar( - "StartT", bound=StartBoundary, default=StartBoundary, covariant=False - ) - StartT_co = TypeVar( - "StartT_co", bound=StartBoundary, default=StartBoundary, covariant=True - ) - StopT = TypeVar("StopT", bound=StopBoundary, default=StopBoundary, covariant=False) - StopT_co = TypeVar( - "StopT_co", bound=StopBoundary, default=StopBoundary, covariant=True - ) -else: - StartT = TypeVar("StartT", bound=StartBoundary, covariant=False) - StopT = TypeVar("StopT", bound=StopBoundary, covariant=False) - StartT_co = TypeVar("StartT_co", bound=StartBoundary, covariant=True) - StopT_co = TypeVar("StopT_co", bound=StopBoundary, covariant=True) +StartT = TypeVar("StartT", bound=StartBoundary, default=StartBoundary, covariant=False) +StartT_co = TypeVar( + "StartT_co", bound=StartBoundary, default=StartBoundary, covariant=True +) +StopT = TypeVar("StopT", bound=StopBoundary, default=StopBoundary, covariant=False) +StopT_co = TypeVar("StopT_co", bound=StopBoundary, default=StopBoundary, covariant=True) @functools.total_ordering diff --git a/src/denokv/result.py b/src/denokv/result.py index 36201c0..68ba208 100644 --- a/src/denokv/result.py +++ b/src/denokv/result.py @@ -2,31 +2,29 @@ from abc import ABCMeta from dataclasses import dataclass -from typing import TYPE_CHECKING -from typing import Any -from typing import Callable -from typing import Final -from typing import Generic -from typing import Iterable -from typing import Iterator -from typing import Protocol -from typing import TypeVar -from typing import Union -from typing import cast from typing import overload -from typing import runtime_checkable from denokv._pycompat.dataclasses import slots_if310 - -if TYPE_CHECKING: - from typing_extensions import Never - from typing_extensions import ParamSpec - from typing_extensions import Self - from typing_extensions import TypeAlias - from typing_extensions import TypeGuard - from typing_extensions import TypeIs - - P = ParamSpec("P") +from denokv._pycompat.typing import TYPE_CHECKING +from denokv._pycompat.typing import Any +from denokv._pycompat.typing import Callable +from denokv._pycompat.typing import Final +from denokv._pycompat.typing import Generic +from denokv._pycompat.typing import Iterable +from denokv._pycompat.typing import Iterator +from denokv._pycompat.typing import Never +from denokv._pycompat.typing import ParamSpec +from denokv._pycompat.typing import Protocol +from denokv._pycompat.typing import Self +from denokv._pycompat.typing import TypeAlias +from denokv._pycompat.typing import TypeGuard +from denokv._pycompat.typing import TypeIs +from denokv._pycompat.typing import TypeVar +from denokv._pycompat.typing import Union +from denokv._pycompat.typing import cast +from denokv._pycompat.typing import runtime_checkable + +P = ParamSpec("P") @runtime_checkable diff --git a/test/advance_time.py b/test/advance_time.py index d166867..f5dcff7 100644 --- a/test/advance_time.py +++ b/test/advance_time.py @@ -4,13 +4,14 @@ import time from dataclasses import dataclass from dataclasses import field -from typing import Callable -from typing import Final -from typing import Generator from unittest.mock import patch import pytest +from denokv._pycompat.typing import Callable +from denokv._pycompat.typing import Final +from denokv._pycompat.typing import Generator + @pytest.fixture def advance_time_time() -> Generator[None]: diff --git a/test/denokv_testing.py b/test/denokv_testing.py index 88256f9..e257ca2 100644 --- a/test/denokv_testing.py +++ b/test/denokv_testing.py @@ -8,13 +8,6 @@ from datetime import datetime from datetime import timedelta from itertools import groupby -from typing import Any -from typing import ClassVar -from typing import Iterable -from typing import Mapping -from typing import NamedTuple -from typing import Sequence -from typing import TypeVar from typing import overload from uuid import UUID @@ -26,6 +19,13 @@ from denokv._datapath_pb2 import ReadRange from denokv._datapath_pb2 import ReadRangeOutput from denokv._datapath_pb2 import ValueEncoding +from denokv._pycompat.typing import Any +from denokv._pycompat.typing import ClassVar +from denokv._pycompat.typing import Iterable +from denokv._pycompat.typing import Mapping +from denokv._pycompat.typing import NamedTuple +from denokv._pycompat.typing import Sequence +from denokv._pycompat.typing import TypeVar from denokv.auth import DatabaseMetadata from denokv.auth import EndpointInfo from denokv.datapath import AnyKvKey diff --git a/test/pycompat/test_protobuf.py b/test/pycompat/test_protobuf.py index ef42013..b7bce07 100644 --- a/test/pycompat/test_protobuf.py +++ b/test/pycompat/test_protobuf.py @@ -1,11 +1,10 @@ -from typing import cast - import pytest from denokv._datapath_pb2 import AtomicWriteStatus from denokv._datapath_pb2 import MutationType from denokv._datapath_pb2 import ValueEncoding from denokv._pycompat.protobuf import enum_name +from denokv._pycompat.typing import cast def test_enum_name() -> None: diff --git a/test/test_auth.py b/test/test_auth.py index 7557240..00de3a9 100644 --- a/test/test_auth.py +++ b/test/test_auth.py @@ -2,11 +2,6 @@ import json from copy import deepcopy -from typing import Any -from typing import Awaitable -from typing import Callable -from typing import Sequence -from typing import cast from uuid import UUID import aiohttp @@ -14,9 +9,14 @@ import pytest_asyncio from aiohttp import web from aiohttp.test_utils import TestClient as _TestClient -from typing_extensions import TypeAlias from yarl import URL +from denokv._pycompat.typing import Any +from denokv._pycompat.typing import Awaitable +from denokv._pycompat.typing import Callable +from denokv._pycompat.typing import Sequence +from denokv._pycompat.typing import TypeAlias +from denokv._pycompat.typing import cast from denokv._rfc3339 import parse_rfc3339_datetime from denokv.auth import ConsistencyLevel from denokv.auth import DatabaseMetadata diff --git a/test/test_datapath.py b/test/test_datapath.py index f73d53a..8ab2248 100644 --- a/test/test_datapath.py +++ b/test/test_datapath.py @@ -5,12 +5,7 @@ import struct from datetime import datetime from datetime import timedelta -from typing import Awaitable -from typing import Callable -from typing import Final from typing import Literal -from typing import Mapping -from typing import cast from uuid import UUID import pytest @@ -23,7 +18,6 @@ from hypothesis import example from hypothesis import given from hypothesis import strategies as st -from typing_extensions import TypeAlias from v8serialize import Decoder from yarl import URL @@ -35,6 +29,12 @@ from denokv._datapath_pb2 import SnapshotReadOutput from denokv._datapath_pb2 import SnapshotReadStatus from denokv._datapath_pb2 import ValueEncoding +from denokv._pycompat.typing import Awaitable +from denokv._pycompat.typing import Callable +from denokv._pycompat.typing import Final +from denokv._pycompat.typing import Mapping +from denokv._pycompat.typing import TypeAlias +from denokv._pycompat.typing import cast from denokv.auth import ConsistencyLevel from denokv.auth import DatabaseMetadata from denokv.auth import EndpointInfo diff --git a/test/test_kv.py b/test/test_kv.py index 83d9a0f..2389c43 100644 --- a/test/test_kv.py +++ b/test/test_kv.py @@ -9,12 +9,6 @@ from datetime import timedelta from functools import partial from itertools import repeat -from typing import TYPE_CHECKING -from typing import Any -from typing import AsyncGenerator -from typing import Callable -from typing import Mapping -from typing import cast from unittest.mock import AsyncMock from unittest.mock import Mock from unittest.mock import patch @@ -40,6 +34,13 @@ from denokv._datapath_pb2 import SnapshotReadStatus from denokv._datapath_pb2 import ValueEncoding from denokv._pycompat.enum import StrEnum +from denokv._pycompat.typing import Any +from denokv._pycompat.typing import AsyncGenerator +from denokv._pycompat.typing import Callable +from denokv._pycompat.typing import Generator +from denokv._pycompat.typing import Mapping +from denokv._pycompat.typing import TypeAlias +from denokv._pycompat.typing import cast from denokv.asyncio import loop_time from denokv.auth import ConsistencyLevel from denokv.auth import DatabaseMetadata @@ -84,11 +85,6 @@ from test.denokv_testing import mk_db_meta from test.denokv_testing import unsafe_parse_protobuf_kv_entry -if TYPE_CHECKING: - from typing import Generator - - from typing_extensions import TypeAlias - pytest_mark_asyncio = pytest.mark.asyncio() diff --git a/test/test_kv_keys__kvkey.py b/test/test_kv_keys__kvkey.py index 67bf47e..b75dd9a 100644 --- a/test/test_kv_keys__kvkey.py +++ b/test/test_kv_keys__kvkey.py @@ -3,13 +3,13 @@ import re import weakref from typing import Literal -from typing import Sequence -from typing import cast import pytest from fdb.tuple import pack -from typing_extensions import Unpack +from denokv._pycompat.typing import Sequence +from denokv._pycompat.typing import Unpack +from denokv._pycompat.typing import cast from denokv.datapath import AnyKvKey from denokv.datapath import KvKeyEncodable from denokv.datapath import KvKeyPiece diff --git a/test/test_kv_keys__kvkeyrange.py b/test/test_kv_keys__kvkeyrange.py index 68ce3b2..d8de0d6 100644 --- a/test/test_kv_keys__kvkeyrange.py +++ b/test/test_kv_keys__kvkeyrange.py @@ -1,8 +1,8 @@ from typing import Literal -from typing import cast import pytest +from denokv._pycompat.typing import cast from denokv.kv_keys import Exclude from denokv.kv_keys import Include from denokv.kv_keys import IncludeAll diff --git a/test/test_result.py b/test/test_result.py index 846550e..4e9394c 100644 --- a/test/test_result.py +++ b/test/test_result.py @@ -1,18 +1,18 @@ from __future__ import annotations import sys -from typing import TYPE_CHECKING -from typing import Any -from typing import Iterable from typing import Literal -from typing import Sequence -from typing import cast from unittest.mock import Mock import pytest -from typing_extensions import Never -from typing_extensions import TypeIs +from denokv._pycompat.typing import TYPE_CHECKING +from denokv._pycompat.typing import Any +from denokv._pycompat.typing import Iterable +from denokv._pycompat.typing import Never +from denokv._pycompat.typing import Sequence +from denokv._pycompat.typing import TypeIs +from denokv._pycompat.typing import cast from denokv.result import AnyFailure from denokv.result import AnySuccess from denokv.result import Err