Skip to content

Commit 0a49378

Browse files
committed
core: more tests and proper support for PEP 695 type parameter syntax
1 parent 148222e commit 0a49378

File tree

6 files changed

+364
-24
lines changed

6 files changed

+364
-24
lines changed

src/cachew/__init__.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
TYPE_CHECKING,
1515
Any,
1616
Literal,
17-
TypeAliasType,
1817
cast,
1918
get_args,
2019
get_origin,
@@ -46,6 +45,7 @@ def orjson_dumps(*args, **kwargs): # type: ignore[misc]
4645
from .utils import (
4746
CachewException,
4847
TypeNotSupported,
48+
resolve_type_parameters,
4949
)
5050

5151
# in case of changes in the way cachew stores data, this should be changed to discard old caches
@@ -119,15 +119,15 @@ def infer_return_type(func) -> Failure | Inferred:
119119
... return None if len(s) == 0 else s[0]
120120
>>> kind, opt = infer_return_type(first_character)
121121
>>> # in 3.8, Optional[str] is printed as Union[str, None], so need to hack around this
122-
>>> (kind, opt is Optional[str])
122+
>>> (kind, opt == Optional[str])
123123
('single', True)
124124
125125
# tuple is an iterable.. but presumably should be treated as a single value
126126
>>> from typing import Tuple
127127
>>> def a_tuple() -> Tuple[int, str]:
128128
... return (123, 'hi')
129129
>>> infer_return_type(a_tuple)
130-
('single', typing.Tuple[int, str])
130+
('single', tuple[int, str])
131131
132132
>>> from typing import Collection, NamedTuple
133133
>>> class Person(NamedTuple):
@@ -169,14 +169,14 @@ def infer_return_type(func) -> Failure | Inferred:
169169
... yield 1
170170
... yield 'aaa'
171171
>>> infer_return_type(iterator_str_int)
172-
('multiple', Str | Int)
172+
('multiple', str | int)
173173
174174
# a bit of an edge case
175175
>>> from typing import Tuple
176176
>>> def empty_tuple() -> Iterator[Tuple[()]]:
177177
... yield ()
178178
>>> infer_return_type(empty_tuple)
179-
('multiple', typing.Tuple[()])
179+
('multiple', tuple[()])
180180
181181
... # doctest: +ELLIPSIS
182182
@@ -196,7 +196,7 @@ def infer_return_type(func) -> Failure | Inferred:
196196
>>> def unsupported_list() -> List[Custom]:
197197
... return [Custom()]
198198
>>> infer_return_type(unsupported_list)
199-
"can't infer type from typing.List[cachew.Custom]: can't cache <class 'cachew.Custom'>"
199+
"can't infer type from list[cachew.Custom]: can't cache <class 'cachew.Custom'>"
200200
"""
201201
try:
202202
hints = get_type_hints(func)
@@ -208,9 +208,7 @@ def infer_return_type(func) -> Failure | Inferred:
208208
if rtype is None:
209209
return f"no return type annotation on {func}"
210210

211-
if isinstance(rtype, TypeAliasType):
212-
# handle 'type ... = ...' aliases
213-
rtype = rtype.__value__
211+
rtype = resolve_type_parameters(rtype)
214212

215213
def bail(reason: str) -> str:
216214
return f"can't infer type from {rtype}: " + reason

src/cachew/marshall/cachew.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,14 @@
1414
NamedTuple,
1515
Optional,
1616
Tuple,
17-
TypeAliasType,
1817
Union,
1918
get_args,
2019
get_origin,
2120
get_type_hints,
2221
)
2322
from zoneinfo import ZoneInfo
2423

25-
from ..utils import TypeNotSupported, is_namedtuple
24+
from ..utils import TypeNotSupported, is_namedtuple, resolve_type_parameters
2625
from .common import AbstractMarshall, Json
2726

2827

@@ -290,13 +289,11 @@ def load(self, dct: str):
290289

291290

292291
def build_schema(Type) -> Schema:
293-
if isinstance(Type, TypeAliasType):
294-
# handle 'type ... = ...' aliases
295-
Type = Type.__value__
296-
297292
# just to avoid confusion in case of weirdness with stringish type annotations
298293
assert not isinstance(Type, str), Type
299294

295+
Type = resolve_type_parameters(Type)
296+
300297
ptype = PRIMITIVES.get(Type)
301298
if ptype is not None:
302299
return SPrimitive(type=ptype)
@@ -618,6 +615,3 @@ class NotSupported:
618615
helper([1, 2, 3], list[int] | list[Exception])
619616
with pytest.raises(TypeNotSupported, match=r".*runtime union arguments are not unique"):
620617
helper([1, 2, 3], list[Exception] | list[int])
621-
622-
623-
# TODO test type aliases and such??

src/cachew/tests/test_cachew.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,3 +1461,15 @@ def fun() -> IteratorInt:
14611461

14621462
assert list(fun()) == [123]
14631463
assert list(fun()) == [123]
1464+
1465+
1466+
def test_type_alias_generic(tmp_path: Path) -> None:
1467+
type Res[T] = T | Exception
1468+
type IntRes = Res[int]
1469+
1470+
@cachew(tmp_path)
1471+
def fun() -> Iterator[IntRes]:
1472+
yield 123
1473+
1474+
assert list(fun()) == [123]
1475+
assert list(fun()) == [123]

src/cachew/tests/test_future_annotations.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,15 +104,18 @@ def test_future_annotations(
104104
'''
105105

106106
_TEST = '''
107-
type T = int
107+
108+
type Identity[T] = T
109+
I = int
110+
type S = Identity[str]
108111
109112
@cachew(td)
110-
def fun() -> list[T]:
113+
def fun() -> list[I | S]:
111114
print("called")
112-
return [1, 2]
115+
return [1, "2"]
113116
114-
assert list(fun()) == [1, 2]
115-
assert list(fun()) == [1, 2]
117+
assert list(fun()) == [1, "2"]
118+
assert list(fun()) == [1, "2"]
116119
'''
117120

118121
if use_future_annotations:

0 commit comments

Comments
 (0)