Reactive signals for Python with async support
Project description
reaktiv

Reactive Signals for Python with first-class async support, inspired by Angular's reactivity model.
from reaktiv import Signal, ComputeSignal, Effect
count = Signal(0)
doubled = ComputeSignal(lambda: count.get() * 2)
async def log_count():
print(f"Count: {count.get()}, Doubled: {doubled.get()}")
Effect(log_count).schedule()
count.set(5) # Triggers: "Count: 5, Doubled: 10"
Features
⚡ Angular-inspired reactivity
✅ First-class async/await support
🧠 Automatic dependency tracking
💡 Zero external dependencies
🧩 Type annotations throughout
♻️ Efficient memory management
Installation
pip install reaktiv
# or with uv
uv pip install reaktiv
Quick Start
Basic Reactivity
from reaktiv import Signal, Effect
name = Signal("Alice")
async def greet():
print(f"Hello, {name.get()}!")
# Create and schedule effect
greeter = Effect(greet)
greeter.schedule()
name.set("Bob") # Prints: "Hello, Bob!"
Async Effects
from reaktiv import Signal, Effect
import asyncio
data = Signal([])
async def fetch_data():
await asyncio.sleep(0.1)
data.set([1, 2, 3])
Effect(fetch_data).schedule()
Computed Values
from reaktiv import Signal, ComputeSignal
price = Signal(100)
tax_rate = Signal(0.2)
total = ComputeSignal(lambda: price.get() * (1 + tax_rate.get()))
print(total.get()) # 120.0
tax_rate.set(0.25)
print(total.get()) # 125.0
Core Concepts
Signals
# Create
user = Signal("Alice")
# Get value
print(user.get()) # "Alice"
# Update value
user.set("Bob")
Computed Signals
a = Signal(2)
b = Signal(3)
sum_signal = ComputeSignal(
lambda: a.get() + b.get(),
default=0 # Optional error fallback
)
Effects
async def stock_ticker():
price = stock.get()
print(f"Current price: {price}")
await save_to_db(price)
# Create and schedule
effect = Effect(stock_ticker)
effect.schedule()
# Dispose when done
effect.dispose()
Advanced Usage
Error Handling in Computed
# Safe computation with fallback
divisor = Signal(2)
safe_divide = ComputeSignal(
lambda: 10 / divisor.get(),
default=float('inf')
)
divisor.set(0) # Prints traceback but maintains last valid value
Nested Effects
async def parent_effect():
if user.get().is_admin:
# Create child effect conditionally
Effect(child_effect).schedule()
Dynamic Dependencies
switch = Signal(True)
a = Signal(10)
b = Signal(20)
dynamic = ComputeSignal(
lambda: a.get() if switch.get() else b.get()
)
Inspired by Angular Signals • Built for Python's async-first world
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 reaktiv-0.1.0.tar.gz.
File metadata
- Download URL: reaktiv-0.1.0.tar.gz
- Upload date:
- Size: 5.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.5.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5207ddbeef07cfa3fe0c1ce8eec4aab4a18ddac1ff672366fe76a4f8d98d5848
|
|
| MD5 |
2a75a6ee44cab1a04cf0e9adb7897013
|
|
| BLAKE2b-256 |
7a4e4b5071b8a4b7829be583484667f22324d5fc0afdf0a8aa7cc08cc3c65aba
|
File details
Details for the file reaktiv-0.1.0-py3-none-any.whl.
File metadata
- Download URL: reaktiv-0.1.0-py3-none-any.whl
- Upload date:
- Size: 4.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.5.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
49d26f39d154afe2ead7fc8799b0f2e3e2947d868178e2e07473ce72e1e52183
|
|
| MD5 |
e973ae26648a4c0002f2485a45cd05ca
|
|
| BLAKE2b-256 |
0496872b9152cb7397852798d8c569e34a6e7c586c4d85b092d7ef4a8670415c
|