Last active
November 17, 2018 22:32
-
-
Save riyad/ab352356590db3cb8fc1 to your computer and use it in GitHub Desktop.
MagicDict
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
# | |
# Author: Riyad Preukschas <riyad@informatik.uni-bremen.de> | |
# License: Mozilla Public License 2.0 | |
# | |
from collections import defaultdict | |
class MagicDict(defaultdict): | |
def __init__(self, _name=None, **kwargs): | |
super(MagicDict, self).__init__(**kwargs) | |
self._name = _name | |
def __missing__(self, key): | |
name = "%s[\"%s\"]" %( | |
(self._name if self._name is not None else "mock"), | |
key | |
) | |
result = self[key] = MagicDict(_name=name) | |
return result | |
def __eq__(self, other): | |
return self is other | |
def __ne__(self, other): | |
return not self == other | |
def __repr__(self): | |
"""Overriden to mimic the output of mock.MagicMock | |
""" | |
if self._name is not None: | |
name_string = " name='%s'" % self._name | |
else: | |
name_string = "" | |
return "<%s%s id='%s'>" % ( | |
type(self).__name__, | |
name_string, | |
id(self) | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
# | |
# Author: Riyad Preukschas <riyad@informatik.uni-bremen.de> | |
# License: Mozilla Public License 2.0 | |
# | |
from pytest import raises | |
from magicdict import MagicDict | |
def test_init(): | |
MagicDict() | |
def test_creates_different_object_every_time(): | |
m1 = MagicDict() | |
m2 = MagicDict() | |
assert not m1 == m2 | |
def test_setting_items_via_init(): | |
m = MagicDict(foo="bar") | |
assert "bar" == m["foo"] | |
def test_getting_known_item(): | |
m = MagicDict(foo="bar") | |
assert "bar" == m["foo"] | |
def test_getting_unknwon_item(): | |
m = MagicDict() | |
assert m["foo"] is not None | |
def test_unknown_item_is_magic_dict(): | |
m = MagicDict() | |
assert issubclass(type(m["foo"]), MagicDict) | |
def test_getting_item_in_unknown_item(): | |
m = MagicDict() | |
assert m["foo"]["bar"] is not None | |
def test_item_in_unknown_item_is_magic_dict(): | |
m = MagicDict() | |
assert issubclass(type(m["foo"]["bar"]), MagicDict) | |
def test_caching_of_accessed_unknown_items(): | |
m = MagicDict() | |
previous_value = m["foo"] | |
assert previous_value is m["foo"] | |
def test_caching_of_accessed_unknown_items_is_per_instance(): | |
m1 = MagicDict() | |
m1["foo"] | |
m2 = MagicDict() | |
m2["foo"] | |
assert m1["foo"] is not m2["foo"] | |
def test_setting_item(): | |
m = MagicDict() | |
m["foo"] = "bar" | |
assert "bar" == m["foo"] | |
def test_setting_item_in_unknown_item(): | |
m = MagicDict() | |
m["foo"]["bar"] = "baz" | |
assert "baz" == m["foo"]["bar"] | |
def test_attr_access_is_not_allowed(): | |
m = MagicDict() | |
with raises(AttributeError): | |
m.foo | |
def test_only_same_instance_is_equal(): | |
m1 = MagicDict(foo="bar") | |
m2 = MagicDict(foo="bar") | |
assert not m1 == m2 | |
assert m1 != m2 | |
def test_repr_should_make_clear_its_mocked(): | |
m = MagicDict() | |
assert repr(m).startswith("<MagicDict ") | |
def test_repr_of_different_instances_should_distinguishable(): | |
m1 = MagicDict() | |
m2 = MagicDict() | |
assert repr(m1) != repr(m2) | |
def test_repr_makes_clear_which_item_was_accessed(): | |
m = MagicDict() | |
assert "foo" in repr(m["foo"]) | |
def test_repr_makes_clear_which_sub_item_was_accessed(): | |
m = MagicDict() | |
assert '["foo"]["bar"]' in repr(m["foo"]["bar"]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I've also documented the creation process in a blog post.