summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Include/internal/pycore_opcode_metadata.h1
-rw-r--r--Include/internal/pycore_uop_metadata.h4
-rw-r--r--Lib/test/test_type_aliases.py20
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2024-05-30-23-01-00.gh-issue-119821.jPGfvt.rst2
-rw-r--r--Python/bytecodes.c35
-rw-r--r--Python/executor_cases.c.h30
-rw-r--r--Python/generated_cases.c.h35
-rw-r--r--Python/optimizer_cases.c.h7
8 files changed, 76 insertions, 58 deletions
diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h
index d353580..0b83523 100644
--- a/Include/internal/pycore_opcode_metadata.h
+++ b/Include/internal/pycore_opcode_metadata.h
@@ -1323,7 +1323,6 @@ _PyOpcode_macro_expansion[256] = {
[LOAD_FAST_CHECK] = { .nuops = 1, .uops = { { _LOAD_FAST_CHECK, 0, 0 } } },
[LOAD_FAST_LOAD_FAST] = { .nuops = 2, .uops = { { _LOAD_FAST, 5, 0 }, { _LOAD_FAST, 6, 0 } } },
[LOAD_FROM_DICT_OR_DEREF] = { .nuops = 1, .uops = { { _LOAD_FROM_DICT_OR_DEREF, 0, 0 } } },
- [LOAD_FROM_DICT_OR_GLOBALS] = { .nuops = 1, .uops = { { _LOAD_FROM_DICT_OR_GLOBALS, 0, 0 } } },
[LOAD_GLOBAL] = { .nuops = 1, .uops = { { _LOAD_GLOBAL, 0, 0 } } },
[LOAD_GLOBAL_BUILTIN] = { .nuops = 3, .uops = { { _GUARD_GLOBALS_VERSION, 1, 1 }, { _GUARD_BUILTINS_VERSION, 1, 2 }, { _LOAD_GLOBAL_BUILTINS, 1, 3 } } },
[LOAD_GLOBAL_MODULE] = { .nuops = 2, .uops = { { _GUARD_GLOBALS_VERSION, 1, 1 }, { _LOAD_GLOBAL_MODULE, 1, 3 } } },
diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h
index 78f0eaf..690ae34 100644
--- a/Include/internal/pycore_uop_metadata.h
+++ b/Include/internal/pycore_uop_metadata.h
@@ -107,7 +107,6 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {
[_STORE_GLOBAL] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
[_DELETE_GLOBAL] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG,
[_LOAD_LOCALS] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
- [_LOAD_FROM_DICT_OR_GLOBALS] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG,
[_LOAD_GLOBAL] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
[_GUARD_GLOBALS_VERSION] = HAS_DEOPT_FLAG,
[_GUARD_BUILTINS_VERSION] = HAS_DEOPT_FLAG,
@@ -439,7 +438,6 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = {
[_LOAD_FAST_CHECK] = "_LOAD_FAST_CHECK",
[_LOAD_FAST_LOAD_FAST] = "_LOAD_FAST_LOAD_FAST",
[_LOAD_FROM_DICT_OR_DEREF] = "_LOAD_FROM_DICT_OR_DEREF",
- [_LOAD_FROM_DICT_OR_GLOBALS] = "_LOAD_FROM_DICT_OR_GLOBALS",
[_LOAD_GLOBAL] = "_LOAD_GLOBAL",
[_LOAD_GLOBAL_BUILTINS] = "_LOAD_GLOBAL_BUILTINS",
[_LOAD_GLOBAL_MODULE] = "_LOAD_GLOBAL_MODULE",
@@ -692,8 +690,6 @@ int _PyUop_num_popped(int opcode, int oparg)
return 0;
case _LOAD_LOCALS:
return 0;
- case _LOAD_FROM_DICT_OR_GLOBALS:
- return 1;
case _LOAD_GLOBAL:
return 0;
case _GUARD_GLOBALS_VERSION:
diff --git a/Lib/test/test_type_aliases.py b/Lib/test/test_type_aliases.py
index 9c325bc..f8b395f 100644
--- a/Lib/test/test_type_aliases.py
+++ b/Lib/test/test_type_aliases.py
@@ -1,4 +1,5 @@
import pickle
+import textwrap
import types
import unittest
from test.support import check_syntax_error, run_code
@@ -328,3 +329,22 @@ class TypeAliasPickleTest(unittest.TestCase):
with self.subTest(thing=thing, proto=proto):
with self.assertRaises(pickle.PickleError):
pickle.dumps(thing, protocol=proto)
+
+
+class TypeParamsExoticGlobalsTest(unittest.TestCase):
+ def test_exec_with_unusual_globals(self):
+ class customdict(dict):
+ def __missing__(self, key):
+ return key
+
+ code = compile("type Alias = undefined", "test", "exec")
+ ns = customdict()
+ exec(code, ns)
+ Alias = ns["Alias"]
+ self.assertEqual(Alias.__value__, "undefined")
+
+ code = compile("class A: type Alias = undefined", "test", "exec")
+ ns = customdict()
+ exec(code, ns)
+ Alias = ns["A"].Alias
+ self.assertEqual(Alias.__value__, "undefined")
diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-05-30-23-01-00.gh-issue-119821.jPGfvt.rst b/Misc/NEWS.d/next/Core and Builtins/2024-05-30-23-01-00.gh-issue-119821.jPGfvt.rst
new file mode 100644
index 0000000..cc25eee
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2024-05-30-23-01-00.gh-issue-119821.jPGfvt.rst
@@ -0,0 +1,2 @@
+Fix execution of :ref:`annotation scopes <annotation-scopes>` within classes
+when ``globals`` is set to a non-dict. Patch by Jelle Zijlstra.
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 9a81985..1c12e1c 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -1385,18 +1385,35 @@ dummy_func(
ERROR_NO_POP();
}
if (v == NULL) {
- if (PyDict_GetItemRef(GLOBALS(), name, &v) < 0) {
- ERROR_NO_POP();
- }
- if (v == NULL) {
- if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) {
+ if (PyDict_CheckExact(GLOBALS())
+ && PyDict_CheckExact(BUILTINS()))
+ {
+ v = _PyDict_LoadGlobal((PyDictObject *)GLOBALS(),
+ (PyDictObject *)BUILTINS(),
+ name);
+ if (v == NULL) {
+ if (!_PyErr_Occurred(tstate)) {
+ /* _PyDict_LoadGlobal() returns NULL without raising
+ * an exception if the key doesn't exist */
+ _PyEval_FormatExcCheckArg(tstate, PyExc_NameError,
+ NAME_ERROR_MSG, name);
+ }
ERROR_NO_POP();
}
+ }
+ else {
+ /* Slow-path if globals or builtins is not a dict */
+ /* namespace 1: globals */
+ ERROR_IF(PyMapping_GetOptionalItem(GLOBALS(), name, &v) < 0, error);
if (v == NULL) {
- _PyEval_FormatExcCheckArg(
- tstate, PyExc_NameError,
- NAME_ERROR_MSG, name);
- ERROR_NO_POP();
+ /* namespace 2: builtins */
+ ERROR_IF(PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0, error);
+ if (v == NULL) {
+ _PyEval_FormatExcCheckArg(
+ tstate, PyExc_NameError,
+ NAME_ERROR_MSG, name);
+ ERROR_IF(true, error);
+ }
}
}
}
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index e862364..0dfe490 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -1405,35 +1405,7 @@
break;
}
- case _LOAD_FROM_DICT_OR_GLOBALS: {
- PyObject *mod_or_class_dict;
- PyObject *v;
- oparg = CURRENT_OPARG();
- mod_or_class_dict = stack_pointer[-1];
- PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
- if (PyMapping_GetOptionalItem(mod_or_class_dict, name, &v) < 0) {
- JUMP_TO_ERROR();
- }
- if (v == NULL) {
- if (PyDict_GetItemRef(GLOBALS(), name, &v) < 0) {
- JUMP_TO_ERROR();
- }
- if (v == NULL) {
- if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) {
- JUMP_TO_ERROR();
- }
- if (v == NULL) {
- _PyEval_FormatExcCheckArg(
- tstate, PyExc_NameError,
- NAME_ERROR_MSG, name);
- JUMP_TO_ERROR();
- }
- }
- }
- Py_DECREF(mod_or_class_dict);
- stack_pointer[-1] = v;
- break;
- }
+ /* _LOAD_FROM_DICT_OR_GLOBALS is not a viable micro-op for tier 2 because it has both popping and not-popping errors */
/* _LOAD_NAME is not a viable micro-op for tier 2 because it has both popping and not-popping errors */
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 4402787..1a99160 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -4401,18 +4401,35 @@
goto error;
}
if (v == NULL) {
- if (PyDict_GetItemRef(GLOBALS(), name, &v) < 0) {
- goto error;
- }
- if (v == NULL) {
- if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) {
+ if (PyDict_CheckExact(GLOBALS())
+ && PyDict_CheckExact(BUILTINS()))
+ {
+ v = _PyDict_LoadGlobal((PyDictObject *)GLOBALS(),
+ (PyDictObject *)BUILTINS(),
+ name);
+ if (v == NULL) {
+ if (!_PyErr_Occurred(tstate)) {
+ /* _PyDict_LoadGlobal() returns NULL without raising
+ * an exception if the key doesn't exist */
+ _PyEval_FormatExcCheckArg(tstate, PyExc_NameError,
+ NAME_ERROR_MSG, name);
+ }
goto error;
}
+ }
+ else {
+ /* Slow-path if globals or builtins is not a dict */
+ /* namespace 1: globals */
+ if (PyMapping_GetOptionalItem(GLOBALS(), name, &v) < 0) goto pop_1_error;
if (v == NULL) {
- _PyEval_FormatExcCheckArg(
- tstate, PyExc_NameError,
- NAME_ERROR_MSG, name);
- goto error;
+ /* namespace 2: builtins */
+ if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) goto pop_1_error;
+ if (v == NULL) {
+ _PyEval_FormatExcCheckArg(
+ tstate, PyExc_NameError,
+ NAME_ERROR_MSG, name);
+ if (true) goto pop_1_error;
+ }
}
}
}
diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h
index 1b76f14..b378734 100644
--- a/Python/optimizer_cases.c.h
+++ b/Python/optimizer_cases.c.h
@@ -740,12 +740,7 @@
break;
}
- case _LOAD_FROM_DICT_OR_GLOBALS: {
- _Py_UopsSymbol *v;
- v = sym_new_not_null(ctx);
- stack_pointer[-1] = v;
- break;
- }
+ /* _LOAD_FROM_DICT_OR_GLOBALS is not a viable micro-op for tier 2 */
/* _LOAD_NAME is not a viable micro-op for tier 2 */