I have run into a strange dictionary / mapping unpacking behavior in Jython. Originally, in the context of SQLAlchemy, but I managed to narrow it down to the following minimal example:
import collections
class CustomMapping(collections.MutableMapping):
def __init__(self):
self.storage = {}
def __setitem__(self, key, value):
self.storage[key] = value
def __getitem__(self, key):
print('Accessed CustomMapping instance for key %s' % key)
return self.storage[key]
def __delitem__(self, key):
del self.storage[key]
def __len__(self):
return len(self.storage)
def __iter__(self):
for key in self.storage:
yield key
def __str__(self):
return str(self.storage)
And now I run this test code:
print(dict(
name='test', _some_stuff='abc', more='def', **CustomMapping())
)
In Python 2.7, I get what I would expect:
{'more': 'def', '_some_stuff': 'abc', 'name': 'test'}
But in Jython 2.7.0, I get this:
Accessed CustomMapping instance for key name
Accessed CustomMapping instance for key _some_stuff
Accessed CustomMapping instance for key more
{'more': 'def', '_some_stuff': 'abc', 'name': 'test'}
Setting a breakpoint in a debugger also confirms, that during the unpacking, the __getitem__
method of CustomMapping
instance is accessed for every key in the outer dictionary. This is very puzzling, does only happen in Jython, and looks like a bug to me. While the above example uses dict
as an external function, any other function will do.
I hope that someone can shed the light on this behavior. In my real context, this is causing some nasty behavior in my SQLAlchemy - powered application. Any help is greatly appreciated.