Skip to content

Commit f752c48

Browse files
committed
Add tests for call_annotate_function() with classes, instances, and partials
1 parent 6e31007 commit f752c48

File tree

1 file changed

+103
-0
lines changed

1 file changed

+103
-0
lines changed

Lib/test/test_annotationlib.py

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1561,6 +1561,92 @@ def annotate(format, /, __Format=Format, __NotImplementedError=NotImplementedErr
15611561

15621562
self.assertEqual(annotations, {"x": "str"})
15631563

1564+
def test_callable_object_annotate(self):
1565+
# If Format.STRING and Format.VALUE_WITH_FAKE_GLOBALS are not
1566+
# supported fall back to Format.VALUE and convert to strings
1567+
class Annotate:
1568+
def __call__(self, format, /):
1569+
return {"x": str}
1570+
1571+
for fmt in [Format.VALUE, Format.FORWARDREF, Format.STRING]:
1572+
self.assertEqual(
1573+
annotationlib.call_annotate_function(Annotate(), format=fmt),
1574+
{"x": str}
1575+
)
1576+
1577+
def test_callable_object_annotate_forwardref_value_fallback(self):
1578+
# If Format.STRING and Format.VALUE_WITH_FAKE_GLOBALS are not
1579+
# supported fall back to Format.VALUE and convert to strings
1580+
class Annotate:
1581+
def __call__(self, format, /, __Format=Format,
1582+
__NotImplementedError=NotImplementedError):
1583+
if format == __Format.VALUE:
1584+
return {"x": str}
1585+
else:
1586+
raise __NotImplementedError(format)
1587+
1588+
annotations = annotationlib.call_annotate_function(
1589+
Annotate(),
1590+
Format.FORWARDREF,
1591+
)
1592+
1593+
self.assertEqual(annotations, {"x": str})
1594+
1595+
def test_callable_class_annotate_forwardref_value_fallback(self):
1596+
# If Format.STRING and Format.VALUE_WITH_FAKE_GLOBALS are not
1597+
# supported fall back to Format.VALUE and convert to strings
1598+
class Annotate(dict):
1599+
def __init__(self, format, /, __Format=Format,
1600+
__NotImplementedError=NotImplementedError):
1601+
if format == __Format.VALUE:
1602+
super().__init__({"x": int})
1603+
else:
1604+
raise __NotImplementedError(format)
1605+
1606+
annotations = annotationlib.call_annotate_function(
1607+
Annotate,
1608+
Format.FORWARDREF,
1609+
)
1610+
1611+
self.assertEqual(annotations, {"x": int})
1612+
1613+
def test_callable_partial_annotate_forwardref_value_fallback(self):
1614+
# If Format.STRING and Format.VALUE_WITH_FAKE_GLOBALS are not
1615+
# supported fall back to Format.VALUE and convert to strings
1616+
def format(format, second, /, *, third, __Format=Format,
1617+
__NotImplementedError=NotImplementedError):
1618+
if format == __Format.VALUE:
1619+
return {"x": format * second * third}
1620+
else:
1621+
raise __NotImplementedError(format)
1622+
1623+
annotations = annotationlib.call_annotate_function(
1624+
functools.partial(format, functools.Placeholder, 5, third=6),
1625+
Format.FORWARDREF,
1626+
)
1627+
1628+
self.assertEqual(annotations, {"x": Format.VALUE * 5 * 6})
1629+
1630+
def test_callable_object_annotate_string_fakeglobals(self):
1631+
# If Format.STRING is not supported but Format.VALUE_WITH_FAKE_GLOBALS is
1632+
# prefer that over Format.VALUE
1633+
class Annotate:
1634+
def __call__(self, format, /, __Format=Format,
1635+
__NotImplementedError=NotImplementedError):
1636+
if format == __Format.VALUE:
1637+
return {'x': str}
1638+
elif format == __Format.VALUE_WITH_FAKE_GLOBALS:
1639+
return {'x': int}
1640+
else:
1641+
raise __NotImplementedError(format)
1642+
1643+
annotations = annotationlib.call_annotate_function(
1644+
Annotate(),
1645+
Format.STRING,
1646+
)
1647+
1648+
self.assertEqual(annotations, {"x": "int"})
1649+
15641650
def test_condition_not_stringified(self):
15651651
# Make sure the first condition isn't evaluated as True by being converted
15661652
# to a _Stringifier
@@ -1606,6 +1692,23 @@ def annotate(format, /):
16061692
with self.assertRaises(DemoException):
16071693
annotationlib.call_annotate_function(annotate, format=fmt)
16081694

1695+
def test_callable_object_error_from_value_raised(self):
1696+
# Test that the error from format.VALUE is raised
1697+
# if all formats fail
1698+
1699+
class DemoException(Exception): ...
1700+
1701+
class Annotate:
1702+
def __call__(self, format, /):
1703+
if format == Format.VALUE:
1704+
raise DemoException()
1705+
else:
1706+
raise NotImplementedError(format)
1707+
1708+
for fmt in [Format.VALUE, Format.FORWARDREF, Format.STRING]:
1709+
with self.assertRaises(DemoException):
1710+
annotationlib.call_annotate_function(Annotate(), format=fmt)
1711+
16091712

16101713
class MetaclassTests(unittest.TestCase):
16111714
def test_annotated_meta(self):

0 commit comments

Comments
 (0)