Add verifier

This commit is contained in:
lash 2022-03-11 10:31:08 +00:00
parent 9f71401bb5
commit 9ad005ae42
Signed by: lash
GPG Key ID: 21D2E7BB88C2A746
6 changed files with 28 additions and 6 deletions

View File

@ -1,3 +1,7 @@
- 0.1.1
* Add optional, pluggable verifier to protect state transition
- 0.1.0
* Release version bump
- 0.0.19:
* Enable alias with comma separated values
- 0.0.18

View File

@ -1,6 +1,6 @@
[metadata]
name = shep
version = 0.1.0rc1
version = 0.1.1rc1
description = Multi-state key stores using bit masks
author = Louis Holbrook
author_email = dev@holbrook.no

View File

@ -26,3 +26,9 @@ class StateCorruptionError(RuntimeError):
"""An irrecoverable discrepancy between persisted state and memory state has occurred.
"""
pass
class StateTransitionInvalid(Exception):
"""Raised if state transition verification fails
"""
pass

View File

@ -1,12 +1,18 @@
# standard imports
import re
# local imports
from shep.error import (
StateExists,
StateInvalid,
StateItemExists,
StateItemNotFound,
StateTransitionInvalid,
)
re_name = r'^[a-zA-Z_]+$'
class State:
"""State is an in-memory bitmasked state store for key-value pairs, or even just keys alone.
@ -22,17 +28,17 @@ class State:
base_state_name = 'NEW'
def __init__(self, bits, logger=None):
def __init__(self, bits, logger=None, verifier=None):
self.__bits = bits
self.__limit = (1 << bits) - 1
self.__c = 0
setattr(self, self.base_state_name, 0)
#self.NEW = 0
self.__reverse = {0: getattr(self, self.base_state_name)}
self.__keys = {getattr(self, self.base_state_name): []}
self.__keys_reverse = {}
self.__contents = {}
self.verifier = verifier
@classmethod
@ -54,8 +60,8 @@ class State:
# validates a state name and return its canonical representation
def __check_name_valid(self, k):
if not k.isalpha():
raise ValueError('only alpha')
if not re.match(re_name, k):
raise ValueError('only alpha and underscore')
return k.upper()
@ -323,6 +329,11 @@ class State:
if current_state_list == None:
raise StateCorruptionError(to_state)
if self.verifier != None:
r = self.verifier(self, from_state, to_state)
if r != None:
raise StateTransitionInvalid('{} -> {}: {}'.format(from_state, to_state, r))
self.__add_state_list(to_state, key)
current_state_list.pop(idx)

2
shep/verify.py Normal file
View File

@ -0,0 +1,2 @@
def default_checker(statestore, old, new):
return None

View File

@ -18,7 +18,6 @@ class TestState(unittest.TestCase):
for k in [
'f0o',
'f oo',
'f_oo',
]:
with self.assertRaises(ValueError):
states.add(k)