Skip to content

Commit 3ed2adb

Browse files
authored
Update supported features (#855)
* Union shorthand is now mostly supported * Explicitly mention type guards as being supported * ParamSpec is partly supported * Describe cases where built-in generics are not supported * Reference typeshed issues for unsupported features Restructure unsupported features section
1 parent 7d2fae8 commit 3ed2adb

File tree

1 file changed

+97
-15
lines changed

1 file changed

+97
-15
lines changed

docs/stubs.rst

Lines changed: 97 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ not use the positional-only syntax from PEP 570 [#pep570]_, introduced in
5959
Python 3.8, although type checker authors are encouraged to support it.
6060

6161
Stubs are treated as if ``from __future__ import annotations`` is enabled.
62-
In particular, built-in generics and forward references can be used.
62+
In particular, built-in generics, pipe union syntax (``X | Y``), and forward
63+
references can be used.
6364

6465
Starting with Python 3.8, the :py:mod:`ast` module from the standard library supports
6566
all syntax features required by this PEP. Older Python versions can use the
@@ -170,6 +171,35 @@ specified in ``__all__`` are imported::
170171

171172
Type checkers support cyclic imports in stub files.
172173

174+
Built-in Generics
175+
-----------------
176+
177+
PEP 585 [#pep585]_ built-in generics are generally supported, with
178+
the following exceptions [#ts-4820]_:
179+
180+
* Built-in generics don't work in type aliases.
181+
* Built-in generics don't work in base classes.
182+
* ``type`` is not supported.
183+
* Variable length tuples (``tuple[X, ...]``) are not supported.
184+
185+
In these cases, the appropriate types from ``typing`` must be used.
186+
187+
Using imports from ``collections.abc`` instead of ``typing`` is
188+
generally possible and recommended.
189+
190+
Unions
191+
------
192+
193+
Declaring unions with ``Union`` and ``Optional`` is supported by all
194+
type checkers. With the exception of type aliases [#ts-4819]_, the shorthand syntax
195+
is also supported::
196+
197+
def foo(x: int | str) -> int | None: ... # recommended
198+
def foo(x: Union[int, str]) -> Optional[int]: ... # ok
199+
200+
TYPE_ALIAS = Union[int, str] # ok
201+
TYPE_ALIAS = int | str # does not work with all type checkers
202+
173203
Module Level Attributes
174204
-----------------------
175205

@@ -231,6 +261,8 @@ The class must match the class in which it is declared. Using other classes,
231261
including sub or super classes, will not work. In addition, the ``self``
232262
annotation cannot contain type variables.
233263

264+
.. _supported-functions:
265+
234266
Functions and Methods
235267
---------------------
236268

@@ -282,9 +314,21 @@ But::
282314
@classmethod
283315
def create_it(cls: _T) -> _T: ... # cls has type _T
284316

317+
PEP 612 [#pep612]_ parameter specification variables (``ParamSpec``)
318+
are supported in argument and return types, although
319+
they need to be marked with ``# type: ignore`` to work with all
320+
type checkers [#ts-4827]_::
321+
322+
_P = ParamSpec("_P")
323+
_T = TypeVar("_T")
324+
325+
def foo(cb: Callable[_P, _T]) -> Callable[_P, _T]: ... # type: ignore
326+
327+
PEP 647 [#pep647]_ type guards are supported.
328+
285329
Using a function or method body other than the ellipsis literal is currently
286330
unspecified. Stub authors may experiment with other bodies, but it is up to
287-
individual type checkers how to interpret them.
331+
individual type checkers how to interpret them::
288332

289333
def foo(): ... # compatible
290334
def bar(): pass # behavior undefined
@@ -465,11 +509,14 @@ No::
465509
Unsupported Features
466510
--------------------
467511

468-
Currently, positional-only argument syntax (PEP 570 [#pep570]_),
469-
unions using the pipe operator (``|``) (PEP 604 [#pep604]_),
470-
``ParamSpec`` (PEP 612 [#pep612]_), and ``TypeAlias`` (PEP 613 [#pep613]_)
471-
are not supported by all type
472-
checkers and should not be used in stubs.
512+
Currently, the following features are not supported by all type checkers
513+
and should not be used in stubs:
514+
515+
* Positional-only argument syntax (PEP 570 [#pep570]_). Instead, use
516+
the syntax described in the section :ref:`supported-functions`.
517+
[#ts-4972]_
518+
* ``TypeAlias`` (PEP 613 [#pep613]_). Instead, use a simple
519+
assigment to define a type alias. [#ts-4913]_
473520

474521
Type Stub Content
475522
=================
@@ -594,9 +641,9 @@ the following class::
594641

595642
An appropriate stub definition is::
596643

597-
from typing import Any, Optional
644+
from typing import Any
598645
class Foo:
599-
def __getattr__(self, name: str) -> Optional[Any]: ...
646+
def __getattr__(self, name: str) -> Any | None: ...
600647

601648
Note that only ``__getattr__``, not ``__getattribute__``, is guaranteed to be
602649
supported in stubs.
@@ -741,6 +788,29 @@ No::
741788
x: int
742789
class MyError(Exception): ... # leave an empty line between the classes
743790

791+
Shorthand Syntax
792+
----------------
793+
794+
Where possible, use shorthand syntax for unions instead of
795+
``Union`` or ``Optional``. ``None`` should be the last
796+
element of an union. See the Unions_ section for cases where
797+
using the shorthand syntax is not possible.
798+
799+
Yes::
800+
801+
def foo(x: str | int) -> None: ...
802+
def bar(x: str | None) -> int | None: ...
803+
804+
No::
805+
806+
def foo(x: Union[str, int]) -> None: ...
807+
def bar(x: Optional[str]) -> Optional[int]: ...
808+
def baz(x: None | str) -> None: ...
809+
810+
But the following is still necessary::
811+
812+
TYPE_ALIAS = Optional[Union[str, int]]
813+
744814
Module Level Attributes
745815
-----------------------
746816

@@ -801,19 +871,19 @@ does not apply to positional-only arguments, which are marked with a double
801871
underscore.
802872

803873
Use the ellipsis literal ``...`` in place of actual default argument
804-
values. Use an explicit ``Optional`` annotation instead of
874+
values. Use an explicit ``X | None`` annotation instead of
805875
a ``None`` default.
806876

807877
Yes::
808878

809879
def foo(x: int = ...) -> None: ...
810-
def bar(y: Optional[str] = ...) -> None: ...
880+
def bar(y: str | None = ...) -> None: ...
811881

812882
No::
813883

814884
def foo(x: int = 0) -> None: ...
815885
def bar(y: str = None) -> None: ...
816-
def baz(z: Optional[str] = None) -> None: ...
886+
def baz(z: str | None = None) -> None: ...
817887

818888
Do not annotate ``self`` and ``cls`` in method definitions, except when
819889
referencing a type variable.
@@ -861,12 +931,12 @@ with an underscore.
861931
Yes::
862932

863933
_T = TypeVar("_T")
864-
_DictList = dict[str, list[Optional[int]]]
934+
_DictList = Dict[str, List[Optional[int]]
865935

866936
No::
867937

868938
T = TypeVar("T")
869-
DictList = dict[str, list[Optional[int]]]
939+
DictList = Dict[str, List[Optional[int]]]
870940

871941
Language Features
872942
-----------------
@@ -949,7 +1019,9 @@ Maybe::
9491019
Avoid union return types, since they require ``isinstance()`` checks.
9501020
Use ``Any`` or ``X | Any`` if necessary.
9511021

952-
Use built-in generics instead of the aliases from ``typing``.
1022+
Use built-in generics instead of the aliases from ``typing``,
1023+
where possible. See the section `Built-in Generics`_ for cases,
1024+
where it's not possible to use them.
9531025

9541026
Yes::
9551027

@@ -1005,8 +1077,18 @@ PEPs
10051077
.. [#pep604] PEP 604 -- Allow writing union types as X | Y, Prados and Moss (https://www.python.org/dev/peps/pep-0604)
10061078
.. [#pep612] PEP 612 -- Parameter Specification Variables, Mendoza (https://www.python.org/dev/peps/pep-0612)
10071079
.. [#pep613] PEP 613 -- Explicit Type Aliases, Zhu (https://www.python.org/dev/peps/pep-0613)
1080+
.. [#pep647] PEP 647 -- User-Defined Type Guards, Traut (https://www.python.org/dev/peps/pep-0647)
10081081
.. [#pep3107] PEP 3107 -- Function Annotations, Winter and Lownds (https://www.python.org/dev/peps/pep-3107)
10091082
1083+
Bugs
1084+
----
1085+
1086+
.. [#ts-4819] typeshed issue #4819 -- PEP 604 tracker (https://github.com/python/typeshed/issues/4819)
1087+
.. [#ts-4820] typeshed issue #4820 -- PEP 585 tracker (https://github.com/python/typeshed/issues/4820)
1088+
.. [#ts-4827] typeshed issue #4827 -- PEP 612 tracker (https://github.com/python/typeshed/issues/4827)
1089+
.. [#ts-4913] typeshed issue #4913 -- PEP 613 tracker (https://github.com/python/typeshed/issues/4913)
1090+
.. [#ts-4972] typeshed issue #4972 -- PEP 570 tracker (https://github.com/python/typeshed/issues/4972)
1091+
10101092
Copyright
10111093
=========
10121094

0 commit comments

Comments
 (0)