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:
@@ -187,8 +187,11 @@ class ForwardRef:
|
||||
except Exception:
|
||||
if not is_forwardref_format:
|
||||
raise
|
||||
|
||||
# All variables, in scoping order, should be checked before
|
||||
# triggering __missing__ to create a _Stringifier.
|
||||
new_locals = _StringifierDict(
|
||||
{**builtins.__dict__, **locals},
|
||||
{**builtins.__dict__, **globals, **locals},
|
||||
globals=globals,
|
||||
owner=owner,
|
||||
is_class=self.__forward_is_class__,
|
||||
|
||||
@@ -1877,6 +1877,32 @@ class TestForwardRefClass(unittest.TestCase):
|
||||
|
||||
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):
|
||||
fr = ForwardRef("if")
|
||||
with self.assertRaises(SyntaxError):
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
Fix partial evaluation of :class:`annotationlib.ForwardRef` objects which rely
|
||||
on names defined as globals.
|
||||
Reference in New Issue
Block a user