[issue31968] exec(): method's default arguments from dict-inherited globals

Ilya Polyakovskiy report at bugs.python.org
Tue Nov 7 07:49:16 EST 2017


New submission from Ilya Polyakovskiy <ilya.polyakovskiy at jetbrains.com>:

I'm using exec() to run code with globals object inherited from dict. The problem is overloaded __getitem__ doesn't called to load default argument for class methods.
Here the example. Let's assume we create some variable storage for code execution

class Env(dict):
    def __init__(self, external_storage):
        super().__init__()
        self._external_storage = external_storage

    def __setitem__(self, key, value):
        print('__setitem__: {}'.format(key))
        self._external_storage[key] = value

    def __getitem__(self, key):
        print('__getitem__: {}'.format(key))
        return self._external_storage[key]


storage = {}
env = Env(storage)
env['var'] = 2

exec("""
class A:
    def foo(self, x=var):
        print('foo(): {}'.format(x))

a = A()
a.foo()
""", env)

This code will fail with output:
__setitem__: var
Traceback (most recent call last):
  File "inheri-test.py", line 29, in <module>
    """, env)
  File "<string>", line 2, in <module>
  File "<string>", line 3, in A
NameError: name 'var' is not defined


As far as I understand the problem is Python/ceval.c:2120. There is only PyDict_GetItem used to load variable from f_globals, instead of PyObject_GetItem in case of f_globals is not exact dict.

----------
components: Interpreter Core
messages: 305746
nosy: Ilya Polyakovskiy
priority: normal
severity: normal
status: open
title: exec(): method's default arguments from dict-inherited globals
versions: Python 3.5, Python 3.6

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue31968>
_______________________________________


More information about the Python-bugs-list mailing list