Commit graph

6 commits

Author SHA1 Message Date
Simon Willison
8b89a3aca8 TableContext - table page now renders a documented Context dataclass
The table HTML view constructs a TableContext instead of an ad-hoc
dict, matching how the database and query pages already work. Fields
resolved by registered extras are declared with extra_field() so their
documentation lives on the Extra classes in table_extras.py; fields
added by the view code carry help metadata next to the view.

render_template() now converts Context dataclasses shallowly instead
of via dataclasses.asdict(), which deep-copied every value and would
fail on values like sqlite3.Row.

Keys not declared on TableContext - extras requested with ?_extra= on
the HTML page, or extra filter context from filters_from_request
plugins - are now dropped from the HTML template context rather than
passed through undocumented.

Refs #2127

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 07:47:15 -07:00
Simon Willison
63995ce823 extra_field() - Context fields documented by their Extra class
A Context dataclass field declared with extra_field() takes its
documentation from the description on the registered Extra of the same
name, validated against the class's extras_scope. This keeps doc
strings next to the resolve() code instead of duplicating them on the
dataclass, ahead of introducing TableContext and RowContext.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 07:47:15 -07:00
Simon Willison
3ea7ed8606 Isolate test plugins from template context contract tests
Datasette instances created with plugins_dir register their plugins on
the global plugin manager for the rest of the process, so the contract
tests could see extra_template_vars keys leaked from earlier test
modules (e.g. the session-scoped ds_client fixture). A fixture now
unregisters non-default plugins implementing extra_template_vars for
the duration of each contract test and restores them afterwards.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 07:47:15 -07:00
Simon Willison
a55ae2adfc Generated template context documentation, closes #1510
docs/template_context.rst is generated by cog from the manifest in
datasette/template_contexts.py, following the json_api_doc.py pattern.
It documents the base context available on every page plus the
database, query, table and row pages, including the stability policy
for custom template authors.

Refs #2127

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 07:47:15 -07:00
Simon Willison
6a1b237b39 Documented template context manifest with contract tests
datasette/template_contexts.py is the source of truth for the template
context contract: the variables custom templates can rely on for the
database, query, table and row pages, plus the base context that
render_template() adds to every page.

Documentation for each key comes from the Context dataclass field help
(database, query), the Extra class description (table and row extras)
or inline docs in the manifest (keys added by view code).

Contract tests render each page with template_debug ?_context=1 and
assert the real context keys exactly match the documented set, in both
directions - an undocumented addition or a removed documented key both
fail.

Refs #1510, #2127

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 07:47:15 -07:00
Simon Willison
435ff7fa88 Context.documented_fields() and extras doc-metadata enforcement
- Context dataclasses now expose documented_fields(), returning
  ContextField(name, type_name, help) for each field
- ExtraRegistry.internal_classes_for_scope() returns the Extra classes
  that are available to HTML templates but excluded from JSON
- Tests enforce that every registered Extra has a description and every
  DatabaseContext/QueryContext field has help metadata

Refs #1510, #2127

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 07:47:15 -07:00