Remove render_to_sx from public API: enforce sx_call for all service code
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m44s

Replace ~250 render_to_sx calls across all services with sync sx_call,
converting many async functions to sync where no other awaits remained.
Make render_to_sx/render_to_sx_with_env private (_render_to_sx).
Add (post-header-ctx) IO primitive and shared post/post-admin defmacros.
Convert built-in post/post-admin layouts from Python to register_sx_layout
with .sx defcomps. Remove dead post_admin_mobile_nav_sx.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-04 19:30:45 +00:00
parent 57e0d0c341
commit 959e63d440
61 changed files with 1352 additions and 1208 deletions

View File

@@ -15,7 +15,7 @@ async def _markets_admin_panel_sx(ctx: dict) -> str:
"""Render the markets list + create form panel."""
from quart import g, url_for
from shared.services.registry import services
from shared.sx.helpers import render_to_sx
from shared.sx.helpers import sx_call
from shared.sx.parser import SxExpr
rights = ctx.get("rights") or {}
@@ -32,30 +32,30 @@ async def _markets_admin_panel_sx(ctx: dict) -> str:
form_html = ""
if can_create:
create_url = url_for("page_admin.create_market")
form_html = await render_to_sx("crud-create-form",
form_html = sx_call("crud-create-form",
create_url=create_url, csrf=csrf,
errors_id="market-create-errors",
list_id="markets-list",
placeholder="e.g. Suma, Craft Fair",
btn_label="Add market")
list_html = await _markets_admin_list_sx(ctx, markets)
return await render_to_sx("crud-panel",
list_html = _markets_admin_list_sx(ctx, markets)
return sx_call("crud-panel",
form=SxExpr(form_html), list=SxExpr(list_html),
list_id="markets-list")
async def _markets_admin_list_sx(ctx: dict, markets: list) -> str:
def _markets_admin_list_sx(ctx: dict, markets: list) -> str:
"""Render the markets list items."""
from quart import url_for
from shared.utils import route_prefix
from shared.sx.helpers import render_to_sx
from shared.sx.helpers import sx_call
csrf_token = ctx.get("csrf_token")
csrf = csrf_token() if callable(csrf_token) else (csrf_token or "")
prefix = route_prefix()
if not markets:
return await render_to_sx("empty-state",
return sx_call("empty-state",
message="No markets yet. Create one above.",
cls="text-gray-500 mt-4")
@@ -67,7 +67,7 @@ async def _markets_admin_list_sx(ctx: dict, markets: list) -> str:
href = prefix + f"/{post_slug}/{m_slug}/"
del_url = url_for("page_admin.delete_market", market_slug=m_slug)
csrf_hdr = f'{{"X-CSRFToken":"{csrf}"}}'
parts.append(await render_to_sx("crud-item",
parts.append(sx_call("crud-item",
href=href, name=m_name, slug=m_slug,
del_url=del_url, csrf_hdr=csrf_hdr,
list_id="markets-list",
@@ -116,13 +116,13 @@ async def _h_all_markets_content(**kw):
page_info[p.id] = {"title": p.title, "slug": p.slug}
if not markets:
return await _no_markets_sx()
return _no_markets_sx()
prefix = route_prefix()
next_url = prefix + url_for("all_markets.markets_fragment", page=page + 1)
cards = await _market_cards_sx(markets, page_info, page, has_more, next_url)
return await _markets_grid(cards)
cards = _market_cards_sx(markets, page_info, page, has_more, next_url)
return _markets_grid(cards)
async def _h_page_markets_content(slug=None, **kw):
@@ -138,30 +138,30 @@ async def _h_page_markets_content(slug=None, **kw):
post_slug = post.get("slug", "")
if not markets:
return await _no_markets_sx("No markets for this page")
return _no_markets_sx("No markets for this page")
prefix = route_prefix()
next_url = prefix + url_for("page_markets.markets_fragment", page=page + 1)
cards = await _market_cards_sx(markets, {}, page, has_more, next_url,
cards = _market_cards_sx(markets, {}, page, has_more, next_url,
show_page_badge=False, post_slug=post_slug)
return await _markets_grid(cards)
return _markets_grid(cards)
async def _h_page_admin_content(slug=None, **kw):
from shared.sx.page import get_template_context
from shared.sx.helpers import render_to_sx
from shared.sx.helpers import sx_call
from shared.sx.parser import SxExpr
ctx = await get_template_context()
content = await _markets_admin_panel_sx(ctx)
return await render_to_sx("market-admin-content-wrap", inner=SxExpr(content))
return sx_call("market-admin-content-wrap", inner=SxExpr(content))
async def _h_market_home_content(page_slug=None, market_slug=None, **kw):
def _h_market_home_content(page_slug=None, market_slug=None, **kw):
from quart import g
post_data = getattr(g, "post_data", {})
post = post_data.get("post", {})
return await _market_landing_content_sx(post)
return _market_landing_content_sx(post)
def _h_market_admin_content(page_slug=None, market_slug=None, **kw):