Completed
Push — develop ( b4a21c...b1df34 )
by Jace
02:37
created

NestedDictionary   A

Complexity

Total Complexity 2

Size/Duplication

Total Lines 11
Duplicated Lines 0 %
Metric Value
wmc 2
dl 0
loc 11
rs 10

2 Methods

Rating   Name   Duplication   Size   Complexity  
A __init__() 0 4 1
A __repr__() 0 2 1
1
"""Integration tests for nested attributes."""
2
# pylint: disable=missing-docstring,no-self-use,attribute-defined-outside-init,no-member,misplaced-comparison-constant
0 ignored issues
show
introduced by
Bad option value 'misplaced-comparison-constant'
Loading history...
3
4
5
from unittest.mock import patch
6
import logging
7
8
import yorm
9
10
from . import strip
11
12
13
@yorm.attr(status=yorm.types.Boolean)
14
class StatusDictionary(yorm.types.Dictionary):
15
16
    pass
17
18
19
@yorm.attr(all=yorm.types.Float)
20
class NestedList3(yorm.types.List):
21
22
    def __repr__(self):
23
        return "<nested-list-3 {}>".format((id(self)))
24
25
26
@yorm.attr(nested_list_3=NestedList3)
27
@yorm.attr(number=yorm.types.Float)
28
class NestedDictionary3(yorm.types.AttributeDictionary):
29
30
    def __init__(self):
31
        super().__init__()
32
        self.number = 0
33
        self.nested_list_3 = []
34
35
    def __repr__(self):
36
        print(self.number)  # trigger a potential recursion issue
37
        return "<nested-dictionary-3 {}>".format((id(self)))
38
39
40
@yorm.attr(all=yorm.types.Float)
41
class NestedList2(yorm.types.List):
42
43
    def __repr__(self):
44
        return "<nested-list-2 {}>".format((id(self)))
45
46
47
@yorm.attr(nested_dict_3=NestedDictionary3)
48
@yorm.attr(number=yorm.types.Float)
49
class NestedDictionary2(yorm.types.AttributeDictionary):
50
51
    def __init__(self):
52
        super().__init__()
53
        self.number = 0
54
55
    def __repr__(self):
56
        print(self.number)  # trigger a potential recursion issue
57
        return "<nested-dictionary-2 {}>".format((id(self)))
58
59
60
@yorm.attr(nested_list_2=NestedList2)
61
@yorm.attr(number=yorm.types.Float)
62
class NestedDictionary(yorm.types.AttributeDictionary):
63
64
    def __init__(self):
65
        super().__init__()
66
        self.number = 0
67
        self.nested_list_2 = []
68
69
    def __repr__(self):
70
        return "<nested-dictionary {}>".format((id(self)))
71
72
73
@yorm.attr(all=NestedDictionary2)
74
class NestedList(yorm.types.List):
75
76
    def __repr__(self):
77
        return "<nested-list {}>".format((id(self)))
78
79
80
@yorm.attr(nested_dict=NestedDictionary)
81
@yorm.attr(nested_list=NestedList)
82
@yorm.sync("sample.yml")
83
class Top:
84
85
    def __init__(self):
86
        self.nested_list = []
87
        self.nested_dict = {}
88
89
    def __repr__(self):
90
        return "<top {}>".format((id(self)))
91
92
93
@patch('yorm.settings.fake', True)
94
class TestNestedOnce:
95
96
    def test_append_triggers_store(self):
97
        top = Top()
98
        logging.info("Appending dictionary to list...")
99
        top.nested_list.append({'number': 1})
100
        assert strip("""
101
        nested_dict:
102
          nested_list_2: []
103
          number: 0.0
104
        nested_list:
105
        - nested_dict_3:
106
            nested_list_3: []
107
            number: 0.0
108
          number: 1.0
109
        """) == top.__mapper__.text
110
111
    def test_set_by_index_triggers_store(self):
112
        top = Top()
113
        top.nested_list = [{'number': 1.5}]
114
        assert strip("""
115
        nested_dict:
116
          nested_list_2: []
117
          number: 0.0
118
        nested_list:
119
        - nested_dict_3:
120
            nested_list_3: []
121
            number: 0.0
122
          number: 1.5
123
        """) == top.__mapper__.text
124
        top.nested_list[0] = {'number': 1.6}
125
        assert strip("""
126
        nested_dict:
127
          nested_list_2: []
128
          number: 0.0
129
        nested_list:
130
        - nested_dict_3:
131
            nested_list_3: []
132
            number: 0.0
133
          number: 1.6
134
        """) == top.__mapper__.text
135
136
    def test_get_by_index_triggers_fetch(self):
137
        top = Top()
138
        top.__mapper__.text = strip("""
139
        nested_list:
140
        - number: 1.7
141
        """)
142
        assert 1.7 == top.nested_list[0].number
143
144
    def test_delete_index_triggers_store(self):
145
        top = Top()
146
        top.nested_list = [{'number': 1.8}, {'number': 1.9}]
147
        assert strip("""
148
        nested_dict:
149
          nested_list_2: []
150
          number: 0.0
151
        nested_list:
152
        - nested_dict_3:
153
            nested_list_3: []
154
            number: 0.0
155
          number: 1.8
156
        - nested_dict_3:
157
            nested_list_3: []
158
            number: 0.0
159
          number: 1.9
160
        """) == top.__mapper__.text
161
        del top.nested_list[0]
162
        assert strip("""
163
        nested_dict:
164
          nested_list_2: []
165
          number: 0.0
166
        nested_list:
167
        - nested_dict_3:
168
            nested_list_3: []
169
            number: 0.0
170
          number: 1.9
171
        """) == top.__mapper__.text
172
173
    def test_set_dict_as_attribute_triggers_store(self):
174
        top = Top()
175
        top.nested_dict.number = 2
176
        assert strip("""
177
        nested_dict:
178
          nested_list_2: []
179
          number: 2.0
180
        nested_list: []
181
        """) == top.__mapper__.text
182
183
184
@patch('yorm.settings.fake', True)
185
class TestNestedTwice:
186
187
    def test_nested_list_item_value_change_triggers_store(self):
188
        top = Top()
189
        top.nested_list = [{'number': 3}]
190
        assert strip("""
191
        nested_dict:
192
          nested_list_2: []
193
          number: 0.0
194
        nested_list:
195
        - nested_dict_3:
196
            nested_list_3: []
197
            number: 0.0
198
          number: 3.0
199
        """) == top.__mapper__.text
200
        top.nested_list[0].number = 4
201
        assert strip("""
202
        nested_dict:
203
          nested_list_2: []
204
          number: 0.0
205
        nested_list:
206
        - nested_dict_3:
207
            nested_list_3: []
208
            number: 0.0
209
          number: 4.0
210
        """) == top.__mapper__.text
211
212
    def test_nested_dict_item_value_change_triggers_store(self):
213
        top = Top()
214
        top.nested_dict = {'nested_list_2': [5]}
215
        assert strip("""
216
        nested_dict:
217
          nested_list_2:
218
          - 5.0
219
          number: 0.0
220
        nested_list: []
221
        """) == top.__mapper__.text
222
        top.nested_dict.nested_list_2.append(6)
223
        assert strip("""
224
        nested_dict:
225
          nested_list_2:
226
          - 5.0
227
          - 6.0
228
          number: 0.0
229
        nested_list: []
230
        """) == top.__mapper__.text
231
232
    def test_dict_in_list_value_change_triggers_store(self):
233
        top = Top()
234
        top.nested_list.append(None)
235
        top.nested_list[0].nested_dict_3.number = 8
236
        assert strip("""
237
        nested_dict:
238
          nested_list_2: []
239
          number: 0.0
240
        nested_list:
241
        - nested_dict_3:
242
            nested_list_3: []
243
            number: 8.0
244
          number: 0.0
245
        """) == top.__mapper__.text
246
247
    def test_list_in_dict_append_triggers_store(self):
248
        top = Top()
249
        top.nested_list.append(None)
250
        top.nested_list.append(None)
251
        for nested_dict_2 in top.nested_list:
252
            nested_dict_2.number = 9
253
            nested_dict_2.nested_dict_3.nested_list_3.append(10)
254
        assert strip("""
255
        nested_dict:
256
          nested_list_2: []
257
          number: 0.0
258
        nested_list:
259
        - nested_dict_3:
260
            nested_list_3:
261
            - 10.0
262
            number: 0.0
263
          number: 9.0
264
        - nested_dict_3:
265
            nested_list_3:
266
            - 10.0
267
            number: 0.0
268
          number: 9.0
269
        """) == top.__mapper__.text
270
271
272
@patch('yorm.settings.fake', True)
273
class TestAliases:
274
275
    @yorm.attr(var4=NestedList3)
276
    @yorm.attr(var5=StatusDictionary)
277
    @yorm.sync("fake/path")
278
    class Sample:
279
280
        def __repr__(self):
281
            return "<sample {}>".format(id(self))
282
283
    def setup_method(self, _):
284
        self.sample = self.Sample()
285
286
    @staticmethod
287
    def _log_ref(name, var, ref):
288
        logging.info("%s: %r", name, var)
289
        logging.info("%s_ref: %r", name, ref)
290
        logging.info("%s ID: %s", name, id(var))
291
        logging.info("%s_ref ID: %s", name, id(ref))
292
        assert id(ref) == id(var)
293
        assert ref == var
294
295
    def test_alias_list(self):
296
        yorm.update_object(self.sample)
297
        var4_ref = self.sample.var4
298
        self._log_ref('var4', self.sample.var4, var4_ref)
299
        assert [] == self.sample.var4
300
301
        logging.info("Appending 42 to var4_ref...")
302
        var4_ref.append(42)
303
        self._log_ref('var4', self.sample.var4, var4_ref)
304
        assert [42] == self.sample.var4
305
306
        logging.info("Appending 2015 to var4_ref...")
307
        var4_ref.append(2015)
308
        assert [42, 2015] == self.sample.var4
309
310
    def test_alias_dict(self):
311
        yorm.update_object(self.sample)
312
        var5_ref = self.sample.var5
313
        self._log_ref('var5', self.sample.var5, var5_ref)
314
        assert {'status': False} == self.sample.var5
315
316
        logging.info("Setting status=True in var5_ref...")
317
        var5_ref['status'] = True
318
        self._log_ref('var5', self.sample.var5, var5_ref)
319
        assert {'status': True} == self.sample.var5
320
321
        logging.info("Setting status=False in var5_ref...")
322
        var5_ref['status'] = False
323
        self._log_ref('var5', self.sample.var5, var5_ref)
324
        assert {'status': False} == self.sample.var5
325
326
    def test_alias_dict_in_list(self):
327
        top = Top()
328
        top.nested_list.append(None)
329
        ref1 = top.nested_list[0]
330
        ref2 = top.nested_list[0].nested_dict_3
331
        ref3 = top.nested_list[0].nested_dict_3.nested_list_3
332
        yorm.update(top)
333
        assert id(ref1) == id(top.nested_list[0])
334
        assert id(ref2) == id(top.nested_list[0].nested_dict_3)
335
        assert id(ref3) == id(top.nested_list[0].nested_dict_3.nested_list_3)
336
337
    def test_alias_list_in_dict(self):
338
        top = Top()
339
        logging.info("Updating nested attribute...")
340
        top.nested_dict.number = 1
341
        logging.info("Storing refs...")
342
        ref1 = top.nested_dict
343
        ref2 = top.nested_dict.nested_list_2
344
        yorm.update(top)
345
        assert id(ref1) == id(top.nested_dict)
346
        assert id(ref2) == id(top.nested_dict.nested_list_2)
347