Skip to main content

Observ 👁

Vue.js-style reactivity for Python. Wrap your state in a reactive proxy, and observ tracks every read and write for you: computed values invalidate themselves, watchers fire when something they depend on changes. No dirty flags, no manual invalidation, no dependency bookkeeping.

📖 Documentation · 📦 PyPI · 🧪 Examples (Qt, rendercanvas)

🖼️ Building a GUI?

Head straight to Collagraph — a full-featured, Vue-inspired declarative UI framework built on top of observ. If you're looking for a strong reactive GUI framework for your Python Qt/PySide applications, Collagraph is the main entrypoint; observ is the reactivity engine underneath it.

Why observ?

  • Automatic dependency tracking — computed state knows exactly what it depends on and lazily re-evaluates only when needed.
  • React to any change — watch plain state or computed state and build unidirectional data flow: state changes drive view changes, input events drive state changes.
  • Zero dependencies, framework agnostic — a pure Python library (≥ 3.9) that plugs into any event loop: asyncio, Qt, or your own.
  • Fully typed — a PEP 561 typed package, checked with ty in CI.

Quick start

pip install observ
from observ import computed, reactive, watch

state = reactive({
    "todos": [
        {"title": "groceries", "done": False},
        {"title": "dishes", "done": True},
    ],
})

@computed
def progress():
    done = sum(todo["done"] for todo in state["todos"])
    return f"{done}/{len(state['todos'])} done"

watcher = watch(progress, lambda new: print(new), sync=True)

# Mutate the plain dicts and lists you already have —
# observ sees every change, no matter how deeply nested:
state["todos"][0]["done"] = True                            # prints: 2/2 done
state["todos"].append({"title": "laundry", "done": False})  # prints: 2/3 done

# ...but you only ever react when a *result* actually changes:
state["todos"][1]["title"] = "do the dishes"                # (no print)

No subclasses to inherit, no observable fields to declare, no signals to wire up: reactive() takes your existing data, and dependencies are tracked automatically simply by using it.

Continue with the Quick Start tutorial, or dive into the Guide and API Reference.

Related projects

  • Collagraph: reactive user interfaces in Python, built on top of observ.
  • Reliev: the store (with undo/redo support) that used to be part of observ.
  • Patchdiff: diffing and patching for plain Python data structures — the same dicts, lists and sets you'd wrap with observ.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

observ-1.0.0.tar.gz (67.7 kB view details)

Uploaded Source

Built Distribution

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

observ-1.0.0-py3-none-any.whl (26.3 kB view details)

Uploaded Python 3

File details

Details for the file observ-1.0.0.tar.gz.

File metadata

  • Download URL: observ-1.0.0.tar.gz
  • Upload date:
  • Size: 67.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for observ-1.0.0.tar.gz
Algorithm Hash digest
SHA256 290bf5a45009ecc5d48e6d2b0a9b47e103e56948045be1237974298f55c170fd
MD5 4640d9edeeb2ef3b6ac746888b12578e
BLAKE2b-256 103cc37c12be0c46745f82f7994bedb9302b69a9014e4711589c1ebf6328ebdc

See more details on using hashes here.

Provenance

The following attestation bundles were made for observ-1.0.0.tar.gz:

Publisher: ci.yml on fork-tongue/observ

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file observ-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: observ-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 26.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for observ-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 179b7520723420150789d965394a970c31a2f455d4700e3108315130b1110f38
MD5 ae9119f62dfc12ab37460d1cbb7786de
BLAKE2b-256 f90b55c42220c691f6458ff713603a12c6e800cc0f4770e6b8441aaad56ec541

See more details on using hashes here.

Provenance

The following attestation bundles were made for observ-1.0.0-py3-none-any.whl:

Publisher: ci.yml on fork-tongue/observ

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

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