Spectate: Track Mutable Data Changes
Spectate (v1.0.1) is a Python library designed to track changes to mutable data types, providing undo/redo capabilities for operations on objects like dictionaries and lists. It achieves this by wrapping functions that modify tracked objects, recording events for each change. The library is currently feature-complete and in maintenance mode, with a slow release cadence.
Common errors
-
AttributeError: 'dict' object has no attribute 'some_attribute'
cause Attempting attribute access on an event object (e.g., `event.foo`) after upgrading to spectate v1.0.0+, where event objects are standard Python dictionaries.fixAccess event data using dictionary key notation: `event['some_attribute']`. -
ImportError: cannot import name 'Immutable' from 'spectate.utils'
cause Trying to import the `Immutable` class, which was removed from `spectate.utils` in v1.0.0.fixRemove the `from spectate.utils import Immutable` statement. Spectate no longer uses this class internally, and event objects are now standard dictionaries. -
TypeError: rollback() missing 1 required positional argument: 'undo'
cause Calling `spectate.events.rollback()` without providing the mandatory `undo` argument, which was introduced in v1.0.0.fixPass the `undo` argument when calling `spectate.events.rollback()`, for example: `spectate.events.rollback(my_undo_function)`.
Warnings
- breaking Event objects returned by Spectate (e.g., from `spectate.events.current_event()`) are now standard Python dictionaries, not `Immutable` (dict-like) objects with attribute access.
- breaking The `spectate.utils.Immutable` class has been completely removed.
- breaking The `undo` parameter for `spectate.events.rollback()` is now required.
Install
-
pip install spectate
Imports
- track
from spectate import track
- undo
from spectate import undo
- redo
from spectate import redo
- rollback
from spectate import rollback
- Immutable
from spectate.utils import Immutable
N/A (removed)
Quickstart
from spectate import track, undo, redo
a = {}
@track(a)
def add_entry(key, value):
a[key] = value
add_entry('x', 1)
add_entry('y', 2)
print(f"Initial state: {a}")
undo()
print(f"After first undo: {a}")
undo()
print(f"After second undo: {a}")
redo()
print(f"After first redo: {a}")
redo()
print(f"After second redo: {a}")