|
@@ -13,6 +13,7 @@ cmdtest_d.include.group_mgr: Command group manager for the MMGen Wallet cmdtest
|
|
|
"""
|
|
"""
|
|
|
|
|
|
|
|
import sys, os, time
|
|
import sys, os, time
|
|
|
|
|
+from collections import namedtuple
|
|
|
|
|
|
|
|
from mmgen.color import yellow, green, cyan
|
|
from mmgen.color import yellow, green, cyan
|
|
|
from mmgen.util import Msg, die
|
|
from mmgen.util import Msg, die
|
|
@@ -44,6 +45,14 @@ class CmdGroupMgr:
|
|
|
self.network_id = cfg._proto.coin.lower() + ('_tn' if cfg._proto.testnet else '')
|
|
self.network_id = cfg._proto.coin.lower() + ('_tn' if cfg._proto.testnet else '')
|
|
|
self.name = type(self).__name__
|
|
self.name = type(self).__name__
|
|
|
|
|
|
|
|
|
|
+ @classmethod
|
|
|
|
|
+ def get_cmd_groups(cls, cfg):
|
|
|
|
|
+ exclude = cfg.exclude_groups.split(',') if cfg.exclude_groups else []
|
|
|
|
|
+ for e in exclude:
|
|
|
|
|
+ if e not in cmd_groups_dfl:
|
|
|
|
|
+ die(1, f'{e!r}: group not recognized')
|
|
|
|
|
+ return [s for s in cmd_groups_dfl if s not in exclude]
|
|
|
|
|
+
|
|
|
def create_cmd_group(self, cls, sg_name=None):
|
|
def create_cmd_group(self, cls, sg_name=None):
|
|
|
|
|
|
|
|
cmd_group_in = dict(cls.cmd_group_in)
|
|
cmd_group_in = dict(cls.cmd_group_in)
|
|
@@ -80,12 +89,12 @@ class CmdGroupMgr:
|
|
|
return tuple(gen())
|
|
return tuple(gen())
|
|
|
|
|
|
|
|
def load_mod(self, gname, modname=None):
|
|
def load_mod(self, gname, modname=None):
|
|
|
- clsname, kwargs = self.cmd_groups[gname]
|
|
|
|
|
- if modname is None and 'modname' in kwargs:
|
|
|
|
|
- modname = kwargs['modname']
|
|
|
|
|
|
|
+ grp = self.cmd_groups[gname]
|
|
|
|
|
+ if modname is None and 'modname' in grp.params:
|
|
|
|
|
+ modname = grp.params['modname']
|
|
|
import importlib
|
|
import importlib
|
|
|
modpath = f'test.cmdtest_d.{modname or gname}'
|
|
modpath = f'test.cmdtest_d.{modname or gname}'
|
|
|
- return getattr(importlib.import_module(modpath), clsname)
|
|
|
|
|
|
|
+ return getattr(importlib.import_module(modpath), grp.clsname)
|
|
|
|
|
|
|
|
def create_group(self, gname, sg_name, full_data=False, modname=None, is3seed=False, add_dpy=False):
|
|
def create_group(self, gname, sg_name, full_data=False, modname=None, is3seed=False, add_dpy=False):
|
|
|
"""
|
|
"""
|
|
@@ -94,38 +103,33 @@ class CmdGroupMgr:
|
|
|
without touching 'cmd_list'
|
|
without touching 'cmd_list'
|
|
|
"""
|
|
"""
|
|
|
|
|
|
|
|
- cls = self.load_mod(gname, modname)
|
|
|
|
|
- cdata = []
|
|
|
|
|
-
|
|
|
|
|
def get_shared_deps(cmdname, tmpdir_idx):
|
|
def get_shared_deps(cmdname, tmpdir_idx):
|
|
|
"""
|
|
"""
|
|
|
shared_deps are "implied" dependencies for all cmds in cmd_group that don't appear in
|
|
shared_deps are "implied" dependencies for all cmds in cmd_group that don't appear in
|
|
|
the cmd_group data or cmds' argument lists. Supported only for 3seed tests at present.
|
|
the cmd_group data or cmds' argument lists. Supported only for 3seed tests at present.
|
|
|
"""
|
|
"""
|
|
|
- if not hasattr(cls, 'shared_deps'):
|
|
|
|
|
- return []
|
|
|
|
|
-
|
|
|
|
|
return [k for k, v in cfgs[str(tmpdir_idx)]['dep_generators'].items()
|
|
return [k for k, v in cfgs[str(tmpdir_idx)]['dep_generators'].items()
|
|
|
- if k in cls.shared_deps and v != cmdname]
|
|
|
|
|
|
|
+ if k in cls.shared_deps and v != cmdname] if hasattr(cls, 'shared_deps') else []
|
|
|
|
|
+
|
|
|
|
|
+ cls = self.load_mod(gname, modname)
|
|
|
|
|
|
|
|
if not 'cmd_group' in cls.__dict__ and hasattr(cls, 'cmd_group_in'):
|
|
if not 'cmd_group' in cls.__dict__ and hasattr(cls, 'cmd_group_in'):
|
|
|
cls.cmd_group = self.create_cmd_group(cls, sg_name)
|
|
cls.cmd_group = self.create_cmd_group(cls, sg_name)
|
|
|
|
|
|
|
|
- for a, b in cls.cmd_group:
|
|
|
|
|
- if is3seed:
|
|
|
|
|
- for n, (i, j) in enumerate(zip(cls.tmpdir_nums, (128, 192, 256))):
|
|
|
|
|
- k = f'{a}_{n+1}'
|
|
|
|
|
- if hasattr(cls, 'skip_cmds') and k in cls.skip_cmds:
|
|
|
|
|
- continue
|
|
|
|
|
- sdeps = get_shared_deps(k, i)
|
|
|
|
|
- if isinstance(b, str):
|
|
|
|
|
- cdata.append((k, (i, f'{b} ({j}-bit)', [[[]+sdeps, i]])))
|
|
|
|
|
- else:
|
|
|
|
|
- cdata.append((k, (i, f'{b[1]} ({j}-bit)', [[b[0]+sdeps, i]])))
|
|
|
|
|
- elif full_data:
|
|
|
|
|
- cdata.append((a, b))
|
|
|
|
|
- else:
|
|
|
|
|
- cdata.append((a, (cls.tmpdir_nums[0], b, [[[], cls.tmpdir_nums[0]]])))
|
|
|
|
|
|
|
+ def gen_cdata():
|
|
|
|
|
+ cgd = namedtuple('cmd_group_data', ['tmpdir_num', 'desc', 'dpy_list'])
|
|
|
|
|
+ for a, b in cls.cmd_group:
|
|
|
|
|
+ if is3seed:
|
|
|
|
|
+ for n, (i, j) in enumerate(zip(cls.tmpdir_nums, [128, 192, 256])):
|
|
|
|
|
+ k = f'{a}_{n + 1}'
|
|
|
|
|
+ if not k in cls.skip_cmds:
|
|
|
|
|
+ yield (k, cgd(i, f'{b} ({j}-bit)', [[get_shared_deps(k, i), i]]))
|
|
|
|
|
+ elif full_data:
|
|
|
|
|
+ yield (a, cgd(*b))
|
|
|
|
|
+ else:
|
|
|
|
|
+ yield (a, cgd(cls.tmpdir_nums[0], b, [[[], cls.tmpdir_nums[0]]]))
|
|
|
|
|
+
|
|
|
|
|
+ cdata = tuple(gen_cdata()) # cannot use dict() here because of repeated keys
|
|
|
|
|
|
|
|
if add_dpy:
|
|
if add_dpy:
|
|
|
self.dpy_data.update(dict(cdata))
|
|
self.dpy_data.update(dict(cdata))
|
|
@@ -143,37 +147,52 @@ class CmdGroupMgr:
|
|
|
return cls
|
|
return cls
|
|
|
|
|
|
|
|
def gm_init_group(self, cfg, trunner, gname, sg_name, spawn_prog):
|
|
def gm_init_group(self, cfg, trunner, gname, sg_name, spawn_prog):
|
|
|
- kwargs = self.cmd_groups[gname][1]
|
|
|
|
|
- cls = self.create_group(gname, sg_name, **kwargs)
|
|
|
|
|
|
|
+ cls = self.create_group(gname, sg_name, **self.cmd_groups[gname].params)
|
|
|
cls.group_name = gname
|
|
cls.group_name = gname
|
|
|
return cls(cfg, trunner, cfgs, spawn_prog)
|
|
return cls(cfg, trunner, cfgs, spawn_prog)
|
|
|
|
|
|
|
|
def get_cls_by_gname(self, gname):
|
|
def get_cls_by_gname(self, gname):
|
|
|
- return self.load_mod(gname, self.cmd_groups[gname][1].get('modname'))
|
|
|
|
|
|
|
+ return self.load_mod(gname, self.cmd_groups[gname].params.get('modname'))
|
|
|
|
|
+
|
|
|
|
|
+ def list_cmds(self):
|
|
|
|
|
+
|
|
|
|
|
+ def gen_output():
|
|
|
|
|
+ yield green('AVAILABLE COMMANDS:')
|
|
|
|
|
+ for gname in self.cmd_groups:
|
|
|
|
|
+ tg = self.gm_init_group(self.cfg, None, gname, None, None)
|
|
|
|
|
+ gdesc = tg.__doc__.strip() if tg.__doc__ else type(tg).__name__
|
|
|
|
|
+ yield '\n' + green(f'{gname!r} - {gdesc}:')
|
|
|
|
|
+ name_w = max(len(cmd) for cmd in self.cmd_list)
|
|
|
|
|
+ for cmd in self.cmd_list:
|
|
|
|
|
+ data = self.dpy_data[cmd]
|
|
|
|
|
+ yield ' {a:{w}} - {b}'.format(
|
|
|
|
|
+ a = cmd,
|
|
|
|
|
+ b = data if isinstance(data, str) else data.desc,
|
|
|
|
|
+ w = name_w)
|
|
|
|
|
+
|
|
|
|
|
+ from mmgen.ui import do_pager
|
|
|
|
|
+ do_pager('\n'.join(gen_output()))
|
|
|
|
|
|
|
|
def list_cmd_groups(self):
|
|
def list_cmd_groups(self):
|
|
|
- ginfo = []
|
|
|
|
|
- for gname in self.cmd_groups:
|
|
|
|
|
- ginfo.append((gname, self.get_cls_by_gname(gname)))
|
|
|
|
|
|
|
|
|
|
if self.cfg.list_current_cmd_groups:
|
|
if self.cfg.list_current_cmd_groups:
|
|
|
- exclude = (self.cfg.exclude_groups or '').split(',')
|
|
|
|
|
- ginfo = [g for g in ginfo
|
|
|
|
|
- if self.network_id in g[1].networks
|
|
|
|
|
- and not g[0] in exclude
|
|
|
|
|
- and g[0] in tuple(self.cmd_groups_dfl) + tuple(self.cfg._args)]
|
|
|
|
|
|
|
+ names = tuple(cmd_groups_dfl) + tuple(self.cfg._args)
|
|
|
|
|
+ exclude = self.cfg.exclude_groups.split(',') if self.cfg.exclude_groups else []
|
|
|
|
|
+ ginfo = {name: cls
|
|
|
|
|
+ for name, cls in [(gname, self.get_cls_by_gname(gname)) for gname in names]
|
|
|
|
|
+ if self.network_id in cls.networks and not name in exclude}
|
|
|
desc = 'CONFIGURED'
|
|
desc = 'CONFIGURED'
|
|
|
else:
|
|
else:
|
|
|
|
|
+ ginfo = {name: self.get_cls_by_gname(name) for name in self.cmd_groups}
|
|
|
desc = 'AVAILABLE'
|
|
desc = 'AVAILABLE'
|
|
|
|
|
|
|
|
def gen_output():
|
|
def gen_output():
|
|
|
yield green(f'{desc} COMMAND GROUPS AND SUBGROUPS:')
|
|
yield green(f'{desc} COMMAND GROUPS AND SUBGROUPS:')
|
|
|
yield ''
|
|
yield ''
|
|
|
- for name, cls in ginfo:
|
|
|
|
|
|
|
+ name_w = max(len(name) for name in ginfo)
|
|
|
|
|
+ for name, cls in ginfo.items():
|
|
|
if not cls.is_helper:
|
|
if not cls.is_helper:
|
|
|
- yield ' {} - {}'.format(
|
|
|
|
|
- yellow(name.ljust(13)),
|
|
|
|
|
- (cls.__doc__.strip() if cls.__doc__ else cls.__name__))
|
|
|
|
|
|
|
+ yield ' {} - {}'.format(yellow(name.ljust(name_w)), cls.__doc__.strip())
|
|
|
if 'cmd_subgroups' in cls.__dict__:
|
|
if 'cmd_subgroups' in cls.__dict__:
|
|
|
subgroups = {k:v for k, v in cls.cmd_subgroups.items() if not k.startswith('_')}
|
|
subgroups = {k:v for k, v in cls.cmd_subgroups.items() if not k.startswith('_')}
|
|
|
max_w = max(len(k) for k in subgroups)
|
|
max_w = max(len(k) for k in subgroups)
|
|
@@ -182,8 +201,7 @@ class CmdGroupMgr:
|
|
|
|
|
|
|
|
from mmgen.ui import do_pager
|
|
from mmgen.ui import do_pager
|
|
|
do_pager('\n'.join(gen_output()))
|
|
do_pager('\n'.join(gen_output()))
|
|
|
-
|
|
|
|
|
- Msg('\n' + ' '.join(e[0] for e in ginfo))
|
|
|
|
|
|
|
+ Msg('\n' + ' '.join(ginfo))
|
|
|
|
|
|
|
|
def find_cmd_in_groups(self, cmd, group=None):
|
|
def find_cmd_in_groups(self, cmd, group=None):
|
|
|
"""
|
|
"""
|
|
@@ -191,7 +209,7 @@ class CmdGroupMgr:
|
|
|
and return it as a string. Loads modules but alters no global variables.
|
|
and return it as a string. Loads modules but alters no global variables.
|
|
|
"""
|
|
"""
|
|
|
if group:
|
|
if group:
|
|
|
- if not group in [e[0] for e in self.cmd_groups]:
|
|
|
|
|
|
|
+ if not group in self.cmd_groups:
|
|
|
die(1, f'{group!r}: unrecognized group')
|
|
die(1, f'{group!r}: unrecognized group')
|
|
|
groups = [self.cmd_groups[group]]
|
|
groups = [self.cmd_groups[group]]
|
|
|
else:
|
|
else:
|