mirror of
https://github.com/python/cpython.git
synced 2025-12-08 06:10:17 +00:00
gh-138425: Correctly partially evaluate global generics with undefined params in ref.evaluate(format=Format.FORWARDREF) (#138430)
Co-authored-by: sobolevn <mail@sobolevn.me>
This commit is contained in:
parent
31de83d5e2
commit
e66f87ca73
3 changed files with 32 additions and 1 deletions
|
|
@ -187,8 +187,11 @@ def evaluate(
|
||||||
except Exception:
|
except Exception:
|
||||||
if not is_forwardref_format:
|
if not is_forwardref_format:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
# All variables, in scoping order, should be checked before
|
||||||
|
# triggering __missing__ to create a _Stringifier.
|
||||||
new_locals = _StringifierDict(
|
new_locals = _StringifierDict(
|
||||||
{**builtins.__dict__, **locals},
|
{**builtins.__dict__, **globals, **locals},
|
||||||
globals=globals,
|
globals=globals,
|
||||||
owner=owner,
|
owner=owner,
|
||||||
is_class=self.__forward_is_class__,
|
is_class=self.__forward_is_class__,
|
||||||
|
|
|
||||||
|
|
@ -1877,6 +1877,32 @@ def test_name_lookup_without_eval(self):
|
||||||
|
|
||||||
self.assertEqual(exc.exception.name, "doesntexist")
|
self.assertEqual(exc.exception.name, "doesntexist")
|
||||||
|
|
||||||
|
def test_evaluate_undefined_generic(self):
|
||||||
|
# Test the codepath where have to eval() with undefined variables.
|
||||||
|
class C:
|
||||||
|
x: alias[int, undef]
|
||||||
|
|
||||||
|
generic = get_annotations(C, format=Format.FORWARDREF)["x"].evaluate(
|
||||||
|
format=Format.FORWARDREF,
|
||||||
|
globals={"alias": dict}
|
||||||
|
)
|
||||||
|
self.assertNotIsInstance(generic, ForwardRef)
|
||||||
|
self.assertIs(generic.__origin__, dict)
|
||||||
|
self.assertEqual(len(generic.__args__), 2)
|
||||||
|
self.assertIs(generic.__args__[0], int)
|
||||||
|
self.assertIsInstance(generic.__args__[1], ForwardRef)
|
||||||
|
|
||||||
|
generic = get_annotations(C, format=Format.FORWARDREF)["x"].evaluate(
|
||||||
|
format=Format.FORWARDREF,
|
||||||
|
globals={"alias": Union},
|
||||||
|
locals={"alias": dict}
|
||||||
|
)
|
||||||
|
self.assertNotIsInstance(generic, ForwardRef)
|
||||||
|
self.assertIs(generic.__origin__, dict)
|
||||||
|
self.assertEqual(len(generic.__args__), 2)
|
||||||
|
self.assertIs(generic.__args__[0], int)
|
||||||
|
self.assertIsInstance(generic.__args__[1], ForwardRef)
|
||||||
|
|
||||||
def test_fwdref_invalid_syntax(self):
|
def test_fwdref_invalid_syntax(self):
|
||||||
fr = ForwardRef("if")
|
fr = ForwardRef("if")
|
||||||
with self.assertRaises(SyntaxError):
|
with self.assertRaises(SyntaxError):
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
Fix partial evaluation of :class:`annotationlib.ForwardRef` objects which rely
|
||||||
|
on names defined as globals.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue