8000 [3.13] gh-119821: Support non-dict globals in LOAD_FROM_DICT_OR_GLOBA… · python/cpython@a055984 · GitHub
[go: up one dir, main page]

Skip to content

Commit a055984

Browse files
[3.13] gh-119821: Support non-dict globals in LOAD_FROM_DICT_OR_GLOBALS (#119822) (#119889)
dSupport non-dict globals in LOAD_FROM_DICT_OR_GLOBALS The implementation basically copies LOAD_GLOBAL. Possibly it could be deduplicated, but that seems like it may get hairy since the two operations have different operands. This is important to fix in 3.14 for PEP 649, but it's a bug in earlier versions too, and we should backport to 3.13 and 3.12 if possible. (cherry picked from commit 80a4e38)
1 parent 0a266f7 commit a055984

File tree

8 files changed

+76
-59
lines changed

8 files changed

+76
-59
lines changed

Include/internal/pycore_opcode_metadata.h

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_uop_metadata.h

Lines changed: 0 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/test/test_type_aliases.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import pickle
2+
import textwrap
23
import types
34
import unittest
45
from test.support import check_syntax_error, run_code
@@ -328,3 +329,22 @@ def test_pickling_local(self):
328329
with self.subTest(thing=thing, proto=proto):
329330
with self.assertRaises(pickle.PickleError):
330331
pickle.dumps(thing, protocol=proto)
332+
333+
334+
class TypeParamsExoticGlobalsTest(unittest.TestCase):
335+
def test_exec_with_unusual_globals(self):
336+
class customdict(dict):
337+
def __missing__(self, key):
338+
return key
339+
340+
code = compile("type Alias = undefined", "test", "exec")
341+
ns = customdict()
342+
exec(code, ns)
343+
Alias = ns["Alias"]
344+
self.assertEqual(Alias.__value__, "undefined")
345+
346+
code = compile("class A: type Alias = undefined", "test", "exec")
347+
ns = customdict()
348+
exec(code, ns)
349+
Alias = ns["A"].Alias
350+
self.assertEqual(Alias.__value__, "undefined")
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix execution of :ref:`annotation scopes <annotation-scopes>` within classes
2+
when ``globals`` is set to a non-dict. Patch by Jelle Zijlstra.

Python/bytecodes.c

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1375,18 +1375,35 @@ dummy_func(
13751375
ERROR_NO_POP();
13761376
}
13771377
if (v == NULL) {
1378-
if (PyDict_GetItemRef(GLOBALS(), name, &v) < 0) {
1379-
ERROR_NO_POP();
1380-
}
1381-
if (v == NULL) {
1382-
if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) {
1378+
if (PyDict_CheckExact(GLOBALS())
1379+
&& PyDict_CheckExact(BUILTINS()))
1380+
{
1381+
v = _PyDict_LoadGlobal((PyDictObject *)GLOBALS(),
1382+
(PyDictObject *)BUILTINS(),
1383+
name);
1384+
if (v == NULL) {
1385+
if (!_PyErr_Occurred(tstate)) {
1386+
/* _PyDict_LoadGlobal() returns NULL without raising
1387+
* an exception if the key doesn't exist */
1388+
_PyEval_FormatExcCheckArg(tstate, PyExc_NameError,
1389+
NAME_ERROR_MSG, name);
1390+
}
13831391
ERROR_NO_POP();
13841392
}
1393+
}
1394+
else {
1395+
/* Slow-path if globals or builtins is not a dict */
1396+
/* namespace 1: globals */
1397+
ERROR_IF(PyMapping_GetOptionalItem(GLOBALS(), name, &v) < 0, error);
13851398
if (v == NULL) {
1386-
_PyEval_FormatExcCheckArg(
1387-
tstate, PyExc_NameError,
1388-
NAME_ERROR_MSG, name);
1389-
ERROR_NO_POP();
1399+
/* namespace 2: builtins */
1400+
ERROR_IF(PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0, error);
1401+
if (v == NULL) {
1402+
_PyEval_FormatExcCheckArg(
1403+
tstate, PyExc_NameError,
1404+
NAME_ERROR_MSG, name);
1405+
ERROR_IF(true, error);
1406+
}
13901407
}
13911408
}
13921409
}

Python/executor_cases.c.h

Lines changed: 1 addition & 29 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/generated_cases.c.h

Lines changed: 26 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/optimizer_cases.c.h

Lines changed: 1 addition & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
0