From d9a2e0cfd1d0015bee3774c2d10deb0ac35603e6 Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Thu, 1 Dec 2022 12:32:31 +0000 Subject: [PATCH] AddrIdxList: cleanups, new `id_str` property --- mmgen/addrlist.py | 69 ++++++++++++++++++----------- test/objtest_py_d/ot_btc_mainnet.py | 8 ++-- test/unit_tests_d/ut_addrlist.py | 24 ++++++++++ 3 files changed, 71 insertions(+), 30 deletions(-) diff --git a/mmgen/addrlist.py b/mmgen/addrlist.py index fcb48a28..ce8bec77 100755 --- a/mmgen/addrlist.py +++ b/mmgen/addrlist.py @@ -31,35 +31,52 @@ def dmsg_sc(desc,data): if g.debug_addrlist: Msg(f'sc_debug_{desc}: {data}') -class AddrIdxList(list,InitErrors,MMGenObject): +class AddrIdxList(tuple,InitErrors,MMGenObject): + max_len = 1000000 - def __init__(self,fmt_str=None,idx_list=None,sep=','): + + def __new__(cls,fmt_str=None,idx_list=None,sep=','): try: - if idx_list: - return list.__init__(self,sorted({AddrIdx(i) for i in idx_list})) - elif fmt_str: - ret = [] - for i in (fmt_str.split(sep)): - j = i.split('-') - if len(j) == 1: - idx = AddrIdx(i) - if not idx: - break - ret.append(idx) - elif len(j) == 2: - beg = AddrIdx(j[0]) - if not beg: - break - end = AddrIdx(j[1]) - if not beg or (end < beg): - break - ret.extend([AddrIdx(x) for x in range(beg,end+1)]) - else: break - else: - return list.__init__(self,sorted(set(ret))) # fell off end of loop - success - raise ValueError(f'{i!r}: invalid range') + if fmt_str: + def gen(): + for i in (fmt_str.split(sep)): + j = [int(x) for x in i.split('-')] + if len(j) == 1: + yield j[0] + elif len(j) == 2: + if j[0] > j[1]: + raise ValueError(f'{i}: invalid range') + for k in range(j[0], j[1] + 1): + yield k + else: + raise ValueError(f'{i}: invalid range') + idx_list = tuple(gen()) + return tuple.__new__(cls,sorted({AddrIdx(i) for i in (idx_list or [])})) except Exception as e: - return type(self).init_fail(e,idx_list or fmt_str) + return cls.init_fail(e,idx_list or fmt_str) + + @property + def id_str(self): + + def gen(): + i_save = self[0] + yield f'{i_save}' + in_range = False + + for i in self[1:]: + if i - i_save == 1: + in_range = True + else: + if in_range: + in_range = False + yield f'-{i_save}' + yield f',{i}' + i_save = i + + if in_range: + yield f'-{i_save}' + + return ''.join(gen()) if self else '' class AddrListEntryBase(MMGenListItem): invalid_attrs = {'proto'} diff --git a/test/objtest_py_d/ot_btc_mainnet.py b/test/objtest_py_d/ot_btc_mainnet.py index d3bb1633..cb15314d 100755 --- a/test/objtest_py_d/ot_btc_mainnet.py +++ b/test/objtest_py_d/ot_btc_mainnet.py @@ -57,11 +57,11 @@ tests = { }, 'AddrIdxList': { 'arg1': 'fmt_str', - 'bad': ('x','5,9,1-2-3','8,-11','66,3-2'), + 'bad': ('x','5,9,1-2-3','8,-11','66,3-2','0-3'), 'good': ( - ('3,2,2',[2,3]), - ('101,1,3,5,2-7,99',[1,2,3,4,5,6,7,99,101]), - ({'idx_list':AddrIdxList('1-5')},[1,2,3,4,5]) + ('3,2,2',(2,3)), + ('101,1,3,5,2-7,99',(1,2,3,4,5,6,7,99,101)), + ({'idx_list':AddrIdxList('1-5')},(1,2,3,4,5)) ) }, 'SubSeedIdxRange': { diff --git a/test/unit_tests_d/ut_addrlist.py b/test/unit_tests_d/ut_addrlist.py index ad5ab1e9..4a29266e 100755 --- a/test/unit_tests_d/ut_addrlist.py +++ b/test/unit_tests_d/ut_addrlist.py @@ -55,6 +55,30 @@ def do_test(list_type,chksum,idx_spec=None,pw_id_str=None,add_kwargs=None): class unit_tests: + def idxlist(self,name,ut): + for i,o in ( + ('99,88-102,1-3,4,9,818,444-445,816', '1-4,9,88-102,444-445,816,818'), + ('99,88-99,100,102,4-7,9,818,444-445,816,1', '1,4-7,9,88-100,102,444-445,816,818'), + ('8', '8'), + ('2-4', '2-4'), + ('1,2-4', '1-4'), + ('2-4,1-9,9,1,8', '1-9'), + ('2-4,1', '1-4'), + ('2-2', '2'), + ('2,2', '2'), + ('2-3', '2-3'), + ('2,3', '2-3'), + ('3,2', '2-3'), + ('2,4', '2,4'), + ('', ''), + ): + l = AddrIdxList(i) + if opt.verbose: + msg('list: {}\nin: {}\nout: {}\n'.format(list(l),i,o)) + assert l.id_str == o, f'{l.id_str} != {o}' + + return True + def addr(self,name,ut): return ( do_test(AddrList,'BCE8 082C 0973 A525','1-3') and