pages.discovery

Page actions AI-ready formats and sharing
Open LLM text
Share with AI
Ask Claude Ask ChatGPT Ask Gemini Ask Copilot

Filesystem route discovery for the pages/ directory.

Walks the pages directory tree and discovers:

  • _layout.htmlfiles as layout templates
  • _context.pyfiles as context providers
  • .pyroute files as handler modules

Directory names…

Filesystem route discovery for the pages/ directory.

Walks the pages directory tree and discovers:

  • _layout.htmlfiles as layout templates
  • _context.pyfiles as context providers
  • .pyroute files as handler modules

Directory names wrapped in\{braces}become path parameters. page.py maps to the directory URL; other .pyfiles append their stem to the path.

Modeled on Bengal's ContentDiscovery but for routes instead of content.

pages.discovery

Name Type Default Description
type
qualified_name
element_type
description
source_file
line_number
is_autodoc
autodoc_element
_autodoc_template
_autodoc_url_path
_autodoc_page_type
title
doc_content_hash

Symbols on this page

function default_route_name

Derive a dotted default route name from a URL path.

Parameter braces are stripped and the param name is kept bare:

/contacts/\{contact_id}"contacts.contact_id"…

Jump to symbol
function discover_pages

Walk a pages directory and discover all routes.

Jump to symbol
function discover_pages_with_findings

Walk a pages directory and discover routes plus handler-discovery findings.

Same asdiscover_pages() but also returns a list of PageHandlerFinding objects describing page.py…

Jump to symbol
function _walk_directory

Recursively walk a directory, discovering routes and layouts.

Jump to symbol
function _infer_route_kind

Infer route kind from file combination. Informational only.

Jump to symbol
function _parse_layout_metadata

Read{# target #}and optional shell scope comments from a layout.

Supported annotations::

{# preset: preset_name #} {# target: element_id #} {# domain:…
Jump to symbol
function _resolve_layout_preset

Resolve a named layout preset or raise for unknown names.

Jump to symbol
function _normalize_outlet_mode

Normalize{# outlet_mode: #}token to a known mode.

Jump to symbol
function _load_viewmodel

Load viewmodel() function from _viewmodel.py.

Jump to symbol
function _load_actions

Load @action decorated functions from _actions.py.

Jump to symbol
function _load_meta

Load RouteMeta from a _meta.py file.

Checks for META constant first, then meta() callable. Returns (meta, meta_provider) — one will be set, the other…

Jump to symbol
function dict_to_route_meta

Convert a meta dict to a normalizedRouteMeta, filling provided keys.

auth accepts a plain str(back-compatible), a structured AuthSpec, or a …

Jump to symbol
function _coerce_auth

Coerce a rawauth value to the canonical AuthSpec | Noneshape.

  • dict -> AuthSpecbuilt from permissions/mode/policy/scopes…
Jump to symbol
function normalize_route_meta

Return meta withauth canonicalized to AuthSpec | None.

Applied at discovery time (staticMETA) and at request time for dynamic meta()…

Jump to symbol
function _load_context_provider

Load a context() function from a _context.py file.

Uses path-based module names (_chirp_ctx_collections, etc.) so sibling directories do not overwrite each other in sys.modules.…

Jump to symbol
function _process_route_file

Load a route .py file and extract handler functions.

page.pymaps to the directory URL. Other files append their stem to the URL path.…

Jump to symbol
default_route_name
function
def default_route_name(url_path: str) -> str

Derive a dotted default route name from a URL path.

Parameter braces are stripped and the param name is kept bare:

/contacts/\{contact_id}"contacts.contact_id". Typed params drop the type:/{id:int}"id". The root path/ becomes "index"so every route has a non-empty name.

Parameters

Name Type Default Description
url_path str
discover_pages
function
def discover_pages(pages_dir: str | Path, *, layout_presets: Mapping[str, LayoutPreset] | None = None) -> list[PageRoute]

Walk a pages directory and discover all routes.

Parameters

Name Type Default Description
pages_dir str | Path Path to the ``pages/`` directory.
layout_presets Mapping[str, LayoutPreset] | None None
discover_pages_with_findings
function
def discover_pages_with_findings(pages_dir: str | Path, *, layout_presets: Mapping[str, LayoutPreset] | None = None) -> tuple[list[PageRoute], list[PageHandlerFinding]]

Walk a pages directory and discover routes plus handler-discovery findings.

Same asdiscover_pages() but also returns a list of PageHandlerFinding objects describing page.pyfiles that have no recognised handler or define handler-shaped typos. Findings are consumed by thepage_handlerscontract check.

Parameters

Name Type Default Description
pages_dir str | Path
layout_presets Mapping[str, LayoutPreset] | None None
_walk_directory
function
def _walk_directory(directory: Path, root: Path, *, url_parts: list[str], layouts: list[LayoutInfo], context_providers: list[ContextProvider], depth: int, routes: list[PageRoute], findings: list[PageHandlerFinding], layout_presets: Mapping[str, LayoutPreset]) -> None

Recursively walk a directory, discovering routes and layouts.

Parameters

Name Type Default Description
directory Path Current directory being walked.
root Path Root pages directory (for computing template paths).
url_parts list[str] URL path segments accumulated so far.
layouts list[LayoutInfo] Layout chain accumulated from parent directories.
context_providers list[ContextProvider] Context providers from parent directories.
depth int Current nesting depth.
routes list[PageRoute] Accumulator for discovered routes.
findings list[PageHandlerFinding]
layout_presets Mapping[str, LayoutPreset]
_infer_route_kind
function
def _infer_route_kind(*, has_template: bool, is_param_dir: bool) -> RouteKind

Infer route kind from file combination. Informational only.

Parameters

Name Type Default Description
has_template bool
is_param_dir bool
_parse_layout_metadata
function
def _parse_layout_metadata(layout_file: Path, *, layout_presets: Mapping[str, LayoutPreset]) -> dict[str, Any]

Read{# target #}and optional shell scope comments from a layout.

Supported annotations::

{# preset: preset_name #}
{# target: element_id #}
{# domain: navigation_domain #}
{# shell: shell_name #}
{# swap_scope: symbolic_name #}
{# outlet: element_id #}
{# outlet_mode: compose | replace #}
{# frames: id1, id2 #}

Parameters

Name Type Default Description
layout_file Path
layout_presets Mapping[str, LayoutPreset]
_resolve_layout_preset
function
def _resolve_layout_preset(layout_file: Path, preset_name: str | None, layout_presets: Mapping[str, LayoutPreset]) -> LayoutPreset | None

Resolve a named layout preset or raise for unknown names.

Parameters

Name Type Default Description
layout_file Path
preset_name str | None
layout_presets Mapping[str, LayoutPreset]
_normalize_outlet_mode
function
def _normalize_outlet_mode(raw: str | OutletSwapMode | None) -> OutletSwapMode

Normalize{# outlet_mode: #}token to a known mode.

Parameters

Name Type Default Description
raw str | OutletSwapMode | None
_load_viewmodel
function
def _load_viewmodel(viewmodel_file: Path, root: Path) -> Any

Load viewmodel() function from _viewmodel.py.

Parameters

Name Type Default Description
viewmodel_file Path
root Path
_load_actions
function
def _load_actions(actions_file: Path, root: Path) -> tuple[ActionInfo, ...]

Load @action decorated functions from _actions.py.

Parameters

Name Type Default Description
actions_file Path
root Path
_load_meta
function
def _load_meta(meta_file: Path, root: Path) -> tuple[RouteMeta | None, Any]

Load RouteMeta from a _meta.py file.

Checks for META constant first, then meta() callable. Returns (meta, meta_provider) — one will be set, the other None. Raises ValueError if _meta.py has neither META nor meta().

Parameters

Name Type Default Description
meta_file Path
root Path
dict_to_route_meta
function
def dict_to_route_meta(d: dict[str, Any]) -> RouteMeta

Convert a meta dict to a normalizedRouteMeta, filling provided keys.

auth accepts a plain str(back-compatible), a structured AuthSpec, or a dictthat constructs an AuthSpec (e.g. {"permissions": ["a", "b"], "mode": "any"}). The result is canonicalized so the request-time gate is allocation-free.

Parameters

Name Type Default Description
d dict[str, Any]
_coerce_auth
function
def _coerce_auth(value: Any) -> Any

Coerce a rawauth value to the canonical AuthSpec | Noneshape.

  • dict -> AuthSpecbuilt from permissions/mode/policy/scopes(a dict auth is always a declared gate; anAuthSpecalways requires authentication, so there is norequired key). scopesis the machine-token axis, parallel to permissions.
  • str / AuthSpec / None-> normalized via the shared core so the runtime meaning of every legacy string is preserved exactly.

Adict mode other than "all" / "any" raises ValueErrorat coercion time (discovery for staticMETA, request time for dynamic meta()) — fail loud rather than silently degrading an invalid mode.

Parameters

Name Type Default Description
value Any
normalize_route_meta
function
def normalize_route_meta(meta: RouteMeta | None) -> RouteMeta | None

Return meta withauth canonicalized to AuthSpec | None.

Applied at discovery time (staticMETA) and at request time for dynamic meta()results, so the request-time gate (enforce_route_meta_auth()) never re-allocates a spec and reserved-token confusion ("Required" / " required " / "") surfaces as a startupauth_specissue rather than a silent 403. Returns meta unchanged whenauthis already canonical (allocation-free).

Parameters

Name Type Default Description
meta RouteMeta | None
_load_context_provider
function
def _load_context_provider(context_file: Path, root: Path, depth: int) -> ContextProvider | None

Load a context() function from a _context.py file.

Uses path-based module names (_chirp_ctx_collections, etc.) so sibling directories do not overwrite each other in sys.modules.

Returns None if the module doesn't export acontextfunction.

Parameters

Name Type Default Description
context_file Path
root Path
depth int
_process_route_file
function
def _process_route_file(file: Path, root: Path, *, url_parts: list[str], layout_chain: LayoutChain, context_providers: tuple[ContextProvider, ...], routes: list[PageRoute], findings: list[PageHandlerFinding], route_meta: RouteMeta | None = None, meta_provider: Any = None, actions: tuple[ActionInfo, ...] = (), viewmodel_provider: Any = None) -> None

Load a route .py file and extract handler functions.

page.pymaps to the directory URL. Other files append their stem to the URL path.

Handler functions are named after HTTP methods:get, post, etc.

Parameters

Name Type Default Description
file Path
root Path
url_parts list[str]
layout_chain LayoutChain
context_providers tuple[ContextProvider, ...]
routes list[PageRoute]
findings list[PageHandlerFinding]
route_meta RouteMeta | None None
meta_provider Any None
actions tuple[ActionInfo, ...] ()
viewmodel_provider Any None

View source · /home/runner/work/chirp/chirp/site/../src/chirp/pages/discovery.py:1