Add verifier
This commit is contained in:
parent
9f71401bb5
commit
9ad005ae42
@ -1,3 +1,7 @@
|
|||||||
|
- 0.1.1
|
||||||
|
* Add optional, pluggable verifier to protect state transition
|
||||||
|
- 0.1.0
|
||||||
|
* Release version bump
|
||||||
- 0.0.19:
|
- 0.0.19:
|
||||||
* Enable alias with comma separated values
|
* Enable alias with comma separated values
|
||||||
- 0.0.18
|
- 0.0.18
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[metadata]
|
[metadata]
|
||||||
name = shep
|
name = shep
|
||||||
version = 0.1.0rc1
|
version = 0.1.1rc1
|
||||||
description = Multi-state key stores using bit masks
|
description = Multi-state key stores using bit masks
|
||||||
author = Louis Holbrook
|
author = Louis Holbrook
|
||||||
author_email = dev@holbrook.no
|
author_email = dev@holbrook.no
|
||||||
|
@ -26,3 +26,9 @@ class StateCorruptionError(RuntimeError):
|
|||||||
"""An irrecoverable discrepancy between persisted state and memory state has occurred.
|
"""An irrecoverable discrepancy between persisted state and memory state has occurred.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class StateTransitionInvalid(Exception):
|
||||||
|
"""Raised if state transition verification fails
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
@ -1,12 +1,18 @@
|
|||||||
|
# standard imports
|
||||||
|
import re
|
||||||
|
|
||||||
# local imports
|
# local imports
|
||||||
from shep.error import (
|
from shep.error import (
|
||||||
StateExists,
|
StateExists,
|
||||||
StateInvalid,
|
StateInvalid,
|
||||||
StateItemExists,
|
StateItemExists,
|
||||||
StateItemNotFound,
|
StateItemNotFound,
|
||||||
|
StateTransitionInvalid,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
re_name = r'^[a-zA-Z_]+$'
|
||||||
|
|
||||||
class State:
|
class State:
|
||||||
"""State is an in-memory bitmasked state store for key-value pairs, or even just keys alone.
|
"""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'
|
base_state_name = 'NEW'
|
||||||
|
|
||||||
def __init__(self, bits, logger=None):
|
def __init__(self, bits, logger=None, verifier=None):
|
||||||
self.__bits = bits
|
self.__bits = bits
|
||||||
self.__limit = (1 << bits) - 1
|
self.__limit = (1 << bits) - 1
|
||||||
self.__c = 0
|
self.__c = 0
|
||||||
setattr(self, self.base_state_name, 0)
|
setattr(self, self.base_state_name, 0)
|
||||||
#self.NEW = 0
|
|
||||||
|
|
||||||
self.__reverse = {0: getattr(self, self.base_state_name)}
|
self.__reverse = {0: getattr(self, self.base_state_name)}
|
||||||
self.__keys = {getattr(self, self.base_state_name): []}
|
self.__keys = {getattr(self, self.base_state_name): []}
|
||||||
self.__keys_reverse = {}
|
self.__keys_reverse = {}
|
||||||
self.__contents = {}
|
self.__contents = {}
|
||||||
|
self.verifier = verifier
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -54,8 +60,8 @@ class State:
|
|||||||
|
|
||||||
# validates a state name and return its canonical representation
|
# validates a state name and return its canonical representation
|
||||||
def __check_name_valid(self, k):
|
def __check_name_valid(self, k):
|
||||||
if not k.isalpha():
|
if not re.match(re_name, k):
|
||||||
raise ValueError('only alpha')
|
raise ValueError('only alpha and underscore')
|
||||||
return k.upper()
|
return k.upper()
|
||||||
|
|
||||||
|
|
||||||
@ -323,6 +329,11 @@ class State:
|
|||||||
if current_state_list == None:
|
if current_state_list == None:
|
||||||
raise StateCorruptionError(to_state)
|
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)
|
self.__add_state_list(to_state, key)
|
||||||
current_state_list.pop(idx)
|
current_state_list.pop(idx)
|
||||||
|
|
||||||
|
2
shep/verify.py
Normal file
2
shep/verify.py
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
def default_checker(statestore, old, new):
|
||||||
|
return None
|
@ -18,7 +18,6 @@ class TestState(unittest.TestCase):
|
|||||||
for k in [
|
for k in [
|
||||||
'f0o',
|
'f0o',
|
||||||
'f oo',
|
'f oo',
|
||||||
'f_oo',
|
|
||||||
]:
|
]:
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
states.add(k)
|
states.add(k)
|
||||||
|
Loading…
Reference in New Issue
Block a user