This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: LOAD_NAME not using PyObject_GetItem when globals() is a dict subclass
Type: enhancement Stage: resolved
Components: Interpreter Core Versions:
process
Status: closed Resolution: duplicate
Dependencies: Superseder: Inconsistent behavior if globals is a dict subclass
View: 32615
Assigned To: Nosy List: douglas-raillard-arm, methane, terry.reedy
Priority: normal Keywords:

Created on 2021-07-27 14:13 by douglas-raillard-arm, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (6)
msg398299 - (view) Author: Douglas Raillard (douglas-raillard-arm) Date: 2021-07-27 14:13
Re-raising the bug reported by Kevin Shweh:
thread: https://bugs.python.org/issue14385
message: https://bugs.python.org/msg337245

Here is a copy for easier reference:

The patch for this issue changed LOAD_GLOBAL to use PyObject_GetItem when globals() is a dict subclass, but LOAD_NAME, STORE_GLOBAL, and DELETE_GLOBAL weren't changed. (LOAD_NAME uses PyObject_GetItem for builtins now, but not for globals.)

This means that global lookup doesn't respect overridden __getitem__ inside a class statement (unless you explicitly declare the name global with a global statement, in which case LOAD_GLOBAL gets used instead of LOAD_NAME).

I don't have a strong opinion on whether STORE_GLOBAL or DELETE_GLOBAL should respect overridden __setitem__ or __delitem__, but the inconsistency between LOAD_GLOBAL and LOAD_NAME seems like a bug that should be fixed.

For reference, in the following code, the first 3 exec calls successfully print 5, and the last exec call fails, due to the LOAD_GLOBAL/LOAD_NAME inconsistency:

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())


I encountered the same issue when trying to create a way to "instantiate" modules with some globals replaced by user-defined values to make a dependency-injection system. I therefore want to lookup some names in a separate dict rather than getting the value normally bound in that module (typically by an import statement).
msg398458 - (view) Author: Inada Naoki (methane) * (Python committer) Date: 2021-07-29 06:05
Is this issue duplicate of https://bugs.python.org/issue32615 and https://bugs.python.org/issue1402289 ?
msg398471 - (view) Author: Douglas Raillard (douglas-raillard-arm) Date: 2021-07-29 09:28
Looks like it is, for some reason I did not find these previous issues when looking for existing ones.
msg398967 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2021-08-05 06:20
Both preceding issues were closed as rejected.
msg398968 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2021-08-05 06:22
If you want to change that decision, I suggest posting on python-ideas list explaining why you disagree and get support for a change now.
msg398976 - (view) Author: Douglas Raillard (douglas-raillard-arm) Date: 2021-08-05 09:01
I ended up with a slightly different API that allows me to preemptively set some global names before the code runs in the module, so my use case sort of vanished. I don't think there is a real need of beating the dead horse here.

My only suggestion on the topic is that since the feature is not documented and is not really usable anyway, we might as well remove the slow path in LOAD_GLOBAL (unless there is a use case for having LOAD_GLOBAL and not LOAD_NAME I'm missing)
History
Date User Action Args
2022-04-11 14:59:47adminsetgithub: 88912
2021-08-05 09:01:32douglas-raillard-armsetmessages: + msg398976
2021-08-05 06:22:21terry.reedysetmessages: + msg398968
2021-08-05 06:20:54terry.reedysetstatus: open -> closed

superseder: Inconsistent behavior if globals is a dict subclass
nosy: + terry.reedy
versions: - Python 3.10
messages: + msg398967

type: enhancement
resolution: duplicate
stage: resolved
2021-07-29 09:28:33douglas-raillard-armsetmessages: + msg398471
2021-07-29 06:05:21methanesetnosy: + methane
messages: + msg398458
2021-07-27 14:13:35douglas-raillard-armcreate