python-benedict/tests/test_keypath_dict.py

856 lines
21 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
from benedict.dicts.keypath import KeypathDict
import unittest
class keypath_dict_test_case(unittest.TestCase):
def test_init_with_custom_separator(self):
d = {
'a.b': {
'c.d': 1,
'e.f': 2,
},
'g.h': {
'i.j': 3,
'k.l': 4,
},
}
b = KeypathDict(d, keypath_separator='/')
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,
},
}
b = KeypathDict(d, keypath_separator=None)
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):
KeypathDict(d)
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)
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,
}
b = KeypathDict(d1, keypath_separator='/')
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)
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)
def test_get_with_keys_list(self):
d = {
'a': {
'b': {
'c': 1,
'd': 2,
},
},
}
b = KeypathDict(d)
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)
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)
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)
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)
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)
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)
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)
def test_has_with_keys_list_and_no_keypath_separator(self):
d = {
'a': {
'b': {
'c': 1,
'd': 2,
},
},
}
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)
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)
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)
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)
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
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)
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)
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)
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)
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)
val = b.pop('b', None)
self.assertEqual(val, None)
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')
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'])
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)
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 = {
'x': {
'a': None,
'b': 0,
'c': 1,
},
}
b = KeypathDict(d)
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)
def test_setdefault_with_3_keys(self):
d = {
'y': {
'z': {
'a': None,
'b': 0,
'c': 1,
},
},
}
b = KeypathDict(d)
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)