new class: IndexedDict
- dict that keeps a list of keys for efficient lookup by index
This commit is contained in:
parent
792c791910
commit
b15a295e6a
3 changed files with 98 additions and 5 deletions
30
mmgen/obj.py
30
mmgen/obj.py
|
|
@ -112,6 +112,36 @@ class MMGenObject(object):
|
|||
import re
|
||||
return re.sub('\n+','\n',''.join(out))
|
||||
|
||||
# dict that keeps a list of keys for efficient lookup by index
|
||||
class IndexedDict(dict):
|
||||
|
||||
def __init__(self,*args,**kwargs):
|
||||
if args or kwargs:
|
||||
self.die('initializing values via constructor')
|
||||
self.__keylist = []
|
||||
return dict.__init__(self,*args,**kwargs)
|
||||
|
||||
def __setitem__(self,key,value):
|
||||
if key in self:
|
||||
self.die('reassignment to existing key')
|
||||
self.__keylist.append(key)
|
||||
return dict.__setitem__(self,key,value)
|
||||
|
||||
@property
|
||||
def keys(self):
|
||||
return self.__keylist
|
||||
|
||||
def key(self,idx):
|
||||
return self.__keylist[idx]
|
||||
|
||||
def __delitem__(self,*args): self.die('item deletion')
|
||||
def move_to_end(self,*args): self.die('item moving')
|
||||
def clear(self,*args): self.die('clearing')
|
||||
def update(self,*args): self.die('updating')
|
||||
|
||||
def die(self,desc):
|
||||
raise NotImplementedError('{} not implemented for type {}'.format(desc,type(self).__name__))
|
||||
|
||||
class MMGenList(list,MMGenObject): pass
|
||||
class MMGenDict(dict,MMGenObject): pass
|
||||
class AddrListList(list,MMGenObject): pass
|
||||
|
|
|
|||
|
|
@ -70,14 +70,13 @@ class SubSeedList(MMGenObject):
|
|||
def __init__(self,parent_seed):
|
||||
self.member_type = SubSeed
|
||||
self.parent_seed = parent_seed
|
||||
from collections import OrderedDict
|
||||
self.data = { 'long': OrderedDict(), 'short': OrderedDict() }
|
||||
self.data = { 'long': IndexedDict(), 'short': IndexedDict() }
|
||||
|
||||
def __len__(self):
|
||||
return len(self.data['long'])
|
||||
|
||||
def get_params_by_ss_idx(self,ss_idx):
|
||||
sid = list(self.data[ss_idx.type].keys())[ss_idx.idx-1]
|
||||
sid = self.data[ss_idx.type].key(ss_idx.idx-1)
|
||||
idx,nonce = self.data[ss_idx.type][sid]
|
||||
return (sid,idx,nonce)
|
||||
|
||||
|
|
@ -184,8 +183,8 @@ class SubSeedList(MMGenObject):
|
|||
hdr += fs1.format('Long Subseeds','Short Subseeds')
|
||||
hdr += fs1.format('-------------','--------------')
|
||||
|
||||
sl = tuple(self.data['long'])
|
||||
ss = tuple(self.data['short'])
|
||||
sl = self.data['long'].keys
|
||||
ss = self.data['short'].keys
|
||||
body = (fs2.format(sl[n-1],ss[n-1],i=n) for n in r.iterate())
|
||||
|
||||
return hdr + ''.join(body)
|
||||
|
|
|
|||
64
test/unit_tests_d/ut_indexed_dict.py
Executable file
64
test/unit_tests_d/ut_indexed_dict.py
Executable file
|
|
@ -0,0 +1,64 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
test/unit_tests_d/ut_indexed_dict: IndexedDict class unit test for the MMGen suite
|
||||
"""
|
||||
|
||||
from mmgen.common import *
|
||||
|
||||
class unit_test(object):
|
||||
|
||||
def run_test(self,name):
|
||||
bad_msg = ( 'initializing values via constructor',
|
||||
'reassignment to existing key',
|
||||
'item deletion',
|
||||
'item moving',
|
||||
'clearing',
|
||||
'updating' )
|
||||
def bad0(): IndexedDict(arg)
|
||||
def bad1(): d['a'] = 2
|
||||
def bad2(): del d['a']
|
||||
def bad3(): d.move_to_end('a')
|
||||
def bad4(): d.clear()
|
||||
def bad5(): d.update(d)
|
||||
|
||||
def odie(n): rdie(3,"\nillegal action '{}' failed to raise exception".format(bad_msg[n]))
|
||||
def omsg(e): vmsg(' - ' + e.args[0])
|
||||
|
||||
msg_r('Testing class IndexedDict...')
|
||||
|
||||
from mmgen.obj import IndexedDict
|
||||
d = IndexedDict()
|
||||
|
||||
d['a'] = 1
|
||||
d['b'] = 2
|
||||
|
||||
vmsg('\nChecking error handling:')
|
||||
|
||||
arg = [('a',1),('b',2)]
|
||||
dict(arg)
|
||||
|
||||
for i in range(6):
|
||||
try: locals()['bad'+str(i)]()
|
||||
except NotImplementedError as e: omsg(e)
|
||||
else: odie(i)
|
||||
|
||||
try: d.key(2)
|
||||
except Exception as e: omsg(e)
|
||||
else: odie('list index out of range')
|
||||
|
||||
d['c'] = 3
|
||||
|
||||
d_chk = {'a':1,'b':2,'c':3}
|
||||
assert d == d_chk, d
|
||||
|
||||
d_keys_chk = ['a','b','c']
|
||||
assert d.keys == d_keys_chk, d.keys
|
||||
|
||||
A = d.key(0)
|
||||
assert A == 'a', A
|
||||
|
||||
A = d.key(2)
|
||||
assert A == 'c', A
|
||||
|
||||
msg('OK')
|
||||
return True
|
||||
Loading…
Add table
Add a link
Reference in a new issue