Merry christmas everybody,
I'm implementing a custom dictionary that allows attribute access, e.g. dct.attribute
. The dictionaries can be nested, so dct.nested_dct.attribute
should also be possible. This is working pretty well already, except for the star-star-unpacking. I think I'm able to express what I'm trying to do better using code than words. So here is the class I'm writing. The tests should explain pretty clearly what it does:
class DotDict(dict):
def __getattr__(self, item):
return self.__getitem__(item)
def __getitem__(self, item):
item = super().__getitem__(item)
if isinstance(item, dict):
return self.__class__(item)
return item
class TestDotDict:
@pytest.fixture
def dot_dict(self):
input_dict = dict(
a=1,
b=dict(
c=2,
d=3,
)
)
return DotDict(input_dict)
def test_can_access_by_dot(self, dot_dict):
assert dot_dict.a == 1
def test_returned_dicts_are_dot_dicts(self, dot_dict):
b_dict = dot_dict["b"]
assert isinstance(b_dict, DotDict)
assert b_dict.c == 2
def test_getting_item_also_returns_dot_dicts(self, dot_dict):
b_dict = dot_dict["b"]
assert isinstance(b_dict, DotDict)
assert b_dict.c == 2
def test_unpack_as_function_arguments_yields_dot_dicts_for_children(self, dot_dict):
# this is failing
def checker(a, b):
assert a == 1
assert b.c == 2
checker(**dot_dict)
As stated in the comment, the last test is failing. Does anybody know how to fix it?
Following the answers from this question: star unpacking for own classes , I figured I need to inherit from collections.abc.Mapping
and dict
. However, this didn't solve the issue.
I was thinking this might be related to a MRO that's not entirely clear to me. But no matter if I change the class definition to
class DotDict(Mapping, item):
or
class DotDict(item, Mapping):
my tests won't become green.