Skip to main content

Type-safe observables and proxies for building reactive Python applications.

Project description

Observant.py

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

PyPI version License: 0BSD License: 0BSD

Installation

pip install observant

Core Types

Observant.py provides a set of observable primitives:

  • Observable[T]: Wraps a scalar value and notifies listeners on change
  • ObservableList[T]: Observable wrapper around a list
  • ObservableDict[K, V]: Observable wrapper around a dictionary
  • ObservableProxy[T]: Wraps a dataclass or object and exposes its fields as observables
  • UndoableObservable[T]: Adds undo/redo support to any observable

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

observant-0.1.2.tar.gz (20.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

observant-0.1.2-py3-none-any.whl (18.4 kB view details)

Uploaded Python 3

File details

Details for the file observant-0.1.2.tar.gz.

File metadata

  • Download URL: observant-0.1.2.tar.gz
  • Upload date:
  • Size: 20.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for observant-0.1.2.tar.gz
Algorithm Hash digest
SHA256 9afd224b95e792b1b02e3c42d55a56eebc2120a947cacfc12a2b8dfa68eecfc2
MD5 febbf816ec714b7b2db79e8ee9fe1066
BLAKE2b-256 191441db2321e28e3ed85295bd62786bf1dbacb59eb9d484268f6616f7e5533e

See more details on using hashes here.

File details

Details for the file observant-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: observant-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 18.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for observant-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 fb9e09ac188823eea7f82e5ac4fdd5aa7f73ce491ff545b96cd08e8e47f13c11
MD5 bef4e6f092f95b24ec7e963dc7deb7e6
BLAKE2b-256 4863a5ed11511ac91ab73954ecd84458b108f6fcfc1656e711f7cdee8ae499ed

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page