1 Commits

Author SHA1 Message Date
lash
3039595d40 Release version 2022-03-11 10:31:46 +00:00
3 changed files with 12 additions and 85 deletions

View File

@@ -1,64 +0,0 @@
from shep.state import State
# we don't like "NEW" as the default label for a new item in the queue, so we change it to BACKLOG
State.set_default_state('backlog')
# define all the valid states
st = State(5)
st.add('pending')
st.add('blocked')
st.add('doing')
st.add('review')
st.add('finished')
# define a couple of states that give a bit more context to progress; something is blocked before starting development or something is blocked during development...
st.alias('startblock', st.BLOCKED, st.PENDING)
st.alias('doingblock', st.BLOCKED, st.DOING)
# create the foo key which will forever languish in backlog
k = 'foo'
st.put(k)
foo_state = st.state(k)
foo_state_name = st.name(foo_state)
foo_contents_r = st.get('foo')
print('{} {} {}'.format(k, foo_state_name, foo_contents_r))
# Create bar->baz and advance it from backlog to pending
k = 'bar'
bar_contents = 'baz'
st.put(k, contents=bar_contents)
st.next(k)
bar_state = st.state(k)
bar_state_name = st.name(bar_state)
bar_contents_r = st.get('bar')
print('{} {} {}'.format(k, bar_state_name, bar_contents_r))
# Create inky->pinky and move to doing then doing-blocked
k = 'inky'
inky_contents = 'pinky'
st.put(k, contents=inky_contents)
inky_state = st.state(k)
st.move(k, st.DOING)
st.set(k, st.BLOCKED)
inky_state = st.state(k)
inky_state_name = st.name(inky_state)
inky_contents_r = st.get('inky')
print('{} {} {}'.format(k, inky_state_name, bar_contents_r))
# then replace the content
# note that replace could potentially mean some VCS below
inky_new_contents = 'blinky'
st.replace(k, inky_new_contents)
inky_contents_r = st.get('inky')
print('{} {} {}'.format(k, inky_state_name, inky_contents_r))
# so now move to review
st.move(k, st.REVIEW)
inky_state = st.state(k)
inky_state_name = st.name(inky_state)
print('{} {} {}'.format(k, inky_state_name, inky_contents_r))

View File

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

View File

@@ -19,27 +19,18 @@ class State:
:param logger: Standard library logging instance to output to
:type logger: logging.Logger
"""
base_state_name = 'NEW'
def __init__(self, bits, logger=None):
self.__bits = bits
self.__limit = (1 << bits) - 1
self.__c = 0
setattr(self, self.base_state_name, 0)
#self.NEW = 0
self.NEW = 0
self.__reverse = {0: getattr(self, self.base_state_name)}
self.__keys = {getattr(self, self.base_state_name): []}
self.__reverse = {0: self.NEW}
self.__keys = {self.NEW: []}
self.__keys_reverse = {}
self.__contents = {}
@classmethod
def set_default_state(cls, state_name):
cls.base_state_name = state_name.upper()
# return true if v is a single-bit state
def __is_pure(self, v):
if v == 0:
@@ -206,7 +197,7 @@ class State:
:return: State name
"""
if v == None or v == 0:
return self.base_state_name
return 'NEW'
k = self.__reverse.get(v)
if k == None:
raise StateInvalid(v)
@@ -261,13 +252,13 @@ class State:
def put(self, key, state=None, contents=None):
"""Add a key to an existing state.
If no state it specified, the default state attribute State.base_state_name will be used.
If no state it specified, the default state attribute "NEW" will be used.
Contents may be supplied as value to pair with the given key. Contents may be changed later by calling the `replace` method.
:param key: Content key to add
:type key: str
:param state: Initial state for the put. If not given, initial state will be State.base_state_name
:param state: Initial state for the put. If not given, initial state will be NEW
:type state: int
:param contents: Contents to associate with key. A valie of None should be recognized as an undefined value as opposed to a zero-length value throughout any backend
:type contents: str
@@ -277,7 +268,7 @@ class State:
:return: Resulting state that key is put under (should match the input state)
"""
if state == None:
state = getattr(self, self.base_state_name)
state = self.NEW
elif self.__reverse.get(state) == None:
raise StateInvalid(state)
self.__check_key(key)
@@ -360,13 +351,13 @@ class State:
def unset(self, key, not_state):
"""Unset a single bit, moving to a pure or alias state.
The resulting state cannot be State.base_state_name (0).
The resulting state cannot be NEW (0).
:param key: Content key to modify state for
:type key: str
:param or_state: Atomic stat to add
:type or_state: int
:raises ValueError: State is not a single bit state, or attempts to revert to State.base_state_name
:raises ValueError: State is not a single bit state, or attempts to revert to NEW
:raises StateItemNotFound: Content key is not registered
:raises StateInvalid: Resulting state after addition of atomic state is unknown
:rtype: int
@@ -383,8 +374,8 @@ class State:
if to_state == current_state:
raise ValueError('invalid change for state {}: {}'.format(key, not_state))
if to_state == getattr(self, self.base_state_name):
raise ValueError('State {} for {} cannot be reverted to {}'.format(current_state, key, self.base_state_name))
if to_state == self.NEW:
raise ValueError('State {} for {} cannot be reverted to NEW'.format(current_state, key))
new_state = self.__reverse.get(to_state)
if new_state == None: