Theme
Version
GitHub PyPI Discord
On this page

Template analysis

Discovery, analysis, source mapping, and formatting for Python-embedded templates.

View source

LspPosition class

A zero-based line and UTF-16 character position used by LSP clients.

Attributes

  • line int - Zero-based source line.
  • character int - Zero-based UTF-16 code-unit offset on that line.
View source

LspRange class

A half-open LSP range in a source document.

Attributes

View source

PythonComponentAssetFormatResult class

One validated, atomic Python component-asset formatting result.

Attributes

View source

PythonComponentAssetPlan class

An immutable Python-source plan awaiting JavaScript and CSS providers.

A plan is bound to the complete source passed to prepare_python_component_assets. Provider work may happen asynchronously before the caller passes every reply to finish_python_component_assets.

Attributes

View source

PythonComponentAssetRegion class

One definite direct literal asset on a Citry component class.

Attributes

View source

PythonComponentAssetRequest class

One standalone JavaScript or CSS document offered to a provider.

Attributes

  • plan_id str - Identity of the source-bound Python formatting plan.
  • id str - Identity of this request within the plan.
  • component_name str - Name of the declaring component class.
  • asset_kind PythonComponentAssetKind - Component asset containing this provider region.
  • language EmbeddedLanguage - Standalone language expected by the provider.
  • region_kind EmbeddedRegionKind | None - Template body kind, or None for a direct js or css literal.
  • source str - Decoded provider-owned source.
  • virtual_source str - Standalone source to send to the provider.
View source

PythonTemplateFormatError class

Bases: ValueError

A formatting refusal that never exposes a partial Python candidate.

Attributes

  • code str - Stable formatter failure code.
  • notices tuple[PythonTemplateNotice, ...] - Component-specific reasons relevant to the refusal.
  • range tuple[int, int] | None - Optional absolute half-open Python string-offset range.
  • diagnostic object | None - Optional nested parser diagnostic. Template parser diagnostic offsets remain relative to the decoded template.
View source

PythonTemplateNotice class

One definite component template skipped for an explicit reason.

View source

PythonTemplateSourceMap class

Map Citry parser byte ranges back into an authored Python document.

The map decodes plain, raw, and Unicode string literals, including implicit literal concatenation. Parser indices address the decoded template as UTF-8 bytes. Returned positions address the Python document with the zero-based UTF-16 coordinates required by LSP.

Build a map with from_ast for valid Python or from_coordinates for a literal region found by a conservative lexical scanner.

Attributes

  • template_source str - Decoded, common-indent-normalized Citry template text passed to the parser.
View source

from_ast function

from_ast(host_source: str, node: Constant) -> PythonTemplateSourceMap

Build a map for a string-valued Python AST constant.

Python AST columns are interpreted as zero-based UTF-8 byte offsets, matching CPython's contract. Adjacent literals represented by the same constant are decoded as one template.

Parameters

  • host_source str - Complete Python document text.
  • node Constant - A string-valued ast.Constant from host_source.

Returns

PythonTemplateSourceMap: A source map whose ``template_source`` is the normalized inline

Raises

  • TypeError - If node is not a string-valued ast.Constant.
  • ValueError - If source positions are missing or the authored text does not decode to node.value.
View source

from_coordinates function

from_coordinates(host_source: str, lineno: int, col_offset: int, end_lineno: int | None = None, end_col_offset: int | None = None, accept_incomplete: bool = False) -> PythonTemplateSourceMap

Build a map from Python parser coordinates around a literal expression.

Supply both end coordinates for complete source. A conservative lexical scanner may omit them and set accept_incomplete=True for an unfinished final triple-quoted literal, in which case the document end is the temporary content boundary.

Parameters

  • host_source str - Complete Python document text.
  • lineno int - 1-based line containing the first literal prefix or quote.
  • col_offset int - Zero-based UTF-8 byte column of that prefix or quote.
  • end_lineno int | None - 1-based line immediately after the expression.
  • end_col_offset int | None - Zero-based UTF-8 byte column immediately after the expression.
  • accept_incomplete bool - Accept an unfinished final triple-quoted literal and map its content through the end of the document.

Returns

PythonTemplateSourceMap: A map for the decoded string expression.

Raises

  • ValueError - If coordinates, literal syntax, or escape syntax are invalid or unsupported.
View source

map_range function

map_range(start_index: int, end_index: int) -> LspRange

Convert one half-open parser byte range to Python-document coordinates.

Parameters

  • start_index int - Inclusive UTF-8 byte offset in template_source.
  • end_index int - Exclusive UTF-8 byte offset in template_source.

Returns

LspRange: The corresponding zero-based LSP range in the Python document.

Raises

  • ValueError - If the range is reversed, outside the template, or splits a UTF-8 code point.
View source

range_is_unambiguous function

range_is_unambiguous(start_index: int, end_index: int) -> bool

Return whether a parser range stays inside one authored literal body.

Normalized indentation and Python escapes remain mappable inside one literal. Crossing an implicit-concatenation boundary is ambiguous for editor edits and semantic result ranges.

Parameters

  • start_index int - Inclusive UTF-8 byte offset in template_source.
  • end_index int - Exclusive UTF-8 byte offset in template_source.

Returns

bool: ``True`` when both boundaries belong to one literal body.

Raises

  • ValueError - If the range is reversed, outside the template, or splits a UTF-8 code point.
View source

parser_index_at function

parser_index_at(position: LspPosition) -> int | None

Return the parser byte boundary at an authored LSP position.

Positions in quotes, prefixes, comments between concatenated literals, or other Python outside the decoded template return None. A position inside an authored escape maps to the byte boundary after the decoded character.

View source

TemplateAnalysis class

A complete, immutable snapshot of one Citry component registry.

Attributes

  • component_names frozenset[str] - Normalized registered names without the c- tag prefix. The set includes aliases and built-in component names.
  • lint TemplateLintInfo - Application lint settings and known global variables.
  • component_lint Mapping[str, TemplateLintInfo] - Effective lint settings and known variables keyed by stable component definition ID.
View source

parse_template function

parse_template(source: str) -> Template

Parse authored Citry source with this registry's component contracts.

The parser checks registered component inputs and slots. Extension transforms are not run because they do not currently provide a mapping back to the authored source. Names absent from component_names need a separate unknown-component diagnostic after a successful parse.

Parameters

  • source str - Authored Citry template source.

Returns

Template: The parsed template AST.

Raises

  • SyntaxError - If syntax or a registered component contract is invalid.
  • ValueError - If parser configuration is invalid.
View source

to_dict function

to_dict() -> dict[str, object]

Return a fresh JSON-ready copy of this analysis snapshot.

View source

from_dict function

from_dict(value: object) -> TemplateAnalysis

Rebuild a snapshot from :meth:to_dict portable data.

View source

TemplateLintConsumer class

Describe one proven component namespace used by a physical template.

Attributes

  • known_names frozenset[str] - Root names available to this component's template.
  • namespace_policy Literal['closed', 'allow-extra', 'unknown'] - Whether those names exhaust normalized template data.
  • rule_unknown_template_variable Literal['ignore', 'warning', 'error'] - Configured severity for undeclared free roots.
View source

namespace_policy attribute

namespace_policy: Literal['closed', 'allow-extra', 'unknown']
View source

rule_unknown_template_variable attribute

rule_unknown_template_variable: Literal['ignore', 'warning', 'error']
View source

TemplateLintInfo class

Carry one component's effective lint rule and known global variables.

View source

TemplateVariableInfo class

Describe one known template variable using detached portable text.

View source

type_fidelity attribute

type_fidelity: Literal['normalized', 'unavailable']
View source

source attribute

source: VariableSource
View source

to_dict function

to_dict() -> dict[str, object]

Return a JSON-ready detached copy.

View source

from_dict function

from_dict(value: object) -> TemplateVariableInfo

Validate and restore one detached variable record.

View source

discover_python_component_assets function

discover_python_component_assets(source: str) -> PythonComponentAssetDiscovery

Discover direct literal and static file assets on proven components.

Discovery recognizes direct template, js, and css literals, plus constant template_file, js_file, and css_file paths. It never imports the module or evaluates a computed declaration.

Parameters

  • source str - Complete Python module source.

Returns

PythonComponentAssetDiscovery: Definite inline regions, file declarations, and explicit notices.

Raises

  • SyntaxError - If source is not a complete valid Python module.
  • TypeError - If source is not a string.
View source

discover_python_templates function

discover_python_templates(source: str, recover_incomplete: bool = False) -> PythonTemplateDiscovery

Discover direct literal templates on provable Citry component classes.

Normal batch tooling leaves recover_incomplete false and receives the original Python SyntaxError. An interactive editor may opt into the narrow recovery of one unfinished direct triple-quoted template literal.

View source

finish_python_component_assets function

finish_python_component_assets(plan: PythonComponentAssetPlan, results: Sequence[EmbeddedFormatResult], require_providers: bool = False) -> PythonComponentAssetFormatResult

Validate provider replies and atomically finish one Python source plan.

Every selected literal is rewritten only after every provider reply, Python parse, asset rediscovery, and decoded-value check succeeds. A failure raises without exposing a partial source candidate.

Parameters

Returns

PythonComponentAssetFormatResult: The complete formatted Python source and provider metadata.

Raises

  • PythonTemplateFormatError - If replies are missing, stale, duplicated, unavailable when required, invalid, or unsafe to rewrite.
  • TypeError - If plan, results, or require_providers has the wrong type.
View source

format_python_component_assets function

format_python_component_assets(source: str, kinds: Collection[PythonComponentAssetKind | str] = tuple(PythonComponentAssetKind), host_offset: int | None = None, provider: Callable[[PythonComponentAssetRequest], EmbeddedFormatResult] | None = None, require_providers: bool = False) -> PythonComponentAssetFormatResult

Format selected direct component assets in one atomic Python-file edit.

This synchronous convenience function prepares a plan, invokes provider once per JavaScript or CSS request, then validates and finishes the plan. Call the two-pass prepare and finish functions directly when provider work must be asynchronous. With no provider, M2 template formatting still runs while JavaScript and CSS requests remain unchanged with notices.

Parameters

  • source str - Complete Python module source.
  • kinds Collection[PythonComponentAssetKind | str] - Explicit template, js, and css kinds to select.
  • host_offset int | None - Optional zero-based Python string offset selecting only the containing direct asset.
  • provider Callable[[PythonComponentAssetRequest], EmbeddedFormatResult] | None - Optional synchronous JavaScript/CSS formatting callback.
  • require_providers bool - Reject the complete operation when any selected embedded region has no provider.

Returns

PythonComponentAssetFormatResult: The validated complete source, changed asset identities, notices, and

Raises

  • PythonTemplateFormatError - If discovery, formatting, a provider, or final validation fails. No partial candidate is exposed.
  • TypeError - If an argument or provider reply has the wrong type.
  • ValueError - If host_offset or a selected kind is invalid.
View source

format_python_templates function

format_python_templates(source: str, host_offset: int | None = None) -> PythonTemplateFormatResult

Format proven direct Citry template literals in complete Python source.

With no offset, every definite inline template is one atomic operation. A host offset selects only the literal content containing that Python string position. The result preserves string prefixes, delimiters, and all host text outside the exact decoded-template rewrite hunks.

Parameters

  • source str - Complete Python module source.
  • host_offset int | None - Optional zero-based Python string offset inside one template literal body.

Returns

PythonTemplateFormatResult: The validated source, changed component names, and discovery notices.

Raises

  • PythonTemplateFormatError - If Python or Citry syntax is invalid, a selected literal is not safely rewriteable, or validation fails.
  • TypeError - If source or host_offset has the wrong type.
  • ValueError - If host_offset is outside source.
View source

prepare_python_component_assets function

prepare_python_component_assets(source: str, kinds: Collection[PythonComponentAssetKind | str] = tuple(PythonComponentAssetKind), host_offset: int | None = None) -> PythonComponentAssetPlan

Prepare one atomic Python component-asset formatting operation.

Templates first receive Citry structure and Python-expression formatting. Safe script and style bodies, plus direct js and css literals, become standalone provider requests. The returned plan makes no source edit, so callers may resolve those requests asynchronously.

Parameters

  • source str - Complete Python module source.
  • kinds Collection[PythonComponentAssetKind | str] - Explicit component asset kinds selected for this operation.
  • host_offset int | None - Optional zero-based Python string offset. When supplied, only the containing selected direct asset is prepared.

Returns

PythonComponentAssetPlan: A source-bound plan and its provider requests.

Raises

  • PythonTemplateFormatError - If Python or selected asset syntax is invalid, or a selected literal cannot be rewritten safely.
  • TypeError - If an argument has the wrong type.
  • ValueError - If host_offset is outside source or a kind is unknown.
View source

lint_unknown_template_variables function

lint_unknown_template_variables(template: object, consumers: Sequence[TemplateLintConsumer]) -> tuple[TemplateLintFinding, ...]

Diagnose free roots missing from at least one proven component namespace.

Parameters

  • template object - Parsed Citry template AST. Its parser-reported free variables already exclude lexical and Python-local bindings.
  • consumers Sequence[TemplateLintConsumer] - Every proven component that consumes this physical template.

Returns

TemplateLintFinding: Findings in the parser's stable free-variable order. No consumer means

Raises

  • TypeError - If the parsed object lacks Citry free-variable records.
Citry version: 0.3.2