gh-132491: Rename annotationlib.value_to_string to type_repr (#132492)

This commit is contained in:
Jelle Zijlstra 2025-04-15 13:10:53 -07:00 committed by GitHub
parent 5e80fee41a
commit 11f6603845
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 37 additions and 26 deletions

View file

@ -214,7 +214,7 @@ Functions
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_string`. they are converted using :func:`type_repr`.
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.STRING` 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.
@ -393,7 +393,7 @@ Functions
.. versionadded:: 3.14 .. versionadded:: 3.14
.. function:: value_to_string(value) .. function:: type_repr(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.STRING` format. This calls :func:`repr` for most :attr:`~Format.STRING` format. This calls :func:`repr` for most

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_string from annotationlib import type_repr
return (f'collections.abc.Callable' return (f'collections.abc.Callable'
f'[[{", ".join([value_to_string(a) for a in self.__args__[:-1]])}], ' f'[[{", ".join([type_repr(a) for a in self.__args__[:-1]])}], '
f'{value_to_string(self.__args__[-1])}]') f'{type_repr(self.__args__[-1])}]')
def __reduce__(self): def __reduce__(self):
args = self.__args__ args = self.__args__

View file

@ -15,7 +15,7 @@ __all__ = [
"get_annotate_function", "get_annotate_function",
"get_annotations", "get_annotations",
"annotations_to_string", "annotations_to_string",
"value_to_string", "type_repr",
] ]
@ -795,29 +795,27 @@ def get_annotations(
return return_value return return_value
def value_to_string(value): def type_repr(value):
"""Convert a Python value to a format suitable for use with the STRING 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 STRING format but do This is intended 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.
""" """
if isinstance(value, type): if isinstance(value, (type, types.FunctionType, types.BuiltinFunctionType)):
if value.__module__ == "builtins": if value.__module__ == "builtins":
return value.__qualname__ return value.__qualname__
return f"{value.__module__}.{value.__qualname__}" return f"{value.__module__}.{value.__qualname__}"
if value is ...: if value is ...:
return "..." return "..."
if isinstance(value, (types.FunctionType, types.BuiltinFunctionType)):
return value.__name__
return repr(value) return repr(value)
def annotations_to_string(annotations): def annotations_to_string(annotations):
"""Convert an annotation dict containing values to approximately the STRING format.""" """Convert an annotation dict containing values to approximately the STRING format."""
return { return {
n: t if isinstance(t, str) else value_to_string(t) n: t if isinstance(t, str) else type_repr(t)
for n, t in annotations.items() for n, t in annotations.items()
} }

View file

@ -13,7 +13,7 @@ from annotationlib import (
get_annotations, get_annotations,
get_annotate_function, get_annotate_function,
annotations_to_string, annotations_to_string,
value_to_string, type_repr,
) )
from typing import Unpack from typing import Unpack
@ -1173,18 +1173,28 @@ class TestGetAnnotateFunction(unittest.TestCase):
class TestToSource(unittest.TestCase): class TestToSource(unittest.TestCase):
def test_value_to_string(self): def test_type_repr(self):
self.assertEqual(value_to_string(int), "int") class Nested:
self.assertEqual(value_to_string(MyClass), "test.test_annotationlib.MyClass") pass
self.assertEqual(value_to_string(len), "len")
self.assertEqual(value_to_string(value_to_string), "value_to_string") def nested():
self.assertEqual(value_to_string(times_three), "times_three") pass
self.assertEqual(value_to_string(...), "...")
self.assertEqual(value_to_string(None), "None") self.assertEqual(type_repr(int), "int")
self.assertEqual(value_to_string(1), "1") self.assertEqual(type_repr(MyClass), f"{__name__}.MyClass")
self.assertEqual(value_to_string("1"), "'1'") self.assertEqual(
self.assertEqual(value_to_string(Format.VALUE), repr(Format.VALUE)) type_repr(Nested), f"{__name__}.TestToSource.test_type_repr.<locals>.Nested")
self.assertEqual(value_to_string(MyClass()), "my repr") self.assertEqual(
type_repr(nested), f"{__name__}.TestToSource.test_type_repr.<locals>.nested")
self.assertEqual(type_repr(len), "len")
self.assertEqual(type_repr(type_repr), "annotationlib.type_repr")
self.assertEqual(type_repr(times_three), f"{__name__}.times_three")
self.assertEqual(type_repr(...), "...")
self.assertEqual(type_repr(None), "None")
self.assertEqual(type_repr(1), "1")
self.assertEqual(type_repr("1"), "'1'")
self.assertEqual(type_repr(Format.VALUE), repr(Format.VALUE))
self.assertEqual(type_repr(MyClass()), "my repr")
def test_annotations_to_string(self): def test_annotations_to_string(self):
self.assertEqual(annotations_to_string({}), {}) self.assertEqual(annotations_to_string({}), {})

View file

@ -253,7 +253,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 _lazy_annotationlib.value_to_string(obj) return _lazy_annotationlib.type_repr(obj)
def _collect_type_parameters(args, *, enforce_default_ordering: bool = True): def _collect_type_parameters(args, *, enforce_default_ordering: bool = True):

View file

@ -0,0 +1,3 @@
Rename ``annotationlib.value_to_string`` to
:func:`annotationlib.type_repr` and provide better handling for function
objects.