[3.13] gh-114053: Fix another edge case involving get_type_hints, PEP 695 and PEP 563 (GH-120272) (#121003)

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
This commit is contained in:
Miss Islington (bot) 2024-06-25 18:30:08 +02:00 committed by GitHub
parent 899dfbaf0e
commit f4f8a714b5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 132 additions and 11 deletions

View file

@ -4858,20 +4858,30 @@ class GenericTests(BaseTestCase):
{'x': list[list[ForwardRef('X')]]}
)
def test_pep695_generic_with_future_annotations(self):
def test_pep695_generic_class_with_future_annotations(self):
original_globals = dict(ann_module695.__dict__)
hints_for_A = get_type_hints(ann_module695.A)
A_type_params = ann_module695.A.__type_params__
self.assertIs(hints_for_A["x"], A_type_params[0])
self.assertEqual(hints_for_A["y"].__args__[0], Unpack[A_type_params[1]])
self.assertIs(hints_for_A["z"].__args__[0], A_type_params[2])
# should not have changed as a result of the get_type_hints() calls!
self.assertEqual(ann_module695.__dict__, original_globals)
def test_pep695_generic_class_with_future_annotations_and_local_shadowing(self):
hints_for_B = get_type_hints(ann_module695.B)
self.assertEqual(hints_for_B.keys(), {"x", "y", "z"})
self.assertEqual(hints_for_B, {"x": int, "y": str, "z": bytes})
def test_pep695_generic_class_with_future_annotations_name_clash_with_global_vars(self):
hints_for_C = get_type_hints(ann_module695.C)
self.assertEqual(
set(hints_for_B.values()) ^ set(ann_module695.B.__type_params__),
set()
set(hints_for_C.values()),
set(ann_module695.C.__type_params__)
)
def test_pep_695_generic_function_with_future_annotations(self):
hints_for_generic_function = get_type_hints(ann_module695.generic_function)
func_t_params = ann_module695.generic_function.__type_params__
self.assertEqual(
@ -4882,6 +4892,54 @@ class GenericTests(BaseTestCase):
self.assertIs(hints_for_generic_function["z"].__origin__, func_t_params[2])
self.assertIs(hints_for_generic_function["zz"].__origin__, func_t_params[2])
def test_pep_695_generic_function_with_future_annotations_name_clash_with_global_vars(self):
self.assertEqual(
set(get_type_hints(ann_module695.generic_function_2).values()),
set(ann_module695.generic_function_2.__type_params__)
)
def test_pep_695_generic_method_with_future_annotations(self):
hints_for_generic_method = get_type_hints(ann_module695.D.generic_method)
params = {
param.__name__: param
for param in ann_module695.D.generic_method.__type_params__
}
self.assertEqual(
hints_for_generic_method,
{"x": params["Foo"], "y": params["Bar"], "return": types.NoneType}
)
def test_pep_695_generic_method_with_future_annotations_name_clash_with_global_vars(self):
self.assertEqual(
set(get_type_hints(ann_module695.D.generic_method_2).values()),
set(ann_module695.D.generic_method_2.__type_params__)
)
def test_pep_695_generics_with_future_annotations_nested_in_function(self):
results = ann_module695.nested()
self.assertEqual(
set(results.hints_for_E.values()),
set(results.E.__type_params__)
)
self.assertEqual(
set(results.hints_for_E_meth.values()),
set(results.E.generic_method.__type_params__)
)
self.assertNotEqual(
set(results.hints_for_E_meth.values()),
set(results.E.__type_params__)
)
self.assertEqual(
set(results.hints_for_E_meth.values()).intersection(results.E.__type_params__),
set()
)
self.assertEqual(
set(results.hints_for_generic_func.values()),
set(results.generic_func.__type_params__)
)
def test_extended_generic_rules_subclassing(self):
class T1(Tuple[T, KT]): ...
class T2(Tuple[T, ...]): ...