datasette/template_contexts.py is now a thin index with no
documentation strings of its own - the docs live next to the code:
- Each page's Context class (DatabaseContext, QueryContext,
TableContext, RowContext) carries a docstring, its template name and
help metadata on view-added fields, in the view module itself
- extra_field() fields document themselves from the Extra classes
- The keys render_template() adds to every page are documented in
TEMPLATE_BASE_CONTEXT in app.py, next to the code that adds them,
with the contract tests keeping the two in sync
docs/template_context.rst is regenerated from the dataclasses, so the
table and row pages now include field types like the others.
Refs #2127
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
RowView declares context_class = RowContext; BaseView.render()
constructs the dataclass from the assembled context, dropping any keys
not declared on the class, after select_templates and
alternate_url_json have been added. Extras-named fields use
extra_field() so their documentation comes from the Extra classes;
view-added fields carry help metadata next to the view code.
Refs #2127
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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>
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>
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>
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>
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>
- 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>