-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathtest_wildcats.py
260 lines (182 loc) · 5.82 KB
/
test_wildcats.py
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
import json
import typing as ty
import pytest
from typecats import Cat, struc
from typecats.exceptions import StructuringError
from data_utils import ld
@Cat
class MyWildcat(dict):
name: str
age: int = 0
@Cat
class LocatedWildcat(MyWildcat):
location: str = ""
@Cat
class Wrapper:
wrap: bool = True
wildcat: ty.Optional[MyWildcat] = None
@Cat
class EmptyWildcatWithBool(dict):
has_default: str = ""
@Cat
class UserClaims(dict):
hasVSCs: bool = False
@Cat
class Organization(dict):
id: str
name: str
userClaims: ty.Optional[UserClaims]
@Cat
class KnowledgebaseMetadata(dict):
make: str = ""
def test_wildcats():
dwc = dict(name="Steve", age=4, location="Colorado")
wrapped = Wrapper.struc(dict(wrap=False, wildcat=dwc))
print(wrapped)
if wrapped.wildcat:
wrapped.wildcat["adjust"] = 88
wc = MyWildcat.struc(dwc)
assert type(wc) == MyWildcat
print(wc)
wc["favorite_color"] = "green"
print(wc)
# print(wc.location) # would be a mypy type error
print(wc["location"]) # not a mypy type error
lwc = LocatedWildcat.struc(wc.unstruc())
print("Located wildcat at " + lwc.location)
assert lwc.location == "Colorado"
lwc["location"] = "Georgia"
# even when a defined attribut is set on a Wildcat via __setitem__ instead of __set__,
# the actual __dict__ attribute gets overwritten correctly.
assert lwc["location"] == "Georgia"
assert lwc.location == "Georgia"
lwc["isDangerous"] = False
lwc.update({"location": "Tennessee"})
assert lwc.location == "Tennessee"
assert lwc["location"] == "Tennessee"
ndwc = lwc.unstruc()
print(ndwc)
assert ndwc["location"] == "Tennessee"
assert not ndwc["isDangerous"]
xoi_dict = json.loads(open(ld("xoi.json")).read())
XOi = Organization.struc(xoi_dict)
assert XOi
XOi["dynamic"] = dict(inner="type")
assert XOi.userClaims
XOi.userClaims.hasVSCs = True
XOi.userClaims["somethingDynamic"] = 8888
print(XOi)
new_xoi = XOi.unstruc()
print("\nunstructured:")
print(new_xoi)
assert new_xoi["userClaims"]["somethingDynamic"] == 8888
assert new_xoi["dynamic"] == dict(inner="type")
# test truthy checks that are generated for Wildcats
assert MyWildcat("named")
assert not bool(EmptyWildcatWithBool())
assert bool(EmptyWildcatWithBool("test"))
assert not KnowledgebaseMetadata()
assert KnowledgebaseMetadata(make="GM")
km = KnowledgebaseMetadata()
km["other_thing"] = True
assert bool(km)
def test_attr_in_wildcat_dict_is_unstructured():
"""Items inside the Wildcat dict should also be unstructured if they're unstructurable"""
@Cat
class MyWildcat(dict):
whatever: str = ""
@Cat
class Hidden:
number: int
mw = MyWildcat("blah")
mw["hidden"] = Hidden(3)
mwd = mw.unstruc()
assert mwd["hidden"]["number"] == 3 # 'hidden' is unstructured to dict
assert mwd["whatever"] == "blah" # other stuff still works
with pytest.raises(AttributeError):
mwd["hidden"].number
def test_nested_wildcats_still_unstructure():
"""It's wildcats all the way down
Wildcats nested inside a Wildcat dict should be properly unstructured
as Wildcats, retaining all untyped keys but also unstructuring the typed ones.
"""
@Cat
class MyWildcat(dict):
foo: str = "foo"
@Cat
class Hidden(dict):
bar: str = "bar"
@Cat
class NestedHidden:
reqd: int
wow: str = "UAU!!"
mw = MyWildcat()
mw["hidden"] = Hidden()
mw["hidden"]["nested_hidden"] = NestedHidden(8, "UAU!!!!!!")
mwd = mw.unstruc()
assert mwd["foo"] == "foo"
assert mwd["hidden"]["bar"] == "bar"
assert mwd["hidden"]["nested_hidden"] == dict(reqd=8, wow="UAU!!!!!!")
def test_wildcat_with_id():
@Cat
class WithId(dict):
id: str
age: int
wi = WithId.struc(dict(id="iii", age=4))
assert wi == WithId("iii", 4)
def test_wildcat_repr_no_conflicts():
@Cat
class WithDictMethodAttrs(dict):
items: ty.List[int] # type: ignore
keys: ty.Set[str] # type: ignore
wdma = WithDictMethodAttrs([1, 2, 3], {"a", "b"})
assert "Wildcat" not in str(wdma)
wdma["test"] = "a str"
assert "Wildcat" in str(wdma)
def test_wildcat_equality_takes_wildcat_key_values_into_account():
@Cat
class Nested(dict):
i: int
@Cat
class Wildcat2(dict):
species: str
n: Nested
base = dict(species="young", n=dict(i=7, j=10))
wc = Wildcat2.struc(base)
assert wc == Wildcat2.struc(base)
wc.n["p"] = "j"
assert wc != Wildcat2.struc(base)
del wc.n["p"]
assert wc == Wildcat2.struc(base)
wc.n.i = 8
assert wc != Wildcat2.struc(base)
def test_wildcat_struc_with_wildcat_backwards_compatibility():
@Cat
class Nested(dict):
i: int
@Cat
class WithNested:
nested: Nested
# This used to work with BaseConverter but stopped working with GenConverter.
c = WithNested.struc(dict(nested=Nested(i=6)))
assert c.nested.i == 6
def test_wildcat_struc_with_non_wildcat_does_not_work():
@Cat
class Nested:
i: int
@Cat
class WithNested:
nested: Nested
# Make sure that this particular case only works with wildcats
with pytest.raises(StructuringError):
WithNested.struc(dict(nested=Nested(i=6)))
def test_wildcat_structure_on_parametrized_generic():
# The wildcat.struc(CatObject) compatibility once broke with generics
T = ty.TypeVar("T")
@Cat
class TList(dict, ty.Generic[T]):
the_list: ty.List[T]
int_list = struc(TList[int], dict(the_list=[1, 2, 3]))
assert int_list.the_list == [1, 2, 3]
str_list = struc(TList[str], dict(the_list=["a", "b", "c"]))
assert str_list.the_list == ["a", "b", "c"]