diff --git a/mmgen/addrgen.py b/mmgen/addrgen.py
index 606b6348..6f95f851 100755
--- a/mmgen/addrgen.py
+++ b/mmgen/addrgen.py
@@ -46,7 +46,7 @@ class addr_generator:
def __init__(self,proto,addr_type):
super().__init__(proto,addr_type)
- from .util import get_keccak
+ from .util2 import get_keccak
self.keccak_256 = get_keccak()
def AddrGenerator(proto,addr_type):
diff --git a/mmgen/crypto.py b/mmgen/crypto.py
index d8343513..cb185d51 100755
--- a/mmgen/crypto.py
+++ b/mmgen/crypto.py
@@ -38,7 +38,7 @@ from .util import (
get_words_from_user,
make_chksum_8,
compare_chksums,
- pwfile_reuse_warning,
+ oneshot_warning,
)
mmenc_ext = 'mmenc'
@@ -63,6 +63,11 @@ hash_presets = {
'7': _hp(18, 8, 24),
}
+class pwfile_reuse_warning(oneshot_warning):
+ message = 'Reusing passphrase from file {!r} at user request'
+ def __init__(self,fn):
+ oneshot_warning.__init__(self,div=fn,fmt_args=[fn],reverse=True)
+
def get_hash_params(hash_preset):
if hash_preset in hash_presets:
return hash_presets[hash_preset] # N,r,p
diff --git a/mmgen/main_tool.py b/mmgen/main_tool.py
index 38ecbaaf..3ac4168d 100755
--- a/mmgen/main_tool.py
+++ b/mmgen/main_tool.py
@@ -229,6 +229,7 @@ def process_args(cmd,cmd_args,cls):
if sys.stdin.isatty():
die( 'BadFilename', "Standard input is a TTY. Can't use '-' as a filename" )
else:
+ from .util2 import parse_bytespec
max_dlen_spec = '10kB' # limit input to 10KB for now
max_dlen = parse_bytespec(max_dlen_spec)
u_args[0] = os.read(0,max_dlen)
@@ -293,7 +294,7 @@ def process_args(cmd,cmd_args,cls):
return ( args, kwargs )
def process_result(ret,pager=False,print_result=False):
- from .util import Msg,die,parse_bytespec
+ from .util import Msg,die
"""
Convert result to something suitable for output to screen and return it.
If result is bytes and not convertible to utf8, output as binary using os.write().
diff --git a/mmgen/proto/eth/contract.py b/mmgen/proto/eth/contract.py
index 87a27fbc..458a9f96 100755
--- a/mmgen/proto/eth/contract.py
+++ b/mmgen/proto/eth/contract.py
@@ -155,7 +155,7 @@ class Token(TokenCommon):
def __init__(self,proto,addr,decimals,rpc=None):
if type(self).__name__ == 'Token':
- from ...util import get_keccak
+ from ...util2 import get_keccak
self.keccak_256 = get_keccak()
self.proto = proto
self.addr = TokenAddr(proto,addr)
@@ -167,7 +167,7 @@ class Token(TokenCommon):
class TokenResolve(TokenCommon,metaclass=AsyncInit):
async def __init__(self,proto,rpc,addr):
- from ...util import get_keccak
+ from ...util2 import get_keccak
self.keccak_256 = get_keccak()
self.proto = proto
self.rpc = rpc
diff --git a/mmgen/proto/eth/misc.py b/mmgen/proto/eth/misc.py
index c344805f..bb94dc3f 100755
--- a/mmgen/proto/eth/misc.py
+++ b/mmgen/proto/eth/misc.py
@@ -12,7 +12,8 @@
proto.eth.misc: miscellaneous utilities for Ethereum base protocol
"""
-from ...util import die,get_keccak
+from ...util import die
+from ...util2 import get_keccak
def extract_key_from_geth_keystore_wallet(wallet_fn,passwd,check_addr=True):
"""
diff --git a/mmgen/proto/eth/pyethereum/utils.py b/mmgen/proto/eth/pyethereum/utils.py
index 3dca7ad8..f20e57b8 100644
--- a/mmgen/proto/eth/pyethereum/utils.py
+++ b/mmgen/proto/eth/pyethereum/utils.py
@@ -6,7 +6,7 @@ from py_ecc.secp256k1 import privtopub,ecdsa_raw_sign,ecdsa_raw_recover
from .. import rlp
from ..rlp.sedes import Binary
-from ....util import get_keccak
+from ....util2 import get_keccak
keccak_256 = get_keccak()
def sha3_256(bstr):
diff --git a/mmgen/proto/xmr/keygen.py b/mmgen/proto/xmr/keygen.py
index 82606c66..7599fcac 100755
--- a/mmgen/proto/xmr/keygen.py
+++ b/mmgen/proto/xmr/keygen.py
@@ -24,7 +24,7 @@ class backend:
from ...proto.xmr.params import mainnet
self.proto_cls = mainnet
- from ...util import get_keccak
+ from ...util2 import get_keccak
self.keccak_256 = get_keccak()
def to_viewkey(self,privkey):
diff --git a/mmgen/protocol.py b/mmgen/protocol.py
index c6d5c109..54cf59da 100755
--- a/mmgen/protocol.py
+++ b/mmgen/protocol.py
@@ -95,7 +95,7 @@ class CoinProtocol(MMGenObject):
assert self.name.startswith('Ethereum'), 'CoinProtocol.Base_chk1'
if self.base_coin in ('ETH','XMR'):
- from .util import get_keccak
+ from .util2 import get_keccak
self.keccak_256 = get_keccak()
if need_amt:
diff --git a/mmgen/tool/fileutil.py b/mmgen/tool/fileutil.py
index d7de8c54..1d5bda51 100755
--- a/mmgen/tool/fileutil.py
+++ b/mmgen/tool/fileutil.py
@@ -23,7 +23,7 @@ tool/fileutil.py: File routines for the 'mmgen-tool' utility
import os
from .common import tool_cmd_base
-from ..util import msg,msg_r,qmsg,die,suf,parse_bytespec,make_full_path
+from ..util import msg,msg_r,qmsg,die,suf,make_full_path
from ..crypto import get_random,aesctr_iv_len
class tool_cmd(tool_cmd_base):
@@ -95,6 +95,7 @@ class tool_cmd(tool_cmd_base):
from cryptography.hazmat.backends import default_backend
from ..opts import opt
+ from ..util2 import parse_bytespec
def encrypt_worker(wid):
ctr_init_val = os.urandom( aesctr_iv_len )
diff --git a/mmgen/tool/help.py b/mmgen/tool/help.py
index 7ceef59a..e78ea032 100755
--- a/mmgen/tool/help.py
+++ b/mmgen/tool/help.py
@@ -25,7 +25,8 @@ import mmgen.main_tool as main_tool
def main_help():
- from ..util import pretty_format,capfirst
+ from ..util import capfirst
+ from ..util2 import pretty_format
def do():
for clsname,cmdlist in main_tool.mods.items():
diff --git a/mmgen/tool/util.py b/mmgen/tool/util.py
index cf472926..b82887ca 100755
--- a/mmgen/tool/util.py
+++ b/mmgen/tool/util.py
@@ -25,7 +25,7 @@ from .common import tool_cmd_base
class tool_cmd(tool_cmd_base):
"general string conversion and hashing utilities"
- # mmgen.util.bytespec_map
+ # mmgen.util2.bytespec_map
def bytespec(self,dd_style_byte_specifier:str):
"""
convert a byte specifier such as ‘4GB’ into an integer
@@ -48,10 +48,10 @@ class tool_cmd(tool_cmd_base):
EB = 1000000000000000000
E = 1152921504606846976
"""
- from ..util import parse_bytespec
+ from ..util2 import parse_bytespec
return parse_bytespec(dd_style_byte_specifier)
- # mmgen.util.bytespec_map
+ # mmgen.util2.bytespec_map
def to_bytespec(self,
n: int,
dd_style_byte_specifier: str,
@@ -78,7 +78,7 @@ class tool_cmd(tool_cmd_base):
EB = 1000000000000000000
E = 1152921504606846976
"""
- from ..util import int2bytespec
+ from ..util2 import int2bytespec
return int2bytespec( n, dd_style_byte_specifier, fmt, print_sym )
def randhex(self,
@@ -107,7 +107,7 @@ class tool_cmd(tool_cmd_base):
line_nums: "format for line numbers (valid choices: 'hex','dec')" = 'hex'):
"create hexdump of data from file (use '-' for stdin)"
from ..fileutil import get_data_from_file
- from ..util import pretty_hexdump
+ from ..util2 import pretty_hexdump
data = get_data_from_file( infile, dash=True, quiet=True, binary=True )
return pretty_hexdump( data, cols=cols, line_nums=line_nums ).rstrip()
@@ -118,7 +118,7 @@ class tool_cmd(tool_cmd_base):
import sys,os,msvcrt
msvcrt.setmode( sys.stdout.fileno(), os.O_BINARY )
from ..fileutil import get_data_from_file
- from ..util import decode_pretty_hexdump
+ from ..util2 import decode_pretty_hexdump
hexdata = get_data_from_file( infile, dash=True, quiet=True )
return decode_pretty_hexdump(hexdata)
@@ -138,7 +138,7 @@ class tool_cmd(tool_cmd_base):
from ..fileutil import get_data_from_file
b = get_data_from_file( data, binary=True )
elif hex_input:
- from ..util import decode_pretty_hexdump
+ from ..util2 import decode_pretty_hexdump
b = decode_pretty_hexdump(data)
else:
b = data
@@ -219,7 +219,7 @@ class tool_cmd(tool_cmd_base):
add_spaces: 'add a space after every 5th character' = True):
"convert a hexadecimal string to die roll base6 (base6d)"
from ..baseconv import baseconv
- from ..util import block_format
+ from ..util2 import block_format
ret = baseconv('b6d').fromhex(hexstr,pad,tostr=True)
return block_format( ret, gw=5, cols=None ).strip() if add_spaces else ret
diff --git a/mmgen/util.py b/mmgen/util.py
index 0c4dbae7..638a18a1 100755
--- a/mmgen/util.py
+++ b/mmgen/util.py
@@ -17,7 +17,7 @@
# along with this program. If not, see .
"""
-util.py: Low-level routines imported by other modules in the MMGen suite
+util.py: Frequently-used variables, classes and functions for the MMGen suite
"""
import sys,os,time,re
@@ -26,8 +26,6 @@ from .color import *
from .globalvars import g
from .opts import opt
-import mmgen.color as color_mod
-
ascii_lowercase = 'abcdefghijklmnopqrstuvwxyz'
hexdigits = '0123456789abcdefABCDEF'
@@ -136,21 +134,6 @@ def die(ev,s='',stdout=False):
else:
raise ValueError(f'{ev}: exit value must be string or int instance')
-def die_wait(delay,ev=0,s=''):
- assert isinstance(delay,int)
- assert isinstance(ev,int)
- if s:
- msg(s)
- time.sleep(delay)
- sys.exit(ev)
-
-def die_pause(ev=0,s=''):
- assert isinstance(ev,int)
- if s:
- msg(s)
- input('Press ENTER to exit')
- sys.exit(ev)
-
def Die(ev=0,s=''):
die(ev=ev,s=s,stdout=True)
@@ -191,12 +174,6 @@ def list_gen(*data):
yield i[0]
return list(gen())
-def removeprefix(s,pfx): # workaround for pre-Python 3.9
- return s[len(pfx):] if s.startswith(pfx) else s
-
-def removesuffix(s,sfx): # workaround for pre-Python 3.9
- return s[:len(sfx)] if s.endswith(sfx) else s
-
def remove_dups(iterable,edesc='element',desc='list',quiet=False,hide=False):
"""
Remove duplicate occurrences of iterable elements, preserving first occurrence
@@ -215,70 +192,6 @@ def exit_if_mswin(feature):
if g.platform == 'win':
die(2, capfirst(feature) + ' not supported on the MSWin / MSYS2 platform' )
-def get_keccak(cached_ret=[]):
-
- if not cached_ret:
- from .opts import opt
- # called in opts.init() via CoinProtocol, so must use getattr():
- if getattr(opt,'use_internal_keccak_module',False):
- qmsg('Using internal keccak module by user request')
- from .contrib.keccak import keccak_256
- else:
- try:
- from sha3 import keccak_256
- except:
- from .contrib.keccak import keccak_256
- cached_ret.append(keccak_256)
-
- return cached_ret[0]
-
-# From 'man dd':
-# c=1, w=2, b=512, kB=1000, K=1024, MB=1000*1000, M=1024*1024,
-# GB=1000*1000*1000, G=1024*1024*1024, and so on for T, P, E, Z, Y.
-bytespec_map = (
- ('c', 1),
- ('w', 2),
- ('b', 512),
- ('kB', 1000),
- ('K', 1024),
- ('MB', 1000000),
- ('M', 1048576),
- ('GB', 1000000000),
- ('G', 1073741824),
- ('TB', 1000000000000),
- ('T', 1099511627776),
- ('PB', 1000000000000000),
- ('P', 1125899906842624),
- ('EB', 1000000000000000000),
- ('E', 1152921504606846976),
-)
-
-def int2bytespec(n,spec,fmt,print_sym=True):
- def spec2int(spec):
- for k,v in bytespec_map:
- if k == spec:
- return v
- else:
- die('{spec}: unrecognized bytespec')
- return '{:{}f}{}'.format( n / spec2int(spec), fmt, spec if print_sym else '' )
-
-def parse_bytespec(nbytes):
- m = re.match(r'([0123456789.]+)(.*)',nbytes)
- if m:
- if m.group(2):
- for k,v in bytespec_map:
- if k == m.group(2):
- from decimal import Decimal
- return int(Decimal(m.group(1)) * v)
- else:
- msg("Valid byte specifiers: '{}'".format("' '".join([i[0] for i in bytespec_map])))
- elif '.' in nbytes:
- raise ValueError('fractional bytes not allowed')
- else:
- return int(nbytes)
-
- die(1,f'{nbytes!r}: invalid byte specifier')
-
def suf(arg,suf_type='s',verb='none'):
suf_types = {
'none': {
@@ -338,10 +251,6 @@ def make_chksum_6(s):
def is_chksum_6(s):
return len(s) == 6 and set(s) <= set(hexdigits_lc)
-def make_iv_chksum(s):
- from hashlib import sha256
- return sha256(s).hexdigest()[:8].upper()
-
def split_into_cols(col_wid,s):
return ' '.join([s[col_wid*i:col_wid*(i+1)] for i in range(len(s)//col_wid+1)]).rstrip()
@@ -377,19 +286,6 @@ def secs_to_hms(secs):
def secs_to_ms(secs):
return '{:02d}:{:02d}'.format(secs//60, secs % 60)
-def format_elapsed_hr(t,now=None,cached={}):
- e = int((now or time.time()) - t)
- if not e in cached:
- abs_e = abs(e)
- cached[e] = ', '.join(
- '{} {}{}'.format(n,desc,suf(n)) for desc,n in (
- ('day', abs_e // 86400),
- ('hour', abs_e // 3600 % 24),
- ('minute', abs_e // 60 % 60),
- ) if n
- ) + (' ago' if e > 0 else ' in the future') if abs_e // 60 else 'just now'
- return cached[e]
-
def is_int(s):
try:
int(str(s))
@@ -411,43 +307,6 @@ def is_utf8(s):
def remove_whitespace(s,ws='\t\r\n '):
return s.translate(dict((ord(e),None) for e in ws))
-def pretty_format(s,width=80,pfx=''):
- out = []
- while(s):
- if len(s) <= width:
- out.append(s)
- break
- i = s[:width].rfind(' ')
- out.append(s[:i])
- s = s[i+1:]
- return pfx + ('\n'+pfx).join(out)
-
-def block_format(data,gw=2,cols=8,line_nums=None,data_is_hex=False):
- assert line_nums in (None,'hex','dec'),"'line_nums' must be one of None, 'hex' or 'dec'"
- ln_fs = '{:06x}: ' if line_nums == 'hex' else '{:06}: '
- bytes_per_chunk = gw
- if data_is_hex:
- gw *= 2
- nchunks = len(data)//gw + bool(len(data)%gw)
- return ''.join(
- ('' if (line_nums == None or i % cols) else ln_fs.format(i*bytes_per_chunk))
- + data[i*gw:i*gw+gw]
- + (' ' if (not cols or (i+1) % cols) else '\n')
- for i in range(nchunks)
- ).rstrip() + '\n'
-
-def pretty_hexdump(data,gw=2,cols=8,line_nums=None):
- return block_format(data.hex(),gw,cols,line_nums,data_is_hex=True)
-
-def decode_pretty_hexdump(data):
- pat = re.compile(fr'^[{hexdigits}]+:\s+')
- lines = [pat.sub('',line) for line in data.splitlines()]
- try:
- return bytes.fromhex(''.join((''.join(lines).split())))
- except:
- msg('Data not in hexdump format')
- return False
-
def strip_comment(line):
return re.sub('#.*','',line).rstrip()
@@ -511,8 +370,9 @@ class oneshot_warning:
def do(self,wcls,div,fmt_args,reverse):
def do_warning():
+ import mmgen.color
message = getattr(wcls,'message')
- color = getattr( color_mod, getattr(wcls,'color') )
+ color = getattr( mmgen.color, getattr(wcls,'color') )
msg(color('WARNING: ' + message.format(*fmt_args)))
if not hasattr(wcls,'data'):
@@ -535,11 +395,6 @@ class oneshot_warning_group(oneshot_warning):
def __init__(self,wcls,div=None,fmt_args=[],reverse=False):
self.do(getattr(self,wcls),div,fmt_args,reverse)
-class pwfile_reuse_warning(oneshot_warning):
- message = 'Reusing passphrase from file {!r} at user request'
- def __init__(self,fn):
- oneshot_warning.__init__(self,div=fn,fmt_args=[fn],reverse=True)
-
def line_input(prompt,echo=True,insert_txt=''):
"""
multi-line prompts OK
diff --git a/mmgen/util2.py b/mmgen/util2.py
new file mode 100755
index 00000000..306feb0e
--- /dev/null
+++ b/mmgen/util2.py
@@ -0,0 +1,151 @@
+#!/usr/bin/env python3
+#
+# mmgen = Multi-Mode GENerator, a command-line cryptocurrency wallet
+# Copyright (C)2013-2022 The MMGen Project
+# Licensed under the GNU General Public License, Version 3:
+# https://www.gnu.org/licenses
+# Public project repositories:
+# https://github.com/mmgen/mmgen
+# https://gitlab.com/mmgen/mmgen
+
+"""
+util2.py: Less frequently-used variables, classes and utility functions for the MMGen suite
+"""
+
+import re,time
+from .util import msg,qmsg,suf,hexdigits
+
+def die_wait(delay,ev=0,s=''):
+ assert isinstance(delay,int)
+ assert isinstance(ev,int)
+ if s:
+ msg(s)
+ time.sleep(delay)
+ sys.exit(ev)
+
+def die_pause(ev=0,s=''):
+ assert isinstance(ev,int)
+ if s:
+ msg(s)
+ input('Press ENTER to exit')
+ sys.exit(ev)
+
+def removeprefix(s,pfx): # workaround for pre-Python 3.9
+ return s[len(pfx):] if s.startswith(pfx) else s
+
+def removesuffix(s,sfx): # workaround for pre-Python 3.9
+ return s[:len(sfx)] if s.endswith(sfx) else s
+
+def get_keccak(cached_ret=[]):
+
+ if not cached_ret:
+ from .opts import opt
+ # called in opts.init() via CoinProtocol, so must use getattr():
+ if getattr(opt,'use_internal_keccak_module',False):
+ qmsg('Using internal keccak module by user request')
+ from .contrib.keccak import keccak_256
+ else:
+ try:
+ from sha3 import keccak_256
+ except:
+ from .contrib.keccak import keccak_256
+ cached_ret.append(keccak_256)
+
+ return cached_ret[0]
+
+# From 'man dd':
+# c=1, w=2, b=512, kB=1000, K=1024, MB=1000*1000, M=1024*1024,
+# GB=1000*1000*1000, G=1024*1024*1024, and so on for T, P, E, Z, Y.
+bytespec_map = (
+ ('c', 1),
+ ('w', 2),
+ ('b', 512),
+ ('kB', 1000),
+ ('K', 1024),
+ ('MB', 1000000),
+ ('M', 1048576),
+ ('GB', 1000000000),
+ ('G', 1073741824),
+ ('TB', 1000000000000),
+ ('T', 1099511627776),
+ ('PB', 1000000000000000),
+ ('P', 1125899906842624),
+ ('EB', 1000000000000000000),
+ ('E', 1152921504606846976),
+)
+
+def int2bytespec(n,spec,fmt,print_sym=True):
+ def spec2int(spec):
+ for k,v in bytespec_map:
+ if k == spec:
+ return v
+ else:
+ die('{spec}: unrecognized bytespec')
+ return '{:{}f}{}'.format( n / spec2int(spec), fmt, spec if print_sym else '' )
+
+def parse_bytespec(nbytes):
+ m = re.match(r'([0123456789.]+)(.*)',nbytes)
+ if m:
+ if m.group(2):
+ for k,v in bytespec_map:
+ if k == m.group(2):
+ from decimal import Decimal
+ return int(Decimal(m.group(1)) * v)
+ else:
+ msg("Valid byte specifiers: '{}'".format("' '".join([i[0] for i in bytespec_map])))
+ elif '.' in nbytes:
+ raise ValueError('fractional bytes not allowed')
+ else:
+ return int(nbytes)
+
+ die(1,f'{nbytes!r}: invalid byte specifier')
+
+def format_elapsed_hr(t,now=None,cached={}):
+ e = int((now or time.time()) - t)
+ if not e in cached:
+ abs_e = abs(e)
+ cached[e] = ' '.join(
+ '{} {}{}'.format(n,desc,suf(n)) for desc,n in (
+ ('day', abs_e // 86400),
+ ('hour', abs_e // 3600 % 24),
+ ('minute', abs_e // 60 % 60),
+ ) if n
+ ) + (' ago' if e > 0 else ' in the future') if abs_e // 60 else 'just now'
+ return cached[e]
+
+def pretty_format(s,width=80,pfx=''):
+ out = []
+ while(s):
+ if len(s) <= width:
+ out.append(s)
+ break
+ i = s[:width].rfind(' ')
+ out.append(s[:i])
+ s = s[i+1:]
+ return pfx + ('\n'+pfx).join(out)
+
+def block_format(data,gw=2,cols=8,line_nums=None,data_is_hex=False):
+ assert line_nums in (None,'hex','dec'),"'line_nums' must be one of None, 'hex' or 'dec'"
+ ln_fs = '{:06x}: ' if line_nums == 'hex' else '{:06}: '
+ bytes_per_chunk = gw
+ if data_is_hex:
+ gw *= 2
+ nchunks = len(data)//gw + bool(len(data)%gw)
+ return ''.join(
+ ('' if (line_nums == None or i % cols) else ln_fs.format(i*bytes_per_chunk))
+ + data[i*gw:i*gw+gw]
+ + (' ' if (not cols or (i+1) % cols) else '\n')
+ for i in range(nchunks)
+ ).rstrip() + '\n'
+
+def pretty_hexdump(data,gw=2,cols=8,line_nums=None):
+ return block_format(data.hex(),gw,cols,line_nums,data_is_hex=True)
+
+def decode_pretty_hexdump(data):
+ pat = re.compile(fr'^[{hexdigits}]+:\s+')
+ lines = [pat.sub('',line) for line in data.splitlines()]
+ try:
+ return bytes.fromhex(''.join((''.join(lines).split())))
+ except:
+ msg('Data not in hexdump format')
+ return False
diff --git a/mmgen/wallet/dieroll.py b/mmgen/wallet/dieroll.py
index 597e99cc..2ad196ae 100755
--- a/mmgen/wallet/dieroll.py
+++ b/mmgen/wallet/dieroll.py
@@ -15,7 +15,8 @@ wallet.dieroll: dieroll wallet class
import time
from ..globalvars import g
from ..opts import opt
-from ..util import msg,msg_r,die,fmt,block_format,remove_whitespace,keypress_confirm
+from ..util import msg,msg_r,die,fmt,remove_whitespace,keypress_confirm
+from ..util2 import block_format
from ..seed import Seed
from ..baseconv import baseconv
from .unenc import wallet
diff --git a/mmgen/wallet/incog_hex.py b/mmgen/wallet/incog_hex.py
index 8a5e0dc9..051fd56b 100755
--- a/mmgen/wallet/incog_hex.py
+++ b/mmgen/wallet/incog_hex.py
@@ -12,7 +12,7 @@
wallet.incog_hex: hexadecimal incognito wallet class
"""
-from ..util import pretty_hexdump,decode_pretty_hexdump
+from ..util2 import pretty_hexdump,decode_pretty_hexdump
from .incog_base import wallet
class wallet(wallet):
diff --git a/mmgen/wallet/incog_hidden.py b/mmgen/wallet/incog_hidden.py
index 187d5eb3..4b4347cf 100755
--- a/mmgen/wallet/incog_hidden.py
+++ b/mmgen/wallet/incog_hidden.py
@@ -24,11 +24,11 @@ from ..util import (
die,
compare_or_die,
keypress_confirm,
- parse_bytespec,
line_input,
capfirst,
confirm_or_raise
)
+from ..util2 import parse_bytespec
from .incog_base import wallet
class wallet(wallet):
diff --git a/mmgen/xmrwallet.py b/mmgen/xmrwallet.py
index 2f48bbbb..905fe31d 100755
--- a/mmgen/xmrwallet.py
+++ b/mmgen/xmrwallet.py
@@ -142,6 +142,7 @@ class MoneroMMGenTX:
if pmid:
fs += ' Payment ID: {pmid}'
+ from .util2 import format_elapsed_hr
return fmt(fs,strip_char='\t',indent=indent).format(
orange(self.base_chksum.upper()),
d.seed_id.hl(),
diff --git a/scripts/exec_wrapper.py b/scripts/exec_wrapper.py
index e61fe99a..96378f7e 100755
--- a/scripts/exec_wrapper.py
+++ b/scripts/exec_wrapper.py
@@ -44,7 +44,7 @@ def exec_wrapper_write_traceback(e,exit_val):
cwd = os.path.abspath('.')
def fixup_fn(fn_in):
- from mmgen.util import removeprefix,removesuffix
+ from mmgen.util2 import removeprefix,removesuffix
fn = removeprefix(removeprefix(fn_in,cwd+'/'),'test/overlay/tree/')
return removesuffix(fn,'_orig.py') + '.py' if fn.endswith('_orig.py') else fn
# Python 3.9:
diff --git a/test/misc/oneshot_warning.py b/test/misc/oneshot_warning.py
index a2365d5b..4e0d69d2 100755
--- a/test/misc/oneshot_warning.py
+++ b/test/misc/oneshot_warning.py
@@ -30,6 +30,8 @@ class wg(oneshot_warning_group):
for i in (1,2,3):
+ from mmgen.crypto import pwfile_reuse_warning
+
msg('\npw')
for k in ('A','B'):
ret = pwfile_reuse_warning(k).warning_shown
diff --git a/test/test.py b/test/test.py
index d12a6bd5..e921241d 100755
--- a/test/test.py
+++ b/test/test.py
@@ -376,7 +376,7 @@ class CmdGroupMgr(object):
def gen():
for name,data in cls.cmd_group_in:
if name.startswith('subgroup.'):
- from mmgen.util import removeprefix
+ from mmgen.util2 import removeprefix
sg_key = removeprefix(name,'subgroup.')
# sg_key = name.removeprefix('subgroup.') # Python 3.9
if sg_name in (None,sg_key):
diff --git a/test/test_py_d/ts_tool.py b/test/test_py_d/ts_tool.py
index cbd773e1..40992bca 100755
--- a/test/test_py_d/ts_tool.py
+++ b/test/test_py_d/ts_tool.py
@@ -33,7 +33,7 @@ class TestSuiteTool(TestSuiteMain,TestSuiteBase):
def tool_rand2file(self):
outfile = os.path.join(self.tmpdir,'rand2file.out')
- from mmgen.util import parse_bytespec
+ from mmgen.util2 import parse_bytespec
for nbytes in ('1','1023','1K','1048575','1M','1048577','123M'):
t = self.spawn(
'mmgen-tool',