mirror of
https://github.com/simonw/datasette.git
synced 2026-09-28 12:54:10 +02:00
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>
This commit is contained in:
parent
63995ce823
commit
8b89a3aca8
4 changed files with 172 additions and 3 deletions
|
|
@ -344,3 +344,28 @@ async def test_datasette_close_continues_past_db_error():
|
|||
ds.close()
|
||||
assert good._closed
|
||||
assert ds._internal_database._closed
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_datasette_render_template_dataclass_values_not_deep_copied():
|
||||
# display_rows can contain values like sqlite3.Row that cannot be
|
||||
# deep-copied, so render_template must convert Context dataclasses
|
||||
# shallowly - https://github.com/simonw/datasette/issues/2127
|
||||
class RefusesDeepCopy:
|
||||
def __deepcopy__(self, memo):
|
||||
raise RuntimeError("deepcopy not supported")
|
||||
|
||||
def __str__(self):
|
||||
return "shallow-copied-value"
|
||||
|
||||
@dataclasses.dataclass
|
||||
class ExampleContext(Context):
|
||||
title: str
|
||||
status: int
|
||||
error: RefusesDeepCopy
|
||||
|
||||
context = ExampleContext(title="Hello", status=200, error=RefusesDeepCopy())
|
||||
ds = Datasette(memory=True)
|
||||
await ds.invoke_startup()
|
||||
rendered = await ds.render_template("error.html", context)
|
||||
assert "shallow-copied-value" in rendered
|
||||
|
|
|
|||
|
|
@ -178,6 +178,14 @@ async def test_template_context_matches_documented_contract(
|
|||
)
|
||||
|
||||
|
||||
def test_table_context_fields_match_documented_contract():
|
||||
from datasette.views.table import TableContext
|
||||
|
||||
assert {f.name for f in TableContext.documented_fields()} == {
|
||||
key.name for key in PAGES["table"].documented_keys()
|
||||
}
|
||||
|
||||
|
||||
def test_base_context_keys_all_have_docs():
|
||||
for key in BASE_CONTEXT_KEYS:
|
||||
assert key.doc, "Base context key {} is missing docs".format(key.name)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue