Completed
Push — develop ( 0e4f30...ae7ea2 )
by Jace
11s
created

test_list_in_dict_append_triggers_save()   B

Complexity

Conditions 3

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 24
rs 8.9713
cc 3
1
"""Integration tests for nested attributes."""
2
# pylint: disable=missing-docstring,no-self-use,attribute-defined-outside-init,no-member
3
# pylint: disable=unused-variable,misplaced-comparison-constant
0 ignored issues
show
introduced by
Bad option value 'misplaced-comparison-constant'
Loading history...
4
5
from unittest.mock import patch
6
7
import pytest
8
from expecter import expect
0 ignored issues
show
Configuration introduced by
The import expecter could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

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