Skip to content

Commit e70b489

Browse files
committed
Test typing._BaseGenericAlias callables as annotate functions
1 parent b96532f commit e70b489

File tree

1 file changed

+37
-2
lines changed

1 file changed

+37
-2
lines changed

Lib/test/test_annotationlib.py

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import pickle
1010
from string.templatelib import Template, Interpolation
1111
import random
12+
import types
1213
import typing
1314
import sys
1415
import unittest
@@ -1696,8 +1697,9 @@ def __init__(self, format, /, __Format=Format,
16961697
self.assertEqual(annotations, {"x": int})
16971698

16981699
def test_callable_generic_class_annotate_forwardref_value_fallback(self):
1699-
# If Format.STRING and Format.VALUE_WITH_FAKE_GLOBALS are not
1700-
# supported fall back to Format.VALUE and convert to strings
1700+
# Generics that inherit from builtins become types.GenericAlias objects.
1701+
# This is special-case in annotationlib to ensure the constructor is handled
1702+
# as with standard classes and __orig_class__ is set correctly.
17011703
class Annotate[T](dict[T]):
17021704
def __init__(self, format, /, __Format=Format,
17031705
__NotImplementedError=NotImplementedError):
@@ -1714,6 +1716,39 @@ def __init__(self, format, /, __Format=Format,
17141716
self.assertEqual(annotations, {"x": int})
17151717
self.assertEqual(annotations.__orig_class__, Annotate[int])
17161718

1719+
def test_callable_typing_generic_class_annotate_forwardref_value_fallback(self):
1720+
# Standard generics are 'typing._GenericAlias' objects. These are implemented
1721+
# in Python with a __call__ method (in _typing.BaseGenericAlias), so should work
1722+
# as with any callable class instance.
1723+
class Annotate[T]:
1724+
def __init__(self, format, /, __Format=Format,
1725+
__NotImplementedError=NotImplementedError):
1726+
if format == __Format.VALUE:
1727+
self.data = {"x": int}
1728+
else:
1729+
raise __NotImplementedError(format)
1730+
def __getitem__(self, item):
1731+
return self.data[item]
1732+
def __iter__(self):
1733+
return iter(self.data)
1734+
def __len__(self):
1735+
return len(self.data)
1736+
def __getattr__(self, attr):
1737+
val = getattr(collections.abc.Mapping, attr)
1738+
if isinstance(val, types.FunctionType):
1739+
return types.MethodType(val, self)
1740+
return val
1741+
def __eq__(self, other):
1742+
return dict(self.items()) == dict(other.items())
1743+
1744+
annotations = annotationlib.call_annotate_function(
1745+
Annotate[int],
1746+
Format.FORWARDREF,
1747+
)
1748+
1749+
self.assertEqual(annotations, {"x": int})
1750+
self.assertEqual(annotations.__orig_class__, Annotate[int])
1751+
17171752
def test_callable_partial_annotate_forwardref_value_fallback(self):
17181753
# If Format.STRING and Format.VALUE_WITH_FAKE_GLOBALS are not
17191754
# supported fall back to Format.VALUE and convert to strings

0 commit comments

Comments
 (0)