# RustyTags
โ ๏ธ **Early Beta** - This library is in active development and APIs may change.
A high-performance HTML generation library that provides a Rust-based Python extension for building HTML/SVG tags. RustyTags offers significant speed improvements over pure Python HTML generation libraries through memory optimization and Rust-powered performance, featuring FastHTML-style syntax, comprehensive Datastar integration, and full-stack web development utilities.
## What RustyTags Does
RustyTags generates HTML and SVG content programmatically with:
- **Speed**: Rust-powered performance with memory optimization and caching
- **Modern Syntax**: FastHTML-style callable chaining with minimal performance overhead
- **Automatic Mapping Expansion**: Dictionaries automatically expand as tag attributes
- **Datastar Integration**: Complete reactive web development with shorthand attributes and server-sent events
- **Full-Stack Utilities**: Page templates, decorators, async backends, and event handling
- **Type Safety**: Smart type conversion for Python objects (booleans, numbers, strings)
- **Framework Integration**: Supports `__html__`, `_repr_html_`, and `render()` methods
- **Advanced Features**: Custom tags, attribute mapping, complete HTML5/SVG support
## Quick Start
### Installation
```bash
# Install from PyPI (recommended)
pip install rusty-tags
# For development/customization - build from source
git clone <repository>
cd rustyTags
maturin develop
```
### FastAPI Full-Stack Application Example
Here's a complete reactive web application demonstrating RustyTags' CQRS (Command Query Responsibility Segregation) capabilities with real-time server-sent events:
```python
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from rusty_tags import *
from rusty_tags.utils import create_template
from rusty_tags.datastar import DS, signals
from rusty_tags.backend import on_event, send_stream, process_queue, event
from datastar_py.fastapi import datastar_response, ReadSignals, ServerSentEventGenerator as SSE
from datastar_py.consts import ElementPatchMode
import asyncio
# Setup page template with UI framework (Franken UI in this example)
hdrs = (
Link(rel='stylesheet', href='https://cdn.jsdelivr.net/npm/franken-ui@2.1.0/dist/css/core.min.css'),
Script(src='https://cdn.jsdelivr.net/npm/franken-ui@2.1.0/dist/js/core.iife.js', type='module'),
)
page = create_template(hdrs=hdrs, htmlkw=dict(cls="bg-background"), bodykw=dict(cls="p-16"))
app = FastAPI()
# Reusable UI component with automatic mapping expansion
def Section(title, *content):
return Div(
H2(title, dict(cls="uk-h2 mb-4")), # Mapping expansion in action!
Div(*content, cls="border rounded-md p-4"),
cls="my-4 max-w-md"
)
# QUERY side: Main application page
@app.get("/")
@page(title="Reactive FastAPI App", wrap_in=HTMLResponse)
def index():
return Main(
Section("Server Event Updates Demo ๐",
Form(
Input(
placeholder="Send message and press Enter",
type="text",
bind="message",
cls="uk-input"
),
# COMMAND: Trigger server-side event processing
on_submit=DS.get("/queries/user", contentType="form")
),
Div(id="updates") # Real-time updates container
),
signals=signals(message=""), # Client state
on_load=DS.get("/updates") # Connect to SSE stream
)
# Event system setup for CQRS pattern
events_signal = event("events")
results_queue = asyncio.Queue()
# COMMAND side: Process user actions
@app.get("/queries/{sender}")
async def queries(sender: str, request: Request, signals: ReadSignals):
"""COMMAND: Trigger events and process user inputs"""
send_stream(events_signal, sender, results_queue,
signals=signals, request=request)
# QUERY side: Real-time updates stream
@app.get("/updates")
@datastar_response
async def event_stream(request: Request, signals: ReadSignals):
"""QUERY: SSE endpoint for real-time UI updates"""
return process_queue(results_queue)
# Event handlers: Business logic with HTML responses
@on_event("events", sender="user")
def notify(sender, request: Request, signals: dict | None):
"""Process user message and return HTML updates"""
message = (signals or {}).get("message", "No message provided")
# Execute client-side notification
yield SSE.execute_script(f"UIkit.notification({{message: '{message}'}})")
# Update UI with new content (using mapping expansion)
yield SSE.patch_elements(
Div(f"Server processed: {message}", dict(cls="text-lg font-bold mt-2")),
selector="#updates",
mode=ElementPatchMode.APPEND
)
# Reset form state
yield SSE.patch_signals({"message": ""})
# Additional event handlers can be added easily
@events_signal.connect
def log_messages(sender, request: Request, signals: dict | None):
message = (signals or {}).get("message", "")
print(f"๐ Message logged: {message}")
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
```
**Key Features Demonstrated:**
- **๐ Mapping Expansion**: `dict(cls="...")` automatically becomes `cls="..."`
- **๐๏ธ CQRS Pattern**: Separate command (`/queries`) and query (`/updates`) endpoints
- **โก Real-time Updates**: Server-sent events with automatic HTML patching
- **๐จ Framework Integration**: Works seamlessly with any CSS framework
- **๐ Reactive State**: Client-server state synchronization
- **๐ก Event-Driven**: Scalable event handling with multiple subscribers
### Simple Usage Examples
```python
from rusty_tags import Div, P, A, Button, Input
from rusty_tags.datastar import signals, DS
# Basic HTML generation with mapping expansion
content = Div(
P("Hello World", dict(cls="greeting", id="welcome")),
Button("Click me", dict(type="button", disabled=False)),
cls="container"
)
print(content)
# <div class="container"><p class="greeting" id="welcome">Hello World</p><button type="button">Click me</button></div>
# Reactive component with Datastar
counter = Div(
P(text="$count", cls="display"),
Button("+", on_click="$count++"),
Button("-", on_click="$count--"),
signals=signals(count=0)
)
# Advanced actions with DS utilities
form = Div(
Input(bind="$email", placeholder="Email"),
Button("Submit", on_click=DS.post("/api/submit", data="$email")),
signals=signals(email="")
)
```
## Features
### ๐ Automatic Mapping Expansion
RustyTags now automatically expands Python dictionaries passed as positional arguments into tag attributes:
```python
# Before: Manual unpacking required
Div("Content", **{"id": "main", "class": "container", "hidden": False})
# Now: Automatic expansion!
Div("Content", dict(id="main", class_="container", hidden=False))
# Output: <div id="main" class="container">Content</div>
# Works with any mapping type and combines with regular kwargs
attrs = {"data-value": 123, "title": "Tooltip"}
Div("Text", attrs, id="element", cls="active")
# Output: <div data-value="123" title="Tooltip" id="element" class="active">Text</div>
```
**Key Features:**
- **Automatic Detection**: Any dict in positional args is expanded as attributes
- **Type Preservation**: Booleans, numbers, strings handled correctly
- **Datastar Compatible**: `ds_` attributes and reactive `cls` dicts preserved
- **Performance Optimized**: Zero overhead expansion at the Rust level
### ๐๏ธ CQRS (Command Query Responsibility Segregation) Architecture
RustyTags enables clean separation of commands and queries for scalable reactive applications:
```python
# COMMAND side: Handle user actions
@app.post("/commands/user/{action}")
async def handle_command(action: str, request: Request, signals: ReadSignals):
"""Process user commands and trigger events"""
send_stream(user_events, action, updates_queue,
signals=signals, request=request)
# QUERY side: Real-time UI updates
@app.get("/queries/updates")
@datastar_response
async def query_updates(request: Request):
"""Stream UI updates based on processed events"""
return process_queue(updates_queue)
# Event handlers: Business logic with HTML responses
@on_event("user_events", sender="create_todo")
def create_todo_handler(sender, signals: dict, **kwargs):
# Business logic
todo = create_todo(signals.get("todo_text"))
# Return HTML update
yield SSE.patch_elements(
TodoItem(todo, dict(id=f"todo-{todo.id}")),
selector="#todo-list",
mode=ElementPatchMode.APPEND
)
```
**CQRS Benefits:**
- **๐ Commands**: Separate endpoints for state-changing operations
- **๐ Queries**: Dedicated streams for real-time UI updates
- **๐ Event-Driven**: Loose coupling between commands and UI updates
- **๐ Scalable**: Event handlers can be distributed across services
- **๐งช Testable**: Clear separation of concerns and business logic
### ๐ Full-Stack Web Development Utilities
**Page Templates & Decorators:**
```python
from rusty_tags.utils import Page, create_template
# Production-ready page template
page = create_template(
"My App",
hdrs=(
Meta(charset="utf-8"),
Meta(name="viewport", content="width=device-width, initial-scale=1"),
Link(rel="stylesheet", href="/static/app.css")
),
datastar=True
)
@page(title="Dashboard")
def dashboard():
return Main(
Section("Analytics", dict(role="main", cls="dashboard")),
Nav(A("Home", href="/"), A("Settings", href="/settings"))
)
```
**Async Backend Integration:**
```python
from rusty_tags.backend import on_event, send_stream, process_queue
import asyncio
# Multi-subscriber event system
@on_event("user_action", sender="notification")
async def send_notification(sender, **data):
yield Div(f"๐ฌ {data['message']}", cls="notification")
@on_event("user_action", sender="analytics")
async def track_analytics(sender, **data):
# Log to analytics service
print(f"๐ Event tracked: {data}")
```
### Datastar Reactive Integration
- **Shorthand Attributes**: Clean syntax with `signals`, `bind`, `show`, `text`, `on_click`, etc.
- **Action Generators**: Built-in `DS` class for common patterns (`DS.post()`, `DS.get()`, etc.)
- **Backward Compatible**: Full support for `ds_*` prefixed attributes
- **Event Handling**: Comprehensive `on_*` event attribute support
- **State Management**: Built-in signals, computed values, and effects
- **Server-Sent Events**: Full SSE support with `datastar-py` integration
- **Performance Optimized**: Zero overhead for Datastar attribute processing
### FastHTML-Style Callable API
- **Chainable Syntax**: Support for `Div(cls="container")(children...)` patterns
- **Flexible Composition**: Mix traditional and callable styles seamlessly
- **Performance Optimized**: Minimal overhead (6-8%) for callable functionality
- **Smart Returns**: Empty tags return callable builders, populated tags return HTML
### Performance Optimizations
- **Memory Pooling**: Thread-local string pools for efficient memory reuse
- **Lock-free Caching**: Global caches for attribute and tag name transformations
- **String Interning**: Pre-allocated common HTML strings
- **SIMD Ready**: Optimized for modern CPU instruction sets
- **Stack Allocation**: SmallVec for small collections to avoid heap allocation
### Smart Type Conversion
- **Automatic Type Handling**: Booleans, integers, floats, strings
- **Framework Integration**: `__html__()`, `_repr_html_()`, `render()` method support
- **Attribute Mapping**: `cls` โ `class`, `_for` โ `for`, etc.
- **Error Handling**: Clear error messages for unsupported types
### HTML Features
- **All Standard Tags**: Complete HTML5 tag set with optimized generation
- **Automatic DOCTYPE**: Html tag includes `<!doctype html>`
- **Custom Tags**: Dynamic tag creation with any tag name
- **Attribute Processing**: Smart attribute key transformation and value conversion
## API Features & Architecture
RustyTags provides clean, intuitive APIs with multiple styles and full-stack capabilities:
```python
# Traditional style with mapping expansion
from rusty_tags import Div, P, Input, Button
content = Div(
P("Text", dict(class_="highlight", data_id="p1")),
cls="container"
)
# FastHTML-style callable chaining
content = Div(cls="container")(P("Text", _class="highlight"))
# Full-stack reactive application
from rusty_tags.datastar import signals, reactive_class, DS
from rusty_tags.backend import on_event
from rusty_tags.utils import Page, create_template
# Backend event handler
@on_event("todo_updated")
async def handle_todo_update(sender, **data):
# Return HTML update
yield Div(f"Todo {data['id']} updated!", cls="notification")
# Interactive todo application
def todo_app():
return Page(
Div(
Input(
type="text",
bind="$newTodo",
placeholder="Add todo...",
on_keyup="event.key === 'Enter' && $addTodo()"
),
Button("Add", on_click="$addTodo()"),
Div(
# Dynamic todo list
show="$todos.length > 0",
effect="console.log('Todos updated:', $todos)"
),
signals=signals(
newTodo="",
todos=[]
),
cls="todo-app"
),
title="Todo App",
datastar=True
)
# Page template decorator
template = create_template("My App", datastar=True)
@template.page("Dashboard")
def dashboard():
return Div("Welcome to dashboard!", dict(role="main", cls="dashboard"))
```
### ๐ฆ **Module Structure**
**Core Engine (`rusty_tags.*`):**
- High-performance Rust-based HTML/SVG tag generation
- Automatic mapping expansion and type conversion
- FastHTML-style callable syntax support
**Datastar Integration (`rusty_tags.datastar`):**
- Shorthand attribute support and action generators
- Server-sent events with `datastar-py` integration
- Reactive state management utilities
**Full-Stack Utilities (`rusty_tags.utils`):**
- Page templates and layout management
- Function decorators for view composition
- IPython/Jupyter integration with `show()`
**Async Backend (`rusty_tags.backend`):**
- Event-driven architecture with Blinker signals
- Async SSE streaming and queue processing
- Concurrent event handler execution
## Datastar Integration
RustyTags provides comprehensive Datastar support for building reactive web applications:
### Shorthand Attributes
All Datastar attributes support clean shorthand syntax:
```python
# Before (still supported)
Div(ds_signals={"count": 0}, ds_show="$visible", ds_on_click="$increment()")
# After (new shorthand)
Div(signals={"count": 0}, show="$visible", on_click="$increment()")
```
### Supported Datastar Attributes
**Core Attributes:**
- `signals` โ `data-signals` - Component state management
- `bind` โ `data-bind` - Two-way data binding
- `show` โ `data-show` - Conditional visibility
- `text` โ `data-text` - Dynamic text content
- `attrs` โ `data-attrs` - Dynamic attributes
- `data_style` โ `data-style` - Dynamic styling
**Event Attributes:**
- `on_click`, `on_hover`, `on_submit`, `on_focus`, `on_blur`
- `on_keydown`, `on_change`, `on_input`, `on_load`
- `on_intersect`, `on_interval`, `on_raf`, `on_resize`
**Advanced Attributes:**
- `effect` โ `data-effect` - Side effects
- `computed` โ `data-computed` - Computed values
- `ref` โ `data-ref` - Element references
- `indicator` โ `data-indicator` - Loading states
- `persist` โ `data-persist` - State persistence
- `ignore` โ `data-ignore` - Skip processing
### Complete Example
```python
from rusty_tags import Div, Button, Input, Span
from rusty_tags.datastar import signals, reactive_class, DS
# Interactive counter with Datastar
counter_app = Div(
Span(text="$count", cls="display"),
Div(
Button("-", on_click="$count--"),
Button("+", on_click="$count++"),
Button("Reset", on_click=DS.set("count", 0)),
cls="controls"
),
Input(
type="range",
bind="$count",
attrs={"min": "0", "max": "100"}
),
signals={"count": 50},
effect="console.log('Count changed:', $count)",
cls="counter-app"
)
```
## Performance
RustyTags significantly outperforms pure Python HTML generation:
- 3-10x faster than equivalent Python code
- Optimized memory usage with pooling and interning
- Aggressive compiler optimizations in release builds
## Development Status
๐ง **Early Beta**: While the core functionality is stable and tested, this library is still in early development. Breaking changes may occur in future versions. Production use is not recommended yet.
### Current Features โ
- **Core Engine**: All HTML5 and SVG tags with Rust performance
- **Mapping Expansion**: Automatic dict-to-attributes expansion
- **Callable API**: FastHTML-style chainable syntax
- **Datastar Integration**: Complete reactive web development stack
- **Full-Stack Utilities**: Page templates, decorators, async backends
- **Event System**: Blinker-based event handling with async support
- **Server-Sent Events**: Real-time updates with datastar-py integration
- **Type Safety**: Smart type conversion and attribute mapping
- **Performance**: Memory optimization, caching, and Rust-powered speed
- **Custom Tags**: Dynamic tag creation and framework integration
### Planned Features ๐
- **Template Engine**: Jinja2/Mako integration for server-side rendering
- **Streaming HTML**: Chunked response generation for large documents
- **PyPI Distribution**: Official package releases and versioning
- **Developer Tools**: Hot reload, debugging utilities, and performance profilers
### Dependencies & Integration
**Core Dependencies:**
- `datastar-py`: Official Datastar Python SDK for SSE and attributes
- `blinker`: Signal/event system for backend event handling
- `maturin`: Rust-Python build system for performance-critical code
**Framework Integration:**
- **FastAPI**: Native async support with SSE streaming
- **Flask**: Compatible with Jinja2 templates and request contexts
- **Django**: Template integration and ORM query rendering
- **IPython/Jupyter**: Built-in `show()` function for notebook display
- **Starlette**: ASGI compatibility with streaming responses
## Development & Customization
### Build from Source
```bash
# Clone repository for customization
git clone <repository>
cd rustyTags
# Development build
maturin develop
# Release build with optimizations
maturin build --release
# Run tests and benchmarks
python test_complex.py
python stress_test.py
python benchmark_comparison.py
```
### Running the FastAPI Example
```bash
# Install RustyTags and FastAPI dependencies
pip install rusty-tags fastapi uvicorn datastar-py
# Run the example application
python lab/FastapiApp.py
# Open browser to http://localhost:8000
# Try sending messages to see real-time CQRS in action!
```
## Requirements
**Runtime:**
- Python 3.8+
- `datastar-py` (official Datastar Python SDK)
- `blinker` (signal/event system)
**Development/Building:**
- Rust 1.70+
- Maturin for building Rust extensions
- Optional: IPython/Jupyter for `show()` functionality
## License
MIT
Raw data
{
"_id": null,
"home_page": null,
"name": "rusty-tags",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "html, web, performance, rust, template",
"author": "RustyTags Contributors",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/0f/d2/fe32530637db8558554c1e7ffb803452a01384a6c10c94455c6d3b79f2b9/rusty_tags-0.5.26.tar.gz",
"platform": null,
"description": "# RustyTags\n\n\u26a0\ufe0f **Early Beta** - This library is in active development and APIs may change.\n\nA high-performance HTML generation library that provides a Rust-based Python extension for building HTML/SVG tags. RustyTags offers significant speed improvements over pure Python HTML generation libraries through memory optimization and Rust-powered performance, featuring FastHTML-style syntax, comprehensive Datastar integration, and full-stack web development utilities.\n\n## What RustyTags Does\n\nRustyTags generates HTML and SVG content programmatically with:\n- **Speed**: Rust-powered performance with memory optimization and caching\n- **Modern Syntax**: FastHTML-style callable chaining with minimal performance overhead\n- **Automatic Mapping Expansion**: Dictionaries automatically expand as tag attributes\n- **Datastar Integration**: Complete reactive web development with shorthand attributes and server-sent events\n- **Full-Stack Utilities**: Page templates, decorators, async backends, and event handling\n- **Type Safety**: Smart type conversion for Python objects (booleans, numbers, strings)\n- **Framework Integration**: Supports `__html__`, `_repr_html_`, and `render()` methods\n- **Advanced Features**: Custom tags, attribute mapping, complete HTML5/SVG support\n\n## Quick Start\n\n### Installation\n\n```bash\n# Install from PyPI (recommended)\npip install rusty-tags\n\n# For development/customization - build from source\ngit clone <repository>\ncd rustyTags\nmaturin develop\n```\n\n### FastAPI Full-Stack Application Example\n\nHere's a complete reactive web application demonstrating RustyTags' CQRS (Command Query Responsibility Segregation) capabilities with real-time server-sent events:\n\n```python\nfrom fastapi import FastAPI, Request\nfrom fastapi.responses import HTMLResponse\nfrom rusty_tags import *\nfrom rusty_tags.utils import create_template\nfrom rusty_tags.datastar import DS, signals\nfrom rusty_tags.backend import on_event, send_stream, process_queue, event\nfrom datastar_py.fastapi import datastar_response, ReadSignals, ServerSentEventGenerator as SSE\nfrom datastar_py.consts import ElementPatchMode\nimport asyncio\n\n# Setup page template with UI framework (Franken UI in this example)\nhdrs = (\n Link(rel='stylesheet', href='https://cdn.jsdelivr.net/npm/franken-ui@2.1.0/dist/css/core.min.css'),\n Script(src='https://cdn.jsdelivr.net/npm/franken-ui@2.1.0/dist/js/core.iife.js', type='module'),\n)\npage = create_template(hdrs=hdrs, htmlkw=dict(cls=\"bg-background\"), bodykw=dict(cls=\"p-16\"))\n\napp = FastAPI()\n\n# Reusable UI component with automatic mapping expansion\ndef Section(title, *content):\n return Div(\n H2(title, dict(cls=\"uk-h2 mb-4\")), # Mapping expansion in action!\n Div(*content, cls=\"border rounded-md p-4\"),\n cls=\"my-4 max-w-md\"\n )\n\n# QUERY side: Main application page\n@app.get(\"/\")\n@page(title=\"Reactive FastAPI App\", wrap_in=HTMLResponse)\ndef index():\n return Main(\n Section(\"Server Event Updates Demo \ud83d\ude80\",\n Form(\n Input(\n placeholder=\"Send message and press Enter\",\n type=\"text\", \n bind=\"message\", \n cls=\"uk-input\"\n ),\n # COMMAND: Trigger server-side event processing\n on_submit=DS.get(\"/queries/user\", contentType=\"form\")\n ),\n Div(id=\"updates\") # Real-time updates container\n ),\n signals=signals(message=\"\"), # Client state\n on_load=DS.get(\"/updates\") # Connect to SSE stream\n )\n\n# Event system setup for CQRS pattern\nevents_signal = event(\"events\")\nresults_queue = asyncio.Queue()\n\n# COMMAND side: Process user actions\n@app.get(\"/queries/{sender}\")\nasync def queries(sender: str, request: Request, signals: ReadSignals):\n \"\"\"COMMAND: Trigger events and process user inputs\"\"\"\n send_stream(events_signal, sender, results_queue, \n signals=signals, request=request)\n\n# QUERY side: Real-time updates stream \n@app.get(\"/updates\")\n@datastar_response\nasync def event_stream(request: Request, signals: ReadSignals):\n \"\"\"QUERY: SSE endpoint for real-time UI updates\"\"\"\n return process_queue(results_queue)\n\n# Event handlers: Business logic with HTML responses\n@on_event(\"events\", sender=\"user\") \ndef notify(sender, request: Request, signals: dict | None):\n \"\"\"Process user message and return HTML updates\"\"\"\n message = (signals or {}).get(\"message\", \"No message provided\")\n \n # Execute client-side notification\n yield SSE.execute_script(f\"UIkit.notification({{message: '{message}'}})\")\n \n # Update UI with new content (using mapping expansion)\n yield SSE.patch_elements(\n Div(f\"Server processed: {message}\", dict(cls=\"text-lg font-bold mt-2\")),\n selector=\"#updates\", \n mode=ElementPatchMode.APPEND\n )\n \n # Reset form state\n yield SSE.patch_signals({\"message\": \"\"})\n\n# Additional event handlers can be added easily\n@events_signal.connect\ndef log_messages(sender, request: Request, signals: dict | None):\n message = (signals or {}).get(\"message\", \"\")\n print(f\"\ud83d\udcdd Message logged: {message}\")\n\nif __name__ == \"__main__\":\n import uvicorn\n uvicorn.run(app, host=\"0.0.0.0\", port=8000)\n```\n\n**Key Features Demonstrated:**\n- **\ud83c\udd95 Mapping Expansion**: `dict(cls=\"...\")` automatically becomes `cls=\"...\"`\n- **\ud83c\udfd7\ufe0f CQRS Pattern**: Separate command (`/queries`) and query (`/updates`) endpoints\n- **\u26a1 Real-time Updates**: Server-sent events with automatic HTML patching\n- **\ud83c\udfa8 Framework Integration**: Works seamlessly with any CSS framework\n- **\ud83d\udd04 Reactive State**: Client-server state synchronization\n- **\ud83d\udce1 Event-Driven**: Scalable event handling with multiple subscribers\n\n### Simple Usage Examples\n\n```python\nfrom rusty_tags import Div, P, A, Button, Input\nfrom rusty_tags.datastar import signals, DS\n\n# Basic HTML generation with mapping expansion\ncontent = Div(\n P(\"Hello World\", dict(cls=\"greeting\", id=\"welcome\")),\n Button(\"Click me\", dict(type=\"button\", disabled=False)),\n cls=\"container\"\n)\nprint(content)\n# <div class=\"container\"><p class=\"greeting\" id=\"welcome\">Hello World</p><button type=\"button\">Click me</button></div>\n\n# Reactive component with Datastar\ncounter = Div(\n P(text=\"$count\", cls=\"display\"),\n Button(\"+\", on_click=\"$count++\"),\n Button(\"-\", on_click=\"$count--\"),\n signals=signals(count=0)\n)\n\n# Advanced actions with DS utilities\nform = Div(\n Input(bind=\"$email\", placeholder=\"Email\"),\n Button(\"Submit\", on_click=DS.post(\"/api/submit\", data=\"$email\")),\n signals=signals(email=\"\")\n)\n```\n\n## Features\n\n### \ud83c\udd95 Automatic Mapping Expansion\nRustyTags now automatically expands Python dictionaries passed as positional arguments into tag attributes:\n\n```python\n# Before: Manual unpacking required\nDiv(\"Content\", **{\"id\": \"main\", \"class\": \"container\", \"hidden\": False})\n\n# Now: Automatic expansion!\nDiv(\"Content\", dict(id=\"main\", class_=\"container\", hidden=False))\n# Output: <div id=\"main\" class=\"container\">Content</div>\n\n# Works with any mapping type and combines with regular kwargs\nattrs = {\"data-value\": 123, \"title\": \"Tooltip\"}\nDiv(\"Text\", attrs, id=\"element\", cls=\"active\")\n# Output: <div data-value=\"123\" title=\"Tooltip\" id=\"element\" class=\"active\">Text</div>\n```\n\n**Key Features:**\n- **Automatic Detection**: Any dict in positional args is expanded as attributes\n- **Type Preservation**: Booleans, numbers, strings handled correctly\n- **Datastar Compatible**: `ds_` attributes and reactive `cls` dicts preserved\n- **Performance Optimized**: Zero overhead expansion at the Rust level\n\n### \ud83c\udfd7\ufe0f CQRS (Command Query Responsibility Segregation) Architecture\n\nRustyTags enables clean separation of commands and queries for scalable reactive applications:\n\n```python\n# COMMAND side: Handle user actions\n@app.post(\"/commands/user/{action}\")\nasync def handle_command(action: str, request: Request, signals: ReadSignals):\n \"\"\"Process user commands and trigger events\"\"\"\n send_stream(user_events, action, updates_queue, \n signals=signals, request=request)\n\n# QUERY side: Real-time UI updates\n@app.get(\"/queries/updates\") \n@datastar_response\nasync def query_updates(request: Request):\n \"\"\"Stream UI updates based on processed events\"\"\"\n return process_queue(updates_queue)\n\n# Event handlers: Business logic with HTML responses\n@on_event(\"user_events\", sender=\"create_todo\")\ndef create_todo_handler(sender, signals: dict, **kwargs):\n # Business logic\n todo = create_todo(signals.get(\"todo_text\"))\n \n # Return HTML update\n yield SSE.patch_elements(\n TodoItem(todo, dict(id=f\"todo-{todo.id}\")),\n selector=\"#todo-list\",\n mode=ElementPatchMode.APPEND\n )\n```\n\n**CQRS Benefits:**\n- **\ud83d\udcdd Commands**: Separate endpoints for state-changing operations\n- **\ud83d\udcd6 Queries**: Dedicated streams for real-time UI updates \n- **\ud83d\udd04 Event-Driven**: Loose coupling between commands and UI updates\n- **\ud83d\ude80 Scalable**: Event handlers can be distributed across services\n- **\ud83e\uddea Testable**: Clear separation of concerns and business logic\n\n### \ud83c\udf1f Full-Stack Web Development Utilities\n\n**Page Templates & Decorators:**\n```python\nfrom rusty_tags.utils import Page, create_template\n\n# Production-ready page template\npage = create_template(\n \"My App\",\n hdrs=(\n Meta(charset=\"utf-8\"),\n Meta(name=\"viewport\", content=\"width=device-width, initial-scale=1\"),\n Link(rel=\"stylesheet\", href=\"/static/app.css\")\n ),\n datastar=True\n)\n\n@page(title=\"Dashboard\")\ndef dashboard():\n return Main(\n Section(\"Analytics\", dict(role=\"main\", cls=\"dashboard\")),\n Nav(A(\"Home\", href=\"/\"), A(\"Settings\", href=\"/settings\"))\n )\n```\n\n**Async Backend Integration:**\n```python\nfrom rusty_tags.backend import on_event, send_stream, process_queue\nimport asyncio\n\n# Multi-subscriber event system\n@on_event(\"user_action\", sender=\"notification\")\nasync def send_notification(sender, **data):\n yield Div(f\"\ud83d\udcec {data['message']}\", cls=\"notification\")\n\n@on_event(\"user_action\", sender=\"analytics\") \nasync def track_analytics(sender, **data):\n # Log to analytics service\n print(f\"\ud83d\udcca Event tracked: {data}\")\n```\n\n### Datastar Reactive Integration\n- **Shorthand Attributes**: Clean syntax with `signals`, `bind`, `show`, `text`, `on_click`, etc.\n- **Action Generators**: Built-in `DS` class for common patterns (`DS.post()`, `DS.get()`, etc.)\n- **Backward Compatible**: Full support for `ds_*` prefixed attributes\n- **Event Handling**: Comprehensive `on_*` event attribute support\n- **State Management**: Built-in signals, computed values, and effects\n- **Server-Sent Events**: Full SSE support with `datastar-py` integration\n- **Performance Optimized**: Zero overhead for Datastar attribute processing\n\n### FastHTML-Style Callable API\n- **Chainable Syntax**: Support for `Div(cls=\"container\")(children...)` patterns\n- **Flexible Composition**: Mix traditional and callable styles seamlessly\n- **Performance Optimized**: Minimal overhead (6-8%) for callable functionality\n- **Smart Returns**: Empty tags return callable builders, populated tags return HTML\n\n### Performance Optimizations\n- **Memory Pooling**: Thread-local string pools for efficient memory reuse\n- **Lock-free Caching**: Global caches for attribute and tag name transformations\n- **String Interning**: Pre-allocated common HTML strings\n- **SIMD Ready**: Optimized for modern CPU instruction sets\n- **Stack Allocation**: SmallVec for small collections to avoid heap allocation\n\n### Smart Type Conversion\n- **Automatic Type Handling**: Booleans, integers, floats, strings\n- **Framework Integration**: `__html__()`, `_repr_html_()`, `render()` method support\n- **Attribute Mapping**: `cls` \u2192 `class`, `_for` \u2192 `for`, etc.\n- **Error Handling**: Clear error messages for unsupported types\n\n### HTML Features\n- **All Standard Tags**: Complete HTML5 tag set with optimized generation\n- **Automatic DOCTYPE**: Html tag includes `<!doctype html>` \n- **Custom Tags**: Dynamic tag creation with any tag name\n- **Attribute Processing**: Smart attribute key transformation and value conversion\n\n## API Features & Architecture\n\nRustyTags provides clean, intuitive APIs with multiple styles and full-stack capabilities:\n\n```python\n# Traditional style with mapping expansion\nfrom rusty_tags import Div, P, Input, Button\ncontent = Div(\n P(\"Text\", dict(class_=\"highlight\", data_id=\"p1\")),\n cls=\"container\"\n)\n\n# FastHTML-style callable chaining\ncontent = Div(cls=\"container\")(P(\"Text\", _class=\"highlight\"))\n\n# Full-stack reactive application\nfrom rusty_tags.datastar import signals, reactive_class, DS\nfrom rusty_tags.backend import on_event\nfrom rusty_tags.utils import Page, create_template\n\n# Backend event handler\n@on_event(\"todo_updated\")\nasync def handle_todo_update(sender, **data):\n # Return HTML update\n yield Div(f\"Todo {data['id']} updated!\", cls=\"notification\")\n\n# Interactive todo application\ndef todo_app():\n return Page(\n Div(\n Input(\n type=\"text\", \n bind=\"$newTodo\", \n placeholder=\"Add todo...\",\n on_keyup=\"event.key === 'Enter' && $addTodo()\"\n ),\n Button(\"Add\", on_click=\"$addTodo()\"),\n Div(\n # Dynamic todo list\n show=\"$todos.length > 0\",\n effect=\"console.log('Todos updated:', $todos)\"\n ),\n signals=signals(\n newTodo=\"\",\n todos=[]\n ),\n cls=\"todo-app\"\n ),\n title=\"Todo App\",\n datastar=True\n )\n\n# Page template decorator\ntemplate = create_template(\"My App\", datastar=True)\n\n@template.page(\"Dashboard\") \ndef dashboard():\n return Div(\"Welcome to dashboard!\", dict(role=\"main\", cls=\"dashboard\"))\n```\n\n### \ud83d\udce6 **Module Structure**\n\n**Core Engine (`rusty_tags.*`):**\n- High-performance Rust-based HTML/SVG tag generation\n- Automatic mapping expansion and type conversion\n- FastHTML-style callable syntax support\n\n**Datastar Integration (`rusty_tags.datastar`):**\n- Shorthand attribute support and action generators\n- Server-sent events with `datastar-py` integration\n- Reactive state management utilities\n\n**Full-Stack Utilities (`rusty_tags.utils`):**\n- Page templates and layout management \n- Function decorators for view composition\n- IPython/Jupyter integration with `show()`\n\n**Async Backend (`rusty_tags.backend`):**\n- Event-driven architecture with Blinker signals\n- Async SSE streaming and queue processing\n- Concurrent event handler execution\n\n## Datastar Integration\n\nRustyTags provides comprehensive Datastar support for building reactive web applications:\n\n### Shorthand Attributes\n\nAll Datastar attributes support clean shorthand syntax:\n\n```python\n# Before (still supported)\nDiv(ds_signals={\"count\": 0}, ds_show=\"$visible\", ds_on_click=\"$increment()\")\n\n# After (new shorthand)\nDiv(signals={\"count\": 0}, show=\"$visible\", on_click=\"$increment()\")\n```\n\n### Supported Datastar Attributes\n\n**Core Attributes:**\n- `signals` \u2192 `data-signals` - Component state management\n- `bind` \u2192 `data-bind` - Two-way data binding\n- `show` \u2192 `data-show` - Conditional visibility\n- `text` \u2192 `data-text` - Dynamic text content\n- `attrs` \u2192 `data-attrs` - Dynamic attributes\n- `data_style` \u2192 `data-style` - Dynamic styling\n\n**Event Attributes:**\n- `on_click`, `on_hover`, `on_submit`, `on_focus`, `on_blur`\n- `on_keydown`, `on_change`, `on_input`, `on_load`\n- `on_intersect`, `on_interval`, `on_raf`, `on_resize`\n\n**Advanced Attributes:**\n- `effect` \u2192 `data-effect` - Side effects\n- `computed` \u2192 `data-computed` - Computed values\n- `ref` \u2192 `data-ref` - Element references\n- `indicator` \u2192 `data-indicator` - Loading states\n- `persist` \u2192 `data-persist` - State persistence\n- `ignore` \u2192 `data-ignore` - Skip processing\n\n### Complete Example\n\n```python\nfrom rusty_tags import Div, Button, Input, Span\nfrom rusty_tags.datastar import signals, reactive_class, DS\n\n# Interactive counter with Datastar\ncounter_app = Div(\n Span(text=\"$count\", cls=\"display\"),\n Div(\n Button(\"-\", on_click=\"$count--\"),\n Button(\"+\", on_click=\"$count++\"),\n Button(\"Reset\", on_click=DS.set(\"count\", 0)),\n cls=\"controls\"\n ),\n Input(\n type=\"range\",\n bind=\"$count\",\n attrs={\"min\": \"0\", \"max\": \"100\"}\n ),\n signals={\"count\": 50},\n effect=\"console.log('Count changed:', $count)\",\n cls=\"counter-app\"\n)\n```\n\n## Performance\n\nRustyTags significantly outperforms pure Python HTML generation:\n- 3-10x faster than equivalent Python code\n- Optimized memory usage with pooling and interning\n- Aggressive compiler optimizations in release builds\n\n## Development Status\n\n\ud83d\udea7 **Early Beta**: While the core functionality is stable and tested, this library is still in early development. Breaking changes may occur in future versions. Production use is not recommended yet.\n\n### Current Features \u2705\n- **Core Engine**: All HTML5 and SVG tags with Rust performance\n- **Mapping Expansion**: Automatic dict-to-attributes expansion\n- **Callable API**: FastHTML-style chainable syntax\n- **Datastar Integration**: Complete reactive web development stack\n- **Full-Stack Utilities**: Page templates, decorators, async backends\n- **Event System**: Blinker-based event handling with async support\n- **Server-Sent Events**: Real-time updates with datastar-py integration\n- **Type Safety**: Smart type conversion and attribute mapping\n- **Performance**: Memory optimization, caching, and Rust-powered speed\n- **Custom Tags**: Dynamic tag creation and framework integration\n\n### Planned Features \ud83d\udd04\n- **Template Engine**: Jinja2/Mako integration for server-side rendering \n- **Streaming HTML**: Chunked response generation for large documents\n- **PyPI Distribution**: Official package releases and versioning\n- **Developer Tools**: Hot reload, debugging utilities, and performance profilers\n\n### Dependencies & Integration\n\n**Core Dependencies:**\n- `datastar-py`: Official Datastar Python SDK for SSE and attributes\n- `blinker`: Signal/event system for backend event handling\n- `maturin`: Rust-Python build system for performance-critical code\n\n**Framework Integration:**\n- **FastAPI**: Native async support with SSE streaming\n- **Flask**: Compatible with Jinja2 templates and request contexts\n- **Django**: Template integration and ORM query rendering\n- **IPython/Jupyter**: Built-in `show()` function for notebook display\n- **Starlette**: ASGI compatibility with streaming responses\n\n## Development & Customization\n\n### Build from Source\n\n```bash\n# Clone repository for customization\ngit clone <repository>\ncd rustyTags\n\n# Development build \nmaturin develop\n\n# Release build with optimizations\nmaturin build --release\n\n# Run tests and benchmarks\npython test_complex.py\npython stress_test.py\npython benchmark_comparison.py\n```\n\n### Running the FastAPI Example\n\n```bash\n# Install RustyTags and FastAPI dependencies\npip install rusty-tags fastapi uvicorn datastar-py\n\n# Run the example application\npython lab/FastapiApp.py\n\n# Open browser to http://localhost:8000\n# Try sending messages to see real-time CQRS in action!\n```\n\n## Requirements\n\n**Runtime:**\n- Python 3.8+\n- `datastar-py` (official Datastar Python SDK)\n- `blinker` (signal/event system)\n\n**Development/Building:**\n- Rust 1.70+\n- Maturin for building Rust extensions\n- Optional: IPython/Jupyter for `show()` functionality\n\n## License\n\nMIT\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "High-performance HTML generation library with Rust-based Python extension",
"version": "0.5.26",
"project_urls": {
"Homepage": "https://github.com/ndendic/rustyTags",
"Issues": "https://github.com/ndendic/rustyTags/issues",
"Repository": "https://github.com/ndendic/rustyTags"
},
"split_keywords": [
"html",
" web",
" performance",
" rust",
" template"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "38911db0e2826a02f6fdcdc6cd09828683a9f42ea2df7d3f2fd29f65f2272ad6",
"md5": "24787a377c36f6317f1be4233251c1a7",
"sha256": "0f7d6db2fdd66d726a7d72d9dd54eb4525ea7d605509339d98e38482bc4289bc"
},
"downloads": -1,
"filename": "rusty_tags-0.5.26-cp312-cp312-manylinux_2_34_x86_64.whl",
"has_sig": false,
"md5_digest": "24787a377c36f6317f1be4233251c1a7",
"packagetype": "bdist_wheel",
"python_version": "cp312",
"requires_python": ">=3.8",
"size": 920943,
"upload_time": "2025-09-06T19:32:16",
"upload_time_iso_8601": "2025-09-06T19:32:16.445457Z",
"url": "https://files.pythonhosted.org/packages/38/91/1db0e2826a02f6fdcdc6cd09828683a9f42ea2df7d3f2fd29f65f2272ad6/rusty_tags-0.5.26-cp312-cp312-manylinux_2_34_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "0fd2fe32530637db8558554c1e7ffb803452a01384a6c10c94455c6d3b79f2b9",
"md5": "db361333ed4f5ca004678a680a0309ad",
"sha256": "b0de7cea48daf6c1c68673ce3cfe2d32283c7c65d4e9791002235a654ad5b5ef"
},
"downloads": -1,
"filename": "rusty_tags-0.5.26.tar.gz",
"has_sig": false,
"md5_digest": "db361333ed4f5ca004678a680a0309ad",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 62445,
"upload_time": "2025-09-06T19:32:19",
"upload_time_iso_8601": "2025-09-06T19:32:19.383665Z",
"url": "https://files.pythonhosted.org/packages/0f/d2/fe32530637db8558554c1e7ffb803452a01384a6c10c94455c6d3b79f2b9/rusty_tags-0.5.26.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-09-06 19:32:19",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "ndendic",
"github_project": "rustyTags",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "rusty-tags"
}