Files
pybricks-api/doc/common/extensions/awaitable.py
T
Laurens Valk 9bd82f7246 doc: Replace fork with extensions.
Use clean upstream Sphinx and use extensions for the awaitable types and work around a Sphinx docstring parsing bug.
2026-08-24 11:01:50 +02:00

62 lines
1.9 KiB
Python

"""Show ``await`` in front of multitasking functions and methods.
The Pybricks API returns awaitable objects when a run loop is active but
blocks otherwise. Such functions are annotated with ``MaybeAwaitable*``
return types. This extension:
* makes autodoc treat functions/methods returning ``MaybeAwaitable*`` as
async (there is no public hook for this, so ``is_async`` is patched);
* renders the signature prefix as ``await`` (linked to the multitasking
section in tools) instead of ``async``, which better matches how users
call these functions.
"""
from typing import Sequence
from docutils import nodes
from sphinx.addnodes import desc_sig_keyword
from sphinx.application import Sphinx
from sphinx.domains.python import PyFunction, PyMethod, type_to_xref
from sphinx.ext.autodoc._property_types import _FunctionDefProperties
def _is_async(self: _FunctionDefProperties) -> bool:
if "async" in self.properties:
return True
try:
return_type = self._obj.__annotations__["return"]
except Exception:
return False
return "MaybeAwaitable" in str(return_type)
class _AwaitPrefixMixin:
"""Replaces the ``async`` keyword prefix with a linked ``await``."""
def get_signature_prefix(self, sig: str) -> Sequence[nodes.Node]:
prefix = []
for node in super().get_signature_prefix(sig):
if isinstance(node, desc_sig_keyword) and node.astext() == "async":
node = type_to_xref("await", self.env, suppress_prefix=True)
prefix.append(node)
return prefix
class PybricksPyFunction(_AwaitPrefixMixin, PyFunction):
pass
class PybricksPyMethod(_AwaitPrefixMixin, PyMethod):
pass
def setup(app: Sphinx):
_FunctionDefProperties.is_async = property(_is_async)
app.add_directive_to_domain("py", "function", PybricksPyFunction, override=True)
app.add_directive_to_domain("py", "method", PybricksPyMethod, override=True)
return {"parallel_read_safe": True}