bpo-41923: PEP 613: Add TypeAlias to typing module (#22532)
This special marker annotation is intended to help in distinguishing proper PEP 484-compliant type aliases from regular top-level variable assignments.
This commit is contained in:
parent
f90dc36c15
commit
4f3c25043d
|
@ -34,6 +34,8 @@ In the function ``greeting``, the argument ``name`` is expected to be of type
|
|||
:class:`str` and the return type :class:`str`. Subtypes are accepted as
|
||||
arguments.
|
||||
|
||||
.. _type-aliases:
|
||||
|
||||
Type aliases
|
||||
============
|
||||
|
||||
|
@ -489,6 +491,17 @@ These can be used as types in annotations and do not support ``[]``.
|
|||
.. versionadded:: 3.5.4
|
||||
.. versionadded:: 3.6.2
|
||||
|
||||
.. data:: TypeAlias
|
||||
|
||||
Special annotation for explicitly declaring a :ref:`type alias <type-aliases>`.
|
||||
For example::
|
||||
|
||||
from typing import TypeAlias
|
||||
|
||||
Factors: TypeAlias = list[int]
|
||||
|
||||
.. versionadded:: 3.10
|
||||
|
||||
Special forms
|
||||
"""""""""""""
|
||||
|
||||
|
|
|
@ -99,8 +99,29 @@ in :issue:`38605`.)
|
|||
* :pep:`618`: The :func:`zip` function now has an optional ``strict`` flag, used
|
||||
to require that all the iterables have an equal length.
|
||||
|
||||
PEP604: New Type Operator
|
||||
-------------------------
|
||||
PEP 613: TypeAlias Annotation
|
||||
-----------------------------
|
||||
|
||||
:pep:`484` introduced the concept of type aliases, only requiring them to be
|
||||
top-level unannotated assignments. This simplicity sometimes made it difficult
|
||||
for type checkers to distinguish between type aliases and ordinary assignments,
|
||||
especially when forward references or invalid types were involved. Compare::
|
||||
|
||||
StrCache = 'Cache[str]' # a type alias
|
||||
LOG_PREFIX = 'LOG[DEBUG]' # a module constant
|
||||
|
||||
Now the :mod:`typing` module has a special annotation :data:`TypeAlias` to
|
||||
declare type aliases more explicitly::
|
||||
|
||||
StrCache: TypeAlias = 'Cache[str]' # a type alias
|
||||
LOG_PREFIX = 'LOG[DEBUG]' # a module constant
|
||||
|
||||
See :pep:`613` for more details.
|
||||
|
||||
(Contributed by Mikhail Golubev in :issue:`41923`.)
|
||||
|
||||
PEP604: New Type Union Operator
|
||||
-------------------------------
|
||||
|
||||
A new type union operator was introduced which enables the syntax ``X | Y``.
|
||||
This provides a cleaner way of expressing 'either type X or type Y' instead of
|
||||
|
|
|
@ -24,6 +24,7 @@ from typing import NamedTuple, TypedDict
|
|||
from typing import IO, TextIO, BinaryIO
|
||||
from typing import Pattern, Match
|
||||
from typing import Annotated, ForwardRef
|
||||
from typing import TypeAlias
|
||||
import abc
|
||||
import typing
|
||||
import weakref
|
||||
|
@ -4176,6 +4177,45 @@ class AnnotatedTests(BaseTestCase):
|
|||
self.assertEqual(X[int], List[Annotated[int, 5]])
|
||||
|
||||
|
||||
class TypeAliasTests(BaseTestCase):
|
||||
def test_canonical_usage_with_variable_annotation(self):
|
||||
Alias: TypeAlias = Employee
|
||||
|
||||
def test_canonical_usage_with_type_comment(self):
|
||||
Alias = Employee # type: TypeAlias
|
||||
|
||||
def test_cannot_instantiate(self):
|
||||
with self.assertRaises(TypeError):
|
||||
TypeAlias()
|
||||
|
||||
def test_no_isinstance(self):
|
||||
with self.assertRaises(TypeError):
|
||||
isinstance(42, TypeAlias)
|
||||
|
||||
def test_no_issubclass(self):
|
||||
with self.assertRaises(TypeError):
|
||||
issubclass(Employee, TypeAlias)
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
issubclass(TypeAlias, Employee)
|
||||
|
||||
def test_cannot_subclass(self):
|
||||
with self.assertRaises(TypeError):
|
||||
class C(TypeAlias):
|
||||
pass
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
class C(type(TypeAlias)):
|
||||
pass
|
||||
|
||||
def test_repr(self):
|
||||
self.assertEqual(repr(TypeAlias), 'typing.TypeAlias')
|
||||
|
||||
def test_cannot_subscript(self):
|
||||
with self.assertRaises(TypeError):
|
||||
TypeAlias[int]
|
||||
|
||||
|
||||
class AllTests(BaseTestCase):
|
||||
"""Tests for __all__."""
|
||||
|
||||
|
|
|
@ -113,6 +113,7 @@ __all__ = [
|
|||
'runtime_checkable',
|
||||
'Text',
|
||||
'TYPE_CHECKING',
|
||||
'TypeAlias',
|
||||
]
|
||||
|
||||
# The pseudo-submodules 're' and 'io' are part of the public
|
||||
|
@ -460,6 +461,21 @@ def Literal(self, parameters):
|
|||
return _GenericAlias(self, parameters)
|
||||
|
||||
|
||||
@_SpecialForm
|
||||
def TypeAlias(self, parameters):
|
||||
"""Special marker indicating that an assignment should
|
||||
be recognized as a proper type alias definition by type
|
||||
checkers.
|
||||
|
||||
For example::
|
||||
|
||||
Predicate: TypeAlias = Callable[..., bool]
|
||||
|
||||
It's invalid when used anywhere except as in the example above.
|
||||
"""
|
||||
raise TypeError(f"{self} is not subscriptable")
|
||||
|
||||
|
||||
class ForwardRef(_Final, _root=True):
|
||||
"""Internal wrapper to hold a forward reference."""
|
||||
|
||||
|
|
|
@ -611,6 +611,7 @@ Christoph Gohlke
|
|||
Tim Golden
|
||||
Yonatan Goldschmidt
|
||||
Mark Gollahon
|
||||
Mikhail Golubev
|
||||
Guilherme Gonçalves
|
||||
Tiago Gonçalves
|
||||
Chris Gonnerman
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Implement :pep:`613`, introducing :data:`typing.TypeAlias` annotation.
|
Loading…
Reference in New Issue