2019-06-10 09:59:16 +00:00
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
2019-06-11 11:07:02 +00:00
|
|
|
|
from benedict.dicts.keypath import KeypathDict
|
2019-06-10 09:59:16 +00:00
|
|
|
|
|
|
|
|
|
import unittest
|
|
|
|
|
|
|
|
|
|
|
2019-11-07 16:47:12 +00:00
|
|
|
|
class keypath_dict_test_case(unittest.TestCase):
|
2019-06-10 09:59:16 +00:00
|
|
|
|
|
2019-07-09 10:55:34 +00:00
|
|
|
|
def test_init_with_custom_separator(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a.b': {
|
|
|
|
|
'c.d': 1,
|
|
|
|
|
'e.f': 2,
|
|
|
|
|
},
|
|
|
|
|
'g.h': {
|
|
|
|
|
'i.j': 3,
|
|
|
|
|
'k.l': 4,
|
|
|
|
|
},
|
|
|
|
|
}
|
2019-07-09 14:03:41 +00:00
|
|
|
|
b = KeypathDict(d, keypath_separator='/')
|
2019-07-09 10:55:34 +00:00
|
|
|
|
self.assertEqual(b.get('a.b/c.d'), 1)
|
|
|
|
|
self.assertEqual(b.get('a.b/e.f'), 2)
|
|
|
|
|
self.assertEqual(b.get('g.h/i.j'), 3)
|
|
|
|
|
self.assertEqual(b.get('g.h/k.l'), 4)
|
|
|
|
|
|
|
|
|
|
def test_init_without_keypath_separator(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': 1,
|
|
|
|
|
'c': 2,
|
|
|
|
|
},
|
|
|
|
|
'd': {
|
|
|
|
|
'e': 3,
|
|
|
|
|
'f': 4,
|
|
|
|
|
},
|
|
|
|
|
}
|
2019-07-09 14:03:41 +00:00
|
|
|
|
b = KeypathDict(d, keypath_separator=None)
|
2019-07-09 10:55:34 +00:00
|
|
|
|
self.assertEqual(b.get('a.b'), None)
|
|
|
|
|
self.assertEqual(b.get('a.c'), None)
|
|
|
|
|
self.assertEqual(b.get('d.e'), None)
|
|
|
|
|
self.assertEqual(b.get('d.f'), None)
|
|
|
|
|
|
|
|
|
|
def test_init_with_dict_with_separator_in_keys(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a.b.c': 1,
|
|
|
|
|
'c.d.e': 2,
|
|
|
|
|
}
|
|
|
|
|
with self.assertRaises(ValueError):
|
2019-10-04 08:45:21 +00:00
|
|
|
|
KeypathDict(d)
|
2019-07-09 10:55:34 +00:00
|
|
|
|
|
|
|
|
|
def test_update_with_dict_with_separator_in_keys(self):
|
|
|
|
|
d1 = {
|
|
|
|
|
'a': 1,
|
|
|
|
|
'b': 2,
|
|
|
|
|
'c': 3,
|
|
|
|
|
}
|
|
|
|
|
d2 = {
|
|
|
|
|
'a.x': 4,
|
|
|
|
|
'a.y': 5,
|
|
|
|
|
'a.z': 6,
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d1)
|
|
|
|
|
with self.assertRaises(ValueError):
|
|
|
|
|
b.update(d2)
|
|
|
|
|
|
2019-07-09 11:09:35 +00:00
|
|
|
|
def test_update_with_dict_without_separator_in_keys(self):
|
|
|
|
|
d1 = {
|
|
|
|
|
'a': 1,
|
|
|
|
|
'b': 2,
|
|
|
|
|
'c': 3,
|
|
|
|
|
}
|
|
|
|
|
d2 = {
|
|
|
|
|
'a.x': 4,
|
|
|
|
|
'a.y': 5,
|
|
|
|
|
'a.z': 6,
|
|
|
|
|
}
|
2019-07-09 14:03:41 +00:00
|
|
|
|
b = KeypathDict(d1, keypath_separator='/')
|
2019-07-09 11:09:35 +00:00
|
|
|
|
b.update(d2)
|
|
|
|
|
self.assertEqual(b.get('a'), 1)
|
|
|
|
|
self.assertEqual(b.get('b'), 2)
|
|
|
|
|
self.assertEqual(b.get('c'), 3)
|
|
|
|
|
self.assertEqual(b.get('a.x'), 4)
|
|
|
|
|
self.assertEqual(b.get('a.y'), 5)
|
|
|
|
|
self.assertEqual(b.get('a.z'), 6)
|
|
|
|
|
|
2019-06-10 09:59:16 +00:00
|
|
|
|
def test_fromkeys(self):
|
|
|
|
|
k = [
|
|
|
|
|
'a',
|
|
|
|
|
'a.b',
|
|
|
|
|
'a.b.c',
|
|
|
|
|
'a.b.d',
|
|
|
|
|
'a.b.e',
|
|
|
|
|
'x',
|
|
|
|
|
'x.y',
|
|
|
|
|
'x.z',
|
|
|
|
|
]
|
|
|
|
|
b = KeypathDict.fromkeys(k)
|
|
|
|
|
r = {
|
|
|
|
|
'x': {
|
|
|
|
|
'y': None,
|
|
|
|
|
'z': None,
|
|
|
|
|
},
|
|
|
|
|
'a': {
|
|
|
|
|
'b': {
|
|
|
|
|
'c': None,
|
|
|
|
|
'd': None,
|
|
|
|
|
'e': None,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
self.assertEqual(b, r)
|
|
|
|
|
|
|
|
|
|
def test_fromkeys_with_value(self):
|
|
|
|
|
k = [
|
|
|
|
|
'a',
|
|
|
|
|
'a.b',
|
|
|
|
|
'a.b.c',
|
|
|
|
|
'a.b.d',
|
|
|
|
|
'a.b.e',
|
|
|
|
|
'x',
|
|
|
|
|
'x.y',
|
|
|
|
|
'x.z',
|
|
|
|
|
]
|
|
|
|
|
b = KeypathDict.fromkeys(k, True)
|
|
|
|
|
r = {
|
|
|
|
|
'x': {
|
|
|
|
|
'y': True,
|
|
|
|
|
'z': True,
|
|
|
|
|
},
|
|
|
|
|
'a': {
|
|
|
|
|
'b': {
|
|
|
|
|
'c': True,
|
|
|
|
|
'd': True,
|
|
|
|
|
'e': True,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
self.assertEqual(b, r)
|
|
|
|
|
|
|
|
|
|
def test_get_with_1_valid_key(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': 1,
|
|
|
|
|
1: 1
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
self.assertEqual(b.get('a', 2), 1)
|
|
|
|
|
self.assertEqual(b.get(1, 2), 1)
|
|
|
|
|
|
|
|
|
|
def test_get_with_1_invalid_key(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': 1,
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
self.assertEqual(b.get('b', 2), 2)
|
|
|
|
|
|
|
|
|
|
def test_get_with_1_not_str_key(self):
|
|
|
|
|
d = {
|
|
|
|
|
None: None,
|
|
|
|
|
False: False,
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
self.assertEqual(b.get(None, 1), None)
|
|
|
|
|
self.assertEqual(b.get(False, True), False)
|
|
|
|
|
self.assertEqual(b.get(True, True), True)
|
|
|
|
|
self.assertEqual(b.get(0, 1), 0)
|
|
|
|
|
|
|
|
|
|
def test_getitem_with_1_valid_key(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': 1,
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
self.assertEqual(b['a'], 1)
|
|
|
|
|
|
|
|
|
|
def test_getitem_with_1_invalid_key(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': 1,
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
val = b['b']
|
|
|
|
|
print(val)
|
|
|
|
|
|
|
|
|
|
def test_getitem_with_1_not_str_key(self):
|
|
|
|
|
d = {
|
|
|
|
|
None: None,
|
|
|
|
|
False: False,
|
|
|
|
|
# 0: 0,
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
self.assertEqual(b[None], None)
|
|
|
|
|
self.assertEqual(b[False], False)
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
val = b[True]
|
|
|
|
|
print(val)
|
|
|
|
|
|
|
|
|
|
self.assertEqual(b[0], 0)
|
|
|
|
|
|
|
|
|
|
def test_get_with_2_valid_keys(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': 1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
self.assertEqual(b.get('a.b', 2), 1)
|
|
|
|
|
|
|
|
|
|
def test_get_with_2_invalid_keys(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': 1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
self.assertEqual(b.get('b.a', 2), 2)
|
|
|
|
|
|
|
|
|
|
def test_getitem_with_2_valid_keys(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': 1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
self.assertEqual(b['a.b'], 1)
|
|
|
|
|
|
|
|
|
|
def test_getitem_with_2_invalid_keys(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': 1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
val = b['b.a']
|
|
|
|
|
print(val)
|
|
|
|
|
|
|
|
|
|
def test_get_with_3_valid_keys(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': {
|
|
|
|
|
'c': 1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
self.assertEqual(b.get('a.b.c', 2), 1)
|
|
|
|
|
|
|
|
|
|
def test_get_with_3_invalid_keys(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': {
|
|
|
|
|
'c': 1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
self.assertEqual(b.get('c.b.a', 2), 2)
|
|
|
|
|
|
2019-06-11 16:40:23 +00:00
|
|
|
|
def test_get_with_keys_list(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': {
|
|
|
|
|
'c': 1,
|
|
|
|
|
'd': 2,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
2020-01-07 13:38:57 +00:00
|
|
|
|
self.assertEqual(b.get(['a']), {'b': {'c': 1,'d': 2,},})
|
2019-06-11 16:40:23 +00:00
|
|
|
|
self.assertEqual(b.get(['a', 'b.c']), 1)
|
|
|
|
|
self.assertEqual(b.get(['a', 'b', 'c']), 1)
|
|
|
|
|
self.assertEqual(b.get(['a', 'b', 'd']), 2)
|
|
|
|
|
self.assertEqual(b.get(['a', 'b', 'e']), None)
|
|
|
|
|
|
2019-10-29 15:30:01 +00:00
|
|
|
|
def test_get_with_keys_list_and_no_keypath_separator(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': {
|
|
|
|
|
'c': 1,
|
|
|
|
|
'd': 2,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d, keypath_separator=None)
|
|
|
|
|
self.assertEqual(b.get(['a', 'b.c']), None)
|
|
|
|
|
self.assertEqual(b.get(['a', 'b', 'c']), 1)
|
|
|
|
|
self.assertEqual(b.get(['a', 'b', 'd']), 2)
|
|
|
|
|
self.assertEqual(b.get(['a', 'b', 'e']), None)
|
|
|
|
|
|
2019-06-10 09:59:16 +00:00
|
|
|
|
def test_getitem_with_3_valid_keys(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': {
|
|
|
|
|
'c': 1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
self.assertEqual(b['a.b.c'], 1)
|
|
|
|
|
|
|
|
|
|
def test_getitem_with_3_invalid_keys(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': {
|
|
|
|
|
'c': 1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
val = b['c.b.a']
|
|
|
|
|
print(val)
|
|
|
|
|
|
2019-06-11 16:40:23 +00:00
|
|
|
|
def test_get_item_with_keys_list(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': {
|
|
|
|
|
'c': 1,
|
|
|
|
|
'd': 2,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
self.assertEqual(b['a', 'b.c'], 1)
|
|
|
|
|
self.assertEqual(b['a', 'b', 'c'], 1)
|
|
|
|
|
self.assertEqual(b['a', 'b', 'd'], 2)
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
val = b['a', 'b', 'e']
|
|
|
|
|
print(val)
|
2019-06-10 09:59:16 +00:00
|
|
|
|
|
2019-10-29 15:30:01 +00:00
|
|
|
|
def test_get_item_with_keys_list_and_no_keypath_separator(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': {
|
|
|
|
|
'c': 1,
|
|
|
|
|
'd': 2,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d, keypath_separator=None)
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
val = b['a', 'b.c']
|
|
|
|
|
print(val)
|
|
|
|
|
self.assertEqual(b['a', 'b', 'c'], 1)
|
|
|
|
|
self.assertEqual(b['a', 'b', 'd'], 2)
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
val = b['a', 'b', 'e']
|
|
|
|
|
print(val)
|
|
|
|
|
|
2019-06-10 09:59:16 +00:00
|
|
|
|
def test_has_with_1_key(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': 0,
|
|
|
|
|
'b': None,
|
|
|
|
|
'c': {},
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
self.assertTrue('a' in b)
|
|
|
|
|
self.assertTrue('b' in b)
|
|
|
|
|
self.assertTrue('c' in b)
|
|
|
|
|
self.assertFalse('d' in b)
|
|
|
|
|
|
|
|
|
|
def test_has_with_2_keys(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'a': 0,
|
|
|
|
|
'b': None,
|
|
|
|
|
'c': {},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
self.assertTrue('a.a' in b)
|
|
|
|
|
self.assertTrue('a.b' in b)
|
|
|
|
|
self.assertTrue('a.c' in b)
|
|
|
|
|
self.assertFalse('a.d' in b)
|
|
|
|
|
self.assertFalse('b' in b)
|
|
|
|
|
self.assertFalse('b.a' in b)
|
|
|
|
|
|
|
|
|
|
def test_has_with_3_keys(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': {
|
|
|
|
|
'c': 0,
|
|
|
|
|
'd': None,
|
|
|
|
|
'e': {},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
self.assertTrue('a.b.c' in b)
|
|
|
|
|
self.assertTrue('a.b.d' in b)
|
|
|
|
|
self.assertTrue('a.b.e' in b)
|
|
|
|
|
self.assertFalse('a.b.f' in b)
|
|
|
|
|
self.assertFalse('b.f' in b)
|
|
|
|
|
self.assertFalse('f' in b)
|
|
|
|
|
|
2019-06-11 16:40:23 +00:00
|
|
|
|
def test_has_with_keys_list(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': {
|
|
|
|
|
'c': 1,
|
|
|
|
|
'd': 2,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
self.assertTrue(['a', 'b.c'] in b)
|
|
|
|
|
self.assertTrue(['a', 'b', 'c'] in b)
|
|
|
|
|
self.assertTrue(['a', 'b', 'd'] in b)
|
|
|
|
|
self.assertFalse(['a', 'b', 'e'] in b)
|
|
|
|
|
|
2019-10-29 15:30:01 +00:00
|
|
|
|
def test_has_with_keys_list_and_no_keypath_separator(self):
|
2019-06-10 09:59:16 +00:00
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': {
|
2019-10-29 15:30:01 +00:00
|
|
|
|
'c': 1,
|
|
|
|
|
'd': 2,
|
2019-06-10 09:59:16 +00:00
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
2019-10-29 15:30:01 +00:00
|
|
|
|
b = KeypathDict(d, keypath_separator=None)
|
|
|
|
|
self.assertFalse(['a', 'b.c'] in b)
|
|
|
|
|
self.assertTrue(['a', 'b', 'c'] in b)
|
|
|
|
|
self.assertTrue(['a', 'b', 'd'] in b)
|
|
|
|
|
self.assertFalse(['a', 'b', 'e'] in b)
|
|
|
|
|
|
|
|
|
|
def test_keypath_separator_getter_setter(self):
|
|
|
|
|
d = KeypathDict({}, keypath_separator=None)
|
|
|
|
|
self.assertEqual(d.keypath_separator, None)
|
|
|
|
|
d['a.b.c'] = 1
|
|
|
|
|
with self.assertRaises(ValueError):
|
|
|
|
|
d.keypath_separator = '.'
|
|
|
|
|
d.keypath_separator = '/'
|
|
|
|
|
self.assertEqual(d.keypath_separator, '/')
|
|
|
|
|
d['x/y/z'] = 2
|
|
|
|
|
r = {
|
|
|
|
|
'a.b.c': 1,
|
|
|
|
|
'x': {
|
|
|
|
|
'y': {
|
|
|
|
|
'z': 2,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
self.assertEqual(d, r)
|
2019-06-10 09:59:16 +00:00
|
|
|
|
|
|
|
|
|
def test_set_override_existing_item(self):
|
|
|
|
|
d = {}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
b.set('a.b.c', 1)
|
|
|
|
|
r = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': {
|
|
|
|
|
'c': 1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
b.set('a.b.c', 2)
|
|
|
|
|
r = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': {
|
|
|
|
|
'c': 2
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
self.assertEqual(b, r)
|
|
|
|
|
b.set('a.b.c.d', 3)
|
|
|
|
|
r = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': {
|
|
|
|
|
'c': {
|
|
|
|
|
'd': 3
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
self.assertEqual(b, r)
|
|
|
|
|
|
|
|
|
|
def test_setitem_override_existing_item(self):
|
|
|
|
|
d = {}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
b['a.b.c'] = 1
|
|
|
|
|
r = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': {
|
|
|
|
|
'c': 1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
b['a.b.c'] = 2
|
|
|
|
|
r = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': {
|
|
|
|
|
'c': 2
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
self.assertEqual(b, r)
|
|
|
|
|
b['a.b.c.d'] = 3
|
|
|
|
|
r = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': {
|
|
|
|
|
'c': {
|
|
|
|
|
'd': 3
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
self.assertEqual(b, r)
|
|
|
|
|
|
2019-06-11 16:40:23 +00:00
|
|
|
|
def test_setitem_with_keys_list(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': {
|
|
|
|
|
'c': 1,
|
|
|
|
|
'd': 2,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
b['a', 'b.c'] = 2
|
|
|
|
|
self.assertEqual(b['a.b.c'], 2)
|
|
|
|
|
b['a', 'b', 'c'] = 3
|
|
|
|
|
self.assertEqual(b['a.b.c'], 3)
|
|
|
|
|
b['a', 'b', 'd'] = 4
|
|
|
|
|
self.assertEqual(b['a.b.d'], 4)
|
|
|
|
|
b['a', 'b', 'e'] = 5
|
|
|
|
|
self.assertEqual(b['a.b.e'], 5)
|
|
|
|
|
|
2019-10-29 15:30:01 +00:00
|
|
|
|
def test_setitem_with_keys_list_and_no_keypath_separator(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': {
|
|
|
|
|
'c': 1,
|
|
|
|
|
'd': 2,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d, keypath_separator=None)
|
|
|
|
|
b['a', 'b', 'c'] = 3
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
val = b['a.b.c']
|
|
|
|
|
print(val)
|
|
|
|
|
self.assertEqual(b['a', 'b', 'c'], 3)
|
|
|
|
|
|
|
|
|
|
b['a', 'b', 'd'] = 4
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
val = b['a.b.d']
|
|
|
|
|
print(val)
|
|
|
|
|
self.assertEqual(b['a', 'b', 'd'], 4)
|
|
|
|
|
|
|
|
|
|
b['a', 'b', 'e'] = 5
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
val = b['a.b.e']
|
|
|
|
|
print(val)
|
|
|
|
|
self.assertEqual(b['a', 'b', 'e'], 5)
|
|
|
|
|
|
2019-07-09 10:55:34 +00:00
|
|
|
|
def test_setitem_with_dict_value_with_separator_in_keys(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': {
|
|
|
|
|
'c': 1,
|
|
|
|
|
'd': 2,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
v = {
|
|
|
|
|
'i.j.k': 3,
|
|
|
|
|
'x.y.z': 4,
|
|
|
|
|
}
|
|
|
|
|
# print(b['a.b.e.x.y.z'])
|
|
|
|
|
# print(b.keypaths())
|
|
|
|
|
with self.assertRaises(ValueError):
|
|
|
|
|
b['a.b.e'] = v
|
|
|
|
|
|
2019-06-10 09:59:16 +00:00
|
|
|
|
def test_delitem_with_1_valid_key(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': 1,
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
del b['a']
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
del b['a']
|
|
|
|
|
self.assertEqual(b.get('a'), None)
|
|
|
|
|
|
|
|
|
|
def test_delitem_with_1_invalid_key(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': 1,
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
del b['b']
|
|
|
|
|
self.assertEqual(b.get('b'), None)
|
|
|
|
|
|
|
|
|
|
def test_delitem_with_2_valid_keys(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': 1,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
|
|
|
|
|
del b['a.b']
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
del b['a.b']
|
|
|
|
|
self.assertEqual(b.get('a'), {})
|
|
|
|
|
|
|
|
|
|
del b['a']
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
del b['a']
|
|
|
|
|
self.assertEqual(b.get('a'), None)
|
|
|
|
|
|
|
|
|
|
def test_delitem_with_2_invalid_keys(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': 1,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
del b['a.c']
|
|
|
|
|
self.assertEqual(b.get('a'), { 'b': 1 })
|
|
|
|
|
|
|
|
|
|
def test_delitem_with_3_valid_keys(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': {
|
|
|
|
|
'c': 1,
|
|
|
|
|
'd': 2,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
|
|
|
|
|
del b['a.b.c']
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
del b['a.b.c']
|
|
|
|
|
self.assertEqual(b.get('a.b'), { 'd':2 })
|
|
|
|
|
|
|
|
|
|
del b['a.b.d']
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
del b['a.b.d']
|
|
|
|
|
self.assertEqual(b.get('a.b'), {})
|
|
|
|
|
|
|
|
|
|
del b['a.b']
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
del b['a.b']
|
|
|
|
|
self.assertEqual(b.get('a.b'), None)
|
|
|
|
|
|
|
|
|
|
def test_delitem_with_3_invalid_keys(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': {
|
|
|
|
|
'c': 1,
|
|
|
|
|
'd': 2,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
del b['a.b.c.d']
|
|
|
|
|
self.assertEqual(b.get('a.b.c'), 1)
|
|
|
|
|
|
2019-06-11 16:40:23 +00:00
|
|
|
|
def test_delitem_with_keys_list(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': {
|
|
|
|
|
'c': 1,
|
|
|
|
|
'd': 2,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
del b['a', 'b', 'c', 'd']
|
|
|
|
|
del b['a', 'b', 'c']
|
|
|
|
|
self.assertEqual(b.get('a.b.c', 3), 3)
|
|
|
|
|
|
2019-10-29 15:30:01 +00:00
|
|
|
|
def test_delitem_with_keys_list_and_no_keypath_separator(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': {
|
|
|
|
|
'c': 1,
|
|
|
|
|
'd': 2,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d, keypath_separator=None)
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
del b['a', 'b', 'c', 'd']
|
|
|
|
|
del b['a', 'b', 'c']
|
|
|
|
|
self.assertEqual(b.get('a.b.c', 3), 3)
|
|
|
|
|
|
2019-09-12 15:14:16 +00:00
|
|
|
|
def test_pop_default(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': 1,
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
val = b.pop('b', 2)
|
|
|
|
|
self.assertEqual(val, 2)
|
|
|
|
|
val = b.pop('c', default=3)
|
|
|
|
|
self.assertEqual(val, 3)
|
|
|
|
|
|
2019-06-10 09:59:16 +00:00
|
|
|
|
def test_pop_with_1_valid_key(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': 1,
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
val = b.pop('a')
|
|
|
|
|
self.assertEqual(val, 1)
|
|
|
|
|
|
|
|
|
|
def test_pop_with_1_invalid_key(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': 1,
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
val = b.pop('b')
|
|
|
|
|
val = b.pop('b', False)
|
|
|
|
|
self.assertFalse(val)
|
2019-07-19 08:58:38 +00:00
|
|
|
|
val = b.pop('b', None)
|
|
|
|
|
self.assertEqual(val, None)
|
2019-06-10 09:59:16 +00:00
|
|
|
|
|
|
|
|
|
def test_pop_with_2_valid_keys(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': 1,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
|
|
|
|
|
val = b.pop('a.b')
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
val = b.pop('a.b')
|
|
|
|
|
self.assertEqual(val, 1)
|
|
|
|
|
|
|
|
|
|
val = b.pop('a')
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
val = b.pop('a')
|
|
|
|
|
self.assertEqual(val, {})
|
|
|
|
|
|
|
|
|
|
def test_pop_with_2_invalid_keys(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': 1,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
|
|
|
|
|
val = b.pop('a.c', 2)
|
|
|
|
|
self.assertEqual(val, 2)
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
val = b.pop('a.c')
|
|
|
|
|
self.assertEqual(b.get('a'), { 'b': 1 })
|
|
|
|
|
|
|
|
|
|
val = b.pop('x.y', 1)
|
|
|
|
|
self.assertEqual(val, 1)
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
val = b.pop('x.y')
|
|
|
|
|
|
2019-06-11 16:40:23 +00:00
|
|
|
|
def test_pop_with_keys_list(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': 1,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
|
|
|
|
|
val = b.pop(['a', 'c'], 2)
|
|
|
|
|
self.assertEqual(val, 2)
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
val = b.pop(['a', 'c'])
|
|
|
|
|
self.assertEqual(b.get('a'), { 'b': 1 })
|
|
|
|
|
|
|
|
|
|
val = b.pop(['x', 'y'], 1)
|
|
|
|
|
self.assertEqual(val, 1)
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
val = b.pop(['x', 'y'])
|
|
|
|
|
|
2019-10-29 15:30:01 +00:00
|
|
|
|
val = b.pop(['a', 'b'])
|
|
|
|
|
self.assertEqual(val, 1)
|
|
|
|
|
|
|
|
|
|
def test_pop_with_keys_list_and_no_keypath_separator(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': {
|
|
|
|
|
'b': 1,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d, keypath_separator=None)
|
|
|
|
|
|
|
|
|
|
val = b.pop(['a', 'c'], 2)
|
|
|
|
|
self.assertEqual(val, 2)
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
val = b.pop(['a', 'c'])
|
|
|
|
|
self.assertEqual(b.get('a'), { 'b': 1 })
|
|
|
|
|
|
|
|
|
|
val = b.pop(['x', 'y'], 1)
|
|
|
|
|
self.assertEqual(val, 1)
|
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
|
val = b.pop(['x', 'y'])
|
|
|
|
|
|
|
|
|
|
val = b.pop(['a', 'b'])
|
|
|
|
|
self.assertEqual(val, 1)
|
|
|
|
|
|
2019-06-10 09:59:16 +00:00
|
|
|
|
def test_setdefault_with_1_key(self):
|
|
|
|
|
d = {
|
|
|
|
|
'a': None,
|
|
|
|
|
'b': 0,
|
|
|
|
|
'c': 1,
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
|
|
|
|
b.setdefault('a', 2)
|
|
|
|
|
b.setdefault('b', 2)
|
|
|
|
|
b.setdefault('c', 2)
|
|
|
|
|
b.setdefault('d', 2)
|
|
|
|
|
self.assertEqual(b['a'], None)
|
|
|
|
|
self.assertEqual(b['b'], 0)
|
|
|
|
|
self.assertEqual(b['c'], 1)
|
|
|
|
|
self.assertEqual(b['d'], 2)
|
|
|
|
|
|
|
|
|
|
def test_setdefault_with_2_keys(self):
|
|
|
|
|
d = {
|
2019-07-05 15:54:50 +00:00
|
|
|
|
'x': {
|
2019-06-10 09:59:16 +00:00
|
|
|
|
'a': None,
|
|
|
|
|
'b': 0,
|
|
|
|
|
'c': 1,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
2019-07-05 15:54:50 +00:00
|
|
|
|
b.setdefault('x.a', 2)
|
|
|
|
|
b.setdefault('x.b', 2)
|
|
|
|
|
b.setdefault('x.c', 2)
|
|
|
|
|
b.setdefault('x.d', 2)
|
|
|
|
|
self.assertEqual(b['x.a'], None)
|
|
|
|
|
self.assertEqual(b['x.b'], 0)
|
|
|
|
|
self.assertEqual(b['x.c'], 1)
|
|
|
|
|
self.assertEqual(b['x.d'], 2)
|
2019-06-10 09:59:16 +00:00
|
|
|
|
|
|
|
|
|
def test_setdefault_with_3_keys(self):
|
|
|
|
|
d = {
|
2019-07-05 15:54:50 +00:00
|
|
|
|
'y': {
|
|
|
|
|
'z': {
|
2019-06-10 09:59:16 +00:00
|
|
|
|
'a': None,
|
|
|
|
|
'b': 0,
|
|
|
|
|
'c': 1,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
b = KeypathDict(d)
|
2019-07-05 15:54:50 +00:00
|
|
|
|
b.setdefault('y.z.a', 2)
|
|
|
|
|
b.setdefault('y.z.b', 2)
|
|
|
|
|
b.setdefault('y.z.c', 2)
|
|
|
|
|
b.setdefault('y.z.d', 2)
|
|
|
|
|
self.assertEqual(b['y.z.a'], None)
|
|
|
|
|
self.assertEqual(b['y.z.b'], 0)
|
|
|
|
|
self.assertEqual(b['y.z.c'], 1)
|
|
|
|
|
self.assertEqual(b['y.z.d'], 2)
|