Make SxExpr a str subclass, sx_call/render functions return SxExpr

SxExpr is now a str subclass so it works everywhere a plain string
does (join, isinstance, f-strings) while serialize() still emits it
unquoted. sx_call() and all internal render functions (_render_to_sx,
async_eval_to_sx, etc.) return SxExpr, eliminating the "forgot to
wrap" bug class that caused the sx_content leak and list serialization
bugs.

- Phase 0: SxExpr(str) with .source property, __add__/__radd__
- Phase 1: sx_call returns SxExpr (drop-in, all 200+ sites unchanged)
- Phase 2: async_eval_to_sx, async_eval_slot_to_sx, _render_to_sx,
  mobile_menu_sx return SxExpr; remove isinstance(str) workaround
- Phase 3: Remove ~150 redundant SxExpr() wrappings across 45 files
- Phase 4: serialize() docstring, handler return docs, ;; returns: sx

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-04 21:47:00 +00:00
parent ad75798ab7
commit 278ae3e8f6
45 changed files with 378 additions and 379 deletions

View File

@@ -78,7 +78,7 @@ def _calendars_header_sx(ctx: dict, *, oob: bool = False) -> str:
link_href = url_for("calendars.home")
return sx_call("menu-row-sx", id="calendars-row", level=3,
link_href=link_href,
link_label_content=SxExpr(sx_call("events-calendars-label")),
link_label_content=sx_call("events-calendars-label"),
child_id="calendars-header-child", oob=oob)
@@ -104,7 +104,7 @@ def _calendar_header_sx(ctx: dict, *, oob: bool = False) -> str:
nav_html = _calendar_nav_sx(ctx)
return sx_call("menu-row-sx", id="calendar-row", level=3,
link_href=link_href, link_label_content=SxExpr(label_html),
link_href=link_href, link_label_content=label_html,
nav=SxExpr(nav_html) if nav_html else None, child_id="calendar-header-child", oob=oob)
@@ -158,7 +158,7 @@ def _day_header_sx(ctx: dict, *, oob: bool = False) -> str:
nav_html = _day_nav_sx(ctx)
return sx_call("menu-row-sx", id="day-row", level=4,
link_href=link_href, link_label_content=SxExpr(label_html),
link_href=link_href, link_label_content=label_html,
nav=SxExpr(nav_html) if nav_html else None, child_id="day-header-child", oob=oob)
@@ -271,7 +271,7 @@ def _markets_header_sx(ctx: dict, *, oob: bool = False) -> str:
link_href = url_for("defpage_events_markets")
return sx_call("menu-row-sx", id="markets-row", level=3,
link_href=link_href,
link_label_content=SxExpr(sx_call("events-markets-label")),
link_label_content=sx_call("events-markets-label"),
child_id="markets-header-child", oob=oob)
@@ -544,7 +544,7 @@ def _day_row_html(ctx: dict, entry) -> str:
state = getattr(entry, "state", "pending") or "pending"
state_badge = _entry_state_badge_html(state)
state_td = sx_call("events-day-row-state",
state_id=f"entry-state-{entry.id}", badge=SxExpr(state_badge))
state_id=f"entry-state-{entry.id}", badge=state_badge)
# Cost
cost = getattr(entry, "cost", None)
@@ -564,9 +564,9 @@ def _day_row_html(ctx: dict, entry) -> str:
actions_td = sx_call("events-day-row-actions")
return sx_call("events-day-row",
tr_cls=tr_cls, name=SxExpr(name_html), slot=SxExpr(slot_html),
state=SxExpr(state_td), cost=SxExpr(cost_td),
tickets=SxExpr(tickets_td), actions=SxExpr(actions_td))
tr_cls=tr_cls, name=name_html, slot=slot_html,
state=state_td, cost=cost_td,
tickets=tickets_td, actions=actions_td)
# ---------------------------------------------------------------------------
@@ -598,7 +598,7 @@ def _calendar_admin_main_panel_html(ctx: dict) -> str:
description_html = _calendar_description_display_html(calendar, desc_edit_url)
return sx_call("events-calendar-admin-panel",
description_content=SxExpr(description_html), csrf=csrf,
description_content=description_html, csrf=csrf,
description=desc)