Skip to content

Commit

Permalink
[3.12] gh-104879: Fix TypeAliasType.__module__ in exec() (GH-104881) (#…
Browse files Browse the repository at this point in the history
…104890)

(cherry picked from commit fe77a99)

Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
  • Loading branch information
miss-islington and JelleZijlstra authored May 24, 2023
1 parent 3d91d03 commit b670214
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 2 deletions.
9 changes: 9 additions & 0 deletions Lib/test/test_type_aliases.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,))
Expand Down
34 changes: 34 additions & 0 deletions Lib/test/test_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -8006,6 +8031,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')
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix crash when accessing the ``__module__`` attribute of type aliases
defined outside a module. Patch by Jelle Zijlstra.
9 changes: 7 additions & 2 deletions Objects/typevarobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down

0 comments on commit b670214

Please sign in to comment.