class SmashTableError(Exception) Also raised on its own for a failure no caller can act on, such as a staged version missing when a transaction unwound. Retrying one of those cannot help.
pip install smashtableThe wheel ships type stubs, so an editor completes the container methods and a checker rejects a misspelled isolation level or key layout before the call ever runs.
Two indexes over the same entities have to move together, or a lookup by name finds an identifier that no longer resolves:
import smashtable as st
by_id = st.SortedMap(key=int) # entity id → record
by_name = st.SortedMap(key=str) # name → entity id
with st.transaction(by_id, by_name) as (ids, names):
ids[42] = "carol"
names["carol"] = 42
# both indexes have changedEach container is a mapping in its own right, so the usual vocabulary works:
list(by_id) # [42] — keys, in order
dict(by_name) # {'carol': 42}
by_id.items() # a lazy view, not a copy
by_id.scan(0, 100) # the half-open window [0, 100)If the block raises, nothing was applied:
try:
with st.transaction(by_id, by_name) as (ids, names):
ids[43] = "dave"
names["dave"] = 43
raise ValueError("failed validation")
except ValueError:
pass
assert 43 not in by_id and "dave" not in by_nameWithout this, the alternative is an O(n) defensive copy that every alias to the container can still read through mid-update:
backup = dict(cache) # copies the whole thing
try:
for key, value in updates.items():
cache[key] = transform(value) # raises on item 40 of 100
except Exception:
cache.clear(); cache.update(backup) # O(n) again, and readers already saw the torn stateSmashTableErrorBase of every refusal this module raises, so one except catches the family.class SmashTableError(Exception) Also raised on its own for a failure no caller can act on, such as a staged version missing when a transaction unwound. Retrying one of those cannot help.