Skip to main content

Lightweight atomic state management for IoT devices and embedded systems

Project description

StateQuark

License: MIT Python 3.10+

Atomic state management for IoT and embedded systems. Inspired by Jotai.

Installation

pip install statequark

Quick Start

from statequark import quark, batch

# Basic state
temperature = quark(20.0)
print(temperature.value)  # 20.0
temperature.set(25.5)

# Derived state (auto-updates when dependencies change)
temp_f = quark(lambda get: get(temperature) * 9/5 + 32, deps=[temperature])
print(temp_f.value)  # 77.9

# Subscriptions
temperature.subscribe(lambda q: print(f"Temp: {q.value}"))
temperature.set(30.0)  # prints: Temp: 30.0

# Reset to initial value
temperature.reset()  # back to 20.0

# Batch updates (single notification)
with batch():
    sensor1.set(25.0)
    sensor2.set(60.0)

Utilities

Storage (Persistent State)

from statequark import quark_with_storage

# State survives device reboot
config = quark_with_storage("device_config", {"threshold": 25.0})
config.set({"threshold": 30.0})  # Saved to .statequark/device_config.json

Reducer (Action-based Updates)

from statequark import quark_with_reducer

def motor_reducer(state, action):
    match action["type"]:
        case "START": return {**state, "running": True}
        case "SET_SPEED": return {**state, "speed": action["value"]}
    return state

motor = quark_with_reducer({"running": False, "speed": 0}, motor_reducer)
motor.dispatch({"type": "START"})
motor.dispatch({"type": "SET_SPEED", "value": 100})

Select (Partial Subscription)

from statequark import quark, select

sensor = quark({"temp": 25.0, "humidity": 60})
temp = select(sensor, lambda d: d["temp"])  # Only triggers when temp changes
temp.subscribe(lambda q: print(f"Temp changed: {q.value}"))

Family (Dynamic Quarks)

from statequark import quark, quark_family

sensors = quark_family(lambda id: quark(0.0))
living_room = sensors("living_room")
bedroom = sensors("bedroom")
kitchen = sensors("kitchen")

Debounce / Throttle (Noise Filtering)

from statequark import debounce, throttle

# Debounce: wait 100ms of silence before updating
temp = debounce(0.0, 0.1)

# Throttle: max 1 update per second
display = throttle(0, 1.0)

History (Undo/Redo)

from statequark import history

setting = history(50)
setting.set(60)
setting.set(70)
setting.undo()  # 60
setting.undo()  # 50
setting.redo()  # 60

Validate (Value Validation)

from statequark import validate, in_range, clamp

# Raise error on invalid
temp = validate(25.0, in_range(0, 100))

# Auto-clamp on invalid
temp = validate(25.0, in_range(0, 100), clamp(0, 100))
temp.set(150)  # Clamped to 100

Middleware (Extensible Hooks)

from statequark import middleware, logger, persist

storage = {}
counter = middleware(0)
counter.use(logger("counter"))  # Log changes
counter.use(persist(storage, "count"))  # Save to dict
counter.set(42)  # [counter] 0 -> 42

Loadable (Async State)

from statequark import quark, loadable

data = quark(None)
state = loadable(data)
state.set_loading()   # state.value.state == "loading"
state.set_data(42)    # state.value.state == "hasData"
state.set_error(err)  # state.value.state == "hasError"

IoT Example

from statequark import quark, quark_with_storage, validate, in_range, clamp

# Persistent config
config = quark_with_storage("config", {"threshold": 30})

# Validated sensor with auto-clamp
soil = validate(65.0, in_range(0, 100), clamp(0, 100))

# Derived alert
alert = quark(
    lambda get: get(soil) < get(config)["threshold"],
    deps=[soil, config]
)

# Hardware control
alert.subscribe(lambda q: gpio.output(PUMP_PIN, q.value))

API Reference

Core

Function Description
quark(value) Create state
quark(fn, deps=[...]) Create derived state
batch() Batch updates context

Quark Methods

Method Description
.value Get current value
.set(v) Set value (sync)
await .set_async(v) Set value (async)
.reset() Reset to initial
.subscribe(fn) Subscribe to changes
.unsubscribe(fn) Unsubscribe
.cleanup() Release resources

Utilities

Function Description
quark_with_storage(key, default) Persistent state
quark_with_reducer(init, reducer) Action-based state
select(source, selector) Partial subscription
quark_family(factory) Dynamic quark creation
debounce(init, delay) Debounced updates
throttle(init, interval) Throttled updates
history(init, max_size) Undo/redo support
validate(init, validator, on_invalid) Value validation
middleware(init) Middleware pipeline
loadable(source) Async state wrapper

License

MIT

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

statequark-0.5.0.tar.gz (23.0 kB view details)

Uploaded Source

Built Distribution

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

statequark-0.5.0-py3-none-any.whl (20.3 kB view details)

Uploaded Python 3

File details

Details for the file statequark-0.5.0.tar.gz.

File metadata

  • Download URL: statequark-0.5.0.tar.gz
  • Upload date:
  • Size: 23.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for statequark-0.5.0.tar.gz
Algorithm Hash digest
SHA256 ec3356a13236acbca1ec63c1a7e4282f64718e29d9fa62a7f3e7a53e32a15099
MD5 3f51fbc4e9f1cd613e689fb297764e53
BLAKE2b-256 674393d67c1ce8bf2cde117352b817935321bfffd45f38a20d5c7106ad99976a

See more details on using hashes here.

File details

Details for the file statequark-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: statequark-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 20.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for statequark-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 26273a33473244a7fba30812d21b995606d8167f689ee6971fd32409f7015940
MD5 2a9b20416569ff91eb71d3f03e6fe0fe
BLAKE2b-256 ba268f07ad15e9186723f78ba6507bbe8bdb077bee5755e1f30cd1db24faffb5

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