shep/shep/state.py

114 lines
2.3 KiB
Python
Raw Normal View History

2022-01-31 09:32:48 +01:00
# standard imports
import enum
# local imports
from shep.error import (
2022-01-31 09:38:14 +01:00
StateExists,
StateInvalid,
)
2022-01-31 09:32:48 +01:00
class State:
2022-01-31 10:55:56 +01:00
def __init__(self, bits, logger=None, store=None):
2022-01-31 09:32:48 +01:00
self.__bits = bits
2022-01-31 09:38:14 +01:00
self.__limit = (1 << bits) - 1
2022-01-31 09:32:48 +01:00
self.__c = 0
self.__reverse = {}
2022-01-31 10:55:56 +01:00
self.__logger = logger
self.__store = store
2022-01-31 09:32:48 +01:00
2022-01-31 09:38:14 +01:00
def __is_pure(self, v):
c = 1
for i in range(self.__bits):
if c & v > 0:
break
c <<= 1
return c == v
2022-01-31 09:32:48 +01:00
2022-01-31 09:38:14 +01:00
def __check_name(self, k):
2022-01-31 10:12:49 +01:00
if not k.isalpha():
raise ValueError('only alpha')
2022-01-31 09:38:14 +01:00
k = k.upper()
2022-01-31 09:32:48 +01:00
try:
getattr(self, k)
raise StateExists(k)
except AttributeError:
pass
2022-01-31 09:38:14 +01:00
return k
2022-01-31 09:32:48 +01:00
def __check_valid(self, v):
2022-01-31 09:38:14 +01:00
v = int(v)
if self.__reverse.get(v):
2022-01-31 10:55:56 +01:00
raise StateExists(v)
return v
def __check_value(self, v):
v = self.__check_valid(v)
2022-01-31 09:38:14 +01:00
if v > self.__limit:
raise OverflowError(v)
return v
def __check_value_cursor(self, v):
v = self.__check_valid(v)
if v > 1 << self.__c:
raise StateInvalid(v)
return v
2022-01-31 09:38:14 +01:00
def __set(self, k, v):
setattr(self, k, v)
self.__reverse[v] = k
2022-01-31 09:32:48 +01:00
self.__c += 1
2022-01-31 09:38:14 +01:00
def add(self, k):
v = 1 << self.__c
k = self.__check_name(k)
v = self.__check_value(v)
2022-01-31 09:38:14 +01:00
self.__set(k, v)
def alias(self, k, v):
k = self.__check_name(k)
v = self.__check_value_cursor(v)
2022-01-31 09:38:14 +01:00
if self.__is_pure(v):
raise ValueError('use add to add pure values')
self.__set(k, v)
2022-01-31 10:12:49 +01:00
def all(self):
l = []
for k in dir(self):
if k[0] == '_':
continue
if k.upper() != k:
continue
l.append(k)
l.sort()
return l
2022-01-31 10:55:56 +01:00
def match(self, v, pure=False):
r = []
2022-01-31 10:55:56 +01:00
if not pure:
m = self.__reverse.get(v)
if m != None:
r.append(m)
c = 1
for i in range(self.__bits):
if v & c > 0:
2022-01-31 10:55:56 +01:00
try:
k = self.__reverse[c]
r.append(k)
except KeyError:
pass
c <<= 1
return r