fixes #7 : 'items' return always the first key of a given type associated with a value
Internally changes the key-dicts by type to use OrderedDicts. Therefore, when requesting the items(key_type=str) for a value defined as m["abc", "def"] = 123 The returned item will always have the key "abc" for 123, and never "def". Previous behavior was undefined. Also changes tests that relied on the return order of "items": The multi_dict is not expected to work as an OrderedDict itself, and code should not rely on this.
This commit is contained in:
parent
92b2935f20
commit
6f0dc223ee
@ -27,9 +27,10 @@ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|||||||
DEALINGS IN THE SOFTWARE.
|
DEALINGS IN THE SOFTWARE.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
from collections import OrderedDict
|
||||||
import sys
|
import sys
|
||||||
_python3 = sys.version_info.major >= 3
|
_python3 = sys.version_info.major >= 3
|
||||||
del sys
|
|
||||||
|
|
||||||
class multi_key_dict(object):
|
class multi_key_dict(object):
|
||||||
""" The purpose of this type is to provide a multi-key dictionary.
|
""" The purpose of this type is to provide a multi-key dictionary.
|
||||||
@ -279,7 +280,7 @@ class multi_key_dict(object):
|
|||||||
|
|
||||||
# store direct key as a value in an intermediate dictionary
|
# store direct key as a value in an intermediate dictionary
|
||||||
if(not key_type in self.__dict__):
|
if(not key_type in self.__dict__):
|
||||||
self.__setattr__(key_type, dict())
|
self.__setattr__(key_type, OrderedDict())
|
||||||
self.__dict__[key_type][key] = direct_key
|
self.__dict__[key_type][key] = direct_key
|
||||||
|
|
||||||
# store the value in the actual dictionary
|
# store the value in the actual dictionary
|
||||||
@ -439,7 +440,7 @@ def test_multi_key_dict():
|
|||||||
assert (current_values == vals), 'itervalues(): expected {0}, but collected {1}'.format(current_values, vals)
|
assert (current_values == vals), 'itervalues(): expected {0}, but collected {1}'.format(current_values, vals)
|
||||||
|
|
||||||
#test items(int)
|
#test items(int)
|
||||||
items_for_int = sorted([(32, '4'), (23, 0)])
|
items_for_int = sorted([(12, '4'), (23, 0)])
|
||||||
assert (items_for_int == sorted(m.items(int))), 'items(int): expected {0}, but collected {1}'.format(items_for_int,
|
assert (items_for_int == sorted(m.items(int))), 'items(int): expected {0}, but collected {1}'.format(items_for_int,
|
||||||
sorted(m.items(int)))
|
sorted(m.items(int)))
|
||||||
|
|
||||||
@ -450,13 +451,13 @@ def test_multi_key_dict():
|
|||||||
|
|
||||||
# test items() (default - all items)
|
# test items() (default - all items)
|
||||||
# we tested keys(), values(), and __get_item__ above so here we'll re-create all_items using that
|
# we tested keys(), values(), and __get_item__ above so here we'll re-create all_items using that
|
||||||
all_items = []
|
all_items = set()
|
||||||
keys = m.keys()
|
keys = m.keys()
|
||||||
values = m.values()
|
values = m.values()
|
||||||
for k in keys:
|
for k in keys:
|
||||||
all_items.append( (tuple(k), m[k[0]]) )
|
all_items.add( (tuple(k), m[k[0]]) )
|
||||||
|
|
||||||
res = list(m.items())
|
res = set(m.items())
|
||||||
assert (all_items == res), 'items() (all items): expected {0},\n\t\t\t\tbut collected {1}'.format(all_items, res)
|
assert (all_items == res), 'items() (all items): expected {0},\n\t\t\t\tbut collected {1}'.format(all_items, res)
|
||||||
|
|
||||||
# now test deletion..
|
# now test deletion..
|
||||||
@ -496,23 +497,22 @@ def test_multi_key_dict():
|
|||||||
|
|
||||||
# test iterkeys()
|
# test iterkeys()
|
||||||
num_of_elements = 0
|
num_of_elements = 0
|
||||||
curr_index_in_range = 0
|
returned_keys = set()
|
||||||
for key in m.iterkeys(int):
|
for key in m.iterkeys(int):
|
||||||
expected = tst_range[curr_index_in_range]
|
returned_keys.add(key)
|
||||||
assert (key == expected), 'iterkeys(int): expected {0}, but received {1}'.format(expected, key)
|
|
||||||
curr_index_in_range += 1
|
|
||||||
num_of_elements += 1
|
num_of_elements += 1
|
||||||
assert(num_of_elements > 0), 'm.iteritems(int) returned generator that did not produce anything'
|
assert(num_of_elements > 0), 'm.iteritems(int) returned generator that did not produce anything'
|
||||||
|
assert (returned_keys == set(tst_range)), 'iterkeys(int): expected {0}, but received {1}'.format(expected, key)
|
||||||
|
|
||||||
|
|
||||||
#test itervalues(int)
|
#test itervalues(int)
|
||||||
curr_index_in_range = 0
|
|
||||||
num_of_elements = 0
|
num_of_elements = 0
|
||||||
|
returned_values = set()
|
||||||
for value in m.itervalues(int):
|
for value in m.itervalues(int):
|
||||||
expected = tst_range[curr_index_in_range]
|
returned_values.add(value)
|
||||||
assert (value == expected), 'itervalues(int): expected {0}, but received {1}'.format(expected, value)
|
|
||||||
curr_index_in_range += 1
|
|
||||||
num_of_elements += 1
|
num_of_elements += 1
|
||||||
assert (num_of_elements > 0), 'm.itervalues(int) returned generator that did not produce anything'
|
assert (num_of_elements > 0), 'm.itervalues(int) returned generator that did not produce anything'
|
||||||
|
assert (returned_values == set(tst_range)), 'itervalues(int): expected {0}, but received {1}'.format(expected, value)
|
||||||
|
|
||||||
# test values(int)
|
# test values(int)
|
||||||
res = sorted([x for x in m.values(int)])
|
res = sorted([x for x in m.values(int)])
|
||||||
@ -601,6 +601,8 @@ def test_multi_key_dict():
|
|||||||
|
|
||||||
print ('All test passed OK!')
|
print ('All test passed OK!')
|
||||||
|
|
||||||
|
__all__ = ["multi_key_dict"]
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
try:
|
try:
|
||||||
test_multi_key_dict()
|
test_multi_key_dict()
|
||||||
|
Loading…
Reference in New Issue
Block a user