gh-119180: Rename SOURCE format to STRING (#124620)

This commit is contained in:
Jelle Zijlstra 2024-09-26 13:49:48 -07:00 committed by GitHub
parent a4d1fdfb15
commit 2c10832887
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 156 additions and 171 deletions

View File

@ -32,7 +32,7 @@ This module supports retrieving annotations in three main formats
for annotations that cannot be resolved, allowing you to inspect the for annotations that cannot be resolved, allowing you to inspect the
annotations without evaluating them. This is useful when you need to annotations without evaluating them. This is useful when you need to
work with annotations that may contain unresolved forward references. work with annotations that may contain unresolved forward references.
* :attr:`~Format.SOURCE` returns the annotations as a string, similar * :attr:`~Format.STRING` returns the annotations as a string, similar
to how it would appear in the source file. This is useful for documentation to how it would appear in the source file. This is useful for documentation
generators that want to display annotations in a readable way. generators that want to display annotations in a readable way.
@ -135,7 +135,7 @@ Classes
values. Real objects may contain references to, :class:`ForwardRef` values. Real objects may contain references to, :class:`ForwardRef`
proxy objects. proxy objects.
.. attribute:: SOURCE .. attribute:: STRING
:value: 3 :value: 3
Values are the text string of the annotation as it appears in the Values are the text string of the annotation as it appears in the
@ -197,23 +197,23 @@ Classes
Functions Functions
--------- ---------
.. function:: annotations_to_source(annotations) .. function:: annotations_to_string(annotations)
Convert an annotations dict containing runtime values to a Convert an annotations dict containing runtime values to a
dict containing only strings. If the values are not already strings, dict containing only strings. If the values are not already strings,
they are converted using :func:`value_to_source`. they are converted using :func:`value_to_string`.
This is meant as a helper for user-provided This is meant as a helper for user-provided
annotate functions that support the :attr:`~Format.SOURCE` format but annotate functions that support the :attr:`~Format.STRING` format but
do not have access to the code creating the annotations. do not have access to the code creating the annotations.
For example, this is used to implement the :attr:`~Format.SOURCE` for For example, this is used to implement the :attr:`~Format.STRING` for
:class:`typing.TypedDict` classes created through the functional syntax: :class:`typing.TypedDict` classes created through the functional syntax:
.. doctest:: .. doctest::
>>> from typing import TypedDict >>> from typing import TypedDict
>>> Movie = TypedDict("movie", {"name": str, "year": int}) >>> Movie = TypedDict("movie", {"name": str, "year": int})
>>> get_annotations(Movie, format=Format.SOURCE) >>> get_annotations(Movie, format=Format.STRING)
{'name': 'str', 'year': 'int'} {'name': 'str', 'year': 'int'}
.. versionadded:: 3.14 .. versionadded:: 3.14
@ -282,7 +282,7 @@ Functions
NameError: name 'undefined' is not defined NameError: name 'undefined' is not defined
>>> call_evaluate_function(Alias.evaluate_value, Format.FORWARDREF) >>> call_evaluate_function(Alias.evaluate_value, Format.FORWARDREF)
ForwardRef('undefined') ForwardRef('undefined')
>>> call_evaluate_function(Alias.evaluate_value, Format.SOURCE) >>> call_evaluate_function(Alias.evaluate_value, Format.STRING)
'undefined' 'undefined'
.. versionadded:: 3.14 .. versionadded:: 3.14
@ -369,14 +369,14 @@ Functions
.. versionadded:: 3.14 .. versionadded:: 3.14
.. function:: value_to_source(value) .. function:: value_to_string(value)
Convert an arbitrary Python value to a format suitable for use by the Convert an arbitrary Python value to a format suitable for use by the
:attr:`~Format.SOURCE` format. This calls :func:`repr` for most :attr:`~Format.STRING` format. This calls :func:`repr` for most
objects, but has special handling for some objects, such as type objects. objects, but has special handling for some objects, such as type objects.
This is meant as a helper for user-provided This is meant as a helper for user-provided
annotate functions that support the :attr:`~Format.SOURCE` format but annotate functions that support the :attr:`~Format.STRING` format but
do not have access to the code creating the annotations. It can also do not have access to the code creating the annotations. It can also
be used to provide a user-friendly string representation for other be used to provide a user-friendly string representation for other
objects that contain values that are commonly encountered in annotations. objects that contain values that are commonly encountered in annotations.

View File

@ -3427,7 +3427,7 @@ Introspection helpers
* Replaces type hints that evaluate to :const:`!None` with * Replaces type hints that evaluate to :const:`!None` with
:class:`types.NoneType`. :class:`types.NoneType`.
* Supports the :attr:`~annotationlib.Format.FORWARDREF` and * Supports the :attr:`~annotationlib.Format.FORWARDREF` and
:attr:`~annotationlib.Format.SOURCE` formats. :attr:`~annotationlib.Format.STRING` formats.
*forward_ref* must be an instance of :class:`~annotationlib.ForwardRef`. *forward_ref* must be an instance of :class:`~annotationlib.ForwardRef`.
*owner*, if given, should be the object that holds the annotations that *owner*, if given, should be the object that holds the annotations that

View File

@ -91,7 +91,7 @@ annotations. Annotations may be evaluated in the :attr:`~annotationlib.Format.VA
format (which evaluates annotations to runtime values, similar to the behavior in format (which evaluates annotations to runtime values, similar to the behavior in
earlier Python versions), the :attr:`~annotationlib.Format.FORWARDREF` format earlier Python versions), the :attr:`~annotationlib.Format.FORWARDREF` format
(which replaces undefined names with special markers), and the (which replaces undefined names with special markers), and the
:attr:`~annotationlib.Format.SOURCE` format (which returns annotations as strings). :attr:`~annotationlib.Format.STRING` format (which returns annotations as strings).
This example shows how these formats behave: This example shows how these formats behave:
@ -106,7 +106,7 @@ This example shows how these formats behave:
NameError: name 'Undefined' is not defined NameError: name 'Undefined' is not defined
>>> get_annotations(func, format=Format.FORWARDREF) >>> get_annotations(func, format=Format.FORWARDREF)
{'arg': ForwardRef('Undefined')} {'arg': ForwardRef('Undefined')}
>>> get_annotations(func, format=Format.SOURCE) >>> get_annotations(func, format=Format.STRING)
{'arg': 'Undefined'} {'arg': 'Undefined'}
Implications for annotated code Implications for annotated code

View File

@ -485,10 +485,10 @@ class _CallableGenericAlias(GenericAlias):
def __repr__(self): def __repr__(self):
if len(self.__args__) == 2 and _is_param_expr(self.__args__[0]): if len(self.__args__) == 2 and _is_param_expr(self.__args__[0]):
return super().__repr__() return super().__repr__()
from annotationlib import value_to_source from annotationlib import value_to_string
return (f'collections.abc.Callable' return (f'collections.abc.Callable'
f'[[{", ".join([value_to_source(a) for a in self.__args__[:-1]])}], ' f'[[{", ".join([value_to_string(a) for a in self.__args__[:-1]])}], '
f'{value_to_source(self.__args__[-1])}]') f'{value_to_string(self.__args__[-1])}]')
def __reduce__(self): def __reduce__(self):
args = self.__args__ args = self.__args__

View File

@ -15,15 +15,15 @@ __all__ = [
"call_evaluate_function", "call_evaluate_function",
"get_annotate_function", "get_annotate_function",
"get_annotations", "get_annotations",
"annotations_to_source", "annotations_to_string",
"value_to_source", "value_to_string",
] ]
class Format(enum.IntEnum): class Format(enum.IntEnum):
VALUE = 1 VALUE = 1
FORWARDREF = 2 FORWARDREF = 2
SOURCE = 3 STRING = 3
_Union = None _Union = None
@ -291,9 +291,21 @@ class _Stringifier:
return other.__ast_node__ return other.__ast_node__
elif isinstance(other, slice): elif isinstance(other, slice):
return ast.Slice( return ast.Slice(
lower=self.__convert_to_ast(other.start) if other.start is not None else None, lower=(
upper=self.__convert_to_ast(other.stop) if other.stop is not None else None, self.__convert_to_ast(other.start)
step=self.__convert_to_ast(other.step) if other.step is not None else None, if other.start is not None
else None
),
upper=(
self.__convert_to_ast(other.stop)
if other.stop is not None
else None
),
step=(
self.__convert_to_ast(other.step)
if other.step is not None
else None
),
) )
else: else:
return ast.Constant(value=other) return ast.Constant(value=other)
@ -469,7 +481,7 @@ def call_annotate_function(annotate, format, *, owner=None, _is_evaluate=False):
can be called with any of the format arguments in the Format enum, but can be called with any of the format arguments in the Format enum, but
compiler-generated __annotate__ functions only support the VALUE format. compiler-generated __annotate__ functions only support the VALUE format.
This function provides additional functionality to call __annotate__ This function provides additional functionality to call __annotate__
functions with the FORWARDREF and SOURCE formats. functions with the FORWARDREF and STRING formats.
*annotate* must be an __annotate__ function, which takes a single argument *annotate* must be an __annotate__ function, which takes a single argument
and returns a dict of annotations. and returns a dict of annotations.
@ -487,8 +499,8 @@ def call_annotate_function(annotate, format, *, owner=None, _is_evaluate=False):
return annotate(format) return annotate(format)
except NotImplementedError: except NotImplementedError:
pass pass
if format == Format.SOURCE: if format == Format.STRING:
# SOURCE is implemented by calling the annotate function in a special # STRING is implemented by calling the annotate function in a special
# environment where every name lookup results in an instance of _Stringifier. # environment where every name lookup results in an instance of _Stringifier.
# _Stringifier supports every dunder operation and returns a new _Stringifier. # _Stringifier supports every dunder operation and returns a new _Stringifier.
# At the end, we get a dictionary that mostly contains _Stringifier objects (or # At the end, we get a dictionary that mostly contains _Stringifier objects (or
@ -524,9 +536,9 @@ def call_annotate_function(annotate, format, *, owner=None, _is_evaluate=False):
for key, val in annos.items() for key, val in annos.items()
} }
elif format == Format.FORWARDREF: elif format == Format.FORWARDREF:
# FORWARDREF is implemented similarly to SOURCE, but there are two changes, # FORWARDREF is implemented similarly to STRING, but there are two changes,
# at the beginning and the end of the process. # at the beginning and the end of the process.
# First, while SOURCE uses an empty dictionary as the namespace, so that all # First, while STRING uses an empty dictionary as the namespace, so that all
# name lookups result in _Stringifier objects, FORWARDREF uses the globals # name lookups result in _Stringifier objects, FORWARDREF uses the globals
# and builtins, so that defined names map to their real values. # and builtins, so that defined names map to their real values.
# Second, instead of returning strings, we want to return either real values # Second, instead of returning strings, we want to return either real values
@ -688,14 +700,14 @@ def get_annotations(
# __annotations__ threw NameError and there is no __annotate__. In that case, # __annotations__ threw NameError and there is no __annotate__. In that case,
# we fall back to trying __annotations__ again. # we fall back to trying __annotations__ again.
return dict(_get_dunder_annotations(obj)) return dict(_get_dunder_annotations(obj))
case Format.SOURCE: case Format.STRING:
# For SOURCE, we try to call __annotate__ # For STRING, we try to call __annotate__
ann = _get_and_call_annotate(obj, format) ann = _get_and_call_annotate(obj, format)
if ann is not None: if ann is not None:
return ann return ann
# But if we didn't get it, we use __annotations__ instead. # But if we didn't get it, we use __annotations__ instead.
ann = _get_dunder_annotations(obj) ann = _get_dunder_annotations(obj)
return annotations_to_source(ann) return annotations_to_string(ann)
case _: case _:
raise ValueError(f"Unsupported format {format!r}") raise ValueError(f"Unsupported format {format!r}")
@ -764,10 +776,10 @@ def get_annotations(
return return_value return return_value
def value_to_source(value): def value_to_string(value):
"""Convert a Python value to a format suitable for use with the SOURCE format. """Convert a Python value to a format suitable for use with the STRING format.
This is inteded as a helper for tools that support the SOURCE format but do This is inteded as a helper for tools that support the STRING format but do
not have access to the code that originally produced the annotations. It uses not have access to the code that originally produced the annotations. It uses
repr() for most objects. repr() for most objects.
@ -783,10 +795,10 @@ def value_to_source(value):
return repr(value) return repr(value)
def annotations_to_source(annotations): def annotations_to_string(annotations):
"""Convert an annotation dict containing values to approximately the SOURCE format.""" """Convert an annotation dict containing values to approximately the STRING format."""
return { return {
n: t if isinstance(t, str) else value_to_source(t) n: t if isinstance(t, str) else value_to_string(t)
for n, t in annotations.items() for n, t in annotations.items()
} }

View File

@ -12,8 +12,8 @@ from annotationlib import (
ForwardRef, ForwardRef,
get_annotations, get_annotations,
get_annotate_function, get_annotate_function,
annotations_to_source, annotations_to_string,
value_to_source, value_to_string,
) )
from typing import Unpack from typing import Unpack
@ -39,14 +39,14 @@ class MyClass:
class TestFormat(unittest.TestCase): class TestFormat(unittest.TestCase):
def test_enum(self): def test_enum(self):
self.assertEqual(annotationlib.Format.VALUE.value, 1) self.assertEqual(Format.VALUE.value, 1)
self.assertEqual(annotationlib.Format.VALUE, 1) self.assertEqual(Format.VALUE, 1)
self.assertEqual(annotationlib.Format.FORWARDREF.value, 2) self.assertEqual(Format.FORWARDREF.value, 2)
self.assertEqual(annotationlib.Format.FORWARDREF, 2) self.assertEqual(Format.FORWARDREF, 2)
self.assertEqual(annotationlib.Format.SOURCE.value, 3) self.assertEqual(Format.STRING.value, 3)
self.assertEqual(annotationlib.Format.SOURCE, 3) self.assertEqual(Format.STRING, 3)
class TestForwardRefFormat(unittest.TestCase): class TestForwardRefFormat(unittest.TestCase):
@ -54,9 +54,7 @@ class TestForwardRefFormat(unittest.TestCase):
def inner(arg: x): def inner(arg: x):
pass pass
anno = annotationlib.get_annotations( anno = annotationlib.get_annotations(inner, format=Format.FORWARDREF)
inner, format=annotationlib.Format.FORWARDREF
)
fwdref = anno["arg"] fwdref = anno["arg"]
self.assertIsInstance(fwdref, annotationlib.ForwardRef) self.assertIsInstance(fwdref, annotationlib.ForwardRef)
self.assertEqual(fwdref.__forward_arg__, "x") self.assertEqual(fwdref.__forward_arg__, "x")
@ -66,16 +64,14 @@ class TestForwardRefFormat(unittest.TestCase):
x = 1 x = 1
self.assertEqual(fwdref.evaluate(), x) self.assertEqual(fwdref.evaluate(), x)
anno = annotationlib.get_annotations( anno = annotationlib.get_annotations(inner, format=Format.FORWARDREF)
inner, format=annotationlib.Format.FORWARDREF
)
self.assertEqual(anno["arg"], x) self.assertEqual(anno["arg"], x)
def test_function(self): def test_function(self):
def f(x: int, y: doesntexist): def f(x: int, y: doesntexist):
pass pass
anno = annotationlib.get_annotations(f, format=annotationlib.Format.FORWARDREF) anno = annotationlib.get_annotations(f, format=Format.FORWARDREF)
self.assertIs(anno["x"], int) self.assertIs(anno["x"], int)
fwdref = anno["y"] fwdref = anno["y"]
self.assertIsInstance(fwdref, annotationlib.ForwardRef) self.assertIsInstance(fwdref, annotationlib.ForwardRef)
@ -92,14 +88,14 @@ class TestSourceFormat(unittest.TestCase):
def inner(arg: x): def inner(arg: x):
pass pass
anno = annotationlib.get_annotations(inner, format=annotationlib.Format.SOURCE) anno = annotationlib.get_annotations(inner, format=Format.STRING)
self.assertEqual(anno, {"arg": "x"}) self.assertEqual(anno, {"arg": "x"})
def test_function(self): def test_function(self):
def f(x: int, y: doesntexist): def f(x: int, y: doesntexist):
pass pass
anno = annotationlib.get_annotations(f, format=annotationlib.Format.SOURCE) anno = annotationlib.get_annotations(f, format=Format.STRING)
self.assertEqual(anno, {"x": "int", "y": "doesntexist"}) self.assertEqual(anno, {"x": "int", "y": "doesntexist"})
def test_expressions(self): def test_expressions(self):
@ -133,7 +129,7 @@ class TestSourceFormat(unittest.TestCase):
): ):
pass pass
anno = annotationlib.get_annotations(f, format=annotationlib.Format.SOURCE) anno = annotationlib.get_annotations(f, format=Format.STRING)
self.assertEqual( self.assertEqual(
anno, anno,
{ {
@ -184,7 +180,7 @@ class TestSourceFormat(unittest.TestCase):
): ):
pass pass
anno = annotationlib.get_annotations(f, format=annotationlib.Format.SOURCE) anno = annotationlib.get_annotations(f, format=Format.STRING)
self.assertEqual( self.assertEqual(
anno, anno,
{ {
@ -218,7 +214,7 @@ class TestSourceFormat(unittest.TestCase):
): ):
pass pass
anno = annotationlib.get_annotations(f, format=annotationlib.Format.SOURCE) anno = annotationlib.get_annotations(f, format=Format.STRING)
self.assertEqual( self.assertEqual(
anno, anno,
{ {
@ -241,13 +237,13 @@ class TestSourceFormat(unittest.TestCase):
pass pass
with self.assertRaisesRegex(TypeError, format_msg): with self.assertRaisesRegex(TypeError, format_msg):
annotationlib.get_annotations(f, format=annotationlib.Format.SOURCE) annotationlib.get_annotations(f, format=Format.STRING)
def f(fstring_format: f"{a:02d}"): def f(fstring_format: f"{a:02d}"):
pass pass
with self.assertRaisesRegex(TypeError, format_msg): with self.assertRaisesRegex(TypeError, format_msg):
annotationlib.get_annotations(f, format=annotationlib.Format.SOURCE) annotationlib.get_annotations(f, format=Format.STRING)
class TestForwardRefClass(unittest.TestCase): class TestForwardRefClass(unittest.TestCase):
@ -276,7 +272,7 @@ class TestForwardRefClass(unittest.TestCase):
with self.assertRaises(NameError): with self.assertRaises(NameError):
ForwardRef("T").evaluate(owner=int) ForwardRef("T").evaluate(owner=int)
T, = Gen.__type_params__ (T,) = Gen.__type_params__
self.assertIs(ForwardRef("T").evaluate(type_params=Gen.__type_params__), T) self.assertIs(ForwardRef("T").evaluate(type_params=Gen.__type_params__), T)
self.assertIs(ForwardRef("T").evaluate(owner=Gen), T) self.assertIs(ForwardRef("T").evaluate(owner=Gen), T)
@ -294,8 +290,7 @@ class TestForwardRefClass(unittest.TestCase):
def test_fwdref_with_module(self): def test_fwdref_with_module(self):
self.assertIs(ForwardRef("Format", module="annotationlib").evaluate(), Format) self.assertIs(ForwardRef("Format", module="annotationlib").evaluate(), Format)
self.assertIs( self.assertIs(
ForwardRef("Counter", module="collections").evaluate(), ForwardRef("Counter", module="collections").evaluate(), collections.Counter
collections.Counter
) )
self.assertEqual( self.assertEqual(
ForwardRef("Counter[int]", module="collections").evaluate(), ForwardRef("Counter[int]", module="collections").evaluate(),
@ -383,22 +378,20 @@ class TestGetAnnotations(unittest.TestCase):
self.assertEqual(annotationlib.get_annotations(C1), {"a": int}) self.assertEqual(annotationlib.get_annotations(C1), {"a": int})
self.assertEqual( self.assertEqual(
annotationlib.get_annotations(C1, format=annotationlib.Format.FORWARDREF), annotationlib.get_annotations(C1, format=Format.FORWARDREF),
{"a": int}, {"a": int},
) )
self.assertEqual( self.assertEqual(
annotationlib.get_annotations(C1, format=annotationlib.Format.SOURCE), annotationlib.get_annotations(C1, format=Format.STRING),
{"a": "int"}, {"a": "int"},
) )
self.assertEqual(annotationlib.get_annotations(NoDict), {"b": str}) self.assertEqual(annotationlib.get_annotations(NoDict), {"b": str})
self.assertEqual( self.assertEqual(
annotationlib.get_annotations( annotationlib.get_annotations(NoDict, format=Format.FORWARDREF),
NoDict, format=annotationlib.Format.FORWARDREF
),
{"b": str}, {"b": str},
) )
self.assertEqual( self.assertEqual(
annotationlib.get_annotations(NoDict, format=annotationlib.Format.SOURCE), annotationlib.get_annotations(NoDict, format=Format.STRING),
{"b": "str"}, {"b": "str"},
) )
@ -410,20 +403,20 @@ class TestGetAnnotations(unittest.TestCase):
pass pass
self.assertEqual( self.assertEqual(
annotationlib.get_annotations(f1, format=annotationlib.Format.VALUE), annotationlib.get_annotations(f1, format=Format.VALUE),
{"a": int}, {"a": int},
) )
self.assertEqual(annotationlib.get_annotations(f1, format=1), {"a": int}) self.assertEqual(annotationlib.get_annotations(f1, format=1), {"a": int})
fwd = annotationlib.ForwardRef("undefined") fwd = annotationlib.ForwardRef("undefined")
self.assertEqual( self.assertEqual(
annotationlib.get_annotations(f2, format=annotationlib.Format.FORWARDREF), annotationlib.get_annotations(f2, format=Format.FORWARDREF),
{"a": fwd}, {"a": fwd},
) )
self.assertEqual(annotationlib.get_annotations(f2, format=2), {"a": fwd}) self.assertEqual(annotationlib.get_annotations(f2, format=2), {"a": fwd})
self.assertEqual( self.assertEqual(
annotationlib.get_annotations(f1, format=annotationlib.Format.SOURCE), annotationlib.get_annotations(f1, format=Format.STRING),
{"a": "int"}, {"a": "int"},
) )
self.assertEqual(annotationlib.get_annotations(f1, format=3), {"a": "int"}) self.assertEqual(annotationlib.get_annotations(f1, format=3), {"a": "int"})
@ -446,30 +439,26 @@ class TestGetAnnotations(unittest.TestCase):
pass pass
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
annotationlib.get_annotations( annotationlib.get_annotations(foo, format=Format.FORWARDREF, eval_str=True)
foo, format=annotationlib.Format.FORWARDREF, eval_str=True annotationlib.get_annotations(foo, format=Format.STRING, eval_str=True)
)
annotationlib.get_annotations(
foo, format=annotationlib.Format.SOURCE, eval_str=True
)
def test_stock_annotations(self): def test_stock_annotations(self):
def foo(a: int, b: str): def foo(a: int, b: str):
pass pass
for format in (annotationlib.Format.VALUE, annotationlib.Format.FORWARDREF): for format in (Format.VALUE, Format.FORWARDREF):
with self.subTest(format=format): with self.subTest(format=format):
self.assertEqual( self.assertEqual(
annotationlib.get_annotations(foo, format=format), annotationlib.get_annotations(foo, format=format),
{"a": int, "b": str}, {"a": int, "b": str},
) )
self.assertEqual( self.assertEqual(
annotationlib.get_annotations(foo, format=annotationlib.Format.SOURCE), annotationlib.get_annotations(foo, format=Format.STRING),
{"a": "int", "b": "str"}, {"a": "int", "b": "str"},
) )
foo.__annotations__ = {"a": "foo", "b": "str"} foo.__annotations__ = {"a": "foo", "b": "str"}
for format in annotationlib.Format: for format in Format:
with self.subTest(format=format): with self.subTest(format=format):
self.assertEqual( self.assertEqual(
annotationlib.get_annotations(foo, format=format), annotationlib.get_annotations(foo, format=format),
@ -491,10 +480,10 @@ class TestGetAnnotations(unittest.TestCase):
for kwargs in [ for kwargs in [
{}, {},
{"eval_str": False}, {"eval_str": False},
{"format": annotationlib.Format.VALUE}, {"format": Format.VALUE},
{"format": annotationlib.Format.FORWARDREF}, {"format": Format.FORWARDREF},
{"format": annotationlib.Format.VALUE, "eval_str": False}, {"format": Format.VALUE, "eval_str": False},
{"format": annotationlib.Format.FORWARDREF, "eval_str": False}, {"format": Format.FORWARDREF, "eval_str": False},
]: ]:
with self.subTest(**kwargs): with self.subTest(**kwargs):
self.assertEqual( self.assertEqual(
@ -529,7 +518,7 @@ class TestGetAnnotations(unittest.TestCase):
for kwargs in [ for kwargs in [
{"eval_str": True}, {"eval_str": True},
{"format": annotationlib.Format.VALUE, "eval_str": True}, {"format": Format.VALUE, "eval_str": True},
]: ]:
with self.subTest(**kwargs): with self.subTest(**kwargs):
self.assertEqual( self.assertEqual(
@ -563,48 +552,36 @@ class TestGetAnnotations(unittest.TestCase):
) )
self.assertEqual( self.assertEqual(
annotationlib.get_annotations(isa, format=annotationlib.Format.SOURCE), annotationlib.get_annotations(isa, format=Format.STRING),
{"a": "int", "b": "str"}, {"a": "int", "b": "str"},
) )
self.assertEqual( self.assertEqual(
annotationlib.get_annotations( annotationlib.get_annotations(isa.MyClass, format=Format.STRING),
isa.MyClass, format=annotationlib.Format.SOURCE
),
{"a": "int", "b": "str"}, {"a": "int", "b": "str"},
) )
self.assertEqual( self.assertEqual(
annotationlib.get_annotations( annotationlib.get_annotations(isa.function, format=Format.STRING),
isa.function, format=annotationlib.Format.SOURCE
),
{"a": "int", "b": "str", "return": "MyClass"}, {"a": "int", "b": "str", "return": "MyClass"},
) )
self.assertEqual( self.assertEqual(
annotationlib.get_annotations( annotationlib.get_annotations(isa.function2, format=Format.STRING),
isa.function2, format=annotationlib.Format.SOURCE
),
{"a": "int", "b": "str", "c": "MyClass", "return": "MyClass"}, {"a": "int", "b": "str", "c": "MyClass", "return": "MyClass"},
) )
self.assertEqual( self.assertEqual(
annotationlib.get_annotations( annotationlib.get_annotations(isa.function3, format=Format.STRING),
isa.function3, format=annotationlib.Format.SOURCE
),
{"a": "int", "b": "str", "c": "MyClass"}, {"a": "int", "b": "str", "c": "MyClass"},
) )
self.assertEqual( self.assertEqual(
annotationlib.get_annotations( annotationlib.get_annotations(annotationlib, format=Format.STRING),
annotationlib, format=annotationlib.Format.SOURCE {},
), )
self.assertEqual(
annotationlib.get_annotations(isa.UnannotatedClass, format=Format.STRING),
{}, {},
) )
self.assertEqual( self.assertEqual(
annotationlib.get_annotations( annotationlib.get_annotations(
isa.UnannotatedClass, format=annotationlib.Format.SOURCE isa.unannotated_function, format=Format.STRING
),
{},
)
self.assertEqual(
annotationlib.get_annotations(
isa.unannotated_function, format=annotationlib.Format.SOURCE
), ),
{}, {},
) )
@ -620,13 +597,11 @@ class TestGetAnnotations(unittest.TestCase):
{"a": int, "b": str, "return": isa.MyClass}, {"a": int, "b": str, "return": isa.MyClass},
) )
self.assertEqual( self.assertEqual(
annotationlib.get_annotations( annotationlib.get_annotations(wrapped, format=Format.FORWARDREF),
wrapped, format=annotationlib.Format.FORWARDREF
),
{"a": int, "b": str, "return": isa.MyClass}, {"a": int, "b": str, "return": isa.MyClass},
) )
self.assertEqual( self.assertEqual(
annotationlib.get_annotations(wrapped, format=annotationlib.Format.SOURCE), annotationlib.get_annotations(wrapped, format=Format.STRING),
{"a": "int", "b": "str", "return": "MyClass"}, {"a": "int", "b": "str", "return": "MyClass"},
) )
self.assertEqual( self.assertEqual(
@ -643,12 +618,12 @@ class TestGetAnnotations(unittest.TestCase):
for kwargs in [ for kwargs in [
{}, {},
{"eval_str": False}, {"eval_str": False},
{"format": annotationlib.Format.VALUE}, {"format": Format.VALUE},
{"format": annotationlib.Format.FORWARDREF}, {"format": Format.FORWARDREF},
{"format": annotationlib.Format.SOURCE}, {"format": Format.STRING},
{"format": annotationlib.Format.VALUE, "eval_str": False}, {"format": Format.VALUE, "eval_str": False},
{"format": annotationlib.Format.FORWARDREF, "eval_str": False}, {"format": Format.FORWARDREF, "eval_str": False},
{"format": annotationlib.Format.SOURCE, "eval_str": False}, {"format": Format.STRING, "eval_str": False},
]: ]:
with self.subTest(**kwargs): with self.subTest(**kwargs):
self.assertEqual( self.assertEqual(
@ -681,7 +656,7 @@ class TestGetAnnotations(unittest.TestCase):
for kwargs in [ for kwargs in [
{"eval_str": True}, {"eval_str": True},
{"format": annotationlib.Format.VALUE, "eval_str": True}, {"format": Format.VALUE, "eval_str": True},
]: ]:
with self.subTest(**kwargs): with self.subTest(**kwargs):
self.assertEqual( self.assertEqual(
@ -767,9 +742,9 @@ class TestGetAnnotations(unittest.TestCase):
annotationlib.get_annotations(f, format=Format.FORWARDREF), annotationlib.get_annotations(f, format=Format.FORWARDREF),
{"x": str}, {"x": str},
) )
# ... but not in SOURCE which always uses __annotate__ # ... but not in STRING which always uses __annotate__
self.assertEqual( self.assertEqual(
annotationlib.get_annotations(f, format=Format.SOURCE), annotationlib.get_annotations(f, format=Format.STRING),
{"x": "int"}, {"x": "int"},
) )
@ -804,7 +779,7 @@ class TestGetAnnotations(unittest.TestCase):
) )
self.assertEqual( self.assertEqual(
annotationlib.get_annotations(ha, format=Format.SOURCE), {"x": "int"} annotationlib.get_annotations(ha, format=Format.STRING), {"x": "int"}
) )
def test_raising_annotations_on_custom_object(self): def test_raising_annotations_on_custom_object(self):
@ -844,7 +819,7 @@ class TestGetAnnotations(unittest.TestCase):
annotationlib.get_annotations(hb, format=Format.FORWARDREF), {"x": int} annotationlib.get_annotations(hb, format=Format.FORWARDREF), {"x": int}
) )
self.assertEqual( self.assertEqual(
annotationlib.get_annotations(hb, format=Format.SOURCE), {"x": str} annotationlib.get_annotations(hb, format=Format.STRING), {"x": str}
) )
def test_pep695_generic_class_with_future_annotations(self): def test_pep695_generic_class_with_future_annotations(self):
@ -974,15 +949,13 @@ class TestCallEvaluateFunction(unittest.TestCase):
return undefined return undefined
with self.assertRaises(NameError): with self.assertRaises(NameError):
annotationlib.call_evaluate_function(evaluate, annotationlib.Format.VALUE) annotationlib.call_evaluate_function(evaluate, Format.VALUE)
self.assertEqual( self.assertEqual(
annotationlib.call_evaluate_function( annotationlib.call_evaluate_function(evaluate, Format.FORWARDREF),
evaluate, annotationlib.Format.FORWARDREF
),
annotationlib.ForwardRef("undefined"), annotationlib.ForwardRef("undefined"),
) )
self.assertEqual( self.assertEqual(
annotationlib.call_evaluate_function(evaluate, annotationlib.Format.SOURCE), annotationlib.call_evaluate_function(evaluate, Format.STRING),
"undefined", "undefined",
) )
@ -1093,25 +1066,25 @@ class TestGetAnnotateFunction(unittest.TestCase):
class TestToSource(unittest.TestCase): class TestToSource(unittest.TestCase):
def test_value_to_source(self): def test_value_to_string(self):
self.assertEqual(value_to_source(int), "int") self.assertEqual(value_to_string(int), "int")
self.assertEqual(value_to_source(MyClass), "test.test_annotationlib.MyClass") self.assertEqual(value_to_string(MyClass), "test.test_annotationlib.MyClass")
self.assertEqual(value_to_source(len), "len") self.assertEqual(value_to_string(len), "len")
self.assertEqual(value_to_source(value_to_source), "value_to_source") self.assertEqual(value_to_string(value_to_string), "value_to_string")
self.assertEqual(value_to_source(times_three), "times_three") self.assertEqual(value_to_string(times_three), "times_three")
self.assertEqual(value_to_source(...), "...") self.assertEqual(value_to_string(...), "...")
self.assertEqual(value_to_source(None), "None") self.assertEqual(value_to_string(None), "None")
self.assertEqual(value_to_source(1), "1") self.assertEqual(value_to_string(1), "1")
self.assertEqual(value_to_source("1"), "'1'") self.assertEqual(value_to_string("1"), "'1'")
self.assertEqual(value_to_source(Format.VALUE), repr(Format.VALUE)) self.assertEqual(value_to_string(Format.VALUE), repr(Format.VALUE))
self.assertEqual(value_to_source(MyClass()), "my repr") self.assertEqual(value_to_string(MyClass()), "my repr")
def test_annotations_to_source(self): def test_annotations_to_string(self):
self.assertEqual(annotations_to_source({}), {}) self.assertEqual(annotations_to_string({}), {})
self.assertEqual(annotations_to_source({"x": int}), {"x": "int"}) self.assertEqual(annotations_to_string({"x": int}), {"x": "int"})
self.assertEqual(annotations_to_source({"x": "int"}), {"x": "int"}) self.assertEqual(annotations_to_string({"x": "int"}), {"x": "int"})
self.assertEqual( self.assertEqual(
annotations_to_source({"x": int, "y": str}), {"x": "int", "y": "str"} annotations_to_string({"x": int, "y": str}), {"x": "int", "y": "str"}
) )

View File

@ -375,7 +375,7 @@ class DeferredEvaluationTests(unittest.TestCase):
with self.assertRaises(NotImplementedError): with self.assertRaises(NotImplementedError):
annotate(annotationlib.Format.FORWARDREF) annotate(annotationlib.Format.FORWARDREF)
with self.assertRaises(NotImplementedError): with self.assertRaises(NotImplementedError):
annotate(annotationlib.Format.SOURCE) annotate(annotationlib.Format.STRING)
with self.assertRaises(NotImplementedError): with self.assertRaises(NotImplementedError):
annotate(None) annotate(None)
self.assertEqual(annotate(annotationlib.Format.VALUE), {"x": int}) self.assertEqual(annotate(annotationlib.Format.VALUE), {"x": int})

View File

@ -1440,7 +1440,7 @@ class TestEvaluateFunctions(unittest.TestCase):
self.assertIs(case(1), int) self.assertIs(case(1), int)
self.assertIs(annotationlib.call_evaluate_function(case, annotationlib.Format.VALUE), int) self.assertIs(annotationlib.call_evaluate_function(case, annotationlib.Format.VALUE), int)
self.assertIs(annotationlib.call_evaluate_function(case, annotationlib.Format.FORWARDREF), int) self.assertIs(annotationlib.call_evaluate_function(case, annotationlib.Format.FORWARDREF), int)
self.assertEqual(annotationlib.call_evaluate_function(case, annotationlib.Format.SOURCE), 'int') self.assertEqual(annotationlib.call_evaluate_function(case, annotationlib.Format.STRING), 'int')
def test_constraints(self): def test_constraints(self):
def f[T: (int, str)](): pass def f[T: (int, str)](): pass
@ -1451,7 +1451,7 @@ class TestEvaluateFunctions(unittest.TestCase):
self.assertEqual(case.evaluate_constraints(1), (int, str)) self.assertEqual(case.evaluate_constraints(1), (int, str))
self.assertEqual(annotationlib.call_evaluate_function(case.evaluate_constraints, annotationlib.Format.VALUE), (int, str)) self.assertEqual(annotationlib.call_evaluate_function(case.evaluate_constraints, annotationlib.Format.VALUE), (int, str))
self.assertEqual(annotationlib.call_evaluate_function(case.evaluate_constraints, annotationlib.Format.FORWARDREF), (int, str)) self.assertEqual(annotationlib.call_evaluate_function(case.evaluate_constraints, annotationlib.Format.FORWARDREF), (int, str))
self.assertEqual(annotationlib.call_evaluate_function(case.evaluate_constraints, annotationlib.Format.SOURCE), '(int, str)') self.assertEqual(annotationlib.call_evaluate_function(case.evaluate_constraints, annotationlib.Format.STRING), '(int, str)')
def test_const_evaluator(self): def test_const_evaluator(self):
T = TypeVar("T", bound=int) T = TypeVar("T", bound=int)

View File

@ -7059,7 +7059,7 @@ class GetTypeHintTests(BaseTestCase):
self.assertIsInstance(annos['x'], annotationlib.ForwardRef) self.assertIsInstance(annos['x'], annotationlib.ForwardRef)
self.assertEqual(annos['x'].__arg__, 'undefined') self.assertEqual(annos['x'].__arg__, 'undefined')
self.assertEqual(get_type_hints(C, format=annotationlib.Format.SOURCE), self.assertEqual(get_type_hints(C, format=annotationlib.Format.STRING),
{'x': 'undefined'}) {'x': 'undefined'})
@ -7898,7 +7898,7 @@ class NamedTupleTests(BaseTestCase):
self.assertEqual(Z.__annotations__, annos) self.assertEqual(Z.__annotations__, annos)
self.assertEqual(Z.__annotate__(annotationlib.Format.VALUE), annos) self.assertEqual(Z.__annotate__(annotationlib.Format.VALUE), annos)
self.assertEqual(Z.__annotate__(annotationlib.Format.FORWARDREF), annos) self.assertEqual(Z.__annotate__(annotationlib.Format.FORWARDREF), annos)
self.assertEqual(Z.__annotate__(annotationlib.Format.SOURCE), {"a": "None", "b": "str"}) self.assertEqual(Z.__annotate__(annotationlib.Format.STRING), {"a": "None", "b": "str"})
def test_future_annotations(self): def test_future_annotations(self):
code = """ code = """
@ -8241,7 +8241,7 @@ class TypedDictTests(BaseTestCase):
self.assertEqual(Emp.__annotations__, annos) self.assertEqual(Emp.__annotations__, annos)
self.assertEqual(Emp.__annotate__(annotationlib.Format.VALUE), annos) self.assertEqual(Emp.__annotate__(annotationlib.Format.VALUE), annos)
self.assertEqual(Emp.__annotate__(annotationlib.Format.FORWARDREF), annos) self.assertEqual(Emp.__annotate__(annotationlib.Format.FORWARDREF), annos)
self.assertEqual(Emp.__annotate__(annotationlib.Format.SOURCE), {'name': 'str', 'id': 'int'}) self.assertEqual(Emp.__annotate__(annotationlib.Format.STRING), {'name': 'str', 'id': 'int'})
self.assertEqual(Emp.__total__, True) self.assertEqual(Emp.__total__, True)
self.assertEqual(Emp.__required_keys__, {'name', 'id'}) self.assertEqual(Emp.__required_keys__, {'name', 'id'})
self.assertIsInstance(Emp.__required_keys__, frozenset) self.assertIsInstance(Emp.__required_keys__, frozenset)
@ -8603,7 +8603,7 @@ class TypedDictTests(BaseTestCase):
self.assertEqual(A.__orig_bases__, (TypedDict, Generic[T])) self.assertEqual(A.__orig_bases__, (TypedDict, Generic[T]))
self.assertEqual(A.__mro__, (A, Generic, dict, object)) self.assertEqual(A.__mro__, (A, Generic, dict, object))
self.assertEqual(A.__annotations__, {'a': T}) self.assertEqual(A.__annotations__, {'a': T})
self.assertEqual(A.__annotate__(annotationlib.Format.SOURCE), {'a': 'T'}) self.assertEqual(A.__annotate__(annotationlib.Format.STRING), {'a': 'T'})
self.assertEqual(A.__parameters__, (T,)) self.assertEqual(A.__parameters__, (T,))
self.assertEqual(A[str].__parameters__, ()) self.assertEqual(A[str].__parameters__, ())
self.assertEqual(A[str].__args__, (str,)) self.assertEqual(A[str].__args__, (str,))
@ -8616,7 +8616,7 @@ class TypedDictTests(BaseTestCase):
self.assertEqual(A.__orig_bases__, (TypedDict, Generic[T])) self.assertEqual(A.__orig_bases__, (TypedDict, Generic[T]))
self.assertEqual(A.__mro__, (A, Generic, dict, object)) self.assertEqual(A.__mro__, (A, Generic, dict, object))
self.assertEqual(A.__annotations__, {'a': T}) self.assertEqual(A.__annotations__, {'a': T})
self.assertEqual(A.__annotate__(annotationlib.Format.SOURCE), {'a': 'T'}) self.assertEqual(A.__annotate__(annotationlib.Format.STRING), {'a': 'T'})
self.assertEqual(A.__parameters__, (T,)) self.assertEqual(A.__parameters__, (T,))
self.assertEqual(A[str].__parameters__, ()) self.assertEqual(A[str].__parameters__, ())
self.assertEqual(A[str].__args__, (str,)) self.assertEqual(A[str].__args__, (str,))
@ -8628,7 +8628,7 @@ class TypedDictTests(BaseTestCase):
self.assertEqual(A2.__orig_bases__, (Generic[T], TypedDict)) self.assertEqual(A2.__orig_bases__, (Generic[T], TypedDict))
self.assertEqual(A2.__mro__, (A2, Generic, dict, object)) self.assertEqual(A2.__mro__, (A2, Generic, dict, object))
self.assertEqual(A2.__annotations__, {'a': T}) self.assertEqual(A2.__annotations__, {'a': T})
self.assertEqual(A2.__annotate__(annotationlib.Format.SOURCE), {'a': 'T'}) self.assertEqual(A2.__annotate__(annotationlib.Format.STRING), {'a': 'T'})
self.assertEqual(A2.__parameters__, (T,)) self.assertEqual(A2.__parameters__, (T,))
self.assertEqual(A2[str].__parameters__, ()) self.assertEqual(A2[str].__parameters__, ())
self.assertEqual(A2[str].__args__, (str,)) self.assertEqual(A2[str].__args__, (str,))
@ -8640,7 +8640,7 @@ class TypedDictTests(BaseTestCase):
self.assertEqual(B.__orig_bases__, (A[KT],)) self.assertEqual(B.__orig_bases__, (A[KT],))
self.assertEqual(B.__mro__, (B, Generic, dict, object)) self.assertEqual(B.__mro__, (B, Generic, dict, object))
self.assertEqual(B.__annotations__, {'a': T, 'b': KT}) self.assertEqual(B.__annotations__, {'a': T, 'b': KT})
self.assertEqual(B.__annotate__(annotationlib.Format.SOURCE), {'a': 'T', 'b': 'KT'}) self.assertEqual(B.__annotate__(annotationlib.Format.STRING), {'a': 'T', 'b': 'KT'})
self.assertEqual(B.__parameters__, (KT,)) self.assertEqual(B.__parameters__, (KT,))
self.assertEqual(B.__total__, False) self.assertEqual(B.__total__, False)
self.assertEqual(B.__optional_keys__, frozenset(['b'])) self.assertEqual(B.__optional_keys__, frozenset(['b']))
@ -8665,7 +8665,7 @@ class TypedDictTests(BaseTestCase):
'b': KT, 'b': KT,
'c': int, 'c': int,
}) })
self.assertEqual(C.__annotate__(annotationlib.Format.SOURCE), { self.assertEqual(C.__annotate__(annotationlib.Format.STRING), {
'a': 'T', 'a': 'T',
'b': 'KT', 'b': 'KT',
'c': 'int', 'c': 'int',
@ -8689,7 +8689,7 @@ class TypedDictTests(BaseTestCase):
'b': T, 'b': T,
'c': KT, 'c': KT,
}) })
self.assertEqual(Point3D.__annotate__(annotationlib.Format.SOURCE), { self.assertEqual(Point3D.__annotate__(annotationlib.Format.STRING), {
'a': 'T', 'a': 'T',
'b': 'T', 'b': 'T',
'c': 'KT', 'c': 'KT',
@ -8725,7 +8725,7 @@ class TypedDictTests(BaseTestCase):
'b': KT, 'b': KT,
'c': int, 'c': int,
}) })
self.assertEqual(WithImplicitAny.__annotate__(annotationlib.Format.SOURCE), { self.assertEqual(WithImplicitAny.__annotate__(annotationlib.Format.STRING), {
'a': 'T', 'a': 'T',
'b': 'KT', 'b': 'KT',
'c': 'int', 'c': 'int',
@ -8929,7 +8929,7 @@ class TypedDictTests(BaseTestCase):
A.__annotations__ A.__annotations__
self.assertEqual( self.assertEqual(
A.__annotate__(annotationlib.Format.SOURCE), A.__annotate__(annotationlib.Format.STRING),
{'x': 'NotRequired[undefined]', 'y': 'ReadOnly[undefined]', {'x': 'NotRequired[undefined]', 'y': 'ReadOnly[undefined]',
'z': 'Required[undefined]'}, 'z': 'Required[undefined]'},
) )

View File

@ -245,7 +245,7 @@ def _type_repr(obj):
if isinstance(obj, tuple): if isinstance(obj, tuple):
# Special case for `repr` of types with `ParamSpec`: # Special case for `repr` of types with `ParamSpec`:
return '[' + ', '.join(_type_repr(t) for t in obj) + ']' return '[' + ', '.join(_type_repr(t) for t in obj) + ']'
return annotationlib.value_to_source(obj) return annotationlib.value_to_string(obj)
def _collect_type_parameters(args, *, enforce_default_ordering: bool = True): def _collect_type_parameters(args, *, enforce_default_ordering: bool = True):
@ -1036,7 +1036,7 @@ def evaluate_forward_ref(
* Recursively evaluates forward references nested within the type hint. * Recursively evaluates forward references nested within the type hint.
* Rejects certain objects that are not valid type hints. * Rejects certain objects that are not valid type hints.
* Replaces type hints that evaluate to None with types.NoneType. * Replaces type hints that evaluate to None with types.NoneType.
* Supports the *FORWARDREF* and *SOURCE* formats. * Supports the *FORWARDREF* and *STRING* formats.
*forward_ref* must be an instance of ForwardRef. *owner*, if given, *forward_ref* must be an instance of ForwardRef. *owner*, if given,
should be the object that holds the annotations that the forward reference should be the object that holds the annotations that the forward reference
@ -1053,7 +1053,7 @@ def evaluate_forward_ref(
if type_params is _sentinel: if type_params is _sentinel:
_deprecation_warning_for_no_type_params_passed("typing.evaluate_forward_ref") _deprecation_warning_for_no_type_params_passed("typing.evaluate_forward_ref")
type_params = () type_params = ()
if format == annotationlib.Format.SOURCE: if format == annotationlib.Format.STRING:
return forward_ref.__forward_arg__ return forward_ref.__forward_arg__
if forward_ref.__forward_arg__ in _recursive_guard: if forward_ref.__forward_arg__ in _recursive_guard:
return forward_ref return forward_ref
@ -2380,7 +2380,7 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False,
hints = {} hints = {}
for base in reversed(obj.__mro__): for base in reversed(obj.__mro__):
ann = annotationlib.get_annotations(base, format=format) ann = annotationlib.get_annotations(base, format=format)
if format is annotationlib.Format.SOURCE: if format is annotationlib.Format.STRING:
hints.update(ann) hints.update(ann)
continue continue
if globalns is None: if globalns is None:
@ -2404,7 +2404,7 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False,
value = _eval_type(value, base_globals, base_locals, base.__type_params__, value = _eval_type(value, base_globals, base_locals, base.__type_params__,
format=format, owner=obj) format=format, owner=obj)
hints[name] = value hints[name] = value
if include_extras or format is annotationlib.Format.SOURCE: if include_extras or format is annotationlib.Format.STRING:
return hints return hints
else: else:
return {k: _strip_annotations(t) for k, t in hints.items()} return {k: _strip_annotations(t) for k, t in hints.items()}
@ -2418,7 +2418,7 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False,
and not hasattr(obj, '__annotate__') and not hasattr(obj, '__annotate__')
): ):
raise TypeError(f"{obj!r} is not a module, class, or callable.") raise TypeError(f"{obj!r} is not a module, class, or callable.")
if format is annotationlib.Format.SOURCE: if format is annotationlib.Format.STRING:
return hints return hints
if globalns is None: if globalns is None:
@ -2937,7 +2937,7 @@ def _make_eager_annotate(types):
if format in (annotationlib.Format.VALUE, annotationlib.Format.FORWARDREF): if format in (annotationlib.Format.VALUE, annotationlib.Format.FORWARDREF):
return checked_types return checked_types
else: else:
return annotationlib.annotations_to_source(types) return annotationlib.annotations_to_string(types)
return annotate return annotate
@ -2972,7 +2972,7 @@ class NamedTupleMeta(type):
def annotate(format): def annotate(format):
annos = annotationlib.call_annotate_function(original_annotate, format) annos = annotationlib.call_annotate_function(original_annotate, format)
if format != annotationlib.Format.SOURCE: if format != annotationlib.Format.STRING:
return {key: _type_check(val, f"field {key} annotation must be a type") return {key: _type_check(val, f"field {key} annotation must be a type")
for key, val in annos.items()} for key, val in annos.items()}
return annos return annos
@ -3220,13 +3220,13 @@ class _TypedDictMeta(type):
annos.update(base_annos) annos.update(base_annos)
if own_annotate is not None: if own_annotate is not None:
own = annotationlib.call_annotate_function(own_annotate, format, owner=tp_dict) own = annotationlib.call_annotate_function(own_annotate, format, owner=tp_dict)
if format != annotationlib.Format.SOURCE: if format != annotationlib.Format.STRING:
own = { own = {
n: _type_check(tp, msg, module=tp_dict.__module__) n: _type_check(tp, msg, module=tp_dict.__module__)
for n, tp in own.items() for n, tp in own.items()
} }
elif format == annotationlib.Format.SOURCE: elif format == annotationlib.Format.STRING:
own = annotationlib.annotations_to_source(own_annotations) own = annotationlib.annotations_to_string(own_annotations)
else: else:
own = own_checked_annotations own = own_checked_annotations
annos.update(own) annos.update(own)

View File

@ -168,7 +168,7 @@ constevaluator_call(PyObject *self, PyObject *args, PyObject *kwargs)
return NULL; return NULL;
} }
PyObject *value = ((constevaluatorobject *)self)->value; PyObject *value = ((constevaluatorobject *)self)->value;
if (format == 3) { // SOURCE if (format == 3) { // STRING
PyUnicodeWriter *writer = PyUnicodeWriter_Create(5); // cannot be <5 PyUnicodeWriter *writer = PyUnicodeWriter_Create(5); // cannot be <5
if (writer == NULL) { if (writer == NULL) {
return NULL; return NULL;