Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Datasette 1.0 documented template context (maybe via API docs) #1510

Open
simonw opened this issue Nov 15, 2021 · 3 comments
Open

Datasette 1.0 documented template context (maybe via API docs) #1510

simonw opened this issue Nov 15, 2021 · 3 comments

Comments

@simonw
Copy link
Owner

simonw commented Nov 15, 2021

Documented context plus protective unit tests. Goal is that custom templates built for 1.x will not break without a 2.x release.

@simonw simonw added this to the Datasette 1.0 milestone Nov 15, 2021
@simonw simonw changed the title Datasette 1.0 documented template context Datasette 1.0 documented template context (maybe via API docs) Mar 15, 2022
@simonw
Copy link
Owner Author

simonw commented Mar 15, 2022

If I set a rule that everything available in the template context MUST also be available via the JSON API (maybe through an extras mechanism) I can combine this with API documentation and solve both at once.

@simonw
Copy link
Owner Author

simonw commented Mar 20, 2022

I really like the idea of making this effectively the same thing as the fully documented, stable JSON API that comes as part of 1.0. If you want to know what will be available to your templates, consult the API documentation.

@simonw
Copy link
Owner Author

simonw commented Jun 28, 2023

I prototyped an approach to this using dataclasses and a cog mechanism for turning those into rendered tables in Sphinx. Here's what that prototype looks like:

image

See 6822378 for how it works.

Here's the class that documented:

@dataclass
class Table:
"A table is a useful thing"
name: str = doc("The name of the table")
columns: List[str] = doc("List of column names in the table")
primary_keys: List[str] = doc("List of column names that are primary keys")
count: int = doc("Number of rows in the table")
hidden: bool = doc(
"Should this table default to being hidden in the main database UI?"
)
fts_table: Optional[str] = doc(
"If this table has FTS support, the accompanying FTS table name"
)
foreign_keys: ForeignKey = doc("List of foreign keys for this table")
private: bool = doc("Private tables are not visible to signed-out anonymous users")

And the code that generates the rST:

def rst_docs_for_dataclass(klass: Any) -> str:
"""Generate reStructuredText (reST) docs for a dataclass."""
docs = []
# Class name and docstring
docs.append(klass.__name__)
docs.append("-" * len(klass.__name__))
docs.append("")
if klass.__doc__:
docs.append(klass.__doc__)
docs.append("")
# Dataclass fields
docs.append("Fields")
docs.append("~~~~~~")
docs.append("")
for name, field_info in klass.__dataclass_fields__.items():
if is_builtin_type(field_info.type):
# <class 'int'>
type_name = field_info.type.__name__
else:
# List[str]
type_name = str(field_info.type).replace("typing.", "")
docs.append(f':{name} - ``{type_name}``: {field_info.metadata.get("doc", "")}')
return "\n".join(docs)

And the bit that cog executes:

.. [[[cog
from datasette.context import rst_docs_for_dataclass, Table
cog.out(rst_docs_for_dataclass(Table))
.. ]]]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant