From dbea4233f7b9224198f78584ac3d8ef994dd616c Mon Sep 17 00:00:00 2001 From: dr-carlos Date: Fri, 7 Nov 2025 07:33:01 +1030 Subject: [PATCH 1/4] Test unsupported format in ForwardRef.evaluate() --- Lib/test/test_annotationlib.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Lib/test/test_annotationlib.py b/Lib/test/test_annotationlib.py index fd5d43b09b9702..a9f5fca3331895 100644 --- a/Lib/test/test_annotationlib.py +++ b/Lib/test/test_annotationlib.py @@ -1793,6 +1793,19 @@ def test_evaluate_forwardref_format(self): support.EqualToForwardRef('"a" + 1'), ) + def test_evaluate_notimplemented_format(self): + class C: + x: alias + + fwdref = get_annotations(C, format=Format.FORWARDREF)["x"] + + with self.assertRaises(NotImplementedError): + fwdref.evaluate(format=Format.VALUE_WITH_FAKE_GLOBALS) + + with self.assertRaises(NotImplementedError): + # Some other unsupported value + fwdref.evaluate(format=7) + def test_evaluate_with_type_params(self): class Gen[T]: alias = int From aea588700cec9c5c7c47144c874b7d58eba96840 Mon Sep 17 00:00:00 2001 From: dr-carlos Date: Fri, 7 Nov 2025 09:02:19 +1030 Subject: [PATCH 2/4] Test dict cell closure with multiple variables --- Lib/test/test_annotationlib.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Lib/test/test_annotationlib.py b/Lib/test/test_annotationlib.py index a9f5fca3331895..981d973e6429be 100644 --- a/Lib/test/test_annotationlib.py +++ b/Lib/test/test_annotationlib.py @@ -73,6 +73,30 @@ def inner(arg: x): anno = get_annotations(inner, format=Format.FORWARDREF) self.assertEqual(anno["arg"], x) + def test_multiple_closure(self): + def inner(arg: x[y]): + pass + + fwdref = get_annotations(inner, format=Format.FORWARDREF)["arg"] + self.assertIsInstance(fwdref, ForwardRef) + self.assertEqual(fwdref.__forward_arg__, "x[y]") + with self.assertRaises(NameError): + fwdref.evaluate() + + y = str + fwdref = get_annotations(inner, format=Format.FORWARDREF)["arg"] + self.assertIsInstance(fwdref, ForwardRef) + extra_name, extra_val = next(iter(fwdref.__extra_names__.items())) + self.assertEqual(fwdref.__forward_arg__.replace(extra_name, extra_val.__name__), "x[str]") + with self.assertRaises(NameError): + fwdref.evaluate() + + x = list + self.assertEqual(fwdref.evaluate(), x[y]) + + fwdref = get_annotations(inner, format=Format.FORWARDREF)["arg"] + self.assertEqual(fwdref, x[y]) + def test_function(self): def f(x: int, y: doesntexist): pass From 98cbdf82f1372ee3ec6ada46e4a8b27b3480adf5 Mon Sep 17 00:00:00 2001 From: dr-carlos Date: Fri, 7 Nov 2025 09:10:32 +1030 Subject: [PATCH 3/4] Test all options in ForwardRef repr --- Lib/test/test_annotationlib.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Lib/test/test_annotationlib.py b/Lib/test/test_annotationlib.py index 981d973e6429be..7cbe5c94f849a5 100644 --- a/Lib/test/test_annotationlib.py +++ b/Lib/test/test_annotationlib.py @@ -1712,6 +1712,14 @@ def test_forward_repr(self): repr(List[ForwardRef("int", module="mod")]), "typing.List[ForwardRef('int', module='mod')]", ) + self.assertEqual( + repr(List[ForwardRef("int", module="mod", is_class=True)]), + "typing.List[ForwardRef('int', module='mod', is_class=True)]", + ) + self.assertEqual( + repr(List[ForwardRef("int", owner="class")]), + "typing.List[ForwardRef('int', owner='class')]", + ) def test_forward_recursion_actually(self): def namespace1(): From 7b431c67d9b0b9e85f60c0b680ffed111b3fdcd5 Mon Sep 17 00:00:00 2001 From: dr-carlos Date: Fri, 7 Nov 2025 09:11:49 +1030 Subject: [PATCH 4/4] Test ForwardRef being a final class --- Lib/test/test_annotationlib.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Lib/test/test_annotationlib.py b/Lib/test/test_annotationlib.py index 7cbe5c94f849a5..fdc452d67b217a 100644 --- a/Lib/test/test_annotationlib.py +++ b/Lib/test/test_annotationlib.py @@ -1971,6 +1971,11 @@ def test_fwdref_invalid_syntax(self): with self.assertRaises(SyntaxError): fr.evaluate() + def test_fwdref_final_class(self): + with self.assertRaises(TypeError): + class C(ForwardRef): + pass + class TestAnnotationLib(unittest.TestCase): def test__all__(self):