PEP 727: Documentation Metadata in Typing

:cry:

Quick, personal summary, with new thoughts:

  • Counter-argument: ā€œitā€™s not typingā€. Annotated was designed to annotate types, true, but also says:

    As such, Annotated can be useful for code that wants to use annotations for purposes outside Pythonā€™s static typing system.

    Unfortunately the typing module is the only meaningful location in the standard library for Doc (next to Annotated). There isnā€™t a generic documentation-related standard module :confused: (maybe we could create one :smiling_imp:?). Even if many do not use or consider typing primarily as documentation, it is still also documentation.

  • Counter-argument: ā€œitā€™s too verboseā€. Not really. Spacing taken aside, you can alias Annotated as A, then A[int, Doc("string")] is ~10 characters more than int, for each documented parameter. But from that we could substract the average length of parameter names, since we donā€™t have to repeat them in function/class docstrings.

  • Counter-argument: ā€œit makes big signaturesā€. Big signatures can be collapsed (partly or completely) with adequate tooling. Even without Doc, signatures with annotated types can grow quite big, so it would make sense to me that IDEs and text editors would allow collapsing each parameter in signatures, maybe just showing the (truncated) unannotated type and (truncated) default value.

  • Counter-argument: ā€œitā€™s not pretty or as pretty as function docstringsā€. Personal preference :person_shrugging:

  • Counter-argument: ā€œaccepting it in the stdlib puts pressure on the ecosystem to adopt itā€. Recent thought I had: True, but the opposite is true too. By not providing a standard way to structure docs data, pressure is put on the ecosystem to rely on non-standard, divergent, unspecified and sub-optimal docstring styles.


Anyway, I hope Iā€™m not starting a debate over again :sweat_smile: Iā€™m actually happy if Doc lives in a third-party library :slightly_smiling_face: Just wanted to share my perspective again as someone who works a lot with docstring styles (and grows to enjoy them less and less). I hope we can continue working and discussing towards a standard solution even after this PEP is withdrawn or rejected :smiling_face:

It already does, as typing_extensions.Doc, and you are free to use it. Weā€™ll probably keep it in typing_extensions indefinitely even if the PEP gets withdrawn or rejected, for backwards compatibility reasons.

You are free to use it in your own code using the typing-extensions version. If usage of typing_extensions.Doc becomes widespread, that will be a good argument for accepting the PEP and putting it in the standard library.

7 Likes

Ah thatā€™s good to know, thanks!

If @ is deemed too cryptic by many, then how about -?

- can be intuitively read as em dash, used in places where a set of parentheses or a colon might otherwise be used:

def some_function(
    some_parameter: SomeType - "Some documentation goes here",
) -> SomeReturn - "Some details about this return type":
    """ Documenting the function itself here """

And as a bonus - is both a binary operator and a unary operator so thereā€™s the potential to allow a parameter to be annotated without a type:

def some_function(
    some_parameter: SomeType - "Some documentation goes here",
    **kwargs: - "Additional keyword arguments"
) -> SomeReturn - "Some details about this return type":
    """ Documenting the function itself here """

Some might argue that em dash is really a long dash, usually represented in ASCII as two dashes, which we can also consider as an alternative for better aesthetics:

def some_function(
    some_parameter: SomeType -- "Some documentation goes here",
    **kwargs: -- "Additional keyword arguments"
) -> SomeReturn -- "Some details about this return type":
    """ Documenting the function itself here """

This would make the syntax more in line with SQL comments.

1 Like

Doesnā€™t that cause problems?

>>> string = "foo"
>>> -string
Doc("foo")

Surely it would be better to write this?

def some_function(
    **kwargs: Any - "Additional keyword arguments"
) -> None:
    ...

I donā€™t think itā€™s a problem because it currently produces a TypeError. Thereā€™s otherwise no intuitive use for it as a unary operator for a string anyway.

Yes, but my point is just so we can keep type annotation optional.

Even if this was worth pursuing, and I donā€™t think it is, @ was used in that hypothetical because there is no conceivable future to need matmul for types. Using - is problematic due to the potential for difference types in the future (ie. Iterable[str] - str, being any iterable of strings that isnā€™t just a string), paired with strings being used for forward references in typing.

Keep in mind that there were plenty of other things brought up in this discussion against this idea that donā€™t matter what the syntax actually would be.

1 Like

Good point, so type - 'string' is problematic because 'string' can be used as a forward reference of a type, but I think type -- 'string' can still work because - 'string' can be made a Doc('string'), which type.__sub__ can special-case and make Annotated[type, Doc('string')].

Yes, the syntax just occurred to me and I thought Iā€™d share it here just in case the other arguments against this idea get resolved later.

EDIT: Actually, I think I may have just resolved what I believe to be the biggest argument against this idea, namely that the original proposal makes the annotation too verbose, to the point that it adversely affects readability.

So instead of:

def some_function(
    some_parameter: Annotated[SomeType, Doc("Some documentation goes here")],
    **kwargs: Annotated[Any, Doc("Additional keyword arguments")]
) -> Annotated[SomeReturn, Doc("Some details about this return type")]:
    """ Documenting the function itself here """

It can now be:

def some_function(
    some_parameter: SomeType -- "Some documentation goes here",
    **kwargs: Any -- "Additional keyword arguments"
) -> SomeReturn -- "Some details about this return type":
    """ Documenting the function itself here """

which looks a lot less verbose and more readable to me.

Perhaps itā€™s enough to nudge this proposal back on track for a reconsideration?