Last active
August 29, 2023 14:39
-
-
Save pawamoy/a12cb4a5f66d913519070b52b2a9d54b to your computer and use it in GitHub Desktop.
Documentation Metadata
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This gist shows how we could get rid of docstrings micro-syntax | |
# like Google-style and Numpydoc-style pseudo-standards, | |
# using an enhanced version of PEP 727. | |
# The goal is to replace the following sections: | |
# Attributes | |
# Functions/Methods | |
# Classes | |
# Modules | |
# Deprecated | |
# Examples | |
# Parameters | |
# Other Parameters | |
# Raises | |
# Warns | |
# Yields | |
# Receives | |
# Returns | |
from typing import ( | |
Annotated, | |
Generator, | |
Iterator, | |
NotRequired, | |
TypedDict, | |
Unpack, | |
doc, | |
deprecated, | |
name, # does not exist yet | |
raises, # does not exist yet | |
warns, # does not exist yet | |
) | |
# Documenting module/class attributes, replacing Attributes sections: | |
FOO: Annotated[str, doc("Description.")] | |
# The benefit is that the documentation is also available at runtime, | |
# while a docstring below the attribute is not, and requires static analysis. | |
### ALREADY POSSIBLE. | |
# Documenting functions, methods, classes and modules is done as previously: | |
# with functions/methods/classes/modules docstrings (summary and body, using whatever markup). | |
# Documentation generators can then auto-summarize existing objects. | |
### ALREADY POSSIBLE. | |
# Documenting deprecations, replacing Deprecated sections: | |
BAR: Annotated[int, deprecated("Deprecated since v2.")] | |
# For functions, maybe add the information to the return value annotation: | |
def bar() -> Annotated[None, deprecated("Deprecated since v2.")]: | |
... | |
# For parameters: | |
def bar(param: Annotated[int, deprecated("Deprecated since v2.")] = None): | |
... | |
### NOT YET POSSIBLE: PEP 727 + 702 | |
# Documenting examples, replacing Examples sections: | |
# nothing specific here, we can have some nice things | |
# like (Markdown) extensions that parse pycon code blocks | |
# directly, without requiring indentation or fences. | |
# Or maybe no extensions at all, and just indent pycon code: | |
# it's correctly parsed, and readable as is. | |
### ALREADY POSSIBLE. | |
# Documenting parameters, replacing Parameters sections: | |
def foo( | |
bar: Annotated[str, doc("Description.")] = "default", | |
): | |
... | |
### ALREADY POSSIBLE. | |
# Documenting other parameters (keyword arguments), replacing Other Parameters sections: | |
class FooFooKwargs(TypedDict, total=False): | |
bar: Annotated[NotRequired[str], doc("Description.")] | |
baz: Annotated[NotRequired[str], doc("Description.")] | |
def foofoo( | |
**kwargs: Unpack[FooFooKwargs], | |
): | |
... | |
# THIS IS RATHER CONVOLUTED. Hoping for something easier in the future... | |
### ALREADY POSSIBLE. | |
# Documenting exceptions, replacing Raises sections, | |
# maybe add the information to the return value annotation: | |
def bar() -> Annotated[ | |
None, | |
raises( | |
ValueError("When something goes wrong."), | |
TypeError("When something goes even wronger."), | |
) | |
]: | |
... | |
### NOT YET POSSIBLE | |
# Documenting warnings, replacing Warns sections, | |
# maybe add the information to the return value annotation: | |
def bar() -> Annotated[ | |
None, | |
warns( | |
FutureWarning("Hello users."), | |
DeprecationWarning("Hello developers."), | |
) | |
]: | |
... | |
### NOT YET POSSIBLE | |
# Documenting yielded and received values, replacing Yields and Receives sections: | |
def bar() -> Generator[ | |
Annotated[int, doc("Yielded integers.")], | |
Annotated[int, doc("Received integers.")], | |
Annotated[int, doc("Final returned value.")], | |
]: | |
... | |
# Same thing with Iterator instead of Generator: | |
def bar() -> Iterator[Annotated[int, doc("Yielded integers.")]]: | |
... | |
### ALREADY POSSIBLE. | |
# Advanced use-case: documenting multiple yielded/received/returned values: | |
def bar() -> Generator[ | |
tuple[ | |
Annotated[int, name("python"), doc("First element of the yielded value.")], | |
Annotated[float, name("cobra"), doc("Second element of the yielded value.")], | |
], | |
tuple[ | |
Annotated[int, name("beep"), doc("First element of the received value.")], | |
Annotated[float, name("boop"), doc("Second element of the received value.")], | |
], | |
tuple[ | |
Annotated[int, name("super"), doc("First element of the returned value.")], | |
Annotated[float, name("hyper"), doc("Second element of the returned value.")], | |
], | |
]: | |
... | |
# That works with Iterator too, and regular functions. | |
### ALREADY POSSIBLE (without specifying names). | |
# Other considerations: attributes `deprecated` and `name` | |
# of typing could instead be keyword arguments of the `doc` function: | |
def bar( | |
param: Annotated[str, doc("Old parameter.", deprecated="Deprecated since v2.")], | |
) -> Iterator[Annotated[int, doc("Yielded integers.", name="cute_int")]]: | |
... | |
### NOT YET POSSIBLE: PEP 727 + 702 | |
# Admonitions like Note, Warning, etc., can then simply be | |
# written in docstrings using the chosen markup features. | |
### ALREADY POSSIBLE. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment