mmnode-blocks-info: --fields: support +<list>-<list>, 'all'-<list>

This commit is contained in:
The MMGen Project 2021-03-25 11:59:14 +00:00
commit ae03007bba
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
3 changed files with 70 additions and 18 deletions

View file

@ -124,28 +124,42 @@ class BlocksInfo:
t_fmt = lambda self,t: f'{t/86400:.2f} days' if t > 172800 else f'{t/3600:.2f} hrs'
def __init__(self,cmd_args,opt,rpc):
@classmethod
def parse_cslist(cls,uarg,full_set,dfl_set,desc):
def parse_cslist(uarg,full_set,dfl_set,desc):
m = re.match('([+-]){1}',uarg)
pfx = m[1] if m else None
usr_set = set((uarg[1:] if m else uarg).split(','))
dfl_set = set(dfl_set)
for e in usr_set:
if e not in full_set:
die(1,f'{e!r}: unrecognized {desc}')
res = (
dfl_set | usr_set if pfx == '+' else
dfl_set - usr_set if pfx == '-' else
usr_set
)
def make_list(m,func):
groups_lc = [set(e.lower() for e in g.split(',')) for g in m.groups()]
for group in groups_lc:
for e in group:
if e not in full_set_lc:
die(1,f'{e!r}: unrecognized {desc}')
# display elements in order:
return [e for e in full_set if e in res]
return [e for e in full_set if e.lower() in func(groups_lc)]
full_set_lc = set(e.lower() for e in full_set)
dfl_set_lc = set(e.lower() for e in dfl_set)
cspat = r'(\w+(?:,\w+)*)'
for pat,func in (
( rf'{cspat}$', lambda g: g[0] ),
( rf'\+{cspat}$', lambda g: dfl_set_lc | g[0] ),
( rf'\-{cspat}$', lambda g: dfl_set_lc - g[0] ),
( rf'\+{cspat}\-{cspat}$', lambda g: ( dfl_set_lc | g[0] ) - g[1] ),
( rf'\-{cspat}\+{cspat}$', lambda g: ( dfl_set_lc - g[0] ) | g[1] ),
( rf'all\-{cspat}$', lambda g: full_set_lc - g[0] )
):
m = re.match(pat,uarg,re.ASCII|re.IGNORECASE)
if m:
return make_list(m,func)
else:
die(1,f'{uarg}: invalid parameter')
def __init__(self,cmd_args,opt,rpc):
def parse_cs_uarg(uarg,full_set,dfl_set,desc):
return (
full_set if uarg == 'all' else [] if uarg == 'none' else
parse_cslist(uarg,full_set,dfl_set,desc)
self.parse_cslist(uarg,full_set,dfl_set,desc)
)
def get_fields():

View file

@ -57,7 +57,10 @@ opts_data = {
See AVAILABLE FIELDS below. Prefix the list with '+'
to add the fields to the defaults, or '-' to remove
them. The special values 'all' and 'none' select all
available fields or none, respectively.
available fields or none, respectively. The '+' and
'-'-prefixed lists may be concatenated to specify both
addition and removal of fields. A single '-'-prefixed
list may be additionally prefixed by 'all'.
-s, --stats= Display the specified stats (comma-separated list).
See AVAILABLE STATS below. The prefixes and special
values available to the --fields option are recognized.
@ -120,9 +123,16 @@ EXAMPLES:
fields from the defaults and skipping stats:
$ {p} -o -size,subsidy -s none +10
Display data for the last ten blocks, omitting the 'size' and 'version'
fields from the defaults and adding the 'inputs' and 'utxo_inc' fields:
$ {p} -o -version,size+utxo_inc,inputs +10
Display all fields and stats for the last ten blocks:
$ {p} -o all -s all +10
Same as above, but omit the 'miner' and 'hash' fields:
$ {p} -o all-miner,hash -s all +10
Same as above, but display only fields relating to stats:
$ {p} -o none -s all -f +10

View file

@ -45,6 +45,24 @@ range_vecs = (
( '+144*10+12*12', (tip-1439, tip, None, 1440, 144 ), (tip-1439, tip, list(range(tip-1439,tip+1,144))) ),
)
full_set = ['aa','bbb','ccc_P2','ddddd','eeeeee','ffffffff','gg']
dfl_set = ['aa','ddddd','ffffffff']
fields_vecs = (
( 'Ccc_P2', ['ccc_P2'] ),
( '+CCC_P2', ['aa','ccc_P2','ddddd','ffffffff'] ),
( '+Aa', dfl_set ),
( '+ddDDD,FffffffF', dfl_set ),
( '+bBb', ['aa','bbb','ddddd','ffffffff'] ),
( '-ddddd', ['aa','ffffffff'] ),
( '-DDDDD,fFffffff', ['aa'] ),
( '-ffffffff,AA,DdDdD', [] ),
( '+aa,gG,ccC_P2', ['aa','ccc_P2','ddddd','ffffffff','gg'] ),
( '+BBB,gg-dDddD,fFffffff', ['aa','bbb','gg'] ),
( '-dDddD,fFffffff+BBB,gg', ['aa','bbb','gg'] ),
( 'aLL-Ccc_P2', [e for e in full_set if e != 'ccc_P2'] ),
( 'All-dDddd,aa', [e for e in full_set if e not in ('aa','ddddd')] ),
)
class dummyRPC:
blockcount = tip
@ -57,6 +75,16 @@ class dummyOpt:
class unit_tests:
def parse_field(self,name,ut):
vmsg('{:28} => {}'.format('FULL SET:',full_set))
vmsg('{:28} => {}'.format('DFL SET: ',dfl_set))
b = BlocksInfo
for opt,chk in fields_vecs:
ret = b.parse_cslist(opt,full_set,dfl_set,'field')
vmsg(f'{opt:28} => {ret}')
assert ret == chk, f'{ret} != {chk}'
return True
def parse_rangespec(self,name,ut):
b = BlocksInfo(0,dummyOpt(),dummyRPC())