New submission from Kevin Shweh <kevin.sh...@gmail.com>:

LOAD_NAME and LOAD_GLOBAL don't treat dict subclasses for globals() the same 
way. If globals() is a dict subclass, LOAD_GLOBAL will respect overridden 
__getitem__, but LOAD_NAME will use PyDict_GetItem. This causes global lookup 
to behave differently in class statements; for example, in the following code, 
the final exec is the only one where print(y) causes a NameError:

class Foo(dict):
    def __getitem__(self, index):
        return 5 if index == 'y' else super().__getitem__(index)
 
exec('print(y)', Foo())
exec('global y; print(y)', Foo())
exec('''
class UsesLOAD_NAME:
    global y
    print(y)''', Foo())
exec('''
class UsesLOAD_NAME:
    print(y)''', Foo())


STORE_GLOBAL and DELETE_GLOBAL also go straight for PyDict_SetItem and 
PyDict_DelItem; I don't know whether those should be considered bugs as well, 
but the inconsistency between LOAD_NAME and LOAD_GLOBAL definitely seems wrong.

(For reference, the change that introduced the inconsistency was made for issue 
#14385, which was intended to support non-dict __builtins__.)

----------
components: Interpreter Core
messages: 337356
nosy: Kevin Shweh
priority: normal
severity: normal
status: open
title: LOAD_NAME and LOAD_GLOBAL handle dict subclasses for globals() 
differently
type: behavior
versions: Python 3.7, Python 3.8

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue36220>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to