Skip to content

Commit ace6bc5

Browse files
committed
gh-130907: Error when accessing __annotations__ on a partially defined module
1 parent 3a09986 commit ace6bc5

File tree

3 files changed

+39
-1
lines changed

3 files changed

+39
-1
lines changed

Lib/test/test_type_annotations.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import annotationlib
22
import inspect
3+
import tempfile
34
import textwrap
45
import types
56
import unittest
6-
from test.support import run_code, check_syntax_error
7+
from pathlib import Path
8+
from test.support import run_code, check_syntax_error, import_helper
79

810

911
class TypeAnnotationTests(unittest.TestCase):
@@ -109,6 +111,18 @@ class D(metaclass=C):
109111
del D.__annotations__
110112
self.assertEqual(D.__annotations__, {})
111113

114+
def test_partially_executed_module(self):
115+
partialexe = import_helper.import_module("test.typinganndata.partialexecution")
116+
self.assertEqual(
117+
partialexe.a.__annotations__,
118+
{"v1": int, "v2": int},
119+
)
120+
self.assertIsInstance(partialexe.b.exc, RuntimeError)
121+
self.assertEqual(
122+
str(partialexe.b.exc),
123+
"cannot access __annotations__ while module is initializing",
124+
)
125+
112126

113127
def build_module(code: str, name: str = "top") -> types.ModuleType:
114128
ns = run_code(code)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Raise an error if the ``__annotations__`` attribute is accessed on a module
2+
that has not finished executing.

Objects/moduleobject.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,6 +1247,28 @@ module_get_annotations(PyObject *self, void *Py_UNUSED(ignored))
12471247

12481248
PyObject *annotations;
12491249
if (PyDict_GetItemRef(dict, &_Py_ID(__annotations__), &annotations) == 0) {
1250+
PyObject *spec;
1251+
if (PyDict_GetItemRef(m->md_dict, &_Py_ID(__spec__), &spec) < 0) {
1252+
Py_DECREF(dict);
1253+
return NULL;
1254+
}
1255+
if (spec != NULL) {
1256+
int rc = _PyModuleSpec_IsInitializing(spec);
1257+
if (rc < 0) {
1258+
Py_DECREF(spec);
1259+
Py_DECREF(dict);
1260+
return NULL;
1261+
}
1262+
Py_DECREF(spec);
1263+
if (rc) {
1264+
PyErr_SetString(PyExc_RuntimeError,
1265+
"cannot access __annotations__ "
1266+
"while module is initializing");
1267+
Py_DECREF(dict);
1268+
return NULL;
1269+
}
1270+
}
1271+
12501272
PyObject *annotate;
12511273
int annotate_result = PyDict_GetItemRef(dict, &_Py_ID(__annotate__), &annotate);
12521274
if (annotate_result < 0) {

0 commit comments

Comments
 (0)