Type-safe observables and proxies for building reactive Python applications.
Project description
Observant.py
Reactive state management for Python.
Track changes, validate data, implement undo/redo, and build reactive UIs with ease.
📚 Full documentation: https://mrowrlib.github.io/observant.py
Installation
pip install observant
Core Types
Observant.py provides a set of observable primitives:
Observable[T]: Wraps a scalar value and notifies listeners on changeObservableList[T]: Observable wrapper around a listObservableDict[K, V]: Observable wrapper around a dictionaryObservableProxy[T]: Wraps a dataclass or object and exposes its fields as observables
Quick Examples
Observable
from observant import Observable
count = Observable(0)
count.on_change(lambda v: print(f"Count is now {v}"))
count.set(1) # → Count is now 1
ObservableList
from observant import ObservableList
items = ObservableList(["a", "b"])
items.on_change(lambda change: print(f"List changed: {change.type.name}"))
items.append("c") # → List changed: ADD
ObservableDict
from observant import ObservableDict
settings = ObservableDict({"theme": "dark"})
settings.on_change(lambda change: print(f"Settings changed: {change.key}"))
settings["theme"] = "light" # → Settings changed: theme
ObservableProxy
from observant import ObservableProxy
from dataclasses import dataclass
@dataclass
class User:
name: str
age: int
user = User(name="Ada", age=36)
proxy = ObservableProxy(user)
name = proxy.observable(str, "name")
name.on_change(lambda v: print(f"Name changed to {v}"))
name.set("Grace") # → Name changed to Grace
# Save changes back to the original object
proxy.save_to(user)
print(user.name) # → Grace
Features
- ✅ Type-safe observables: Full type hints and generics support
- 🔁 Undo/Redo support: Track and revert changes
- 🧠 Computed properties: Create derived values that update automatically
- 🧪 Validation: Add validators to ensure data integrity
- 🔄 Dirty state tracking: Know which fields have been modified
- 🔗 Sync back to original objects: Optionally sync changes immediately
Advanced Example: MVVM Pattern
from observant import ObservableProxy
from dataclasses import dataclass
from typing import List
@dataclass
class TodoItem:
text: str
completed: bool
@dataclass
class TodoListModel:
items: List[TodoItem]
class TodoListViewModel:
def __init__(self, model: TodoListModel):
self.model = model
self.proxy = ObservableProxy(model)
# Get observable list of items
self.items = self.proxy.observable_list(TodoItem, "items")
# Register computed properties
self.proxy.register_computed(
"completed_count",
lambda: sum(1 for item in self.items if item.completed),
["items"]
)
def add_item(self, text: str):
self.items.append(TodoItem(text=text, completed=False))
def toggle_item(self, index: int):
item = self.items[index]
item_proxy = ObservableProxy(item)
completed_obs = item_proxy.observable(bool, "completed")
completed_obs.set(not completed_obs.get())
item_proxy.save_to(item)
def save(self):
self.proxy.save_to(self.model)
# Usage
model = TodoListModel(items=[])
view_model = TodoListViewModel(model)
# Listen for changes
view_model.proxy.computed(int, "completed_count").on_change(
lambda count: print(f"Completed: {count}")
)
# Add and toggle items
view_model.add_item("Learn Python")
view_model.add_item("Learn Observant.py")
view_model.toggle_item(0) # → Completed: 1
Learn More
Check out the full documentation and examples at https://mrowrlib.github.io/observant.py
Project details
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 observant-0.1.3.tar.gz.
File metadata
- Download URL: observant-0.1.3.tar.gz
- Upload date:
- Size: 32.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1578bef948f7ca206e8cdc1077b9dda2157111ea0b33f208fd4642162ab985d1
|
|
| MD5 |
58511e85099b248823b103638197702d
|
|
| BLAKE2b-256 |
d8edea8c8f2cba89df9c38a658dfbc54bfd5918e25265b63a2e58eb60c7538cb
|
File details
Details for the file observant-0.1.3-py3-none-any.whl.
File metadata
- Download URL: observant-0.1.3-py3-none-any.whl
- Upload date:
- Size: 34.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
af59d3e3930db9e093dcabbdbf5bcc840fc317b68beb10c29cb51dc342762772
|
|
| MD5 |
6d517e4e1e4514321dced0f8bb9d4907
|
|
| BLAKE2b-256 |
a5cccf42c6276593649c6c4e9cbbd7116413b7ce0994f99d5d0c229d7455c9a7
|