new class: IndexedDict

- dict that keeps a list of keys for efficient lookup by index
This commit is contained in:
The MMGen Project 2019-06-05 14:06:03 +00:00
commit b15a295e6a
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
3 changed files with 98 additions and 5 deletions

View file

@ -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

View file

@ -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)

View 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