]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-104879: Fix TypeAliasType.__module__ in exec() (#104881)
authorJelle Zijlstra <jelle.zijlstra@gmail.com>
Wed, 24 May 2023 18:48:13 +0000 (11:48 -0700)
committerGitHub <noreply@github.com>
Wed, 24 May 2023 18:48:13 +0000 (11:48 -0700)
Lib/test/test_type_aliases.py
Lib/test/test_typing.py
Misc/NEWS.d/next/Core and Builtins/2023-05-24-10-19-35.gh-issue-104879.v-29NL.rst [new file with mode: 0644]
Objects/typevarobject.c

index 56d150d67afb6f413d3e677556c764af0fcdfd01..c43499609aaa56dc99cf7b39b64a1c80a4462011 100644 (file)
@@ -159,6 +159,15 @@ class TypeAliasConstructorTest(unittest.TestCase):
         self.assertEqual(TA.__type_params__, ())
         self.assertEqual(TA.__module__, __name__)
 
+    def test_attributes_with_exec(self):
+        ns = {}
+        exec("type TA = int", ns, ns)
+        TA = ns["TA"]
+        self.assertEqual(TA.__name__, "TA")
+        self.assertIs(TA.__value__, int)
+        self.assertEqual(TA.__type_params__, ())
+        self.assertIs(TA.__module__, None)
+
     def test_generic(self):
         T = TypeVar("T")
         TA = TypeAliasType("TA", list[T], type_params=(T,))
index 76c9e39f1d70e60a38e8a5c2f3d501bf4a26d17e..46c8e7452004edf48b8df6cf50bdbc22278986cc 100644 (file)
@@ -373,6 +373,20 @@ class TypeVarTests(BaseTestCase):
         self.assertIs(T.__covariant__, False)
         self.assertIs(T.__contravariant__, False)
         self.assertIs(T.__infer_variance__, False)
+        self.assertEqual(T.__module__, __name__)
+
+    def test_basic_with_exec(self):
+        ns = {}
+        exec('from typing import TypeVar; T = TypeVar("T", bound=float)', ns, ns)
+        T = ns['T']
+        self.assertIsInstance(T, TypeVar)
+        self.assertEqual(T.__name__, 'T')
+        self.assertEqual(T.__constraints__, ())
+        self.assertIs(T.__bound__, float)
+        self.assertIs(T.__covariant__, False)
+        self.assertIs(T.__contravariant__, False)
+        self.assertIs(T.__infer_variance__, False)
+        self.assertIs(T.__module__, None)
 
     def test_attributes(self):
         T_bound = TypeVar('T_bound', bound=int)
@@ -939,6 +953,17 @@ class TypeVarTupleTests(BaseTestCase):
         Ts2 = TypeVarTuple('Ts2')
         self.assertEqual(Ts2.__name__, 'Ts2')
 
+    def test_module(self):
+        Ts = TypeVarTuple('Ts')
+        self.assertEqual(Ts.__module__, __name__)
+
+    def test_exec(self):
+        ns = {}
+        exec('from typing import TypeVarTuple; Ts = TypeVarTuple("Ts")', ns)
+        Ts = ns['Ts']
+        self.assertEqual(Ts.__name__, 'Ts')
+        self.assertIs(Ts.__module__, None)
+
     def test_instance_is_equal_to_itself(self):
         Ts = TypeVarTuple('Ts')
         self.assertEqual(Ts, Ts)
@@ -7985,6 +8010,15 @@ class ParamSpecTests(BaseTestCase):
         self.assertEqual(P, P)
         self.assertIsInstance(P, ParamSpec)
         self.assertEqual(P.__name__, 'P')
+        self.assertEqual(P.__module__, __name__)
+
+    def test_basic_with_exec(self):
+        ns = {}
+        exec('from typing import ParamSpec; P = ParamSpec("P")', ns, ns)
+        P = ns['P']
+        self.assertIsInstance(P, ParamSpec)
+        self.assertEqual(P.__name__, 'P')
+        self.assertIs(P.__module__, None)
 
     def test_valid_uses(self):
         P = ParamSpec('P')
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-24-10-19-35.gh-issue-104879.v-29NL.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-24-10-19-35.gh-issue-104879.v-29NL.rst
new file mode 100644 (file)
index 0000000..235f418
--- /dev/null
@@ -0,0 +1,2 @@
+Fix crash when accessing the ``__module__`` attribute of type aliases
+defined outside a module. Patch by Jelle Zijlstra.
index 6730ebfc064e356980ecf342ef4432e4cdea9234..6aa0d8a3bc53be739481ddec43bef4d894047b0c 100644 (file)
@@ -1319,8 +1319,13 @@ typealias_module(PyObject *self, void *unused)
         return Py_NewRef(ta->module);
     }
     if (ta->compute_value != NULL) {
-        // PyFunction_GetModule() returns a borrowed reference
-        return Py_NewRef(PyFunction_GetModule(ta->compute_value));
+        PyObject* mod = PyFunction_GetModule(ta->compute_value);
+        if (mod != NULL) {
+            // PyFunction_GetModule() returns a borrowed reference,
+            // and it may return NULL (e.g., for functions defined
+            // in an exec()'ed block).
+            return Py_NewRef(mod);
+        }
     }
     Py_RETURN_NONE;
 }