1

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.

Community
  • 1
  • 1
Leonid Shifrin
  • 22,449
  • 4
  • 68
  • 100

0 Answers0