From 08d866b39203ba639e8d0b4f07194e5547f973f5 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sat, 28 Sep 2024 14:27:09 -0700 Subject: [PATCH] Rename TypeExpr to TypeForm (#475) No backwards compatibility required because we never released TypeExpr. Also took the opportunity to expand the docstring. --- CHANGELOG.md | 2 +- doc/index.rst | 4 +-- src/test_typing_extensions.py | 46 +++++++++++++++++------------------ src/typing_extensions.py | 44 +++++++++++++++++++++------------ 4 files changed, 55 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01eee613..db6719c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Unreleased -- Add `typing_extensions.TypeExpr` from PEP 747. Patch by +- Add `typing_extensions.TypeForm` from PEP 747. Patch by Jelle Zijlstra. - Add `typing_extensions.get_annotations`, a backport of `inspect.get_annotations` that adds features specified diff --git a/doc/index.rst b/doc/index.rst index 23a531c4..91740aa7 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -367,9 +367,9 @@ Special typing primitives .. versionadded:: 4.6.0 -.. data:: TypeExpr +.. data:: TypeForm - See :pep:`747`. A type hint representing a type expression. + See :pep:`747`. A special form representing the value of a type expression. .. versionadded:: 4.13.0 diff --git a/src/test_typing_extensions.py b/src/test_typing_extensions.py index 81a4c7ca..8c2726f8 100644 --- a/src/test_typing_extensions.py +++ b/src/test_typing_extensions.py @@ -70,7 +70,7 @@ TypeAlias, TypeAliasType, TypedDict, - TypeExpr, + TypeForm, TypeGuard, TypeIs, TypeVar, @@ -5508,33 +5508,33 @@ def test_no_isinstance(self): issubclass(int, TypeIs) -class TypeExprTests(BaseTestCase): +class TypeFormTests(BaseTestCase): def test_basics(self): - TypeExpr[int] # OK - self.assertEqual(TypeExpr[int], TypeExpr[int]) + TypeForm[int] # OK + self.assertEqual(TypeForm[int], TypeForm[int]) - def foo(arg) -> TypeExpr[int]: ... - self.assertEqual(gth(foo), {'return': TypeExpr[int]}) + def foo(arg) -> TypeForm[int]: ... + self.assertEqual(gth(foo), {'return': TypeForm[int]}) def test_repr(self): - if hasattr(typing, 'TypeExpr'): + if hasattr(typing, 'TypeForm'): mod_name = 'typing' else: mod_name = 'typing_extensions' - self.assertEqual(repr(TypeExpr), f'{mod_name}.TypeExpr') - cv = TypeExpr[int] - self.assertEqual(repr(cv), f'{mod_name}.TypeExpr[int]') - cv = TypeExpr[Employee] - self.assertEqual(repr(cv), f'{mod_name}.TypeExpr[{__name__}.Employee]') - cv = TypeExpr[Tuple[int]] - self.assertEqual(repr(cv), f'{mod_name}.TypeExpr[typing.Tuple[int]]') + self.assertEqual(repr(TypeForm), f'{mod_name}.TypeForm') + cv = TypeForm[int] + self.assertEqual(repr(cv), f'{mod_name}.TypeForm[int]') + cv = TypeForm[Employee] + self.assertEqual(repr(cv), f'{mod_name}.TypeForm[{__name__}.Employee]') + cv = TypeForm[Tuple[int]] + self.assertEqual(repr(cv), f'{mod_name}.TypeForm[typing.Tuple[int]]') def test_cannot_subclass(self): with self.assertRaises(TypeError): - class C(type(TypeExpr)): + class C(type(TypeForm)): pass with self.assertRaises(TypeError): - class D(type(TypeExpr[int])): + class D(type(TypeForm[int])): pass def test_call(self): @@ -5546,24 +5546,24 @@ def test_call(self): ] for obj in objs: with self.subTest(obj=obj): - self.assertIs(TypeExpr(obj), obj) + self.assertIs(TypeForm(obj), obj) with self.assertRaises(TypeError): - TypeExpr() + TypeForm() with self.assertRaises(TypeError): - TypeExpr("too", "many") + TypeForm("too", "many") def test_cannot_init_type(self): with self.assertRaises(TypeError): - type(TypeExpr)() + type(TypeForm)() with self.assertRaises(TypeError): - type(TypeExpr[Optional[int]])() + type(TypeForm[Optional[int]])() def test_no_isinstance(self): with self.assertRaises(TypeError): - isinstance(1, TypeExpr[int]) + isinstance(1, TypeForm[int]) with self.assertRaises(TypeError): - issubclass(int, TypeExpr) + issubclass(int, TypeForm) class LiteralStringTests(BaseTestCase): diff --git a/src/typing_extensions.py b/src/typing_extensions.py index 3fd797a2..5bf4f2dc 100644 --- a/src/typing_extensions.py +++ b/src/typing_extensions.py @@ -86,7 +86,7 @@ 'Text', 'TypeAlias', 'TypeAliasType', - 'TypeExpr', + 'TypeForm', 'TypeGuard', 'TypeIs', 'TYPE_CHECKING', @@ -2047,23 +2047,30 @@ def f(val: Union[int, Awaitable[int]]) -> int: """) # 3.14+? -if hasattr(typing, 'TypeExpr'): - TypeExpr = typing.TypeExpr +if hasattr(typing, 'TypeForm'): + TypeForm = typing.TypeForm # 3.9 elif sys.version_info[:2] >= (3, 9): - class _TypeExprForm(_ExtensionsSpecialForm, _root=True): - # TypeExpr(X) is equivalent to X but indicates to the type checker - # that the object is a TypeExpr. + class _TypeFormForm(_ExtensionsSpecialForm, _root=True): + # TypeForm(X) is equivalent to X but indicates to the type checker + # that the object is a TypeForm. def __call__(self, obj, /): return obj - @_TypeExprForm - def TypeExpr(self, parameters): - """Special typing form used to represent a type expression. + @_TypeFormForm + def TypeForm(self, parameters): + """A special form representing the value that results from the evaluation + of a type expression. This value encodes the information supplied in the + type expression, and it represents the type described by that type expression. + + When used in a type expression, TypeForm describes a set of type form objects. + It accepts a single type argument, which must be a valid type expression. + ``TypeForm[T]`` describes the set of all type form objects that represent + the type T or types that are assignable to T. Usage: - def cast[T](typ: TypeExpr[T], value: Any) -> T: ... + def cast[T](typ: TypeForm[T], value: Any) -> T: ... reveal_type(cast(int, "x")) # int @@ -2073,7 +2080,7 @@ def cast[T](typ: TypeExpr[T], value: Any) -> T: ... return typing._GenericAlias(self, (item,)) # 3.8 else: - class _TypeExprForm(_ExtensionsSpecialForm, _root=True): + class _TypeFormForm(_ExtensionsSpecialForm, _root=True): def __getitem__(self, parameters): item = typing._type_check(parameters, f'{self._name} accepts only a single type') @@ -2082,13 +2089,20 @@ def __getitem__(self, parameters): def __call__(self, obj, /): return obj - TypeExpr = _TypeExprForm( - 'TypeExpr', - doc="""Special typing form used to represent a type expression. + TypeForm = _TypeFormForm( + 'TypeForm', + doc="""A special form representing the value that results from the evaluation + of a type expression. This value encodes the information supplied in the + type expression, and it represents the type described by that type expression. + + When used in a type expression, TypeForm describes a set of type form objects. + It accepts a single type argument, which must be a valid type expression. + ``TypeForm[T]`` describes the set of all type form objects that represent + the type T or types that are assignable to T. Usage: - def cast[T](typ: TypeExpr[T], value: Any) -> T: ... + def cast[T](typ: TypeForm[T], value: Any) -> T: ... reveal_type(cast(int, "x")) # int