Time-travel variable framework for Python
Project description
Alma — Time-Travel Variable Framework
"What if every variable remembered where it came from?"
Alma is a lightweight, thread-safe Python framework that wraps ordinary values in observable, auditable containers — giving you a complete mutation history and the ability to roll back to any past state.
Installation
No external dependencies. Copy alma.py into your project or install once a package
is published:
pip install alma # (future)
Quick start
import alma
# 1. Create a watched variable
score = alma.watch("score", 0)
# 2. Mutate it
score.set(10).set(20).set(30) # fluent chaining
# 3. Inspect
print(score.get()) # 30
print(score.last_change()) # ChangeRecord(index=3, value=30, ...)
# 4. Full audit trail
for record in score.history():
print(record)
# 5. Time-travel
score.rollback(1) # back to 10
print(score.get()) # 10
# 6. Restore initial value
score.reset()
print(score.get()) # 0
API reference
alma.watch(name, initial_value, *, deep_copy=True, validators=None, on_change=None, overwrite=False) → AlmaVar
Create a watched variable in the global default registry.
| Argument | Type | Description |
|---|---|---|
name |
str |
Unique identifier |
initial_value |
Any |
Starting value |
deep_copy |
bool |
Deep-copy every stored value (default True) |
validators |
list[callable] |
Raise ValueError to reject a value |
on_change |
list[callable] |
(var, record) listeners fired after every set |
overwrite |
bool |
Replace an existing registration |
AlmaVar
| Method | Returns | Description |
|---|---|---|
get() |
T |
Current value |
set(value, *, label=None) |
self |
Update value; append ChangeRecord |
history() |
list[ChangeRecord] |
Full mutation history |
last_change() |
ChangeRecord |
Most recent ChangeRecord |
rollback(index, *, label=None) |
self |
Restore value at index; appends a new record |
reset() |
self |
Shorthand for rollback(0) |
diff() |
list[dict] |
Consecutive-change diffs with elapsed ms |
freeze() |
self |
Prevent further mutations |
thaw() |
self |
Re-enable mutations |
add_validator(fn) |
self |
Register a validator |
add_listener(fn) |
self |
Register a change listener |
ChangeRecord
Immutable dataclass stored in every variable's history.
@dataclass(frozen=True)
class ChangeRecord:
index: int
value: Any
timestamp: datetime # UTC
label: str | None
Advanced usage
Validators
def must_be_positive(v):
if v < 0:
raise ValueError(f"Expected positive, got {v}")
balance = alma.watch("balance", 100.0)
balance.add_validator(must_be_positive)
balance.set(50) # OK
balance.set(-1) # raises ValueError
Change listeners
import logging
def audit(var, record):
logging.info("[%s] → %r (index=%d)", var.name, record.value, record.index)
price = alma.watch("price", 9.99, on_change=[audit])
price.set(12.49) # logs immediately
Freeze a variable
config = alma.watch("config", {"debug": True})
config.freeze()
config.set({"debug": False}) # raises FrozenError
Working with the registry directly
from alma import AlmaRegistry
reg = AlmaRegistry()
x = reg.watch("x", 0)
y = reg.watch("y", 100)
print(reg.snapshot()) # {"x": 0, "y": 100}
print(reg.all_vars()) # {"x": AlmaVar(...), "y": AlmaVar(...)}
reg.unregister("x")
Running tests
pip install pytest
pytest test_alma.py -v
Suggested future extensions
| Extension | Description |
|---|---|
| Persistence | var.save(path) / AlmaVar.load(path) via JSON or pickle — persist history across restarts |
| Branching history | Git-like branches so rollbacks don't destroy the forward path |
| Async support | async def set_async(...) + asyncio.Lock for use inside async event loops |
AlmaNamespace |
Dict-like container that watches every key independently |
| Middleware / interceptors | Transform values before storage (e.g., encryption, compression) |
| Remote sync | Publish changes to Redis pub/sub or a WebSocket bus for distributed state |
| Typed generics + Pydantic | AlmaVar[MyModel] with automatic schema validation |
| Diff engine | Deep structural diffing for dicts/lists powered by deepdiff |
| Time-windowed history | Automatically prune records older than N seconds/minutes |
| Export / replay | Replay a recorded history against a function for deterministic testing |
| CLI inspector | alma inspect <pickle_file> to explore history in the terminal |
| Jupyter widget | Interactive timeline slider to scrub variable state in notebooks |
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 alma_framework-0.1.0.tar.gz.
File metadata
- Download URL: alma_framework-0.1.0.tar.gz
- Upload date:
- Size: 9.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.0rc1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6fdd89e1b05e3aa3ad69c0329185da17b42f1eb7b294082edd3fe4dbf0d66b38
|
|
| MD5 |
9e2c0472db621ed387c3979aefd9646c
|
|
| BLAKE2b-256 |
bf2d7b1c6abc6b3ed80d098a9a3311b72bd49b02a6054510473e249b08953150
|
File details
Details for the file alma_framework-0.1.0-py3-none-any.whl.
File metadata
- Download URL: alma_framework-0.1.0-py3-none-any.whl
- Upload date:
- Size: 8.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.0rc1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f899a08a33e51ded310b59dd132ec4d9296b275167582e293fb1fb0e72c77480
|
|
| MD5 |
cb2dcce460c13115316a1bced9757bf2
|
|
| BLAKE2b-256 |
9fffc6e01eb60fbae527ab468ccef7f27389503264e98b39e8a467dfabff60e3
|