[msys2]: enable color output, handle exceptions in main.py

This commit is contained in:
The MMGen Project 2019-03-27 16:52:26 +00:00
commit 823e325c6c
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
11 changed files with 109 additions and 90 deletions

View file

@ -52,30 +52,42 @@ for c in _colors:
def nocolor(s): return s
def init_color(enable_color=True,num_colors='auto'):
if enable_color:
assert num_colors in ('auto',8,16,256)
globals()['_reset'] = '\033[0m'
if num_colors in (8,16):
pfx = '_16_'
elif num_colors in (256,):
def init_color(num_colors='auto'):
assert num_colors in ('auto',8,16,256)
globals()['_reset'] = '\033[0m'
if num_colors in (8,16):
pfx = '_16_'
elif num_colors in (256,):
pfx = '_256_'
else:
try:
import os
assert os.environ['TERM'][-8:] == '256color'
pfx = '_256_'
else:
except:
try:
import os
assert os.environ['TERM'][-8:] == '256color'
pfx = '_256_'
import subprocess
a = subprocess.check_output(['infocmp','-0']).decode()
b = [e.split('#')[1] for e in a.split(',') if e[:6] == 'colors'][0]
pfx = ('_16_','_256_')[b=='256']
except:
try:
import subprocess
a = subprocess.check_output(['infocmp','-0'])
b = [e.split('#')[1] for e in a.split(',') if e[:6] == 'colors'][0]
pfx = ('_16_','_256_')[b=='256']
except:
pfx = '_16_'
pfx = '_16_'
for c in _colors:
globals()['_clr_'+c] = globals()[pfx+c]
for c in _colors:
globals()['_clr_'+c] = globals()[pfx+c]
def start_mscolor():
import sys
from mmgen.globalvars import g
try:
import colorama
colorama.init(strip=True,convert=True)
except:
from mmgen.util import msg
msg('Import of colorama module failed')
else:
g.stdout = sys.stdout
g.stderr = sys.stderr
def test_color():
try:
@ -83,8 +95,9 @@ def test_color():
colorama.init(strip=True,convert=True)
except:
pass
for desc,n in (('auto','auto'),('8-color',8),('256-color',256)):
if n != 'auto': init_color(num_colors=n)
init_color(num_colors=n)
print('{:9}: {}'.format(desc,' '.join([globals()[c](c) for c in sorted(_colors)])))
if __name__ == '__main__': test_color()

View file

@ -45,7 +45,7 @@ class g(object):
author = 'The MMGen Project'
email = '<mmgen@tuta.io>'
Cdates = '2013-2019'
keywords = 'Bitcoin, BTC, cryptocurrency, wallet, cold storage, offline, online, spending, open-source, command-line, Python, Linux, Bitcoin Core, bitcoind, hd, deterministic, hierarchical, secure, anonymous, Electrum, seed, mnemonic, brainwallet, Scrypt, utility, script, scriptable, blockchain, raw, transaction, permissionless, console, terminal, curses, ansi, color, tmux, remote, client, daemon, RPC, json, entropy, xterm, rxvt, PowerShell, MSYS, MinGW, mswin, Armbian, Raspbian, Raspberry Pi, Orange Pi, BCash, BCH, Litecoin, LTC, altcoin, ZEC, Zcash, DASH, Dashpay, ETH, Ethereum, Classic, SHA256Compress, XMR, Monero, monerod, EMC, Emercoin, ERC20, token, deploy, contract, gas, fee, smart contract, solidity, Parity, testnet, devmode, Kovan'
keywords = 'Bitcoin, BTC, Ethereum, ETH, Monero, XMR, ERC20, cryptocurrency, wallet, BIP32, cold storage, offline, online, spending, open-source, command-line, Python, Linux, Bitcoin Core, bitcoind, hd, deterministic, hierarchical, secure, anonymous, Electrum, seed, mnemonic, brainwallet, Scrypt, utility, script, scriptable, blockchain, raw, transaction, permissionless, console, terminal, curses, ansi, color, tmux, remote, client, daemon, RPC, json, entropy, xterm, rxvt, PowerShell, MSYS, MSYS2, MinGW, MinGW64, MSWin, Armbian, Raspbian, Raspberry Pi, Orange Pi, BCash, BCH, Litecoin, LTC, altcoin, ZEC, Zcash, DASH, Dashpay, SHA256Compress, monerod, EMC, Emercoin, token, deploy, contract, gas, fee, smart contract, solidity, Parity, testnet, devmode, Kovan'
max_int = 0xffffffff
stdin_tty = bool(sys.stdin.isatty() or os.getenv('MMGEN_TEST_SUITE_POPEN_SPAWN'))
@ -111,7 +111,7 @@ class g(object):
else:
die(1,"'{}': platform not supported by {}\n".format(sys.platform,proj_name))
color = sys.stdout.isatty() and platform != 'win'
color = sys.stdout.isatty()
if os.getenv('HOME'): # Linux or MSYS
home_dir = os.getenv('HOME')

View file

@ -26,41 +26,34 @@ def launch(what):
what = 'wallet'
if what == 'keygen': what = 'addrgen'
import sys
import sys,os
from mmgen.globalvars import g
if g.platform == 'linux' and sys.stdin.isatty():
import termios,atexit
fd = sys.stdin.fileno()
old = termios.tcgetattr(fd)
atexit.register(lambda: termios.tcsetattr(fd,termios.TCSADRAIN,old))
try:
import termios
platform = 'linux'
except:
platform = 'win'
if platform == 'win':
__import__('mmgen.main_' + what)
else:
import os,atexit
if sys.stdin.isatty():
fd = sys.stdin.fileno()
old = termios.tcgetattr(fd)
def at_exit(): termios.tcsetattr(fd, termios.TCSADRAIN, old)
atexit.register(at_exit)
try: __import__('mmgen.main_' + what)
except KeyboardInterrupt:
sys.stderr.write('\nUser interrupt\n')
except EOFError:
sys.stderr.write('\nEnd of file\n')
except Exception as e:
if os.getenv('MMGEN_TRACEBACK'):
raise
else:
try: m = '{}'.format(e.args[0])
except: m = repr(e.args[0])
except KeyboardInterrupt:
sys.stderr.write('\nUser interrupt\n')
except EOFError:
sys.stderr.write('\nEnd of file\n')
except Exception as e:
if os.getenv('MMGEN_TRACEBACK'):
raise
else:
try: m = '{}'.format(e.args[0])
except: m = repr(e.args[0])
from mmgen.util import die,ydie,rdie
d = [ (ydie,2,'\nMMGen Unhandled Exception ({n}): {m}'),
(die, 1,'{m}'),
(ydie,2,'{m}'),
(ydie,3,'\nMMGen Error ({n}): {m}'),
(rdie,4,'\nMMGen Fatal Error ({n}): {m}')
][e.mmcode if hasattr(e,'mmcode') else 0]
from mmgen.util import die,ydie,rdie
d = [ (ydie,2,'\nMMGen Unhandled Exception ({n}): {m}'),
(die, 1,'{m}'),
(ydie,2,'{m}'),
(ydie,3,'\nMMGen Error ({n}): {m}'),
(rdie,4,'\nMMGen Fatal Error ({n}): {m}')
][e.mmcode if hasattr(e,'mmcode') else 0]
d[0](d[1],d[2].format(n=type(e).__name__,m=m))
d[0](d[1],d[2].format(n=type(e).__name__,m=m))

View file

@ -75,10 +75,11 @@ def opt_postproc_initializations():
from mmgen.term import set_terminal_vars
set_terminal_vars()
from mmgen.color import init_color
init_color(enable_color=g.color,num_colors=('auto',256)[bool(g.force_256_color)])
if g.color and g.platform == 'win': start_mscolor()
if g.color: # MMGEN_DISABLE_COLOR sets this to False
from mmgen.color import start_mscolor,init_color
if g.platform == 'win':
start_mscolor()
init_color(num_colors=('auto',256)[bool(g.force_256_color)])
g.coin = g.coin.upper() # allow user to use lowercase
g.dcoin = g.coin

View file

@ -112,6 +112,7 @@ def _kb_hold_protect_mswin():
def _get_keypress_mswin(prompt='',immed_chars='',prehold_protect=True,num_chars=None):
msg_r(prompt)
sys.stderr.flush()
timeout = float(0.5)
while True:
@ -134,12 +135,14 @@ def _get_keypress_mswin(prompt='',immed_chars='',prehold_protect=True,num_chars=
def _get_keypress_mswin_raw(prompt='',immed_chars='',prehold_protect=None,num_chars=None):
msg_r(prompt)
sys.stderr.flush()
ch = msvcrt.getch()
if ch == 3: raise KeyboardInterrupt
return ch
def _get_keypress_mswin_stub(prompt='',immed_chars='',prehold_protect=None,num_chars=None):
msg_r(prompt)
sys.stderr.flush()
return os.read(0,1)
def _get_terminal_size_linux():

View file

@ -25,11 +25,26 @@ from hashlib import sha256
from string import hexdigits,digits
from mmgen.color import *
from mmgen.exception import *
from mmgen.globalvars import g
def msg(s): g.stderr.write(s + '\n')
def msg_r(s): g.stderr.write(s)
def Msg(s): g.stdout.write(s + '\n')
def Msg_r(s): g.stdout.write(s)
if g.platform == 'win':
def msg_r(s):
try:
g.stderr.write(s)
except:
os.write(2,s.encode())
def Msg_r(s):
try:
g.stdout.write(s)
except:
os.write(1,s.encode())
def msg(s): msg_r(s + '\n')
def Msg(s): Msg_r(s + '\n')
else:
def msg_r(s): g.stderr.write(s)
def Msg_r(s): g.stdout.write(s)
def msg(s): g.stderr.write(s + '\n')
def Msg(s): g.stdout.write(s + '\n')
def msgred(s): msg(red(s))
def rmsg(s): msg(red(s))
@ -428,15 +443,6 @@ def strip_comments(line):
def remove_comments(lines):
return [m for m in [strip_comments(l) for l in lines] if m != '']
from mmgen.globalvars import g
def start_mscolor():
try:
import colorama
colorama.init(strip=True,convert=True)
except:
msg('Import of colorama module failed')
def get_hash_params(hash_preset):
if hash_preset in g.hash_presets:
return g.hash_presets[hash_preset] # N,p,r,buflen
@ -756,7 +762,13 @@ def my_raw_input(prompt,echo=True,insert_txt='',use_readline=True):
reply = input(prompt)
else:
from getpass import getpass
reply = getpass(prompt)
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()

View file

@ -1,6 +1,5 @@
#!/bin/bash
# Tested on Linux, MinGW-64
# MinGW's bash 3.1.17 doesn't do ${var^^}
# Tested on Linux, MSys2
trap 'echo -e "${GREEN}Exiting at user request$RESET"; exit' INT

View file

@ -68,7 +68,7 @@ chksum_pat = r'\b[A-F0-9]{4} [A-F0-9]{4} [A-F0-9]{4} [A-F0-9]{4}\b'
def ok_msg():
if opt.profile: return
os.write(2,green('\nOK\n').encode() if opt.exact_output or opt.verbose else b' OK\n')
sys.stderr.write(green('\nOK\n') if opt.exact_output or opt.verbose else ' OK\n')
def skip(name,reason=None):
msg('Skipping {}{}'.format(name,' ({})'.format(reason) if reason else ''))
@ -81,9 +81,9 @@ def confirm_continue():
raise KeyboardInterrupt('Exiting at user request')
def omsg(s):
os.write(2,s.encode() + b'\n')
sys.stderr.write(s + '\n')
def omsg_r(s):
os.write(2,s.encode())
sys.stderr.write(s)
def imsg(s):
if opt.exact_output or opt.verbose: omsg(s)
def imsg_r(s):
@ -93,13 +93,10 @@ def iqmsg(s):
def iqmsg_r(s):
if not opt.quiet: omsg_r(s)
if g.platform == 'win':
def silence(): pass
else:
devnull_fh = open('/dev/null','w')
def silence():
if not (opt.verbose or opt.exact_output):
g.stdout = g.stderr = devnull_fh
devnull_fh = open(('/dev/null','null.out')[g.platform == 'win'],'w')
def silence():
if not (opt.verbose or opt.exact_output):
g.stdout = g.stderr = devnull_fh
def end_silence():
if not (opt.verbose or opt.exact_output):

View file

@ -67,7 +67,7 @@ class TestSuiteBase(object):
def skip_for_win(self):
if g.platform == 'win':
msg("Skipping test '{}': not supported on MinGW platform".format(self.test_name))
msg("Skipping test '{}': not supported on MSys2 platform".format(self.test_name))
return True
else:
return False

View file

@ -527,7 +527,7 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
return t
def alice_add_label_badaddr1(self):
return self.alice_add_label_badaddr(rt_pw,'Invalid coin address for this chain: '+rt_pw)
return self.alice_add_label_badaddr(rt_pw,'Invalid coin address for this chain: ')
def alice_add_label_badaddr2(self):
addr = g.proto.pubhash2addr('00'*20,False) # mainnet zero address

View file

@ -147,6 +147,7 @@ class TestSuiteWalletConv(TestSuiteBase,TestSuiteShared):
pw = True )
def ref_hincog_blkdev_conv_out(self):
if self.skip_for_win(): return 'skip'
imsg('Creating block device image file')
ic_img = joinpath(self.tmpdir,'hincog_blkdev_img')
subprocess.check_output(['dd','if=/dev/zero','of='+ic_img,'bs=1K','count=1'],stderr=subprocess.PIPE)