@documented decorator plus unit test plus sphinx.ext.autodoc

New mechanism for marking datasette.utils functions that should be covered by the
documentation, then testing that they have indeed been documented.

Also enabled sphinx.ext.autodoc which can now be used to embed the documented
versions of those functions.

Refs #1176
pull/1631/head
Simon Willison 2022-02-06 22:30:00 -08:00
rodzic 9b83ff2ee4
commit d9b508ffaa
4 zmienionych plików z 43 dodań i 4 usunięć

Wyświetl plik

@ -12,6 +12,7 @@ import os
import re
import shlex
import tempfile
import typing
import time
import types
import shutil
@ -59,8 +60,17 @@ Column = namedtuple(
"Column", ("cid", "name", "type", "notnull", "default_value", "is_pk", "hidden")
)
functions_marked_as_documented = []
async def await_me_maybe(value):
def documented(fn):
functions_marked_as_documented.append(fn)
return fn
@documented
async def await_me_maybe(value: typing.Any) -> typing.Any:
"If value is callable, call it. If awaitable, await it. Otherwise return it."
if callable(value):
value = value()
if asyncio.iscoroutine(value):
@ -915,7 +925,9 @@ class BadMetadataError(Exception):
pass
def parse_metadata(content):
@documented
def parse_metadata(content: str) -> dict:
"Detects if content is JSON or YAML and parses it appropriately."
# content can be JSON or YAML
try:
return json.loads(content)

Wyświetl plik

@ -31,7 +31,7 @@
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = ["sphinx.ext.extlinks"]
extensions = ["sphinx.ext.extlinks", "sphinx.ext.autodoc"]
extlinks = {
"issue": ("https://github.com/simonw/datasette/issues/%s", "#"),

Wyświetl plik

@ -865,6 +865,17 @@ This function accepts a string containing either JSON or YAML, expected to be of
If the metadata cannot be parsed as either JSON or YAML the function will raise a ``utils.BadMetadataError`` exception.
.. autofunction:: datasette.utils.parse_metadata
.. _internals_utils_await_me_maybe:
await_me_maybe(value)
---------------------
Utility function for calling ``await`` on a return value if it is awaitable, otherwise returning the value. This is used by Datasette to support plugin hooks that can optionally return awaitable functions. Read more about this function in `The “await me maybe” pattern for Python asyncio <https://simonwillison.net/2020/Sep/2/await-me-maybe/>`__.
.. autofunction:: datasette.utils.await_me_maybe
.. _internals_tracer:
datasette.tracer

Wyświetl plik

@ -2,7 +2,7 @@
Tests to ensure certain things are documented.
"""
from click.testing import CliRunner
from datasette import app
from datasette import app, utils
from datasette.cli import cli
from datasette.filters import Filters
from pathlib import Path
@ -86,3 +86,19 @@ def documented_table_filters():
@pytest.mark.parametrize("filter", [f.key for f in Filters._filters])
def test_table_filters_are_documented(documented_table_filters, filter):
assert filter in documented_table_filters
@pytest.fixture(scope="session")
def documented_fns():
internals_rst = (docs_path / "internals.rst").read_text()
# Any line that starts .. _internals_utils_X
lines = internals_rst.split("\n")
prefix = ".. _internals_utils_"
return {
line.split(prefix)[1].split(":")[0] for line in lines if line.startswith(prefix)
}
@pytest.mark.parametrize("fn", utils.functions_marked_as_documented)
def test_functions_marked_with_documented_are_documented(documented_fns, fn):
assert fn.__name__ in documented_fns