From 99beeb0d493671cf8185f7d3f390f7047d7fb6a4 Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Wed, 8 Apr 2020 08:48:52 +0000 Subject: [PATCH] tool: minor changes --- mmgen/main_tool.py | 51 +++++++++++++++++++------------------ mmgen/seed.py | 4 +-- mmgen/tool.py | 36 ++++++++++++-------------- test/test_py_d/ts_ethdev.py | 4 +-- test/test_py_d/ts_misc.py | 6 +++-- test/test_py_d/ts_tool.py | 5 ++-- test/tooltest2.py | 14 +++++----- 7 files changed, 59 insertions(+), 61 deletions(-) diff --git a/mmgen/main_tool.py b/mmgen/main_tool.py index 8cea5b9a..bdd8b3ef 100755 --- a/mmgen/main_tool.py +++ b/mmgen/main_tool.py @@ -25,33 +25,34 @@ from mmgen.common import * def make_cmd_help(): import mmgen.tool - out = [] - for bc in mmgen.tool.MMGenToolCmd.__bases__: - cls_doc = bc.__doc__.strip().split('\n') - for l in cls_doc: - if l is cls_doc[0]: l += ':' - l = l.replace('\t','',1) - if l: - l = l.replace('\t',' ') - out.append(l[0].upper() + l[1:]) - else: - out.append('') - out.append('') + def make_help(): + for bc in mmgen.tool.MMGenToolCmd.__bases__: + cls_doc = bc.__doc__.strip().split('\n') + for l in cls_doc: + if l is cls_doc[0]: + l += ':' + l = l.replace('\t','',1) + if l: + l = l.replace('\t',' ') + yield l[0].upper() + l[1:] + else: + yield '' + yield '' - cls_funcs = bc._user_commands() - max_w = max(map(len,cls_funcs)) - fs = ' {{:{}}} - {{}}'.format(max_w) - for func in cls_funcs: - m = getattr(bc,func) - if m.__doc__: - out.append(fs.format(func, - pretty_format( m.__doc__.strip().replace('\n\t\t',' '), - width=79-(max_w+7), - pfx=' '*(max_w+5)).lstrip() - )) - out.append('') + max_w = max(map(len,bc._user_commands())) + fs = ' {{:{}}} - {{}}'.format(max_w) + for name in bc._user_commands(): + code = getattr(bc,name) + if code.__doc__: + yield fs.format(name, + pretty_format( + code.__doc__.strip().replace('\n\t\t',' '), + width=79-(max_w+7), + pfx=' '*(max_w+5)).lstrip() + ) + yield '' - return '\n'.join(out) + return '\n'.join(make_help()) opts_data = { 'text': { diff --git a/mmgen/seed.py b/mmgen/seed.py index ef6c49e4..6ab25ee6 100755 --- a/mmgen/seed.py +++ b/mmgen/seed.py @@ -1591,8 +1591,8 @@ harder to find, you're advised to choose a much larger file size than this. if fsize >= min_fsize: break msg('File size must be an integer no less than {}'.format(min_fsize)) - from mmgen.tool import MMGenToolCmd - MMGenToolCmd().rand2file(fn,str(fsize)) + from mmgen.tool import MMGenToolCmdFileUtil + MMGenToolCmdFileUtil().rand2file(fn,str(fsize)) check_offset = False else: die(1,'Exiting at user request') diff --git a/mmgen/tool.py b/mmgen/tool.py index 87c54cc4..cd273842 100755 --- a/mmgen/tool.py +++ b/mmgen/tool.py @@ -93,16 +93,13 @@ def _usage(cmd=None,exit_val=1): for bc in MMGenToolCmd.__bases__: cls_info = bc.__doc__.strip().split('\n')[0] Msg(' {}{}\n'.format(cls_info[0].upper(),cls_info[1:])) - ucmds = bc._user_commands() - max_w = max(map(len,ucmds)) - for cmd in ucmds: - if getattr(MMGenToolCmd,cmd).__doc__: - Msg(' {:{w}} {}'.format(cmd,_create_call_sig(cmd),w=max_w)) + max_w = max(map(len,bc._user_commands())) + for cmd in bc._user_commands(): + Msg(' {:{w}} {}'.format(cmd,_create_call_sig(cmd),w=max_w)) Msg('') Msg(m2) elif cmd in MMGenToolCmd._user_commands(): - docstr = getattr(MMGenToolCmd,cmd).__doc__.strip() - msg('{}'.format(capfirst(docstr))) + msg('{}'.format(capfirst(getattr(MMGenToolCmd,cmd).__doc__.strip()))) msg('USAGE: {} {} {}'.format(g.prog_name,cmd,_create_call_sig(cmd))) else: die(1,"'{}': no such tool command".format(cmd)) @@ -239,14 +236,13 @@ mnemonic_fmts = { } mn_opts_disp = "(valid options: '{}')".format("', '".join(mnemonic_fmts)) -class MMGenToolCmdBase(object): +class MMGenToolCmds(object): @classmethod def _user_commands(cls): return [e for e in dir(cls) if e[0] != '_' and getattr(cls,e).__doc__ and callable(getattr(cls,e))] - -class MMGenToolCmdMisc(MMGenToolCmdBase): +class MMGenToolCmdMisc(MMGenToolCmds): "miscellaneous commands" def help(self,command_name=''): @@ -255,7 +251,7 @@ class MMGenToolCmdMisc(MMGenToolCmdBase): usage = help -class MMGenToolCmdUtil(MMGenToolCmdBase): +class MMGenToolCmdUtil(MMGenToolCmds): "general string conversion and hashing utilities" def bytespec(self,dd_style_byte_specifier:str): @@ -366,7 +362,7 @@ class MMGenToolCmdUtil(MMGenToolCmdBase): "convert a die roll base6 (base6d) number to hexadecimal" return baseconv.tohex(remove_whitespace(b6d_num),'b6d',pad) -class MMGenToolCmdCoin(MMGenToolCmdBase): +class MMGenToolCmdCoin(MMGenToolCmds): """ cryptocoin key/address utilities @@ -448,7 +444,7 @@ class MMGenToolCmdCoin(MMGenToolCmdBase): assert opt.type == 'segwit','This command is meaningful only for --type=segwit' assert redeem_scripthex[:4] == '0014','{!r}: invalid redeem script'.format(redeem_scripthex) assert len(redeem_scripthex) == 44,'{} bytes: invalid redeem script length'.format(len(redeem_scripthex)//2) - return self.pubhash2addr(self.hash160(redeem_scripthex)) + return self.pubhash2addr(hash160(redeem_scripthex)) def pubhash2addr(self,pubhashhex:'sstr'): "convert public key hash to address" @@ -473,7 +469,7 @@ class MMGenToolCmdCoin(MMGenToolCmdBase): from mmgen.tx import scriptPubKey2addr return scriptPubKey2addr(hexstr)[0] -class MMGenToolCmdMnemonic(MMGenToolCmdBase): +class MMGenToolCmdMnemonic(MMGenToolCmds): """ seed phrase utilities (valid formats: 'mmgen' (default), 'bip39', 'xmrseed') @@ -569,7 +565,7 @@ class MMGenToolCmdMnemonic(MMGenToolCmdBase): ret = ['{:>4} {}'.format(n,e) for n,e in enumerate(ret)] return '\n'.join(ret) -class MMGenToolCmdFile(MMGenToolCmdBase): +class MMGenToolCmdFile(MMGenToolCmds): "utilities for viewing/checking MMGen address and transaction files" def _file_chksum(self,mmgen_addrfile,objname): @@ -629,7 +625,7 @@ class MMGenToolCmdFile(MMGenToolCmdBase): [MMGenTX(fn,offline=True).format_view(terse=terse,sort=tx_sort) for fn in flist.names()] ).rstrip() -class MMGenToolCmdFileCrypt(MMGenToolCmdBase): +class MMGenToolCmdFileCrypt(MMGenToolCmds): """ file encryption and decryption @@ -661,7 +657,7 @@ class MMGenToolCmdFileCrypt(MMGenToolCmdBase): write_data_to_file(outfile,dec_d,'decrypted data',binary=True) return True -class MMGenToolCmdFileUtil(MMGenToolCmdBase): +class MMGenToolCmdFileUtil(MMGenToolCmds): "file utilities" def find_incog_data(self,filename:str,incog_id:str,keep_searching=False): @@ -751,7 +747,7 @@ class MMGenToolCmdFileUtil(MMGenToolCmdBase): return True -class MMGenToolCmdWallet(MMGenToolCmdBase): +class MMGenToolCmdWallet(MMGenToolCmds): "key, address or subseed generation from an MMGen wallet" def get_subseed(self,subseed_idx:str,wallet=''): @@ -808,7 +804,7 @@ class MMGenToolCmdWallet(MMGenToolCmdBase): from mmgen.tw import TwAddrList,TwUnspentOutputs -class MMGenToolCmdRPC(MMGenToolCmdBase): +class MMGenToolCmdRPC(MMGenToolCmds): "tracking wallet commands using the JSON-RPC interface" def getbalance(self,minconf=1,quiet=False,pager=False): @@ -911,7 +907,7 @@ class MMGenToolCmdRPC(MMGenToolCmdBase): msg("Address '{}' deleted from tracking wallet".format(ret)) return ret -class MMGenToolCmdMonero(MMGenToolCmdBase): +class MMGenToolCmdMonero(MMGenToolCmds): """ Monero wallet utilities diff --git a/test/test_py_d/ts_ethdev.py b/test/test_py_d/ts_ethdev.py index 97018ce8..e0c10ec4 100755 --- a/test/test_py_d/ts_ethdev.py +++ b/test/test_py_d/ts_ethdev.py @@ -636,9 +636,9 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared): def token_transfer_ops(self,op,amt=1000): self.spawn('',msg_only=True) sid = dfl_sid - from mmgen.tool import MMGenToolCmd + from mmgen.tool import MMGenToolCmdWallet usr_mmaddrs = ['{}:E:{}'.format(sid,i) for i in (11,21)] - usr_addrs = [MMGenToolCmd().gen_addr(addr,dfl_words_file) for addr in usr_mmaddrs] + usr_addrs = [MMGenToolCmdWallet().gen_addr(addr,dfl_words_file) for addr in usr_mmaddrs] self._rpc_init() from mmgen.altcoins.eth.contract import Token diff --git a/test/test_py_d/ts_misc.py b/test/test_py_d/ts_misc.py index e3ce2d81..3048d149 100755 --- a/test/test_py_d/ts_misc.py +++ b/test/test_py_d/ts_misc.py @@ -44,7 +44,7 @@ class TestSuiteHelp(TestSuiteBase): 'addrgen','keygen','passgen', 'seedsplit','seedjoin', 'txcreate','txsign','txsend','txdo','txbump', - 'addrimport','tool','regtest','autosign')): + 'addrimport','regtest','autosign')): for s in scripts: t = self._run_cmd('mmgen-'+s,[arg],extra_desc='(mmgen-{})'.format(s),no_output=True) return t @@ -82,8 +82,10 @@ class TestSuiteHelp(TestSuiteBase): return t def tool_help(self): + self._run_cmd('mmgen-tool',['--help'],extra_desc="('mmgen-tool --help')") self._run_cmd('mmgen-tool',['help'],extra_desc="('mmgen-tool help')") - return self._run_cmd('mmgen-tool',['usage'],extra_desc="('mmgen-tool usage')") + self._run_cmd('mmgen-tool',['usage'],extra_desc="('mmgen-tool usage')") + return self._run_cmd('mmgen-tool',['help','randpair'],extra_desc="('mmgen-tool help randpair')") def test_help(self): self._run_cmd('test.py',['-h'],cmd_dir='test') diff --git a/test/test_py_d/ts_tool.py b/test/test_py_d/ts_tool.py index 408e9cc4..f838bdb9 100755 --- a/test/test_py_d/ts_tool.py +++ b/test/test_py_d/ts_tool.py @@ -31,12 +31,11 @@ class TestSuiteTool(TestSuiteMain,TestSuiteBase): def tool_rand2file(self): outfile = os.path.join(self.tmpdir,'rand2file.out') - from mmgen.tool import MMGenToolCmd - tu = MMGenToolCmd() + from mmgen.tool import MMGenToolCmdUtil for nbytes in ('1','1023','1K','1048575','1M','1048577','123M'): t = self.spawn( 'mmgen-tool', ['-d',self.tmpdir,'-r0','rand2file','rand2file.out',nbytes], - extra_desc='({} byte{})'.format(nbytes,suf(tu.bytespec(nbytes))) + extra_desc='({} byte{})'.format(nbytes,suf(MMGenToolCmdUtil().bytespec(nbytes))) ) t.expect('random data written to file') t.read() diff --git a/test/tooltest2.py b/test/tooltest2.py index 9bc1deb5..f9a3091e 100755 --- a/test/tooltest2.py +++ b/test/tooltest2.py @@ -784,7 +784,7 @@ def run_test(gid,cmd_name): if g.coin != 'BTC' or g.testnet: return m2 = '' m = '{} {}{}'.format(purple('Testing'), cmd_name if opt.names else - extract_docstring(getattr(getattr(tool,'MMGenToolCmd'+gid),cmd_name)),m2) + docstring_head(getattr(getattr(tool,'MMGenToolCmd'+gid),cmd_name)),m2) msg_r(green(m)+'\n' if opt.verbose else m) @@ -813,7 +813,8 @@ def run_test(gid,cmd_name): if exec_code: exec(exec_code) aargs,kwargs = tool._process_args(cmd_name,args) oq_save = opt.quiet - if not opt.verbose: opt.quiet = True + if not opt.verbose: + opt.quiet = True if stdin_input: fd0,fd1 = os.pipe() if os.fork(): # parent @@ -910,13 +911,13 @@ def run_test(gid,cmd_name): if not opt.verbose: msg('OK') -def extract_docstring(obj): +def docstring_head(obj): return obj.__doc__.strip().split('\n')[0] def do_group(gid): qmsg(blue("Testing {}".format( "command group '{}'".format(gid) if opt.names - else extract_docstring(getattr(tool,'MMGenToolCmd'+gid))))) + else docstring_head(getattr(tool,'MMGenToolCmd'+gid))))) for cname in [e for e in dir(getattr(tool,'MMGenToolCmd'+gid)) if e[0] != '_']: if cname not in tests[gid]: @@ -938,8 +939,7 @@ def do_cmd_in_group(cmd): def list_tested_cmds(): for gid in tests: - for cname in [e for e in dir(getattr(tool,'MMGenToolCmd'+gid)) if e[0] != '_']: - Msg(cname) + Msg('\n'.join(tests[gid])) sys.argv = [sys.argv[0]] + ['--skip-cfg-file'] + sys.argv[1:] @@ -954,7 +954,7 @@ import mmgen.tool as tool if opt.list_tests: Msg('Available tests:') for gid in tests: - Msg(' {:6} - {}'.format(gid,extract_docstring(getattr(tool,'MMGenToolCmd'+gid)))) + Msg(' {:6} - {}'.format(gid,docstring_head(getattr(tool,'MMGenToolCmd'+gid)))) sys.exit(0) if opt.list_tested_cmds: