PEP 727: Specify `Doc` in type aliases documents the type alias symbol, update rejected ideas (#3581)
📝 Update PEP to specify `Doc` in type aliases documents the type alias symbol
This commit is contained in:
parent
0244d89009
commit
d9e47a206b
|
@ -136,11 +136,12 @@ conventions:
|
|||
* Elimination of the possibility of having inconsistencies between the name of a
|
||||
parameter in the signature and the name in the docstring when it is renamed.
|
||||
|
||||
* Reuse of documentation for symbols used in multiple places via type aliases.
|
||||
|
||||
* Access to the documentation string for each symbol at runtime, including existing
|
||||
(older) Python versions.
|
||||
|
||||
* A more formalized way to document other symbols, like type aliases, that could
|
||||
use :py:class:`~typing.Annotated`.
|
||||
|
||||
* No microsyntax to learn for newcomers, it's just Python syntax.
|
||||
|
||||
* Parameter documentation inheritance for functions captured
|
||||
|
@ -171,9 +172,8 @@ For example:
|
|||
:py:class:`~typing.Annotated` is normally used as a type annotation, in those cases,
|
||||
any ``typing.Doc`` inside of it would document the symbol being annotated.
|
||||
|
||||
When :py:class:`~typing.Annotated` is used to declare a type alias and that type
|
||||
alias is used in an annotation, ``typing.Doc`` would document the symbol being
|
||||
annotated instead of exclusively the type alias.
|
||||
When :py:class:`~typing.Annotated` is used to declare a type alias, ``typing.Doc``
|
||||
would then document the type alias symbol.
|
||||
|
||||
For example:
|
||||
|
||||
|
@ -181,51 +181,29 @@ For example:
|
|||
|
||||
from typing import Annotated, Doc, TypeAlias
|
||||
|
||||
from external_library import UserResolver
|
||||
|
||||
UserName: TypeAlias = Annotated[str, Doc("The user's name")]
|
||||
CurrentUser: TypeAlias = Annotated[str, Doc("The current system user"), UserResolver()]
|
||||
|
||||
def create_user(name: Annotated[str, Doc("The user's name")]): ...
|
||||
|
||||
def delete_user(name: Annotated[str, Doc("The user to delete")]): ...
|
||||
|
||||
|
||||
def create_user(name: UserName): ...
|
||||
|
||||
def delete_user(name: UserName): ...
|
||||
|
||||
|
||||
When a type alias is put inside of :py:class:`~typing.Annotated` and it has a
|
||||
``typing.Doc``, the last one used (the top-most) takes precedence, this allows
|
||||
overriding the documentation.
|
||||
|
||||
For example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
from typing import Annotated, Doc, TypeAlias
|
||||
|
||||
|
||||
UserName: TypeAlias = Annotated[str, Doc("The user's name")]
|
||||
|
||||
|
||||
def create_user(name: UserName): ...
|
||||
|
||||
def delete_user(name: Annotated[UserName, Doc("The user to delete")]): ...
|
||||
|
||||
|
||||
In this case, for the ``name`` parameter in ``delete_user()``, the documentation string
|
||||
would be ``"The user to delete"``.
|
||||
In this case, if a user imported ``CurrentUser``, tools like editors could provide
|
||||
a tooltip with the documentation string when a user hovers over that symbol, or
|
||||
documentation tools could include the type alias with its documentation in their
|
||||
generated output.
|
||||
|
||||
For tools extracting the information at runtime, they would normally use
|
||||
:py:func:`~typing.get_type_hints` with the parameter ``include_extras=True``,
|
||||
and as :py:class:`~typing.Annotated` is normalized (even with type aliases), this
|
||||
would mean they should use the last ``typing.Doc`` available, as that is the last
|
||||
one used.
|
||||
would mean they should use the last ``typing.Doc`` available, if more than one is
|
||||
used, as that is the last one used.
|
||||
|
||||
At runtime, ``typing.Doc`` instances have an attribute ``documentation`` with the
|
||||
string passed to it.
|
||||
|
||||
When a type alias is used on its own, without annotating any additional symbol,
|
||||
``typing.Doc`` documents the type alias itself. This would be useful if the
|
||||
type alias is included on its own in documentation systems or if it's used directly
|
||||
in some way, to show tooltips in editors.
|
||||
|
||||
When a function's signature is captured by a :py:class:`~typing.ParamSpec`,
|
||||
any documentation strings associated with the parameters should be retained.
|
||||
|
||||
|
@ -625,6 +603,50 @@ difficult to combine it with :py:class:`~typing.Annotated` for other purposes (
|
|||
e.g. with FastAPI metadata, Pydantic fields, etc.) or adding additional metadata
|
||||
apart from the documentation string (e.g. deprecation).
|
||||
|
||||
|
||||
Transferring Documentation from Type aliases
|
||||
--------------------------------------------
|
||||
|
||||
A previous version of this proposal specified that when type aliases declared with
|
||||
:py:class:`~typing.Annotated` were used, and these type aliases were used in
|
||||
annotations, the documentation string would be transferred to the annotated symbol.
|
||||
|
||||
For example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
from typing import Annotated, Doc, TypeAlias
|
||||
|
||||
|
||||
UserName: TypeAlias = Annotated[str, Doc("The user's name")]
|
||||
|
||||
|
||||
def create_user(name: UserName): ...
|
||||
|
||||
def delete_user(name: UserName): ...
|
||||
|
||||
|
||||
This was rejected after receiving feedback from the maintainer of one of the main
|
||||
components used to provide editor support.
|
||||
|
||||
|
||||
Shorthand with Slices
|
||||
---------------------
|
||||
|
||||
In the discussion, it was suggested to use a shorthand with slices:
|
||||
|
||||
.. code:: python
|
||||
|
||||
is_approved: Annotated[str: "The status of a PEP."]
|
||||
|
||||
|
||||
Although this is a very clever idea and would remove the need for a new ``Doc`` class,
|
||||
runtime executing of current versions of Python don't allow it.
|
||||
|
||||
At runtime, :py:class:`~typing.Annotated` requires at least two arguments, and it
|
||||
requires the first argument to be type, it crashes if it is a slice.
|
||||
|
||||
|
||||
Open Issues
|
||||
===========
|
||||
|
||||
|
@ -665,10 +687,6 @@ features. But again, as with type annotations, this would be optional and only
|
|||
to be used by those that are willing to take the extra verbosity in exchange
|
||||
for the benefits.
|
||||
|
||||
Additionally, if type aliases were used, documentation could be put outside of the
|
||||
signature and the docstring, reducing the total verbosity of the signature and the
|
||||
function body.
|
||||
|
||||
Of course, more advanced users might want to look at the source code of the libraries
|
||||
and if the authors of those libraries adopted this, those advanced users would end up
|
||||
having to look at that code with additional signature verbosity instead of docstring
|
||||
|
|
Loading…
Reference in New Issue