Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow namedtuples to be values #138

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions addict/addict.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,12 @@ def _hook(cls, item):
if isinstance(item, dict):
return cls(item)
elif isinstance(item, (list, tuple)):
return type(item)(cls._hook(elem) for elem in item)
try:
return type(item)(cls._hook(elem) for elem in item)
except TypeError:
# some subclasses don't implement a constructor that
# accepts a generator, e.g. namedtuple
return type(item)(*(cls._hook(elem) for elem in item))
return item

def __getattr__(self, item):
Expand All @@ -80,9 +85,16 @@ def to_dict(self):
if isinstance(value, type(self)):
base[key] = value.to_dict()
elif isinstance(value, (list, tuple)):
base[key] = type(value)(
item.to_dict() if isinstance(item, type(self)) else
item for item in value)
try:
base[key] = type(value)(
item.to_dict() if isinstance(item, type(self)) else
item for item in value)
except TypeError:
# some subclasses don't implement a constructor that
# accepts a generator, e.g. namedtuple
base[key] = type(value)(*(
item.to_dict() if isinstance(item, type(self)) else
item for item in value))
else:
base[key] = value
return base
Expand Down
12 changes: 12 additions & 0 deletions test_addict.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import copy
import unittest
import pickle
import collections
from addict import Dict


Expand Down Expand Up @@ -572,6 +573,17 @@ def test_top_freeze_disallows_new_key_addition(self):
d.newKey = TEST_VAL
self.assertEqual(d.newKey, TEST_VAL)

def test_to_dict_with_namedtuple(self):
MyNamedTuple = collections.namedtuple("MyNamedTuple", ["x", "y"])
nested = {'a': MyNamedTuple({'a': 0}, {2: 0})}
prop = self.dict_class(nested)
regular = prop.to_dict()
self.assertDictEqual(regular, prop)
self.assertDictEqual(regular, nested)
self.assertIsInstance(regular['a'], MyNamedTuple)
self.assertNotIsInstance(regular['a'][0], self.dict_class)
self.assertNotIsInstance(regular['a'].x, self.dict_class)

class DictTests(unittest.TestCase, AbstractTestsClass):
dict_class = Dict

Expand Down