Skip to content

Commit

Permalink
Prefer built-in generics (#100)
Browse files Browse the repository at this point in the history
  • Loading branch information
srittau authored Feb 26, 2021
1 parent ac8f840 commit 4b0d7c0
Showing 1 changed file with 29 additions and 12 deletions.
41 changes: 29 additions & 12 deletions pep-9999.rst
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ not use the positional-only syntax from PEP 570 [#pep570]_, introduced in
Python 3.8, although type checker authors are encouraged to support it.

Stubs are treated as if ``from __future__ import annotations`` is enabled.
In particular, forward references can be used.
In particular, built-in generics and forward references can be used.

Starting with Python 3.8, the ast_ module from the standard library supports
all syntax features required by this PEP. Older Python versions can use the
Expand Down Expand Up @@ -321,7 +321,7 @@ Aliases and NewType

Type checkers should accept module-level and class-level aliases, e.g.::

_IntList = List[int]
_IntList = list[int]

class C:
def f(self) -> int: ...
Expand Down Expand Up @@ -476,7 +476,6 @@ Unsupported Features
--------------------

Currently, positional-only argument syntax (PEP 570 [#pep570]_),
generics in standard collections (PEP 585 [#pep585]_),
unions using the pipe operator (``|``) (PEP 604 [#pep604]_),
``ParamSpec`` (PEP 612 [#pep612]_), and ``TypeAlias`` (PEP 613 [#pep613]_)
are not supported by all type
Expand Down Expand Up @@ -832,14 +831,14 @@ Yes::
class Foo:
def bar(self) -> None: ...
@classmethod
def create(cls: Type[_T]) -> _T: ...
def create(cls: type[_T]) -> _T: ...

No::

class Foo:
def bar(self: Foo) -> None: ...
@classmethod
def baz(cls: Type[Foo]) -> int: ...
def baz(cls: type[Foo]) -> int: ...

The bodies of functions and methods should consist of only the ellipsis
literal ``...`` on the same line as the closing parenthesis and colon.
Expand Down Expand Up @@ -869,12 +868,12 @@ with an underscore.
Yes::

_T = TypeVar("_T")
_DictList = Dict[str, List[Optional[int]]]
_DictList = dict[str, list[Optional[int]]]

No::

T = TypeVar("T")
DictList = Dict[str, List[Optional[int]]]
DictList = dict[str, list[Optional[int]]]

Language Features
-----------------
Expand Down Expand Up @@ -932,31 +931,49 @@ For arguments, prefer protocols and abstract types (``Mapping``,
``Sequence``, ``Iterable``, etc.). If an argument accepts literally any value,
use ``object`` instead of ``Any``.

For return values, prefer concrete types (``List``, ``Dict``, etc.) for
For return values, prefer concrete types (``list``, ``dict``, etc.) for
concrete implementations. The return values of protocols
and abstract base classes must be judged on a case-by-case basis.

Yes::

def map_it(input: Iterable[str]) -> List[int]: ...
def create_map() -> Dict[str, int]: ...
def map_it(input: Iterable[str]) -> list[int]: ...
def create_map() -> dict[str, int]: ...
def to_string(o: object) -> str: ... # accepts any object

No::

def map_it(input: List[str]) -> List[int]: ...
def map_it(input: list[str]) -> list[int]: ...
def create_map() -> MutableMapping[str, int]: ...
def to_string(o: Any) -> str: ...

Maybe::

class MyProto(Protocol):
def foo(self) -> List[int]: ...
def foo(self) -> list[int]: ...
def bar(self) -> Mapping[str]: ...

Avoid ``Union`` return types, since they require ``isinstance()`` checks.
Use ``Any`` if necessary.

Use built-in generics instead of the aliases from ``typing``.

Yes::

def foo(x: type[MyClass]) -> list[str]: ...

No::

from typing import List, Type

def foo(x: Type[MyClass]) -> List[str]: ...

But::

from typing import Iterable

def foo(x: Iterable[str]) -> None: ...

NamedTuple and TypedDict
------------------------

Expand Down

0 comments on commit 4b0d7c0

Please sign in to comment.