|
@@ -17,7 +17,7 @@
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
"""
|
|
|
-util.py: Frequently-used variables, classes and functions for the MMGen suite
|
|
|
+util.py: Frequently-used variables, classes and utility functions for the MMGen suite
|
|
|
"""
|
|
|
|
|
|
import sys,os,time,re
|
|
@@ -188,10 +188,6 @@ def remove_dups(iterable,edesc='element',desc='list',quiet=False,hide=False):
|
|
|
ret.append(e)
|
|
|
return ret if type(iterable).__name__ == 'generator' else type(iterable)(ret)
|
|
|
|
|
|
-def exit_if_mswin(feature):
|
|
|
- if g.platform == 'win':
|
|
|
- die(2, capfirst(feature) + ' not supported on the MSWin / MSYS2 platform' )
|
|
|
-
|
|
|
def suf(arg,suf_type='s',verb='none'):
|
|
|
suf_types = {
|
|
|
'none': {
|
|
@@ -334,32 +330,9 @@ def compare_or_die(val1, desc1, val2, desc2, e='Error'):
|
|
|
dmsg(f'{capfirst(desc2)} OK ({val2})')
|
|
|
return True
|
|
|
|
|
|
-def check_wallet_extension(fn):
|
|
|
- from .wallet import get_wallet_data
|
|
|
- get_wallet_data( ext=get_extension(fn), die_on_fail=True ) # raises exception on failure
|
|
|
-
|
|
|
def make_full_path(outdir,outfile):
|
|
|
return os.path.normpath(os.path.join(outdir, os.path.basename(outfile)))
|
|
|
|
|
|
-def confirm_or_raise(message,action,expect='YES',exit_msg='Exiting at user request'):
|
|
|
- if message:
|
|
|
- msg(message)
|
|
|
- if line_input(
|
|
|
- (f'{action} ' if action[0].isupper() else f'Are you sure you want to {action}?\n') +
|
|
|
- f'Type uppercase {expect!r} to confirm: '
|
|
|
- ).strip() != expect:
|
|
|
- die( 'UserNonConfirmation', exit_msg )
|
|
|
-
|
|
|
-def get_words_from_user(prompt):
|
|
|
- words = line_input(prompt, echo=opt.echo_passphrase).split()
|
|
|
- dmsg('Sanitized input: [{}]'.format(' '.join(words)))
|
|
|
- return words
|
|
|
-
|
|
|
-def get_data_from_user(desc='data'): # user input MUST be UTF-8
|
|
|
- data = line_input(f'Enter {desc}: ',echo=opt.echo_passphrase)
|
|
|
- dmsg(f'User input: [{data}]')
|
|
|
- return data
|
|
|
-
|
|
|
class oneshot_warning:
|
|
|
|
|
|
color = 'nocolor'
|
|
@@ -395,129 +368,12 @@ 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)
|
|
|
|
|
|
-def line_input(prompt,echo=True,insert_txt=''):
|
|
|
- """
|
|
|
- multi-line prompts OK
|
|
|
- one-line prompts must begin at beginning of line
|
|
|
- empty prompts forbidden due to interactions with readline
|
|
|
- """
|
|
|
- assert prompt,'calling line_input() with an empty prompt forbidden'
|
|
|
-
|
|
|
- def init_readline():
|
|
|
- try:
|
|
|
- import readline
|
|
|
- except ImportError:
|
|
|
- return False
|
|
|
- else:
|
|
|
- if insert_txt:
|
|
|
- readline.set_startup_hook(lambda: readline.insert_text(insert_txt))
|
|
|
- return True
|
|
|
- else:
|
|
|
- return False
|
|
|
-
|
|
|
- if not sys.stdout.isatty():
|
|
|
- msg_r(prompt)
|
|
|
- prompt = ''
|
|
|
-
|
|
|
- from .term import kb_hold_protect
|
|
|
- kb_hold_protect()
|
|
|
-
|
|
|
- if g.test_suite_popen_spawn:
|
|
|
- msg(prompt)
|
|
|
- sys.stderr.flush()
|
|
|
- reply = os.read(0,4096).decode().rstrip('\n') # strip NL to mimic behavior of input()
|
|
|
- elif echo or not sys.stdin.isatty():
|
|
|
- clear_buffer = init_readline() if sys.stdin.isatty() else False
|
|
|
- reply = input(prompt)
|
|
|
- if clear_buffer:
|
|
|
- import readline
|
|
|
- readline.set_startup_hook(lambda: readline.insert_text(''))
|
|
|
- else:
|
|
|
- from getpass import getpass
|
|
|
- if g.platform == 'win':
|
|
|
- # MSWin hack - getpass('foo') doesn't flush stderr
|
|
|
- msg_r(prompt.strip()) # getpass('') adds a space
|
|
|
- sys.stderr.flush()
|
|
|
- reply = getpass('')
|
|
|
- else:
|
|
|
- reply = getpass(prompt)
|
|
|
-
|
|
|
- kb_hold_protect()
|
|
|
-
|
|
|
- return reply.strip()
|
|
|
-
|
|
|
-def keypress_confirm(prompt,default_yes=False,verbose=False,no_nl=False,complete_prompt=False):
|
|
|
-
|
|
|
- if not complete_prompt:
|
|
|
- prompt = '{} {}: '.format( prompt, '(Y/n)' if default_yes else '(y/N)' )
|
|
|
-
|
|
|
- nl = f'\r{" "*len(prompt)}\r' if no_nl else '\n'
|
|
|
-
|
|
|
- if g.accept_defaults:
|
|
|
- msg(prompt)
|
|
|
- return default_yes
|
|
|
-
|
|
|
- from .term import get_char
|
|
|
- while True:
|
|
|
- reply = get_char(prompt,immed_chars='yYnN').strip('\n\r')
|
|
|
- if not reply:
|
|
|
- msg_r(nl)
|
|
|
- return True if default_yes else False
|
|
|
- elif reply in 'yYnN':
|
|
|
- msg_r(nl)
|
|
|
- return True if reply in 'yY' else False
|
|
|
- else:
|
|
|
- msg_r('\nInvalid reply\n' if verbose else '\r')
|
|
|
-
|
|
|
def stdout_or_pager(s):
|
|
|
- (do_pager if opt.pager else Msg_r)(s)
|
|
|
-
|
|
|
-def do_pager(text):
|
|
|
-
|
|
|
- pagers = ['less','more']
|
|
|
- end_msg = '\n(end of text)\n\n'
|
|
|
- # --- Non-MSYS Windows code deleted ---
|
|
|
- # raw, chop, horiz scroll 8 chars, disable buggy line chopping in MSYS
|
|
|
- os.environ['LESS'] = (('--shift 8 -RS'),('-cR -#1'))[g.platform=='win']
|
|
|
-
|
|
|
- if 'PAGER' in os.environ and os.environ['PAGER'] != pagers[0]:
|
|
|
- pagers = [os.environ['PAGER']] + pagers
|
|
|
-
|
|
|
- from subprocess import run
|
|
|
- from .color import set_vt100
|
|
|
- for pager in pagers:
|
|
|
- try:
|
|
|
- m = text + ('' if pager == 'less' else end_msg)
|
|
|
- p = run([pager],input=m.encode(),check=True)
|
|
|
- msg_r('\r')
|
|
|
- except:
|
|
|
- pass
|
|
|
- else:
|
|
|
- break
|
|
|
+ if opt.pager:
|
|
|
+ from .ui import do_pager
|
|
|
+ do_pager(s)
|
|
|
else:
|
|
|
- Msg(text+end_msg)
|
|
|
- set_vt100()
|
|
|
-
|
|
|
-def do_license_msg(immed=False):
|
|
|
-
|
|
|
- if opt.quiet or g.no_license or opt.yes or not g.stdin_tty:
|
|
|
- return
|
|
|
-
|
|
|
- import mmgen.contrib.license as gpl
|
|
|
- msg(gpl.warning)
|
|
|
-
|
|
|
- from .term import get_char
|
|
|
- prompt = "Press 'w' for conditions and warranty info, or 'c' to continue: "
|
|
|
- while True:
|
|
|
- reply = get_char(prompt, immed_chars=('','wc')[bool(immed)])
|
|
|
- if reply == 'w':
|
|
|
- do_pager(gpl.conditions)
|
|
|
- elif reply == 'c':
|
|
|
- msg('')
|
|
|
- break
|
|
|
- else:
|
|
|
- msg_r('\r')
|
|
|
- msg('')
|
|
|
+ Msg_r(s)
|
|
|
|
|
|
def get_subclasses(cls,names=False):
|
|
|
def gen(cls):
|
|
@@ -558,3 +414,7 @@ def wrap_ripemd160(called=[]):
|
|
|
hashlib_new = hashlib.new
|
|
|
hashlib.new = hashlib_new_wrapper
|
|
|
called.append(True)
|
|
|
+
|
|
|
+def exit_if_mswin(feature):
|
|
|
+ if g.platform == 'win':
|
|
|
+ die(2, capfirst(feature) + ' not supported on the MSWin / MSYS2 platform' )
|