Dictionary extraction such as c = {**a, **b} not functioning properly.
heetbeet opened this issue · comments
The following was tested on Linux Mint 17, Python version Python 3.6.2 :: Anaconda custom (64-bit)
and dotmap version sys.version_info(major=3, minor=6, micro=2, releaselevel='final', serial=0)
(lambda **x:x)(**DotMap(a=1))
returns an unexpected empty dictionary{}
,{**DotMap(a=1),**DotMap(b=2)}
returns an unexpected empty dictionary{}
, andm = DotMap(); m.a = 2; m.b = 3; print('{a} {b}'.format(**m));
fails withKeyError: 'a'
.
Other functionality is working properly such as:
DotMap(a=1)['a']
returns an expected1
, andDotMap(a=1).a
returns an expected1
.
@heetbeet I'm not able to reproduce item 3, but I can reproduce 1 and 2.
The issue seems to be that, because DotMap
inherits from OrderedDict
, its own implementations for
__len__
__iter__
__getitem__
are being ignored in these particular types of **
calls and instead being called for the parent OrderedDict
class.
I can fix your cases by removing that inheritance and only having it inherit from MutableMapping
but that breaks a unit test in __main__
with the title == copy order preservation ==
.
If you have immediate suggestions, I'm open to them. Otherwise, I'll have to debug this at a later time.
@drgrib I see. I switched over to the following implementation for my dot dictionary needs (I know it clashes for keys that are the same as the dictionary names - such as "pop", "update", "keys", "values", etc.):
class DotDict(dict):
def __init__(self, **kwds):
self.update(kwds)
self.__dict__ = self
So I am not in an immediate need for fixes. I'll switch back to DotMap in the future when doing a bit of code refactoring and the pip default is working nicely again. Thanks for the trouble.
Shortest test on python2.7.13 for this issue:
>>> dict(**dotmap.DotMap(a=1))
{}
When using ** a lot this means DotMap fails as a dropin replacement for dictionaries. And it would be so nice to have just that.
I've given this multiple shots and it's honestly too complicated to be worth the trouble when there is a simple workaround available already:
>>> dict(**dotmap.DotMap(a=1).toDict())
{'a': 1}
More on why completely acing the subclass in this manner is so difficult here.
Fixed in #53