From 9c72194ba600f8a4da4405c1827d33b4ce97d6cb Mon Sep 17 00:00:00 2001 From: donBarbos Date: Wed, 6 Aug 2025 21:17:36 +0400 Subject: [PATCH 1/4] Add backport for `annotationlib.type_repr` Closes: #544 --- CHANGELOG.md | 9 ++++++++ doc/index.rst | 10 +++++++++ src/test_typing_extensions.py | 39 +++++++++++++++++++++++++++++++++++ src/typing_extensions.py | 21 +++++++++++++++++++ 4 files changed, 79 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8855595e..d3b768ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +# Unreleased + +- Add `typing_extensions.type_repr` helper function, a backport of + [`annotationlib.type_repr`](https://docs.python.org/3.14/library/annotationlib.html#annotationlib.type_repr), + introduced in Python 3.14 (CPython PR + https://github.com/python/cpython/pull/124551, originally by Jelle Zijlstra). + Patch by Semyon Moroz. + + # Release 4.14.1 (July 4, 2025) - Fix usage of `typing_extensions.TypedDict` nested inside other types diff --git a/doc/index.rst b/doc/index.rst index 21d6fa60..67a250d4 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -933,6 +933,16 @@ Functions .. versionadded:: 4.1.0 +.. function:: type_repr(value) + + See :py:func:`annotationlib.type_repr`. In ``annotationlib`` since 3.14. + + Convert an arbitrary Python value to a format suitable for use by + the :attr:`Format.STRING`. + + + .. versionadded:: 4.15.0 + Enums ~~~~~ diff --git a/src/test_typing_extensions.py b/src/test_typing_extensions.py index cb3b462b..7a6380a3 100644 --- a/src/test_typing_extensions.py +++ b/src/test_typing_extensions.py @@ -101,6 +101,7 @@ reveal_type, runtime, runtime_checkable, + type_repr, ) NoneType = type(None) @@ -8368,6 +8369,44 @@ def test_capsule_type(self): self.assertIsInstance(_datetime.datetime_CAPI, typing_extensions.CapsuleType) +class MyClass: + def __repr__(self): + return "my repr" + + +class TestTypeRepr(BaseTestCase): + def test_custom_types(self): + + class Nested: + pass + + def nested(): + pass + + self.assertEqual(type_repr(MyClass), f"{__name__}.MyClass") + self.assertEqual( + type_repr(Nested), + f"{__name__}.TestTypeRepr.test_custom_types..Nested", + ) + self.assertEqual( + type_repr(nested), + f"{__name__}.TestTypeRepr.test_custom_types..nested", + ) + self.assertEqual(type_repr(times_three), f"{__name__}.times_three") + self.assertEqual(type_repr(Format.VALUE), repr(Format.VALUE)) + self.assertEqual(type_repr(MyClass()), "my repr") + + def test_builtin_types(self): + self.assertEqual(type_repr(int), "int") + self.assertEqual(type_repr(object), "object") + self.assertEqual(type_repr(None), "None") + self.assertEqual(type_repr(len), "len") + self.assertEqual(type_repr(1), "1") + self.assertEqual(type_repr("1"), "'1'") + self.assertEqual(type_repr(''), "''") + self.assertEqual(type_repr(...), "...") + + def times_three(fn): @functools.wraps(fn) def wrapper(a, b): diff --git a/src/typing_extensions.py b/src/typing_extensions.py index efa09d55..7f838700 100644 --- a/src/typing_extensions.py +++ b/src/typing_extensions.py @@ -100,6 +100,7 @@ 'TypeGuard', 'TypeIs', 'TYPE_CHECKING', + 'type_repr', 'Never', 'NoReturn', 'ReadOnly', @@ -4192,6 +4193,26 @@ def __getstate__(self): raise TypeError(f"Cannot pickle {type(self).__name__!r} object") +if sys.version_info >= (3, 14, 0, "beta"): + type_repr = annotationlib.type_repr +else: + def type_repr(value): + """Convert a Python value to a format suitable for use with the STRING format. + + 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 + repr() for most objects. + + """ + if isinstance(value, (type, _types.FunctionType, _types.BuiltinFunctionType)): + if value.__module__ == "builtins": + return value.__qualname__ + return f"{value.__module__}.{value.__qualname__}" + if value is ...: + return "..." + return repr(value) + + # Aliases for items that are in typing in all supported versions. # We use hasattr() checks so this library will continue to import on # future versions of Python that may remove these names. From 5fd96c2e8e8035059a2047dce79b0ad58829f6de Mon Sep 17 00:00:00 2001 From: Semyon Moroz Date: Wed, 6 Aug 2025 17:34:38 +0000 Subject: [PATCH 2/4] Update CHANGELOG.md Co-authored-by: Brian Schubert --- CHANGELOG.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d3b768ee..9b9dc8db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,9 @@ # Unreleased -- Add `typing_extensions.type_repr` helper function, a backport of +- Add `typing_extensions.type_repr`, a backport of [`annotationlib.type_repr`](https://docs.python.org/3.14/library/annotationlib.html#annotationlib.type_repr), - introduced in Python 3.14 (CPython PR - https://github.com/python/cpython/pull/124551, originally by Jelle Zijlstra). - Patch by Semyon Moroz. + introduced in Python 3.14 (CPython PR [#124551](https://github.com/python/cpython/pull/124551), + originally by Jelle Zijlstra). Patch by Semyon Moroz. # Release 4.14.1 (July 4, 2025) From c37a6ee8e21b98f7d9895280bb11dce8d2090c68 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 6 Aug 2025 17:35:58 +0000 Subject: [PATCH 3/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b9dc8db..cb143299 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ - Add `typing_extensions.type_repr`, a backport of [`annotationlib.type_repr`](https://docs.python.org/3.14/library/annotationlib.html#annotationlib.type_repr), - introduced in Python 3.14 (CPython PR [#124551](https://github.com/python/cpython/pull/124551), + introduced in Python 3.14 (CPython PR [#124551](https://github.com/python/cpython/pull/124551), originally by Jelle Zijlstra). Patch by Semyon Moroz. From 494c13f9c64a82d6574b5a3f049910d06b0fec0b Mon Sep 17 00:00:00 2001 From: Semyon Moroz Date: Wed, 6 Aug 2025 17:57:31 +0000 Subject: [PATCH 4/4] Update index.rst Co-authored-by: Brian Schubert --- doc/index.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/index.rst b/doc/index.rst index 67a250d4..c22336fb 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -940,7 +940,6 @@ Functions Convert an arbitrary Python value to a format suitable for use by the :attr:`Format.STRING`. - .. versionadded:: 4.15.0 Enums