Citry instance and config
The Citry instance that scopes components, settings, and caches, and the warning class for deprecated features.
Citry class
Global instance that scopes all component state.
A Citry instance owns:
- A private component-name registry reached through the engine's methods
- Settings
- Transient rendering state
All Component classes are assigned to a Citry instance at class definition time. If no instance is specified, the default instance is used.
Call initialize() after startup-time registration and before a server starts request threads. Lazy initialization remains available, but a thread that encounters lifecycle work owned by another thread receives CitryLifecycleInProgress.
render_template function
render_template(source: str, variables: Mapping[str, Any] | None = None, slots: Mapping[str, Any] | None = None, template_globals: Mapping[str, Any] | None = None, provides: Mapping[str, Any] | None = None, foreign_compile_contexts: Sequence[ForeignCompileContext] = (), origin: str = '<render_template>') -> CitryRenderRender trusted standalone Citry template source through the normal pipeline.
engine_id attribute
engine_id: strReturn this engine's opaque process-lifetime identity token.
The value is stable for this Citry instance, including across clear(), and differs for another instance in the same process. Component-introspection consumers combine it with Component.class_id and Component.definition_id when they need to confirm that retained metadata still describes an exact live component generation.
Returns
str: A non-time-derived token intended only for same-process identity
atomic_registration function
atomic_registration() -> Iterator[None]Publish a group of component registrations together.
Component classes defined inside the block register normally and fire the normal class and registration hooks. If the block raises, Citry restores its component names, class-ID and file indexes, tag rules, and discovery state to their values at entry. Another thread receives CitryLifecycleInProgress rather than observing or changing the group before it commits.
This context manager is additive: it publishes new classes and aliases; unregister() rejects removals inside the block. Start the block outside other component lifecycle operations; nested atomic-registration blocks are rejected. Ordinary component definitions and their hooks remain reentrant inside the block.
Rollback covers the Citry registration and installation indexes listed above. Rendered-output caches, side effects that extension hooks or ordinary Python write elsewhere, and registrations made to another Citry instance are outside the transaction.
Yields
- None - None. Component factories return their own created classes; the
- None - context manager only owns publication and rollback.
Example
with app.atomic_registration(): class AcmeButton(Component): citry = app
Raises
CitryLifecycleInProgress- If another thread owns component lifecycle work for this Citry instance.RuntimeError- If called inside another component lifecycle operation on the same thread.
register_library function
register_library(library: ComponentLibrary | ModuleType) -> LibraryInstallationMaterialize and publish an engine-neutral component library.
A library package may be passed directly when it exposes its manifest as __citry_library__. Registration creates a distinct concrete Component class for every definition and this Citry instance. The classes and immutable installation record become visible together.
Repeating the same manifest and exact definition generation returns the existing installation without rerunning component hooks. Clear the Citry instance before installing a reloaded or changed manifest with the same library name.
Example
import citry_ui from citry import Citry app = Citry() installed = app.register_library(citry_ui)
Parameters
libraryComponentLibrary | ModuleType- AComponentLibraryor imported package exposing one as__citry_library__.
Returns
LibraryInstallation: The exact active [`LibraryInstallation`](/reference/component-libraries/#citry-libraryinstallation).
Raises
LibraryManifestChanged- If the library name is already associated with another manifest or definition generation.LibraryInstallationStale- If internal registry mutation damaged an active installation.ValueError- If a required extension is not installed or a component identity collides with existing state.AlreadyRegistered- If a registry name is already occupied.CitryLifecycleInProgress- If another thread owns lifecycle work.RuntimeError- If registration is attempted recursively.
get_library_installation function
get_library_installation(name: str) -> LibraryInstallationReturn one exact active component-library installation.
Parameters
namestr- The manifest's case-sensitive library name.
Returns
LibraryInstallation: The current immutable installation handle.
Raises
LibraryNotInstalled- If no library withnameis active.LibraryInstallationStale- If private registry mutation damaged the installation record.CitryLifecycleInProgress- If another thread owns lifecycle work.
register function
Register an additional name for a component owned by this instance.
Component classes register automatically when they are defined. This method supports same-engine aliases and re-registering a class after it was removed. A class owned by another Citry instance is rejected.
Fires on_component_registered once per call, after the registry accepts the class.
Raises
AlreadyRegistered- If the requested name or class ID belongs to a different component, or the name is reserved.ValueError- If the component belongs to another Citry instance, is a retired built-in generation, or the requested name is invalid.CitryLifecycleInProgress- If another thread is changing component lifecycle state.
unregister function
Unregister one name or all names for a component owned by this instance.
Fires on_component_unregistered once per call, after the registry removes the class.
Raises
NotRegistered- If the requested class or name is not registered.ValueError- If asked to remove a built-in's canonical name or unregister the built-in class.CitryLifecycleInProgress- If another thread is changing component lifecycle state.RuntimeError- If called insideatomic_registration()on this thread; atomic registration is additive.
get function
Look up a component by name.
Parameters
namestr- Registered component name, matched case-insensitively.
Returns
type[Component]: The registered component class.
Raises
NotRegistered- If no component has this name after discovery.CitryLifecycleInProgress- If another thread is changing component lifecycle state.
components attribute
All registered components as a name-to-class mapping.
Raises
CitryLifecycleInProgress- If another thread is changing component lifecycle state.
inspect_components function
inspect_components(include_builtins: bool = False, resolve_assets: bool = False, include_default_values: bool = False, include_extensions: Iterable[str] = ()) -> ComponentCatalogReturn an immutable catalog of the currently registered components.
The method completes normal lazy discovery and built-in creation, then copies the registry once. Schema and asset metadata are built from that copy after lifecycle coordination is released. Asset inspection never reads source content or changes render and hot-reload caches.
Parameters
include_builtinsbool- Include Citry's framework component classes.resolve_assetsbool- Check declared asset paths on the filesystem and report resolved, missing, and searched paths.include_default_valuesbool- Copy portable literal schema defaults into field metadata. Default factories are never called.include_extensionsIterable[str]- Installed extensions whose versioned component metadata inspectors should run. Names are deduplicated and sorted; no inspector runs unless explicitly requested.
Returns
ComponentCatalog: A canonically ordered [`ComponentCatalog`](/reference/component-introspection/#citry-componentcatalog)
Raises
TypeError- If a boolean option is not a bool orinclude_extensionsis a string or non-iterable.ComponentIntrospectionError- If a requested extension is missing, unsupported, fails, or publishes invalid metadata.CitryLifecycleInProgress- If another thread is changing component lifecycle state.
inspect_component function
inspect_component(component: str | type[Component], resolve_assets: bool = False, include_default_values: bool = False, include_extensions: Iterable[str] = ()) -> ComponentInfoInspect one component selected from a copied registry snapshot.
A string is matched case-insensitively as a registered component name. A class must be owned by this engine and present under at least one name. Looking up an alias does not change the record's deterministic primary name.
Parameters
componentstr | type[Component]- A registered name or exact registered component class.resolve_assetsbool- Check declared asset paths on the filesystem.include_default_valuesbool- Copy portable literal schema defaults.include_extensionsIterable[str]- Installed extensions whose versioned metadata inspectors should run. Names are deduplicated and sorted.
Returns
ComponentInfo: A value-only [`ComponentInfo`](/reference/component-introspection/#citry-componentinfo) record.
Raises
TypeError- Ifcomponentis neither a string nor a class, a boolean option is not a bool, orinclude_extensionsis a string or non-iterable.NotRegistered- If the name or exact class is absent from the copied registry snapshot.ComponentIntrospectionError- If a requested extension is missing, unsupported, fails, or publishes invalid metadata.CitryLifecycleInProgress- If another thread is changing component lifecycle state.
inspect_component_graph function
inspect_component_graph(include_builtins: bool = False) -> ComponentGraphReturn authored component dependencies from one registry snapshot.
Citry copies the complete name-to-class registry once, then reads each selected component's effective primary template without rendering or running template-load transforms. The graph includes direct dependency and reverse-reference queries plus explicit unresolved targets and source problems.
Experimental
The component graph is experimental. Its methods, attributes, and JSON output may change in a minor release without a deprecation period.
Example
graph = app.inspect_component_graph() for dependency in graph.dependencies("account-page"): print(dependency.name) for dependent in graph.dependents("avatar"): print(dependent.name)
Note
The graph covers component tags in authored primary templates. It does not claim to find components composed from Python, inserted by a transform, or chosen by a dynamic selector.
Parameters
include_builtinsbool- Include Citry's framework component definitions and references to them.
Returns
ComponentGraph: A versioned [`ComponentGraph`](/reference/component-graph/#citry-componentgraph) containing
Raises
TypeError- Ifinclude_builtinsis not a bool.CitryLifecycleInProgress- If another thread is changing component lifecycle state.
initialize function
initialize() -> NonePrepare component registration state before starting worker threads.
This imports configured component modules when autodiscovery is enabled, creates Citry's built-in components, and builds the current parse-time tag rules. Component template, JavaScript, and CSS asset files remain lazy and are loaded when rendering needs them.
Call this after startup-time component registration and before a server begins handling requests concurrently. Repeated successful calls are safe; a later registration invalidates tag rules, and another call rebuilds them.
Initialization is retryable rather than globally transactional. If a module import fails, components from earlier successful module imports may remain registered, while the incomplete work is retried later.
Returns
None: None.
Raises
CitryLifecycleInProgress- If another thread is changing component lifecycle state.RuntimeError- If called recursively from an active lifecycle hook or initialization on this thread.
template_analysis function
template_analysis() -> TemplateAnalysisCapture the complete component contracts used to analyze templates.
The method completes normal component discovery and built-in registration under the engine's lifecycle guard. The returned snapshot keeps normalized registered names and parse-time input and slot rules together, so tooling cannot observe a partial registry. Call it again after component registration or reload to capture the new state.
Experimental
Part of the experimental template analysis API that
citry check,citry formatand citry-lsp use. It may change in a minor release without a deprecation period.
Returns
TemplateAnalysis: An immutable [`TemplateAnalysis`](/reference/template-analysis/#citry-templateanalysis) snapshot.
Raises
CitryLifecycleInProgress- If another thread is changing component lifecycle state.RuntimeError- If discovery or component initialization fails.
autodiscover function
Import this instance's component modules so their classes register.
With no argument, imports every component module under the instance's dirs - the same scan the autodiscover setting performs automatically on first use - and marks that automatic scan done, so it will not run again. Pass dirs to import an extra set of directories on demand without affecting the automatic scan.
The directories must be importable: each one (or a parent of it) is on sys.path/PYTHONPATH, which is how a component file is mapped to the import name Python uses for it. A directory that holds component modules but is not importable raises ValueError.
Returns the dotted import paths of the modules that were imported. Safe to call more than once: an already-imported module has its components re-registered directly, so a call after clear() rebuilds the registry and a call that changes nothing is a no-op.
A scan is marked complete only after every module imports successfully. If one module raises, registrations it made to this Citry instance during that import are rolled back, and a later call can retry it. Earlier modules and dependency modules that imported successfully remain registered. Python side effects and registrations made to another Citry instance are outside this rollback. Calling autodiscover() recursively from a component module raises RuntimeError.
Raises
CitryLifecycleInProgress- If another thread is changing component lifecycle state.RuntimeError- If a component module starts another autodiscovery scan on the same instance.
urls attribute
This instance's HTTP route table (framework-neutral URLRoutes).
The web-integration adapters (citry.contrib.asgi and friends) mount these into the host application; the routes serve cached component JS/CSS, the client runtime, and extension endpoints.
commands attribute
commands: dict[str, tuple[type[ExtensionCommand], ...]]This instance's CLI commands, keyed by extension name.
Each registered extension contributes the commands it declares in Extension.commands; the citry command-line tool reaches one as citry ext run <extension name> <command name>. See ExtensionManager.commands for ordering and the uniqueness guarantee.
mounted_prefix attribute
mounted_prefix: str | NoneWhere this instance's routes are mounted (e.g. "/citry"), or None when nothing is mounted.
set_mounted_prefix function
set_mounted_prefix(prefix: str) -> NoneRecord where this instance's routes are mounted in the host app.
The adapters' mount() call this; call it directly only in a process that builds URLs without mounting the routes itself (for example a worker that renders fragments served by another process). prefix must start with /; a trailing / is dropped.
Raises
ValueError- Ifprefixdoes not start with/.
build_url function
An absolute URL path for one of this instance's routes.
path is the route's full path (no leading slash), e.g. "cache/Table_a1b2c3.js". When the host app is served below a sub-path, such as /shop, the URL starts with that sub-path. The integration that mount() set up reads it from the current request. Raises RuntimeError when no web integration is mounted, since the URL would point nowhere.
runtime_url function
runtime_url() -> strReturn the URL of Citry's browser runtime for a page you write by hand.
Pages that Citry renders already link the runtime. Call this when your own HTML loads it, for example a page that only receives HTML fragments. The URL holds a hash of the runtime file, so the browser keeps the file between page loads. The hash, and so the URL, changes when an upgrade changes the file. The URL includes the mount prefix and any sub-path the app is served below, such as /shop. When the app sets cache, this call also stores the runtime there, so another worker can serve it.
A static HTML file that you write once keeps the old hash after an upgrade. Link the stable /citry/citry.js from that file instead; the browser then downloads it on every page load.
Example
from citry import citry src = citry.runtime_url() html = f'<script src="{src}"></script>'
Returns
str: The runtime's URL path, such as ``/citry/citry.<hash>.js``.
Raises
RuntimeError- If no web integration is mounted, because the URL would point nowhere.Exception- Any error the cache backend raises when it cannot store the runtime.
get_component_by_class_id function
Look up a registered component class by its class_id.
class_id is the stable identifier (MyComp.class_id) used in cache keys and script URLs. Raises KeyError when no registered class has that id.
Raises
KeyError- If no registered component has this class ID.CitryLifecycleInProgress- If another thread is changing component lifecycle state.
get_components_for_file function
The component classes whose assets resolved to path.
Most callers want invalidate_file(), which both finds these classes and resets them. This lower-level lookup is for a caller that wants the classes without resetting (a custom hot-reload handler, a test). Dead weakrefs are pruned on read.
invalidate_file function
Drop cached template/JS/CSS for every component that loaded an asset from path, so the next render re-reads it from disk.
Returns the component classes it reset. An empty list means the file backs no loaded component, which a hot-reload handler can read as "not mine" and, if it wants, fall through to a full restart. This is the call a file watcher makes, whatever web framework hosts the app; see Hot reload during development for the built-in watchers.
invalidate_all function
Reset cached template/JS/CSS for every component that has loaded a file, so the next render re-reads them all from disk. Returns the reset classes (in first-seen order).
For when a change cannot be mapped to a single path: a bulk edit, a branch switch, or a custom watcher reporting an event it cannot resolve to one file. Unlike clear(), this leaves the registry and autodiscovery untouched.
clear function
clear() -> NoneClear registrations and caches, and re-arm autodiscovery.
Raises
CitryLifecycleInProgress- If another thread is changing component lifecycle state.RuntimeError- If called from another lifecycle operation on this thread.
citry module
The Citry global instance - scopes all component state.
A Citry instance owns a component registry, settings, and transient rendering state. Every Component subclass is assigned to a Citry instance, either by declaring citry = my_citry in its class body or by using the default instance.
Example
Using the default instance (most common)::
from citry import Component class MyTable(Component): template = "<table>...</table>"Using a custom instance::
from citry import Citry, Component my_citry = Citry() class MyTable(Component): citry = my_citry template = "<table>...</table>"Isolated instances for testing::
def test_my_component(): test_citry = Citry() # Components registered here don't leak to other tests class MyTable(Component): citry = test_citry template = "..."
AlreadyRegistered class
Bases: Exception
Raised when registering a component under a name that is already taken.
NotRegistered class
Bases: Exception
Raised when looking up a component name that is not registered.
CitryLifecycleInProgress class
Bases: RuntimeError
Raised when another thread is changing Citry's component lifecycle state.
Component discovery, registration, built-in creation, and clearing publish related state together. A competing thread receives this error rather than observing an incomplete registry or waiting in a way that can deadlock with Python's module-import locks.
One case waits instead: when a render or component lookup needs the Citry instance's one-time setup (discovery and built-in creation) while another thread runs it, it waits for that setup to finish. A thread that is importing a module, or running a reset, still receives this error, because the setup may be waiting for that import or for the locks the reset holds; so does a wait that lasts over a minute. Finish Citry.initialize() before starting request threads to avoid both this error and that wait during normal server operation. An operation that encounters it may also be retried after the active lifecycle operation finishes.
CitrySettings class
Immutable settings for a Citry instance.
Every security mode is enforced during serialization. The defaults preserve established output; restrictive JavaScript modes inventory, omit, or reject client behavior without changing render-cache data.
Experimental
The
event_result_resolversandevent_payload_codecssettings are experimental. What a resolver or a codec receives and returns may change in a minor release without a deprecation period.
Attributes
extensionsSequence[type[Extension] | Extension | str]- The extensions to install on the instance. Each entry is anExtensionsubclass, a ready-made instance, or an import string like"myapp.extensions.MyExtension". The set is fixed once the instance is constructed.extensions_defaultsMapping[str, Mapping[str, Any]]- Default config values for extensions, keyed by extension name, e.g.{"events": {"_csrf": True}}. When an extension reads a config field for a component, the component's own nested config class wins, a value given here fills in next, and the extension's built-in default comes last.dirstuple[Path, ...]- Directories searched when resolving a component's asset files (template_file,js_file,css_file, andDependenciesentries), after the directory of the component's own.pyfile. Entries are converted toPathand must be absolute; this is validated at construction (a relative entry raisesValueError).cacheCitryCache | str | None- Where citry stores what it caches: aCitryCacheobject or an import string like"myapp.caching.MyCache".Nonegives the instance its own in-memory cache. The live backend built from this setting isCitry.cache.sandbox_expressionsbool- Whether template expressions ({{ ... }}and dynamicc-*attributes) are evaluated in the security sandbox. On by default. Turning it off evaluates expressions as plain Python, which is faster but removes security guardrails. Only do so when every template comes from a trusted source.autodiscoverbool- Whether to import the component modules underdirsthe first time a component is looked up, so their classes register themselves without being imported by hand. On by default; when nodirsare set there is nothing to scan, so the default instance does nothing. The directories must be importable (onsys.path/PYTHONPATH). SeeCitry.autodiscoverandcitry.autodiscovery.modeMode- The build environment,"production"(the default) or"development". In"production", each configured i18n catalog package must ship a valid compiled manifest, written bycitry ext run i18n compile; creating theCitryinstance raisesValueErrorwhen it is missing or does not match."development"turns on three things. Citry reads the Fluent sources directly; if the package also contains a compiled manifest, it must still match the sources, so delete or recompile it after editing translations. Turning a page into HTML issues aRuntimeWarningwhen two elements on it share anid, naming the components that wrote them. And Citry logs a browser console warning when Vue's first render of a part Vue builds in the browser differs from the HTML the server sent. A production page does not load this browser check. An unrecognized value raisesValueErrorat construction. See Development mode.template_globalsMapping[str, Any]- Variables exposed to every component's template without being returned from eachtemplate_data(). They are merged into every component's template variables on render, so a template can reference one directly ({{ site_name }}). A component's owntemplate_datawins when it returns a key of the same name, so globals act as defaults. The value given here is the starting set; the live, editable copy isCitry.template_globals, which is how you add or change a global after the instance exists (including the default instance, created at import before your code runs).lintLintSettings- Template lint severities, analysis-only variables, and the render-time input type check. Runtime globals are discovered fromCitry.template_globalsand do not need to be repeated here.security_cspSecurityCspMode- Content Security Policy check for rendered output. Citry scans the final HTML for raw<script>and<style>elements, inlineon*attributes, andjavascript:URLs."off"skips the check,"warn"keeps the output and emits oneRuntimeWarninglisting what it found, and"strict"raises instead of returning that output.citry checkand the editor also report these problems where a template writes them directly, as a warning with"warn"and an error with"strict"(citry.template.csp-incompatible).security_javascriptSecurityJavascriptMode- JavaScript delivery policy."allow"keeps current behavior,"warn"inventories client requirements,"omit"leaves Citry-managed JavaScript out, and"forbid"rejects rendered subtrees that require executable client behavior.security_script_integritySecurityScriptIntegrityMode- Whether Citry reports script hashes. Under both values, the tags Citry writes for files it serves carryintegrity, so the browser refuses a file with different content."off"reports no hashes."citry"also lists SHA-384 hashes ofScriptobjects, inline ones included, inSerializedSecuritywhen Citry knows their exact content, and raisesTypeErrorfor a ready-made tag, whose content it cannot read.ssrbool- Send each interactive Vue document's content in its HTML. On by default: the server writes the page for Vue to adopt ("hydrate"), and a page it cannot write that way carries Citry's ordinary server HTML, which Vue replaces when it mounts.Falsesends an empty mount element instead, and Vue builds the page in the browser. Noninteractive output is unchanged.ssr_element_thresholdint- Send small pages without their content. A page whose server-written HTML holds this many elements or fewer is sent with an empty mount element and built in the browser, which can be slightly faster for a small page because the browser does not parse the HTML and then hydrate it. The default,0, keeps the content of every page that contains an element, which search engines and readers without JavaScript need. It applies only to pages Vue can adopt; a page Vue replaces always carries its server HTML. Must be a non-negativeint: another type raisesTypeErrorand a negative value raisesValueErrorwhen the settings are created.vue_asset_max_bytesint | None- The most bytes eachCitryinstance keeps in memory, whencacheis not set, for the files that pages fetch by URL: the compiled component code and stylesheets of interactive pages, and the stylesheets thatcss_data()produces on any page. The default is 64 MiB, andNoneremoves the limit. Pages load these files possibly long after they were rendered. When the total grows past this limit, the files used longest ago are dropped, and a page that is still open gets a 404 if it later asks for one of them. The files of a page being written out are never dropped, so the total can exceed the limit by that page's files. Whencacheis set, the files are stored there, this setting has no effect, and the backend's own size limit and rules for dropping entries apply. Must be a positiveintorNone: another type raisesTypeErrorand zero or a negative value raisesValueErrorwhen the settings are created.max_component_depthint- How many components deep a page may nest before rendering stops withRecursionError. The default,2000, is far deeper than real pages nest, so it only stops a component that keeps rendering itself, such as a tree node whose data lists the node among its own children. Without the limit that render would run until the process runs out of memory. The error names the chain of components, and<c-error-fallback>cannot catch it. Must be a positiveint: another type raisesTypeErrorand zero or less raisesValueErrorwhen the settings are created. A component rendered from a{{ ... }}expression or through<c-component>starts a new count. Python's own recursion limit stops that kind of recursion much earlier, with an ordinaryRecursionErrorthat<c-error-fallback>can catch, so avoid wrapping such a recursion in one.model_baseobject-The kind of class Citry generates from every plain schema declaration (
class Kwargs:with annotated fields, and likewiseTemplateData,JsData,CssData,State, and Eventsdataclasses), and a base those classes share.None(the default) generates dataclasses. A Pydantic v2 or v1 model class generates models that subclass it, so itsmodel_configand validators apply, and Pydantic, not Citry, checks the values. A dataclass generates dataclasses that subclass it and copy its options.typing.NamedTuplegenerates named tuples.Statecannot be a named tuple, a frozen dataclass, or a frozen model, because handlers change it. Classes decorated with@dataclass, hand-written models,Slots, Citry's own components, and components from an installed library are kept as written. An import string such as"pydantic.BaseModel"is imported when theCitryinstance is built.Building the settings raises
TypeErrorfor a value of another kind, a named tuple class with fields, a dataclass with its own__init__, a Pydantic dataclass, or a root model. An import string is checked only whenCitryis built:ImportErrorif it cannot be imported,TypeErrorif it names a class of another kind. A component class fails when it is defined if a schema cannot take the kind; see "Share one schema base" in the inputs and validation guide.id_generatorCallable[[], str] | str | None- A function returning the per-render id stamped on each component instance (component.id; static output also writes it into each component root'sdata-cid-<id>attribute). Given as a callable or a"path.to.func"import string; passing a class also works: it is called once, and the resulting object is used as the generator (handy when the generator keeps state, like a counter).Noneuses the built-in generator. Override it for stable ids in snapshot tests. The generator must return ids that are unique among the components on one page and contain only lowercase ASCII letters, digits, hyphens, and underscores. The lowercase rule is required because the id is embedded in an HTML attribute name. This does not touchclass_id, which stays a stable hash of the component's import path.secretstr | list[str] | None- The signing secret for values citry hands to the browser and must recognize when they come back, such as the state the Events extension round-trips on each event call. A single string is the common form. A list means key rotation: the first entry signs new values, and a value signed by any entry still verifies, so already-issued values stay valid while a new key rolls out. A list or a tuple is accepted. Every entry must be a string with at least one character that is not whitespace;Citry(...)raisesValueErrorotherwise, andTypeErrorfor an entry that is not a plainstr. A bare string is stored as a one-element list.None(the default) means no secret is set. Django projects can reuseSECRET_KEYand anySECRET_KEY_FALLBACKSby passingcitry.contrib.django.secret().event_result_resolversSequence[Any]- Experimental. Result resolvers for the Events extension. When an event handler returns a value, citry converts it into the actions sent back to the browser (the instructions the client runtime applies: re-render this component, redirect, and so on). A resolver adds support for your own return types: it is given the handler's return value and either converts it into those actions or declines, letting the next resolver try. Resolvers run in order, after the built-in conversions; the first one to convert the value wins.event_payload_codecsSequence[Any]- Experimental. Payload codecs for the Events extension's HTTP endpoints. A codec reads one request format (identified by its content type) into the event call the extension expects, so clients are not limited to the built-in JSON, form, and query formats. Codecs given here are tried before the built-in ones, in order.
security_script_integrity attribute
security_script_integrity: SecurityScriptIntegrityMode LintSettings class
Configure Citry's template and browser lint rules, analysis-only variables, and the render-time input type check.
Raises
TypeError- If a variable or global collection is not a mapping, orcheck_input_typesorinclude_librariesis not abool.ValueError- If a severity or variable name is invalid.
Attributes
rule_unknown_template_variableLintSeverity- Severity for a free template root that is absent from the proven component namespace. The default is"error". A schema that explicitly allows extra fields caps this rule at"warning".rule_i18n_missing_param_typeLintSeverity- Severity for a translation message variable that has no@paramcomment giving its type, when the variable is used only as plain text on the server. Variables used in a selector, a formatting function, a browser call, or as aSlotalways need a type, whatever this setting says. The default is"warning".template_variablesMapping[str, object]- Extra variables known to template analysis but not injected at runtime. Values are annotations. UseAnnotated[T, "description"]to attach concise documentation.rule_unknown_vue_variableLintSeverity- Severity for a free Vue-expression root absent from the component's proven browser scope. The default is"error".vue_variablesMapping[str, object]- Extra variables or custom Vue magics known only to browser analysis. Values use the same annotation convention astemplate_variables.rule_unknown_component_js_variableLintSeverity- Severity for a free variable used inside a$componentinitializer. The default is"error".component_js_globalsMapping[str, object]- Extra globals available to component JavaScript analysis. Values use the same annotation convention astemplate_variables.rule_unknown_component_js_memberLintSeverity- Severity for athis.<name>orcomponent.<name>read in component JavaScript that the component instance does not have. The default is"error".rule_vue_python_variableLintSeverity- Severity for a Vue expression that reads a name bound in Python by an enclosingc-forloop orc-fillbinding. The browser looks that name up in Vue state, not in the Python loop. The default is"warning".rule_alpine_attributeLintSeverity- Severity for an Alpinex-*attribute, such asx-dataorx-on:click, on an HTML element. Citry uses Vue, so nothing reads the attribute. Set"ignore"when another library on the page readsx-*attributes. The default is"warning".rule_alpine_cloakLintSeverity- Severity forx-cloakon an HTML element. Nothing in Citry removes the attribute, so a[x-cloak]CSS rule keeps the element hidden. The default is"error".rule_invalid_attribute_valueLintSeverity- Severity for a static HTML attribute value outside the keywords that attribute accepts, such asdraggable="treu"or<input type="datetime">, or for a boolean attribute with a value other than its own name, such asdisabled="false", which still disables the element. For an enumerated value, the browser ignores it or falls back to a default. The default is"error".citry check --staticand an editor that has not loaded the application report it as a warning, because they cannot read your settings.rule_i18n_cross_language_fallbackLintSeverity- Severity for atr()call, aself.i18n.tr()call, or a message inI18n.client_messagesthat has no translation in some locale, so that locale shows text from a fallback language. The page still renders, but the text cannot mark its own language. Set"error"to require complete translations. A<c-trans>message is always an error, because rendering it in another language fails. The default is"warning".rule_misspelled_directiveLintSeverity- Severity for ac-*attribute on an HTML element or custom element that looks like a misspelled Citry directive, such asc-iffforc-if, orc-show, which Citry writes asc-if. Citry renders it as an ordinary attribute, so the directive never runs; withc-iffthe element always shows up. An attribute of the element, such asc-id, is not reported. It also covers av-*name that looks like a misspelled Vue directive, such asv-iff, which Vue looks up as a custom directive, so the page fails in the browser. The default is"error".rule_misspelled_attributeLintSeverity- Severity for an attribute on an HTML element that is one typing slip from an attribute the element accepts, such astitelfortitle. The browser ignores it. The default is"error".rule_misspelled_elementLintSeverity- Severity for a lowercase tag that is one typing slip from an HTML element, such as<dvi>. The default is"error".rule_unknown_aria_attributeLintSeverity- Severity for anaria-*attribute that WAI-ARIA does not define, such asaria-expandd. Browsers and screen readers ignore it. The default is"error".rule_invalid_nestingLintSeverity- Severity for an element that the browser moves out of an open<p>, such as<div>inside<p>. The default is"error".rule_duplicate_idLintSeverity- Severity for a literalidthat two elements of one template always render. The default is"error".rule_missing_image_altLintSeverity- Severity for an<img>with noalttext. The default is"warning".rule_invalid_model_targetLintSeverity- Severity forv-modelon an element that holds no value, such as<form>, which fails when Vue compiles the page. The default is"error".rule_misspelled_eventLintSeverity- Severity for a listener on an HTML element whose event name is one typing slip from a DOM event, such as@clik. The listener never runs. The default is"warning".rule_invalid_vue_expressionLintSeverity- Severity for a Vue expression, such as the value ofv-ifor@click, that is not valid JavaScript, which fails when Vue compiles the page. The default is"error".rule_vue_compile_errorLintSeverity- Severity for anything else Vue's compiler rejects in a template, such as a<div>directly inside a<table>, a<button>inside a<button>, or av-elsewith nov-ifbefore it. A component that uses Vue fails to render. The default is"error".rule_undeclared_component_eventLintSeverity- Severity for a listener on a component tag for an event the child component does not declare inemits, such as@hdieforhide. The listener usually never runs.citry checkreports it only with your application loaded. The default is"warning".rule_missing_component_keyLintSeverity- Severity for a component that<c-for>repeats without a#c-keyon a page that uses Vue, which fails to render once the loop has two items.citry checkreports it only with your application loaded. The default is"error".rule_prop_assignmentLintSeverity- Severity for a component that assigns to one of its own Vue props, such as@click="open = false"orthis.open = falsein its JavaScript. Props are read-only, so the value does not change.citry checkreports it only with your application loaded. The default is"error".rule_unknown_server_event_fieldLintSeverity- Severity for an@c-*binding that sends a key the handler's data class does not declare, such assave({amont: 1}). The server rejects the call.citry checkand the editor report it only with your application loaded. The default is"error".rule_missing_server_event_fieldLintSeverity- Severity for an@c-*binding that leaves out a field the handler's data class requires. The server rejects the call.citry checkand the editor report it only with your application loaded. The default is"error".rule_incompatible_server_event_fieldLintSeverity- Severity for an@c-*binding that sends a literal value the handler's data class does not accept, such assave({amount: '1'})for anintfield. The server rejects the call.citry checkand the editor report it only with your application loaded. The default is"error".rule_unknown_form_fieldLintSeverity- Severity for a control in a form whose@c-submitsends the form's fields to a server event, when the handler's data class does not declare the control'sname, such as<input name="qeury">for a fieldq. The server rejects each submit that sends the control.citry checkand the editor report it only with your application loaded. The default is"error".rule_missing_form_fieldLintSeverity- Severity for a form whose@c-submitsends its fields to a server event, when no control in it is named after a field the handler's data class requires. It is reported only when the template shows every control the form can send.citry checkand the editor report it only with your application loaded. The default is"error".rule_misspelled_css_variableLintSeverity- Severity for avar(--name)in a component's CSS that is one typing slip from a key itscss_data()returns, such asvar(--acent)foraccent. Nothing sets the property.citry checkreports it only with your application loaded. The default is"warning".rule_misspelled_css_classLintSeverity- Severity for a class in a template's staticclassattribute that is one typing slip (two neighboring letters swapped, one doubled, or one left out) from a class the component's owncssorcss_filestyles, such asbordfor.board. It is reported only when no CSS Citry reads declares the class as written: no registered component's CSS,Dependenciesstylesheet, or template<style>element. Slips that usually name another class of the same family are not reported: a moved, doubled, or dropped digit (col-1for.col-12); a missing finalsafter a letter other thans(tabfor.tabs); one of these short words, as the whole class or as its last word after a hyphen or underscore, next to its longer form:close(closed),collapse(collapsed),disable(disabled),enable(enabled),fade(faded),mute(muted),show(shown),slide(slider), andtoggle(toggledortoggler), as innavbar-togglefor.navbar-toggler; and one letter typed twice or left out in a first hyphen-separated part of one or two characters (p-4for.px-4).citry checkreports it only with your application loaded. The default is"warning".rule_undeclared_css_classLintSeverity- Severity for every class in a template's staticclassattribute that no CSS Citry reads declares: no registered component'scss,css_file, inline or local-fileDependenciesstylesheet, or template<style>element. Classes from a site stylesheet or a CSS framework such as Tailwind, and classes used only by JavaScript or tests, are reported too, so the default is"ignore", which turns the rule off.citry checkreports it only with your application loaded.rule_undeclared_css_variableLintSeverity- Severity for everyvar(--name)without a fallback in a component'scssorcss_filewhen nothing Citry reads sets--name: no registered component's CSS,css_data()key, templatestyleattribute or binding, JavaScript, or Python module. Properties that a site stylesheet, a design system, or a script outside Citry sets are reported too, so the default is"ignore", which turns the rule off.citry checkreports it only with your application loaded.rule_unknown_urlLintSeverity- Severity for a literalhref,src, oractionpath, such as/abuot, that none of your app's routes or static files serves.citry checkand the editor report it only with your application loaded, and only when a web framework integration (citry.contrib.flask.mount(),citry.contrib.fastapi.mount(), orcitry.contrib.django.urlpatterns()) ran while the app loaded. A path another server answers, such as a reverse proxy, is reported too. The default is"warning".rule_unknown_inject_keyLintSeverity- Severity for aself.inject("key")call with a literal key and no default when no provider above the component gives that key. Citry looks for a<c-provide>around the component's tag in the templates that use it, aprovide()call in the components above it or in the component whose<c-slot>shows it, and a literal key in arender(provides={...})call in your project. When no template uses the component, Citry compares the key with every key the app provides. A key passed only in aprovidesdictionary built elsewhere, or provided by a helper function, is reported too, so the default is"warning".citry checkand the editor report it only with your application loaded.check_input_typesbool- Check that each value a component receives has the type its annotation names. On by default, in development and in production. Unlike therule_*settings, this check runs when a component renders, not incitry checkor the editor. Citry compares each field of the component'sKwargs,TemplateData,JsData,CssData, andStatewith the field's annotation and raisesTypeErrorfor a value of the wrong type, soCard(title=123)againsttitle: strfails with a message that names the component, the field, the expected type, and the value. Only the outer type is checked:list[str]accepts anylist. A field's own default always passes. Annotations Citry cannot test while the page runs, such asAny, a type variable, or a name imported only for type checkers, are not checked, and Pydantic models and dataclasses that write their own__init__keep their own rules. Inputs and validation lists what each annotation accepts. A component overrides this for itself withcheck_input_typesin its nestedLintclass.include_librariesbool- Whethercitry checkalso reports findings in the components of a library you registered withregister_library(), such as Citry UI. Off by default: you cannot change a library's code, socitry checkleaves those findings out of the report and the exit status, and prints how many it left out. Set it toTrue, or passcitry check --include-libraries, to report them, for example in the library's own tests. A finding is left out only when every component it belongs to comes from a library, so a finding in your subclass of a library component, including one in the code it inherits, is reported. The editor ignores this setting and checks every file you open.
rule_unknown_component_js_variable attribute
rule_unknown_component_js_variable: LintSeverity rule_unknown_component_js_member attribute
rule_unknown_component_js_member: LintSeverity rule_i18n_cross_language_fallback attribute
rule_i18n_cross_language_fallback: LintSeverity rule_incompatible_server_event_field attribute
rule_incompatible_server_event_field: LintSeverity CitryCache class
Bases: Protocol
The cache backend interface.
Implement these four methods to plug in any store (Redis, diskcache, Django's cache framework, ...). Keys and values are strings.
set function
Store value under key. ttl is seconds until expiry; None means keep forever.
InMemoryCache class
The default cache backend: a thread-safe store inside the current process.
Unbounded by default for ordinary entries. Pass max_entries to cap them; when full, the entry that was read or written longest ago is dropped to make room. An entry written with a ttl is removed once it expires, at the next write, even when nothing reads its key again.
Server-stored Events State (keys that start with citry:state:) is kept apart, under its own budget of state_max_bytes (64 MiB by default), and does not count toward max_entries. When the budget is full, the State entry read or written longest ago is dropped, so many State writes cannot push out page assets. A dropped entry makes that visitor's next call answer stale_state, and the page offers a reload. An entry larger than the whole budget is not stored, and Citry logs a warning. state_max_bytes=None removes the budget.
Single-process only: each instance is its own store. With several worker processes, a page rendered by one worker can link a generated Vue bundle or css_data() stylesheet that another worker then answers with a 404, so use a shared backend such as RedisCache or DjangoCache instead.
Raises
ValueError- Whenmax_entriesorstate_max_bytesis not a positiveintorNone.
CitryDeprecationWarning class
Bases: DeprecationWarning
Warn that your code uses a Citry feature that will be removed.
Citry uses this class for every deprecation warning: when you call a deprecated function, pass a deprecated argument, or set a deprecated setting. The warning names the line in your code that used the feature and says what to use instead. From 1.0.0 on, a deprecated feature keeps working, and keeps warning, for at least two minor releases and at least three months, and is removed only in a major release.
It is a subclass of DeprecationWarning, so Python shows it by default only in code run as __main__ and under test runners such as pytest. A web server started some other way does not show it. Turn it into an error in your tests to find every use before you upgrade.
Example
# pyproject.toml [tool.pytest.ini_options] filterwarnings = [ "error::citry.CitryDeprecationWarning", ]