Completed
Branch master (6e6000)
by Fabio
01:45
created

tests.test_keypath_dict   F

Complexity

Total Complexity 88

Size/Duplication

Total Lines 856
Duplicated Lines 18.11 %

Importance

Changes 0
Metric Value
wmc 88
eloc 637
dl 155
loc 856
rs 1.963
c 0
b 0
f 0

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complexity

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like tests.test_keypath_dict often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
# -*- coding: utf-8 -*-
2
3
from benedict.dicts.keypath import KeypathDict
4
5
import unittest
6
7
8
class keypath_dict_test_case(unittest.TestCase):
9
10
    def test_init_with_custom_separator(self):
11
        d = {
12
            'a.b': {
13
                'c.d': 1,
14
                'e.f': 2,
15
            },
16
            'g.h': {
17
                'i.j': 3,
18
                'k.l': 4,
19
            },
20
        }
21
        b = KeypathDict(d, keypath_separator='/')
22
        self.assertEqual(b.get('a.b/c.d'), 1)
23
        self.assertEqual(b.get('a.b/e.f'), 2)
24
        self.assertEqual(b.get('g.h/i.j'), 3)
25
        self.assertEqual(b.get('g.h/k.l'), 4)
26
27
    def test_init_without_keypath_separator(self):
28
        d = {
29
            'a': {
30
                'b': 1,
31
                'c': 2,
32
            },
33
            'd': {
34
                'e': 3,
35
                'f': 4,
36
            },
37
        }
38
        b = KeypathDict(d, keypath_separator=None)
39
        self.assertEqual(b.get('a.b'), None)
40
        self.assertEqual(b.get('a.c'), None)
41
        self.assertEqual(b.get('d.e'), None)
42
        self.assertEqual(b.get('d.f'), None)
43
44
    def test_init_with_dict_with_separator_in_keys(self):
45
        d = {
46
            'a.b.c': 1,
47
            'c.d.e': 2,
48
        }
49
        with self.assertRaises(ValueError):
50
            KeypathDict(d)
51
52
    def test_update_with_dict_with_separator_in_keys(self):
53
        d1 = {
54
            'a': 1,
55
            'b': 2,
56
            'c': 3,
57
        }
58
        d2 = {
59
            'a.x': 4,
60
            'a.y': 5,
61
            'a.z': 6,
62
        }
63
        b = KeypathDict(d1)
64
        with self.assertRaises(ValueError):
65
            b.update(d2)
66
67
    def test_update_with_dict_without_separator_in_keys(self):
68
        d1 = {
69
            'a': 1,
70
            'b': 2,
71
            'c': 3,
72
        }
73
        d2 = {
74
            'a.x': 4,
75
            'a.y': 5,
76
            'a.z': 6,
77
        }
78
        b = KeypathDict(d1, keypath_separator='/')
79
        b.update(d2)
80
        self.assertEqual(b.get('a'), 1)
81
        self.assertEqual(b.get('b'), 2)
82
        self.assertEqual(b.get('c'), 3)
83
        self.assertEqual(b.get('a.x'), 4)
84
        self.assertEqual(b.get('a.y'), 5)
85
        self.assertEqual(b.get('a.z'), 6)
86
87
    def test_fromkeys(self):
88
        k = [
89
            'a',
90
            'a.b',
91
            'a.b.c',
92
            'a.b.d',
93
            'a.b.e',
94
            'x',
95
            'x.y',
96
            'x.z',
97
        ]
98
        b = KeypathDict.fromkeys(k)
99
        r = {
100
            'x': {
101
                'y': None,
102
                'z': None,
103
            },
104
            'a': {
105
                'b': {
106
                    'c': None,
107
                    'd': None,
108
                    'e': None,
109
                },
110
            },
111
        }
112
        self.assertEqual(b, r)
113
114
    def test_fromkeys_with_value(self):
115
        k = [
116
            'a',
117
            'a.b',
118
            'a.b.c',
119
            'a.b.d',
120
            'a.b.e',
121
            'x',
122
            'x.y',
123
            'x.z',
124
        ]
125
        b = KeypathDict.fromkeys(k, True)
126
        r = {
127
            'x': {
128
                'y': True,
129
                'z': True,
130
            },
131
            'a': {
132
                'b': {
133
                    'c': True,
134
                    'd': True,
135
                    'e': True,
136
                },
137
            },
138
        }
139
        self.assertEqual(b, r)
140
141
    def test_get_with_1_valid_key(self):
142
        d = {
143
            'a': 1,
144
            1: 1
145
        }
146
        b = KeypathDict(d)
147
        self.assertEqual(b.get('a', 2), 1)
148
        self.assertEqual(b.get(1, 2), 1)
149
150
    def test_get_with_1_invalid_key(self):
151
        d = {
152
            'a': 1,
153
        }
154
        b = KeypathDict(d)
155
        self.assertEqual(b.get('b', 2), 2)
156
157
    def test_get_with_1_not_str_key(self):
158
        d = {
159
            None: None,
160
            False: False,
161
        }
162
        b = KeypathDict(d)
163
        self.assertEqual(b.get(None, 1), None)
164
        self.assertEqual(b.get(False, True), False)
165
        self.assertEqual(b.get(True, True), True)
166
        self.assertEqual(b.get(0, 1), 0)
167
168
    def test_getitem_with_1_valid_key(self):
169
        d = {
170
            'a': 1,
171
        }
172
        b = KeypathDict(d)
173
        self.assertEqual(b['a'], 1)
174
175
    def test_getitem_with_1_invalid_key(self):
176
        d = {
177
            'a': 1,
178
        }
179
        b = KeypathDict(d)
180
        with self.assertRaises(KeyError):
181
            val = b['b']
182
            print(val)
183
184
    def test_getitem_with_1_not_str_key(self):
185
        d = {
186
            None: None,
187
            False: False,
188
            # 0: 0,
189
        }
190
        b = KeypathDict(d)
191
        self.assertEqual(b[None], None)
192
        self.assertEqual(b[False], False)
193
        with self.assertRaises(KeyError):
194
            val = b[True]
195
            print(val)
196
197
        self.assertEqual(b[0], 0)
198
199
    def test_get_with_2_valid_keys(self):
200
        d = {
201
            'a': {
202
                'b': 1
203
            }
204
        }
205
        b = KeypathDict(d)
206
        self.assertEqual(b.get('a.b', 2), 1)
207
208
    def test_get_with_2_invalid_keys(self):
209
        d = {
210
            'a': {
211
                'b': 1
212
            }
213
        }
214
        b = KeypathDict(d)
215
        self.assertEqual(b.get('b.a', 2), 2)
216
217
    def test_getitem_with_2_valid_keys(self):
218
        d = {
219
            'a': {
220
                'b': 1
221
            }
222
        }
223
        b = KeypathDict(d)
224
        self.assertEqual(b['a.b'], 1)
225
226
    def test_getitem_with_2_invalid_keys(self):
227
        d = {
228
            'a': {
229
                'b': 1
230
            }
231
        }
232
        b = KeypathDict(d)
233
        with self.assertRaises(KeyError):
234
            val = b['b.a']
235
            print(val)
236
237
    def test_get_with_3_valid_keys(self):
238
        d = {
239
            'a': {
240
                'b': {
241
                    'c': 1
242
                }
243
            }
244
        }
245
        b = KeypathDict(d)
246
        self.assertEqual(b.get('a.b.c', 2), 1)
247
248
    def test_get_with_3_invalid_keys(self):
249
        d = {
250
            'a': {
251
                'b': {
252
                    'c': 1
253
                }
254
            }
255
        }
256
        b = KeypathDict(d)
257
        self.assertEqual(b.get('c.b.a', 2), 2)
258
259
    def test_get_with_keys_list(self):
260
        d = {
261
            'a': {
262
                'b': {
263
                    'c': 1,
264
                    'd': 2,
265
                },
266
            },
267
        }
268
        b = KeypathDict(d)
269
        self.assertEqual(b.get(['a', 'b.c']), 1)
270
        self.assertEqual(b.get(['a', 'b', 'c']), 1)
271
        self.assertEqual(b.get(['a', 'b', 'd']), 2)
272
        self.assertEqual(b.get(['a', 'b', 'e']), None)
273
274
    def test_get_with_keys_list_and_no_keypath_separator(self):
275
        d = {
276
            'a': {
277
                'b': {
278
                    'c': 1,
279
                    'd': 2,
280
                },
281
            },
282
        }
283
        b = KeypathDict(d, keypath_separator=None)
284
        self.assertEqual(b.get(['a', 'b.c']), None)
285
        self.assertEqual(b.get(['a', 'b', 'c']), 1)
286
        self.assertEqual(b.get(['a', 'b', 'd']), 2)
287
        self.assertEqual(b.get(['a', 'b', 'e']), None)
288
289
    def test_getitem_with_3_valid_keys(self):
290
        d = {
291
            'a': {
292
                'b': {
293
                    'c': 1
294
                }
295
            }
296
        }
297
        b = KeypathDict(d)
298
        self.assertEqual(b['a.b.c'], 1)
299
300
    def test_getitem_with_3_invalid_keys(self):
301
        d = {
302
            'a': {
303
                'b': {
304
                    'c': 1
305
                }
306
            }
307
        }
308
        b = KeypathDict(d)
309
        with self.assertRaises(KeyError):
310
            val = b['c.b.a']
311
            print(val)
312
313
    def test_get_item_with_keys_list(self):
314
        d = {
315
            'a': {
316
                'b': {
317
                    'c': 1,
318
                    'd': 2,
319
                },
320
            },
321
        }
322
        b = KeypathDict(d)
323
        self.assertEqual(b['a', 'b.c'], 1)
324
        self.assertEqual(b['a', 'b', 'c'], 1)
325
        self.assertEqual(b['a', 'b', 'd'], 2)
326
        with self.assertRaises(KeyError):
327
            val = b['a', 'b', 'e']
328
            print(val)
329
330
    def test_get_item_with_keys_list_and_no_keypath_separator(self):
331
        d = {
332
            'a': {
333
                'b': {
334
                    'c': 1,
335
                    'd': 2,
336
                },
337
            },
338
        }
339
        b = KeypathDict(d, keypath_separator=None)
340
        with self.assertRaises(KeyError):
341
            val = b['a', 'b.c']
342
            print(val)
343
        self.assertEqual(b['a', 'b', 'c'], 1)
344
        self.assertEqual(b['a', 'b', 'd'], 2)
345
        with self.assertRaises(KeyError):
346
            val = b['a', 'b', 'e']
347
            print(val)
348
349
    def test_has_with_1_key(self):
350
        d = {
351
            'a': 0,
352
            'b': None,
353
            'c': {},
354
        }
355
        b = KeypathDict(d)
356
        self.assertTrue('a' in b)
357
        self.assertTrue('b' in b)
358
        self.assertTrue('c' in b)
359
        self.assertFalse('d' in b)
360
361
    def test_has_with_2_keys(self):
362
        d = {
363
            'a': {
364
                'a': 0,
365
                'b': None,
366
                'c': {},
367
            },
368
        }
369
        b = KeypathDict(d)
370
        self.assertTrue('a.a' in b)
371
        self.assertTrue('a.b' in b)
372
        self.assertTrue('a.c' in b)
373
        self.assertFalse('a.d' in b)
374
        self.assertFalse('b' in b)
375
        self.assertFalse('b.a' in b)
376
377
    def test_has_with_3_keys(self):
378
        d = {
379
            'a': {
380
                'b': {
381
                    'c': 0,
382
                    'd': None,
383
                    'e': {},
384
                },
385
            },
386
        }
387
        b = KeypathDict(d)
388
        self.assertTrue('a.b.c' in b)
389
        self.assertTrue('a.b.d' in b)
390
        self.assertTrue('a.b.e' in b)
391
        self.assertFalse('a.b.f' in b)
392
        self.assertFalse('b.f' in b)
393
        self.assertFalse('f' in b)
394
395
    def test_has_with_keys_list(self):
396
        d = {
397
            'a': {
398
                'b': {
399
                    'c': 1,
400
                    'd': 2,
401
                },
402
            },
403
        }
404
        b = KeypathDict(d)
405
        self.assertTrue(['a', 'b.c'] in b)
406
        self.assertTrue(['a', 'b', 'c'] in b)
407
        self.assertTrue(['a', 'b', 'd'] in b)
408
        self.assertFalse(['a', 'b', 'e'] in b)
409
410
    def test_has_with_keys_list_and_no_keypath_separator(self):
411
        d = {
412
            'a': {
413
                'b': {
414
                    'c': 1,
415
                    'd': 2,
416
                },
417
            },
418
        }
419
        b = KeypathDict(d, keypath_separator=None)
420
        self.assertFalse(['a', 'b.c'] in b)
421
        self.assertTrue(['a', 'b', 'c'] in b)
422
        self.assertTrue(['a', 'b', 'd'] in b)
423
        self.assertFalse(['a', 'b', 'e'] in b)
424
425
    def test_keypath_separator_getter_setter(self):
426
        d = KeypathDict({}, keypath_separator=None)
427
        self.assertEqual(d.keypath_separator, None)
428
        d['a.b.c'] = 1
429
        with self.assertRaises(ValueError):
430
            d.keypath_separator = '.'
431
        d.keypath_separator = '/'
432
        self.assertEqual(d.keypath_separator, '/')
433
        d['x/y/z'] = 2
434
        r = {
435
            'a.b.c': 1,
436
            'x': {
437
                'y': {
438
                    'z': 2,
439
                },
440
            },
441
        }
442
        self.assertEqual(d, r)
443
444
    def test_set_override_existing_item(self):
445
        d = {}
446
        b = KeypathDict(d)
447
        b.set('a.b.c', 1)
448
        r = {
449
            'a': {
450
                'b': {
451
                    'c': 1
452
                }
453
            }
454
        }
455
        b.set('a.b.c', 2)
456
        r = {
457
            'a': {
458
                'b': {
459
                    'c': 2
460
                }
461
            }
462
        }
463
        self.assertEqual(b, r)
464
        b.set('a.b.c.d', 3)
465
        r = {
466
            'a': {
467
                'b': {
468
                    'c': {
469
                        'd': 3
470
                    }
471
                }
472
            }
473
        }
474
        self.assertEqual(b, r)
475
476
    def test_setitem_override_existing_item(self):
477
        d = {}
478
        b = KeypathDict(d)
479
        b['a.b.c'] = 1
480
        r = {
481
            'a': {
482
                'b': {
483
                    'c': 1
484
                }
485
            }
486
        }
487
        b['a.b.c'] = 2
488
        r = {
489
            'a': {
490
                'b': {
491
                    'c': 2
492
                }
493
            }
494
        }
495
        self.assertEqual(b, r)
496
        b['a.b.c.d'] = 3
497
        r = {
498
            'a': {
499
                'b': {
500
                    'c': {
501
                        'd': 3
502
                    }
503
                }
504
            }
505
        }
506
        self.assertEqual(b, r)
507
508
    def test_setitem_with_keys_list(self):
509
        d = {
510
            'a': {
511
                'b': {
512
                    'c': 1,
513
                    'd': 2,
514
                },
515
            },
516
        }
517
        b = KeypathDict(d)
518
        b['a', 'b.c'] = 2
519
        self.assertEqual(b['a.b.c'], 2)
520
        b['a', 'b', 'c'] = 3
521
        self.assertEqual(b['a.b.c'], 3)
522
        b['a', 'b', 'd'] = 4
523
        self.assertEqual(b['a.b.d'], 4)
524
        b['a', 'b', 'e'] = 5
525
        self.assertEqual(b['a.b.e'], 5)
526
527
    def test_setitem_with_keys_list_and_no_keypath_separator(self):
528
        d = {
529
            'a': {
530
                'b': {
531
                    'c': 1,
532
                    'd': 2,
533
                },
534
            },
535
        }
536
        b = KeypathDict(d, keypath_separator=None)
537
        b['a', 'b', 'c'] = 3
538
        with self.assertRaises(KeyError):
539
            val = b['a.b.c']
540
            print(val)
541
        self.assertEqual(b['a', 'b', 'c'], 3)
542
543
        b['a', 'b', 'd'] = 4
544
        with self.assertRaises(KeyError):
545
            val = b['a.b.d']
546
            print(val)
547
        self.assertEqual(b['a', 'b', 'd'], 4)
548
549
        b['a', 'b', 'e'] = 5
550
        with self.assertRaises(KeyError):
551
            val = b['a.b.e']
552
            print(val)
553
        self.assertEqual(b['a', 'b', 'e'], 5)
554
555
    def test_setitem_with_dict_value_with_separator_in_keys(self):
556
        d = {
557
            'a': {
558
                'b': {
559
                    'c': 1,
560
                    'd': 2,
561
                },
562
            },
563
        }
564
        b = KeypathDict(d)
565
        v = {
566
            'i.j.k': 3,
567
            'x.y.z': 4,
568
        }
569
        # print(b['a.b.e.x.y.z'])
570
        # print(b.keypaths())
571
        with self.assertRaises(ValueError):
572
            b['a.b.e'] = v
573
574
    def test_delitem_with_1_valid_key(self):
575
        d = {
576
            'a': 1,
577
        }
578
        b = KeypathDict(d)
579
        del b['a']
580
        with self.assertRaises(KeyError):
581
            del b['a']
582
        self.assertEqual(b.get('a'), None)
583
584
    def test_delitem_with_1_invalid_key(self):
585
        d = {
586
            'a': 1,
587
        }
588
        b = KeypathDict(d)
589
        with self.assertRaises(KeyError):
590
            del b['b']
591
        self.assertEqual(b.get('b'), None)
592
593
    def test_delitem_with_2_valid_keys(self):
594
        d = {
595
            'a': {
596
                'b': 1,
597
            }
598
        }
599
        b = KeypathDict(d)
600
601
        del b['a.b']
602
        with self.assertRaises(KeyError):
603
            del b['a.b']
604
        self.assertEqual(b.get('a'), {})
605
606
        del b['a']
607
        with self.assertRaises(KeyError):
608
            del b['a']
609
        self.assertEqual(b.get('a'), None)
610
611
    def test_delitem_with_2_invalid_keys(self):
612
        d = {
613
            'a': {
614
                'b': 1,
615
            }
616
        }
617
        b = KeypathDict(d)
618
        with self.assertRaises(KeyError):
619
            del b['a.c']
620
        self.assertEqual(b.get('a'), { 'b': 1 })
621
622
    def test_delitem_with_3_valid_keys(self):
623
        d = {
624
            'a': {
625
                'b': {
626
                    'c': 1,
627
                    'd': 2,
628
                },
629
            }
630
        }
631
        b = KeypathDict(d)
632
633
        del b['a.b.c']
634
        with self.assertRaises(KeyError):
635
            del b['a.b.c']
636
        self.assertEqual(b.get('a.b'), { 'd':2 })
637
638
        del b['a.b.d']
639
        with self.assertRaises(KeyError):
640
            del b['a.b.d']
641
        self.assertEqual(b.get('a.b'), {})
642
643
        del b['a.b']
644
        with self.assertRaises(KeyError):
645
            del b['a.b']
646
        self.assertEqual(b.get('a.b'), None)
647
648
    def test_delitem_with_3_invalid_keys(self):
649
        d = {
650
            'a': {
651
                'b': {
652
                    'c': 1,
653
                    'd': 2,
654
                },
655
            }
656
        }
657
        b = KeypathDict(d)
658
        with self.assertRaises(KeyError):
659
            del b['a.b.c.d']
660
        self.assertEqual(b.get('a.b.c'), 1)
661
662
    def test_delitem_with_keys_list(self):
663
        d = {
664
            'a': {
665
                'b': {
666
                    'c': 1,
667
                    'd': 2,
668
                },
669
            }
670
        }
671
        b = KeypathDict(d)
672
        with self.assertRaises(KeyError):
673
            del b['a', 'b', 'c', 'd']
674
        del b['a', 'b', 'c']
675
        self.assertEqual(b.get('a.b.c', 3), 3)
676
677
    def test_delitem_with_keys_list_and_no_keypath_separator(self):
678
        d = {
679
            'a': {
680
                'b': {
681
                    'c': 1,
682
                    'd': 2,
683
                },
684
            }
685
        }
686
        b = KeypathDict(d, keypath_separator=None)
687
        with self.assertRaises(KeyError):
688
            del b['a', 'b', 'c', 'd']
689
        del b['a', 'b', 'c']
690
        self.assertEqual(b.get('a.b.c', 3), 3)
691
692
    def test_pop_default(self):
693
        d = {
694
            'a': 1,
695
        }
696
        b = KeypathDict(d)
697
        val = b.pop('b', 2)
698
        self.assertEqual(val, 2)
699
        val = b.pop('c', default=3)
700
        self.assertEqual(val, 3)
701
702
    def test_pop_with_1_valid_key(self):
703
        d = {
704
            'a': 1,
705
        }
706
        b = KeypathDict(d)
707
        val = b.pop('a')
708
        self.assertEqual(val, 1)
709
710
    def test_pop_with_1_invalid_key(self):
711
        d = {
712
            'a': 1,
713
        }
714
        b = KeypathDict(d)
715
        with self.assertRaises(KeyError):
716
            val = b.pop('b')
717
        val = b.pop('b', False)
718
        self.assertFalse(val)
719
        val = b.pop('b', None)
720
        self.assertEqual(val, None)
721
722
    def test_pop_with_2_valid_keys(self):
723
        d = {
724
            'a': {
725
                'b': 1,
726
            }
727
        }
728
        b = KeypathDict(d)
729
730
        val = b.pop('a.b')
731
        with self.assertRaises(KeyError):
732
            val = b.pop('a.b')
733
        self.assertEqual(val, 1)
734
735
        val = b.pop('a')
736
        with self.assertRaises(KeyError):
737
            val = b.pop('a')
738
        self.assertEqual(val, {})
739
740
    def test_pop_with_2_invalid_keys(self):
741
        d = {
742
            'a': {
743
                'b': 1,
744
            }
745
        }
746
        b = KeypathDict(d)
747
748
        val = b.pop('a.c', 2)
749
        self.assertEqual(val, 2)
750
        with self.assertRaises(KeyError):
751
            val = b.pop('a.c')
752
        self.assertEqual(b.get('a'), { 'b': 1 })
753
754
        val = b.pop('x.y', 1)
755
        self.assertEqual(val, 1)
756
        with self.assertRaises(KeyError):
757
            val = b.pop('x.y')
758
759
    def test_pop_with_keys_list(self):
760
        d = {
761
            'a': {
762
                'b': 1,
763
            }
764
        }
765
        b = KeypathDict(d)
766
767
        val = b.pop(['a', 'c'], 2)
768
        self.assertEqual(val, 2)
769
        with self.assertRaises(KeyError):
770
            val = b.pop(['a', 'c'])
771
        self.assertEqual(b.get('a'), { 'b': 1 })
772
773
        val = b.pop(['x', 'y'], 1)
774
        self.assertEqual(val, 1)
775
        with self.assertRaises(KeyError):
776
            val = b.pop(['x', 'y'])
777
778
        val = b.pop(['a', 'b'])
779
        self.assertEqual(val, 1)
780
781
    def test_pop_with_keys_list_and_no_keypath_separator(self):
782
        d = {
783
            'a': {
784
                'b': 1,
785
            }
786
        }
787
        b = KeypathDict(d, keypath_separator=None)
788
789
        val = b.pop(['a', 'c'], 2)
790
        self.assertEqual(val, 2)
791
        with self.assertRaises(KeyError):
792
            val = b.pop(['a', 'c'])
793
        self.assertEqual(b.get('a'), { 'b': 1 })
794
795
        val = b.pop(['x', 'y'], 1)
796
        self.assertEqual(val, 1)
797
        with self.assertRaises(KeyError):
798
            val = b.pop(['x', 'y'])
799
800
        val = b.pop(['a', 'b'])
801
        self.assertEqual(val, 1)
802
803
    def test_setdefault_with_1_key(self):
804
        d = {
805
            'a': None,
806
            'b': 0,
807
            'c': 1,
808
        }
809
        b = KeypathDict(d)
810
        b.setdefault('a', 2)
811
        b.setdefault('b', 2)
812
        b.setdefault('c', 2)
813
        b.setdefault('d', 2)
814
        self.assertEqual(b['a'], None)
815
        self.assertEqual(b['b'], 0)
816
        self.assertEqual(b['c'], 1)
817
        self.assertEqual(b['d'], 2)
818
819
    def test_setdefault_with_2_keys(self):
820
        d = {
821
            'x': {
822
                'a': None,
823
                'b': 0,
824
                'c': 1,
825
            },
826
        }
827
        b = KeypathDict(d)
828
        b.setdefault('x.a', 2)
829
        b.setdefault('x.b', 2)
830
        b.setdefault('x.c', 2)
831
        b.setdefault('x.d', 2)
832
        self.assertEqual(b['x.a'], None)
833
        self.assertEqual(b['x.b'], 0)
834
        self.assertEqual(b['x.c'], 1)
835
        self.assertEqual(b['x.d'], 2)
836
837
    def test_setdefault_with_3_keys(self):
838
        d = {
839
            'y': {
840
                'z': {
841
                    'a': None,
842
                    'b': 0,
843
                    'c': 1,
844
                },
845
            },
846
        }
847
        b = KeypathDict(d)
848
        b.setdefault('y.z.a', 2)
849
        b.setdefault('y.z.b', 2)
850
        b.setdefault('y.z.c', 2)
851
        b.setdefault('y.z.d', 2)
852
        self.assertEqual(b['y.z.a'], None)
853
        self.assertEqual(b['y.z.b'], 0)
854
        self.assertEqual(b['y.z.c'], 1)
855
        self.assertEqual(b['y.z.d'], 2)
856