A utility package for Caspian projects
Project description
Caspian Utils (casp)
HTML-first utilities for Caspian applications.
caspian-utils is the shared Python runtime package behind Caspian templates, components, layouts, RPC handlers, and supporting utilities. This repository is not a full application starter, so this README documents the package surface that exists here.
- PyPI package:
caspian-utils - Python package:
casp - Python requirement:
>=3.14
Installation
pip install caspian-utils
Core Model
Caspian is HTML-first.
- write UI in
.html - use native Jinja syntax for server-rendered values and control flow
- define reusable components in Python
- import components with
@importcomments inside HTML - render components with
<x-component-name />tags - place child routes in layouts with a real HTML
<slot /> - render pages and layouts from Python with helpers in
casp.layout
There is no Caspian-only template syntax layer. Use standard Jinja {{ ... }} and {% ... %} directly.
HTML-First Components
Define a component in Python
from casp.component_decorator import component
@component
def AlertBox(title: str, children: str = "", class_name: str = "") -> str:
return f"""
<section class="alert {class_name}">
<h2>{title}</h2>
<div>{children}</div>
</section>
"""
Import and use it in HTML
<!-- @import { AlertBox } from "../components/ui" -->
<main class="space-y-4">
<x-alert-box title="Saved">
<p>Your settings were updated.</p>
</x-alert-box>
</main>
Alias imports when needed
<!-- @import { AlertBox as Notice } from "../components/ui" -->
<div>
<x-notice title="Heads up" />
</div>
Import and tag rules:
AlertBoxbecomes<x-alert-box>- aliases also convert to kebab-case, so
Noticebecomes<x-notice> - grouped imports use
<!-- @import { A, B as C } from "..." --> - single imports use
<!-- @import ComponentName from "..." --> - paths are resolved relative to the current template or component directory
Example: <!-- @import { AlertBox } from "../components/ui" --> resolves AlertBox from ../components/ui/AlertBox.py.
Rendering Pages
Use casp.layout to render HTML templates relative to a Python file.
from casp.layout import render_page
def get_dashboard() -> str:
return render_page(__file__, {
"pageTitle": "Dashboard",
"stats": ["Projects", "Tasks", "Alerts"],
})
<!-- app/dashboard/index.html -->
<!-- @import { AlertBox } from "../components/ui" -->
<main class="space-y-6">
<h1>{{ pageTitle }}</h1>
<x-alert-box title="Welcome back" class="rounded border p-4">
<p>Rendered through an imported Python component.</p>
</x-alert-box>
<ul>
{% for label in stats %}
<li>{{ label }}</li>
{% endfor %}
</ul>
</main>
casp.layout also exposes render_layout(), render(), load_template(), compile_template(), and layout discovery helpers for nested layout flows.
Nested Layouts
Layouts are authored as HTML and use a real <slot /> element as the child-route outlet.
<!-- app/layout.html -->
<html>
<head>
<title>{{ metadata.title }}</title>
</head>
<body>
<slot />
</body>
</html>
During nested layout rendering, Caspian parses the layout HTML and replaces real <slot> elements with the current child page or nested layout. Escaped documentation text such as <slot /> is not treated as a layout outlet.
If a layout needs shared props or metadata, add a sibling layout.py:
from casp.layout import Metadata
metadata = Metadata(title="Dashboard")
def layout():
return {
"shell_class": "dashboard-shell",
}
Those props are available in layout.html as {{ layout.shell_class }}. The installed layout runtime supports sync or async layout() results, but layout work should stay focused on shared subtree props or metadata.
Template Syntax
Caspian templates use native Jinja:
{{ value }}for interpolation{% if condition %}...{% endif %}for conditionals{% for item in items %}...{% endfor %}for loops- filters such as
{{ children | safe }}
There is no additional Caspian template language on top of Jinja.
Template Constraints
Some compiler rules are important when writing templates:
- every page, layout, and component must render exactly one top-level HTML element
- unknown
<x-...>tags raise an error unless the component has been imported - async components are supported by the component pipeline
- authored PulsePoint scripts should be plain
<script>tags inside the single root; the runtime can rewrite them for browser execution
These constraints exist because Caspian injects pp-component metadata into the rendered root element.
RPC Helpers
The package also includes the server-side RPC decorator and related request/serialization utilities.
from casp.rpc import rpc
@rpc(require_auth=True, limits="30/minute")
async def save_profile(name: str):
return {"ok": True, "name": name}
casp.rpc includes:
- RPC registration
- auth-aware decorators
- rate limiting
- serialization for common Python objects
- FastAPI-oriented request and response helpers
Auth Policy
casp.auth provides the framework runtime for sessions, route checks, decorators, CSRF helpers, and OAuth providers. Application auth policy should live in an app-owned src/lib/auth/auth_config.py file, where the app builds AuthSettings and applies them during startup with configure_auth(...).
Keep route privacy, redirects, and RBAC policy in that app config file instead of changing casp.auth.
Main Modules
| Module | Purpose |
|---|---|
casp.layout |
Load, compile, and render pages and nested layouts with native Jinja and parser-based <slot /> replacement |
casp.html_native |
BeautifulSoup-backed fragment parsing helpers used by layout and component transforms |
casp.component_decorator |
@component, component loading, and HTML rendering helpers |
casp.components_compiler |
Parse @import directives and transform <x-...> component tags |
casp.html_attrs |
Attribute rendering, prop alias normalization, and Tailwind class merge helpers |
casp.scripts_type |
Rewrite authored PulsePoint scripts for browser runtime execution |
casp.rpc |
RPC decorator, registration, serialization, and request handling helpers |
casp.streaming |
Server-Sent Events helpers including SSE |
casp.auth |
Auth settings, session helpers, decorators, OAuth providers, and route checks |
casp.runtime_security |
Safe public-file serving, security headers, and production secret checks |
casp.cache_handler |
Page cache helpers |
casp.state_manager |
Request-scoped and session-backed state helpers |
casp.validate |
Validation and sanitization helpers for strings, IDs, files, dates, and numbers |
casp.caspian_config |
Config loading and file index helpers |
Included Dependencies
This release currently installs utilities commonly used by Caspian apps, including:
fastapijinja2beautifulsoup4slowapipython-multiparthttpxcuid2python-ulid
See setup.py for the pinned versions in this release.
Repository
TheSteelNinjaCode/caspian_utils
License
MIT
Author
Jefferson Abraham
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file caspian_utils-0.3.6.tar.gz.
File metadata
- Download URL: caspian_utils-0.3.6.tar.gz
- Upload date:
- Size: 51.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a6d92e28f296e9b581b8ba48a826f9ebf25089c7057d92a43120d75c9d5f3dd3
|
|
| MD5 |
995173f2dd7fc2d489d341daab0d460c
|
|
| BLAKE2b-256 |
0130b38978809fd5f35403a5f2340457211a3bbc3933d55510e110b7d36cc3fb
|
File details
Details for the file caspian_utils-0.3.6-py3-none-any.whl.
File metadata
- Download URL: caspian_utils-0.3.6-py3-none-any.whl
- Upload date:
- Size: 53.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f937e9aa9ba3f8e1f0f55b7aadec4ff77e9f7e97573efcf26acf9b68284389bf
|
|
| MD5 |
ec945857486071e6ce4a0aaffe12ede3
|
|
| BLAKE2b-256 |
659ea46b7d05f4c1e9122175f9099847d4a41d09c17e9e68f91fa27c20e7b324
|