-
-
Notifications
You must be signed in to change notification settings - Fork 136
Expand file tree
/
Copy pathtest_generics_695.py
More file actions
118 lines (76 loc) · 3.3 KB
/
test_generics_695.py
File metadata and controls
118 lines (76 loc) · 3.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
"""Tests for PEP 695 (Type Parameter Syntax)."""
from dataclasses import dataclass
import pytest
from attrs import define
from cattrs import BaseConverter, Converter
from ._compat import is_py312_plus
@pytest.mark.skipif(not is_py312_plus, reason="3.12+ syntax")
def test_simple_generic_roundtrip(converter: BaseConverter):
"""PEP 695 attrs generics work."""
@define
class A[T]:
a: T
assert converter.structure({"a": "1"}, A[int]) == A(1)
assert converter.unstructure(A(1)) == {"a": 1}
if isinstance(converter, Converter):
# Only supported on a Converter
assert converter.unstructure(A(1), A[int]) == {"a": 1}
@pytest.mark.skipif(not is_py312_plus, reason="3.12+ syntax")
def test_simple_generic_roundtrip_dc(converter: BaseConverter):
"""PEP 695 dataclass generics work."""
@dataclass
class A[T]:
a: T
assert converter.structure({"a": "1"}, A[int]) == A(1)
assert converter.unstructure(A(1)) == {"a": 1}
if isinstance(converter, Converter):
# Only supported on a Converter
assert converter.unstructure(A(1), A[int]) == {"a": 1}
def test_type_aliases(converter: BaseConverter):
"""PEP 695 type aliases work."""
type my_int = int
assert converter.structure("42", my_int) == 42
assert converter.unstructure(42, my_int) == 42
type my_other_int = int
# Manual hooks should work.
converter.register_structure_hook_func(
lambda t: t is my_other_int, lambda v, _: v + 10
)
converter.register_unstructure_hook_func(
lambda t: t is my_other_int, lambda v: v - 20
)
assert converter.structure(1, my_other_int) == 11
assert converter.unstructure(100, my_other_int) == 80
def test_type_aliases_simple_hooks(converter: BaseConverter):
"""PEP 695 type aliases work with `register_un/structure_hook`."""
type my_other_int = int
converter.register_structure_hook(my_other_int, lambda v, _: v + 10)
converter.register_unstructure_hook(my_other_int, lambda v: v - 20)
assert converter.structure(1, my_other_int) == 11
assert converter.unstructure(100, my_other_int) == 80
def test_type_aliases_overwrite_base_hooks(converter: BaseConverter):
"""Overwriting base hooks should affect type aliases."""
converter.register_structure_hook(int, lambda v, _: v + 10)
converter.register_unstructure_hook(int, lambda v: v - 20)
type my_int = int
assert converter.structure(1, my_int) == 11
assert converter.unstructure(100, my_int) == 80
def test_type_alias_with_children(converter: BaseConverter):
"""A type alias that chains to a hook that requires the type parameter works."""
class TestClass:
pass
def structure_testclass(val, type):
assert type is TestClass
return TestClass
converter.register_structure_hook(TestClass, structure_testclass)
type TestAlias = TestClass
assert converter.structure(None, TestAlias) is TestClass
def test_generic_type_alias(converter: BaseConverter):
"""Generic type aliases work.
See https://docs.python.org/3/reference/compound_stmts.html#generic-type-aliases
for details.
"""
type Gen1[T] = T
assert converter.structure("1", Gen1[int]) == 1
type Gen2[K, V] = dict[K, V]
assert converter.structure({"a": "1"}, Gen2[str, int]) == {"a": 1}