[Python-checkins] gh-104879: Fix TypeAliasType.__module__ in exec() (#104881)
JelleZijlstra
webhook-mailer at python.org
Wed May 24 14:48:20 EDT 2023
https://github.com/python/cpython/commit/fe77a99fc8b549a8bf9ccbc5485fe5ea9bcf47b9
commit: fe77a99fc8b549a8bf9ccbc5485fe5ea9bcf47b9
branch: main
author: Jelle Zijlstra <jelle.zijlstra at gmail.com>
committer: JelleZijlstra <jelle.zijlstra at gmail.com>
date: 2023-05-24T11:48:13-07:00
summary:
gh-104879: Fix TypeAliasType.__module__ in exec() (#104881)
files:
A Misc/NEWS.d/next/Core and Builtins/2023-05-24-10-19-35.gh-issue-104879.v-29NL.rst
M Lib/test/test_type_aliases.py
M Lib/test/test_typing.py
M Objects/typevarobject.c
diff --git a/Lib/test/test_type_aliases.py b/Lib/test/test_type_aliases.py
index 56d150d67afb..c43499609aaa 100644
--- a/Lib/test/test_type_aliases.py
+++ b/Lib/test/test_type_aliases.py
@@ -159,6 +159,15 @@ def test_basic(self):
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,))
diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
index 76c9e39f1d70..46c8e7452004 100644
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -373,6 +373,20 @@ def test_basic_plain(self):
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 @@ def test_name(self):
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 @@ def test_basic_plain(self):
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
index 000000000000..235f4180642b
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-05-24-10-19-35.gh-issue-104879.v-29NL.rst
@@ -0,0 +1,2 @@
+Fix crash when accessing the ``__module__`` attribute of type aliases
+defined outside a module. Patch by Jelle Zijlstra.
diff --git a/Objects/typevarobject.c b/Objects/typevarobject.c
index 6730ebfc064e..6aa0d8a3bc53 100644
--- a/Objects/typevarobject.c
+++ b/Objects/typevarobject.c
@@ -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;
}
More information about the Python-checkins
mailing list