Browse Source

py3port: 2to3 on all files

The result of running 2to3-2.7 on all Python files in the repository.
MMGen 6 years ago
parent
commit
949e42ebf4

+ 1 - 1
data_files/mnemonic.py

@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #
 # Electrum - lightweight Bitcoin client
 # Copyright (C) 2011 thomasv@gitorious

+ 31 - 31
mmgen/addr.py

@@ -29,7 +29,7 @@ from mmgen.obj import *
 pnm = g.proj_name
 
 def dmsg_sc(desc,data):
-	if g.debug_addrlist: Msg(u'sc_debug_{}: {}'.format(desc,data))
+	if g.debug_addrlist: Msg('sc_debug_{}: {}'.format(desc,data))
 
 class AddrGenerator(MMGenObject):
 	def __new__(cls,addr_type):
@@ -39,7 +39,7 @@ class AddrGenerator(MMGenObject):
 			assert addr_type in g.proto.mmtypes,'{}: invalid address type for coin {}'.format(addr_type,g.coin)
 			gen_method = addr_type.gen_method
 		else:
-			raise TypeError,'{}: incorrect argument type for {}()'.format(type(addr_type),cls.__name__)
+			raise TypeError('{}: incorrect argument type for {}()'.format(type(addr_type),cls.__name__))
 		gen_methods = {
 			'p2pkh':    AddrGeneratorP2PKH,
 			'segwit':   AddrGeneratorSegwit,
@@ -59,7 +59,7 @@ class AddrGeneratorP2PKH(AddrGenerator):
 		return CoinAddr(g.proto.pubhash2addr(hash160(pubhex),p2sh=False))
 
 	def to_segwit_redeem_script(self,pubhex):
-		raise NotImplementedError,'Segwit redeem script not supported by this address type'
+		raise NotImplementedError('Segwit redeem script not supported by this address type')
 
 class AddrGeneratorSegwit(AddrGenerator):
 	def to_addr(self,pubhex):
@@ -77,7 +77,7 @@ class AddrGeneratorBech32(AddrGenerator):
 		return CoinAddr(g.proto.pubhash2bech32addr(hash160(pubhex)))
 
 	def to_segwit_redeem_script(self,pubhex):
-		raise NotImplementedError,'Segwit redeem script not supported by this address type'
+		raise NotImplementedError('Segwit redeem script not supported by this address type')
 
 class AddrGeneratorEthereum(AddrGenerator):
 	def to_addr(self,pubhex):
@@ -90,7 +90,7 @@ class AddrGeneratorEthereum(AddrGenerator):
 		return WalletPassword(hash256(sk_hex)[:32])
 
 	def to_segwit_redeem_script(self,pubhex):
-		raise NotImplementedError,'Segwit redeem script not supported by this address type'
+		raise NotImplementedError('Segwit redeem script not supported by this address type')
 
 # github.com/FiloSottile/zcash-mini/zcash/address.go
 class AddrGeneratorZcashZ(AddrGenerator):
@@ -99,11 +99,11 @@ class AddrGeneratorZcashZ(AddrGenerator):
 	vk_width = 97
 
 	def zhash256(self,s,t):
-		s = map(ord,s+'\0'*32)
+		s = list(map(ord,s+'\0'*32))
 		s[0] |= 0xc0
 		s[32] = t
 		from mmgen.sha256 import Sha256
-		return Sha256(map(chr,s),preprocess=False).digest()
+		return Sha256(list(map(chr,s)),preprocess=False).digest()
 
 	def to_addr(self,pubhex): # pubhex is really privhex
 		key = pubhex.decode('hex')
@@ -120,7 +120,7 @@ class AddrGeneratorZcashZ(AddrGenerator):
 	def to_viewkey(self,pubhex): # pubhex is really privhex
 		key = pubhex.decode('hex')
 		assert len(key) == 32,'{}: incorrect privkey length'.format(len(key))
-		vk = map(ord,self.zhash256(key,0)+self.zhash256(key,1))
+		vk = list(map(ord,self.zhash256(key,0)+self.zhash256(key,1)))
 		vk[32] &= 0xf8
 		vk[63] &= 0x7f
 		vk[63] |= 0x40
@@ -130,7 +130,7 @@ class AddrGeneratorZcashZ(AddrGenerator):
 		return ZcashViewKey(ret)
 
 	def to_segwit_redeem_script(self,pubhex):
-		raise NotImplementedError,'Zcash z-addresses incompatible with Segwit'
+		raise NotImplementedError('Zcash z-addresses incompatible with Segwit')
 
 class AddrGeneratorMonero(AddrGenerator):
 
@@ -182,7 +182,7 @@ class AddrGeneratorMonero(AddrGenerator):
 		return MoneroViewKey(g.proto.preprocess_key(sha3.keccak_256(sk_hex.decode('hex')).hexdigest(),None))
 
 	def to_segwit_redeem_script(self,sk_hex):
-		raise NotImplementedError,'Monero addresses incompatible with Segwit'
+		raise NotImplementedError('Monero addresses incompatible with Segwit')
 
 class KeyGenerator(MMGenObject):
 
@@ -193,7 +193,7 @@ class KeyGenerator(MMGenObject):
 			assert addr_type in g.proto.mmtypes,'{}: invalid address type for coin {}'.format(addr_type,g.coin)
 			pubkey_type = addr_type.pubkey_type
 		else:
-			raise TypeError,'{}: incorrect argument type for {}()'.format(type(addr_type),cls.__name__)
+			raise TypeError('{}: incorrect argument type for {}()'.format(type(addr_type),cls.__name__))
 		if pubkey_type == 'std':
 			if cls.test_for_secp256k1(silent=silent) and generator != 1:
 				if not opt.key_generator or opt.key_generator == 2 or generator == 2:
@@ -206,7 +206,7 @@ class KeyGenerator(MMGenObject):
 			me.desc = 'mmgen-'+pubkey_type
 			return me
 		else:
-			raise ValueError,'{}: invalid pubkey_type argument'.format(pubkey_type)
+			raise ValueError('{}: invalid pubkey_type argument'.format(pubkey_type))
 
 	@classmethod
 	def test_for_secp256k1(self,silent=False):
@@ -275,7 +275,7 @@ class AddrListEntry(MMGenListItem):
 	wallet_passwd  = MMGenListItemAttr('wallet_passwd','WalletPassword')
 
 class PasswordListEntry(MMGenListItem):
-	passwd = MMGenImmutableAttr('passwd',unicode,typeconv=False) # TODO: create Password type
+	passwd = MMGenImmutableAttr('passwd',str,typeconv=False) # TODO: create Password type
 	idx    = MMGenImmutableAttr('idx','AddrIdx')
 	label  = MMGenListItemAttr('label','TwComment',reassign_ok=True)
 	sec    = MMGenListItemAttr('sec',PrivKey,typeconv=False)
@@ -292,7 +292,7 @@ class AddrListChksum(str,Hilite):
 				) for e in addrlist.data]
 		return str.__new__(cls,make_chksum_N(' '.join(lines), nchars=16, sep=True))
 
-class AddrListIDStr(unicode,Hilite):
+class AddrListIDStr(str,Hilite):
 	color = 'green'
 	trunc_ok = False
 	def __new__(cls,addrlist,fmt_str=None):
@@ -306,7 +306,7 @@ class AddrListIDStr(unicode,Hilite):
 				if prev != ret[-1]: ret += '-', prev
 				ret += ',', i
 			prev = i
-		s = ''.join(map(unicode,ret))
+		s = ''.join(map(str,ret))
 
 		if fmt_str:
 			ret = fmt_str.format(s)
@@ -316,7 +316,7 @@ class AddrListIDStr(unicode,Hilite):
 			ret = '{}{}{}[{}]'.format(addrlist.al_id.sid,('-'+bc,'')[bc=='BTC'],('-'+mt,'')[mt in ('L','E')],s)
 			dmsg_sc('id_str',ret[8:].split('[')[0])
 
-		return unicode.__new__(cls,ret)
+		return str.__new__(cls,ret)
 
 class AddrList(MMGenObject): # Address info for a single seed ID
 	msgs = {
@@ -448,7 +448,7 @@ Removed {{}} duplicate WIF key{{}} from keylist (also in {pnm} key-address file
 					e.wallet_passwd = ag.to_wallet_passwd(e.sec)
 
 			if type(self) == PasswordList:
-				e.passwd = unicode(self.make_passwd(e.sec)) # TODO - own type
+				e.passwd = str(self.make_passwd(e.sec)) # TODO - own type
 				dmsg('Key {:>03}: {}'.format(pos,e.passwd))
 
 			out.append(e)
@@ -482,7 +482,7 @@ Removed {{}} duplicate WIF key{{}} from keylist (also in {pnm} key-address file
 
 	def write_to_file(self,ask_tty=True,ask_write_default_yes=False,binary=False,desc=None):
 		tn = ('','.testnet')[g.proto.is_testnet()]
-		fn = u'{}{x}{}.{}'.format(self.id_str,tn,self.ext,x=u'-α' if g.debug_utf8 else '')
+		fn = '{}{x}{}.{}'.format(self.id_str,tn,self.ext,x='-α' if g.debug_utf8 else '')
 		ask_tty = self.has_keys and not opt.quiet
 		write_data_to_file(fn,self.fmt_data,desc or self.file_desc,ask_tty=ask_tty,binary=binary)
 
@@ -563,12 +563,12 @@ Removed {{}} duplicate WIF key{{}} from keylist (also in {pnm} key-address file
 
 		out = [self.msgs['file_header']+'\n']
 		if self.chksum:
-			out.append(u'# {} data checksum for {}: {}'.format(
+			out.append('# {} data checksum for {}: {}'.format(
 						capfirst(self.data_desc),self.id_str,self.chksum))
 			out.append('# Record this value to a secure location.\n')
 
 		if type(self) == PasswordList:
-			lbl = u'{} {} {}:{}'.format(self.al_id.sid,self.pw_id_str,self.pw_fmt,self.pw_len)
+			lbl = '{} {} {}:{}'.format(self.al_id.sid,self.pw_id_str,self.pw_fmt,self.pw_len)
 		else:
 			bc,mt = g.proto.base_coin,self.al_id.mmtype
 			l_coin = [] if bc == 'BTC' else [g.coin] if bc == 'ETH' else [bc]
@@ -578,9 +578,9 @@ Removed {{}} duplicate WIF key{{}} from keylist (also in {pnm} key-address file
 			lbl = self.al_id.sid + ('',' ')[bool(lbl_p2)] + lbl_p2
 
 		dmsg_sc('lbl',lbl[9:])
-		out.append(u'{} {{'.format(lbl))
+		out.append('{} {{'.format(lbl))
 
-		fs = u'  {:<%s}  {:<34}{}' % len(str(self.data[-1].idx))
+		fs = '  {:<%s}  {:<34}{}' % len(str(self.data[-1].idx))
 		for e in self.data:
 			c = ' '+e.label if enable_comments and e.label else ''
 			if type(self) == KeyList:
@@ -701,14 +701,14 @@ Removed {{}} duplicate WIF key{{}} from keylist (also in {pnm} key-address file
 				base_coin,mmtype = 'BTC',MMGenAddrType('L')
 				check_coin_mismatch(base_coin)
 			else:
-				raise ValueError,u"'{}': Invalid first line for {} file '{}'".format(lines[0],self.gen_desc,fn)
+				raise ValueError("'{}': Invalid first line for {} file '{}'".format(lines[0],self.gen_desc,fn))
 
 			self.al_id = AddrListID(SeedID(sid=sid),mmtype)
 
 			data = self.parse_file_body(lines[1:-1])
 			assert issubclass(type(data),list),'Invalid file body data'
 		except Exception as e:
-			m = u'Invalid address list file ({})'.format(e.message)
+			m = 'Invalid address list file ({})'.format(e.message)
 			if exit_on_error: die(3,m)
 			msg(msg)
 			return False
@@ -804,9 +804,9 @@ Record this checksum: it will be used to verify the password file in the future
 		if chksum_only:
 			Msg(self.chksum)
 		else:
-			fs = u'{}-{}-{}-{}[{{}}]'.format(self.al_id.sid,self.pw_id_str,self.pw_fmt,self.pw_len)
+			fs = '{}-{}-{}-{}[{{}}]'.format(self.al_id.sid,self.pw_id_str,self.pw_fmt,self.pw_len)
 			self.id_str = AddrListIDStr(self,fs)
-			qmsg(u'Checksum for {} data {}: {}'.format(self.data_desc,self.id_str.hl(),self.chksum.hl()))
+			qmsg('Checksum for {} data {}: {}'.format(self.data_desc,self.id_str.hl(),self.chksum.hl()))
 			qmsg(self.msgs[('record_chksum','check_chksum')[bool(infile)]])
 
 	def set_pw_fmt(self,pw_fmt):
@@ -883,7 +883,7 @@ re-import your addresses.
 		if source == 'tw': self.add_tw_data()
 
 	def seed_ids(self):
-		return self.al_ids.keys()
+		return list(self.al_ids.keys())
 
 	def addrlist(self,al_id):
 		# TODO: Validate al_id
@@ -899,18 +899,18 @@ re-import your addresses.
 
 	def coinaddr2mmaddr(self,coinaddr):
 		d = self.make_reverse_dict([coinaddr])
-		return (d.values()[0][0]) if d else None
+		return (list(d.values())[0][0]) if d else None
 
 	@classmethod
 	def get_tw_data(cls):
 		vmsg('Getting address data from tracking wallet')
 		if 'label_api' in g.rpch.caps:
 			accts = g.rpch.listlabels()
-			alists = [a.keys() for a in g.rpch.getaddressesbylabel([[k] for k in accts],batch=True)]
+			alists = [list(a.keys()) for a in g.rpch.getaddressesbylabel([[k] for k in accts],batch=True)]
 		else:
 			accts = g.rpch.listaccounts(0,True)
 			alists = g.rpch.getaddressesbyaccount([[k] for k in accts],batch=True)
-		return zip(accts,alists)
+		return list(zip(accts,alists))
 
 	def add_tw_data(self):
 		d,out,i = self.get_tw_data(),{},0
@@ -934,7 +934,7 @@ re-import your addresses.
 			self.al_ids[addrlist.al_id] = addrlist
 			return True
 		else:
-			raise TypeError, 'Error: object {!r} is not of type AddrList'.format(addrlist)
+			raise TypeError('Error: object {!r} is not of type AddrList'.format(addrlist))
 
 	def make_reverse_dict(self,coinaddrs):
 		d = MMGenDict()

+ 5 - 5
mmgen/altcoin.py

@@ -450,7 +450,7 @@ class CoinInfo(object):
 						msg("Upgrading trust for coin '{}': {} -> {}".format(sym,line[6],1))
 						line[6] = 1
 
-			print(fs.format(*line))
+			print((fs.format(*line)))
 		msg('Processed {} entries'.format(len(data)))
 
 	@classmethod
@@ -466,8 +466,8 @@ class CoinInfo(object):
 		high = phash2addr(ver_num,'ff'*20)
 
 		if verbose:
-			print('low address:  ' + low)
-			print('high address: ' + high)
+			print(('low address:  ' + low))
+			print(('high address: ' + high))
 
 		l1,h1 = low[0],high[0]
 		return (l1,h1) if l1 != h1 else l1
@@ -477,9 +477,9 @@ class CoinInfo(object):
 		w = max(len(e[0]) for e in cls.coin_constants['mainnet'])
 		for line in cls.coin_constants['mainnet']:
 			if reverse:
-				print('{:6} {}'.format(line[1],line[0]))
+				print(('{:6} {}'.format(line[1],line[0])))
 			else:
-				print(('','{:{}} '.format(line[0],w))[include_names] + line[1])
+				print((('','{:{}} '.format(line[0],w))[include_names] + line[1]))
 
 	@classmethod
 	def create_trust_table(cls):

+ 2 - 2
mmgen/altcoins/eth/contract.py

@@ -44,7 +44,7 @@ class Token(MMGenObject): # ERC20
 		if decimals is None:
 			ret_hex = self.do_call('decimals()')
 			try: decimals = int(ret_hex,16)
-			except: raise TokenNotInBlockchain,"Token '{}' not in blockchain".format(addr)
+			except: raise TokenNotInBlockchain("Token '{}' not in blockchain".format(addr))
 		self.base_unit = Decimal(10) ** -decimals
 
 	def transferdata2amt(self,data): # online
@@ -80,7 +80,7 @@ class Token(MMGenObject): # ERC20
 		return g.rpch.eth_getCode('0x'+self.addr)[2:]
 
 	def transfer_from(self,from_addr,to_addr,amt,key,start_gas,gasPrice):
-		raise NotImplementedError,'method not implemented'
+		raise NotImplementedError('method not implemented')
 		return self.transfer(   from_addr,to_addr,amt,key,start_gas,gasPrice,
 								method_sig='transferFrom(address,address,uint256)',
 								from_addr2=from_addr)

+ 9 - 9
mmgen/altcoins/eth/tw.py

@@ -55,11 +55,11 @@ class EthereumTrackingWallet(TrackingWallet):
 			if not 'tokens' in self.data:
 				self.data['tokens'] = {}
 			def conv_types(ad):
-				for v in ad.values():
+				for v in list(ad.values()):
 					v['mmid'] = TwMMGenID(v['mmid'],on_fail='raise')
 					v['comment'] = TwComment(v['comment'],on_fail='raise')
 			conv_types(self.data['accounts'])
-			for v in self.data['tokens'].values():
+			for v in list(self.data['tokens'].values()):
 				conv_types(v)
 
 	def upgrade_wallet_maybe(self):
@@ -131,16 +131,16 @@ class EthereumTrackingWallet(TrackingWallet):
 
 	def sorted_list(self):
 		return sorted(
-			map(lambda x: {'addr':x[0],'mmid':x[1]['mmid'],'comment':x[1]['comment']},self.data_root().items()),
+			[{'addr':x[0],'mmid':x[1]['mmid'],'comment':x[1]['comment']} for x in list(self.data_root().items())],
 			key=lambda x: x['mmid'].sort_key+x['addr'] )
 
 	def mmid_ordered_dict(self):
 		from collections import OrderedDict
-		return OrderedDict(map(lambda x: (x['mmid'],{'addr':x['addr'],'comment':x['comment']}), self.sorted_list()))
+		return OrderedDict([(x['mmid'],{'addr':x['addr'],'comment':x['comment']}) for x in self.sorted_list()])
 
 	@write_mode
 	def set_label(self,coinaddr,lbl):
-		for addr,d in self.data_root().items():
+		for addr,d in list(self.data_root().items()):
 			if addr == coinaddr:
 				d['comment'] = lbl.comment
 				self.write()
@@ -204,12 +204,12 @@ Actions:         [q]uit view, [p]rint to file, pager [v]iew, [w]ide view,
 
 	def get_unspent_rpc(self):
 		rpc_init()
-		return map(lambda d: {
+		return [{
 				'account': TwLabel(d['mmid']+' '+d['comment'],on_fail='raise'),
 				'address': d['addr'],
 				'amount': self.get_addr_bal(d['addr']),
 				'confirmations': 0, # TODO
-				}, TrackingWallet().sorted_list())
+				} for d in TrackingWallet().sorted_list()]
 
 class EthereumTokenTwUnspentOutputs(EthereumTwUnspentOutputs):
 
@@ -238,7 +238,7 @@ class EthereumTwAddrList(TwAddrList):
 		self.total = g.proto.coin_amt('0')
 
 		from mmgen.obj import CoinAddr
-		for mmid,d in tw.items():
+		for mmid,d in list(tw.items()):
 #			if d['confirmations'] < minconf: continue # cannot get confirmations for eth account
 			label = TwLabel(mmid+' '+d['comment'],on_fail='raise')
 			if usr_addr_list and (label.mmid not in usr_addr_list): continue
@@ -297,6 +297,6 @@ class EthereumAddrData(AddrData):
 		vmsg('Getting address data from tracking wallet')
 		tw = TrackingWallet().mmid_ordered_dict()
 		# emulate the output of RPC 'listaccounts' and 'getaddressesbyaccount'
-		return [(mmid+' '+d['comment'],[d['addr']]) for mmid,d in tw.items()]
+		return [(mmid+' '+d['comment'],[d['addr']]) for mmid,d in list(tw.items())]
 
 class EthereumTokenAddrData(EthereumAddrData): pass

+ 3 - 3
mmgen/altcoins/eth/tx.py

@@ -150,7 +150,7 @@ class EthereumMMGenTX(MMGenTX):
 		o_num = len(self.outputs)
 		assert o_num in o_ok,'Transaction has invalid number of outputs!'.format(o_num)
 		self.make_txobj()
-		self.hex = json.dumps(dict([(k,str(v))for k,v in self.txobj.items()]))
+		self.hex = json.dumps(dict([(k,str(v))for k,v in list(self.txobj.items())]))
 		self.update_txid()
 
 	def del_output(self,idx): pass
@@ -317,7 +317,7 @@ class EthereumMMGenTX(MMGenTX):
 
 	def is_in_mempool(self):
 #		pmsg(g.rpch.parity_pendingTransactions())
-		return '0x'+self.coin_txid in map(lambda x: x['hash'],g.rpch.parity_pendingTransactions())
+		return '0x'+self.coin_txid in [x['hash'] for x in g.rpch.parity_pendingTransactions()]
 
 	def is_in_wallet(self):
 		d = g.rpch.eth_getTransactionReceipt('0x'+self.coin_txid)
@@ -401,7 +401,7 @@ class EthereumTokenMMGenTX(EthereumMMGenTX):
 		return True
 
 	def final_inputs_ok_msg(self,change_amt):
-		m = u"Transaction leaves ≈{} {} and {} {} in the sender's account"
+		m = "Transaction leaves ≈{} {} and {} {} in the sender's account"
 		send_acct_tbal = 0 if self.outputs[0].is_chg else \
 				Token(g.token).balance(self.inputs[0].addr) - self.outputs[0].amt
 		return m.format(ETHAmt(change_amt).hl(),g.coin,ETHAmt(send_acct_tbal).hl(),g.dcoin)

+ 2 - 2
mmgen/color.py

@@ -48,7 +48,7 @@ for c in _colors:
 	globals()['_16_'+c]    = '\033[{}m'.format(e[1][0]) if e[1][1] == 0 \
 						else '\033[{};{}m'.format(*e[1])
 	globals()['_clr_'+c] = ''; _reset = ''
-	exec 'def {c}(s): return _clr_{c}+s+_reset'.format(c=c)
+	exec('def {c}(s): return _clr_{c}+s+_reset'.format(c=c))
 
 def nocolor(s): return s
 
@@ -85,6 +85,6 @@ def test_color():
 		pass
 	for desc,n in (('auto','auto'),('8-color',8),('256-color',256)):
 		if n != 'auto': init_color(num_colors=n)
-		print('{:9}: {}'.format(desc,' '.join([globals()[c](c) for c in sorted(_colors)])))
+		print(('{:9}: {}'.format(desc,' '.join([globals()[c](c) for c in sorted(_colors)]))))
 
 if __name__ == '__main__': test_color()

+ 2 - 2
mmgen/common.py

@@ -89,7 +89,7 @@ a plain decimal number, or as {r}, using an integer followed by
 			r=MMGenTX().rel_fee_desc,
 			l=fee_spec_letters(use_quotes=True),
 			u=fee_spec_names() ),
-		'txsign': u"""
+		'txsign': """
 Transactions may contain both {pnm} or non-{pnm} input addresses.
 
 To sign non-{pnm} inputs, a {dn} wallet dump or flat key list is used
@@ -119,4 +119,4 @@ column below:
 			pnm=g.proj_name,
 			pnu=g.proto.name.capitalize(),
 			pnl=g.proj_name.lower())
-	}[k] + (u'-α' if g.debug_utf8 else '')
+	}[k] + ('-α' if g.debug_utf8 else '')

+ 4 - 4
mmgen/crypto.py

@@ -45,7 +45,7 @@ def sha256_rounds(s,n):
 def scramble_seed(seed,scramble_key,hash_rounds):
 	import hmac
 	scr_seed = hmac.new(seed,scramble_key,sha256).digest()
-	fs = u'Seed:  {}\nScramble key: {}\nScrambled seed: {}'
+	fs = 'Seed:  {}\nScramble key: {}\nScrambled seed: {}'
 	dmsg(fs.format(hexlify(seed),scramble_key.decode('utf8'),hexlify(scr_seed)))
 	return sha256_rounds(scr_seed,hash_rounds)
 
@@ -111,7 +111,7 @@ def scrypt_hash_passphrase(passwd,salt,hash_preset,buflen=32):
 	# Buflen arg is for brainwallets only, which use this function to generate
 	# the seed directly.
 	N,r,p = get_hash_params(hash_preset)
-	if type(passwd) == unicode: passwd = passwd.encode('utf8')
+	if type(passwd) == str: passwd = passwd.encode('utf8')
 	return scrypt.hash(passwd,salt,2**N,r,p,buflen=buflen)
 
 def make_key(passwd,salt,hash_preset,desc='encryption key',from_what='passphrase',verbose=False):
@@ -142,7 +142,7 @@ def _get_random_data_from_user(uchars):
 	if opt.quiet: msg_r('\r')
 	else: msg_r("\rThank you.  That's enough.{}\n\n".format(' '*18))
 
-	fmt_time_data = map('{:.22f}'.format,time_data)
+	fmt_time_data = list(map('{:.22f}'.format,time_data))
 	dmsg('\nUser input:\n{!r}\nKeystroke time values:\n{}\n'.format(key_data,'\n'.join(fmt_time_data)))
 	prompt = 'User random data successfully acquired.  Press ENTER to continue'
 	prompt_and_get_char(prompt,'',enter_ok=True)
@@ -171,7 +171,7 @@ def get_hash_preset_from_user(hp=g.hash_preset,desc='data'):
 	while True:
 		ret = my_raw_input(prompt)
 		if ret:
-			if ret in g.hash_presets.keys():
+			if ret in list(g.hash_presets.keys()):
 				return ret
 			else:
 				m = 'Invalid input.  Valid choices are {}'

+ 2 - 2
mmgen/filename.py

@@ -96,13 +96,13 @@ def find_files_in_dir(ftype,fdir,no_dups=False):
 		die(3,"'{}': not a recognized file type".format(ftype))
 
 	try: dirlist = os.listdir(fdir)
-	except: die(3,u"ERROR: unable to read directory '{}'".format(fdir))
+	except: die(3,"ERROR: unable to read directory '{}'".format(fdir))
 
 	matches = [l for l in dirlist if l[-len(ftype.ext)-1:]=='.'+ftype.ext]
 
 	if no_dups:
 		if len(matches) > 1:
-			die(1,u"ERROR: more than one {} file in directory '{}'".format(ftype.__name__,fdir))
+			die(1,"ERROR: more than one {} file in directory '{}'".format(ftype.__name__,fdir))
 		return os.path.join(fdir,matches[0]) if len(matches) else None
 	else:
 		return [os.path.join(fdir,m) for m in matches]

+ 2 - 2
mmgen/globalvars.py

@@ -90,7 +90,7 @@ class g(object):
 	alice                = False
 
 	# test suite:
-	bogus_wallet_data    = u''
+	bogus_wallet_data    = ''
 	debug_utf8           = False
 
 	for k in ('win','linux'):
@@ -107,7 +107,7 @@ class g(object):
 		die(2,'$HOME is not set!  Unable to determine home directory')
 
 	data_dir_root,data_dir,cfg_file = None,None,None
-	daemon_data_dir = u'' # set by user or protocol
+	daemon_data_dir = '' # set by user or protocol
 
 	# User opt sets global var:
 	common_opts = (

+ 7 - 7
mmgen/main.py

@@ -30,7 +30,7 @@ def launch(what):
 			sys.exit(2)
 
 	import sys
-	sys.argv = map(my_dec,sys.argv)
+	sys.argv = list(map(my_dec,sys.argv))
 
 	if what in ('walletgen','walletchk','walletconv','passchg'):
 		what = 'wallet'
@@ -55,15 +55,15 @@ def launch(what):
 			if os.getenv('MMGEN_TRACEBACK'):
 				raise
 			else:
-				try: m = u'{}'.format(e.message)
+				try: m = '{}'.format(e.message)
 				except: m = repr(e.message)
 
 				from mmgen.util import die,ydie,rdie
-				d = [   (ydie,2,u'\nMMGen Unhandled Exception ({n}): {m}'),
-						(die, 1,u'{m}'),
-						(ydie,2,u'{m}'),
-						(ydie,3,u'\nMMGen Error ({n}): {m}'),
-						(rdie,4,u'\nMMGen Fatal Error ({n}): {m}')
+				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))

+ 2 - 2
mmgen/main_addrgen.py

@@ -84,7 +84,7 @@ opts_data = lambda: {
 	what=gen_what,g=g,
 	dmat="'{}' or '{}'".format(g.proto.dfl_mmtype,MAT.mmtypes[g.proto.dfl_mmtype]['name'])
 ),
-	'notes': u"""
+	'notes': """
 
                            NOTES FOR THIS COMMAND
 
@@ -111,7 +111,7 @@ FMT CODES:
 		n_pw=help_notes('passwd'),
 		n_bw=help_notes('brainwallet'),
 		n_fmt='\n  '.join(SeedSource.format_fmt_codes().splitlines()),
-		n_at='\n  '.join(["'{}','{:<12} - {}".format(k,v['name']+"'",v['desc']) for k,v in MAT.mmtypes.items()]),
+		n_at='\n  '.join(["'{}','{:<12} - {}".format(k,v['name']+"'",v['desc']) for k,v in list(MAT.mmtypes.items())]),
 		o=opts
 	)
 }

+ 2 - 2
mmgen/main_addrimport.py

@@ -83,7 +83,7 @@ try:
 	rpc_init()
 except UnrecognizedTokenSymbol as e:
 	m = "When importing addresses for a new token, the token must be specified by address, not symbol."
-	raise type(e),'{}\n{}'.format(e.message,m)
+	raise type(e)('{}\n{}'.format(e.message,m))
 
 if len(cmd_args) == 1:
 	infile = cmd_args[0]
@@ -132,7 +132,7 @@ msg_fmt = '{{:{}}} {{:34}} {{:{}}}'.format(w_n_of_m,w_mmid)
 
 if opt.rescan: import threading
 
-fs = u'Importing {} address{} from {}{}'
+fs = 'Importing {} address{} from {}{}'
 bm =' (batch mode)' if opt.batch else ''
 msg(fs.format(len(al.data),suf(al.data,'es'),infile,bm))
 

+ 12 - 12
mmgen/main_autosign.py

@@ -23,11 +23,11 @@ mmgen-autosign: Auto-sign MMGen transactions
 import sys,os,subprocess,time,signal,shutil
 from stat import *
 
-mountpoint   = u'/mnt/tx'
-tx_dir       = u'/mnt/tx/tx'
-part_label   = u'MMGEN_TX'
-wallet_dir   = u'/dev/shm/autosign'
-key_fn       = u'autosign.key'
+mountpoint   = '/mnt/tx'
+tx_dir       = '/mnt/tx/tx'
+part_label   = 'MMGEN_TX'
+wallet_dir   = '/dev/shm/autosign'
+key_fn       = 'autosign.key'
 
 from mmgen.common import *
 prog_name = os.path.basename(sys.argv[0])
@@ -136,7 +136,7 @@ def get_wallet_files():
 	try: dlist = os.listdir(wallet_dir)
 	except: die(1,m.format(wallet_dir))
 
-	wfs = filter(lambda x: x[-6:] == '.mmdat',dlist)
+	wfs = [x for x in dlist if x[-6:] == '.mmdat']
 	if not wfs:
 		die(1,'No wallet files present!')
 	return [os.path.join(wallet_dir,w) for w in wfs]
@@ -196,7 +196,7 @@ def sign_tx_file(txfile):
 		else:
 			return False
 	except Exception as e:
-		msg(u'An error occurred: {}'.format(e.message))
+		msg('An error occurred: {}'.format(e.message))
 		return False
 	except:
 		return False
@@ -231,7 +231,7 @@ def decrypt_wallets():
 	opt.passwd_file = os.path.join(tx_dir,key_fn)
 #	opt.passwd_file = '/tmp/key'
 	from mmgen.seed import SeedSource
-	msg(u"Unlocking wallet{} with key from '{}'".format(suf(wfs),opt.passwd_file))
+	msg("Unlocking wallet{} with key from '{}'".format(suf(wfs),opt.passwd_file))
 	fails = 0
 	for wf in wfs:
 		try:
@@ -263,18 +263,18 @@ def wipe_existing_key():
 	try: os.stat(fn)
 	except: pass
 	else:
-		msg(u'\nWiping existing key {}'.format(fn))
+		msg('\nWiping existing key {}'.format(fn))
 		subprocess.call(['wipe','-cf',fn])
 
 def create_key():
 	from binascii import hexlify
 	kdata = hexlify(os.urandom(32))
 	fn = os.path.join(tx_dir,key_fn)
-	desc = u'key file {}'.format(fn)
+	desc = 'key file {}'.format(fn)
 	msg('Creating ' + desc)
 	try:
 		with open(fn,'w') as f: f.write(kdata+'\n')
-		os.chmod(fn,0400)
+		os.chmod(fn,0o400)
 		msg('Wrote ' + desc)
 	except:
 		die(2,'Unable to write ' + desc)
@@ -349,7 +349,7 @@ def set_led(cmd):
 
 def get_insert_status():
 	if os.getenv('MMGEN_TEST_SUITE'): return True
-	try: os.stat(os.path.join(u'/dev/disk/by-label',part_label))
+	try: os.stat(os.path.join('/dev/disk/by-label',part_label))
 	except: return False
 	else: return True
 

+ 1 - 1
mmgen/main_passgen.py

@@ -70,7 +70,7 @@ opts_data = lambda: {
 	g=g,pnm=g.proj_name,d58=dfl_len['b58'],d32=dfl_len['b32'],dhex=dfl_len['hex'],
 	kgs=' '.join(['{}:{}'.format(n,k) for n,k in enumerate(g.key_generators,1)])
 ),
-	'notes': u"""
+	'notes': """
 
                            NOTES FOR THIS COMMAND
 

+ 1 - 1
mmgen/main_txsend.py

@@ -49,7 +49,7 @@ if not opt.status: do_license_msg()
 from mmgen.tx import *
 
 tx = MMGenTX(infile,silent_open=True) # sig check performed here
-vmsg(u"Signed transaction file '{}' is valid".format(infile))
+vmsg("Signed transaction file '{}' is valid".format(infile))
 
 if not tx.marked_signed():
 	die(1,'Transaction is not signed!')

+ 1 - 1
mmgen/main_txsign.py

@@ -100,7 +100,7 @@ for tx_num,tx_file in enumerate(tx_files,1):
 	if tx.marked_signed():
 		msg('Transaction is already signed!'); continue
 
-	vmsg(u"Successfully opened transaction file '{}'".format(tx_file))
+	vmsg("Successfully opened transaction file '{}'".format(tx_file))
 
 	if opt.tx_id:
 		msg(tx.txid); continue

+ 4 - 4
mmgen/main_wallet.py

@@ -95,16 +95,16 @@ opts_data = lambda: {
 		iaction=capfirst(iaction),
 		oaction=capfirst(oaction),
 	),
-	'notes': u"""
+	'notes': """
 
 {n_pw}{n_bw}
 
 FMT CODES:
   {f}
 """.format(
-	f=u'\n  '.join(SeedSource.format_fmt_codes().splitlines()),
+	f='\n  '.join(SeedSource.format_fmt_codes().splitlines()),
 	n_pw=help_notes('passwd'),
-	n_bw=(u'','\n\n' + help_notes('brainwallet'))[bw_note]
+	n_bw=('','\n\n' + help_notes('brainwallet'))[bw_note]
 	)
 }
 
@@ -125,7 +125,7 @@ if invoked_as in ('conv','passchg'):
 ss_in = None if invoked_as == 'gen' else SeedSource(sf,passchg=(invoked_as=='passchg'))
 if invoked_as == 'chk':
 	lbl = ss_in.ssdata.label.hl() if hasattr(ss_in.ssdata,'label') else 'NONE'
-	vmsg(u'Wallet label: {}'.format(lbl))
+	vmsg('Wallet label: {}'.format(lbl))
 	# TODO: display creation date
 	sys.exit(0)
 

+ 35 - 35
mmgen/obj.py

@@ -49,10 +49,10 @@ def truncate_str(s,width): # width = screen width
 class MMGenObject(object):
 
 	# Pretty-print any object subclassed from MMGenObject, recursing into sub-objects - WIP
-	def pmsg(self): print(self.pformat())
-	def pdie(self): print(self.pformat()); sys.exit(0)
+	def pmsg(self): print((self.pformat()))
+	def pdie(self): print((self.pformat())); sys.exit(0)
 	def pformat(self,lvl=0):
-		scalars = (str,unicode,int,float,Decimal)
+		scalars = (str,str,int,float,Decimal)
 		def do_list(out,e,lvl=0,is_dict=False):
 			out.append('\n')
 			for i in e:
@@ -63,16 +63,16 @@ class MMGenObject(object):
 					out.append('{:>{l}}{}'.format('',el.pformat(lvl=lvl+1),l=(lvl+1)*8))
 				elif type(el) in scalars:
 					if isList(e):
-						out.append(u'{:>{l}}{:16}\n'.format('',repr(el),l=lvl*8))
+						out.append('{:>{l}}{:16}\n'.format('',repr(el),l=lvl*8))
 					else:
-						out.append(u' {}'.format(repr(el)))
+						out.append(' {}'.format(repr(el)))
 				elif isList(el) or isDict(el):
 					indent = 1 if is_dict else lvl*8+4
-					out.append(u'{:>{l}}{:16}'.format('','<'+type(el).__name__+'>',l=indent))
+					out.append('{:>{l}}{:16}'.format('','<'+type(el).__name__+'>',l=indent))
 					if isList(el) and type(el[0]) in scalars: out.append('\n')
 					do_list(out,el,lvl=lvl+1,is_dict=isDict(el))
 				else:
-					out.append(u'{:>{l}}{:16} {}\n'.format('','<'+type(el).__name__+'>',repr(el),l=(lvl*8)+8))
+					out.append('{:>{l}}{:16} {}\n'.format('','<'+type(el).__name__+'>',repr(el),l=(lvl*8)+8))
 				out.append('\n')
 			if not e: out.append('{}\n'.format(repr(e)))
 
@@ -90,7 +90,7 @@ class MMGenObject(object):
 # 		print self.__dict__.keys()
 # 		print self.keys()
 
-		out = [u'<{}>{}\n'.format(type(self).__name__,' '+repr(self) if isScalar(self) else '')]
+		out = ['<{}>{}\n'.format(type(self).__name__,' '+repr(self) if isScalar(self) else '')]
 		if isList(self) or isDict(self):
 			do_list(out,self,lvl=lvl,is_dict=isDict(self))
 
@@ -100,12 +100,12 @@ class MMGenObject(object):
 			if k in ('_OrderedDict__root','_OrderedDict__map'): continue # exclude these because of recursion
 			e = getattr(self,k)
 			if isList(e) or isDict(e):
-				out.append(u'{:>{l}}{:<10} {:16}'.format('',k,'<'+type(e).__name__+'>',l=(lvl*8)+4))
+				out.append('{:>{l}}{:<10} {:16}'.format('',k,'<'+type(e).__name__+'>',l=(lvl*8)+4))
 				do_list(out,e,lvl=lvl,is_dict=isDict(e))
 			elif hasattr(e,'pformat') and type(e) != type:
-				out.append(u'{:>{l}}{:10} {}'.format('',k,e.pformat(lvl=lvl+1),l=(lvl*8)+4))
+				out.append('{:>{l}}{:10} {}'.format('',k,e.pformat(lvl=lvl+1),l=(lvl*8)+4))
 			else:
-				out.append(u'{:>{l}}{:<10} {:16} {}\n'.format(
+				out.append('{:>{l}}{:<10} {:16} {}\n'.format(
 					'',k,'<'+type(e).__name__+'>',repr(e),l=(lvl*8)+4))
 
 		import re
@@ -126,7 +126,7 @@ class InitErrors(object):
 		if os.getenv('MMGEN_TRACEBACK'): on_fail == 'raise'
 		from mmgen.util import die,msg
 		if   on_fail == 'silent': return None # TODO: return False instead?
-		elif on_fail == 'raise':  raise ValueError,m
+		elif on_fail == 'raise':  raise ValueError(m)
 		elif on_fail == 'die':    die(1,m)
 		elif on_fail == 'return':
 			if m: msg(m)
@@ -144,7 +144,7 @@ class Hilite(object):
 	# 'append_chars' and 'encl' must consist of single-width chars only
 	def fmtc(cls,s,width=None,color=False,encl='',trunc_ok=None,
 				center=False,nullrepl='',append_chars='',append_color=False):
-		s = unicode(s)
+		s = str(s)
 		s_wide_count = len([1 for ch in s if unicodedata.east_asian_width(ch) in ('F','W')])
 		assert type(encl) is str and len(encl) in (0,2),"'encl' must be 2-character str"
 		a,b = list(encl) if encl else ('','')
@@ -248,7 +248,7 @@ class MMGenListItem(MMGenObject):
 
 	def __init__(self,*args,**kwargs):
 		if args:
-			raise ValueError, 'Non-keyword args not allowed'
+			raise ValueError('Non-keyword args not allowed')
 		for k in kwargs:
 			if kwargs[k] != None:
 				setattr(self,k,kwargs[k])
@@ -299,7 +299,7 @@ class AddrIdxList(list,InitErrors,MMGenObject):
 					else: break
 				else:
 					return list.__init__(self,sorted(set(ret))) # fell off end of loop - success
-				raise ValueError,"{!r}: invalid range".format(i)
+				raise ValueError("{!r}: invalid range".format(i))
 		except Exception as e:
 			m = "{!r}: value cannot be converted to AddrIdxList ({})"
 			return type(self).init_fail(m.format(idx_list or fmt_str,e.message),on_fail)
@@ -314,7 +314,7 @@ class BTCAmt(Decimal,Hilite,InitErrors):
 	min_coin_unit = satoshi
 	amt_fs = '4.8'
 	units = ('satoshi',)
-	forbidden_types = (float,long)
+	forbidden_types = (float,int)
 
 	def __new__(cls,num,from_unit=None,on_fail='die'):
 		if type(num) == cls: return num
@@ -323,7 +323,7 @@ class BTCAmt(Decimal,Hilite,InitErrors):
 			if from_unit:
 				assert from_unit in cls.units,(
 					"'{}': unrecognized denomination for {}".format(from_unit,cls.__name__))
-				assert type(num) in (int,long),'value is not an integer or long integer'
+				assert type(num) in (int,int),'value is not an integer or long integer'
 				me = Decimal.__new__(cls,num * getattr(cls,from_unit))
 			else:
 				for t in cls.forbidden_types:
@@ -355,7 +355,7 @@ class BTCAmt(Decimal,Hilite,InitErrors):
 		if fs == None: fs = self.amt_fs
 		s = str(int(self)) if int(self) == self else self.normalize().__format__('f')
 		if '.' in fs:
-			p1,p2 = map(int,fs.split('.',1))
+			p1,p2 = list(map(int,fs.split('.',1)))
 			ss = s.split('.',1)
 			if len(ss) == 2:
 				a,b = ss
@@ -463,7 +463,7 @@ class ViewKey(object):
 		elif g.proto.name == 'monero':
 			return MoneroViewKey.__new__(MoneroViewKey,s,on_fail)
 		else:
-			raise ValueError,'{}: protocol does not support view keys'.format(g.proto.name.capitalize())
+			raise ValueError('{}: protocol does not support view keys'.format(g.proto.name.capitalize()))
 
 class ZcashViewKey(CoinAddr): hex_width = 128
 
@@ -484,7 +484,7 @@ class SeedID(str,Hilite,InitErrors):
 				assert set(sid) <= set(hexdigits.upper()),'not uppercase hex digits'
 				assert len(sid) == cls.width,'not {} characters wide'.format(cls.width)
 				return str.__new__(cls,sid)
-			raise ValueError,'no arguments provided'
+			raise ValueError('no arguments provided')
 		except Exception as e:
 			m = "{!r}: value cannot be converted to SeedID ({})"
 			return cls.init_fail(m.format(seed or sid,e.message),on_fail)
@@ -542,7 +542,7 @@ class TwMMGenID(str,Hilite,InitErrors,MMGenObject):
 		return me
 
 # contains TwMMGenID,TwComment.  Not for display
-class TwLabel(unicode,InitErrors,MMGenObject):
+class TwLabel(str,InitErrors,MMGenObject):
 	def __new__(cls,s,on_fail='die'):
 		if type(s) == cls: return s
 		cls.arg_chk(cls,on_fail)
@@ -550,12 +550,12 @@ class TwLabel(unicode,InitErrors,MMGenObject):
 			ss = s.split(None,1)
 			mmid = TwMMGenID(ss[0],on_fail='raise')
 			comment = TwComment(ss[1] if len(ss) == 2 else '',on_fail='raise')
-			me = unicode.__new__(cls,u'{}{}'.format(mmid,u' {}'.format(comment) if comment else ''))
+			me = str.__new__(cls,'{}{}'.format(mmid,' {}'.format(comment) if comment else ''))
 			me.mmid = mmid
 			me.comment = comment
 			return me
 		except Exception as e:
-			m = u"{}\n{!r}: value cannot be converted to TwLabel"
+			m = "{}\n{!r}: value cannot be converted to TwLabel"
 			return cls.init_fail(m.format(e.message,s),on_fail)
 
 class HexStr(str,Hilite,InitErrors):
@@ -566,7 +566,7 @@ class HexStr(str,Hilite,InitErrors):
 		assert case in ('upper','lower')
 		cls.arg_chk(cls,on_fail)
 		try:
-			assert type(s) in (str,unicode,bytes),'not a string'
+			assert type(s) in (str,str,bytes),'not a string'
 			assert set(s) <= set(getattr(hexdigits,case)()),'not {}case hexadecimal symbols'.format(case)
 			assert not len(s) % 2,'odd-length string'
 			return str.__new__(cls,s)
@@ -689,7 +689,7 @@ class AddrListID(str,Hilite,InitErrors,MMGenObject):
 			m = "Cannot create AddrListID ({})".format(e.message)
 			return cls.init_fail(m,on_fail)
 
-class MMGenLabel(unicode,Hilite,InitErrors):
+class MMGenLabel(str,Hilite,InitErrors):
 	color = 'pink'
 	allowed = []
 	forbidden = []
@@ -701,10 +701,10 @@ class MMGenLabel(unicode,Hilite,InitErrors):
 		cls.arg_chk(cls,on_fail)
 		for k in cls.forbidden,cls.allowed:
 			assert type(k) == list
-			for ch in k: assert type(ch) == unicode and len(ch) == 1
+			for ch in k: assert type(ch) == str and len(ch) == 1
 		try:
 			s = s.strip()
-			if type(s) != unicode:
+			if type(s) != str:
 				s = s.decode('utf8')
 			for ch in s:
 				# Allow:    (L)etter,(N)umber,(P)unctuation,(S)ymbol,(Z)space
@@ -715,12 +715,12 @@ class MMGenLabel(unicode,Hilite,InitErrors):
 			assert len(s) <= cls.max_len, 'too long (>{} symbols)'.format(cls.max_len)
 			assert len(s) >= cls.min_len, 'too short (<{} symbols)'.format(cls.min_len)
 			assert not cls.allowed or set(list(s)).issubset(set(cls.allowed)),\
-				u'contains non-allowed symbols: {}'.format(' '.join(set(list(s)) - set(cls.allowed)))
+				'contains non-allowed symbols: {}'.format(' '.join(set(list(s)) - set(cls.allowed)))
 			assert not cls.forbidden or not any(ch in s for ch in cls.forbidden),\
-				u"contains one of these forbidden symbols: '{}'".format("', '".join(cls.forbidden))
-			return unicode.__new__(cls,s)
+				"contains one of these forbidden symbols: '{}'".format("', '".join(cls.forbidden))
+			return str.__new__(cls,s)
 		except Exception as e:
-			m = u"{!r}: value cannot be converted to {} ({})"
+			m = "{!r}: value cannot be converted to {} ({})"
 			return cls.init_fail(m.format(s,cls.__name__,e.message),on_fail)
 
 class MMGenWalletLabel(MMGenLabel):
@@ -739,7 +739,7 @@ class MMGenPWIDString(MMGenLabel):
 	max_len = 256
 	min_len = 1
 	desc = 'password ID string'
-	forbidden = list(u' :/\\')
+	forbidden = list(' :/\\')
 
 class MMGenAddrType(str,Hilite,InitErrors,MMGenObject):
 	width = 1
@@ -799,7 +799,7 @@ class MMGenAddrType(str,Hilite,InitErrors,MMGenObject):
 		cls.arg_chk(cls,on_fail)
 		from mmgen.globalvars import g
 		try:
-			for k,v in cls.mmtypes.items():
+			for k,v in list(cls.mmtypes.items()):
 				if s in (k,v['name']):
 					if s == v['name']: s = k
 					me = str.__new__(cls,s)
@@ -810,7 +810,7 @@ class MMGenAddrType(str,Hilite,InitErrors,MMGenObject):
 					me.extra_attrs = v['extra_attrs'] if 'extra_attrs' in v else ()
 					me.wif_label   = v['wif_label'] if 'wif_label' in v else 'wif:'
 					return me
-			raise ValueError,'not found'
+			raise ValueError('not found')
 		except Exception as e:
 			m = '{}{!r}: invalid value for {} ({})'.format(
 				('{!r}\n'.format(errmsg) if errmsg else ''),s,cls.__name__,e.message)
@@ -818,7 +818,7 @@ class MMGenAddrType(str,Hilite,InitErrors,MMGenObject):
 
 	@classmethod
 	def get_names(cls):
-		return [v['name'] for v in cls.mmtypes.values()]
+		return [v['name'] for v in list(cls.mmtypes.values())]
 
 class MMGenPasswordType(MMGenAddrType):
 	mmtypes = {

+ 13 - 13
mmgen/opts.py

@@ -64,12 +64,12 @@ def opt_postproc_debug():
 	Msg('    Opts after processing:')
 	for k in a:
 		v = getattr(opt,k)
-		Msg(u'        {:18}: {:<6} [{}]'.format(k,v,type(v).__name__))
+		Msg('        {:18}: {:<6} [{}]'.format(k,v,type(v).__name__))
 	Msg("    Opts set to 'None':")
-	Msg(u'        {}\n'.format('\n        '.join(b)))
+	Msg('        {}\n'.format('\n        '.join(b)))
 	Msg('    Global vars:')
 	for e in [d for d in dir(g) if d[:2] != '__']:
-		Msg(u'        {:<20}: {}'.format(e, getattr(g,e)))
+		Msg('        {:<20}: {}'.format(e, getattr(g,e)))
 	Msg('\n=== end opts.py debug ===\n')
 
 def opt_postproc_initializations():
@@ -108,7 +108,7 @@ def get_cfg_template_data():
 			return f.read()
 	except:
 		msg("WARNING: configuration template not found at '{}'".format(cfg_template))
-		return u''
+		return ''
 
 def get_data_from_cfg_file():
 	from mmgen.util import msg,die,check_or_create_dir
@@ -119,9 +119,9 @@ def get_data_from_cfg_file():
 	def copy_template_data(fn):
 		try:
 			with open(fn,'wb') as f: f.write(template_data)
-			os.chmod(fn,0600)
+			os.chmod(fn,0o600)
 		except:
-			die(2,u"ERROR: unable to write to datadir '{}'".format(g.data_dir))
+			die(2,"ERROR: unable to write to datadir '{}'".format(g.data_dir))
 
 	for k,suf in (('cfg',''),('sample','.sample')):
 		try:
@@ -132,7 +132,7 @@ def get_data_from_cfg_file():
 				copy_template_data(g.cfg_file+suf)
 				data[k] = template_data
 			else:
-				data[k] = u''
+				data[k] = ''
 
 	if template_data and data['sample'] != template_data:
 		g.cfg_options_changed = True
@@ -300,8 +300,8 @@ def init(opts_f,add_opts=[],opt_filter=None):
 		opts_data['long_options'] = common_opts_data
 		if g.debug_utf8:
 			for k in opts_data:
-				if type(opts_data[k]) in (str,unicode):
-					opts_data[k] += u'-α'
+				if type(opts_data[k]) in (str,str):
+					opts_data[k] += '-α'
 		mmgen.share.Opts.parse_opts(sys.argv,opts_data,opt_filter=opt_filter)
 
 	if g.bob or g.alice:
@@ -310,7 +310,7 @@ def init(opts_f,add_opts=[],opt_filter=None):
 		g.proto = CoinProtocol(g.coin,g.testnet)
 		g.data_dir = os.path.join(g.data_dir_root,'regtest',g.coin.lower(),('alice','bob')[g.bob])
 		check_or_create_dir(g.data_dir)
-		import regtest as rt
+		from . import regtest as rt
 		g.rpc_host = 'localhost'
 		g.rpc_port = rt.rpc_port
 		g.rpc_user = rt.rpc_user
@@ -471,7 +471,7 @@ def check_opts(usr_opts):       # Returns false if any check fails
 			if not opt_is_int(val,desc): return False
 			if not opt_is_in_list(int(val),g.seed_lens,desc): return False
 		elif key == 'hash_preset':
-			if not opt_is_in_list(val,g.hash_presets.keys(),desc): return False
+			if not opt_is_in_list(val,list(g.hash_presets.keys()),desc): return False
 		elif key == 'brain_params':
 			a = val.split(',')
 			if len(a) != 2:
@@ -482,7 +482,7 @@ def check_opts(usr_opts):       # Returns false if any check fails
 			if not opt_is_int(a[0],d): return False
 			if not opt_is_in_list(int(a[0]),g.seed_lens,d): return False
 			d = 'hash preset ' + desc
-			if not opt_is_in_list(a[1],g.hash_presets.keys(),d): return False
+			if not opt_is_in_list(a[1],list(g.hash_presets.keys()),d): return False
 		elif key == 'usr_randchars':
 			if val == 0: continue
 			if not opt_is_int(val,desc): return False
@@ -501,7 +501,7 @@ def check_opts(usr_opts):       # Returns false if any check fails
 			if not opt_compares(val,'>',0,desc): return False
 		elif key == 'coin':
 			from mmgen.protocol import CoinProtocol
-			if not opt_is_in_list(val.lower(),CoinProtocol.coins.keys(),'coin'): return False
+			if not opt_is_in_list(val.lower(),list(CoinProtocol.coins.keys()),'coin'): return False
 		elif key == 'rbf':
 			if not g.proto.cap('rbf'):
 				msg('--rbf requested, but {} does not support replace-by-fee transactions'.format(g.coin))

+ 7 - 7
mmgen/protocol.py

@@ -59,7 +59,7 @@ def _b58chk_decode(s):
 	if len(hexstr) % 2: hexstr = '0' + hexstr
 	if hexstr[-8:] == hash256(hexstr[:-8])[:8]:
 		return hexstr[:-8]
-	raise ValueError,'_b58chk_decode(): checksum incorrect'
+	raise ValueError('_b58chk_decode(): checksum incorrect')
 
 # chainparams.cpp
 class BitcoinProtocol(MMGenObject):
@@ -129,7 +129,7 @@ class BitcoinProtocol(MMGenObject):
 	def wif2hex(cls,wif):
 		key = _b58chk_decode(wif)
 		pubkey_type = None
-		for k,v in cls.wif_ver_num.items():
+		for k,v in list(cls.wif_ver_num.items()):
 			if key[:len(v)] == v:
 				pubkey_type = k
 				key = key[len(v):]
@@ -203,7 +203,7 @@ class BitcoinProtocol(MMGenObject):
 
 	@classmethod
 	def pubhash2bech32addr(cls,pubhash):
-		d = map(ord,pubhash.decode('hex'))
+		d = list(map(ord,pubhash.decode('hex')))
 		return bech32.bech32_encode(cls.bech32_hrp,[cls.witness_vernum]+bech32.convertbits(d,8,5))
 
 class BitcoinTestnetProtocol(BitcoinProtocol):
@@ -377,9 +377,9 @@ class ZcashProtocol(BitcoinProtocolAddrgen):
 		if hl == 40:
 			return super(cls,cls).pubhash2addr(pubkey_hash,p2sh)
 		elif hl == 128:
-			raise NotImplementedError,'Zcash z-addresses have no pubkey hash'
+			raise NotImplementedError('Zcash z-addresses have no pubkey hash')
 		else:
-			raise ValueError,'{}: incorrect pubkey_hash length'.format(hl)
+			raise ValueError('{}: incorrect pubkey_hash length'.format(hl))
 
 class ZcashTestnetProtocol(ZcashProtocol):
 	wif_ver_num  = { 'std': 'ef', 'zcash_z': 'ac08' }
@@ -456,12 +456,12 @@ class CoinProtocol(MMGenObject):
 		from mmgen.altcoin import CoinInfo as ci
 		ret = sorted(set(
 			[e[1] for e in ci.coin_constants['mainnet'] if e[6] != -1]
-			+ cls.coins.keys()))
+			+ list(cls.coins.keys())))
 		return [getattr(e,('lower','upper')[upcase])() for e in ret]
 
 	@classmethod
 	def get_base_coin_from_name(cls,name):
-		for proto,foo in cls.coins.values():
+		for proto,foo in list(cls.coins.values()):
 			if name == proto.__name__[:-8].lower():
 				return proto.base_coin
 		return False

+ 3 - 3
mmgen/regtest.py

@@ -38,7 +38,7 @@ common_args = lambda: (
 	'--rpcpassword={}'.format(rpc_password),
 	'--rpcport={}'.format(rpc_port),
 	'--regtest',
-	u'--datadir={}'.format(data_dir))
+	'--datadir={}'.format(data_dir))
 
 def start_daemon(user,quiet=False,daemon=True,reindex=False):
 	# requires Bitcoin ABC version >= 0.16.2
@@ -53,7 +53,7 @@ def start_daemon(user,quiet=False,daemon=True,reindex=False):
 	) + add_args + common_args()
 	if daemon: cmd += ('--daemon',)
 	if reindex: cmd += ('--reindex',)
-	if not g.debug or quiet: vmsg(u'{}'.format(' '.join(cmd)))
+	if not g.debug or quiet: vmsg('{}'.format(' '.join(cmd)))
 	p = subprocess.Popen(cmd,stdout=PIPE,stderr=PIPE)
 	err = process_output(p,silent=False)[1]
 	if err:
@@ -71,7 +71,7 @@ def start_cmd(*args,**kwargs):
 	if args[0] == 'cli':
 		cmd = (g.proto.name+'-cli',) + common_args() + args[1:]
 	if g.debug or not 'quiet' in kwargs:
-		vmsg(u'{}'.format(' '.join(cmd)))
+		vmsg('{}'.format(' '.join(cmd)))
 	ip = op = ep = (PIPE,None)['no_pipe' in kwargs and kwargs['no_pipe']]
 	if 'pipe_stdout_only' in kwargs and kwargs['pipe_stdout_only']: ip = ep = None
 	return subprocess.Popen(cmd,stdin=ip,stdout=op,stderr=ep)

+ 8 - 8
mmgen/rpc.py

@@ -20,7 +20,7 @@
 rpc.py:  Cryptocoin RPC library for the MMGen suite
 """
 
-import httplib,base64,json
+import http.client,base64,json
 
 from mmgen.common import *
 from decimal import Decimal
@@ -68,8 +68,8 @@ class CoinDaemonRPCConnection(object):
 		self.port = port
 
 		for method in self.rpcmethods:
-			exec '{c}.{m} = lambda self,*args,**kwargs: self.request("{m}",*args,**kwargs)'.format(
-						c=type(self).__name__,m=method)
+			exec('{c}.{m} = lambda self,*args,**kwargs: self.request("{m}",*args,**kwargs)'.format(
+						c=type(self).__name__,m=method))
 
 	# Normal mode: call with arg list unrolled, exactly as with cli
 	# Batch mode:  call with list of arg lists as first argument
@@ -86,12 +86,12 @@ class CoinDaemonRPCConnection(object):
 		cf = { 'timeout':g.http_timeout, 'batch':False, 'on_fail':'raise' }
 
 		if cf['on_fail'] not in ('raise','return','silent'):
-			raise ValueError, "request(): {}: illegal value for 'on_fail'".format(cf['on_fail'])
+			raise ValueError("request(): {}: illegal value for 'on_fail'".format(cf['on_fail']))
 
 		for k in cf:
 			if k in kwargs and kwargs[k]: cf[k] = kwargs[k]
 
-		hc = httplib.HTTPConnection(self.host, self.port, False, cf['timeout'])
+		hc = http.client.HTTPConnection(self.host, self.port, False, cf['timeout'])
 
 		if cf['batch']:
 			p = [{'method':cmd,'params':r,'id':n,'jsonrpc':'2.0'} for n,r in enumerate(args[0],1)]
@@ -101,10 +101,10 @@ class CoinDaemonRPCConnection(object):
 		def do_fail(*args):
 			if cf['on_fail'] in ('return','silent'): return 'rpcfail',args
 
-			try:    s = u'{}'.format(args[2])
+			try:    s = '{}'.format(args[2])
 			except: s = repr(args[2])
 
-			raise RPCFailure,s
+			raise RPCFailure(s)
 
 		dmsg_rpc('=== request() debug ===')
 		dmsg_rpc('    RPC POST data ==> {}\n'.format(p))
@@ -151,7 +151,7 @@ class CoinDaemonRPCConnection(object):
 
 		r2 = r.read().decode('utf8')
 
-		dmsg_rpc(u'    RPC REPLY data ==> {}\n'.format(r2))
+		dmsg_rpc('    RPC REPLY data ==> {}\n'.format(r2))
 
 		if not r2:
 			return do_fail(r,2,'Empty reply')

+ 29 - 29
mmgen/seed.py

@@ -200,11 +200,11 @@ class SeedSource(MMGenObject):
 					for c in cls.get_subclasses()
 				if hasattr(c,'fmt_codes')]
 		w = max(len(i[0]) for i in d)
-		ret = [u'{:<{w}}  {:<9} {}'.format(a,b,c,w=w) for a,b,c in [
+		ret = ['{:<{w}}  {:<9} {}'.format(a,b,c,w=w) for a,b,c in [
 			('Format','FileExt','Valid codes'),
 			('------','-------','-----------')
 			] + sorted(d)]
-		return u'\n'.join(ret) + ('',u'-α')[g.debug_utf8] + '\n'
+		return '\n'.join(ret) + ('','-α')[g.debug_utf8] + '\n'
 
 	def get_fmt_data(self):
 		self._format()
@@ -229,7 +229,7 @@ class SeedSourceUnenc(SeedSource):
 	def _encrypt(self): pass
 
 	def _filename(self):
-		return u'{}[{}]{x}.{}'.format(self.seed.sid,self.seed.length,self.ext,x=u'-α' if g.debug_utf8 else '')
+		return '{}[{}]{x}.{}'.format(self.seed.sid,self.seed.length,self.ext,x='-α' if g.debug_utf8 else '')
 
 class SeedSourceEnc(SeedSource):
 
@@ -259,7 +259,7 @@ an empty passphrase, just hit ENTER twice.
 		while True:
 			ret = my_raw_input(p)
 			if ret:
-				if ret in g.hash_presets.keys():
+				if ret in list(g.hash_presets.keys()):
 					self.ssdata.hash_preset = ret
 					return ret
 				else:
@@ -304,7 +304,7 @@ an empty passphrase, just hit ENTER twice.
 			for i in range(g.passwd_max_tries):
 				pw = ' '.join(get_words_from_user('Enter {}: '.format(desc)))
 				pw2 = ' '.join(get_words_from_user('Repeat passphrase: '))
-				dmsg(u'Passphrases: [{}] [{}]'.format(pw,pw2))
+				dmsg('Passphrases: [{}] [{}]'.format(pw,pw2))
 				if pw == pw2:
 					vmsg('Passphrases match'); break
 				else: msg('Passphrases do not match.  Try again.')
@@ -316,7 +316,7 @@ an empty passphrase, just hit ENTER twice.
 		return pw
 
 	def _get_passphrase(self,desc_suf=''):
-		desc = u'{}passphrase for {}{}'.format(
+		desc = '{}passphrase for {}{}'.format(
 			('','old ')[self.op=='pwchg_old'],
 			self.desc,
 			('',' '+desc_suf)[bool(desc_suf)]
@@ -325,7 +325,7 @@ an empty passphrase, just hit ENTER twice.
 			w = pwfile_reuse_warning()
 			ret = ' '.join(get_words_from_file(opt.passwd_file,desc,silent=w))
 		else:
-			ret = ' '.join(get_words_from_user(u'Enter {}: '.format(desc)))
+			ret = ' '.join(get_words_from_user('Enter {}: '.format(desc)))
 		self.ssdata.passwd = ret
 
 	def _get_first_pw_and_hp_and_encrypt_seed(self):
@@ -385,12 +385,12 @@ class Mnemonic (SeedSourceUnenc):
 		longest_word = max(len(w) for w in wl)
 		from string import ascii_lowercase
 
-		m  = u'Enter your {}-word mnemonic, hitting ENTER or SPACE after each word.\n'
-		m += u"Optionally, you may use pad characters.  Anything you type that's not a\n"
-		m += u'lowercase letter will be treated as a “pad character”, i.e. it will simply\n'
-		m += u'be discarded.  Pad characters may be typed before, after, or in the middle\n'
-		m += u"of words.  For each word, once you've typed {} characters total (including\n"
-		m += u'pad characters) a pad character will enter the word.'
+		m  = 'Enter your {}-word mnemonic, hitting ENTER or SPACE after each word.\n'
+		m += "Optionally, you may use pad characters.  Anything you type that's not a\n"
+		m += 'lowercase letter will be treated as a “pad character”, i.e. it will simply\n'
+		m += 'be discarded.  Pad characters may be typed before, after, or in the middle\n'
+		m += "of words.  For each word, once you've typed {} characters total (including\n"
+		m += 'pad characters) a pad character will enter the word.'
 		msg(m.format(mn_len,longest_word))
 
 		def get_word():
@@ -584,8 +584,8 @@ class Wallet (SeedSourceEnc):
 	require_utf8_input = True # label is UTF-8
 
 	def _get_label_from_user(self,old_lbl=''):
-		d = u"to reuse the label '{}'".format(old_lbl.hl()) if old_lbl else 'for no label'
-		p = u'Enter a wallet label, or hit ENTER {}: '.format(d)
+		d = "to reuse the label '{}'".format(old_lbl.hl()) if old_lbl else 'for no label'
+		p = 'Enter a wallet label, or hit ENTER {}: '.format(d)
 		while True:
 			msg_r(p)
 			ret = my_raw_input('')
@@ -605,19 +605,19 @@ class Wallet (SeedSourceEnc):
 		if hasattr(self,'ss_in') and hasattr(self.ss_in.ssdata,'label'):
 			old_lbl = self.ss_in.ssdata.label
 			if opt.keep_label:
-				qmsg(u"Reusing label '{}' at user request".format(old_lbl.hl()))
+				qmsg("Reusing label '{}' at user request".format(old_lbl.hl()))
 				self.ssdata.label = old_lbl
 			elif opt.label:
-				qmsg(u"Using label '{}' requested on command line".format(opt.label.hl()))
+				qmsg("Using label '{}' requested on command line".format(opt.label.hl()))
 				lbl = self.ssdata.label = opt.label
 			else: # Prompt, using old value as default
 				lbl = self._get_label_from_user(old_lbl)
 
 			if (not opt.keep_label) and self.op == 'pwchg_new':
-				m = (u"changed to '{}'".format(lbl),'unchanged')[lbl==old_lbl]
-				qmsg(u'Label {}'.format(m))
+				m = ("changed to '{}'".format(lbl),'unchanged')[lbl==old_lbl]
+				qmsg('Label {}'.format(m))
 		elif opt.label:
-			qmsg(u"Using label '{}' requested on command line".format(opt.label.hl()))
+			qmsg("Using label '{}' requested on command line".format(opt.label.hl()))
 			self.ssdata.label = opt.label
 		else:
 			self._get_label_from_user()
@@ -685,7 +685,7 @@ class Wallet (SeedSourceEnc):
 			if uhp != hp:
 				qmsg("Warning: ignoring user-requested hash preset '{}'".format(uhp))
 
-		hash_params = map(int,hpdata[1:])
+		hash_params = list(map(int,hpdata[1:]))
 
 		if hash_params != get_hash_params(d.hash_preset):
 			msg("Hash parameters '{}' don't match hash preset '{}'".format(' '.join(hash_params),d.hash_preset))
@@ -728,13 +728,13 @@ class Wallet (SeedSourceEnc):
 			return False
 
 	def _filename(self):
-		return u'{}-{}[{},{}]{x}.{}'.format(
+		return '{}-{}[{},{}]{x}.{}'.format(
 				self.seed.sid,
 				self.ssdata.key_id,
 				self.seed.length,
 				self.ssdata.hash_preset,
 				self.ext,
-				x=u'-α' if g.debug_utf8 else '')
+				x='-α' if g.debug_utf8 else '')
 
 class Brainwallet (SeedSourceEnc):
 
@@ -862,14 +862,14 @@ to exit and re-run the program with the '--old-incog-fmt' option.
 	def _filename(self):
 		s = self.seed
 		d = self.ssdata
-		return u'{}-{}-{}[{},{}]{x}.{}'.format(
+		return '{}-{}-{}[{},{}]{x}.{}'.format(
 				s.sid,
 				d.key_id,
 				d.iv_id,
 				s.length,
 				d.hash_preset,
 				self.ext,
-				x=u'-α' if g.debug_utf8 else '')
+				x='-α' if g.debug_utf8 else '')
 
 	def _deformat(self):
 
@@ -990,7 +990,7 @@ harder to find, you're advised to choose a much larger file size than this.
 		d = self.ssdata
 		d.hincog_offset = self._get_hincog_params('input')[1]
 
-		qmsg(u"Getting hidden incog data from file '{}'".format(self.infile.name))
+		qmsg("Getting hidden incog data from file '{}'".format(self.infile.name))
 
 		# Already sanity-checked:
 		d.target_data_len = self._get_incog_data_len(opt.seed_len)
@@ -1001,7 +1001,7 @@ harder to find, you're advised to choose a much larger file size than this.
 		os.lseek(fh,int(d.hincog_offset),os.SEEK_SET)
 		self.fmt_data = os.read(fh,d.target_data_len)
 		os.close(fh)
-		qmsg(u"Data read from file '{}' at offset {}".format(self.infile.name,d.hincog_offset))
+		qmsg("Data read from file '{}' at offset {}".format(self.infile.name,d.hincog_offset))
 
 	# overrides method in SeedSource
 	def write_to_file(self):
@@ -1020,7 +1020,7 @@ harder to find, you're advised to choose a much larger file size than this.
 		try:
 			os.stat(fn)
 		except:
-			if keypress_confirm(u"Requested file '{}' does not exist.  Create?".format(fn),default_yes=True):
+			if keypress_confirm("Requested file '{}' does not exist.  Create?".format(fn),default_yes=True):
 				min_fsize = d.target_data_len + d.hincog_offset
 				msg(self.msg['choose_file_size'].format(min_fsize))
 				while True:
@@ -1048,4 +1048,4 @@ harder to find, you're advised to choose a much larger file size than this.
 		os.lseek(fh, int(d.hincog_offset), os.SEEK_SET)
 		os.write(fh, self.fmt_data)
 		os.close(fh)
-		msg(u"{} written to file '{}' at offset {}".format(capfirst(self.desc),f.name,d.hincog_offset))
+		msg("{} written to file '{}' at offset {}".format(capfirst(self.desc),f.name,d.hincog_offset))

+ 9 - 8
mmgen/share/Opts.py

@@ -21,29 +21,30 @@ Opts.py:  Generic options handling
 """
 
 import sys,getopt
+import collections
 # from mmgen.util import mdie,die,pdie,pmsg # DEBUG
 
 def usage(opts_data):
-	print('USAGE: {} {}'.format(opts_data['prog_name'], opts_data['usage']))
+	print(('USAGE: {} {}'.format(opts_data['prog_name'], opts_data['usage'])))
 	sys.exit(2)
 
 def print_help_and_exit(opts_data,longhelp=False):
 	pn = opts_data['prog_name']
 	pn_len = str(len(pn)+2)
-	out  = u'  {:<{p}} {}\n'.format(pn.upper()+':',opts_data['desc'].strip(),p=pn_len)
-	out += u'  {:<{p}} {} {}\n'.format('USAGE:',pn,opts_data['usage'].strip(),p=pn_len)
+	out  = '  {:<{p}} {}\n'.format(pn.upper()+':',opts_data['desc'].strip(),p=pn_len)
+	out += '  {:<{p}} {} {}\n'.format('USAGE:',pn,opts_data['usage'].strip(),p=pn_len)
 	o = opts_data[('options','long_options')[longhelp]].strip()
 	if 'options_fmt_args' in opts_data:
 		o = o.format(**opts_data['options_fmt_args']())
 	hdr = ('OPTIONS:','  LONG OPTIONS:')[longhelp]
 	ls = ('  ','')[longhelp]
 	es = ('','    ')[longhelp]
-	out += u'{ls}{}\n{ls}{es}{}'.format(hdr,('\n'+ls).join(o.splitlines()),ls=ls,es=es)
+	out += '{ls}{}\n{ls}{es}{}'.format(hdr,('\n'+ls).join(o.splitlines()),ls=ls,es=es)
 	if 'notes' in opts_data and not longhelp:
 		n = opts_data['notes']
-		if callable(n): n = n()
+		if isinstance(n, collections.Callable): n = n()
 		out += '\n  ' + '\n  '.join(n.rstrip().splitlines())
-	print(out.encode('utf8'))
+	print((out.encode('utf8')))
 	sys.exit(0)
 
 def process_opts(argv,opts_data,short_opts,long_opts,skip_help=False):
@@ -55,7 +56,7 @@ def process_opts(argv,opts_data,short_opts,long_opts,skip_help=False):
 	so_str = short_opts.replace('-:','').replace('-','')
 	try: cl_opts,args = getopt.getopt(argv[1:], so_str, long_opts)
 	except getopt.GetoptError as err:
-		print(str(err)); sys.exit(2)
+		print((str(err))); sys.exit(2)
 
 	sopts_list = ':_'.join(['_'.join(list(i)) for i in short_opts.split(':')]).split('_')
 	opts,skipped_help = {},False
@@ -112,7 +113,7 @@ def parse_opts(argv,opts_data,opt_filter=None,skip_help=False):
 				if not skip: od[-1][3] += '\n' + l
 
 		opts_data[k] = '\n'.join(
-			[u'{:<3} --{} {}'.format(
+			['{:<3} --{} {}'.format(
 				('-'+d[0]+',','')[d[0]=='-'],d[1],d[3]) for d in od if d[6] == False]
 		)
 		od_all += od

+ 4 - 4
mmgen/test.py

@@ -33,7 +33,7 @@ def cleandir(d):
 	except: return
 
 	from shutil import rmtree
-	gmsg(u"Cleaning directory '{}'".format(d))
+	gmsg("Cleaning directory '{}'".format(d))
 	for f in files:
 		try:
 			os.unlink(os.path.join(d_enc,f))
@@ -53,11 +53,11 @@ def getrandstr(num_chars,no_space=False):
 	return ''.join([chr(ord(i)%n+m) for i in list(os.urandom(num_chars))])
 
 def mk_tmpdir(d):
-	try: os.mkdir(d,0755)
+	try: os.mkdir(d,0o755)
 	except OSError as e:
 		if e.errno != 17: raise
 	else:
-		vmsg(u"Created directory '{}'".format(d))
+		vmsg("Created directory '{}'".format(d))
 
 def mk_tmpdir_path(path,cfg):
 	try:
@@ -116,6 +116,6 @@ def cmp_or_die(s,t,skip_ok=False):
 def init_coverage():
 	coverdir = os.path.join('test','trace')
 	acc_file = os.path.join('test','trace.acc')
-	try: os.mkdir(coverdir,0755)
+	try: os.mkdir(coverdir,0o755)
 	except: pass
 	return coverdir,acc_file

+ 12 - 12
mmgen/tool.py

@@ -107,14 +107,14 @@ cmd_data = OrderedDict([
 
 def usage(command):
 
-	for v in cmd_data.values():
+	for v in list(cmd_data.values()):
 		if v and v[0][-2:] == '-]':
 			v[0] = v[0][:-2] + ' or STDIN]'
 		if 'MARGS' in v: v.remove('MARGS')
 
 	if not command:
 		Msg('Usage information for mmgen-tool commands:')
-		for k,v in cmd_data.items():
+		for k,v in list(cmd_data.items()):
 			Msg('  {:18} {}'.format(k.lower(),' '.join(v)))
 		from mmgen.main_tool import stdin_msg
 		Msg('\n  '+'\n  '.join(stdin_msg.split('\n')))
@@ -438,7 +438,7 @@ def Rand2file(outfile,nbytes,threads=4,silent=False):
 	nbytes = parse_nbytes(nbytes)
 	from Crypto import Random
 	rh = Random.new()
-	from Queue import Queue
+	from queue import Queue
 	from threading import Thread
 	bsize = 2**20
 	roll = bsize * 4
@@ -486,7 +486,7 @@ def Rand2file(outfile,nbytes,threads=4,silent=False):
 
 	if not silent:
 		msg('\rRead: {} bytes'.format(nbytes))
-		qmsg(u"\r{} bytes of random data written to file '{}'".format(nbytes,outfile))
+		qmsg("\r{} bytes of random data written to file '{}'".format(nbytes,outfile))
 	q1.join()
 	q2.join()
 	f.close()
@@ -537,7 +537,7 @@ def monero_wallet_ops(infile,op,blockheight=None,addrs=None):
 	def create(n,d,fn):
 		try: os.stat(fn)
 		except: pass
-		else: die(1,u"Wallet '{}' already exists!".format(fn))
+		else: die(1,"Wallet '{}' already exists!".format(fn))
 		p = pexpect.spawn('monero-wallet-cli --generate-from-spend-key {}'.format(fn.encode('utf8')))
 		if g.debug: p.logfile = sys.stdout
 		my_expect(p,'Awaiting initial prompt','Secret spend key: ')
@@ -573,7 +573,7 @@ def monero_wallet_ops(infile,op,blockheight=None,addrs=None):
 
 	def sync(n,d,fn):
 		try: os.stat(fn)
-		except: die(1,u"Wallet '{}' does not exist!".format(fn))
+		except: die(1,"Wallet '{}' does not exist!".format(fn))
 		p = pexpect.spawn('monero-wallet-cli --wallet-file={}'.format(fn.encode('utf8')))
 		if g.debug: p.logfile = sys.stdout
 		my_expect(p,'Awaiting password prompt','Wallet password: ')
@@ -615,16 +615,16 @@ def monero_wallet_ops(infile,op,blockheight=None,addrs=None):
 		gmsg('\n{}ing {} wallet{}'.format(m[op][0],dl,suf(dl)))
 		for n,d in enumerate(data): # [d.sec,d.wallet_passwd,d.viewkey,d.addr]
 			fn = os.path.join(
-				opt.outdir or u'',u'{}-{}-MoneroWallet{}'.format(
+				opt.outdir or '','{}-{}-MoneroWallet{}'.format(
 					al.al_id.sid,
 					d.idx,
-					u'-α' if g.debug_utf8 else ''))
-			gmsg(u'\n{}ing wallet {}/{} ({})'.format(m[op][1],n+1,dl,fn))
+					'-α' if g.debug_utf8 else ''))
+			gmsg('\n{}ing wallet {}/{} ({})'.format(m[op][1],n+1,dl,fn))
 			m[op][2](n,d,fn)
 		gmsg('\n{} wallet{} {}ed'.format(dl,suf(dl),m[op][0].lower()))
 		if op == 'sync':
-			col1_w = max(map(len,bals)) + 1
-			fs = u'{:%s} {:18} {:18}' % col1_w
+			col1_w = max(list(map(len,bals))) + 1
+			fs = '{:%s} {:18} {:18}' % col1_w
 			msg('\n'+fs.format('Wallet','  Balance','  Unlocked Balance'))
 			tbals = [Decimal('0'),Decimal('0')]
 			for bal in bals:
@@ -715,7 +715,7 @@ def Txview(*infiles,**kwargs):
 	flist = MMGenFileList(infiles,ftype=MMGenTX)
 	flist.sort_by_age(key=sort_key) # in-place sort
 	from mmgen.term import get_terminal_size
-	sep = u'—'*77+'\n'
+	sep = '—'*77+'\n'
 	out = sep.join([MMGenTX(fn).format_view(terse=terse) for fn in flist.names()])
 	(Msg,do_pager)[pager](out.rstrip())
 

+ 27 - 27
mmgen/tw.py

@@ -126,7 +126,7 @@ watch-only wallet using '{}-addrimport' and then re-run this program.
 				tr_rpc.append(o)
 		self.unspent = self.MMGenTwOutputList(
 						self.MMGenTwUnspentOutput(
-				**dict(i for i in o.items() if i[0] in dir(self.MMGenTwUnspentOutput))
+				**dict(i for i in list(o.items()) if i[0] in dir(self.MMGenTwUnspentOutput))
 						) for o in tr_rpc)
 		for u in self.unspent:
 			if u.label == None: u.label = ''
@@ -143,7 +143,7 @@ watch-only wallet using '{}-addrimport' and then re-run this program.
 		}
 		key = key or self.sort_key
 		if key not in sort_funcs:
-			die(1,"'{}': invalid sort key.  Valid options: {}".format(key,' '.join(sort_funcs.keys())))
+			die(1,"'{}': invalid sort key.  Valid options: {}".format(key,' '.join(list(sort_funcs.keys()))))
 		self.sort_key = key
 		assert type(reverse) == bool
 		self.unspent.sort(key=sort_funcs[key],reverse=reverse or self.reverse)
@@ -190,9 +190,9 @@ watch-only wallet using '{}-addrimport' and then re-run this program.
 
 		out  = [self.hdr_fmt.format(' '.join(self.sort_info()),g.dcoin,self.total.hl())]
 		if g.chain != 'mainnet': out += ['Chain: '+green(g.chain.upper())]
-		fs = {  'btc':   u' {n:%s} {t:%s} {v:2} {a} {A} {c:<}' % (col1_w,tx_w),
-				'eth':   u' {n:%s} {a} {A}' % col1_w,
-				'token': u' {n:%s} {a} {A} {A2}' % col1_w }[self.disp_type]
+		fs = {  'btc':   ' {n:%s} {t:%s} {v:2} {a} {A} {c:<}' % (col1_w,tx_w),
+				'eth':   ' {n:%s} {a} {A}' % col1_w,
+				'token': ' {n:%s} {a} {A} {A2}' % col1_w }[self.disp_type]
 		out += [fs.format(  n='Num',
 							t='TXid'.ljust(tx_w - 5) + ' Vout',
 							v='',
@@ -208,10 +208,10 @@ watch-only wallet using '{}-addrimport' and then re-run this program.
 				else i.twmmid if i.twmmid.type=='mmgen'
 					else 'Non-{}'.format(g.proj_name),width=mmid_w,color=True)
 			if self.show_mmid:
-				addr_out = u'{} {}'.format(
+				addr_out = '{} {}'.format(
 					type(i.addr).fmtc(addr_dots,width=btaddr_w,color=True) if i.skip == 'addr' \
 							else i.addr.fmt(width=btaddr_w,color=True),
-					u'{} {}'.format(mmid_disp,i.label.fmt(width=label_w,color=True) \
+					'{} {}'.format(mmid_disp,i.label.fmt(width=label_w,color=True) \
 							if label_w > 0 else ''))
 			else:
 				addr_out = type(i.addr).fmtc(addr_dots,width=addr_w,color=True) \
@@ -236,9 +236,9 @@ watch-only wallet using '{}-addrimport' and then re-run this program.
 		addr_w = max(len(i.addr) for i in self.unspent)
 		mmid_w = max(len(('',i.twmmid)[i.twmmid.type=='mmgen']) for i in self.unspent) or 12 # DEADBEEF:S:1
 		amt_w = g.proto.coin_amt.max_prec + 4
-		fs = {  'btc':   u' {n:4} {t:%s} {a} {m} {A:%s} {c:<8} {g:<6} {l}' % (self.txid_w+3,amt_w),
-				'eth':   u' {n:4} {a} {m} {A:%s} {l}' % amt_w,
-				'token': u' {n:4} {a} {m} {A:%s} {A2:%s} {l}' % (amt_w,amt_w)
+		fs = {  'btc':   ' {n:4} {t:%s} {a} {m} {A:%s} {c:<8} {g:<6} {l}' % (self.txid_w+3,amt_w),
+				'eth':   ' {n:4} {a} {m} {A:%s} {l}' % amt_w,
+				'token': ' {n:4} {a} {m} {A:%s} {A2:%s} {l}' % (amt_w,amt_w)
 				}[self.disp_type]
 		out = [fs.format(   n='Num',
 							t='Tx ID,Vout',
@@ -429,15 +429,15 @@ class TwAddrList(MMGenDict):
 			# args: minconf,watchonly, MUST use keys() so we get list, not dict
 			if 'label_api' in g.rpch.caps:
 				acct_list = g.rpch.listlabels()
-				acct_addrs = [a.keys() for a in g.rpch.getaddressesbylabel([[k] for k in acct_list],batch=True)]
+				acct_addrs = [list(a.keys()) for a in g.rpch.getaddressesbylabel([[k] for k in acct_list],batch=True)]
 			else:
-				acct_list = g.rpch.listaccounts(0,True).keys() # raw list, no 'L'
+				acct_list = list(g.rpch.listaccounts(0,True).keys()) # raw list, no 'L'
 				acct_addrs = g.rpch.getaddressesbyaccount([[a] for a in acct_list],batch=True) # use raw list here
 			acct_labels = MMGenList([TwLabel(a,on_fail='silent') for a in acct_list])
 			check_dup_mmid(acct_labels)
 			assert len(acct_list) == len(acct_addrs),(
 				'listaccounts() and getaddressesbyaccount() not equal in length')
-			addr_pairs = zip(acct_labels,acct_addrs)
+			addr_pairs = list(zip(acct_labels,acct_addrs))
 			check_addr_array_lens(addr_pairs)
 			for label,addr_arr in addr_pairs:
 				if not label: continue
@@ -455,14 +455,14 @@ class TwAddrList(MMGenDict):
 
 	def format(self,showbtcaddrs,sort,show_age,show_days):
 		out = ['Chain: '+green(g.chain.upper())] if g.chain != 'mainnet' else []
-		fs = u'{{mid}}{} {{cmt}} {{amt}}{}'.format(('',' {addr}')[showbtcaddrs],('',' {age}')[show_age])
-		mmaddrs = [k for k in self.keys() if k.type == 'mmgen']
+		fs = '{{mid}}{} {{cmt}} {{amt}}{}'.format(('',' {addr}')[showbtcaddrs],('',' {age}')[show_age])
+		mmaddrs = [k for k in list(self.keys()) if k.type == 'mmgen']
 		max_mmid_len = max(len(k) for k in mmaddrs) + 2 if mmaddrs else 10
-		max_cmt_len  = max(max(screen_width(v['lbl'].comment) for v in self.values()),7)
+		max_cmt_len  = max(max(screen_width(v['lbl'].comment) for v in list(self.values())),7)
 		addr_width = max(len(self[mmid]['addr']) for mmid in self)
 
 		# fp: fractional part
-		max_fp_len = max([len(a.split('.')[1]) for a in [str(v['amt']) for v in self.values()] if '.' in a] or [1])
+		max_fp_len = max([len(a.split('.')[1]) for a in [str(v['amt']) for v in list(self.values())] if '.' in a] or [1])
 		out += [fs.format(
 				mid=MMGenID.fmtc('MMGenID',width=max_mmid_len),
 				addr=(CoinAddr.fmtc('ADDRESS',width=addr_width) if showbtcaddrs else None),
@@ -558,9 +558,9 @@ class TrackingWallet(MMGenObject):
 
 		try:
 			if not is_mmgen_id(arg1):
-				assert coinaddr,u"Invalid coin address for this chain: {}".format(arg1)
-			assert coinaddr,u"{pn} address '{ma}' not found in tracking wallet"
-			assert self.is_in_wallet(coinaddr),u"Address '{ca}' not found in tracking wallet"
+				assert coinaddr,"Invalid coin address for this chain: {}".format(arg1)
+			assert coinaddr,"{pn} address '{ma}' not found in tracking wallet"
+			assert self.is_in_wallet(coinaddr),"Address '{ca}' not found in tracking wallet"
 		except Exception as e:
 			msg(e.message.format(pn=g.proj_name,ma=mmaddr,ca=coinaddr))
 			return False
@@ -592,8 +592,8 @@ class TrackingWallet(MMGenObject):
 			m = mmaddr.type.replace('mmg','MMG')
 			a = mmaddr.replace(g.proto.base_coin.lower()+':','')
 			s = '{} address {} in tracking wallet'.format(m,a)
-			if label: msg(u"Added label '{}' to {}".format(label,s))
-			else:     msg(u'Removed label from {}'.format(s))
+			if label: msg("Added label '{}' to {}".format(label,s))
+			else:     msg('Removed label from {}'.format(s))
 			return True
 
 	@write_mode
@@ -602,7 +602,7 @@ class TrackingWallet(MMGenObject):
 
 	@write_mode
 	def remove_address(self,addr):
-		raise NotImplementedError,'address removal not implemented for coin {}'.format(g.coin)
+		raise NotImplementedError('address removal not implemented for coin {}'.format(g.coin))
 
 class TwGetBalance(MMGenObject):
 
@@ -616,7 +616,7 @@ class TwGetBalance(MMGenObject):
 		rpc_init()
 		self.minconf = minconf
 		self.quiet = quiet
-		self.data = dict([(k,[g.proto.coin_amt('0')] * 4) for k in 'TOTAL','Non-MMGen','Non-wallet'])
+		self.data = dict([(k,[g.proto.coin_amt('0')] * 4) for k in ('TOTAL','Non-MMGen','Non-wallet')])
 		self.create_data()
 
 	def create_data(self):
@@ -650,12 +650,12 @@ class TwGetBalance(MMGenObject):
 								c=' >={} confirms'.format(self.minconf))
 			for key in sorted(self.data):
 				if not any(self.data[key]): continue
-				o += self.fs.format(**dict(zip(
+				o += self.fs.format(**dict(list(zip(
 							('w','u','p','c'),
 							[key+':'] + [a.fmt(color=True,suf=' '+g.dcoin) for a in self.data[key]]
-							)))
+							))))
 
-		for key,vals in self.data.items():
+		for key,vals in list(self.data.items()):
 			if key == 'TOTAL': continue
 			if vals[3]:
 				o += red('Warning: this wallet contains PRIVATE KEYS for {} outputs!\n'.format(key))

+ 20 - 20
mmgen/tx.py

@@ -113,7 +113,7 @@ def scriptPubKey2addr(s):
 	elif len(s) == 44 and s[:4] == g.proto.witness_vernum_hex + '14':
 		return g.proto.pubhash2bech32addr(s[4:]),'bech32'
 	else:
-		raise NotImplementedError,'Unknown scriptPubKey ({})'.format(s)
+		raise NotImplementedError('Unknown scriptPubKey ({})'.format(s))
 
 from collections import OrderedDict
 class DeserializedTX(OrderedDict,MMGenObject): # need to add MMGen types
@@ -145,7 +145,7 @@ class DeserializedTX(OrderedDict,MMGenObject): # need to add MMGen types
 		if has_witness:
 			u = hshift(tx,2,skip=True)[2:]
 			if u != '01':
-				raise IllegalWitnessFlagValue,"'{}': Illegal value for flag in transaction!".format(u)
+				raise IllegalWitnessFlagValue("'{}': Illegal value for flag in transaction!".format(u))
 			del tx_copy[-len(tx)-2:-len(tx)]
 
 		d['num_txins'] = readVInt(tx)
@@ -181,7 +181,7 @@ class DeserializedTX(OrderedDict,MMGenObject): # need to add MMGen types
 					hshift(wd,readVInt(wd,skip=True),skip=True) for item in range(readVInt(wd,skip=True))
 				]
 			if wd:
-				raise WitnessSizeMismatch,'More witness data than inputs with witnesses!'
+				raise WitnessSizeMismatch('More witness data than inputs with witnesses!')
 
 		d['lock_time'] = bytes2int(hshift(tx,4))
 		d['txid'] = hexlify(sha256(sha256(''.join(tx_copy)).digest()).digest()[::-1])
@@ -239,7 +239,7 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
 	class MMGenTxInput(MMGenListItem):
 		for k in txio_attrs: locals()[k] = txio_attrs[k] # in lieu of inheritance
 		scriptPubKey = MMGenListItemAttr('scriptPubKey','HexStr')
-		sequence = MMGenListItemAttr('sequence',(int,long)[g.platform=='win'],typeconv=False)
+		sequence = MMGenListItemAttr('sequence',(int,int)[g.platform=='win'],typeconv=False)
 
 	class MMGenTxOutput(MMGenListItem):
 		for k in txio_attrs: locals()[k] = txio_attrs[k]
@@ -408,7 +408,7 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
 		# allow for 5% error
 		ratio = float(est_vsize) / vsize
 		if not (0.95 < ratio < 1.05):
-			raise BadTxSizeEstimate,(m1+m2+m3).format(ratio,1/ratio)
+			raise BadTxSizeEstimate((m1+m2+m3).format(ratio,1/ratio))
 
 	# https://bitcoin.stackexchange.com/questions/1195/how-to-calculate-transaction-size-before-sending
 	# 180: uncompressed, 148: compressed
@@ -548,7 +548,7 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
 	def process_fee_spec(self,tx_fee,tx_size,on_fail='throw'):
 		import re
 		units = dict((u[0],u) for u in g.proto.coin_amt.units)
-		pat = r'([1-9][0-9]*)({})'.format('|'.join(units.keys()))
+		pat = r'([1-9][0-9]*)({})'.format('|'.join(list(units.keys())))
 		if g.proto.coin_amt(tx_fee,on_fail='silent'):
 			return g.proto.coin_amt(tx_fee)
 		elif re.match(pat,tx_fee):
@@ -566,10 +566,10 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
 				abs_fee = self.convert_and_check_fee(tx_fee,desc)
 			if abs_fee:
 				m = ('',' (after {}x adjustment)'.format(opt.tx_fee_adj))[opt.tx_fee_adj != 1]
-				p = u'{} TX fee{}: {}{} {} ({} {})\n'.format(
+				p = '{} TX fee{}: {}{} {} ({} {})\n'.format(
 						desc,
 						m,
-						('',u'≈')[self.fee_is_approximate],
+						('','≈')[self.fee_is_approximate],
 						abs_fee.hl(),
 						g.coin,
 						pink(str(self.fee_abs2rel(abs_fee))),
@@ -605,7 +605,7 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
 
 	def decode_io_oldfmt(self,data):
 		tr = {'amount':'amt', 'address':'addr', 'confirmations':'confs','comment':'label'}
-		tr_rev = dict(map(reversed,tr.items()))
+		tr_rev = dict(list(map(reversed,list(tr.items()))))
 		copy_keys = [tr_rev[k] if k in tr_rev else k for k in self.MMGenTxInput.__dict__]
 		ret = MMGenList(self.MMGenTxInput(**dict([(tr[k] if k in tr else k,d[k])
 					for k in copy_keys if k in d and d[k] != ''])) for d in data)
@@ -736,11 +736,11 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
 			self.coin_txid = CoinTxID(dt['txid'],on_fail='raise')
 			self.check_sigs(dt)
 			if not self.coin_txid == g.rpch.decoderawtransaction(self.hex)['txid']:
-				raise BadMMGenTxID,'txid mismatch (after signing)'
+				raise BadMMGenTxID('txid mismatch (after signing)')
 			msg('OK')
 			return True
 		except Exception as e:
-			try: m = u'{}'.format(e.message)
+			try: m = '{}'.format(e.message)
 			except: m = repr(e.message)
 			msg('\n'+yellow(m))
 			return False
@@ -765,17 +765,17 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
 		lt = deserial_tx['lock_time']
 		if lt != int(self.locktime or 0):
 			m2 = 'Transaction hex locktime ({}) does not match MMGen transaction locktime ({})\n{}'
-			raise TxHexMismatch,m2.format(lt,self.locktime,m)
+			raise TxHexMismatch(m2.format(lt,self.locktime,m))
 
 		def check_equal(desc,hexio,mmio):
 			if mmio != hexio:
 				msg('\nMMGen {}:\n{}'.format(desc,pformat(mmio)))
 				msg('Hex {}:\n{}'.format(desc,pformat(hexio)))
 				m2 = '{} in hex transaction data from coin daemon do not match those in MMGen transaction!\n'
-				raise TxHexMismatch,(m2+m).format(desc.capitalize())
+				raise TxHexMismatch((m2+m).format(desc.capitalize()))
 
-		seq_hex   = map(lambda i: int(i['nSeq'],16),deserial_tx['txins'])
-		seq_mmgen = map(lambda i: i.sequence or g.max_int,self.inputs)
+		seq_hex   = [int(i['nSeq'],16) for i in deserial_tx['txins']]
+		seq_mmgen = [i.sequence or g.max_int for i in self.inputs]
 		check_equal('sequence numbers',seq_hex,seq_mmgen)
 
 		d_hex   = sorted((i['txid'],i['vout']) for i in deserial_tx['txins'])
@@ -788,7 +788,7 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
 
 		uh = deserial_tx['unsigned_hex']
 		if str(self.txid) != make_chksum_6(unhexlify(uh)).upper():
-			raise TxHexMismatch,'MMGen TxID ({}) does not match hex transaction data!\n{}'.format(self.txid,m)
+			raise TxHexMismatch('MMGen TxID ({}) does not match hex transaction data!\n{}'.format(self.txid,m))
 
 	def check_pubkey_scripts(self):
 		for n,i in enumerate(self.inputs,1):
@@ -957,7 +957,7 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
 	def create_fn(self):
 		tl = self.get_hex_locktime()
 		tn = ('','.testnet')[g.proto.is_testnet()]
-		self.fn = u'{}{}[{!s}{}{}]{x}{}.{}'.format(
+		self.fn = '{}{}[{!s}{}{}]{x}{}.{}'.format(
 			self.txid,
 			('-'+g.dcoin,'')[g.coin=='BTC'],
 			self.send_amt,
@@ -966,7 +966,7 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
 							)[self.is_replaceable()],
 			('',',tl={}'.format(tl))[bool(tl)],
 			tn,self.ext,
-			x=u'-α' if g.debug_utf8 else '')
+			x='-α' if g.debug_utf8 else '')
 
 	def write_to_file(  self,
 						add_desc='',
@@ -1042,7 +1042,7 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
 						('','confirmations:','{} (around {} days)'.format(confs,days) if blockcount else '')
 					] if ip else icommon + [
 						('','change:',green('True') if e.is_chg else '')]
-					out += '\n'.join([(u'{:>3} {:<8} {}'.format(*d)) for d in items if d[2]]) + '\n\n'
+					out += '\n'.join([('{:>3} {:<8} {}'.format(*d)) for d in items if d[2]]) + '\n\n'
 			return out
 
 		return  format_io('inputs') + format_io('outputs')
@@ -1096,7 +1096,7 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
 		enl = ('\n','')[bool(terse)]
 		out += enl
 		if self.label:
-			out += u'Comment: {}\n{}'.format(self.label.hl(),enl)
+			out += 'Comment: {}\n{}'.format(self.label.hl(),enl)
 
 		out += self.format_view_body(blockcount,nonmm_str,max_mmwid,enl,terse=terse)
 

+ 32 - 32
mmgen/util.py

@@ -53,7 +53,7 @@ def die_wait(delay,ev=0,s=''):
 def die_pause(ev=0,s=''):
 	assert type(ev) == int
 	if s: msg(s)
-	raw_input('Press ENTER to exit')
+	input('Press ENTER to exit')
 	sys.exit(ev)
 def die(ev=0,s=''):
 	assert type(ev) == int
@@ -81,7 +81,7 @@ def pdie(*args):
 def set_for_type(val,refval,desc,invert_bool=False,src=None):
 	src_str = (''," in '{}'".format(src))[bool(src)]
 	if type(refval) == bool:
-		v = unicode(val).lower()
+		v = str(val).lower()
 		if v in ('true','yes','1'):          ret = True
 		elif v in ('false','no','none','0'): ret = False
 		else: die(1,"'{}': invalid value for '{}'{} (must be of type '{}')".format(
@@ -91,7 +91,7 @@ def set_for_type(val,refval,desc,invert_bool=False,src=None):
 		try:
 			ret = type(refval)((val,not val)[invert_bool])
 		except:
-			die(1,u"'{}': invalid value for '{}'{} (must be of type '{}')".format(
+			die(1,"'{}': invalid value for '{}'{} (must be of type '{}')".format(
 				val,desc,src_str,type(refval).__name__))
 	return ret
 
@@ -121,9 +121,9 @@ def check_or_create_dir(path):
 		os.listdir(path)
 	except:
 		try:
-			os.makedirs(path,0700)
+			os.makedirs(path,0o700)
 		except:
-			die(2,u"ERROR: unable to read or create path '{}'".format(path))
+			die(2,"ERROR: unable to read or create path '{}'".format(path))
 
 from mmgen.opts import opt
 
@@ -178,7 +178,7 @@ def make_chksum_8(s,sep=False):
 	return '{} {}'.format(s[:4],s[4:]) if sep else s
 def make_chksum_6(s):
 	from mmgen.obj import HexStr
-	if type(s) == unicode: s = s.encode('utf8')
+	if type(s) == str: s = s.encode('utf8')
 	return HexStr(sha256(s).hexdigest()[:6])
 def is_chksum_6(s): return len(s) == 6 and is_hex_str_lc(s)
 
@@ -280,7 +280,7 @@ class baseconv(object):
 
 	@classmethod
 	def b58decode(cls,s,pad=None):
-		pad = cls.get_pad(s,pad,'de',cls.b58pad_lens_rev,[bytes,unicode])
+		pad = cls.get_pad(s,pad,'de',cls.b58pad_lens_rev,[bytes,str])
 		return unhexlify(cls.tohex(s,'b58',pad=pad*2 if pad else None))
 
 	@staticmethod
@@ -301,7 +301,7 @@ class baseconv(object):
 
 	@classmethod
 	def check_wordlists(cls):
-		for k,v in cls.wl_chksums.items(): assert cls.get_wordlist_chksum(k) == v
+		for k,v in list(cls.wl_chksums.items()): assert cls.get_wordlist_chksum(k) == v
 
 	@classmethod
 	def check_wordlist(cls,wl_id):
@@ -394,7 +394,7 @@ def decode_pretty_hexdump(data):
 		return False
 
 def strip_comments(line):
-	return re.sub(ur'\s+$',u'',re.sub(ur'#.*',u'',line,1))
+	return re.sub(r'\s+$','',re.sub(r'#.*','',line,1))
 
 def remove_comments(lines):
 	return [m for m in [strip_comments(l) for l in lines] if m != '']
@@ -456,7 +456,7 @@ def check_file_type_and_access(fname,ftype,blkdev_ok=False):
 
 	try: mode = os.stat(fname).st_mode
 	except:
-		die(1,u"Unable to stat requested {} '{}'".format(ftype,fname))
+		die(1,"Unable to stat requested {} '{}'".format(ftype,fname))
 
 	for t in ok_types:
 		if t[0](mode): break
@@ -527,7 +527,7 @@ def confirm_or_raise(message,q,expect='YES',exit_msg='Exiting at user request'):
 	a = q+'  ' if q[0].isupper() else 'Are you sure you want to {}?\n'.format(q)
 	b = "Type uppercase '{}' to confirm: ".format(expect)
 	if my_raw_input(a+b).strip() != expect:
-		raise UserNonConfirmation,exit_msg
+		raise UserNonConfirmation(exit_msg)
 
 def write_data_to_file( outfile,data,desc='data',
 						ask_write=False,
@@ -548,7 +548,7 @@ def write_data_to_file( outfile,data,desc='data',
 	if ask_write_default_yes == False or ask_write_prompt:
 		ask_write = True
 
-	if not binary and type(data) == unicode:
+	if not binary and type(data) == str:
 		data = data.encode('utf8')
 
 	def do_stdout():
@@ -570,7 +570,7 @@ def write_data_to_file( outfile,data,desc='data',
 						confirm_or_raise('','output {} to pipe'.format(desc))
 						msg('')
 				of2,pd = os.path.relpath(of),os.path.pardir
-				msg(u"Redirecting output to file '{}'".format((of2,of)[of2[:len(pd)] == pd]))
+				msg("Redirecting output to file '{}'".format((of2,of)[of2[:len(pd)] == pd]))
 			else:
 				msg('Redirecting output to file')
 
@@ -592,9 +592,9 @@ def write_data_to_file( outfile,data,desc='data',
 
 		hush = False
 		if file_exists(outfile) and ask_overwrite:
-			q = u"File '{}' already exists\nOverwrite?".format(outfile)
+			q = "File '{}' already exists\nOverwrite?".format(outfile)
 			confirm_or_raise('',q)
-			msg(u"Overwriting file '{}'".format(outfile))
+			msg("Overwriting file '{}'".format(outfile))
 			hush = True
 
 		# not atomic, but better than nothing
@@ -606,18 +606,18 @@ def write_data_to_file( outfile,data,desc='data',
 				d = ''
 			finally:
 				if d != cmp_data:
-					m = u"{} in file '{}' has been altered by some other program!  Aborting file write"
+					m = "{} in file '{}' has been altered by some other program!  Aborting file write"
 					die(3,m.format(desc,outfile))
 
 		f = open_file_or_exit(outfile,('w','wb')[bool(binary)])
 		try:
 			f.write(data)
 		except:
-			die(2,u"Failed to write {} to file '{}'".format(desc,outfile))
+			die(2,"Failed to write {} to file '{}'".format(desc,outfile))
 		f.close
 
 		if not (hush or silent):
-			msg(u"{} written to file '{}'".format(capfirst(desc),outfile))
+			msg("{} written to file '{}'".format(capfirst(desc),outfile))
 
 		return True
 
@@ -631,17 +631,17 @@ def write_data_to_file( outfile,data,desc='data',
 def get_words_from_user(prompt):
 	# split() also strips
 	words = my_raw_input(prompt, echo=opt.echo_passphrase).split()
-	dmsg(u'Sanitized input: [{}]'.format(' '.join(words)))
+	dmsg('Sanitized input: [{}]'.format(' '.join(words)))
 	return words
 
 def get_words_from_file(infile,desc,silent=False):
 	if not silent:
-		qmsg(u"Getting {} from file '{}'".format(desc,infile))
+		qmsg("Getting {} from file '{}'".format(desc,infile))
 	f = open_file_or_exit(infile, 'r')
 	try: words = f.read().decode('utf8').split() # split() also strips
 	except: die(1,'{} data must be UTF-8 encoded.'.format(capfirst(desc)))
 	f.close()
-	dmsg(u'Sanitized input: [{}]'.format(' '.join(words)))
+	dmsg('Sanitized input: [{}]'.format(' '.join(words)))
 	return words
 
 def get_words(infile,desc,prompt):
@@ -655,7 +655,7 @@ def mmgen_decrypt_file_maybe(fn,desc='',silent=False):
 	have_enc_ext = get_extension(fn) == g.mmenc_ext
 	if have_enc_ext or not is_utf8(d):
 		m = ('Attempting to decrypt','Decrypting')[have_enc_ext]
-		msg(u"{} {} '{}'".format(m,desc,fn))
+		msg("{} {} '{}'".format(m,desc,fn))
 		from mmgen.crypto import mmgen_decrypt_retry
 		d = mmgen_decrypt_retry(d,desc)
 	return d
@@ -664,19 +664,19 @@ def get_lines_from_file(fn,desc='',trim_comments=False,silent=False):
 	dec = mmgen_decrypt_file_maybe(fn,desc,silent=silent)
 	ret = dec.decode('utf8').splitlines() # DOS-safe
 	if trim_comments: ret = remove_comments(ret)
-	dmsg(u"Got {} lines from file '{}'".format(len(ret),fn))
+	dmsg("Got {} lines from file '{}'".format(len(ret),fn))
 	return ret
 
 def get_data_from_user(desc='data',silent=False): # user input MUST be UTF-8
-	p = ('',u'Enter {}: '.format(desc))[g.stdin_tty]
+	p = ('','Enter {}: '.format(desc))[g.stdin_tty]
 	data = my_raw_input(p,echo=opt.echo_passphrase)
-	dmsg(u'User input: [{}]'.format(data))
+	dmsg('User input: [{}]'.format(data))
 	return data
 
 def get_data_from_file(infile,desc='data',dash=False,silent=False,binary=False,require_utf8=False):
 	if dash and infile == '-': return sys.stdin.read()
 	if not opt.quiet and not silent and desc:
-		qmsg(u"Getting {} from file '{}'".format(desc,infile))
+		qmsg("Getting {} from file '{}'".format(desc,infile))
 	f = open_file_or_exit(infile,('r','rb')[bool(binary)],silent=silent)
 	data = f.read()
 	f.close()
@@ -687,7 +687,7 @@ def get_data_from_file(infile,desc='data',dash=False,silent=False,binary=False,r
 
 def pwfile_reuse_warning():
 	if 'passwd_file_used' in globals():
-		qmsg(u"Reusing passphrase from file '{}' at user request".format(opt.passwd_file))
+		qmsg("Reusing passphrase from file '{}' at user request".format(opt.passwd_file))
 		return True
 	globals()['passwd_file_used'] = True
 	return False
@@ -715,7 +715,7 @@ def my_raw_input(prompt,echo=True,insert_txt='',use_readline=True):
 	from mmgen.term import kb_hold_protect
 	kb_hold_protect()
 	if echo or not sys.stdin.isatty():
-		reply = raw_input(prompt.encode('utf8'))
+		reply = input(prompt.encode('utf8'))
 	else:
 		from getpass import getpass
 		reply = getpass(prompt.encode('utf8'))
@@ -731,7 +731,7 @@ def keypress_confirm(prompt,default_yes=False,verbose=False,no_nl=False):
 	from mmgen.term import get_char
 
 	q = ('(y/N)','(Y/n)')[bool(default_yes)]
-	p = u'{} {}: '.format(prompt,q)
+	p = '{} {}: '.format(prompt,q)
 	nl = ('\n','\r{}\r'.format(' '*len(p)))[no_nl]
 
 	if opt.accept_defaults:
@@ -836,7 +836,7 @@ def rpc_init_parity():
 
 		if not addr:
 			m = "'{}': unrecognized token symbol"
-			raise UnrecognizedTokenSymbol,m.format(token_arg)
+			raise UnrecognizedTokenSymbol(m.format(token_arg))
 
 		sym = Token(addr).symbol().upper()
 		vmsg('ERC20 token resolved: {} ({})'.format(addr,sym))
@@ -889,7 +889,7 @@ def rpc_init_bitcoind():
 				auth_cookie=get_coin_daemon_auth_cookie())
 
 	if g.bob or g.alice:
-		import regtest as rt
+		from . import regtest as rt
 		rt.user(('alice','bob')[g.bob],quiet=True)
 	conn.daemon_version = int(conn.getnetworkinfo()['version'])
 	conn.coin_amt_type = (float,str)[conn.daemon_version>=120000]
@@ -935,7 +935,7 @@ def altcoin_subclass(cls,mod_id,cls_name):
 	tname = 'Token' if g.token else ''
 	e1 = 'from mmgen.altcoins.{}.{} import {}{}{}'.format(mod_dir,mod_id,pname,tname,cls_name)
 	e2 = 'cls = {}{}{}'.format(pname,tname,cls_name)
-	try: exec e1; exec e2; return cls
+	try: exec(e1); exec(e2); return cls
 	except ImportError: return cls
 
 # decorator for TrackingWallet

+ 1 - 1
scripts/create-token.py

@@ -183,4 +183,4 @@ def compile_code(code):
 src = create_src(code_in)
 out = compile_code(src)
 if opt.stdout:
-	print(json.dumps(out))
+	print((json.dumps(out)))

+ 1 - 1
scripts/traceback_run.py

@@ -21,7 +21,7 @@ def process_exception():
 
 try:
 	sys.argv.pop(0)
-	exec tb_source
+	exec(tb_source)
 except SystemExit as e:
 	if e.code != 0:
 		process_exception()

+ 3 - 3
setup.py

@@ -67,14 +67,14 @@ class my_build_ext(build_ext):
 		ext_dest = self.get_ext_filename(ext.name)
 		try: os.unlink(ext_dest)
 		except: pass
-		os.chmod(ext_src,0755)
-		print 'copying %s to %s' % (ext_src,ext_dest)
+		os.chmod(ext_src,0o755)
+		print('copying %s to %s' % (ext_src,ext_dest))
 		copy2(ext_src,ext_dest)
 
 class my_install_data(install_data):
 	def run(self):
 		for f in 'mmgen.cfg','mnemonic.py','mn_wordlist.c':
-			os.chmod(os.path.join('data_files',f),0644)
+			os.chmod(os.path.join('data_files',f),0o644)
 		install_data.run(self)
 
 module1 = Extension(

+ 5 - 5
test/gentest.py

@@ -125,7 +125,7 @@ def init_external_prog():
 		try:
 			import ethereum.utils as eth
 		except:
-			raise ImportError,"Unable to import 'pyethereum' module. Is pyethereum installed?"
+			raise ImportError("Unable to import 'pyethereum' module. Is pyethereum installed?")
 		ext_sec2addr = pyethereum_sec2addr
 		ext_lib = 'pyethereum'
 	elif test_support('pycoin'):
@@ -135,7 +135,7 @@ def init_external_prog():
 			from pycoin.ecdsa.secp256k1 import secp256k1_generator
 			from pycoin.networks.registry import network_for_netcode
 		except:
-			raise ImportError,"Unable to import pycoin modules. Is pycoin installed and up-to-date?"
+			raise ImportError("Unable to import pycoin modules. Is pycoin installed and up-to-date?")
 		ext_sec2addr = pycoin_sec2addr
 		ext_lib = 'pycoin'
 	elif test_support('keyconv'):
@@ -144,7 +144,7 @@ def init_external_prog():
 		ext_lib = 'keyconv'
 	else:
 		m = '{}: coin supported by MMGen but unsupported by gentest.py for {}'
-		raise ValueError,m.format(g.coin,('mainnet','testnet')[g.testnet])
+		raise ValueError(m.format(g.coin,('mainnet','testnet')[g.testnet]))
 	b_desc = ext_lib
 	b = 'ext'
 
@@ -202,8 +202,8 @@ def speed_test():
 	qmsg(green(m.format(kg_a.desc,g.coin)))
 	from struct import pack,unpack
 	seed = os.urandom(28)
-	print 'Incrementing key with each round'
-	print 'Starting key:', hexlify(seed+pack('I',0))
+	print('Incrementing key with each round')
+	print('Starting key:', hexlify(seed+pack('I',0)))
 	import time
 	start = last_t = time.time()
 

+ 8 - 8
test/mmgen_pexpect.py

@@ -46,7 +46,7 @@ def my_send(p,t,delay=send_delay,s=False):
 	if opt.verbose:
 		ls = (' ','')[bool(opt.debug or not s)]
 		es = ('  ','')[bool(s)]
-		msg(u'{}SEND {}{}'.format(ls,es,yellow(u"'{}'".format(t.decode('utf8').replace('\n',r'\n')))))
+		msg('{}SEND {}{}'.format(ls,es,yellow("'{}'".format(t.decode('utf8').replace('\n',r'\n')))))
 	return ret
 
 def my_expect(p,s,t='',delay=send_delay,regex=False,nonl=False,silent=False):
@@ -86,7 +86,7 @@ def debug_pexpect_msg(p):
 		errmsg('\n{}{}{}'.format(red('BEFORE ['),p.before,red(']')))
 		errmsg('{}{}{}'.format(red('MATCH ['),p.after,red(']')))
 
-data_dir = os.path.join('test','data_dir'+('',u'-α')[bool(os.getenv('MMGEN_DEBUG_UTF8'))])
+data_dir = os.path.join('test','data_dir'+('','-α')[bool(os.getenv('MMGEN_DEBUG_UTF8'))])
 
 class MMGenPexpect(object):
 
@@ -107,15 +107,15 @@ class MMGenPexpect(object):
 		else:                   cmd,args = mmgen_cmd,cmd_args
 
 		for i in args:
-			if type(i) not in (str,unicode):
+			if type(i) not in (str,str):
 				m1 = 'Error: missing input files in cmd line?:'
 				m2 = '\nName: {}\nCmd: {}\nCmd args: {}'
 				die(2,(m1+m2).format(name,cmd,args))
 
 		if opt.popen_spawn:
-			args = [u'{q}{}{q}'.format(a,q="'" if ' ' in a else '') for a in args]
+			args = ['{q}{}{q}'.format(a,q="'" if ' ' in a else '') for a in args]
 
-		cmd_str = u'{} {}'.format(cmd,u' '.join(args)).replace('\\','/')
+		cmd_str = '{} {}'.format(cmd,' '.join(args)).replace('\\','/')
 		if opt.coverage:
 			fs = 'python -m trace --count --coverdir={} --file={} {c}'
 			cmd_str = fs.format(*init_coverage(),c=cmd_str)
@@ -129,7 +129,7 @@ class MMGenPexpect(object):
 				sys.stderr.write(green('Testing: {}\n'.format(desc)))
 				if not msg_only:
 					s = repr(cmd_str) if g.platform == 'win' else cmd_str
-					sys.stderr.write(clr1(u'Executing {}{}'.format(clr2(s),eol)))
+					sys.stderr.write(clr1('Executing {}{}'.format(clr2(s),eol)))
 			else:
 				m = 'Testing {}: '.format(desc)
 				msg_r(m)
@@ -199,7 +199,7 @@ class MMGenPexpect(object):
 		p = "'w' for conditions and warranty info, or 'c' to continue: "
 		my_expect(self.p,p,'c')
 
-	def label(self,label=u'Test Label (UTF-8) α'):
+	def label(self,label='Test Label (UTF-8) α'):
 		p = 'Enter a wallet label, or hit ENTER for no label: '
 		my_expect(self.p,p,label+'\n')
 
@@ -252,7 +252,7 @@ class MMGenPexpect(object):
 		self.expect(self.NL,nonl=True)
 		outfile = self.p.before.strip().strip("'").decode('utf8')
 		if opt.debug_pexpect: rmsg('Outfile [{}]'.format(outfile))
-		vmsg(u'{} file: {}'.format(desc,cyan(outfile.replace("'",''))))
+		vmsg('{} file: {}'.format(desc,cyan(outfile.replace("'",''))))
 		return outfile
 
 	def no_overwrite(self):

+ 24 - 24
test/objtest.py

@@ -62,7 +62,7 @@ def run_test(test,arg,input_data):
 			del arg['arg']
 		else:
 			args = []
-			ret_chk = arg.values()[0] # assume only one key present
+			ret_chk = list(arg.values())[0] # assume only one key present
 		if 'ret' in arg:
 			ret_chk = arg['ret']
 			del arg['ret']
@@ -77,18 +77,18 @@ def run_test(test,arg,input_data):
 		ret = cls(*args,**kwargs)
 		bad_ret = list() if issubclass(cls,list) else None
 		if (opt.silent and input_data=='bad' and ret!=bad_ret) or (not opt.silent and input_data=='bad'):
-			raise UserWarning,"Non-'None' return value {} with bad input data".format(repr(ret))
+			raise UserWarning("Non-'None' return value {} with bad input data".format(repr(ret)))
 		if opt.silent and input_data=='good' and ret==bad_ret:
-			raise UserWarning,"'None' returned with good input data"
+			raise UserWarning("'None' returned with good input data")
 		if input_data=='good' and ret != ret_chk and repr(ret) != repr(ret_chk):
-			raise UserWarning,"Return value ({!r}) doesn't match expected value ({!r})".format(ret,ret_chk)
+			raise UserWarning("Return value ({!r}) doesn't match expected value ({!r})".format(ret,ret_chk))
 		if not opt.super_silent:
-			msg(u'==> {}'.format(ret))
+			msg('==> {}'.format(ret))
 		if opt.verbose and issubclass(cls,MMGenObject):
 			ret.pmsg() if hasattr(ret,'pmsg') else pmsg(ret)
 	except SystemExit as e:
 		if input_data == 'good':
-			raise ValueError,'Error on good input data'
+			raise ValueError('Error on good input data')
 		if opt.verbose:
 			msg('exitval: {}'.format(e.code))
 	except UserWarning as e:
@@ -97,9 +97,9 @@ def run_test(test,arg,input_data):
 
 r32,r24,r16,r17,r18 = os.urandom(32),os.urandom(24),os.urandom(16),os.urandom(17),os.urandom(18)
 tw_pfx = g.proto.base_coin.lower()+':'
-utf8_text           = u'[α-$ample UTF-8 text-ω]' * 10   # 230 chars, unicode types L,N,P,S,Z
-utf8_text_combining = u'[α-$ámple UTF-8 téxt-ω]' * 10   # L,N,P,S,Z,M
-utf8_text_control   = u'[α-$ample\nUTF-8\ntext-ω]' * 10 # L,N,P,S,Z,C
+utf8_text           = '[α-$ample UTF-8 text-ω]' * 10   # 230 chars, unicode types L,N,P,S,Z
+utf8_text_combining = '[α-$ámple UTF-8 téxt-ω]' * 10   # L,N,P,S,Z,M
+utf8_text_control   = '[α-$ample\nUTF-8\ntext-ω]' * 10 # L,N,P,S,Z,C
 
 from collections import OrderedDict
 tests = OrderedDict([
@@ -115,15 +115,15 @@ tests = OrderedDict([
 			({'idx_list':AddrIdxList('1-5')},[1,2,3,4,5])
 		)}),
 	('BTCAmt', {
-		'bad':  ('-3.2','0.123456789',123L,'123L','22000000',20999999.12345678),
+		'bad':  ('-3.2','0.123456789',123,'123L','22000000',20999999.12345678),
 		'good': (('20999999.12345678',Decimal('20999999.12345678')),)
 		}),
 	('LTCAmt', {
-		'bad':  ('-3.2','0.123456789',123L,'123L','88000000',80999999.12345678),
+		'bad':  ('-3.2','0.123456789',123,'123L','88000000',80999999.12345678),
 		'good': (('80999999.12345678',Decimal('80999999.12345678')),)
 		}),
 	('CoinAddr', {
-		'bad':  (1,'x',u'я'),
+		'bad':  (1,'x','я'),
 		'good': {
 			'btc': (('1MjjELEy6EJwk8fSNfpS8b5teFRo4X5fZr','32GiSWo9zJQgkCmjAaLRrbPwXhKry2jHhj'),
 					('n2FgXPKwuFkCXF946EnoxWJDWF2VwQ6q8J','2MspvWFjBbkv2wzQGqhxJUYPCk3Y2jMaxLN')),
@@ -133,13 +133,13 @@ tests = OrderedDict([
 	}),
 	('SeedID', {
 		'bad':  (
-			{'sid':u'я'},
+			{'sid':'я'},
 			{'sid':'F00F00'},
 			{'sid':'xF00F00x'},
 			{'sid':1},
 			{'sid':'F00BAA123'},
 			{'sid':'f00baa12'},
-			u'я',r32,'abc'),
+			'я',r32,'abc'),
 		'good': (({'sid':'F00BAA12'},'F00BAA12'),(Seed(r16),Seed(r16).sid))
 	}),
 	('MMGenID', {
@@ -147,32 +147,32 @@ tests = OrderedDict([
 		'good': (('F00BAA12:99','F00BAA12:L:99'),'F00BAA12:L:99','F00BAA12:S:99')
 	}),
 	('TwMMGenID', {
-		'bad':  ('x',u'я',u'я:я',1,'f00f00f','a:b','x:L:3','F00BAA12:0','F00BAA12:Z:99',tw_pfx,tw_pfx+u'я'),
+		'bad':  ('x','я','я:я',1,'f00f00f','a:b','x:L:3','F00BAA12:0','F00BAA12:Z:99',tw_pfx,tw_pfx+'я'),
 		'good': (('F00BAA12:99','F00BAA12:L:99'),'F00BAA12:L:99','F00BAA12:S:9999999',tw_pfx+'x')
 	}),
 	('TwLabel', {
-		'bad':  ('x x',u'x я',u'я:я',1,'f00f00f','a:b','x:L:3','F00BAA12:0 x',
-				'F00BAA12:Z:99',tw_pfx+' x',tw_pfx+u'я x'),
+		'bad':  ('x x','x я','я:я',1,'f00f00f','a:b','x:L:3','F00BAA12:0 x',
+				'F00BAA12:Z:99',tw_pfx+' x',tw_pfx+'я x'),
 		'good': (
 			('F00BAA12:99 a comment','F00BAA12:L:99 a comment'),
-			u'F00BAA12:L:99 comment (UTF-8) α',
+			'F00BAA12:L:99 comment (UTF-8) α',
 			'F00BAA12:S:9999999 comment',
 			tw_pfx+'x comment')
 	}),
 	('HexStr', {
-		'bad':  (1,[],'\0','\1',u'я','g','gg','FF','f00'),
+		'bad':  (1,[],'\0','\1','я','g','gg','FF','f00'),
 		'good': ('deadbeef','f00baa12')
 	}),
 	('MMGenTxID', {
-		'bad':  (1,[],'\0','\1',u'я','g','gg','FF','f00','F00F0012'),
+		'bad':  (1,[],'\0','\1','я','g','gg','FF','f00','F00F0012'),
 		'good': ('DEADBE','F00BAA')
 	}),
 	('CoinTxID',{
-		'bad':  (1,[],'\0','\1',u'я','g','gg','FF','f00','F00F0012',hexlify(r16),hexlify(r32)+'ee'),
+		'bad':  (1,[],'\0','\1','я','g','gg','FF','f00','F00F0012',hexlify(r16),hexlify(r32)+'ee'),
 		'good': (hexlify(r32),)
 	}),
 	('WifKey', {
-		'bad':  (1,[],'\0','\1',u'я','g','gg','FF','f00',hexlify(r16),'2MspvWFjBbkv2wzQGqhxJUYPCk3Y2jMaxLN'),
+		'bad':  (1,[],'\0','\1','я','g','gg','FF','f00',hexlify(r16),'2MspvWFjBbkv2wzQGqhxJUYPCk3Y2jMaxLN'),
 		'good': {
 			'btc': (('5KXEpVzjWreTcQoG5hX357s1969MUKNLuSfcszF6yu84kpsNZKb',
 					'KwWr9rDh8KK5TtDa3HLChEvQXNYcUXpwhRFUPc5uSNnMtqNKLFhk'),
@@ -235,7 +235,7 @@ tests = OrderedDict([
 	}),
 	('MMGenPWIDString', { # forbidden = list(u' :/\\')
 		'bad': ('foo/','foo:','foo:\\'),
-		'good':  (u'qwerty@яяя',)
+		'good':  ('qwerty@яяя',)
 	}),
 	('MMGenAddrType', {
 		'bad': ('U','z','xx',1,'dogecoin'),
@@ -250,7 +250,7 @@ tests = OrderedDict([
 		{'s':'B','ret':'B'},
 	)}),
 	('MMGenPasswordType', {
-		'bad': ('U','z',u'я',1,'passw0rd'),
+		'bad': ('U','z','я',1,'passw0rd'),
 		'good':  (
 		{'s':'password','ret':'P'},
 		{'s':'P','ret':'P'},

+ 150 - 150
test/test.py

@@ -37,20 +37,20 @@ set_debug_all()
 g.quiet = False # if 'quiet' was set in config file, disable here
 os.environ['MMGEN_QUIET'] = '0' # and for the spawned scripts
 
-log_file = u'test.py_log'
+log_file = 'test.py_log'
 
 hincog_fn      = 'rand_data'
 hincog_bytes   = 1024*1024
 hincog_offset  = 98765
 hincog_seedlen = 256
 
-incog_id_fn  = u'incog_id'
-non_mmgen_fn = u'coinkey'
-pwfile = u'passwd_file'
+incog_id_fn  = 'incog_id'
+non_mmgen_fn = 'coinkey'
+pwfile = 'passwd_file'
 
-ref_dir = os.path.join(u'test',u'ref')
+ref_dir = os.path.join('test','ref')
 
-rt_pw = u'abc-α'
+rt_pw = 'abc-α'
 ref_wallet_brainpass = 'abc'
 ref_wallet_hash_preset = '1'
 ref_wallet_incog_offset = 123
@@ -58,21 +58,21 @@ ref_wallet_incog_offset = 123
 from mmgen.obj import MMGenTXLabel,PrivKey,ETHAmt
 from mmgen.addr import AddrGenerator,KeyGenerator,AddrList,AddrData,AddrIdxList
 
-ref_tx_label_jp = u'必要なのは、信用ではなく暗号化された証明に基づく電子取引システムであり、これにより希望する二者が信用できる第三者機関を介さずに直接取引できるよう' # 72 chars ('W'ide)
-ref_tx_label_zh = u'所以,我們非常需要這樣一種電子支付系統,它基於密碼學原理而不基於信用,使得任何達成一致的雙方,能夠直接進行支付,從而不需要協力廠商仲介的參與。。' # 72 chars ('F'ull + 'W'ide)
-ref_tx_label_lat_cyr_gr = u''.join(map(unichr,
-									range(65,91) +
-									range(1040,1072) + # cyrillic
-									range(913,939) +   # greek
-									range(97,123)))[:MMGenTXLabel.max_len] # 72 chars
+ref_tx_label_jp = '必要なのは、信用ではなく暗号化された証明に基づく電子取引システムであり、これにより希望する二者が信用できる第三者機関を介さずに直接取引できるよう' # 72 chars ('W'ide)
+ref_tx_label_zh = '所以,我們非常需要這樣一種電子支付系統,它基於密碼學原理而不基於信用,使得任何達成一致的雙方,能夠直接進行支付,從而不需要協力廠商仲介的參與。。' # 72 chars ('F'ull + 'W'ide)
+ref_tx_label_lat_cyr_gr = ''.join(map(chr,
+									list(range(65,91)) +
+									list(range(1040,1072)) + # cyrillic
+									list(range(913,939)) +   # greek
+									list(range(97,123))))[:MMGenTXLabel.max_len] # 72 chars
 ref_bw_hash_preset = '1'
-ref_bw_file        = u'wallet.mmbrain'
-ref_bw_file_spc    = u'wallet-spaced.mmbrain'
+ref_bw_file        = 'wallet.mmbrain'
+ref_bw_file_spc    = 'wallet-spaced.mmbrain'
 
 ref_kafile_pass        = 'kafile password'
 ref_kafile_hash_preset = '1'
 
-ref_enc_fn = u'sample-text.mmenc'
+ref_enc_fn = 'sample-text.mmenc'
 tool_enc_passwd = "Scrypt it, don't hash it!"
 sample_text = \
 	'The Times 03/Jan/2009 Chancellor on brink of second bailout for banks\n'
@@ -81,9 +81,9 @@ sample_text = \
 # under '/dev/shm' and put datadir and temp files here.
 shortopts = ''.join([e[1:] for e in sys.argv if len(e) > 1 and e[0] == '-' and e[1] != '-'])
 shortopts = ['-'+e for e in list(shortopts)]
-data_dir_basename = u'data_dir' + ('',u'-α')[bool(os.getenv('MMGEN_DEBUG_UTF8'))]
-data_dir = os.path.join(u'test',data_dir_basename)
-trash_dir = os.path.join(u'test',u'trash')
+data_dir_basename = 'data_dir' + ('','-α')[bool(os.getenv('MMGEN_DEBUG_UTF8'))]
+data_dir = os.path.join('test',data_dir_basename)
+trash_dir = os.path.join('test','trash')
 
 if not any(e in ('--skip-deps','--resume','-S','-r') for e in sys.argv+shortopts):
 	if g.platform == 'win':
@@ -98,7 +98,7 @@ if not any(e in ('--skip-deps','--resume','-S','-r') for e in sys.argv+shortopts
 					else:
 						time.sleep(2)
 						shutil.rmtree(tdir)
-			os.mkdir(tdir,0755)
+			os.mkdir(tdir,0o755)
 	else:
 		d,pfx = '/dev/shm','mmgen-test-'
 		try:
@@ -107,12 +107,12 @@ if not any(e in ('--skip-deps','--resume','-S','-r') for e in sys.argv+shortopts
 			die(2,'Unable to delete directory tree {}/{}* ({})'.format(d,pfx,e.message))
 		try:
 			import tempfile
-			shm_dir = unicode(tempfile.mkdtemp('',pfx,d))
+			shm_dir = str(tempfile.mkdtemp('',pfx,d))
 		except Exception as e:
 			die(2,'Unable to create temporary directory in {} ({})'.format(d,e.message))
 		for tdir in (data_dir,trash_dir):
 			dd = os.path.join(shm_dir,os.path.basename(tdir))
-			os.mkdir(dd,0755)
+			os.mkdir(dd,0o755)
 			try: os.unlink(tdir)
 			except: pass
 			os.symlink(dd,tdir)
@@ -220,7 +220,7 @@ def restore_debug():
 
 cfgs = {
 	'15': {
-		'tmpdir':        os.path.join(u'test',u'tmp15'),
+		'tmpdir':        os.path.join('test','tmp15'),
 		'wpasswd':       'Dorian-α',
 		'kapasswd':      'Grok the blockchain',
 		'addr_idx_list': '12,99,5-10,5,12', # 8 addresses
@@ -235,7 +235,7 @@ cfgs = {
 		'segwit': get_segwit_bool()
 	},
 	'16': {
-		'tmpdir':        os.path.join(u'test',u'tmp16'),
+		'tmpdir':        os.path.join('test','tmp16'),
 		'wpasswd':       'My changed password',
 		'hash_preset':   '2',
 		'dep_generators': {
@@ -243,26 +243,26 @@ cfgs = {
 		},
 		'segwit': get_segwit_bool()
 	},
-	'17': { 'tmpdir': os.path.join(u'test',u'tmp17') },
-	'18': { 'tmpdir': os.path.join(u'test',u'tmp18') },
+	'17': { 'tmpdir': os.path.join('test','tmp17') },
+	'18': { 'tmpdir': os.path.join('test','tmp18') },
 #	'19': { 'tmpdir': os.path.join(u'test',u'tmp19'), 'wpasswd':'abc' }, B2X
 
-	'31': { 'tmpdir': os.path.join(u'test',u'tmp31'), # L
+	'31': { 'tmpdir': os.path.join('test','tmp31'), # L
 			'addr_idx_list':'1-2', 'segwit': False,
 			'dep_generators': {'addrs':'ref_tx_addrgen1'} },
-	'32': { 'tmpdir': os.path.join(u'test',u'tmp32'), # C
+	'32': { 'tmpdir': os.path.join('test','tmp32'), # C
 			'addr_idx_list':'1-2', 'segwit': False,
 			'dep_generators': {'addrs':'ref_tx_addrgen2'} },
-	'33': { 'tmpdir': os.path.join(u'test',u'tmp33'), # S
+	'33': { 'tmpdir': os.path.join('test','tmp33'), # S
 			'addr_idx_list':'1-2', 'segwit': True,
 			'dep_generators': {'addrs':'ref_tx_addrgen3'} },
-	'34': { 'tmpdir': os.path.join(u'test',u'tmp34'), # B
+	'34': { 'tmpdir': os.path.join('test','tmp34'), # B
 			'addr_idx_list':'1-2', 'segwit': True,
 			'dep_generators': {'addrs':'ref_tx_addrgen4'} },
 
 	'1': {
-		'tmpdir':        os.path.join(u'test',u'tmp1'),
-		'wpasswd':       u'Dorian-α',
+		'tmpdir':        os.path.join('test','tmp1'),
+		'wpasswd':       'Dorian-α',
 		'kapasswd':      'Grok the blockchain',
 		'addr_idx_list': '12,99,5-10,5,12', # 8 addresses
 		'dep_generators':  {
@@ -277,14 +277,14 @@ cfgs = {
 			'mmhex':       'export_hex',
 			'mmincog':     'export_incog',
 			'mmincox':     'export_incog_hex',
-			hincog_fn:     u'export_incog_hidden',
-			incog_id_fn:   u'export_incog_hidden',
+			hincog_fn:     'export_incog_hidden',
+			incog_id_fn:   'export_incog_hidden',
 			'akeys.mmenc': 'keyaddrgen'
 		},
 		'segwit': get_segwit_bool()
 	},
 	'2': {
-		'tmpdir':        os.path.join(u'test',u'tmp2'),
+		'tmpdir':        os.path.join('test','tmp2'),
 		'wpasswd':       'Hodling away',
 		'addr_idx_list': '37,45,3-6,22-23',  # 8 addresses
 		'seed_len':      128,
@@ -298,7 +298,7 @@ cfgs = {
 		'segwit': get_segwit_bool()
 	},
 	'20': {
-		'tmpdir':        os.path.join(u'test',u'tmp20'),
+		'tmpdir':        os.path.join('test','tmp20'),
 		'wpasswd':       'Vsize it',
 		'addr_idx_list': '1-8',  # 8 addresses
 		'seed_len':      256,
@@ -311,7 +311,7 @@ cfgs = {
 		'segwit': get_segwit_bool()
 	},
 	'21': {
-		'tmpdir':        os.path.join(u'test',u'tmp21'),
+		'tmpdir':        os.path.join('test','tmp21'),
 		'wpasswd':       'Vsize it',
 		'addr_idx_list': '1-8',  # 8 addresses
 		'seed_len':      256,
@@ -324,12 +324,12 @@ cfgs = {
 		'segwit': get_segwit_bool()
 	},
 	'22': {
-		'tmpdir': os.path.join(u'test',u'tmp22'),
+		'tmpdir': os.path.join('test','tmp22'),
 		'parity_pidfile': 'parity.pid',
 		'parity_keyfile': 'parity.devkey',
 		},
 	'3': {
-		'tmpdir':        os.path.join(u'test',u'tmp3'),
+		'tmpdir':        os.path.join('test','tmp3'),
 		'wpasswd':       'Major miner',
 		'addr_idx_list': '73,54,1022-1023,2-5', # 8 addresses
 		'dep_generators': {
@@ -341,7 +341,7 @@ cfgs = {
 		'segwit': get_segwit_bool()
 	},
 	'4': {
-		'tmpdir':        os.path.join(u'test',u'tmp4'),
+		'tmpdir':        os.path.join('test','tmp4'),
 		'wpasswd':       'Hashrate good',
 		'addr_idx_list': '63,1004,542-544,7-9', # 8 addresses
 		'seed_len':      192,
@@ -353,13 +353,13 @@ cfgs = {
 			'sigtx':       'txsign4',
 			'txdo':        'txdo4',
 		},
-		'bw_filename': u'brainwallet.mmbrain',
+		'bw_filename': 'brainwallet.mmbrain',
 		'bw_params':   '192,1',
 		'segwit': get_segwit_bool()
 	},
 	'14': {
 		'kapasswd':      'Maxwell',
-		'tmpdir':        os.path.join(u'test',u'tmp14'),
+		'tmpdir':        os.path.join('test','tmp14'),
 		'wpasswd':       'The Halving',
 		'addr_idx_list': '61,998,502-504,7-9', # 8 addresses
 		'seed_len':      256,
@@ -371,7 +371,7 @@ cfgs = {
 		'segwit': get_segwit_bool()
 	},
 	'5': {
-		'tmpdir':        os.path.join(u'test',u'tmp5'),
+		'tmpdir':        os.path.join('test','tmp5'),
 		'wpasswd':       'My changed password-α',
 		'hash_preset':   '2',
 		'dep_generators': {
@@ -421,14 +421,14 @@ cfgs = {
 		'passfile32_chk':  '37B6 C218 2ABC 7508',
 		'passfilehex_chk': '523A F547 0E69 8323',
 		'wpasswd':         'reference password',
-		'ref_wallet':      u'FE3C6545-D782B529[128,1].mmdat',
-		'ic_wallet':       u'FE3C6545-E29303EA-5E229E30[128,1].mmincog',
-		'ic_wallet_hex':   u'FE3C6545-BC4BE3F2-32586837[128,1].mmincox',
+		'ref_wallet':      'FE3C6545-D782B529[128,1].mmdat',
+		'ic_wallet':       'FE3C6545-E29303EA-5E229E30[128,1].mmincog',
+		'ic_wallet_hex':   'FE3C6545-BC4BE3F2-32586837[128,1].mmincox',
 
 		'hic_wallet':       'FE3C6545-161E495F-BEB7548E[128,1].incog-offset123',
 		'hic_wallet_old':   'FE3C6545-161E495F-9860A85B[128,1].incog-old.offset123',
 
-		'tmpdir':        os.path.join(u'test',u'tmp6'),
+		'tmpdir':        os.path.join('test','tmp6'),
 		'kapasswd':      '',
 		'addr_idx_list': '1010,500-501,31-33,1,33,500,1011', # 8 addresses
 		'pass_idx_list': '1,4,9-11,1100',
@@ -481,14 +481,14 @@ cfgs = {
 		'passfile32_chk':  '2A28 C5C7 36EC 217A',
 		'passfilehex_chk': 'B11C AC6A 1464 608D',
 		'wpasswd':         'reference password',
-		'ref_wallet':      u'1378FC64-6F0F9BB4[192,1].mmdat',
-		'ic_wallet':       u'1378FC64-2907DE97-F980D21F[192,1].mmincog',
-		'ic_wallet_hex':   u'1378FC64-4DCB5174-872806A7[192,1].mmincox',
+		'ref_wallet':      '1378FC64-6F0F9BB4[192,1].mmdat',
+		'ic_wallet':       '1378FC64-2907DE97-F980D21F[192,1].mmincog',
+		'ic_wallet_hex':   '1378FC64-4DCB5174-872806A7[192,1].mmincox',
 
-		'hic_wallet':      u'1378FC64-B55E9958-77256FC1[192,1].incog.offset123',
-		'hic_wallet_old':  u'1378FC64-B55E9958-D85FF20C[192,1].incog-old.offset123',
+		'hic_wallet':      '1378FC64-B55E9958-77256FC1[192,1].incog.offset123',
+		'hic_wallet_old':  '1378FC64-B55E9958-D85FF20C[192,1].incog-old.offset123',
 
-		'tmpdir':        os.path.join(u'test',u'tmp7'),
+		'tmpdir':        os.path.join('test','tmp7'),
 		'kapasswd':      '',
 		'addr_idx_list': '1010,500-501,31-33,1,33,500,1011', # 8 addresses
 		'pass_idx_list': '1,4,9-11,1100',
@@ -541,12 +541,12 @@ cfgs = {
 		'passfile32_chk':  'F6C1 CDFB 97D9 FCAE',
 		'passfilehex_chk': 'BD4F A0AC 8628 4BE4',
 		'wpasswd':         'reference password',
-		'ref_wallet':      u'98831F3A-{}[256,1].mmdat'.format(('27F2BF93','E2687906')[g.testnet]),
-		'ref_addrfile':    u'98831F3A{}[1,31-33,500-501,1010-1011]{}.addrs',
-		'ref_segwitaddrfile':u'98831F3A{}-S[1,31-33,500-501,1010-1011]{}.addrs',
-		'ref_bech32addrfile':u'98831F3A{}-B[1,31-33,500-501,1010-1011]{}.addrs',
-		'ref_keyaddrfile': u'98831F3A{}[1,31-33,500-501,1010-1011]{}.akeys.mmenc',
-		'ref_passwdfile':  u'98831F3A-фубар@crypto.org-b58-20[1,4,9-11,1100].pws',
+		'ref_wallet':      '98831F3A-{}[256,1].mmdat'.format(('27F2BF93','E2687906')[g.testnet]),
+		'ref_addrfile':    '98831F3A{}[1,31-33,500-501,1010-1011]{}.addrs',
+		'ref_segwitaddrfile':'98831F3A{}-S[1,31-33,500-501,1010-1011]{}.addrs',
+		'ref_bech32addrfile':'98831F3A{}-B[1,31-33,500-501,1010-1011]{}.addrs',
+		'ref_keyaddrfile': '98831F3A{}[1,31-33,500-501,1010-1011]{}.akeys.mmenc',
+		'ref_passwdfile':  '98831F3A-фубар@crypto.org-b58-20[1,4,9-11,1100].pws',
 		'ref_addrfile_chksum': {
 			'btc': ('6FEF 6FB9 7B13 5D91','424E 4326 CFFE 5F51'),
 			'ltc': ('AD52 C3FE 8924 AAF0','4EBE 2E85 E969 1B30'),
@@ -589,13 +589,13 @@ cfgs = {
 					'6BDB25-MM1[1.23456,50000].testnet.rawtx'),
 			'etc': ('ED3848-ETC[1.2345,40000].rawtx','')
 		},
-		'ic_wallet':       u'98831F3A-5482381C-18460FB1[256,1].mmincog',
-		'ic_wallet_hex':   u'98831F3A-1630A9F2-870376A9[256,1].mmincox',
+		'ic_wallet':       '98831F3A-5482381C-18460FB1[256,1].mmincog',
+		'ic_wallet_hex':   '98831F3A-1630A9F2-870376A9[256,1].mmincox',
 
-		'hic_wallet':       u'98831F3A-F59B07A0-559CEF19[256,1].incog.offset123',
-		'hic_wallet_old':   u'98831F3A-F59B07A0-848535F3[256,1].incog-old.offset123',
+		'hic_wallet':       '98831F3A-F59B07A0-559CEF19[256,1].incog.offset123',
+		'hic_wallet_old':   '98831F3A-F59B07A0-848535F3[256,1].incog-old.offset123',
 
-		'tmpdir':        os.path.join(u'test',u'tmp8'),
+		'tmpdir':        os.path.join('test','tmp8'),
 		'kapasswd':      '',
 		'addr_idx_list': '1010,500-501,31-33,1,33,500,1011', # 8 addresses
 		'pass_idx_list': '1,4,9-11,1100',
@@ -609,7 +609,7 @@ cfgs = {
 		'segwit': get_segwit_bool()
 	},
 	'9': {
-		'tmpdir':        os.path.join(u'test',u'tmp9'),
+		'tmpdir':        os.path.join('test','tmp9'),
 		'tool_enc_infn':      'tool_encrypt.in',
 #		'tool_enc_ref_infn':  'tool_encrypt_ref.in',
 		'wpasswd':         'reference password',
@@ -677,16 +677,16 @@ eth_token_bals = {
 
 def eth_args():
 	assert g.coin in ('ETH','ETC'),'for ethdev tests, --coin must be set to either ETH or ETC'
-	return [u'--outdir={}'.format(cfgs['22']['tmpdir']),'--rpc-port=8549','--quiet']
+	return ['--outdir={}'.format(cfgs['22']['tmpdir']),'--rpc-port=8549','--quiet']
 
 
 from copy import deepcopy
 for a,b in (('6','11'),('7','12'),('8','13')):
 	cfgs[b] = deepcopy(cfgs[a])
-	cfgs[b]['tmpdir'] = os.path.join(u'test',u'tmp'+b)
+	cfgs[b]['tmpdir'] = os.path.join('test','tmp'+b)
 
 if g.debug_utf8:
-	for k in cfgs: cfgs[k]['tmpdir'] += u'-α'
+	for k in cfgs: cfgs[k]['tmpdir'] += '-α'
 
 from collections import OrderedDict
 
@@ -1266,7 +1266,7 @@ if opt.list_cmds:
 	fs = '  {:<{w}} - {}'
 
 	Msg(green('AVAILABLE COMMANDS:'))
-	w = max(map(len,cmd_data))
+	w = max(list(map(len,cmd_data)))
 	for cmd in cmd_data:
 		if cmd[:5] == 'info_':
 			Msg(green('  {}:'.format(capfirst(cmd_data[cmd][0]))))
@@ -1274,7 +1274,7 @@ if opt.list_cmds:
 		Msg('  '+fs.format(cmd,cmd_data[cmd][1],w=w))
 
 	for cl,lbl in ((meta_cmds,'METACOMMANDS'),(cmd_list,'COMMAND GROUPS')):
-		w = max(map(len,cl))
+		w = max(list(map(len,cl)))
 		Msg('\n'+green('AVAILABLE {}:'.format(lbl)))
 		for cmd in cl:
 			ft = format_par(' '.join(cl[cmd]),width=tw,indent=4,as_list=True)
@@ -1282,7 +1282,7 @@ if opt.list_cmds:
 			Msg('  {}{}{}'.format(yellow(cmd+':'),sep,'\n'.join(ft).lstrip()))
 
 	Msg('\n'+green('AVAILABLE UTILITIES:'))
-	w = max(map(len,utils))
+	w = max(list(map(len,utils)))
 	for cmd in sorted(utils):
 		Msg(fs.format(cmd,utils[cmd],w=w))
 
@@ -1301,7 +1301,7 @@ def get_file_with_ext(ext,mydir,delete=True,no_dot=False,return_list=False):
 	if len(flist) > 1:
 		if delete:
 			if not opt.quiet:
-				msg(u"Multiple *.{} files in '{}' - deleting".format(ext,mydir))
+				msg("Multiple *.{} files in '{}' - deleting".format(ext,mydir))
 			for f in flist:
 				msg(f)
 				os.unlink(f)
@@ -1312,7 +1312,7 @@ def get_file_with_ext(ext,mydir,delete=True,no_dot=False,return_list=False):
 def find_generated_exts(cmd):
 	out = []
 	for k in cfgs:
-		for ext,prog in cfgs[k]['dep_generators'].items():
+		for ext,prog in list(cfgs[k]['dep_generators'].items()):
 			if prog == cmd:
 				out.append((ext,cfgs[k]['tmpdir']))
 	return out
@@ -1331,7 +1331,7 @@ def verify_checksum_or_exit(checksum,chk):
 		sys.exit(1)
 	vmsg(green('Checksums match: ') + cyan(chk))
 
-from test.mmgen_pexpect import MMGenPexpect
+from .test.mmgen_pexpect import MMGenPexpect
 class MMGenExpect(MMGenPexpect):
 
 	def __init__(self,name,mmgen_cmd,cmd_args=[],extra_desc='',no_output=False,msg_only=False,no_msg=False):
@@ -1367,9 +1367,9 @@ def create_fake_unspent_entry(coinaddr,al_id=None,idx=None,lbl=None,non_mmgen=Fa
 	amt1,amt2 = {'btc':(10,40),'bch':(10,40),'ltc':(1000,4000)}[coin_sel]
 	ret = {
 		lbl_id: '{}:{}'.format(g.proto.base_coin.lower(),coinaddr) if non_mmgen \
-			else (u'{}:{}{}'.format(al_id,idx,lbl)),
+			else ('{}:{}{}'.format(al_id,idx,lbl)),
 		'vout': int(getrandnum(4) % 8),
-		'txid': unicode(hexlify(os.urandom(32))),
+		'txid': str(hexlify(os.urandom(32))),
 		'amount': g.proto.coin_amt('{}.{}'.format(amt1 + getrandnum(4) % amt2, getrandnum(4) % 100000000)),
 		'address': coinaddr,
 		'spendable': False,
@@ -1405,16 +1405,16 @@ def get_label(do_shuffle=False):
 	from random import shuffle
 	global label_iter
 	try:
-		return unicode(next(label_iter))
+		return str(next(label_iter))
 	except:
 		if do_shuffle: shuffle(labels)
 		label_iter = iter(labels)
-		return unicode(next(label_iter))
+		return str(next(label_iter))
 
 def create_fake_unspent_data(adata,tx_data,non_mmgen_input='',non_mmgen_input_compressed=True):
 
 	out = []
-	for d in tx_data.values():
+	for d in list(tx_data.values()):
 		al = adata.addrlist(d['al_id'])
 		for n,(idx,coinaddr) in enumerate(al.addrpairs()):
 			lbl = get_label(do_shuffle=True)
@@ -1434,14 +1434,14 @@ def create_fake_unspent_data(adata,tx_data,non_mmgen_input='',non_mmgen_input_co
 	return out
 
 def write_fake_data_to_file(d):
-	unspent_data_file = os.path.join(cfg['tmpdir'],u'unspent.json')
+	unspent_data_file = os.path.join(cfg['tmpdir'],'unspent.json')
 	write_data_to_file(unspent_data_file,d,'Unspent outputs',silent=True,ignore_opt_outdir=True)
 	os.environ['MMGEN_BOGUS_WALLET_DATA'] = unspent_data_file.encode('utf8')
-	bwd_msg = u'MMGEN_BOGUS_WALLET_DATA={}'.format(unspent_data_file)
+	bwd_msg = 'MMGEN_BOGUS_WALLET_DATA={}'.format(unspent_data_file)
 	if opt.print_cmdline: msg(bwd_msg)
 	if opt.log: log_fd.write(bwd_msg + ' ')
 	if opt.verbose or opt.exact_output:
-		sys.stderr.write(u"Fake transaction wallet data written to file {!r}\n".format(unspent_data_file))
+		sys.stderr.write("Fake transaction wallet data written to file {!r}\n".format(unspent_data_file))
 
 def create_tx_data(sources,addrs_per_wallet=addrs_per_wallet):
 	tx_data,ad = {},AddrData()
@@ -1481,7 +1481,7 @@ def make_txcreate_cmdline(tx_data):
 			'{}:{},{}'.format(s['al_id'],s['addr_idxs'][0],cfgs[num]['amts'][0]),
 		]
 		# + one change address and one BTC address
-		if num is tx_data.keys()[-1]:
+		if num is list(tx_data.keys())[-1]:
 			cmd_args += ['{}:{}'.format(s['al_id'],s['addr_idxs'][1])]
 			cmd_args += ['{},{}'.format(rand_coinaddr,cfgs[num]['amts'][1])]
 
@@ -1489,7 +1489,7 @@ def make_txcreate_cmdline(tx_data):
 
 def add_comments_to_addr_file(addrfile,outfile,use_labels=False):
 	silence()
-	gmsg(u"Adding comments to address file '{}'".format(addrfile))
+	gmsg("Adding comments to address file '{}'".format(addrfile))
 	a = AddrList(addrfile)
 	for n,idx in enumerate(a.idxs(),1):
 		if use_labels:
@@ -1612,7 +1612,7 @@ def check_deps(cmds):
 
 	check_needs_rerun(ts,cmd,build=False)
 
-	w = max(map(len,rebuild_list)) + 1
+	w = max(list(map(len,rebuild_list))) + 1
 	for cmd in rebuild_list:
 		c = rebuild_list[cmd]
 		m = 'Rebuild' if (c[0] and c[1]) else 'Build' if c[0] else 'OK'
@@ -1655,7 +1655,7 @@ class MMGenTestSuite(object):
 		num = str(cmd_data[cmd][0])
 		dgl = cfgs[num]['dep_generators']
 #	mmsg(num,cmd,dgl)
-		if cmd in dgl.values():
+		if cmd in list(dgl.values()):
 			exts = [k for k in dgl if dgl[k] == cmd]
 			return (num,exts)
 		else:
@@ -1733,7 +1733,7 @@ class MMGenTestSuite(object):
 	def brainwalletgen_ref(self,name):
 		sl_arg = '-l{}'.format(cfg['seed_len'])
 		hp_arg = '-p{}'.format(ref_wallet_hash_preset)
-		label = u"test.py ref. wallet (pw '{}', seed len {}) α".format(ref_wallet_brainpass,cfg['seed_len'])
+		label = "test.py ref. wallet (pw '{}', seed len {}) α".format(ref_wallet_brainpass,cfg['seed_len'])
 		bf = 'ref.mmbrain'
 		args = ['-d',cfg['tmpdir'],hp_arg,sl_arg,'-ib','-L',label]
 		write_to_tmpfile(cfg,bf,ref_wallet_brainpass)
@@ -1752,7 +1752,7 @@ class MMGenTestSuite(object):
 		silence()
 		write_to_tmpfile(cfg,pwfile,get_data_from_file(pf))
 		end_silence()
-		add_args = {'cmdline': ['-d',cfg['tmpdir'],'-L',u'Changed label (UTF-8) α'],
+		add_args = {'cmdline': ['-d',cfg['tmpdir'],'-L','Changed label (UTF-8) α'],
 					'keep':    ['-d',trash_dir,'--keep-label'],
 					'user':    ['-d',trash_dir]
 					}[label_action]
@@ -1764,7 +1764,7 @@ class MMGenTestSuite(object):
 		t.expect('Repeat passphrase: ',cfg['wpasswd']+'\n')
 		t.usr_rand(usr_rand_chars)
 		if label_action == 'user':
-			t.expect('Enter a wallet label.*: ',u'Interactive Label (UTF-8) α\n',regex=True)
+			t.expect('Enter a wallet label.*: ','Interactive Label (UTF-8) α\n',regex=True)
 		t.expect_getend(('Label changed to ','Reusing label ')[label_action=='keep'])
 #		t.expect_getend('Key ID changed: ')
 		if not wf:
@@ -2047,7 +2047,7 @@ class MMGenTestSuite(object):
 			t.expect('Save transaction? (y/N): ','y')
 			t.written_to_file('Transaction')
 		os.unlink(txfile) # our tx file replaces the original
-		cmd = 'touch ' + os.path.join(cfg['tmpdir'],u'txbump')
+		cmd = 'touch ' + os.path.join(cfg['tmpdir'],'txbump')
 		os.system(cmd.encode('utf8'))
 		t.ok()
 
@@ -2118,7 +2118,7 @@ class MMGenTestSuite(object):
 	def export_seed(self,name,wf,desc='seed data',out_fmt='seed',pf=None):
 		f,t = self.walletconv_export(name,wf,desc=desc,out_fmt=out_fmt,pf=pf)
 		silence()
-		msg(u'{}: {}'.format(capfirst(desc),cyan(get_data_from_file(f,desc))))
+		msg('{}: {}'.format(capfirst(desc),cyan(get_data_from_file(f,desc))))
 		end_silence()
 		t.ok()
 
@@ -2142,7 +2142,7 @@ class MMGenTestSuite(object):
 	# TODO: make outdir and hidden incog compatible (ignore --outdir and warn user?)
 	def export_incog_hidden(self,name,wf):
 		rf = os.path.join(cfg['tmpdir'],hincog_fn)
-		add_args = ['-J',u'{},{}'.format(rf,hincog_offset)]
+		add_args = ['-J','{},{}'.format(rf,hincog_offset)]
 		self.export_incog(
 			name,wf,desc='hidden incognito data',out_fmt='hi',add_args=add_args)
 
@@ -2188,7 +2188,7 @@ class MMGenTestSuite(object):
 	def addrgen_incog_hidden(self,name,wf,foo):
 		rf = os.path.join(cfg['tmpdir'],hincog_fn)
 		self.addrgen_incog(name,[],'',in_fmt='hi',desc='hidden incognito data',
-			args=['-H',u'{},{}'.format(rf,hincog_offset),'-l',str(hincog_seedlen)])
+			args=['-H','{},{}'.format(rf,hincog_offset),'-l',str(hincog_seedlen)])
 
 	def keyaddrgen(self,name,wf,pf=None,check_ref=False,mmtype=None):
 		if cfg['segwit'] and not mmtype:
@@ -2224,11 +2224,11 @@ class MMGenTestSuite(object):
 
 	def ref_b32passwdgen(self,name,wf,pf):
 		ea = ['--base32','--passwd-len','17']
-		self.addrgen(name,wf,pf,check_ref=True,ftype='pass32',id_str=u'фубар@crypto.org',extra_args=ea)
+		self.addrgen(name,wf,pf,check_ref=True,ftype='pass32',id_str='фубар@crypto.org',extra_args=ea)
 
 	def ref_hexpasswdgen(self,name,wf,pf):
 		ea = ['--hex']
-		self.addrgen(name,wf,pf,check_ref=True,ftype='passhex',id_str=u'фубар@crypto.org',extra_args=ea)
+		self.addrgen(name,wf,pf,check_ref=True,ftype='passhex',id_str='фубар@crypto.org',extra_args=ea)
 
 	def txsign_keyaddr(self,name,keyaddr_file,txfile):
 		t = MMGenExpect(name,'mmgen-txsign', ['-d',cfg['tmpdir'],'-M',keyaddr_file,txfile])
@@ -2309,7 +2309,7 @@ class MMGenTestSuite(object):
 		self.txsign_ui_common(t,name)
 		self.txsend_ui_common(t,name)
 
-		cmd = 'touch ' + os.path.join(cfg['tmpdir'],u'txdo')
+		cmd = 'touch ' + os.path.join(cfg['tmpdir'],'txdo')
 		os.system(cmd.encode('utf8'))
 		t.ok()
 
@@ -2510,7 +2510,7 @@ class MMGenTestSuite(object):
 
 	def ref_hincog_conv_out(self,name,extra_uopts=[]):
 		ic_f = os.path.join(cfg['tmpdir'],hincog_fn)
-		hi_parms = u'{},{}'.format(ic_f,ref_wallet_incog_offset)
+		hi_parms = '{},{}'.format(ic_f,ref_wallet_incog_offset)
 		sl_parm = '-l' + str(cfg['seed_len'])
 		self.walletconv_out(name,
 			'hidden incognito data', 'hi',
@@ -2803,7 +2803,7 @@ class MMGenTestSuite(object):
 
 	@staticmethod
 	def regtest_user_dir(user,coin=None):
-		return os.path.join(data_dir,u'regtest',coin or g.coin.lower(),user)
+		return os.path.join(data_dir,'regtest',coin or g.coin.lower(),user)
 
 	def regtest_user_sid(self,user):
 		return os.path.basename(get_file_with_ext('mmdat',self.regtest_user_dir(user)))[:8]
@@ -2812,7 +2812,7 @@ class MMGenTestSuite(object):
 		from mmgen.addr import MMGenAddrType
 		for mmtype in g.proto.mmtypes:
 			t = MMGenExpect(name,'mmgen-addrgen',
-				['--quiet','--'+user,'--type='+mmtype,u'--outdir={}'.format(self.regtest_user_dir(user))] +
+				['--quiet','--'+user,'--type='+mmtype,'--outdir={}'.format(self.regtest_user_dir(user))] +
 				([],[wf])[bool(wf)] + [addr_range],
 				extra_desc='({})'.format(MMGenAddrType.mmtypes[mmtype]['name']))
 			t.passphrase('MMGen wallet',passwd)
@@ -2829,9 +2829,9 @@ class MMGenTestSuite(object):
 		for mmtype in g.proto.mmtypes:
 			desc = MMGenAddrType.mmtypes[mmtype]['name']
 			fn = os.path.join(self.regtest_user_dir(user),
-				u'{}{}{}[{}]{x}.testnet.addrs'.format(
+				'{}{}{}[{}]{x}.testnet.addrs'.format(
 					sid,altcoin_pfx,id_strs[desc],addr_range,
-					x=u'-α' if g.debug_utf8 else ''))
+					x='-α' if g.debug_utf8 else ''))
 			if mmtype == g.proto.mmtypes[0] and user == 'bob':
 				psave = g.proto
 				g.proto = CoinProtocol(g.coin,True)
@@ -2967,8 +2967,8 @@ class MMGenTestSuite(object):
 
 	def get_addr_from_regtest_addrlist(self,user,sid,mmtype,idx,addr_range='1-5'):
 		id_str = { 'L':'', 'S':'-S', 'C':'-C', 'B':'-B' }[mmtype]
-		ext = u'{}{}{}[{}]{x}.testnet.addrs'.format(
-			sid,altcoin_pfx,id_str,addr_range,x=u'-α' if g.debug_utf8 else '')
+		ext = '{}{}{}[{}]{x}.testnet.addrs'.format(
+			sid,altcoin_pfx,id_str,addr_range,x='-α' if g.debug_utf8 else '')
 		fn = get_file_with_ext(ext,self.regtest_user_dir(user),no_dot=True)
 		silence()
 		psave = g.proto
@@ -3020,7 +3020,7 @@ class MMGenTestSuite(object):
 		t.ok()
 
 	def regtest_bob_rbf_bump(self,name):
-		ext = u',{}]{x}.testnet.sigtx'.format(rtFee[1][:-1],x=u'-α' if g.debug_utf8 else '')
+		ext = ',{}]{x}.testnet.sigtx'.format(rtFee[1][:-1],x='-α' if g.debug_utf8 else '')
 		txfile = get_file_with_ext(ext,cfg['tmpdir'],delete=False,no_dot=True)
 		return self.regtest_user_txbump(name,'bob',txfile,rtFee[2],'c')
 
@@ -3069,8 +3069,8 @@ class MMGenTestSuite(object):
 
 	def regtest_bob_pre_import(self,name):
 		pairs = self.gen_pairs(5)
-		write_to_tmpfile(cfg,u'non-mmgen.keys','\n'.join([a[0] for a in pairs])+'\n')
-		write_to_tmpfile(cfg,u'non-mmgen.addrs','\n'.join([a[1] for a in pairs])+'\n')
+		write_to_tmpfile(cfg,'non-mmgen.keys','\n'.join([a[0] for a in pairs])+'\n')
+		write_to_tmpfile(cfg,'non-mmgen.addrs','\n'.join([a[1] for a in pairs])+'\n')
 		return self.regtest_user_txdo(name,'bob',rtFee[4],[pairs[0][1]],'3')
 
 	def regtest_user_import(self,name,user,args):
@@ -3082,17 +3082,17 @@ class MMGenTestSuite(object):
 		t.ok()
 
 	def regtest_bob_import_addr(self,name):
-		addr = read_from_tmpfile(cfg,u'non-mmgen.addrs').split()[0]
+		addr = read_from_tmpfile(cfg,'non-mmgen.addrs').split()[0]
 		return self.regtest_user_import(name,'bob',['--rescan','--address='+addr])
 
 	def regtest_bob_import_list(self,name):
-		fn = os.path.join(cfg['tmpdir'],u'non-mmgen.addrs')
+		fn = os.path.join(cfg['tmpdir'],'non-mmgen.addrs')
 		return self.regtest_user_import(name,'bob',['--addrlist',fn])
 
 	def regtest_bob_split2(self,name):
-		addrs = read_from_tmpfile(cfg,u'non-mmgen.addrs').split()
+		addrs = read_from_tmpfile(cfg,'non-mmgen.addrs').split()
 		amts = (1.12345678,2.87654321,3.33443344,4.00990099,5.43214321)
-		outputs1 = map('{},{}'.format,addrs,amts)
+		outputs1 = list(map('{},{}'.format,addrs,amts))
 		sid = self.regtest_user_sid('bob')
 		l1,l2 = (':S',':B') if 'B' in g.proto.mmtypes else (':S',':S') if g.proto.cap('segwit') else (':L',':L')
 		outputs2 = [sid+':C:2,6.333', sid+':L:3,6.667',sid+l1+':4,0.123',sid+l2+':5']
@@ -3119,7 +3119,7 @@ class MMGenTestSuite(object):
 
 	def regtest_alice_add_label1(self,name):
 		sid = self.regtest_user_sid('alice')
-		return self.regtest_user_add_label(name,'alice',sid+':C:1',u'Original Label - 月へ')
+		return self.regtest_user_add_label(name,'alice',sid+':C:1','Original Label - 月へ')
 
 	def regtest_alice_add_label2(self,name):
 		sid = self.regtest_user_sid('alice')
@@ -3141,7 +3141,7 @@ class MMGenTestSuite(object):
 		t.ok()
 
 	def regtest_alice_add_label_badaddr1(self,name):
-		return self.regtest_alice_add_label_badaddr(name,rt_pw,u'Invalid coin address for this chain: '+rt_pw)
+		return self.regtest_alice_add_label_badaddr(name,rt_pw,'Invalid coin address for this chain: '+rt_pw)
 
 	def regtest_alice_add_label_badaddr2(self,name):
 		addr = g.proto.pubhash2addr('00'*20,False) # mainnet zero address
@@ -3177,7 +3177,7 @@ class MMGenTestSuite(object):
 
 	def regtest_alice_chk_label1(self,name):
 		sid = self.regtest_user_sid('alice')
-		return self.regtest_user_chk_label(name,'alice',sid+':C:1',u'Original Label - 月へ')
+		return self.regtest_user_chk_label(name,'alice',sid+':C:1','Original Label - 月へ')
 
 	def regtest_alice_chk_label2(self,name):
 		sid = self.regtest_user_sid('alice')
@@ -3300,7 +3300,7 @@ class MMGenTestSuite(object):
 	def ethdev_setup(self,name):
 		os.environ['MMGEN_BOGUS_WALLET_DATA'] = ''
 		lf_arg = '--log-file=' + os.path.join(data_dir,'parity.log')
-		ss = u'parity.*--log-file=test/data_dir.*/parity.log' # allow for UTF8_DEBUG
+		ss = 'parity.*--log-file=test/data_dir.*/parity.log' # allow for UTF8_DEBUG
 		try:
 			pid = subprocess.check_output(['pgrep','-af',ss]).split()[0]
 			os.kill(int(pid),9)
@@ -3326,8 +3326,8 @@ class MMGenTestSuite(object):
 		t.read()
 		t.ok()
 
-	def ethdev_addrimport(self,name,ext=u'21-23]{}.addrs',expect='9/9',add_args=[],bad_input=False):
-		ext = ext.format(u'-α' if g.debug_utf8 else '')
+	def ethdev_addrimport(self,name,ext='21-23]{}.addrs',expect='9/9',add_args=[],bad_input=False):
+		ext = ext.format('-α' if g.debug_utf8 else '')
 		fn = get_file_with_ext(ext,cfg['tmpdir'],no_dot=True,delete=False)
 		t = MMGenExpect(name,'mmgen-addrimport', eth_args()[1:] + add_args + [fn])
 		if bad_input:
@@ -3364,16 +3364,16 @@ class MMGenTestSuite(object):
 								interactive_fee=interactive_fee,fee_res=fee_res,fee_desc=fee_desc,
 								add_comment=ref_tx_label_jp)
 
-	def ethdev_txsign(self,name,ni=False,ext=u'{}.rawtx',add_args=[]):
-		ext = ext.format(u'-α' if g.debug_utf8 else '')
+	def ethdev_txsign(self,name,ni=False,ext='{}.rawtx',add_args=[]):
+		ext = ext.format('-α' if g.debug_utf8 else '')
 		key_fn = get_tmpfile_fn(cfg,cfg['parity_keyfile'])
 		write_to_tmpfile(cfg,cfg['parity_keyfile'],eth_key+'\n')
 		tx_fn = get_file_with_ext(ext,cfg['tmpdir'],no_dot=True)
 		t = MMGenExpect(name,'mmgen-txsign',eth_args()+add_args + ([],['--yes'])[ni] + ['-k',key_fn,tx_fn,dfl_words])
 		self.txsign_ui_common(t,name,ni=ni,has_label=True)
 
-	def ethdev_txsend(self,name,ni=False,bogus_send=False,ext=u'{}.sigtx',add_args=[]):
-		ext = ext.format(u'-α' if g.debug_utf8 else '')
+	def ethdev_txsend(self,name,ni=False,bogus_send=False,ext='{}.sigtx',add_args=[]):
+		ext = ext.format('-α' if g.debug_utf8 else '')
 		tx_fn = get_file_with_ext(ext,cfg['tmpdir'],no_dot=True)
 		if not bogus_send: os.environ['MMGEN_BOGUS_SEND'] = ''
 		t = MMGenExpect(name,'mmgen-txsend', eth_args()+add_args + [tx_fn])
@@ -3394,19 +3394,19 @@ class MMGenTestSuite(object):
 	def ethdev_txcreate2(self,name):
 		args = ['98831F3A:E:11,1.234']
 		return self.ethdev_txcreate(name,args=args,acct='10',non_mmgen_inputs=1)
-	def ethdev_txsign2(self,name): self.ethdev_txsign(name,ni=True,ext=u'1.234,50000]{}.rawtx')
-	def ethdev_txsend2(self,name): self.ethdev_txsend(name,ext=u'1.234,50000]{}.sigtx')
+	def ethdev_txsign2(self,name): self.ethdev_txsign(name,ni=True,ext='1.234,50000]{}.rawtx')
+	def ethdev_txsend2(self,name): self.ethdev_txsend(name,ext='1.234,50000]{}.sigtx')
 	def ethdev_bal2(self,name): self.ethdev_bal(name,n='2')
 
 	def ethdev_txcreate3(self,name):
 		args = ['98831F3A:E:21,2.345']
 		return self.ethdev_txcreate(name,args=args,acct='10',non_mmgen_inputs=1)
-	def ethdev_txsign3(self,name): self.ethdev_txsign(name,ni=True,ext=u'2.345,50000]{}.rawtx')
-	def ethdev_txsend3(self,name): self.ethdev_txsend(name,ext=u'2.345,50000]{}.sigtx')
+	def ethdev_txsign3(self,name): self.ethdev_txsign(name,ni=True,ext='2.345,50000]{}.rawtx')
+	def ethdev_txsend3(self,name): self.ethdev_txsend(name,ext='2.345,50000]{}.sigtx')
 	def ethdev_bal3(self,name): self.ethdev_bal(name,n='3')
 
 	def ethdev_tx_status(self,name,ext,expect_str):
-		ext = ext.format(u'-α' if g.debug_utf8 else '')
+		ext = ext.format('-α' if g.debug_utf8 else '')
 		tx_fn = get_file_with_ext(ext,cfg['tmpdir'],no_dot=True)
 		t = MMGenExpect(name,'mmgen-txsend', eth_args() + ['--status',tx_fn])
 		t.expect(expect_str)
@@ -3414,7 +3414,7 @@ class MMGenTestSuite(object):
 		t.ok()
 
 	def ethdev_tx_status1(self,name):
-		self.ethdev_tx_status(name,ext=u'2.345,50000]{}.sigtx',expect_str='has 1 confirmation')
+		self.ethdev_tx_status(name,ext='2.345,50000]{}.sigtx',expect_str='has 1 confirmation')
 
 	def ethdev_txcreate4(self,name):
 		args = ['98831F3A:E:2,23.45495']
@@ -3423,23 +3423,23 @@ class MMGenTestSuite(object):
 		return self.ethdev_txcreate(name,args=args,acct='1',non_mmgen_inputs=0,
 					interactive_fee=interactive_fee,fee_res=fee_res)
 
-	def ethdev_txbump(self,name,ext=u',40000]{}.rawtx',fee='50G',add_args=[]):
-		ext = ext.format(u'-α' if g.debug_utf8 else '')
+	def ethdev_txbump(self,name,ext=',40000]{}.rawtx',fee='50G',add_args=[]):
+		ext = ext.format('-α' if g.debug_utf8 else '')
 		tx_fn = get_file_with_ext(ext,cfg['tmpdir'],no_dot=True)
 		t = MMGenExpect(name,'mmgen-txbump', eth_args() + add_args + ['--yes',tx_fn])
 		t.expect('or gas price: ',fee+'\n')
 		t.read()
 		t.ok()
 
-	def ethdev_txsign4(self,name): self.ethdev_txsign(name,ni=True,ext=u'.45495,50000]{}.rawtx')
-	def ethdev_txsend4(self,name): self.ethdev_txsend(name,ext=u'.45495,50000]{}.sigtx')
+	def ethdev_txsign4(self,name): self.ethdev_txsign(name,ni=True,ext='.45495,50000]{}.rawtx')
+	def ethdev_txsend4(self,name): self.ethdev_txsend(name,ext='.45495,50000]{}.sigtx')
 	def ethdev_bal4(self,name): self.ethdev_bal(name,n='4')
 
 	def ethdev_txcreate5(self,name):
 		args = [eth_burn_addr + ','+eth_amt1]
 		return self.ethdev_txcreate(name,args=args,acct='10',non_mmgen_inputs=1)
-	def ethdev_txsign5(self,name): self.ethdev_txsign(name,ni=True,ext=eth_amt1+u',50000]{}.rawtx')
-	def ethdev_txsend5(self,name): self.ethdev_txsend(name,ext=eth_amt1+u',50000]{}.sigtx')
+	def ethdev_txsign5(self,name): self.ethdev_txsign(name,ni=True,ext=eth_amt1+',50000]{}.rawtx')
+	def ethdev_txsend5(self,name): self.ethdev_txsend(name,ext=eth_amt1+',50000]{}.sigtx')
 	def ethdev_bal5(self,name): self.ethdev_bal(name,n='5')
 
 	bal_corr = Decimal('0.0000032') # gas use for token sends varies between ETH and ETC!
@@ -3496,11 +3496,11 @@ class MMGenTestSuite(object):
 
 	def ethdev_token_compile(self,name,token_data={}):
 		MMGenExpect(name,'',msg_only=True)
-		cmd_args = ['--{}={}'.format(k,v) for k,v in token_data.items()]
+		cmd_args = ['--{}={}'.format(k,v) for k,v in list(token_data.items())]
 		silence()
 		imsg("Compiling solidity token contract '{}' with 'solc'".format(token_data['symbol']))
 		cmd = ['scripts/create-token.py','--coin='+g.coin,'--outdir='+cfg['tmpdir']] + cmd_args + [eth_addr]
-		imsg(u"Executing: {}".format(u' '.join(cmd)))
+		imsg("Executing: {}".format(' '.join(cmd)))
 		subprocess.check_output(cmd)
 		imsg("ERC20 token '{}' compiled".format(token_data['symbol']))
 		end_silence()
@@ -3524,7 +3524,7 @@ class MMGenTestSuite(object):
 		t = MMGenExpect(name,'mmgen-'+mmgen_cmd, eth_args() + args)
 		if mmgen_cmd == 'txcreate':
 			t.written_to_file('Ethereum transaction')
-			ext = u'[0,8000]{}.rawtx'.format(u'-α' if g.debug_utf8 else '')
+			ext = '[0,8000]{}.rawtx'.format('-α' if g.debug_utf8 else '')
 			tx_fn = get_file_with_ext(ext,cfg['tmpdir'],no_dot=True)
 			t = MMGenExpect(name,'mmgen-txsign', eth_args() + ['--yes','-k',key_fn,tx_fn],no_msg=True)
 			self.txsign_ui_common(t,name,ni=True,no_ok=True)
@@ -3548,7 +3548,7 @@ class MMGenTestSuite(object):
 	def ethdev_token_deploy1c(self,name): self.ethdev_token_deploy(name,num=1,key='Token',gas=1100000,tx_fee='7G')
 
 	def ethdev_tx_status2(self,name):
-		self.ethdev_tx_status(name,ext=g.coin+u'[0,7000]{}.sigtx',expect_str='successfully executed')
+		self.ethdev_tx_status(name,ext=g.coin+'[0,7000]{}.sigtx',expect_str='successfully executed')
 
 	def ethdev_bal6(self,name): return self.ethdev_bal5(name)
 
@@ -3564,7 +3564,7 @@ class MMGenTestSuite(object):
 		sid = cfgs['8']['seed_id']
 		cmd = lambda i: ['mmgen-tool','--coin='+g.coin,'gen_addr','{}:E:{}'.format(sid,i),'wallet='+dfl_words]
 		silence()
-		usr_addrs = [subprocess.check_output(cmd(i),stderr=sys.stderr).strip() for i in 11,21]
+		usr_addrs = [subprocess.check_output(cmd(i),stderr=sys.stderr).strip() for i in (11,21)]
 		self.init_ethdev_common()
 		from mmgen.altcoins.eth.contract import Token
 		from mmgen.altcoins.eth.tx import EthereumMMGenTX as etx
@@ -3584,15 +3584,15 @@ class MMGenTestSuite(object):
 		self.ethdev_addrgen(name,addrs='21-23')
 
 	def ethdev_token_addrimport_badaddr1(self,name):
-		self.ethdev_addrimport(name,ext=u'[11-13]{}.addrs',add_args=['--token=abc'],bad_input=True)
+		self.ethdev_addrimport(name,ext='[11-13]{}.addrs',add_args=['--token=abc'],bad_input=True)
 
 	def ethdev_token_addrimport_badaddr2(self,name):
-		self.ethdev_addrimport(name,ext=u'[11-13]{}.addrs',add_args=['--token='+'00deadbeef'*4],bad_input=True)
+		self.ethdev_addrimport(name,ext='[11-13]{}.addrs',add_args=['--token='+'00deadbeef'*4],bad_input=True)
 
 	def ethdev_token_addrimport(self,name):
 		for n,r in ('1','11-13'),('2','21-23'):
 			tk_addr = read_from_tmpfile(cfg,'token_addr'+n).strip()
-			self.ethdev_addrimport(name,ext=u'['+r+']{}.addrs',expect='3/3',add_args=['--token='+tk_addr])
+			self.ethdev_addrimport(name,ext='['+r+']{}.addrs',expect='3/3',add_args=['--token='+tk_addr])
 
 	def ethdev_bal7(self,name): return self.ethdev_bal5(name)
 	def ethdev_token_bal1(self,name): self.ethdev_token_bal(name,n='1')
@@ -3612,9 +3612,9 @@ class MMGenTestSuite(object):
 	def ethdev_token_txcreate1(self,name):
 		return self.ethdev_token_txcreate(name,args=['98831F3A:E:12,1.23456'],token='mm1')
 	def ethdev_token_txsign1(self,name):
-		self.ethdev_token_txsign(name,ext=u'1.23456,50000]{}.rawtx',token='mm1')
+		self.ethdev_token_txsign(name,ext='1.23456,50000]{}.rawtx',token='mm1')
 	def ethdev_token_txsend1(self,name):
-		self.ethdev_token_txsend(name,ext=u'1.23456,50000]{}.sigtx',token='mm1')
+		self.ethdev_token_txsend(name,ext='1.23456,50000]{}.sigtx',token='mm1')
 	def ethdev_token_bal2(self,name): self.ethdev_token_bal(name,n='2')
 
 	def ethdev_twview(self,name,args=[],expect_str='',tool_args=[],exit_val=0):
@@ -3628,12 +3628,12 @@ class MMGenTestSuite(object):
 		return self.ethdev_token_txcreate(name,args=[eth_burn_addr+','+eth_amt2],token='mm1')
 
 	def ethdev_token_txbump(self,name):
-		self.ethdev_txbump(name,ext=eth_amt2+u',50000]{}.rawtx',fee='56G',add_args=['--token=mm1'])
+		self.ethdev_txbump(name,ext=eth_amt2+',50000]{}.rawtx',fee='56G',add_args=['--token=mm1'])
 
 	def ethdev_token_txsign2(self,name):
-		self.ethdev_token_txsign(name,ext=eth_amt2+u',50000]{}.rawtx',token='mm1')
+		self.ethdev_token_txsign(name,ext=eth_amt2+',50000]{}.rawtx',token='mm1')
 	def ethdev_token_txsend2(self,name):
-		self.ethdev_token_txsend(name,ext=eth_amt2+u',50000]{}.sigtx',token='mm1')
+		self.ethdev_token_txsend(name,ext=eth_amt2+',50000]{}.sigtx',token='mm1')
 
 	def ethdev_token_bal3(self,name): self.ethdev_token_bal(name,n='3')
 
@@ -3659,9 +3659,9 @@ class MMGenTestSuite(object):
 	def ethdev_txcreate_noamt(self,name):
 		return self.ethdev_txcreate(name,args=['98831F3A:E:12'])
 	def ethdev_txsign_noamt(self,name):
-		self.ethdev_txsign(name,ext=u'99.99895,50000]{}.rawtx')
+		self.ethdev_txsign(name,ext='99.99895,50000]{}.rawtx')
 	def ethdev_txsend_noamt(self,name):
-		self.ethdev_txsend(name,ext=u'99.99895,50000]{}.sigtx')
+		self.ethdev_txsend(name,ext='99.99895,50000]{}.sigtx')
 
 	def ethdev_bal8(self,name):       self.ethdev_bal(name,n='8')
 	def ethdev_token_bal5(self,name): self.ethdev_token_bal(name,n='5')
@@ -3669,9 +3669,9 @@ class MMGenTestSuite(object):
 	def ethdev_token_txcreate_noamt(self,name):
 		return self.ethdev_token_txcreate(name,args=['98831F3A:E:13'],token='mm1',inputs='2',fee='51G')
 	def ethdev_token_txsign_noamt(self,name):
-		self.ethdev_token_txsign(name,ext=u'1.23456,51000]{}.rawtx',token='mm1')
+		self.ethdev_token_txsign(name,ext='1.23456,51000]{}.rawtx',token='mm1')
 	def ethdev_token_txsend_noamt(self,name):
-		self.ethdev_token_txsend(name,ext=u'1.23456,51000]{}.sigtx',token='mm1')
+		self.ethdev_token_txsend(name,ext='1.23456,51000]{}.sigtx',token='mm1')
 
 	def ethdev_bal9(self,name):       self.ethdev_bal(name,n='9')
 	def ethdev_token_bal6(self,name): self.ethdev_token_bal(name,n='6')
@@ -3874,7 +3874,7 @@ try:
 				gmsg('{}Testing {}'.format(('\n','')[bool(opt.resume)],cmd_data[cmd][0]))
 				continue
 			ts.do_cmd(cmd)
-			if cmd is not cmd_data.keys()[-1]: do_between()
+			if cmd is not list(cmd_data.keys())[-1]: do_between()
 except KeyboardInterrupt:
 	die(1,'\nExiting at user request')
 except opt.traceback and Exception:

+ 4 - 4
test/tooltest.py

@@ -178,7 +178,7 @@ add_spawn_args = ['--data-dir='+cfg['tmpdir']] + ['--{}{}'.format(
 if opt.list_cmds:
 	fs = '  {:<{w}} - {}'
 	Msg('Available commands:')
-	w = max(map(len,cmd_data))
+	w = max(list(map(len,cmd_data)))
 	for cmd in cmd_data:
 		Msg(fs.format(cmd,cmd_data[cmd]['desc'],w=w))
 	Msg('\nAvailable utilities:')
@@ -186,8 +186,8 @@ if opt.list_cmds:
 	sys.exit(0)
 if opt.list_names:
 	acc = []
-	for v in cmd_data.values():
-		acc += v['cmd_data'].keys()
+	for v in list(cmd_data.values()):
+		acc += list(v['cmd_data'].keys())
 	tc = sorted(c.lower() for c in acc)
 	msg('{}\n{}'.format(green('Tested commands:'),'\n'.join(tc)))
 	import mmgen.tool
@@ -503,7 +503,7 @@ else:
 	for cmd in cmd_data:
 		msg('Running tests for {}:'.format(cmd_data[cmd]['desc']))
 		ts.do_cmds(cmd)
-		if cmd is not cmd_data.keys()[-1]: msg('')
+		if cmd is not list(cmd_data.keys())[-1]: msg('')
 
 t = int(time.time()) - start_time
 gmsg('All requested tests finished OK, elapsed time: {:02}:{:02}'.format(t/60,t%60))