Commit d3e1025b authored by Matt Traudt's avatar Matt Traudt
Browse files

Add State class and 100% test coverage for it

GH: ref #166
parent a7816baf
from sbws.util.filelock import FileLock
import os
import json
class State:
_ALLOWED_TYPES = (int, float, str, bool, type(None))
def __init__(self, fname):
self._fname = fname
self._state = self._read()
def _read(self):
with FileLock(self._fname):
if not os.path.exists(self._fname):
return {}
with open(self._fname, 'rt') as fd:
return json.load(fd)
def _write(self):
with FileLock(self._fname):
with open(self._fname, 'wt') as fd:
return json.dump(self._state, fd)
def __len__(self):
self._state = self._read()
return self._state.__len__()
def __getitem__(self, key):
if not isinstance(key, str):
raise TypeError(
'Keys must be strings. %s is a %s' % (key, type(key)))
self._state = self._read()
return self._state.__getitem__(key)
def __delitem__(self, key):
if not isinstance(key, str):
raise TypeError(
'Keys must be strings. %s is a %s' % (key, type(key)))
self._state = self._read()
self._state.__delitem__(key)
self._write()
def __setitem__(self, key, value):
if not isinstance(key, str):
raise TypeError(
'Keys must be strings. %s is a %s' % (key, type(key)))
if type(value) not in State._ALLOWED_TYPES:
raise TypeError(
'May only store value with type in %s, not %s' %
(State._ALLOWED_TYPES, type(value)))
self._state = self._read()
self._state.__setitem__(key, value)
self._write()
def __iter__(self):
self._state = self._read()
return self._state.__iter__()
def __contains__(self, item):
self._state = self._read()
return self._state.__contains__(item)
from sbws.util.state import State
import os
# from tempfile import NamedTemporaryFile as NTF
def test_state_set_allowed_key_types(tmpdir):
state = State(os.path.join(tmpdir, 'statefoo'))
attempt_keys = ('k')
for key in attempt_keys:
state[key] = 4
assert state[key] == 4
def test_state_set_bad_key_types(tmpdir):
state = State(os.path.join(tmpdir, 'statefoo'))
attempt_keys = (15983, None, True, -1.2, [], {}, set())
for key in attempt_keys:
try:
state[key] = 4
except TypeError:
pass
else:
assert None, 'Should not have been able to use %s %s as a key' %\
(key, type(key))
try:
state[key]
except TypeError:
pass
else:
assert None, '%s %s is not a valid key type, so should have got '\
'TypeError when giving it' % (key, type(key))
def test_state_set_allowed_value_types(tmpdir):
state = State(os.path.join(tmpdir, 'statefoo'))
attempt_vals = (15983, None, True, -1.2, 'loooooool')
for val in attempt_vals:
state['foo'] = val
assert state['foo'] == val
def test_state_set_bad_value_types(tmpdir):
state = State(os.path.join(tmpdir, 'statefoo'))
attempt_vals = ([], {}, set())
for val in attempt_vals:
try:
state['foo'] = val
except TypeError:
pass
else:
assert None, 'Should not have been able to use %s %s as a value' %\
(val, type(val))
def test_state_del(tmpdir):
state = State(os.path.join(tmpdir, 'statefoo'))
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
for key in d:
state[key] = d[key]
assert len(state) == len(d)
del d['a']
del state['a']
assert len(state) == len(d)
for key in d:
assert d[key] == state[key]
attempt_keys = (15983, None, True, -1.2, [], {}, set())
for key in attempt_keys:
try:
del state[False]
except TypeError:
pass
else:
assert None, 'Should not have been allowed to delete %s %s '\
'because it is not a valid key type' % (key, type(key))
d['e'] = 5
state['e'] = 5
d['e'] = 5.5
state['e'] = 5.5
assert len(state) == len(d)
def test_state_get_len(tmpdir):
state = State(os.path.join(tmpdir, 'statefoo'))
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
for key in d:
state[key] = d[key]
assert len(state) == len(d)
del d['a']
del state['a']
assert len(state) == len(d)
d['e'] = 5
state['e'] = 5
d['e'] = 5.5
state['e'] = 5.5
assert len(state) == len(d)
def test_state_contains(tmpdir):
state = State(os.path.join(tmpdir, 'statefoo'))
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
for key in d:
state[key] = d[key]
assert 'a' in state
assert 'e' not in state
def test_state_iter(tmpdir):
state = State(os.path.join(tmpdir, 'statefoo'))
for key in state:
pass
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
for key in d:
state[key] = d[key]
for key in state:
pass
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment