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
|
* 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.
|
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
|
* Access to the documentation string for each symbol at runtime, including existing
|
||||||
(older) Python versions.
|
(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.
|
* No microsyntax to learn for newcomers, it's just Python syntax.
|
||||||
|
|
||||||
* Parameter documentation inheritance for functions captured
|
* 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,
|
: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.
|
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
|
When :py:class:`~typing.Annotated` is used to declare a type alias, ``typing.Doc``
|
||||||
alias is used in an annotation, ``typing.Doc`` would document the symbol being
|
would then document the type alias symbol.
|
||||||
annotated instead of exclusively the type alias.
|
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
|
@ -181,51 +181,29 @@ For example:
|
||||||
|
|
||||||
from typing import Annotated, Doc, TypeAlias
|
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): ...
|
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
|
||||||
def delete_user(name: UserName): ...
|
documentation tools could include the type alias with its documentation in their
|
||||||
|
generated output.
|
||||||
|
|
||||||
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"``.
|
|
||||||
|
|
||||||
For tools extracting the information at runtime, they would normally use
|
For tools extracting the information at runtime, they would normally use
|
||||||
:py:func:`~typing.get_type_hints` with the parameter ``include_extras=True``,
|
: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
|
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
|
would mean they should use the last ``typing.Doc`` available, if more than one is
|
||||||
one used.
|
used, as that is the last one used.
|
||||||
|
|
||||||
At runtime, ``typing.Doc`` instances have an attribute ``documentation`` with the
|
At runtime, ``typing.Doc`` instances have an attribute ``documentation`` with the
|
||||||
string passed to it.
|
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`,
|
When a function's signature is captured by a :py:class:`~typing.ParamSpec`,
|
||||||
any documentation strings associated with the parameters should be retained.
|
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
|
e.g. with FastAPI metadata, Pydantic fields, etc.) or adding additional metadata
|
||||||
apart from the documentation string (e.g. deprecation).
|
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
|
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
|
to be used by those that are willing to take the extra verbosity in exchange
|
||||||
for the benefits.
|
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
|
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
|
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
|
having to look at that code with additional signature verbosity instead of docstring
|
||||||
|
|
Loading…
Reference in New Issue