From 685cbbc36046b3157d288b607d6dc57da25a02e7 Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Wed, 3 Jun 2020 14:09:21 +0000 Subject: [PATCH] mn_entry.py: select default entry mode with ENTER at prompt --- mmgen/mn_entry.py | 35 +++++++++++++++++++++++++---------- test/test_py_d/ts_autosign.py | 2 +- test/test_py_d/ts_input.py | 13 ++++++++----- 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/mmgen/mn_entry.py b/mmgen/mn_entry.py index 4d581878..108e850b 100755 --- a/mmgen/mn_entry.py +++ b/mmgen/mn_entry.py @@ -241,7 +241,7 @@ class MnemonicEntry(object): """, } word_prompt = ('Enter word #{}: ','Incorrect entry. Repeat word #{}: ') - dfl_entry_mode = None + usr_dfl_entry_mode = None _lw = None _sw = None _usl = None @@ -319,21 +319,27 @@ class MnemonicEntry(object): mode.name + ':', fmt(mode.choose_info,' '*14).lstrip().format(usl=self.uniq_ss_len), )) + prompt = f'Type a number, or hit ENTER for the default ({capfirst(self.dfl_entry_mode)}): ' + erase = '\r' + ' ' * (len(prompt)+19) + '\r' while True: - uret = get_char('Entry mode: ') - if uret in [str(i) for i in range(1,len(em_objs)+1)]: + uret = get_char(prompt).strip() + if uret == '': + msg_r(erase) + return self.get_cls_by_entry_mode(self.dfl_entry_mode)(self) + elif uret in [str(i) for i in range(1,len(em_objs)+1)]: + msg_r(erase) return em_objs[int(uret)-1] else: - msg_r('\b {!r}: invalid choice '.format(uret)) + msg_r(f'\b {uret!r}: invalid choice ') time.sleep(g.err_disp_timeout) - msg_r('\r'+' '*38+'\r') + msg_r(erase) def get_mnemonic_from_user(self,mn_len,validate=True): mll = list(self.conv_cls.seedlen_map_rev[self.wl_id]) assert mn_len in mll, '{}: invalid mnemonic length (must be one of {})'.format(mn_len,mll) - if self.dfl_entry_mode: - em = self.get_cls_by_entry_mode(self.dfl_entry_mode)(self) + if self.usr_dfl_entry_mode: + em = self.get_cls_by_entry_mode(self.usr_dfl_entry_mode)(self) i_add = ' (user-configured)' else: em = self.choose_entry_mode() @@ -342,7 +348,7 @@ class MnemonicEntry(object): msg('\r' + 'Using {} entry mode{}'.format(cyan(em.name.upper()),i_add)) self.em = em - if not self.dfl_entry_mode: + if not self.usr_dfl_entry_mode: m = ( fmt(self.prompt_info['intro']) + '\n' @@ -371,7 +377,10 @@ class MnemonicEntry(object): if validate: self.conv_cls.tohex(words,self.wl_id) - qmsg('Mnemonic is valid') + if self.has_chksum: + qmsg('Mnemonic is valid') + else: + qmsg('Mnemonic is well-formed (mnemonic format has no checksum to validate)') return ' '.join(words) @@ -395,22 +404,28 @@ class MnemonicEntry(object): if v not in tcls.entry_modes: m = 'entry mode {!r} not recognized for wordlist {!r}:\n (valid options: {})' raise ValueError(m.format(v,k,fmt_list(tcls.entry_modes))) - tcls.dfl_entry_mode = v + tcls.usr_dfl_entry_mode = v class MnemonicEntryMMGen(MnemonicEntry): wl_id = 'mmgen' modname = 'baseconv' entry_modes = ('full','minimal','fixed') + dfl_entry_mode = 'minimal' + has_chksum = False class MnemonicEntryBIP39(MnemonicEntry): wl_id = 'bip39' modname = 'bip39' entry_modes = ('full','short','fixed') + dfl_entry_mode = 'fixed' + has_chksum = True class MnemonicEntryMonero(MnemonicEntry): wl_id = 'xmrseed' modname = 'baseconv' entry_modes = ('full','short') + dfl_entry_mode = 'short' + has_chksum = True try: MnemonicEntry.get_cfg_vars() diff --git a/test/test_py_d/ts_autosign.py b/test/test_py_d/ts_autosign.py index 38f000e5..c1a43ff9 100755 --- a/test/test_py_d/ts_autosign.py +++ b/test/test_py_d/ts_autosign.py @@ -80,7 +80,7 @@ class TestSuiteAutosign(TestSuiteBase): from mmgen.mn_entry import mn_entry entry_mode = 'full' mne = mn_entry('mmgen',entry_mode) - t.expect('Entry mode: ',str(mne.entry_modes.index(entry_mode)+1)) + t.expect('Type a number.*: ',str(mne.entry_modes.index(entry_mode)+1),regex=True) stealth_mnemonic_entry(t,mne,mn,entry_mode) wf = t.written_to_file('Autosign wallet') t.ok() diff --git a/test/test_py_d/ts_input.py b/test/test_py_d/ts_input.py index 339f3e4b..0282e446 100755 --- a/test/test_py_d/ts_input.py +++ b/test/test_py_d/ts_input.py @@ -179,12 +179,15 @@ class TestSuiteInput(TestSuiteBase): return ('skip_warn',m) return self.password_entry('Enter passphrase (echoed): ',['--echo-passphrase']) - def _mn2hex(self,fmt,entry_mode='full',mn=None,pad_entry=False): + def _mn2hex(self,fmt,entry_mode='full',mn=None,pad_entry=False,enter_for_dfl=False): mn = mn or sample_mn[fmt]['mn'].split() t = self.spawn('mmgen-tool',['mn2hex_interactive','fmt='+fmt,'mn_len=12','print_mn=1']) from mmgen.mn_entry import mn_entry mne = mn_entry(fmt,entry_mode) - t.expect('Entry mode: ',str(mne.entry_modes.index(entry_mode)+1)) + t.expect( + 'Type a number.*: ', + ('\n' if enter_for_dfl else str(mne.entry_modes.index(entry_mode)+1)), + regex = True ) t.expect('Using (.+) entry mode',regex=True) mode = strip_ansi_escapes(t.p.match.group(1)).lower() assert mode == mne.em.name.lower(), '{} != {}'.format(mode,mne.em.name.lower()) @@ -207,11 +210,11 @@ class TestSuiteInput(TestSuiteBase): t.expect(wcls.choose_seedlen_prompt,'1') t.expect('(Y/n): ','y') if wcls.wclass == 'mnemonic': - t.expect('Entry mode: ','6') + t.expect('Type a number.*: ','6',regex=True) t.expect('invalid') from mmgen.mn_entry import mn_entry mne = mn_entry(fmt,entry_mode) - t.expect('Entry mode: ',str(mne.entry_modes.index(entry_mode)+1)) + t.expect('Type a number.*: ',str(mne.entry_modes.index(entry_mode)+1),regex=True) t.expect('Using (.+) entry mode',regex=True) mode = strip_ansi_escapes(t.p.match.group(1)).lower() assert mode == mne.em.name.lower(), '{} != {}'.format(mode,mne.em.name.lower()) @@ -262,7 +265,7 @@ class TestSuiteInput(TestSuiteBase): def mn2hex_interactive_mmgen_fixed(self): return self._mn2hex('mmgen',entry_mode='fixed') def mn2hex_interactive_bip39(self): return self._mn2hex('bip39',entry_mode='full') def mn2hex_interactive_bip39_short(self): return self._mn2hex('bip39',entry_mode='short',pad_entry=True) - def mn2hex_interactive_bip39_fixed(self): return self._mn2hex('bip39',entry_mode='fixed') + def mn2hex_interactive_bip39_fixed(self): return self._mn2hex('bip39',entry_mode='fixed',enter_for_dfl=True) def mn2hex_interactive_xmr(self): return self._mn2hex('xmrseed',entry_mode='full') def mn2hex_interactive_xmr_short(self): return self._mn2hex('xmrseed',entry_mode='short')