Browse Source

Use new-style string formatting

MMGen 7 years ago
parent
commit
351f5f9118

+ 16 - 16
mmgen/addr.py

@@ -328,7 +328,7 @@ Record this checksum: it will be used to verify the address file in the future
 """.strip(),
 """.strip(),
 	'check_chksum': 'Check this value against your records',
 	'check_chksum': 'Check this value against your records',
 	'removed_dup_keys': """
 	'removed_dup_keys': """
-Removed %s duplicate WIF key%s from keylist (also in {pnm} key-address file
+Removed {{}} duplicate WIF key{{}} from keylist (also in {pnm} key-address file
 """.strip().format(pnm=pnm)
 """.strip().format(pnm=pnm)
 	}
 	}
 	entry_type = AddrListEntry
 	entry_type = AddrListEntry
@@ -371,7 +371,7 @@ Removed %s duplicate WIF key%s from keylist (also in {pnm} key-address file
 		elif al_id or adata:
 		elif al_id or adata:
 			die(3,'Must specify both al_id and adata')
 			die(3,'Must specify both al_id and adata')
 		else:
 		else:
-			die(3,'Incorrect arguments for %s' % type(self).__name__)
+			die(3,'Incorrect arguments for {}'.format(type(self).__name__))
 
 
 		# al_id,adata now set
 		# al_id,adata now set
 		self.data = adata
 		self.data = adata
@@ -389,8 +389,8 @@ Removed %s duplicate WIF key%s from keylist (also in {pnm} key-address file
 			if chksum_only:
 			if chksum_only:
 				Msg(self.chksum)
 				Msg(self.chksum)
 			else:
 			else:
-				qmsg('Checksum for %s data %s: %s' %
-						(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[('check_chksum','record_chksum')[src=='gen']])
 				qmsg(self.msgs[('check_chksum','record_chksum')[src=='gen']])
 
 
 	def update_msgs(self):
 	def update_msgs(self):
@@ -426,7 +426,7 @@ Removed %s duplicate WIF key%s from keylist (also in {pnm} key-address file
 			pos += 1
 			pos += 1
 
 
 			if not g.debug:
 			if not g.debug:
-				qmsg_r('\rGenerating %s #%s (%s of %s)' % (self.gen_desc,num,pos,t_addrs))
+				qmsg_r('\rGenerating {} #{} ({} of {})'.format(self.gen_desc,num,pos,t_addrs))
 
 
 			e = le(idx=num)
 			e = le(idx=num)
 
 
@@ -448,7 +448,7 @@ Removed %s duplicate WIF key%s from keylist (also in {pnm} key-address file
 			out.append(e)
 			out.append(e)
 			if g.debug: Msg('generate():\n{}'.format(e.pformat()))
 			if g.debug: Msg('generate():\n{}'.format(e.pformat()))
 
 
-		qmsg('\r%s: %s %s%s generated%s' % (
+		qmsg('\r{}: {} {}{} generated{}'.format(
 				self.al_id.hl(),t_addrs,self.gen_desc,suf(t_addrs,self.gen_desc_pl),' '*15))
 				self.al_id.hl(),t_addrs,self.gen_desc,suf(t_addrs,self.gen_desc_pl),' '*15))
 		return out
 		return out
 
 
@@ -481,7 +481,7 @@ Removed %s duplicate WIF key%s from keylist (also in {pnm} key-address file
 		return [e.idx for e in self.data]
 		return [e.idx for e in self.data]
 
 
 	def addrs(self):
 	def addrs(self):
-		return ['%s:%s'%(self.al_id.sid,e.idx) for e in self.data]
+		return ['{}:{}'.format(self.al_id.sid,e.idx) for e in self.data]
 
 
 	def addrpairs(self):
 	def addrpairs(self):
 		return [(e.idx,e.addr) for e in self.data]
 		return [(e.idx,e.addr) for e in self.data]
@@ -526,7 +526,7 @@ Removed %s duplicate WIF key%s from keylist (also in {pnm} key-address file
 					pop_list.append(n)
 					pop_list.append(n)
 		for n in reversed(pop_list): self.data.pop(n)
 		for n in reversed(pop_list): self.data.pop(n)
 		if pop_list:
 		if pop_list:
-			vmsg(self.msgs['removed_dup_keys'] % (len(pop_list),suf(removed,'s')))
+			vmsg(self.msgs['removed_dup_keys'].format(len(pop_list),suf(removed,'s')))
 
 
 	def add_wifs(self,key_list):
 	def add_wifs(self,key_list):
 		if not key_list: return
 		if not key_list: return
@@ -543,9 +543,9 @@ Removed %s duplicate WIF key%s from keylist (also in {pnm} key-address file
 		ag = AddrGenerator('p2pkh')
 		ag = AddrGenerator('p2pkh')
 		d = self.data
 		d = self.data
 		for n,e in enumerate(d,1):
 		for n,e in enumerate(d,1):
-			qmsg_r('\rGenerating addresses from keylist: %s/%s' % (n,len(d)))
+			qmsg_r('\rGenerating addresses from keylist: {}/{}'.format(n,len(d)))
 			e.addr = ag.to_addr(kg.to_pubhex(e.sec))
 			e.addr = ag.to_addr(kg.to_pubhex(e.sec))
-		qmsg('\rGenerated addresses from keylist: %s/%s ' % (n,len(d)))
+		qmsg('\rGenerated addresses from keylist: {}/{} '.format(n,len(d)))
 
 
 	def format(self,enable_comments=False):
 	def format(self,enable_comments=False):
 
 
@@ -600,7 +600,7 @@ Removed %s duplicate WIF key%s from keylist (also in {pnm} key-address file
 		while lines:
 		while lines:
 			d = get_line()
 			d = get_line()
 
 
-			assert is_mmgen_idx(d[0]),"'%s': invalid address num. in line: '%s'" % (d[0],' '.join(d))
+			assert is_mmgen_idx(d[0]),"'{}': invalid address num. in line: '{}'".format(d[0],' '.join(d))
 			assert self.check_format(d[1]),"'{}': invalid {}".format(d[1],self.data_desc)
 			assert self.check_format(d[1]),"'{}': invalid {}".format(d[1],self.data_desc)
 
 
 			if len(d) != 3: d.append('')
 			if len(d) != 3: d.append('')
@@ -623,9 +623,9 @@ Removed %s duplicate WIF key%s from keylist (also in {pnm} key-address file
 			ag = AddrGenerator(self.al_id.mmtype)
 			ag = AddrGenerator(self.al_id.mmtype)
 			llen = len(ret)
 			llen = len(ret)
 			for n,e in enumerate(ret):
 			for n,e in enumerate(ret):
-				msg_r('\rVerifying keys %s/%s' % (n+1,llen))
+				msg_r('\rVerifying keys {}/{}'.format(n+1,llen))
 				assert e.addr == ag.to_addr(kg.to_pubhex(e.sec)),(
 				assert e.addr == ag.to_addr(kg.to_pubhex(e.sec)),(
-					"Key doesn't match address!\n  %s\n  %s" % (e.sec.wif,e.addr))
+					"Key doesn't match address!\n  {}\n  {}".format(e.sec.wif,e.addr))
 			msg(' - done')
 			msg(' - done')
 
 
 		return ret
 		return ret
@@ -849,7 +849,7 @@ Record this checksum: it will be used to verify the password file in the future
 class AddrData(MMGenObject):
 class AddrData(MMGenObject):
 	msgs = {
 	msgs = {
 	'too_many_acct_addresses': """
 	'too_many_acct_addresses': """
-ERROR: More than one address found for account: '%s'.
+ERROR: More than one address found for account: '{{}}'.
 Your 'wallet.dat' file appears to have been altered by a non-{pnm} program.
 Your 'wallet.dat' file appears to have been altered by a non-{pnm} program.
 Please restore your tracking wallet from a backup or create a new one and
 Please restore your tracking wallet from a backup or create a new one and
 re-import your addresses.
 re-import your addresses.
@@ -890,7 +890,7 @@ re-import your addresses.
 				obj = l.mmid.obj
 				obj = l.mmid.obj
 				i += 1
 				i += 1
 				if len(addrlist) != 1:
 				if len(addrlist) != 1:
-					die(2,self.msgs['too_many_acct_addresses'] % acct)
+					die(2,self.msgs['too_many_acct_addresses'].format(acct))
 				al_id = AddrListID(SeedID(sid=obj.sid),MMGenAddrType(obj.mmtype))
 				al_id = AddrListID(SeedID(sid=obj.sid),MMGenAddrType(obj.mmtype))
 				if al_id not in data:
 				if al_id not in data:
 					data[al_id] = []
 					data[al_id] = []
@@ -904,7 +904,7 @@ re-import your addresses.
 			self.al_ids[addrlist.al_id] = addrlist
 			self.al_ids[addrlist.al_id] = addrlist
 			return True
 			return True
 		else:
 		else:
-			raise TypeError, 'Error: object %s is not of type AddrList' % repr(addrlist)
+			raise TypeError, 'Error: object {!r} is not of type AddrList'.format(addrlist)
 
 
 	def make_reverse_dict(self,coinaddrs):
 	def make_reverse_dict(self,coinaddrs):
 		d = MMGenDict()
 		d = MMGenDict()

+ 4 - 4
mmgen/filename.py

@@ -44,14 +44,14 @@ class Filename(MMGenObject):
 					self.ftype = ftype
 					self.ftype = ftype
 				# elif: # other MMGen file types
 				# elif: # other MMGen file types
 				else:
 				else:
-					die(3,"'%s': not a recognized file type for SeedSource" % ftype)
+					die(3,"'{}': not a recognized file type for SeedSource".format(ftype))
 			else:
 			else:
-				die(3,"'%s': not a class" % ftype)
+				die(3,"'{}': not a class".format(ftype))
 		else:
 		else:
 			# TODO: other file types
 			# TODO: other file types
 			self.ftype = SeedSource.ext_to_type(self.ext)
 			self.ftype = SeedSource.ext_to_type(self.ext)
 			if not self.ftype:
 			if not self.ftype:
-				die(3,"'%s': not a recognized extension for SeedSource" % self.ext)
+				die(3,"'{}': not a recognized extension for SeedSource".format(self.ext))
 
 
 
 
 		import stat
 		import stat
@@ -62,7 +62,7 @@ class Filename(MMGenObject):
 				fd = os.open(fn, mode)
 				fd = os.open(fn, mode)
 			except OSError as e:
 			except OSError as e:
 				if e.errno == 13:
 				if e.errno == 13:
-					die(2,"'%s': permission denied" % fn)
+					die(2,"'{}': permission denied".format(fn))
 #				if e.errno != 17: raise
 #				if e.errno != 17: raise
 			else:
 			else:
 				self.size = os.lseek(fd, 0, os.SEEK_END)
 				self.size = os.lseek(fd, 0, os.SEEK_END)

+ 1 - 1
mmgen/globalvars.py

@@ -97,7 +97,7 @@ class g(object):
 		if sys.platform[:len(k)] == k:
 		if sys.platform[:len(k)] == k:
 			platform = k; break
 			platform = k; break
 	else:
 	else:
-		die(1,"'%s': platform not supported by %s\n" % (sys.platform,proj_name))
+		die(1,"'{}': platform not supported by {}\n".format(sys.platform,proj_name))
 
 
 	if os.getenv('HOME'):                             # Linux or MSYS
 	if os.getenv('HOME'):                             # Linux or MSYS
 		home_dir = os.getenv('HOME')
 		home_dir = os.getenv('HOME')

+ 1 - 1
mmgen/main_tool.py

@@ -147,7 +147,7 @@ import mmgen.tool as tool
 if Command == 'Help' and not cmd_args: tool.usage(None)
 if Command == 'Help' and not cmd_args: tool.usage(None)
 
 
 if Command not in tool.cmd_data:
 if Command not in tool.cmd_data:
-	die(1,"'%s': no such command" % Command.lower())
+	die(1,"'{}': no such command".format(Command.lower()))
 
 
 args,kwargs = tool.process_args(Command,cmd_args)
 args,kwargs = tool.process_args(Command,cmd_args)
 
 

+ 1 - 1
mmgen/main_txsend.py

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

+ 4 - 4
mmgen/main_txsign.py

@@ -92,13 +92,13 @@ if kl and kal: kl.remove_dup_keys(kal)
 tx_num_str = ''
 tx_num_str = ''
 for tx_num,tx_file in enumerate(tx_files,1):
 for tx_num,tx_file in enumerate(tx_files,1):
 	if len(tx_files) > 1:
 	if len(tx_files) > 1:
-		msg('\nTransaction #%s of %s:' % (tx_num,len(tx_files)))
-		tx_num_str = ' #%s' % tx_num
+		msg('\nTransaction #{} of {}:'.format(tx_num,len(tx_files)))
+		tx_num_str = ' #{}'.format(tx_num)
 	tx = MMGenTX(tx_file)
 	tx = MMGenTX(tx_file)
 
 
 	if tx.marked_signed():
 	if tx.marked_signed():
 		die(1,'Transaction is already signed!')
 		die(1,'Transaction is already signed!')
-	vmsg("Successfully opened transaction file '%s'" % tx_file)
+	vmsg("Successfully opened transaction file '{}'".format(tx_file))
 
 
 	if opt.tx_id:
 	if opt.tx_id:
 		msg(tx.txid); continue
 		msg(tx.txid); continue
@@ -107,7 +107,7 @@ for tx_num,tx_file in enumerate(tx_files,1):
 		tx.view(pause=False,terse=opt.terse_info); continue
 		tx.view(pause=False,terse=opt.terse_info); continue
 
 
 	if not opt.yes:
 	if not opt.yes:
-		tx.view_with_prompt('View data for transaction%s?' % tx_num_str)
+		tx.view_with_prompt('View data for transaction{}?'.format(tx_num_str))
 
 
 	txsign(tx,seed_files,kl,kal,tx_num_str)
 	txsign(tx,seed_files,kl,kal,tx_num_str)
 
 

+ 7 - 7
mmgen/main_wallet.py

@@ -53,7 +53,7 @@ elif invoked_as == 'passchg':
 	iaction = 'input'
 	iaction = 'input'
 	bw_note = False
 	bw_note = False
 else:
 else:
-	die(1,"'%s': unrecognized invocation" % g.prog_name)
+	die(1,"'{}': unrecognized invocation".format(g.prog_name))
 
 
 opts_data = lambda: {
 opts_data = lambda: {
 # Can't use: share/Opts doesn't know anything about fmt codes
 # Can't use: share/Opts doesn't know anything about fmt codes
@@ -117,10 +117,10 @@ sf = get_seed_file(cmd_args,nargs,invoked_as=invoked_as)
 
 
 if not invoked_as == 'chk': do_license_msg()
 if not invoked_as == 'chk': do_license_msg()
 
 
-dw_msg = ('',yellow(' (default wallet)'))[bool(sf and os.path.dirname(sf)==g.data_dir)]
-
 if invoked_as in ('conv','passchg'):
 if invoked_as in ('conv','passchg'):
-	msg(green('Processing input wallet')+dw_msg)
+	m1 = green('Processing input wallet')
+	m2 = yellow(' (default wallet)') if sf and os.path.dirname(sf) == g.data_dir else ''
+	msg(m1+m2)
 
 
 ss_in = None if invoked_as == 'gen' else SeedSource(sf,passchg=(invoked_as=='passchg'))
 ss_in = None if invoked_as == 'gen' else SeedSource(sf,passchg=(invoked_as=='passchg'))
 if invoked_as == 'chk':
 if invoked_as == 'chk':
@@ -130,12 +130,12 @@ if invoked_as == 'chk':
 	sys.exit(0)
 	sys.exit(0)
 
 
 if invoked_as in ('conv','passchg'):
 if invoked_as in ('conv','passchg'):
-	msg(green('Processing output wallet'))
+	gmsg('Processing output wallet')
 
 
 ss_out = SeedSource(ss=ss_in,passchg=invoked_as=='passchg')
 ss_out = SeedSource(ss=ss_in,passchg=invoked_as=='passchg')
 
 
 if invoked_as == 'gen':
 if invoked_as == 'gen':
-	qmsg("This wallet's Seed ID: %s" % ss_out.seed.sid.hl())
+	qmsg("This wallet's Seed ID: {}".format(ss_out.seed.sid.hl()))
 
 
 if invoked_as == 'passchg':
 if invoked_as == 'passchg':
 	if not (opt.force_update or [k for k in ('passwd','hash_preset','label')
 	if not (opt.force_update or [k for k in ('passwd','hash_preset','label')
@@ -155,7 +155,7 @@ if invoked_as == 'passchg' and ss_in.infile.dirname == g.data_dir:
 	try:
 	try:
 		check_output(sd_cmd + [ss_in.infile.name])
 		check_output(sd_cmd + [ss_in.infile.name])
 	except:
 	except:
-		msg(yellow("WARNING: '%s' command failed, using regular file delete instead" % sd_cmd[0]))
+		ymsg("WARNING: '{}' command failed, using regular file delete instead".format(sd_cmd[0]))
 #		msg('Command output: {}\nReturn value {}'.format(e.output,e.returncode))
 #		msg('Command output: {}\nReturn value {}'.format(e.output,e.returncode))
 		os.unlink(ss_in.infile.name)
 		os.unlink(ss_in.infile.name)
 elif invoked_as == 'gen' and not find_file_in_dir(Wallet,g.data_dir) \
 elif invoked_as == 'gen' and not find_file_in_dir(Wallet,g.data_dir) \

+ 18 - 21
mmgen/opts.py

@@ -27,13 +27,13 @@ from mmgen.globalvars import g
 import mmgen.share.Opts
 import mmgen.share.Opts
 from mmgen.util import *
 from mmgen.util import *
 
 
-def usage(): Die(2,'USAGE: %s %s' % (g.prog_name, usage_txt))
+def usage(): Die(2,'USAGE: {} {}'.format((g.prog_name,usage_txt)))
 
 
 def die_on_incompatible_opts(incompat_list):
 def die_on_incompatible_opts(incompat_list):
 	for group in incompat_list:
 	for group in incompat_list:
 		bad = [k for k in opt.__dict__ if opt.__dict__[k] and k in group]
 		bad = [k for k in opt.__dict__ if opt.__dict__[k] and k in group]
 		if len(bad) > 1:
 		if len(bad) > 1:
-			die(1,'Conflicting options: %s' % ', '.join([fmt_opt(b) for b in bad]))
+			die(1,'Conflicting options: {}'.format(', '.join(map(fmt_opt,bad))))
 
 
 def fmt_opt(o): return '--' + o.replace('_','-')
 def fmt_opt(o): return '--' + o.replace('_','-')
 
 
@@ -42,7 +42,7 @@ def _show_hash_presets():
 	msg('Available parameters for scrypt.hash():')
 	msg('Available parameters for scrypt.hash():')
 	msg(fs.format('Preset','N','r','p'))
 	msg(fs.format('Preset','N','r','p'))
 	for i in sorted(g.hash_presets.keys()):
 	for i in sorted(g.hash_presets.keys()):
-		msg(fs.format("'%s'" % i, *g.hash_presets[i]))
+		msg(fs.format("'{}'".format(i,*g.hash_presets[i])))
 	msg('N = memory usage (power of two), p = iterations (rounds)')
 	msg('N = memory usage (power of two), p = iterations (rounds)')
 
 
 def opt_preproc_debug(short_opts,long_opts,skipped_opts,uopts,args):
 def opt_preproc_debug(short_opts,long_opts,skipped_opts,uopts,args):
@@ -64,9 +64,9 @@ def opt_postproc_debug():
 	Msg('    Opts after processing:')
 	Msg('    Opts after processing:')
 	for k in a:
 	for k in a:
 		v = getattr(opt,k)
 		v = getattr(opt,k)
-		Msg('        %-18s: %-6s [%s]' % (k,v,type(v).__name__))
+		Msg('        {:18}: {:<6} [{}]'.format(k,v,type(v).__name__))
 	Msg("    Opts set to 'None':")
 	Msg("    Opts set to 'None':")
-	Msg('        %s\n' % '\n        '.join(b))
+	Msg('        {}\n'.format('\n        '.join(b)))
 	Msg('    Global vars:')
 	Msg('    Global vars:')
 	for e in [d for d in dir(g) if d[:2] != '__']:
 	for e in [d for d in dir(g) if d[:2] != '__']:
 		Msg('        {:<20}: {}'.format(e, getattr(g,e)))
 		Msg('        {:<20}: {}'.format(e, getattr(g,e)))
@@ -341,16 +341,15 @@ def opt_is_tx_fee(val,desc):
 def check_opts(usr_opts):       # Returns false if any check fails
 def check_opts(usr_opts):       # Returns false if any check fails
 
 
 	def opt_splits(val,sep,n,desc):
 	def opt_splits(val,sep,n,desc):
-		sepword = 'comma' if sep == ',' else 'colon' if sep == ':' else "'%s'" % sep
+		sepword = 'comma' if sep == ',' else 'colon' if sep == ':' else "'{}'".format(sep)
 		try: l = val.split(sep)
 		try: l = val.split(sep)
 		except:
 		except:
-			msg("'%s': invalid %s (not %s-separated list)" % (val,desc,sepword))
+			msg("'{}': invalid {} (not {}-separated list)".format(val,desc,sepword))
 			return False
 			return False
 
 
 		if len(l) == n: return True
 		if len(l) == n: return True
 		else:
 		else:
-			msg("'%s': invalid %s (%s %s-separated items required)" %
-					(val,desc,n,sepword))
+			msg("'{}': invalid {} ({} {}-separated items required)".format(val,desc,n,sepword))
 			return False
 			return False
 
 
 	def opt_compares(val,op_str,target,desc,what=''):
 	def opt_compares(val,op_str,target,desc,what=''):
@@ -385,18 +384,17 @@ def check_opts(usr_opts):       # Returns false if any check fails
 		return True
 		return True
 
 
 	def opt_unrecognized(key,val,desc):
 	def opt_unrecognized(key,val,desc):
-		msg("'%s': unrecognized %s for option '%s'"
-				% (val,desc,fmt_opt(key)))
+		msg("'{}': unrecognized {} for option '{}'".format(val,desc,fmt_opt(key)))
 		return False
 		return False
 
 
 	def opt_display(key,val='',beg='For selected',end=':\n'):
 	def opt_display(key,val='',beg='For selected',end=':\n'):
-		s = '%s=%s' % (fmt_opt(key),val) if val else fmt_opt(key)
-		msg_r("%s option '%s'%s" % (beg,s,end))
+		s = '{}={}'.format(fmt_opt(key),val) if val else fmt_opt(key)
+		msg_r("{} option '{}'{}".format(beg,s,end))
 
 
 	global opt
 	global opt
 	for key,val in [(k,getattr(opt,k)) for k in usr_opts]:
 	for key,val in [(k,getattr(opt,k)) for k in usr_opts]:
 
 
-		desc = "parameter for '%s' option" % fmt_opt(key)
+		desc = "parameter for '{}' option".format(fmt_opt(key))
 
 
 		from mmgen.util import check_infile,check_outfile,check_outdir
 		from mmgen.util import check_infile,check_outfile,check_outdir
 		# Check for file existence and readability
 		# Check for file existence and readability
@@ -416,8 +414,9 @@ def check_opts(usr_opts):       # Returns false if any check fails
 			if key == 'out_fmt':
 			if key == 'out_fmt':
 				p = 'hidden_incog_output_params'
 				p = 'hidden_incog_output_params'
 				if sstype == IncogWalletHidden and not getattr(opt,p):
 				if sstype == IncogWalletHidden and not getattr(opt,p):
-						die(1,'Hidden incog format output requested. You must supply'
-						+ " a file and offset with the '%s' option" % fmt_opt(p))
+					m1 = 'Hidden incog format output requested.  '
+					m2 = "You must supply a file and offset with the '{}' option"
+					die(1,m1+m2.format(fmt_opt(p)))
 				if issubclass(sstype,IncogWallet) and opt.old_incog_fmt:
 				if issubclass(sstype,IncogWallet) and opt.old_incog_fmt:
 					opt_display(key,val,beg='Selected',end=' ')
 					opt_display(key,val,beg='Selected',end=' ')
 					opt_display('old_incog_fmt',beg='conflicts with',end=':\n')
 					opt_display('old_incog_fmt',beg='conflicts with',end=':\n')
@@ -446,10 +445,8 @@ def check_opts(usr_opts):       # Returns false if any check fails
 				val2 = getattr(opt,key2)
 				val2 = getattr(opt,key2)
 				from mmgen.seed import IncogWalletHidden
 				from mmgen.seed import IncogWalletHidden
 				if val2 and val2 not in IncogWalletHidden.fmt_codes:
 				if val2 and val2 not in IncogWalletHidden.fmt_codes:
-					die(1,
-						'Option conflict:\n  %s, with\n  %s=%s' % (
-						fmt_opt(key),fmt_opt(key2),val2
-					))
+					fs = 'Option conflict:\n  {}, with\n  {}={}'
+					die(1,fs.format(fmt_opt(key),fmt_opt(key2),val2))
 		elif key == 'seed_len':
 		elif key == 'seed_len':
 			if not opt_is_int(val,desc): return False
 			if not opt_is_int(val,desc): return False
 			if not opt_is_in_list(int(val),g.seed_lens,desc): return False
 			if not opt_is_in_list(int(val),g.seed_lens,desc): return False
@@ -497,6 +494,6 @@ def check_opts(usr_opts):       # Returns false if any check fails
 			if not opt_is_int(val,desc): return False
 			if not opt_is_int(val,desc): return False
 			if not opt_compares(val,'>',0,desc): return False
 			if not opt_compares(val,'>',0,desc): return False
 		else:
 		else:
-			if g.debug: Msg("check_opts(): No test for opt '%s'" % key)
+			if g.debug: Msg("check_opts(): No test for opt '{}'".format(key))
 
 
 	return True
 	return True

+ 3 - 3
mmgen/rpc.py

@@ -102,7 +102,7 @@ class CoinDaemonRPCConnection(object):
 				die(args[1],yellow(s))
 				die(args[1],yellow(s))
 
 
 		dmsg_rpc('=== request() debug ===')
 		dmsg_rpc('=== request() debug ===')
-		dmsg_rpc('    RPC POST data ==> %s\n' % p)
+		dmsg_rpc('    RPC POST data ==> {}\n'.format(p))
 		caller = self
 		caller = self
 		class MyJSONEncoder(json.JSONEncoder):
 		class MyJSONEncoder(json.JSONEncoder):
 			def default(self, obj):
 			def default(self, obj):
@@ -132,7 +132,7 @@ class CoinDaemonRPCConnection(object):
 			m = 'Unable to connect to {} at {}:{} (but port is bound?)'
 			m = 'Unable to connect to {} at {}:{} (but port is bound?)'
 			return do_fail(None,2,m.format(g.proto.daemon_name,self.host,self.port))
 			return do_fail(None,2,m.format(g.proto.daemon_name,self.host,self.port))
 
 
-		dmsg_rpc('    RPC GETRESPONSE data ==> %s\n' % r.__dict__)
+		dmsg_rpc('    RPC GETRESPONSE data ==> {}\n'.format(r.__dict__))
 
 
 		if r.status != 200:
 		if r.status != 200:
 			if cf['on_fail'] not in ('silent','raise'):
 			if cf['on_fail'] not in ('silent','raise'):
@@ -148,7 +148,7 @@ class CoinDaemonRPCConnection(object):
 
 
 		r2 = r.read()
 		r2 = r.read()
 
 
-		dmsg_rpc('    RPC REPLY data ==> %s\n' % r2)
+		dmsg_rpc('    RPC REPLY data ==> {}\n'.format(r2))
 
 
 		if not r2:
 		if not r2:
 			return do_fail(r,2,'Error: empty reply')
 			return do_fail(r,2,'Error: empty reply')

+ 79 - 97
mmgen/seed.py

@@ -32,9 +32,8 @@ pnm = g.proj_name
 
 
 def check_usr_seed_len(seed_len):
 def check_usr_seed_len(seed_len):
 	if opt.seed_len != seed_len and 'seed_len' in opt.set_by_user:
 	if opt.seed_len != seed_len and 'seed_len' in opt.set_by_user:
-		m = 'ERROR: requested seed length (%s) ' + \
-			"doesn't match seed length of source (%s)"
-		die(1, m % (opt.seed_len,seed_len))
+		m = "ERROR: requested seed length ({}) doesn't match seed length of source ({})"
+		die(1,m.format((opt.seed_len,seed_len)))
 
 
 class Seed(MMGenObject):
 class Seed(MMGenObject):
 	def __init__(self,seed_bin=None):
 	def __init__(self,seed_bin=None):
@@ -42,7 +41,7 @@ class Seed(MMGenObject):
 			# Truncate random data for smaller seed lengths
 			# Truncate random data for smaller seed lengths
 			seed_bin = sha256(get_random(1033)).digest()[:opt.seed_len/8]
 			seed_bin = sha256(get_random(1033)).digest()[:opt.seed_len/8]
 		elif len(seed_bin)*8 not in g.seed_lens:
 		elif len(seed_bin)*8 not in g.seed_lens:
-			die(3,'%s: invalid seed length' % len(seed_bin))
+			die(3,'{}: invalid seed length'.format(len(seed_bin)))
 
 
 		self.data      = seed_bin
 		self.data      = seed_bin
 		self.hexdata   = hexlify(seed_bin)
 		self.hexdata   = hexlify(seed_bin)
@@ -121,13 +120,12 @@ class SeedSource(MMGenObject):
 			self._decrypt_retry()
 			self._decrypt_retry()
 		else:
 		else:
 			if not self.stdin_ok:
 			if not self.stdin_ok:
-				die(1,'Reading from standard input not supported for %s format'
-						% self.desc)
+				die(1,'Reading from standard input not supported for {} format'.format(self.desc))
 			self._deformat_retry()
 			self._deformat_retry()
 			self._decrypt_retry()
 			self._decrypt_retry()
 
 
-		m = ('',', seed length %s' % self.seed.length)[self.seed.length!=256]
-		qmsg('Valid %s for Seed ID %s%s' % (self.desc,self.seed.sid.hl(),m))
+		m = ('',', seed length {}'.format(self.seed.length))[self.seed.length!=256]
+		qmsg('Valid {} for Seed ID {}{}'.format(self.desc,self.seed.sid.hl(),m))
 
 
 	def _get_data(self):
 	def _get_data(self):
 		if hasattr(self,'infile'):
 		if hasattr(self,'infile'):
@@ -229,14 +227,14 @@ class SeedSourceUnenc(SeedSource):
 	def _encrypt(self): pass
 	def _encrypt(self): pass
 
 
 	def _filename(self):
 	def _filename(self):
-		return '%s[%s].%s' % (self.seed.sid,self.seed.length,self.ext)
+		return '{}[{}].{}'.format(self.seed.sid,self.seed.length,self.ext)
 
 
 class SeedSourceEnc(SeedSource):
 class SeedSourceEnc(SeedSource):
 
 
 	_msg = {
 	_msg = {
 		'choose_passphrase': """
 		'choose_passphrase': """
-You must choose a passphrase to encrypt your new %s with.
-A key will be generated from your passphrase using a hash preset of '%s'.
+You must choose a passphrase to encrypt your new {} with.
+A key will be generated from your passphrase using a hash preset of '{}'.
 Please note that no strength checking of passphrases is performed.  For
 Please note that no strength checking of passphrases is performed.  For
 an empty passphrase, just hit ENTER twice.
 an empty passphrase, just hit ENTER twice.
 	""".strip()
 	""".strip()
@@ -263,8 +261,7 @@ an empty passphrase, just hit ENTER twice.
 					self.ssdata.hash_preset = ret
 					self.ssdata.hash_preset = ret
 					return ret
 					return ret
 				else:
 				else:
-					msg('Invalid input.  Valid choices are %s' %
-							', '.join(sorted(g.hash_presets.keys())))
+					msg('Invalid input.  Valid choices are {}'.format(', '.join(sorted(g.hash_presets.keys()))))
 			else:
 			else:
 				self.ssdata.hash_preset = hp
 				self.ssdata.hash_preset = hp
 				return hp
 				return hp
@@ -273,21 +270,20 @@ an empty passphrase, just hit ENTER twice.
 		if hasattr(self,'ss_in') and hasattr(self.ss_in.ssdata,'hash_preset'):
 		if hasattr(self,'ss_in') and hasattr(self.ss_in.ssdata,'hash_preset'):
 			old_hp = self.ss_in.ssdata.hash_preset
 			old_hp = self.ss_in.ssdata.hash_preset
 			if opt.keep_hash_preset:
 			if opt.keep_hash_preset:
-				qmsg("Reusing hash preset '%s' at user request" % old_hp)
+				qmsg("Reusing hash preset '{}' at user request".format(old_hp))
 				self.ssdata.hash_preset = old_hp
 				self.ssdata.hash_preset = old_hp
 			elif 'hash_preset' in opt.set_by_user:
 			elif 'hash_preset' in opt.set_by_user:
 				hp = self.ssdata.hash_preset = opt.hash_preset
 				hp = self.ssdata.hash_preset = opt.hash_preset
-				qmsg("Using hash preset '%s' requested on command line"
-						% opt.hash_preset)
+				qmsg("Using hash preset '{}' requested on command line".format(opt.hash_preset))
 			else: # Prompt, using old value as default
 			else: # Prompt, using old value as default
 				hp = self._get_hash_preset_from_user(old_hp,desc_suf)
 				hp = self._get_hash_preset_from_user(old_hp,desc_suf)
 
 
 			if (not opt.keep_hash_preset) and self.op == 'pwchg_new':
 			if (not opt.keep_hash_preset) and self.op == 'pwchg_new':
-				m = ("changed to '%s'" % hp,'unchanged')[hp==old_hp]
-				qmsg('Hash preset %s' % m)
+				m = ("changed to '{}'".format(hp),'unchanged')[hp==old_hp]
+				qmsg('Hash preset {}'.format(m))
 		elif 'hash_preset' in opt.set_by_user:
 		elif 'hash_preset' in opt.set_by_user:
 			self.ssdata.hash_preset = opt.hash_preset
 			self.ssdata.hash_preset = opt.hash_preset
-			qmsg("Using hash preset '%s' requested on command line"%opt.hash_preset)
+			qmsg("Using hash preset '{}' requested on command line".format(opt.hash_preset))
 		else:
 		else:
 			self._get_hash_preset_from_user(opt.hash_preset,desc_suf)
 			self._get_hash_preset_from_user(opt.hash_preset,desc_suf)
 
 
@@ -301,18 +297,17 @@ an empty passphrase, just hit ENTER twice.
 			w = pwfile_reuse_warning()
 			w = pwfile_reuse_warning()
 			pw = ' '.join(get_words_from_file(opt.passwd_file,desc,silent=w))
 			pw = ' '.join(get_words_from_file(opt.passwd_file,desc,silent=w))
 		elif opt.echo_passphrase:
 		elif opt.echo_passphrase:
-			pw = ' '.join(get_words_from_user('Enter %s: ' % desc))
+			pw = ' '.join(get_words_from_user('Enter {}: '.format(desc)))
 		else:
 		else:
 			for i in range(g.passwd_max_tries):
 			for i in range(g.passwd_max_tries):
-				pw = ' '.join(get_words_from_user('Enter %s: ' % desc))
+				pw = ' '.join(get_words_from_user('Enter {}: '.format(desc)))
 				pw2 = ' '.join(get_words_from_user('Repeat passphrase: '))
 				pw2 = ' '.join(get_words_from_user('Repeat passphrase: '))
-				dmsg('Passphrases: [%s] [%s]' % (pw,pw2))
+				dmsg('Passphrases: [{}] [{}]'.format(pw,pw2))
 				if pw == pw2:
 				if pw == pw2:
 					vmsg('Passphrases match'); break
 					vmsg('Passphrases match'); break
 				else: msg('Passphrases do not match.  Try again.')
 				else: msg('Passphrases do not match.  Try again.')
 			else:
 			else:
-				die(2,'User failed to duplicate passphrase in %s attempts' %
-						g.passwd_max_tries)
+				die(2,'User failed to duplicate passphrase in {} attempts'.format(g.passwd_max_tries))
 
 
 		if pw == '': qmsg('WARNING: Empty passphrase')
 		if pw == '': qmsg('WARNING: Empty passphrase')
 		self.ssdata.passwd = pw
 		self.ssdata.passwd = pw
@@ -328,7 +323,7 @@ an empty passphrase, just hit ENTER twice.
 			w = pwfile_reuse_warning()
 			w = pwfile_reuse_warning()
 			ret = ' '.join(get_words_from_file(opt.passwd_file,desc,silent=w))
 			ret = ' '.join(get_words_from_file(opt.passwd_file,desc,silent=w))
 		else:
 		else:
-			ret = ' '.join(get_words_from_user('Enter %s: ' % desc))
+			ret = ' '.join(get_words_from_user('Enter {}: '.format(desc)))
 		self.ssdata.passwd = ret
 		self.ssdata.passwd = ret
 
 
 	def _get_first_pw_and_hp_and_encrypt_seed(self):
 	def _get_first_pw_and_hp_and_encrypt_seed(self):
@@ -344,9 +339,9 @@ an empty passphrase, just hit ENTER twice.
 				pw = self._get_new_passphrase()
 				pw = self._get_new_passphrase()
 				if self.op == 'pwchg_new':
 				if self.op == 'pwchg_new':
 					m = ('changed','unchanged')[pw==old_pw]
 					m = ('changed','unchanged')[pw==old_pw]
-					qmsg('Passphrase %s' % m)
+					qmsg('Passphrase {}'.format(m))
 		else:
 		else:
-			qmsg(self.msg['choose_passphrase'] % (self.desc,d.hash_preset))
+			qmsg(self.msg['choose_passphrase'].format(self.desc,d.hash_preset))
 			self._get_new_passphrase()
 			self._get_new_passphrase()
 
 
 		d.salt     = sha256(get_random(128)).digest()[:g.salt_len]
 		d.salt     = sha256(get_random(128)).digest()[:g.salt_len]
@@ -449,7 +444,7 @@ class Mnemonic (SeedSourceUnenc):
 
 
 		for n,w in enumerate(mn,1):
 		for n,w in enumerate(mn,1):
 			if w not in baseconv.digits[self.wl_id]:
 			if w not in baseconv.digits[self.wl_id]:
-				msg('Invalid mnemonic: word #%s is not in the wordlist' % n)
+				msg('Invalid mnemonic: word #{} is not in the wordlist'.format(n))
 				return False
 				return False
 
 
 		hexseed = baseconv.tohex(mn,self.wl_id,self._mn2hex_pad(mn))
 		hexseed = baseconv.tohex(mn,self.wl_id,self._mn2hex_pad(mn))
@@ -480,30 +475,27 @@ class SeedFile (SeedSourceUnenc):
 		b58seed = baseconv.b58encode(self.seed.data,pad=True)
 		b58seed = baseconv.b58encode(self.seed.data,pad=True)
 		self.ssdata.chksum = make_chksum_6(b58seed)
 		self.ssdata.chksum = make_chksum_6(b58seed)
 		self.ssdata.b58seed = b58seed
 		self.ssdata.b58seed = b58seed
-		self.fmt_data = '%s %s\n' % (
-				self.ssdata.chksum,
-				split_into_cols(4,b58seed)
-			)
+		self.fmt_data = '{} {}\n'.format(self.ssdata.chksum,split_into_cols(4,b58seed))
 
 
 	def _deformat(self):
 	def _deformat(self):
 		desc = self.desc
 		desc = self.desc
 		ld = self.fmt_data.split()
 		ld = self.fmt_data.split()
 
 
 		if not (7 <= len(ld) <= 12): # 6 <= padded b58 data (ld[1:]) <= 11
 		if not (7 <= len(ld) <= 12): # 6 <= padded b58 data (ld[1:]) <= 11
-			msg('Invalid data length (%s) in %s' % (len(ld),desc))
+			msg('Invalid data length ({}) in {}'.format(len(ld),desc))
 			return False
 			return False
 
 
 		a,b = ld[0],''.join(ld[1:])
 		a,b = ld[0],''.join(ld[1:])
 
 
 		if not is_chksum_6(a):
 		if not is_chksum_6(a):
-			msg("'%s': invalid checksum format in %s" % (a, desc))
+			msg("'{}': invalid checksum format in {}".format(a, desc))
 			return False
 			return False
 
 
 		if not is_b58_str(b):
 		if not is_b58_str(b):
-			msg("'%s': not a base 58 string, in %s" % (b, desc))
+			msg("'{}': not a base 58 string, in {}".format(b, desc))
 			return False
 			return False
 
 
-		vmsg_r('Validating %s checksum...' % desc)
+		vmsg_r('Validating {} checksum...'.format(desc))
 
 
 		if not compare_chksums(a,'file',make_chksum_6(b),'computed',verbose=True):
 		if not compare_chksums(a,'file',make_chksum_6(b),'computed',verbose=True):
 			return False
 			return False
@@ -511,7 +503,7 @@ class SeedFile (SeedSourceUnenc):
 		ret = baseconv.b58decode(b,pad=True)
 		ret = baseconv.b58decode(b,pad=True)
 
 
 		if ret == False:
 		if ret == False:
-			msg('Invalid base-58 encoded seed: %s' % val)
+			msg('Invalid base-58 encoded seed: {}'.format(val))
 			return False
 			return False
 
 
 		self.seed = Seed(ret)
 		self.seed = Seed(ret)
@@ -533,7 +525,7 @@ class HexSeedFile (SeedSourceUnenc):
 		h = self.seed.hexdata
 		h = self.seed.hexdata
 		self.ssdata.chksum = make_chksum_6(h)
 		self.ssdata.chksum = make_chksum_6(h)
 		self.ssdata.hexseed = h
 		self.ssdata.hexseed = h
-		self.fmt_data = '%s %s\n' % (self.ssdata.chksum, split_into_cols(4,h))
+		self.fmt_data = '{} {}\n'.format(self.ssdata.chksum, split_into_cols(4,h))
 
 
 	def _deformat(self):
 	def _deformat(self):
 		desc = self.desc
 		desc = self.desc
@@ -542,22 +534,22 @@ class HexSeedFile (SeedSourceUnenc):
 			d[1]
 			d[1]
 			chk,hstr = d[0],''.join(d[1:])
 			chk,hstr = d[0],''.join(d[1:])
 		except:
 		except:
-			msg("'%s': invalid %s" % (self.fmt_data.strip(),desc))
+			msg("'{}': invalid {}".format(self.fmt_data.strip(),desc))
 			return False
 			return False
 
 
 		if not len(hstr)*4 in g.seed_lens:
 		if not len(hstr)*4 in g.seed_lens:
-			msg('Invalid data length (%s) in %s' % (len(hstr),desc))
+			msg('Invalid data length ({}) in {}'.format(len(hstr),desc))
 			return False
 			return False
 
 
 		if not is_chksum_6(chk):
 		if not is_chksum_6(chk):
-			msg("'%s': invalid checksum format in %s" % (chk, desc))
+			msg("'{}': invalid checksum format in {}".format(chk, desc))
 			return False
 			return False
 
 
 		if not is_hex_str(hstr):
 		if not is_hex_str(hstr):
-			msg("'%s': not a hexadecimal string, in %s" % (hstr, desc))
+			msg("'{}': not a hexadecimal string, in {}".format(hstr, desc))
 			return False
 			return False
 
 
-		vmsg_r('Validating %s checksum...' % desc)
+		vmsg_r('Validating {} checksum...'.format(desc))
 
 
 		if not compare_chksums(chk,'file',make_chksum_6(hstr),'computed',verbose=True):
 		if not compare_chksums(chk,'file',make_chksum_6(hstr),'computed',verbose=True):
 			return False
 			return False
@@ -577,8 +569,8 @@ class Wallet (SeedSourceEnc):
 	ext = 'mmdat'
 	ext = 'mmdat'
 
 
 	def _get_label_from_user(self,old_lbl=''):
 	def _get_label_from_user(self,old_lbl=''):
-		d = ("to reuse the label '%s'" % old_lbl.hl()) if old_lbl else 'for no label'
-		p = 'Enter a wallet label, or hit ENTER %s: ' % 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:
 		while True:
 			msg_r(p)
 			msg_r(p)
 			ret = my_raw_input('')
 			ret = my_raw_input('')
@@ -598,19 +590,19 @@ class Wallet (SeedSourceEnc):
 		if hasattr(self,'ss_in') and hasattr(self.ss_in.ssdata,'label'):
 		if hasattr(self,'ss_in') and hasattr(self.ss_in.ssdata,'label'):
 			old_lbl = self.ss_in.ssdata.label
 			old_lbl = self.ss_in.ssdata.label
 			if opt.keep_label:
 			if opt.keep_label:
-				qmsg("Reusing label '%s' at user request" % old_lbl.hl())
+				qmsg("Reusing label '{}' at user request".format(old_lbl.hl()))
 				self.ssdata.label = old_lbl
 				self.ssdata.label = old_lbl
 			elif opt.label:
 			elif opt.label:
-				qmsg("Using label '%s' requested on command line" % opt.label.hl())
+				qmsg("Using label '{}' requested on command line".format(opt.label.hl()))
 				lbl = self.ssdata.label = opt.label
 				lbl = self.ssdata.label = opt.label
 			else: # Prompt, using old value as default
 			else: # Prompt, using old value as default
 				lbl = self._get_label_from_user(old_lbl)
 				lbl = self._get_label_from_user(old_lbl)
 
 
 			if (not opt.keep_label) and self.op == 'pwchg_new':
 			if (not opt.keep_label) and self.op == 'pwchg_new':
-				m = ("changed to '%s'" % lbl,'unchanged')[lbl==old_lbl]
-				qmsg('Label %s' % m)
+				m = ("changed to '{}'".format(lbl),'unchanged')[lbl==old_lbl]
+				qmsg('Label {}'.format(m))
 		elif opt.label:
 		elif opt.label:
-			qmsg("Using label '%s' requested on command line" % opt.label.hl())
+			qmsg("Using label '{}' requested on command line".format(opt.label.hl()))
 			self.ssdata.label = opt.label
 			self.ssdata.label = opt.label
 		else:
 		else:
 			self._get_label_from_user()
 			self._get_label_from_user()
@@ -636,20 +628,18 @@ class Wallet (SeedSourceEnc):
 			'{} {}'.format(make_chksum_6(es_fmt), split_into_cols(4,es_fmt))
 			'{} {}'.format(make_chksum_6(es_fmt), split_into_cols(4,es_fmt))
 		)
 		)
 		chksum = make_chksum_6(' '.join(lines))
 		chksum = make_chksum_6(' '.join(lines))
-		self.fmt_data = '%s\n' % '\n'.join((chksum,)+lines)
+		self.fmt_data = '{}\n'.format('\n'.join((chksum,)+lines))
 
 
 	def _deformat(self):
 	def _deformat(self):
 
 
 		def check_master_chksum(lines,desc):
 		def check_master_chksum(lines,desc):
 
 
 			if len(lines) != 6:
 			if len(lines) != 6:
-				msg('Invalid number of lines (%s) in %s data' %
-						(len(lines),desc))
+				msg('Invalid number of lines ({}) in {} data'.format(len(lines),desc))
 				return False
 				return False
 
 
 			if not is_chksum_6(lines[0]):
 			if not is_chksum_6(lines[0]):
-				msg('Incorrect master checksum (%s) in %s data' %
-						(lines[0],desc))
+				msg('Incorrect master checksum ({}) in {} data'.format(lines[0],desc))
 				return False
 				return False
 
 
 			chk = make_chksum_6(' '.join(lines[1:]))
 			chk = make_chksum_6(' '.join(lines[1:]))
@@ -674,17 +664,16 @@ class Wallet (SeedSourceEnc):
 		hpdata = lines[3].split()
 		hpdata = lines[3].split()
 
 
 		d.hash_preset = hp = hpdata[0][:-1]  # a string!
 		d.hash_preset = hp = hpdata[0][:-1]  # a string!
-		qmsg("Hash preset of wallet: '%s'" % hp)
+		qmsg("Hash preset of wallet: '{}'".format(hp))
 		if 'hash_preset' in opt.set_by_user:
 		if 'hash_preset' in opt.set_by_user:
 			uhp = opt.hash_preset
 			uhp = opt.hash_preset
 			if uhp != hp:
 			if uhp != hp:
-				qmsg("Warning: ignoring user-requested hash preset '%s'" % uhp)
+				qmsg("Warning: ignoring user-requested hash preset '{}'".format(uhp))
 
 
 		hash_params = map(int,hpdata[1:])
 		hash_params = map(int,hpdata[1:])
 
 
 		if hash_params != get_hash_params(d.hash_preset):
 		if hash_params != get_hash_params(d.hash_preset):
-			msg("Hash parameters '%s' don't match hash preset '%s'" %
-					(' '.join(hash_params), d.hash_preset))
+			msg("Hash parameters '{}' don't match hash preset '{}'".format(' '.join(hash_params),d.hash_preset))
 			return False
 			return False
 
 
 		lmin,foo,lmax = [v for k,v in baseconv.b58pad_lens] # 22,33,44
 		lmin,foo,lmax = [v for k,v in baseconv.b58pad_lens] # 22,33,44
@@ -694,7 +683,7 @@ class Wallet (SeedSourceEnc):
 			b58_val = ''.join(l)
 			b58_val = ''.join(l)
 
 
 			if len(b58_val) < lmin or len(b58_val) > lmax:
 			if len(b58_val) < lmin or len(b58_val) > lmax:
-				msg('Invalid format for %s in %s: %s' % (key,self.desc,l))
+				msg('Invalid format for {} in {}: {}'.format(key,self.desc,l))
 				return False
 				return False
 
 
 			if not compare_chksums(chk,key,
 			if not compare_chksums(chk,key,
@@ -703,7 +692,7 @@ class Wallet (SeedSourceEnc):
 
 
 			val = baseconv.b58decode(b58_val,pad=True)
 			val = baseconv.b58decode(b58_val,pad=True)
 			if val == False:
 			if val == False:
-				msg('Invalid base 58 number: %s' % b58_val)
+				msg('Invalid base 58 number: {}'.format(b58_val))
 				return False
 				return False
 
 
 			setattr(d,key,val)
 			setattr(d,key,val)
@@ -756,9 +745,9 @@ class Brainwallet (SeedSourceEnc):
 			seed_len,d.hash_preset = self.get_bw_params()
 			seed_len,d.hash_preset = self.get_bw_params()
 		else:
 		else:
 			if 'seed_len' not in opt.set_by_user:
 			if 'seed_len' not in opt.set_by_user:
-				m1 = 'Using default seed length of %s bits'
+				m1 = 'Using default seed length of {} bits\n'
 				m2 = 'If this is not what you want, use the --seed-len option'
 				m2 = 'If this is not what you want, use the --seed-len option'
-				qmsg((m1+'\n'+m2) % yellow(str(opt.seed_len)))
+				qmsg((m1+m2).format(yellow(str(opt.seed_len))))
 			self._get_hash_preset()
 			self._get_hash_preset()
 			seed_len = opt.seed_len
 			seed_len = opt.seed_len
 		qmsg_r('Hashing brainwallet data.  Please wait...')
 		qmsg_r('Hashing brainwallet data.  Please wait...')
@@ -767,7 +756,7 @@ class Brainwallet (SeedSourceEnc):
 					d.hash_preset, buflen=seed_len/8)
 					d.hash_preset, buflen=seed_len/8)
 		qmsg('Done')
 		qmsg('Done')
 		self.seed = Seed(seed)
 		self.seed = Seed(seed)
-		msg('Seed ID: %s' % self.seed.sid)
+		msg('Seed ID: {}'.format(self.seed.sid))
 		qmsg('Check this value against your records')
 		qmsg('Check this value against your records')
 		return True
 		return True
 
 
@@ -796,7 +785,7 @@ Try again? (Y)es, (n)o, (m)ore information:
 If the Seed ID above is correct but you're seeing this message, then you need
 If the Seed ID above is correct but you're seeing this message, then you need
 to exit and re-run the program with the '--old-incog-fmt' option.
 to exit and re-run the program with the '--old-incog-fmt' option.
 """.strip(),
 """.strip(),
-		'dec_chk': " %s hash preset"
+		'dec_chk': " {} hash preset"
 	}
 	}
 
 
 	def _make_iv_chksum(self,s): return sha256(s).hexdigest()[:8].upper()
 	def _make_iv_chksum(self,s): return sha256(s).hexdigest()[:8].upper()
@@ -813,16 +802,14 @@ to exit and re-run the program with the '--old-incog-fmt' option.
 			return True
 			return True
 		else:
 		else:
 			if opt.old_incog_fmt:
 			if opt.old_incog_fmt:
-				msg('WARNING: old-style incognito format requested.  ' +
-					'Are you sure this is correct?')
-			msg(('Invalid incognito data size (%s bytes) for this ' +
-				'seed length (%s bits)') % (dlen,opt.seed_len))
-			msg('Valid data size for this seed length: %s bytes' % valid_dlen)
+				msg('WARNING: old-style incognito format requested.  Are you sure this is correct?')
+			m = 'Invalid incognito data size ({} bytes) for this seed length ({} bits)'
+			msg(m.format(dlen,opt.seed_len))
+			msg('Valid data size for this seed length: {} bytes'.format(valid_dlen))
 			for sl in g.seed_lens:
 			for sl in g.seed_lens:
 				if dlen == self._get_incog_data_len(sl):
 				if dlen == self._get_incog_data_len(sl):
-					die(1,'Valid seed length for this data size: %s bits' % sl)
-			msg(('This data size (%s bytes) is invalid for all available ' +
-				'seed lengths') % dlen)
+					die(1,'Valid seed length for this data size: {} bits'.format(sl))
+			msg('This data size ({} bytes) is invalid for all available seed lengths'.format(dlen))
 			return False
 			return False
 
 
 	def _encrypt (self):
 	def _encrypt (self):
@@ -833,7 +820,7 @@ to exit and re-run the program with the '--old-incog-fmt' option.
 		# IV is used BOTH to initialize counter and to salt password!
 		# IV is used BOTH to initialize counter and to salt password!
 		d.iv = get_random(g.aesctr_iv_len)
 		d.iv = get_random(g.aesctr_iv_len)
 		d.iv_id = self._make_iv_chksum(d.iv)
 		d.iv_id = self._make_iv_chksum(d.iv)
-		msg('New Incog Wallet ID: %s' % d.iv_id)
+		msg('New Incog Wallet ID: {}'.format(d.iv_id))
 		qmsg('Make a record of this value')
 		qmsg('Make a record of this value')
 		vmsg(self.msg['record_incog_id'])
 		vmsg(self.msg['record_incog_id'])
 
 
@@ -844,7 +831,7 @@ to exit and re-run the program with the '--old-incog-fmt' option.
 
 
 		d.wrapper_key = make_key(d.passwd, d.iv, d.hash_preset, 'incog wrapper key')
 		d.wrapper_key = make_key(d.passwd, d.iv, d.hash_preset, 'incog wrapper key')
 		d.key_id = make_chksum_8(d.wrapper_key)
 		d.key_id = make_chksum_8(d.wrapper_key)
-		vmsg('Key ID: %s' % d.key_id)
+		vmsg('Key ID: {}'.format(d.key_id))
 		d.target_data_len = self._get_incog_data_len(self.seed.length)
 		d.target_data_len = self._get_incog_data_len(self.seed.length)
 
 
 	def _format(self):
 	def _format(self):
@@ -876,7 +863,7 @@ to exit and re-run the program with the '--old-incog-fmt' option.
 		d.iv             = self.fmt_data[0:g.aesctr_iv_len]
 		d.iv             = self.fmt_data[0:g.aesctr_iv_len]
 		d.incog_id       = self._make_iv_chksum(d.iv)
 		d.incog_id       = self._make_iv_chksum(d.iv)
 		d.enc_incog_data = self.fmt_data[g.aesctr_iv_len:]
 		d.enc_incog_data = self.fmt_data[g.aesctr_iv_len:]
-		msg('Incog Wallet ID: %s' % d.incog_id)
+		msg('Incog Wallet ID: {}'.format(d.incog_id))
 		qmsg('Check this value against your records')
 		qmsg('Check this value against your records')
 		vmsg(self.msg['check_incog_id'])
 		vmsg(self.msg['check_incog_id'])
 
 
@@ -885,14 +872,14 @@ to exit and re-run the program with the '--old-incog-fmt' option.
 	def _verify_seed_newfmt(self,data):
 	def _verify_seed_newfmt(self,data):
 		chk,seed = data[:8],data[8:]
 		chk,seed = data[:8],data[8:]
 		if sha256(seed).digest()[:8] == chk:
 		if sha256(seed).digest()[:8] == chk:
-			qmsg('Passphrase%s are correct' % (self.msg['dec_chk'] % 'and'))
+			qmsg('Passphrase{} are correct'.format(self.msg['dec_chk'].format('and')))
 			return seed
 			return seed
 		else:
 		else:
-			msg('Incorrect passphrase%s' % (self.msg['dec_chk'] % 'or'))
+			msg('Incorrect passphrase{}'.format(self.msg['dec_chk'].format('or')))
 			return False
 			return False
 
 
 	def _verify_seed_oldfmt(self,seed):
 	def _verify_seed_oldfmt(self,seed):
-		m = 'Seed ID: %s.  Is the Seed ID correct?' % make_chksum_8(seed)
+		m = 'Seed ID: {}.  Is the Seed ID correct?'.format(make_chksum_8(seed))
 		if keypress_confirm(m, True):
 		if keypress_confirm(m, True):
 			return seed
 			return seed
 		else:
 		else:
@@ -912,7 +899,7 @@ to exit and re-run the program with the '--old-incog-fmt' option.
 		d.enc_seed = dd[g.salt_len:]
 		d.enc_seed = dd[g.salt_len:]
 
 
 		key = make_key(d.passwd, d.salt, d.hash_preset, 'main key')
 		key = make_key(d.passwd, d.salt, d.hash_preset, 'main key')
-		qmsg('Key ID: %s' % make_chksum_8(key))
+		qmsg('Key ID: {}'.format(make_chksum_8(key)))
 
 
 		verify_seed = getattr(self,'_verify_seed_'+
 		verify_seed = getattr(self,'_verify_seed_'+
 						('newfmt','oldfmt')[bool(opt.old_incog_fmt)])
 						('newfmt','oldfmt')[bool(opt.old_incog_fmt)])
@@ -921,7 +908,7 @@ to exit and re-run the program with the '--old-incog-fmt' option.
 
 
 		if seed:
 		if seed:
 			self.seed = Seed(seed)
 			self.seed = Seed(seed)
-			msg('Seed ID: %s' % self.seed.sid)
+			msg('Seed ID: {}'.format(self.seed.sid))
 			return True
 			return True
 		else:
 		else:
 			return False
 			return False
@@ -969,7 +956,7 @@ harder to find, you're advised to choose a much larger file size than this.
   identify the incog wallet data in the future and to locate the offset
   identify the incog wallet data in the future and to locate the offset
   where the data is hidden in the event you forget it.
   where the data is hidden in the event you forget it.
 	""",
 	""",
-		'dec_chk': ', hash preset, offset %s seed length'
+		'dec_chk': ', hash preset, offset {} seed length'
 	}
 	}
 
 
 	def _get_hincog_params(self,wtype):
 	def _get_hincog_params(self,wtype):
@@ -980,15 +967,14 @@ harder to find, you're advised to choose a much larger file size than this.
 		d = self.ssdata
 		d = self.ssdata
 		m = ('Input','Destination')[action=='write']
 		m = ('Input','Destination')[action=='write']
 		if fn.size < d.hincog_offset + d.target_data_len:
 		if fn.size < d.hincog_offset + d.target_data_len:
-			die(1,
-	"%s file '%s' has length %s, too short to %s %s bytes of data at offset %s"
-				% (m,fn.name,fn.size,action,d.target_data_len,d.hincog_offset))
+			fs = "{} file '{}' has length {}, too short to {} {} bytes of data at offset {}"
+			die(1,fs.format(m,fn.name,fn.size,action,d.target_data_len,d.hincog_offset))
 
 
 	def _get_data(self):
 	def _get_data(self):
 		d = self.ssdata
 		d = self.ssdata
 		d.hincog_offset = self._get_hincog_params('input')[1]
 		d.hincog_offset = self._get_hincog_params('input')[1]
 
 
-		qmsg("Getting hidden incog data from file '%s'" % self.infile.name)
+		qmsg("Getting hidden incog data from file '{}'".format(self.infile.name))
 
 
 		# Already sanity-checked:
 		# Already sanity-checked:
 		d.target_data_len = self._get_incog_data_len(opt.seed_len)
 		d.target_data_len = self._get_incog_data_len(opt.seed_len)
@@ -999,8 +985,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)
 		os.lseek(fh,int(d.hincog_offset),os.SEEK_SET)
 		self.fmt_data = os.read(fh,d.target_data_len)
 		self.fmt_data = os.read(fh,d.target_data_len)
 		os.close(fh)
 		os.close(fh)
-		qmsg("Data read from file '%s' at offset %s" %
-				(self.infile.name,d.hincog_offset), 'Data read from file')
+		qmsg("Data read from file '{}' at offset {}".format(self.infile.name,d.hincog_offset))
 
 
 	# overrides method in SeedSource
 	# overrides method in SeedSource
 	def write_to_file(self):
 	def write_to_file(self):
@@ -1019,15 +1004,13 @@ harder to find, you're advised to choose a much larger file size than this.
 		try:
 		try:
 			os.stat(fn)
 			os.stat(fn)
 		except:
 		except:
-			if keypress_confirm("Requested file '%s' does not exist.  Create?"
-					% 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
 				min_fsize = d.target_data_len + d.hincog_offset
 				msg(self.msg['choose_file_size'].format(min_fsize))
 				msg(self.msg['choose_file_size'].format(min_fsize))
 				while True:
 				while True:
 					fsize = parse_nbytes(my_raw_input('Enter file size: '))
 					fsize = parse_nbytes(my_raw_input('Enter file size: '))
 					if fsize >= min_fsize: break
 					if fsize >= min_fsize: break
-					msg('File size must be an integer no less than %s' %
-							min_fsize)
+					msg('File size must be an integer no less than {}'.format(min_fsize))
 
 
 				from mmgen.tool import Rand2file # threaded routine
 				from mmgen.tool import Rand2file # threaded routine
 				Rand2file(fn,str(fsize))
 				Rand2file(fn,str(fsize))
@@ -1037,17 +1020,16 @@ harder to find, you're advised to choose a much larger file size than this.
 
 
 		f = Filename(fn,ftype=type(self),write=True)
 		f = Filename(fn,ftype=type(self),write=True)
 
 
-		dmsg('%s data len %s, offset %s' % (
-				capfirst(self.desc),d.target_data_len,d.hincog_offset))
+		dmsg('{} data len {}, offset {}'.format(capfirst(self.desc),d.target_data_len,d.hincog_offset))
 
 
 		if check_offset:
 		if check_offset:
 			self._check_valid_offset(f,'write')
 			self._check_valid_offset(f,'write')
-			if not opt.quiet: confirm_or_exit('',"alter file '%s'" % f.name)
+			if not opt.quiet:
+				confirm_or_exit('',"alter file '{}'".format(f.name))
 
 
 		flgs = os.O_RDWR|os.O_BINARY if g.platform == 'win' else os.O_RDWR
 		flgs = os.O_RDWR|os.O_BINARY if g.platform == 'win' else os.O_RDWR
 		fh = os.open(f.name,flgs)
 		fh = os.open(f.name,flgs)
 		os.lseek(fh, int(d.hincog_offset), os.SEEK_SET)
 		os.lseek(fh, int(d.hincog_offset), os.SEEK_SET)
 		os.write(fh, self.fmt_data)
 		os.write(fh, self.fmt_data)
 		os.close(fh)
 		os.close(fh)
-		msg("%s written to file '%s' at offset %s" % (
-				capfirst(self.desc),f.name,d.hincog_offset))
+		msg("{} written to file '{}' at offset {}".format(capfirst(self.desc),f.name,d.hincog_offset))

+ 4 - 5
mmgen/share/Opts.py

@@ -24,7 +24,7 @@ import sys,getopt
 # from mmgen.util import mdie,die,pdie,pmsg # DEBUG
 # from mmgen.util import mdie,die,pdie,pmsg # DEBUG
 
 
 def usage(opts_data):
 def usage(opts_data):
-	print('USAGE: %s %s' % (opts_data['prog_name'], opts_data['usage']))
+	print('USAGE: {} {}'.format(opts_data['prog_name'], opts_data['usage']))
 	sys.exit(2)
 	sys.exit(2)
 
 
 def print_help_and_exit(opts_data,longhelp=False):
 def print_help_and_exit(opts_data,longhelp=False):
@@ -81,10 +81,9 @@ def process_opts(argv,opts_data,short_opts,long_opts,defer_help=False):
 				if (v and v_in == bool) or v == v_in:
 				if (v and v_in == bool) or v == v_in:
 					if o_out in opts and opts[o_out] != v_out:
 					if o_out in opts and opts[o_out] != v_out:
 						sys.stderr.write(
 						sys.stderr.write(
-				'Option conflict:\n  --%s=%s, with\n  --%s=%s\n' % (
-					o_out.replace('_','-'),opts[o_out],
-					o_in.replace('_','-'),opts[o_in]
-				))
+							'Option conflict:\n  --{}={}, with\n  --{}={}\n'.format(
+								o_out.replace('_','-'),opts[o_out],
+								o_in.replace('_','-'),opts[o_in]))
 						sys.exit(1)
 						sys.exit(1)
 					else:
 					else:
 						opts[o_out] = v_out
 						opts[o_out] = v_out

+ 7 - 10
mmgen/test.py

@@ -30,7 +30,7 @@ def cleandir(d):
 	try:    files = os.listdir(d)
 	try:    files = os.listdir(d)
 	except: return
 	except: return
 
 
-	msg(green("Cleaning directory '%s'" % d))
+	gmsg("Cleaning directory '{}'".format(d))
 	for f in files:
 	for f in files:
 		try:
 		try:
 			os.unlink(os.path.join(d,f))
 			os.unlink(os.path.join(d,f))
@@ -49,7 +49,7 @@ def mk_tmpdir(d):
 	except OSError as e:
 	except OSError as e:
 		if e.errno != 17: raise
 		if e.errno != 17: raise
 	else:
 	else:
-		vmsg("Created directory '%s'" % d)
+		vmsg("Created directory '{}'".format(d))
 
 
 def mk_tmpdir_path(path,cfg):
 def mk_tmpdir_path(path,cfg):
 	try:
 	try:
@@ -64,7 +64,7 @@ def mk_tmpdir_path(path,cfg):
 			os.symlink(src,cfg['tmpdir'])
 			os.symlink(src,cfg['tmpdir'])
 	except OSError as e:
 	except OSError as e:
 		if e.errno != 17: raise
 		if e.errno != 17: raise
-	else: msg("Created directory '%s'" % cfg['tmpdir'])
+	else: msg("Created directory '{}'".format(cfg['tmpdir']))
 
 
 def get_tmpfile_fn(cfg,fn):
 def get_tmpfile_fn(cfg,fn):
 	return os.path.join(cfg['tmpdir'],fn)
 	return os.path.join(cfg['tmpdir'],fn)
@@ -87,7 +87,7 @@ def read_from_tmpfile(cfg,fn,binary=False):
 def ok():
 def ok():
 	if opt.profile: return
 	if opt.profile: return
 	if opt.verbose or opt.exact_output:
 	if opt.verbose or opt.exact_output:
-		sys.stderr.write(green('OK\n'))
+		gmsg('OK')
 	else: msg(' OK')
 	else: msg(' OK')
 
 
 def ok_or_die(val,chk_func,s,skip_ok=False):
 def ok_or_die(val,chk_func,s,skip_ok=False):
@@ -96,17 +96,14 @@ def ok_or_die(val,chk_func,s,skip_ok=False):
 	if ret:
 	if ret:
 		if not skip_ok: ok()
 		if not skip_ok: ok()
 	else:
 	else:
-		msg(red("Returned value '%s' is not a %s" % (val,s)))
-		sys.exit(3)
+		rdie(3,"Returned value '{}' is not a {}".format((val,s)))
 
 
 def cmp_or_die(s,t,skip_ok=False):
 def cmp_or_die(s,t,skip_ok=False):
 	if s == t:
 	if s == t:
 		if not skip_ok: ok()
 		if not skip_ok: ok()
 	else:
 	else:
-		sys.stderr.write(red(
-			'ERROR: recoded data:\n%s\ndiffers from original data:\n%s\n' %
-				(repr(t),repr(s))))
-		sys.exit(3)
+		m = 'ERROR: recoded data:\n{}\ndiffers from original data:\n{}'
+		rdie(3,m.format(repr(t),repr(s)))
 
 
 def init_coverage():
 def init_coverage():
 	coverdir = os.path.join('test','trace')
 	coverdir = os.path.join('test','trace')

+ 1 - 1
mmgen/tool.py

@@ -122,7 +122,7 @@ def usage(command):
 				c,h = line.split('-',1)
 				c,h = line.split('-',1)
 				Msg('MMGEN-TOOL {}: {}'.format(c.strip().upper(),h.strip()))
 				Msg('MMGEN-TOOL {}: {}'.format(c.strip().upper(),h.strip()))
 		cd = cmd_data[Command]
 		cd = cmd_data[Command]
-		msg('USAGE: {} {} {}'.format(g.prog_name,command,' '.join(cd)))
+		msg('USAGE: {} {} {}'.format(g.prog_name,command.lower(),' '.join(cd)))
 	else:
 	else:
 		msg("'{}': no such tool command".format(command))
 		msg("'{}': no such tool command".format(command))
 	sys.exit(1)
 	sys.exit(1)

+ 14 - 16
mmgen/tw.py

@@ -103,7 +103,7 @@ watch-only wallet using '{}-addrimport' and then re-run this program.
 			'addr':  lambda i: i.addr,
 			'addr':  lambda i: i.addr,
 			'age':   lambda i: 0 - i.confs,
 			'age':   lambda i: 0 - i.confs,
 			'amt':   lambda i: i.amt,
 			'amt':   lambda i: i.amt,
-			'txid':  lambda i: '%s %03s' % (i.txid,i.vout),
+			'txid':  lambda i: '{} {:04}'.format(i.txid,i.vout),
 			'mmid':  lambda i: i.twmmid.sort_key
 			'mmid':  lambda i: i.twmmid.sort_key
 		}
 		}
 		key = key or self.sort_key
 		key = key or self.sort_key
@@ -173,12 +173,11 @@ watch-only wallet using '{}-addrimport' and then re-run this program.
 				else i.twmmid if i.twmmid.type=='mmgen'
 				else i.twmmid if i.twmmid.type=='mmgen'
 					else 'Non-{}'.format(g.proj_name),width=mmid_w,color=True)
 					else 'Non-{}'.format(g.proj_name),width=mmid_w,color=True)
 			if self.show_mmid:
 			if self.show_mmid:
-				addr_out = '%s %s' % (
+				addr_out = '{} {}'.format(
 					type(i.addr).fmtc(addr_dots,width=btaddr_w,color=True) if i.skip == 'addr' \
 					type(i.addr).fmtc(addr_dots,width=btaddr_w,color=True) if i.skip == 'addr' \
-						else i.addr.fmt(width=btaddr_w,color=True),
+							else i.addr.fmt(width=btaddr_w,color=True),
 					'{} {}'.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 '')
-				)
+							if label_w > 0 else ''))
 			else:
 			else:
 				addr_out = type(i.addr).fmtc(addr_dots,width=addr_w,color=True) \
 				addr_out = type(i.addr).fmtc(addr_dots,width=addr_w,color=True) \
 					if i.skip=='addr' else i.addr.fmt(width=addr_w,color=True)
 					if i.skip=='addr' else i.addr.fmt(width=addr_w,color=True)
@@ -239,18 +238,17 @@ watch-only wallet using '{}-addrimport' and then re-run this program.
 			if ret == 'q': return None,None
 			if ret == 'q': return None,None
 			n = AddrIdx(ret,on_fail='silent') # hacky way to test and convert to integer
 			n = AddrIdx(ret,on_fail='silent') # hacky way to test and convert to integer
 			if not n or n < 1 or n > len(self.unspent):
 			if not n or n < 1 or n > len(self.unspent):
-				msg('Choice must be a single number between 1 and %s' % len(self.unspent))
+				msg('Choice must be a single number between 1 and {}'.format(len(self.unspent)))
 # 			elif not self.unspent[n-1].mmid:
 # 			elif not self.unspent[n-1].mmid:
-# 				msg('Address #%s is not an %s address. No label can be added to it' %
-# 						(n,g.proj_name))
+# 				msg('Address #{} is not an {} address. No label can be added to it'.format(n,g.proj_name))
 			else:
 			else:
 				while True:
 				while True:
 					s = my_raw_input("Enter label text (or 'q' to return to main menu): ")
 					s = my_raw_input("Enter label text (or 'q' to return to main menu): ")
 					if s == 'q':
 					if s == 'q':
 						return None,None
 						return None,None
 					elif s == '':
 					elif s == '':
-						if keypress_confirm(
-							"Removing label for address #%s.  Is this what you want?" % n):
+						fs = "Removing label for address #{}.  Is this what you want?"
+						if keypress_confirm(fs.format(n)):
 							return n,s
 							return n,s
 					elif s:
 					elif s:
 						if TwComment(s,on_fail='return'):
 						if TwComment(s,on_fail='return'):
@@ -274,7 +272,7 @@ Display options: show [D]ays, [g]roup, show [m]mgen addr, r[e]draw screen
 			elif reply == 'A': self.do_sort('age')
 			elif reply == 'A': self.do_sort('age')
 			elif reply == 'd': self.do_sort('addr')
 			elif reply == 'd': self.do_sort('addr')
 			elif reply == 'D': self.show_days = not self.show_days
 			elif reply == 'D': self.show_days = not self.show_days
-			elif reply == 'e': msg('\n%s\n%s\n%s' % (self.fmt_display,prompt,p))
+			elif reply == 'e': msg('\n{}\n{}\n{}'.format(self.fmt_display,prompt,p))
 			elif reply == 'g': self.group = not self.group
 			elif reply == 'g': self.group = not self.group
 			elif reply == 'l':
 			elif reply == 'l':
 				idx,lbl = self.get_idx_and_label_from_user()
 				idx,lbl = self.get_idx_and_label_from_user()
@@ -283,17 +281,17 @@ Display options: show [D]ays, [g]roup, show [m]mgen addr, r[e]draw screen
 					if type(self).add_label(e.twmmid,lbl,addr=e.addr):
 					if type(self).add_label(e.twmmid,lbl,addr=e.addr):
 						self.get_unspent_data()
 						self.get_unspent_data()
 						self.do_sort()
 						self.do_sort()
-						msg('%s\n%s\n%s' % (self.fmt_display,prompt,p))
+						msg('{}\n{}\n{}'.format(self.fmt_display,prompt,p))
 					else:
 					else:
-						msg('Label could not be added\n%s\n%s' % (prompt,p))
+						msg('Label could not be added\n{}\n{}'.format(prompt,p))
 			elif reply == 'M': self.do_sort('mmid'); self.show_mmid = True
 			elif reply == 'M': self.do_sort('mmid'); self.show_mmid = True
 			elif reply == 'm': self.show_mmid = not self.show_mmid
 			elif reply == 'm': self.show_mmid = not self.show_mmid
 			elif reply == 'p':
 			elif reply == 'p':
 				msg('')
 				msg('')
-				of = 'listunspent[%s].out' % ','.join(self.sort_info(include_group=False)).lower()
+				of = 'listunspent[{}].out'.format(','.join(self.sort_info(include_group=False))).lower()
 				write_data_to_file(of,self.format_for_printing(),'unspent outputs listing')
 				write_data_to_file(of,self.format_for_printing(),'unspent outputs listing')
-				m = yellow("Data written to '%s'" % of)
-				msg('\n%s\n%s\n\n%s' % (self.fmt_display,m,prompt))
+				m = yellow("Data written to '{}'".format(of))
+				msg('\n{}\n{}\n\n{}'.format(self.fmt_display,m,prompt))
 				continue
 				continue
 			elif reply == 'q': return self.unspent
 			elif reply == 'q': return self.unspent
 			elif reply == 'r': self.unspent.reverse(); self.reverse = not self.reverse
 			elif reply == 'r': self.unspent.reverse(); self.reverse = not self.reverse

+ 7 - 6
mmgen/tx.py

@@ -87,7 +87,7 @@ def select_unspent(unspent,prompt):
 			if selected:
 			if selected:
 				if selected[-1] <= len(unspent):
 				if selected[-1] <= len(unspent):
 					return selected
 					return selected
-				msg('Unspent output number must be <= %s' % len(unspent))
+				msg('Unspent output number must be <= {}'.format(len(unspent)))
 
 
 def mmaddr2coinaddr(mmaddr,ad_w,ad_f):
 def mmaddr2coinaddr(mmaddr,ad_w,ad_f):
 
 
@@ -381,12 +381,13 @@ class MMGenTX(MMGenObject):
 		d = g.rpch.decoderawtransaction(self.hex)
 		d = g.rpch.decoderawtransaction(self.hex)
 		vsize = d['vsize'] if 'vsize' in d else d['size']
 		vsize = d['vsize'] if 'vsize' in d else d['size']
 		vmsg('\nSize: {}, Vsize: {} (true) {} (estimated)'.format(d['size'],vsize,est_vsize))
 		vmsg('\nSize: {}, Vsize: {} (true) {} (estimated)'.format(d['size'],vsize,est_vsize))
-		m1 = 'Estimated transaction vsize is {:1.2f} times the true vsize\n'
+		m1 = '\nERROR: Estimated transaction vsize is {:1.2f} times the true vsize\n'
 		m2 = 'Your transaction fee estimates will be inaccurate\n'
 		m2 = 'Your transaction fee estimates will be inaccurate\n'
 		m3 = 'Please re-create and re-sign the transaction using the option --vsize-adj={:1.2f}'
 		m3 = 'Please re-create and re-sign the transaction using the option --vsize-adj={:1.2f}'
 		# allow for 5% error
 		# allow for 5% error
 		ratio = float(est_vsize) / vsize
 		ratio = float(est_vsize) / vsize
-		assert 0.95 < ratio < 1.05, (m1+m2+m3).format(ratio,1/ratio)
+		if not (0.95 < ratio < 1.05):
+			die(2,(m1+m2+m3).format(ratio,1/ratio))
 
 
 	# https://bitcoin.stackexchange.com/questions/1195/how-to-calculate-transaction-size-before-sending
 	# https://bitcoin.stackexchange.com/questions/1195/how-to-calculate-transaction-size-before-sending
 	# 180: uncompressed, 148: compressed
 	# 180: uncompressed, 148: compressed
@@ -847,7 +848,7 @@ class MMGenTX(MMGenObject):
 			return True
 			return True
 
 
 	def write_txid_to_file(self,ask_write=False,ask_write_default_yes=True):
 	def write_txid_to_file(self,ask_write=False,ask_write_default_yes=True):
-		fn = '%s[%s].%s' % (self.txid,self.send_amt,self.txid_ext)
+		fn = '{}[{}].{}'.format(self.txid,self.send_amt,self.txid_ext)
 		write_data_to_file(fn,self.coin_txid+'\n','transaction ID',
 		write_data_to_file(fn,self.coin_txid+'\n','transaction ID',
 			ask_write=ask_write,
 			ask_write=ask_write,
 			ask_write_default_yes=ask_write_default_yes)
 			ask_write_default_yes=ask_write_default_yes)
@@ -968,7 +969,7 @@ class MMGenTX(MMGenObject):
 		enl = ('\n','')[bool(terse)]
 		enl = ('\n','')[bool(terse)]
 		out += enl
 		out += enl
 		if self.label:
 		if self.label:
-			out += 'Comment: %s\n%s' % (self.label.hl(),enl)
+			out += u'Comment: {}\n{}'.format(self.label.hl(),enl)
 		out += 'Inputs:\n' + enl + format_io(self.inputs)
 		out += 'Inputs:\n' + enl + format_io(self.inputs)
 		out += 'Outputs:\n' + enl + format_io(self.outputs)
 		out += 'Outputs:\n' + enl + format_io(self.outputs)
 
 
@@ -1125,7 +1126,7 @@ class MMGenTX(MMGenObject):
 					coin_addr = mmaddr2coinaddr(a1,ad_w,ad_f) if is_mmgen_id(a1) else CoinAddr(a1)
 					coin_addr = mmaddr2coinaddr(a1,ad_w,ad_f) if is_mmgen_id(a1) else CoinAddr(a1)
 					self.add_output(coin_addr,g.proto.coin_amt(a2))
 					self.add_output(coin_addr,g.proto.coin_amt(a2))
 				else:
 				else:
-					die(2,"%s: invalid subargument in command-line argument '%s'" % (a1,a))
+					die(2,"{}: invalid subargument in command-line argument '{}'".format(a1,a))
 			elif is_mmgen_id(a) or is_coin_addr(a):
 			elif is_mmgen_id(a) or is_coin_addr(a):
 				if self.get_chg_output_idx() != None:
 				if self.get_chg_output_idx() != None:
 					die(2,'ERROR: More than one change address listed on command line')
 					die(2,'ERROR: More than one change address listed on command line')

+ 5 - 5
mmgen/txsign.py

@@ -49,11 +49,11 @@ def get_seed_for_seed_id(sid,infiles,saved_seeds):
 		if infiles:
 		if infiles:
 			ss = SeedSource(infiles.pop(0),ignore_in_fmt=True)
 			ss = SeedSource(infiles.pop(0),ignore_in_fmt=True)
 		elif opt.in_fmt:
 		elif opt.in_fmt:
-			qmsg('Need seed data for Seed ID %s' % sid)
+			qmsg('Need seed data for Seed ID {}'.format(sid))
 			ss = SeedSource()
 			ss = SeedSource()
-			msg('User input produced Seed ID %s' % ss.seed.sid)
+			msg('User input produced Seed ID {}'.format(ss.seed.sid))
 		else:
 		else:
-			die(2,'ERROR: No seed source found for Seed ID: %s' % sid)
+			die(2,'ERROR: No seed source found for Seed ID: {}'.format(sid))
 
 
 		saved_seeds[ss.seed.sid] = ss.seed
 		saved_seeds[ss.seed.sid] = ss.seed
 		if ss.seed.sid == sid: return ss.seed
 		if ss.seed.sid == sid: return ss.seed
@@ -61,7 +61,7 @@ def get_seed_for_seed_id(sid,infiles,saved_seeds):
 def generate_kals_for_mmgen_addrs(need_keys,infiles,saved_seeds):
 def generate_kals_for_mmgen_addrs(need_keys,infiles,saved_seeds):
 	mmids = [e.mmid for e in need_keys]
 	mmids = [e.mmid for e in need_keys]
 	sids = set(i.sid for i in mmids)
 	sids = set(i.sid for i in mmids)
-	vmsg('Need seed%s: %s' % (suf(sids,'s'),' '.join(sids)))
+	vmsg('Need seed{}: {}'.format(suf(sids,'s'),' '.join(sids)))
 	d = MMGenList()
 	d = MMGenList()
 	from mmgen.addr import KeyAddrList
 	from mmgen.addr import KeyAddrList
 	for sid in sids:
 	for sid in sids:
@@ -95,7 +95,7 @@ def add_keys(tx,src,infiles=None,saved_seeds=None,keyaddr_list=None):
 					else:
 					else:
 						die(3,wmsg['mapping_error'].format(m1,mmid,f.addr,'tx file:',e.mmid,e.addr))
 						die(3,wmsg['mapping_error'].format(m1,mmid,f.addr,'tx file:',e.mmid,e.addr))
 	if new_keys:
 	if new_keys:
-		vmsg('Added %s wif key%s from %s' % (len(new_keys),suf(new_keys,'s'),desc))
+		vmsg('Added {} wif key{} from {}'.format(len(new_keys),suf(new_keys,'s'),desc))
 	return new_keys
 	return new_keys
 
 
 def _pop_and_return(args,cmplist): # strips found args
 def _pop_and_return(args,cmplist): # strips found args

+ 44 - 48
mmgen/util.py

@@ -31,6 +31,8 @@ def msg_r(s):  sys.stderr.write(s.encode('utf8'))
 def Msg(s):    sys.stdout.write(s.encode('utf8') + '\n')
 def Msg(s):    sys.stdout.write(s.encode('utf8') + '\n')
 def Msg_r(s):  sys.stdout.write(s.encode('utf8'))
 def Msg_r(s):  sys.stdout.write(s.encode('utf8'))
 def msgred(s): msg(red(s))
 def msgred(s): msg(red(s))
+def rmsg(s):   msg(red(s))
+def rmsg_r(s): msg_r(red(s))
 def ymsg(s):   msg(yellow(s))
 def ymsg(s):   msg(yellow(s))
 def ymsg_r(s): msg_r(yellow(s))
 def ymsg_r(s): msg_r(yellow(s))
 def gmsg(s):   msg(green(s))
 def gmsg(s):   msg(green(s))
@@ -107,11 +109,11 @@ def parse_nbytes(nbytes):
 				if k == m.group(2):
 				if k == m.group(2):
 					return int(m.group(1)) * v
 					return int(m.group(1)) * v
 			else:
 			else:
-				msg("Valid byte specifiers: '%s'" % "' '".join([i[0] for i in smap]))
+				msg("Valid byte specifiers: '{}'".format("' '".join([i[0] for i in smap])))
 		else:
 		else:
 			return int(nbytes)
 			return int(nbytes)
 
 
-	die(1,"'%s': invalid byte specifier" % nbytes)
+	die(1,"'{}': invalid byte specifier".format(nbytes))
 
 
 def check_or_create_dir(path):
 def check_or_create_dir(path):
 	try:
 	try:
@@ -152,7 +154,7 @@ def suf(arg,suf_type='s'):
 	elif any(issubclass(t,c) for c in (list,tuple,set,dict)):
 	elif any(issubclass(t,c) for c in (list,tuple,set,dict)):
 		n = len(arg)
 		n = len(arg)
 	else:
 	else:
-		die(2,'%s: invalid parameter for suf()' % arg)
+		die(2,'{}: invalid parameter for suf()'.format(arg))
 	return suf_types[suf_type][n==1]
 	return suf_types[suf_type][n==1]
 
 
 def get_extension(f):
 def get_extension(f):
@@ -300,13 +302,13 @@ class baseconv(object):
 	def check_wordlist(cls,wl_id):
 	def check_wordlist(cls,wl_id):
 
 
 		wl = baseconv.digits[wl_id]
 		wl = baseconv.digits[wl_id]
-		Msg('Wordlist: %s\nLength: %i words' % (capfirst(wl_id),len(wl)))
+		Msg('Wordlist: {}\nLength: {} words'.format(capfirst(wl_id),len(wl)))
 		new_chksum = cls.get_wordlist_chksum(wl_id)
 		new_chksum = cls.get_wordlist_chksum(wl_id)
 
 
 		a,b = 'generated checksum','saved checksum'
 		a,b = 'generated checksum','saved checksum'
 		compare_chksums(new_chksum,a,cls.wl_chksums[wl_id],b,die_on_fail=True)
 		compare_chksums(new_chksum,a,cls.wl_chksums[wl_id],b,die_on_fail=True)
 
 
-		Msg('Checksum %s matches' % new_chksum)
+		Msg('Checksum {} matches'.format(new_chksum))
 		Msg('List is sorted') if tuple(sorted(wl)) == wl else die(3,'ERROR: List is not sorted!')
 		Msg('List is sorted') if tuple(sorted(wl)) == wl else die(3,'ERROR: List is not sorted!')
 
 
 
 
@@ -330,7 +332,7 @@ class baseconv(object):
 
 
 		hexnum = hexnum.strip()
 		hexnum = hexnum.strip()
 		if not is_hex_str(hexnum):
 		if not is_hex_str(hexnum):
-			die(2,"'%s': not a hexadecimal number" % hexnum)
+			die(2,"'{}': not a hexadecimal number".format(hexnum))
 
 
 		wl = cls.digits[wl_id]
 		wl = cls.digits[wl_id]
 		base = len(wl)
 		base = len(wl)
@@ -378,7 +380,7 @@ def pretty_hexdump(data,gw=2,cols=8,line_nums=False):
 
 
 def decode_pretty_hexdump(data):
 def decode_pretty_hexdump(data):
 	from string import hexdigits
 	from string import hexdigits
-	pat = r'^[%s]+:\s+' % hexdigits
+	pat = r'^[{}]+:\s+'.format(hexdigits)
 	lines = [re.sub(pat,'',l) for l in data.splitlines()]
 	lines = [re.sub(pat,'',l) for l in data.splitlines()]
 	try:
 	try:
 		return unhexlify(''.join((''.join(lines).split())))
 		return unhexlify(''.join((''.join(lines).split())))
@@ -405,27 +407,26 @@ def get_hash_params(hash_preset):
 	if hash_preset in g.hash_presets:
 	if hash_preset in g.hash_presets:
 		return g.hash_presets[hash_preset] # N,p,r,buflen
 		return g.hash_presets[hash_preset] # N,p,r,buflen
 	else: # Shouldn't be here
 	else: # Shouldn't be here
-		die(3,"%s: invalid 'hash_preset' value" % hash_preset)
+		die(3,"{}: invalid 'hash_preset' value".format(hash_preset))
 
 
 def compare_chksums(chk1,desc1,chk2,desc2,hdr='',die_on_fail=False,verbose=False):
 def compare_chksums(chk1,desc1,chk2,desc2,hdr='',die_on_fail=False,verbose=False):
 
 
 	if not chk1 == chk2:
 	if not chk1 == chk2:
-		m = "%s ERROR: %s checksum (%s) doesn't match %s checksum (%s)"\
-				% ((hdr+':\n   ' if hdr else 'CHECKSUM'),desc2,chk2,desc1,chk1)
+		fs = "{} ERROR: {} checksum ({}) doesn't match {} checksum ({})"
+		m = fs.format((hdr+':\n   ' if hdr else 'CHECKSUM'),desc2,chk2,desc1,chk1)
 		if die_on_fail:
 		if die_on_fail:
 			die(3,m)
 			die(3,m)
 		else:
 		else:
 			vmsg(m,force=verbose)
 			vmsg(m,force=verbose)
 			return False
 			return False
 
 
-	vmsg('%s checksum OK (%s)' % (capfirst(desc1),chk1))
+	vmsg('{} checksum OK ({})'.format(capfirst(desc1),chk1))
 	return True
 	return True
 
 
 def compare_or_die(val1, desc1, val2, desc2, e='Error'):
 def compare_or_die(val1, desc1, val2, desc2, e='Error'):
 	if cmp(val1,val2):
 	if cmp(val1,val2):
-		die(3,"%s: %s (%s) doesn't match %s (%s)"
-				% (e,desc2,val2,desc1,val1))
-	dmsg('%s OK (%s)' % (capfirst(desc2),val2))
+		die(3,"{}: {} ({}) doesn't match {} ({})".format(e,desc2,val2,desc1,val1))
+	dmsg('{} OK ({})'.format(capfirst(desc2),val2))
 	return True
 	return True
 
 
 def open_file_or_exit(filename,mode,silent=False):
 def open_file_or_exit(filename,mode,silent=False):
@@ -450,16 +451,15 @@ def check_file_type_and_access(fname,ftype,blkdev_ok=False):
 
 
 	try: mode = os.stat(fname).st_mode
 	try: mode = os.stat(fname).st_mode
 	except:
 	except:
-		die(1,"Unable to stat requested %s '%s'" % (ftype,fname))
+		die(1,"Unable to stat requested {} '{}'".format(ftype,fname))
 
 
 	for t in ok_types:
 	for t in ok_types:
 		if t[0](mode): break
 		if t[0](mode): break
 	else:
 	else:
-		die(1,"Requested %s '%s' is not a %s" % (ftype,fname,
-				' or '.join([t[1] for t in ok_types])))
+		die(1,"Requested {} '{}' is not a {}".format(ftype,fname,' or '.join([t[1] for t in ok_types])))
 
 
 	if not os.access(fname, access):
 	if not os.access(fname, access):
-		die(1,"Requested %s '%s' is not %sable by you" % (ftype,fname,m))
+		die(1,"Requested {} '{}' is not {}able by you".format(ftype,fname,m))
 
 
 	return True
 	return True
 
 
@@ -506,23 +506,21 @@ def get_new_passphrase(desc,passchg=False):
 		for i in range(g.passwd_max_tries):
 		for i in range(g.passwd_max_tries):
 			pw = ' '.join(get_words_from_user('Enter {}: '.format(w)))
 			pw = ' '.join(get_words_from_user('Enter {}: '.format(w)))
 			pw2 = ' '.join(get_words_from_user('Repeat passphrase: '))
 			pw2 = ' '.join(get_words_from_user('Repeat passphrase: '))
-			dmsg('Passphrases: [%s] [%s]' % (pw,pw2))
+			dmsg('Passphrases: [{}] [{}]'.format(pw,pw2))
 			if pw == pw2:
 			if pw == pw2:
 				vmsg('Passphrases match'); break
 				vmsg('Passphrases match'); break
 			else: msg('Passphrases do not match.  Try again.')
 			else: msg('Passphrases do not match.  Try again.')
 		else:
 		else:
-			die(2,'User failed to duplicate passphrase in %s attempts' %
-					g.passwd_max_tries)
+			die(2,'User failed to duplicate passphrase in {} attempts'.format(g.passwd_max_tries))
 
 
 	if pw == '': qmsg('WARNING: Empty passphrase')
 	if pw == '': qmsg('WARNING: Empty passphrase')
 	return pw
 	return pw
 
 
-def confirm_or_exit(message,question,expect='YES',exit_msg='Exiting at user request'):
+def confirm_or_exit(message,q,expect='YES',exit_msg='Exiting at user request'):
 	m = message.strip()
 	m = message.strip()
 	if m: msg(m)
 	if m: msg(m)
-	a = question+'  ' if question[0].isupper() else \
-			'Are you sure you want to %s?\n' % question
-	b = "Type uppercase '%s' to confirm: " % expect
+	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:
 	if my_raw_input(a+b).strip() != expect:
 		die(1,exit_msg)
 		die(1,exit_msg)
 
 
@@ -553,22 +551,22 @@ def write_data_to_file(
 		qmsg('Output to STDOUT requested')
 		qmsg('Output to STDOUT requested')
 		if sys.stdout.isatty():
 		if sys.stdout.isatty():
 			if no_tty:
 			if no_tty:
-				die(2,'Printing %s to screen is not allowed' % desc)
+				die(2,'Printing {} to screen is not allowed'.format(desc))
 			if (ask_tty and not opt.quiet) or binary:
 			if (ask_tty and not opt.quiet) or binary:
-				confirm_or_exit('','output %s to screen' % desc)
+				confirm_or_exit('','output {} to screen'.format(desc))
 		else:
 		else:
-			try:    of = os.readlink('/proc/%d/fd/1' % os.getpid()) # Linux
+			try:    of = os.readlink('/proc/{}/fd/1'.format(os.getpid())) # Linux
 			except: of = None # Windows
 			except: of = None # Windows
 
 
 			if of:
 			if of:
 				if of[:5] == 'pipe:':
 				if of[:5] == 'pipe:':
 					if no_tty:
 					if no_tty:
-						die(2,'Writing %s to pipe is not allowed' % desc)
+						die(2,'Writing {} to pipe is not allowed'.format(desc))
 					if ask_tty and not opt.quiet:
 					if ask_tty and not opt.quiet:
-						confirm_or_exit('','output %s to pipe' % desc)
+						confirm_or_exit('','output {} to pipe'.format(desc))
 						msg('')
 						msg('')
 				of2,pd = os.path.relpath(of),os.path.pardir
 				of2,pd = os.path.relpath(of),os.path.pardir
-				msg("Redirecting output to file '%s'" % (of2,of)[of2[:len(pd)] == pd])
+				msg("Redirecting output to file '{}'".format((of2,of)[of2[:len(pd)] == pd]))
 			else:
 			else:
 				msg('Redirecting output to file')
 				msg('Redirecting output to file')
 
 
@@ -583,27 +581,27 @@ def write_data_to_file(
 			outfile = make_full_path(opt.outdir,outfile)
 			outfile = make_full_path(opt.outdir,outfile)
 
 
 		if ask_write:
 		if ask_write:
-			if not ask_write_prompt: ask_write_prompt = 'Save %s?' % desc
+			if not ask_write_prompt: ask_write_prompt = 'Save {}?'.format(desc)
 			if not keypress_confirm(ask_write_prompt,
 			if not keypress_confirm(ask_write_prompt,
 						default_yes=ask_write_default_yes):
 						default_yes=ask_write_default_yes):
-				die(1,'%s not saved' % capfirst(desc))
+				die(1,'{} not saved'.format(capfirst(desc)))
 
 
 		hush = False
 		hush = False
 		if file_exists(outfile) and ask_overwrite:
 		if file_exists(outfile) and ask_overwrite:
-			q = "File '%s' already exists\nOverwrite?" % outfile
+			q = "File '{}' already exists\nOverwrite?".format(outfile)
 			confirm_or_exit('',q)
 			confirm_or_exit('',q)
-			msg("Overwriting file '%s'" % outfile)
+			msg("Overwriting file '{}'".format(outfile))
 			hush = True
 			hush = True
 
 
 		f = open_file_or_exit(outfile,('w','wb')[bool(binary)])
 		f = open_file_or_exit(outfile,('w','wb')[bool(binary)])
 		try:
 		try:
 			f.write(data)
 			f.write(data)
 		except:
 		except:
-			die(2,"Failed to write %s to file '%s'" % (desc,outfile))
+			die(2,"Failed to write {} to file '{}'".format(desc,outfile))
 		f.close
 		f.close
 
 
 		if not (hush or silent):
 		if not (hush or silent):
-			msg("%s written to file '%s'" % (capfirst(desc),outfile))
+			msg(u"{} written to file '{}'".format(capfirst(desc),outfile))
 
 
 		return True
 		return True
 
 
@@ -617,21 +615,19 @@ def write_data_to_file(
 def get_words_from_user(prompt):
 def get_words_from_user(prompt):
 	# split() also strips
 	# split() also strips
 	words = my_raw_input(prompt, echo=opt.echo_passphrase).split()
 	words = my_raw_input(prompt, echo=opt.echo_passphrase).split()
-	dmsg('Sanitized input: [%s]' % ' '.join(words))
+	dmsg('Sanitized input: [{}]'.format(' '.join(words)))
 	return words
 	return words
 
 
-
 def get_words_from_file(infile,desc,silent=False):
 def get_words_from_file(infile,desc,silent=False):
 	if not silent:
 	if not silent:
-		qmsg("Getting %s from file '%s'" % (desc,infile))
+		qmsg(u"Getting {} from file '{}'".format(desc,infile))
 	f = open_file_or_exit(infile, 'r')
 	f = open_file_or_exit(infile, 'r')
 	# split() also strips
 	# split() also strips
 	words = f.read().split()
 	words = f.read().split()
 	f.close()
 	f.close()
-	dmsg('Sanitized input: [%s]' % ' '.join(words))
+	dmsg('Sanitized input: [{}]'.format(' '.join(words)))
 	return words
 	return words
 
 
-
 def get_words(infile,desc,prompt):
 def get_words(infile,desc,prompt):
 	if infile:
 	if infile:
 		return get_words_from_file(infile,desc)
 		return get_words_from_file(infile,desc)
@@ -643,7 +639,7 @@ def mmgen_decrypt_file_maybe(fn,desc='',silent=False):
 	have_enc_ext = get_extension(fn) == g.mmenc_ext
 	have_enc_ext = get_extension(fn) == g.mmenc_ext
 	if have_enc_ext or not is_utf8(d):
 	if have_enc_ext or not is_utf8(d):
 		m = ('Attempting to decrypt','Decrypting')[have_enc_ext]
 		m = ('Attempting to decrypt','Decrypting')[have_enc_ext]
-		msg("%s %s '%s'" % (m,desc,fn))
+		msg("{} {} '{}'".format(m,desc,fn))
 		from mmgen.crypto import mmgen_decrypt_retry
 		from mmgen.crypto import mmgen_decrypt_retry
 		d = mmgen_decrypt_retry(d,desc)
 		d = mmgen_decrypt_retry(d,desc)
 	return d
 	return d
@@ -658,13 +654,13 @@ def get_lines_from_file(fn,desc='',trim_comments=False,silent=False):
 def get_data_from_user(desc='data',silent=False):
 def get_data_from_user(desc='data',silent=False):
 	p = ('','Enter {}: '.format(desc))[g.stdin_tty]
 	p = ('','Enter {}: '.format(desc))[g.stdin_tty]
 	data = my_raw_input(p,echo=opt.echo_passphrase)
 	data = my_raw_input(p,echo=opt.echo_passphrase)
-	dmsg('User input: [%s]' % data)
+	dmsg('User input: [{}]'.format(data))
 	return data
 	return data
 
 
 def get_data_from_file(infile,desc='data',dash=False,silent=False,binary=False):
 def get_data_from_file(infile,desc='data',dash=False,silent=False,binary=False):
 	if dash and infile == '-': return sys.stdin.read()
 	if dash and infile == '-': return sys.stdin.read()
 	if not opt.quiet and not silent and desc:
 	if not opt.quiet and not silent and desc:
-		qmsg("Getting %s from file '%s'" % (desc,infile))
+		qmsg(u"Getting {} from file '{}'".format(desc,infile))
 	f = open_file_or_exit(infile,('r','rb')[bool(binary)],silent=silent)
 	f = open_file_or_exit(infile,('r','rb')[bool(binary)],silent=silent)
 	data = f.read()
 	data = f.read()
 	f.close()
 	f.close()
@@ -672,7 +668,7 @@ def get_data_from_file(infile,desc='data',dash=False,silent=False,binary=False):
 
 
 def pwfile_reuse_warning():
 def pwfile_reuse_warning():
 	if 'passwd_file_used' in globals():
 	if 'passwd_file_used' in globals():
-		qmsg("Reusing passphrase from file '%s' at user request" % opt.passwd_file)
+		qmsg(u"Reusing passphrase from file '{}' at user request".format(opt.passwd_file))
 		return True
 		return True
 	globals()['passwd_file_used'] = True
 	globals()['passwd_file_used'] = True
 	return False
 	return False
@@ -736,7 +732,7 @@ def prompt_and_get_char(prompt,chars,enter_ok=False,verbose=False):
 	from mmgen.term import get_char
 	from mmgen.term import get_char
 
 
 	while True:
 	while True:
-		reply = get_char('%s: ' % prompt).strip('\n\r')
+		reply = get_char('{}: '.format(prompt)).strip('\n\r')
 
 
 		if reply in chars or (enter_ok and not reply):
 		if reply in chars or (enter_ok and not reply):
 			msg('')
 			msg('')
@@ -777,7 +773,7 @@ def do_license_msg(immed=False):
 
 
 	p = "Press 'w' for conditions and warranty info, or 'c' to continue:"
 	p = "Press 'w' for conditions and warranty info, or 'c' to continue:"
 	msg(gpl.warning)
 	msg(gpl.warning)
-	prompt = '%s ' % p.strip()
+	prompt = '{} '.format(p.strip())
 
 
 	from mmgen.term import get_char
 	from mmgen.term import get_char
 
 

+ 1 - 2
scripts/compute-file-chksum.py

@@ -22,6 +22,5 @@ start = (1,0)[bool(opt.include_first_line)]
 a = make_chksum_6(' '.join(lines[start:]))
 a = make_chksum_6(' '.join(lines[start:]))
 if start == 1:
 if start == 1:
 	b = lines[0]
 	b = lines[0]
-	m = ("Checksum in file (%s) doesn't match computed value!" % b,'Checksum in file OK')[a==b]
-	msg(m)
+	msg(("Checksum in file ({}) doesn't match computed value!".format(b),'Checksum in file OK')[a==b])
 Msg(a)
 Msg(a)

+ 1 - 1
scripts/tx-v1-to-v3.py

@@ -86,7 +86,7 @@ def find_block_by_time(timestamp):
 			bot = block_num
 			bot = block_num
 		block_num = (top + bot) / 2
 		block_num = (top + bot) / 2
 		if top - bot < 2:
 		if top - bot < 2:
-			msg('\nFound: %s ' % block_num)
+			msg('\nFound: {} '.format(block_num))
 			break
 			break
 
 
 	return block_num
 	return block_num

+ 7 - 7
test/gentest.py

@@ -170,7 +170,7 @@ def compare_test():
 
 
 	for i in range(rounds):
 	for i in range(rounds):
 		if opt.verbose or time.time() - last_t >= 0.1:
 		if opt.verbose or time.time() - last_t >= 0.1:
-			qmsg_r('\rRound %s/%s ' % (i+1,rounds))
+			qmsg_r('\rRound {}/{} '.format(i+1,rounds))
 			last_t = time.time()
 			last_t = time.time()
 		sec = PrivKey(os.urandom(32),compressed=addr_type.compressed,pubkey_type=addr_type.pubkey_type)
 		sec = PrivKey(os.urandom(32),compressed=addr_type.compressed,pubkey_type=addr_type.pubkey_type)
 		ph = kg_a.to_pubhex(sec)
 		ph = kg_a.to_pubhex(sec)
@@ -188,10 +188,10 @@ def compare_test():
 				match_error(sec,sec.wif,sec.wif,b_wif,a,b)
 				match_error(sec,sec.wif,sec.wif,b_wif,a,b)
 		else:
 		else:
 			b_addr = ag.to_addr(kg_b.to_pubhex(sec))
 			b_addr = ag.to_addr(kg_b.to_pubhex(sec))
-		vmsg('\nkey:  %s\naddr: %s\n' % (sec.wif,a_addr))
+		vmsg('\nkey:  {}\naddr: {}\n'.format(sec.wif,a_addr))
 		if a_addr != b_addr:
 		if a_addr != b_addr:
 			match_error(sec,sec.wif,a_addr,b_addr,a,ext_lib if b == 'ext' else b)
 			match_error(sec,sec.wif,a_addr,b_addr,a,ext_lib if b == 'ext' else b)
-	qmsg_r('\rRound %s/%s ' % (i+1,rounds))
+	qmsg_r('\rRound {}/{} '.format(i+1,rounds))
 	qmsg(green(('\n','')[bool(opt.verbose)] + 'OK'))
 	qmsg(green(('\n','')[bool(opt.verbose)] + 'OK'))
 
 
 def speed_test():
 def speed_test():
@@ -206,19 +206,19 @@ def speed_test():
 
 
 	for i in range(rounds):
 	for i in range(rounds):
 		if time.time() - last_t >= 0.1:
 		if time.time() - last_t >= 0.1:
-			qmsg_r('\rRound %s/%s ' % (i+1,rounds))
+			qmsg_r('\rRound {}/{} '.format(i+1,rounds))
 			last_t = time.time()
 			last_t = time.time()
 		sec = PrivKey(seed+pack('I',i),compressed=addr_type.compressed,pubkey_type=addr_type.pubkey_type)
 		sec = PrivKey(seed+pack('I',i),compressed=addr_type.compressed,pubkey_type=addr_type.pubkey_type)
 		a_addr = ag.to_addr(kg_a.to_pubhex(sec))
 		a_addr = ag.to_addr(kg_a.to_pubhex(sec))
-		vmsg('\nkey:  %s\naddr: %s\n' % (sec.wif,a_addr))
-	qmsg_r('\rRound %s/%s ' % (i+1,rounds))
+		vmsg('\nkey:  {}\naddr: {}\n'.format(sec.wif,a_addr))
+	qmsg_r('\rRound {}/{} '.format(i+1,rounds))
 	qmsg('\n{} addresses generated in {:.2f} seconds'.format(rounds,time.time()-start))
 	qmsg('\n{} addresses generated in {:.2f} seconds'.format(rounds,time.time()-start))
 
 
 def dump_test():
 def dump_test():
 	m = "Comparing output of address generator '{}' against wallet dump '{}'"
 	m = "Comparing output of address generator '{}' against wallet dump '{}'"
 	qmsg(green(m.format(kg_a.desc,cmd_args[1])))
 	qmsg(green(m.format(kg_a.desc,cmd_args[1])))
 	for n,[wif,a_addr] in enumerate(dump,1):
 	for n,[wif,a_addr] in enumerate(dump,1):
-		qmsg_r('\rKey %s/%s ' % (n,len(dump)))
+		qmsg_r('\rKey {}/{} '.format(n,len(dump)))
 		try:
 		try:
 			sec = PrivKey(wif=wif)
 			sec = PrivKey(wif=wif)
 		except:
 		except:

+ 23 - 24
test/mmgen_pexpect.py

@@ -46,14 +46,14 @@ def my_send(p,t,delay=send_delay,s=False):
 	if opt.verbose:
 	if opt.verbose:
 		ls = (' ','')[bool(opt.debug or not s)]
 		ls = (' ','')[bool(opt.debug or not s)]
 		es = ('  ','')[bool(s)]
 		es = ('  ','')[bool(s)]
-		msg('%sSEND %s%s' % (ls,es,yellow("'%s'"%t.replace('\n',r'\n'))))
+		msg('{}SEND {}{}'.format(ls,es,yellow("'{}'"%t.replace('\n',r'\n'))))
 	return ret
 	return ret
 
 
 def my_expect(p,s,t='',delay=send_delay,regex=False,nonl=False,silent=False):
 def my_expect(p,s,t='',delay=send_delay,regex=False,nonl=False,silent=False):
 	quo = ('',"'")[type(s) == str]
 	quo = ('',"'")[type(s) == str]
 
 
 	if not silent:
 	if not silent:
-		if opt.verbose: msg_r('EXPECT %s' % yellow(quo+str(s)+quo))
+		if opt.verbose: msg_r('EXPECT {}'.format(yellow(quo+str(s)+quo)))
 		elif not opt.exact_output: msg_r('+')
 		elif not opt.exact_output: msg_r('+')
 
 
 	try:
 	try:
@@ -63,14 +63,15 @@ def my_expect(p,s,t='',delay=send_delay,regex=False,nonl=False,silent=False):
 			ret = f(s,timeout=(60,5)[bool(opt.debug_pexpect)])
 			ret = f(s,timeout=(60,5)[bool(opt.debug_pexpect)])
 	except pexpect.TIMEOUT:
 	except pexpect.TIMEOUT:
 		if opt.debug_pexpect: raise
 		if opt.debug_pexpect: raise
-		errmsg(red('\nERROR.  Expect %s%s%s timed out.  Exiting' % (quo,s,quo)))
+		errmsg(red('\nERROR.  Expect {}{}{} timed out.  Exiting'.format(quo,s,quo)))
 		sys.exit(1)
 		sys.exit(1)
 	debug_pexpect_msg(p)
 	debug_pexpect_msg(p)
 
 
-	if opt.debug or (opt.verbose and type(s) != str): msg_r(' ==> %s ' % ret)
+	if opt.debug or (opt.verbose and type(s) != str):
+		msg_r(' ==> {} '.format(ret))
 
 
 	if ret == -1:
 	if ret == -1:
-		errmsg('Error.  Expect returned %s' % ret)
+		errmsg('Error.  Expect returned {}'.format(ret))
 		sys.exit(1)
 		sys.exit(1)
 	else:
 	else:
 		if t == '':
 		if t == '':
@@ -125,7 +126,7 @@ class MMGenPexpect(object):
 				if not msg_only:
 				if not msg_only:
 					sys.stderr.write(clr1('Executing {}{}'.format(clr2(cmd_str),eol)))
 					sys.stderr.write(clr1('Executing {}{}'.format(clr2(cmd_str),eol)))
 			else:
 			else:
-				m = 'Testing %s: ' % desc
+				m = 'Testing {}: '.format(desc)
 				msg_r(m)
 				msg_r(m)
 
 
 		if msg_only: return
 		if msg_only: return
@@ -136,8 +137,7 @@ class MMGenPexpect(object):
 			f = (call,check_output)[bool(no_output)]
 			f = (call,check_output)[bool(no_output)]
 			ret = f([cmd] + args)
 			ret = f([cmd] + args)
 			if f == call and ret != 0:
 			if f == call and ret != 0:
-				m = 'ERROR: process returned a non-zero exit status (%s)'
-				die(1,red(m % ret))
+				die(1,red('ERROR: process returned a non-zero exit status ({})'.format(ret)))
 		else:
 		else:
 			if opt.traceback:
 			if opt.traceback:
 				cmd,args = g.traceback_cmd,[cmd]+args
 				cmd,args = g.traceback_cmd,[cmd]+args
@@ -162,14 +162,12 @@ class MMGenPexpect(object):
 	def cmp_or_die(self,s,t,skip_ok=False,exit_val=0):
 	def cmp_or_die(self,s,t,skip_ok=False,exit_val=0):
 		ret = self.p.wait()
 		ret = self.p.wait()
 		if ret != exit_val:
 		if ret != exit_val:
-			die(1,red('test.py: spawned program exited with value {}'.format(ret)))
+			rdie(1,'test.py: spawned program exited with value {}'.format(ret))
 		if s == t:
 		if s == t:
 			if not skip_ok: ok()
 			if not skip_ok: ok()
 		else:
 		else:
-			sys.stderr.write(red(
-				'ERROR: recoded data:\n%s\ndiffers from original data:\n%s\n' %
-					(repr(t),repr(s))))
-			sys.exit(3)
+			fs = 'ERROR: recoded data:\n{}\ndiffers from original data:\n{}'
+			rdie(3,fs.format(repr(t),repr(s)))
 
 
 	def license(self):
 	def license(self):
 		if 'MMGEN_NO_LICENSE' in os.environ: return
 		if 'MMGEN_NO_LICENSE' in os.environ: return
@@ -181,8 +179,8 @@ class MMGenPexpect(object):
 		my_expect(self.p,p,label+'\n')
 		my_expect(self.p,p,label+'\n')
 
 
 	def usr_rand_out(self,saved=False):
 	def usr_rand_out(self,saved=False):
-		m = '%suser-supplied entropy' % (('','saved ')[saved])
-		my_expect(self.p,'Generating encryption key from OS random data plus ' + m)
+		fs = 'Generating encryption key from OS random data plus {}user-supplied entropy'
+		my_expect(self.p,fs.format(('','saved ')[saved]))
 
 
 	def usr_rand(self,num_chars):
 	def usr_rand(self,num_chars):
 		if opt.usr_random:
 		if opt.usr_random:
@@ -202,20 +200,21 @@ class MMGenPexpect(object):
 			my_expect(self.p,'ENTER to continue: ','\n')
 			my_expect(self.p,'ENTER to continue: ','\n')
 
 
 	def passphrase_new(self,desc,passphrase):
 	def passphrase_new(self,desc,passphrase):
-		my_expect(self.p,('Enter passphrase for %s: ' % desc), passphrase+'\n')
-		my_expect(self.p,'Repeat passphrase: ', passphrase+'\n')
+		my_expect(self.p,'Enter passphrase for {}: '.format(desc),passphrase+'\n')
+		my_expect(self.p,'Repeat passphrase: ',passphrase+'\n')
 
 
 	def passphrase(self,desc,passphrase,pwtype=''):
 	def passphrase(self,desc,passphrase,pwtype=''):
 		if pwtype: pwtype += ' '
 		if pwtype: pwtype += ' '
-		my_expect(self.p,('Enter %spassphrase for %s.*?: ' % (pwtype,desc)),
+		my_expect(self.p,
+				'Enter {}passphrase for {}.*?: '.format(pwtype,desc),
 				passphrase+'\n',regex=True)
 				passphrase+'\n',regex=True)
 
 
 	def hash_preset(self,desc,preset=''):
 	def hash_preset(self,desc,preset=''):
-		my_expect(self.p,('Enter hash preset for %s' % desc))
-		my_expect(self.p,('or hit ENTER .*?:'), str(preset)+'\n',regex=True)
+		my_expect(self.p,'Enter hash preset for {}'.format(desc))
+		my_expect(self.p,'or hit ENTER .*?:',str(preset)+'\n',regex=True)
 
 
 	def written_to_file(self,desc,overwrite_unlikely=False,query='Overwrite?  ',oo=False):
 	def written_to_file(self,desc,overwrite_unlikely=False,query='Overwrite?  ',oo=False):
-		s1 = '%s written to file ' % desc
+		s1 = '{} written to file '.format(desc)
 		s2 = query + "Type uppercase 'YES' to confirm: "
 		s2 = query + "Type uppercase 'YES' to confirm: "
 		ret = my_expect(self.p,([s1,s2],s1)[overwrite_unlikely])
 		ret = my_expect(self.p,([s1,s2],s1)[overwrite_unlikely])
 		if ret == 1:
 		if ret == 1:
@@ -227,8 +226,8 @@ class MMGenPexpect(object):
 # 				ret = my_expect(self.p,s1)
 # 				ret = my_expect(self.p,s1)
 		self.expect(self.NL,nonl=True)
 		self.expect(self.NL,nonl=True)
 		outfile = self.p.before.strip().strip("'")
 		outfile = self.p.before.strip().strip("'")
-		if opt.debug_pexpect: msgred('Outfile [%s]' % outfile)
-		vmsg('%s file: %s' % (desc,cyan(outfile.replace("'",''))))
+		if opt.debug_pexpect: rmsg('Outfile [{}]'.format(outfile))
+		vmsg('{} file: {}'.format(desc,cyan(outfile.replace("'",''))))
 		return outfile
 		return outfile
 
 
 	def no_overwrite(self):
 	def no_overwrite(self):
@@ -249,7 +248,7 @@ class MMGenPexpect(object):
 		self.expect(self.NL,nonl=True,silent=True)
 		self.expect(self.NL,nonl=True,silent=True)
 		debug_pexpect_msg(self.p)
 		debug_pexpect_msg(self.p)
 		end = self.p.before
 		end = self.p.before
-		vmsg(' ==> %s' % cyan(end))
+		vmsg(' ==> {}'.format(cyan(end)))
 		return end
 		return end
 
 
 	def interactive(self):
 	def interactive(self):

+ 1 - 1
test/scrambletest.py

@@ -111,4 +111,4 @@ run_tests()
 
 
 t = int(time.time()) - start_time
 t = int(time.time()) - start_time
 m = '\nAll requested tests finished OK, elapsed time: {:02}:{:02}'
 m = '\nAll requested tests finished OK, elapsed time: {:02}:{:02}'
-msg(green(m.format(t/60,t%60)))
+gmsg(m.format(t/60,t%60))

+ 56 - 64
test/test.py

@@ -91,14 +91,14 @@ if not any(e in ('--skip-deps','--resume','-S','-r') for e in sys.argv+shortopts
 	else:
 	else:
 		d,pfx = '/dev/shm','mmgen-test-'
 		d,pfx = '/dev/shm','mmgen-test-'
 		try:
 		try:
-			subprocess.call('rm -rf %s/%s*'%(d,pfx),shell=True)
+			subprocess.call('rm -rf {}/{}*'.format(d,pfx),shell=True)
 		except Exception as e:
 		except Exception as e:
-			die(2,'Unable to delete directory tree %s/%s* (%s)'%(d,pfx,e))
+			die(2,'Unable to delete directory tree {}/{}* ({})'.format(d,pfx,e))
 		try:
 		try:
 			import tempfile
 			import tempfile
 			shm_dir = tempfile.mkdtemp('',pfx,d)
 			shm_dir = tempfile.mkdtemp('',pfx,d)
 		except Exception as e:
 		except Exception as e:
-			die(2,'Unable to create temporary directory in %s (%s)'%(d,e))
+			die(2,'Unable to create temporary directory in {} ({})'.format(d,e))
 		dd = os.path.join(shm_dir,'data_dir')
 		dd = os.path.join(shm_dir,'data_dir')
 		os.mkdir(dd,0755)
 		os.mkdir(dd,0755)
 		try: os.unlink(data_dir)
 		try: os.unlink(data_dir)
@@ -851,7 +851,7 @@ for a,b in cmd_group['ref']:
 	for i,j in ((1,128),(2,192),(3,256)):
 	for i,j in ((1,128),(2,192),(3,256)):
 		k = a+str(i)
 		k = a+str(i)
 		cmd_list['ref'].append(k)
 		cmd_list['ref'].append(k)
-		cmd_data[k] = (5+i,'%s (%s-bit)' % (b[1],j),[[b[0],5+i]])
+		cmd_data[k] = (5+i,'{} ({}-bit)'.format(b[1],j),[[b[0],5+i]])
 
 
 cmd_data['info_ref_other'] = 'other reference data',[8]
 cmd_data['info_ref_other'] = 'other reference data',[8]
 for a,b in cmd_group['ref_other']:
 for a,b in cmd_group['ref_other']:
@@ -863,14 +863,14 @@ for a,b in cmd_group['conv_in']:
 	for i,j in ((1,128),(2,192),(3,256)):
 	for i,j in ((1,128),(2,192),(3,256)):
 		k = a+str(i)
 		k = a+str(i)
 		cmd_list['conv_in'].append(k)
 		cmd_list['conv_in'].append(k)
-		cmd_data[k] = (10+i,'%s (%s-bit)' % (b,j),[[[],10+i]])
+		cmd_data[k] = (10+i,'{} ({}-bit)'.format(b,j),[[[],10+i]])
 
 
 cmd_data['info_conv_out'] = 'wallet conversion to reference data',[11,12,13]
 cmd_data['info_conv_out'] = 'wallet conversion to reference data',[11,12,13]
 for a,b in cmd_group['conv_out']:
 for a,b in cmd_group['conv_out']:
 	for i,j in ((1,128),(2,192),(3,256)):
 	for i,j in ((1,128),(2,192),(3,256)):
 		k = a+str(i)
 		k = a+str(i)
 		cmd_list['conv_out'].append(k)
 		cmd_list['conv_out'].append(k)
-		cmd_data[k] = (10+i,'%s (%s-bit)' % (b,j),[[[],10+i]])
+		cmd_data[k] = (10+i,'{} ({}-bit)'.format(b,j),[[[],10+i]])
 
 
 cmd_data['info_regtest'] = 'regtest mode',[17]
 cmd_data['info_regtest'] = 'regtest mode',[17]
 for a,b in cmd_group['regtest']:
 for a,b in cmd_group['regtest']:
@@ -939,10 +939,10 @@ if opt.profile: opt.names = True
 if opt.resume: opt.skip_deps = True
 if opt.resume: opt.skip_deps = True
 if opt.log:
 if opt.log:
 	log_fd = open(log_file,'a')
 	log_fd = open(log_file,'a')
-	log_fd.write('\nLog started: %s\n' % make_timestr())
+	log_fd.write('\nLog started: {}\n'.format(make_timestr()))
 
 
 usr_rand_chars = (5,30)[bool(opt.usr_random)]
 usr_rand_chars = (5,30)[bool(opt.usr_random)]
-usr_rand_arg = '-r%s' % usr_rand_chars
+usr_rand_arg = '-r{}'.format(usr_rand_chars)
 cmd_total = 0
 cmd_total = 0
 
 
 # Disable color in spawned scripts so we can parse their output
 # Disable color in spawned scripts so we can parse their output
@@ -993,8 +993,7 @@ if opt.list_cmds:
 	w = max(map(len,cmd_data))
 	w = max(map(len,cmd_data))
 	for cmd in cmd_data:
 	for cmd in cmd_data:
 		if cmd[:5] == 'info_':
 		if cmd[:5] == 'info_':
-			m = capfirst(cmd_data[cmd][0])
-			Msg(green('  %s:' % m))
+			Msg(green('  {}:'.format(capfirst(cmd_data[cmd][0]))))
 			continue
 			continue
 		Msg('  '+fs.format(cmd,cmd_data[cmd][1],w=w))
 		Msg('  '+fs.format(cmd,cmd_data[cmd][1],w=w))
 
 
@@ -1047,15 +1046,15 @@ def get_addrfile_checksum(display=False):
 	addrfile = get_file_with_ext('addrs',cfg['tmpdir'])
 	addrfile = get_file_with_ext('addrs',cfg['tmpdir'])
 	silence()
 	silence()
 	chk = AddrList(addrfile).chksum
 	chk = AddrList(addrfile).chksum
-	if opt.verbose and display: msg('Checksum: %s' % cyan(chk))
+	if opt.verbose and display: msg('Checksum: {}'.format(cyan(chk)))
 	end_silence()
 	end_silence()
 	return chk
 	return chk
 
 
 def verify_checksum_or_exit(checksum,chk):
 def verify_checksum_or_exit(checksum,chk):
 	if checksum != chk:
 	if checksum != chk:
-		errmsg(red('Checksum error: %s' % chk))
+		errmsg(red('Checksum error: {}'.format(chk)))
 		sys.exit(1)
 		sys.exit(1)
-	vmsg(green('Checksums match: %s') % (cyan(chk)))
+	vmsg(green('Checksums match: ') + cyan(chk))
 
 
 from test.mmgen_pexpect import MMGenPexpect
 from test.mmgen_pexpect import MMGenPexpect
 class MMGenExpect(MMGenPexpect):
 class MMGenExpect(MMGenPexpect):
@@ -1096,7 +1095,7 @@ def create_fake_unspent_entry(coinaddr,al_id=None,idx=None,lbl=None,non_mmgen=Fa
 			else (u'{}:{}{}'.format(al_id,idx,lbl.decode('utf8'))),
 			else (u'{}:{}{}'.format(al_id,idx,lbl.decode('utf8'))),
 		'vout': int(getrandnum(4) % 8),
 		'vout': int(getrandnum(4) % 8),
 		'txid': hexlify(os.urandom(32)).decode('utf8'),
 		'txid': hexlify(os.urandom(32)).decode('utf8'),
-		'amount': g.proto.coin_amt('%s.%s' % (amt1+(getrandnum(4) % amt2), getrandnum(4) % 100000000)),
+		'amount': g.proto.coin_amt('{}.{}'.format(amt1 + getrandnum(4) % amt2, getrandnum(4) % 100000000)),
 		'address': coinaddr,
 		'address': coinaddr,
 		'spendable': False,
 		'spendable': False,
 		'scriptPubKey': '{}{}{}'.format(spk_beg,coinaddr.hex,spk_end),
 		'scriptPubKey': '{}{}{}'.format(spk_beg,coinaddr.hex,spk_end),
@@ -1155,11 +1154,11 @@ def write_fake_data_to_file(d):
 	unspent_data_file = os.path.join(cfg['tmpdir'],'unspent.json')
 	unspent_data_file = os.path.join(cfg['tmpdir'],'unspent.json')
 	write_data_to_file(unspent_data_file,d,'Unspent outputs',silent=True)
 	write_data_to_file(unspent_data_file,d,'Unspent outputs',silent=True)
 	os.environ['MMGEN_BOGUS_WALLET_DATA'] = unspent_data_file
 	os.environ['MMGEN_BOGUS_WALLET_DATA'] = unspent_data_file
-	bwd_msg = 'MMGEN_BOGUS_WALLET_DATA=%s' % unspent_data_file
+	bwd_msg = 'MMGEN_BOGUS_WALLET_DATA={}'.format(unspent_data_file)
 	if opt.print_cmdline: msg(bwd_msg)
 	if opt.print_cmdline: msg(bwd_msg)
 	if opt.log: log_fd.write(bwd_msg + ' ')
 	if opt.log: log_fd.write(bwd_msg + ' ')
 	if opt.verbose or opt.exact_output:
 	if opt.verbose or opt.exact_output:
-		sys.stderr.write("Fake transaction wallet data written to file '%s'\n" % unspent_data_file)
+		sys.stderr.write("Fake transaction wallet data written to file '{}'\n".format(unspent_data_file))
 
 
 def create_tx_data(sources):
 def create_tx_data(sources):
 	tx_data,ad = {},AddrData()
 	tx_data,ad = {},AddrData()
@@ -1169,8 +1168,7 @@ def create_tx_data(sources):
 		ad.add(al)
 		ad.add(al)
 		aix = AddrIdxList(fmt_str=cfgs[s]['addr_idx_list'])
 		aix = AddrIdxList(fmt_str=cfgs[s]['addr_idx_list'])
 		if len(aix) != addrs_per_wallet:
 		if len(aix) != addrs_per_wallet:
-			errmsg(red('Address index list length != %s: %s' %
-						(addrs_per_wallet,repr(aix))))
+			errmsg(red('Address index list length != {}: {}'.format(addrs_per_wallet,repr(aix))))
 			sys.exit(0)
 			sys.exit(0)
 		tx_data[s] = {
 		tx_data[s] = {
 			'addrfile': afile,
 			'addrfile': afile,
@@ -1191,8 +1189,7 @@ def make_txcreate_cmdline(tx_data):
 	for k in cfgs:
 	for k in cfgs:
 		cfgs[k]['amts'] = [None,None]
 		cfgs[k]['amts'] = [None,None]
 		for idx,mod in enumerate(mods):
 		for idx,mod in enumerate(mods):
-			cfgs[k]['amts'][idx] = '%s.%s' % ((getrandnum(4) % mod), str(getrandnum(4))[:5])
-
+			cfgs[k]['amts'][idx] = '{}.{}'.format(getrandnum(4) % mod, str(getrandnum(4))[:5])
 
 
 	cmd_args = ['-d',cfg['tmpdir']]
 	cmd_args = ['-d',cfg['tmpdir']]
 	for num in tx_data:
 	for num in tx_data:
@@ -1209,10 +1206,10 @@ def make_txcreate_cmdline(tx_data):
 
 
 def add_comments_to_addr_file(addrfile,outfile):
 def add_comments_to_addr_file(addrfile,outfile):
 	silence()
 	silence()
-	msg(green("Adding comments to address file '%s'" % addrfile))
+	gmsg("Adding comments to address file '{}'".format(addrfile))
 	a = AddrList(addrfile)
 	a = AddrList(addrfile)
 	for n,idx in enumerate(a.idxs(),1):
 	for n,idx in enumerate(a.idxs(),1):
-		if n % 2: a.set_comment(idx,'Test address %s' % n)
+		if n % 2: a.set_comment(idx,'Test address {}'.format(n))
 	a.format(enable_comments=True)
 	a.format(enable_comments=True)
 	write_data_to_file(outfile,a.fmt_data,silent=True)
 	write_data_to_file(outfile,a.fmt_data,silent=True)
 	end_silence()
 	end_silence()
@@ -1227,7 +1224,7 @@ def make_brainwallet_file(fn):
 		return ''.join([ws_list[getrandnum(1)%len(ws_list)] for i in range(nchars)])
 		return ''.join([ws_list[getrandnum(1)%len(ws_list)] for i in range(nchars)])
 	rand_pairs = [wl[getrandnum(4) % len(wl)] + rand_ws_seq() for i in range(nwords)]
 	rand_pairs = [wl[getrandnum(4) % len(wl)] + rand_ws_seq() for i in range(nwords)]
 	d = ''.join(rand_pairs).rstrip() + '\n'
 	d = ''.join(rand_pairs).rstrip() + '\n'
-	if opt.verbose: msg_r('Brainwallet password:\n%s' % cyan(d))
+	if opt.verbose: msg_r('Brainwallet password:\n{}'.format(cyan(d)))
 	write_data_to_file(fn,d,'brainwallet password',silent=True)
 	write_data_to_file(fn,d,'brainwallet password',silent=True)
 
 
 def do_between():
 def do_between():
@@ -1296,27 +1293,26 @@ def check_needs_rerun(
 	return rerun
 	return rerun
 
 
 def refcheck(desc,chk,refchk):
 def refcheck(desc,chk,refchk):
-	vmsg("Comparing %s '%s' to stored reference" % (desc,chk))
+	vmsg("Comparing {} '{}' to stored reference".format(desc,chk))
 	if chk == refchk:
 	if chk == refchk:
 		ok()
 		ok()
 	else:
 	else:
 		if not opt.verbose: errmsg('')
 		if not opt.verbose: errmsg('')
-		errmsg(red("""
-Fatal error - %s '%s' does not match reference value '%s'.  Aborting test
-""".strip() % (desc,chk,refchk)))
+		m = "Fatal error - {} '{}' does not match reference value '{}'.  Aborting test"
+		errmsg(red(m.format(desc,chk,refchk)))
 		sys.exit(3)
 		sys.exit(3)
 
 
 def check_deps(cmds):
 def check_deps(cmds):
 	if len(cmds) != 1:
 	if len(cmds) != 1:
-		die(1,'Usage: %s check_deps <command>' % g.prog_name)
+		die(1,'Usage: {} check_deps <command>'.format(g.prog_name))
 
 
 	cmd = cmds[0]
 	cmd = cmds[0]
 
 
 	if cmd not in cmd_data:
 	if cmd not in cmd_data:
-		die(1,"'%s': unrecognized command" % cmd)
+		die(1,"'{}': unrecognized command".format(cmd))
 
 
 	if not opt.quiet:
 	if not opt.quiet:
-		msg("Checking dependencies for '%s'" % (cmd))
+		msg("Checking dependencies for '{}'".format(cmd))
 
 
 	check_needs_rerun(ts,cmd,build=False)
 	check_needs_rerun(ts,cmd,build=False)
 
 
@@ -1336,7 +1332,7 @@ def clean(usr_dirs=[]):
 		if str(d) in all_dirs:
 		if str(d) in all_dirs:
 			cleandir(all_dirs[str(d)])
 			cleandir(all_dirs[str(d)])
 		else:
 		else:
-			die(1,'%s: invalid directory number' % d)
+			die(1,'{}: invalid directory number'.format(d))
 	cleandir(os.path.join('test','data_dir'))
 	cleandir(os.path.join('test','data_dir'))
 
 
 def skip_for_win():
 def skip_for_win():
@@ -1384,7 +1380,7 @@ class MMGenTestSuite(object):
 
 
 		if opt.resume:
 		if opt.resume:
 			if cmd == opt.resume:
 			if cmd == opt.resume:
-				msg(yellow("Resuming at '%s'" % cmd))
+				ymsg("Resuming at '{}'".format(cmd))
 				opt.resume = False
 				opt.resume = False
 				opt.skip_deps = False
 				opt.skip_deps = False
 			else:
 			else:
@@ -1408,7 +1404,7 @@ class MMGenTestSuite(object):
 			'walletgen','walletconv','walletchk','txcreate','txsign','txsend','txdo','txbump',
 			'walletgen','walletconv','walletchk','txcreate','txsign','txsend','txdo','txbump',
 			'addrgen','addrimport','keygen','passchg','tool','passgen','regtest','autosign')
 			'addrgen','addrimport','keygen','passchg','tool','passgen','regtest','autosign')
 		for s in scripts:
 		for s in scripts:
-			t = MMGenExpect(name,('mmgen-'+s),[arg],extra_desc='(mmgen-%s)'%s,no_output=True)
+			t = MMGenExpect(name,('mmgen-'+s),[arg],extra_desc='(mmgen-{})'.format(s),no_output=True)
 			t.read()
 			t.read()
 			t.ok()
 			t.ok()
 
 
@@ -1434,10 +1430,9 @@ class MMGenTestSuite(object):
 		self.walletgen(name,seed_len=seed_len,gen_dfl_wallet=True)
 		self.walletgen(name,seed_len=seed_len,gen_dfl_wallet=True)
 
 
 	def brainwalletgen_ref(self,name):
 	def brainwalletgen_ref(self,name):
-		sl_arg = '-l%s' % cfg['seed_len']
-		hp_arg = '-p%s' % ref_wallet_hash_preset
-		label = "test.py ref. wallet (pw '%s', seed len %s)" \
-				% (ref_wallet_brainpass,cfg['seed_len'])
+		sl_arg = '-l{}'.format(cfg['seed_len'])
+		hp_arg = '-p{}'.format(ref_wallet_hash_preset)
+		label = "test.py ref. wallet (pw '{}', seed len {})".format(ref_wallet_brainpass,cfg['seed_len'])
 		bf = 'ref.mmbrain'
 		bf = 'ref.mmbrain'
 		args = ['-d',cfg['tmpdir'],hp_arg,sl_arg,'-ib','-L',label]
 		args = ['-d',cfg['tmpdir'],hp_arg,sl_arg,'-ib','-L',label]
 		write_to_tmpfile(cfg,bf,ref_wallet_brainpass)
 		write_to_tmpfile(cfg,bf,ref_wallet_brainpass)
@@ -1489,14 +1484,14 @@ class MMGenTestSuite(object):
 				add_args+args+['-p',hp]+wf_arg,
 				add_args+args+['-p',hp]+wf_arg,
 				extra_desc=extra_desc)
 				extra_desc=extra_desc)
 		if desc != 'hidden incognito data':
 		if desc != 'hidden incognito data':
-			t.expect("Getting %s from file '" % (desc))
+			t.expect("Getting {} from file '".format(desc))
 		if pw:
 		if pw:
 			t.passphrase(desc,cfg['wpasswd'])
 			t.passphrase(desc,cfg['wpasswd'])
 			t.expect(
 			t.expect(
 				['Passphrase is OK', 'Passphrase.* are correct'],
 				['Passphrase is OK', 'Passphrase.* are correct'],
 				regex=True
 				regex=True
 				)
 				)
-		chk = t.expect_getend('Valid %s for Seed ID ' % desc)[:8]
+		chk = t.expect_getend('Valid {} for Seed ID '.format(desc))[:8]
 		if sid: t.cmp_or_die(chk,sid)
 		if sid: t.cmp_or_die(chk,sid)
 		else: t.ok()
 		else: t.ok()
 
 
@@ -1653,7 +1648,7 @@ class MMGenTestSuite(object):
 		if seed_args: # sign and send
 		if seed_args: # sign and send
 			t.expect('Edit transaction comment? (y/N): ','\n')
 			t.expect('Edit transaction comment? (y/N): ','\n')
 			for cnum,desc in (('1','incognito data'),('3','MMGen wallet'),('4','MMGen wallet')):
 			for cnum,desc in (('1','incognito data'),('3','MMGen wallet'),('4','MMGen wallet')):
-				t.passphrase(('%s' % desc),cfgs[cnum]['wpasswd'])
+				t.passphrase(desc,cfgs[cnum]['wpasswd'])
 			t.expect("Type uppercase 'YES' to confirm: ",'YES\n')
 			t.expect("Type uppercase 'YES' to confirm: ",'YES\n')
 		else:
 		else:
 			t.expect('Add a comment to transaction? (y/N): ','\n')
 			t.expect('Add a comment to transaction? (y/N): ','\n')
@@ -1674,7 +1669,7 @@ class MMGenTestSuite(object):
 	def txsign_end(self,t,tnum=None,has_label=False):
 	def txsign_end(self,t,tnum=None,has_label=False):
 		t.expect('Signing transaction')
 		t.expect('Signing transaction')
 		cprompt = ('Add a comment to transaction','Edit transaction comment')[has_label]
 		cprompt = ('Add a comment to transaction','Edit transaction comment')[has_label]
-		t.expect('%s? (y/N): ' % cprompt,'\n')
+		t.expect('{}? (y/N): '.format(cprompt),'\n')
 		t.expect('Save signed transaction.*?\? \(Y/n\): ','y',regex=True)
 		t.expect('Save signed transaction.*?\? \(Y/n\): ','y',regex=True)
 		add = ' #' + tnum if tnum else ''
 		add = ' #' + tnum if tnum else ''
 		t.written_to_file('Signed transaction' + add, oo=True)
 		t.written_to_file('Signed transaction' + add, oo=True)
@@ -1693,7 +1688,7 @@ class MMGenTestSuite(object):
 			t.ok()
 			t.ok()
 		else:
 		else:
 			cprompt = ('Add a comment to transaction','Edit transaction comment')[has_label]
 			cprompt = ('Add a comment to transaction','Edit transaction comment')[has_label]
-			t.expect('%s? (y/N): ' % cprompt,'\n')
+			t.expect('{}? (y/N): '.format(cprompt),'\n')
 			t.expect('Save signed transaction? (Y/n): ','n')
 			t.expect('Save signed transaction? (Y/n): ','n')
 			t.ok(exit_val=1)
 			t.ok(exit_val=1)
 
 
@@ -1712,7 +1707,7 @@ class MMGenTestSuite(object):
 			t.expect('Add a comment to transaction? (y/N): ','\n')
 			t.expect('Add a comment to transaction? (y/N): ','\n')
 		t.expect('Are you sure you want to broadcast this')
 		t.expect('Are you sure you want to broadcast this')
 		m = 'YES, I REALLY WANT TO DO THIS'
 		m = 'YES, I REALLY WANT TO DO THIS'
-		t.expect("'%s' to confirm: " % m,m+'\n')
+		t.expect("'{}' to confirm: ".format(m),m+'\n')
 		if really_send:
 		if really_send:
 			txid = t.expect_getend('Transaction sent: ')
 			txid = t.expect_getend('Transaction sent: ')
 			assert len(txid) == 64
 			assert len(txid) == 64
@@ -1751,7 +1746,7 @@ class MMGenTestSuite(object):
 	def export_seed(self,name,wf,desc='seed data',out_fmt='seed',pf=None):
 	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)
 		f,t = self.walletconv_export(name,wf,desc=desc,out_fmt=out_fmt,pf=pf)
 		silence()
 		silence()
-		msg('%s: %s' % (capfirst(desc),cyan(get_data_from_file(f,desc))))
+		msg('{}: {}'.format(capfirst(desc),cyan(get_data_from_file(f,desc))))
 		end_silence()
 		end_silence()
 		t.ok()
 		t.ok()
 
 
@@ -1775,7 +1770,7 @@ class MMGenTestSuite(object):
 	# TODO: make outdir and hidden incog compatible (ignore --outdir and warn user?)
 	# TODO: make outdir and hidden incog compatible (ignore --outdir and warn user?)
 	def export_incog_hidden(self,name,wf):
 	def export_incog_hidden(self,name,wf):
 		rf = os.path.join(cfg['tmpdir'],hincog_fn)
 		rf = os.path.join(cfg['tmpdir'],hincog_fn)
-		add_args = ['-J','%s,%s'%(rf,hincog_offset)]
+		add_args = ['-J','{},{}'.format(rf,hincog_offset)]
 		self.export_incog(
 		self.export_incog(
 			name,wf,desc='hidden incognito data',out_fmt='hi',add_args=add_args)
 			name,wf,desc='hidden incognito data',out_fmt='hi',add_args=add_args)
 
 
@@ -1785,7 +1780,7 @@ class MMGenTestSuite(object):
 		t = MMGenExpect(name,'mmgen-addrgen', add_args +
 		t = MMGenExpect(name,'mmgen-addrgen', add_args +
 				['-i'+in_fmt,'-d',cfg['tmpdir'],wf,cfg['addr_idx_list']])
 				['-i'+in_fmt,'-d',cfg['tmpdir'],wf,cfg['addr_idx_list']])
 		t.license()
 		t.license()
-		t.expect_getend('Valid %s for Seed ID ' % desc)
+		t.expect_getend('Valid {} for Seed ID '.format(desc))
 		vmsg('Comparing generated checksum with checksum from previous address file')
 		vmsg('Comparing generated checksum with checksum from previous address file')
 		chk = t.expect_getend(r'Checksum for address data .*?: ',regex=True)
 		chk = t.expect_getend(r'Checksum for address data .*?: ',regex=True)
 		if stdout: t.read()
 		if stdout: t.read()
@@ -1808,7 +1803,7 @@ class MMGenTestSuite(object):
 		t.license()
 		t.license()
 		t.expect_getend('Incog Wallet ID: ')
 		t.expect_getend('Incog Wallet ID: ')
 		t.hash_preset(desc,'1')
 		t.hash_preset(desc,'1')
-		t.passphrase('%s \w{8}' % desc, cfg['wpasswd'])
+		t.passphrase('{} \w{{8}}'.format(desc),cfg['wpasswd'])
 		vmsg('Comparing generated checksum with checksum from address file')
 		vmsg('Comparing generated checksum with checksum from address file')
 		chk = t.expect_getend(r'Checksum for address data .*?: ',regex=True)
 		chk = t.expect_getend(r'Checksum for address data .*?: ',regex=True)
 		verify_checksum_or_exit(get_addrfile_checksum(),chk)
 		verify_checksum_or_exit(get_addrfile_checksum(),chk)
@@ -1821,7 +1816,7 @@ class MMGenTestSuite(object):
 	def addrgen_incog_hidden(self,name,wf,foo):
 	def addrgen_incog_hidden(self,name,wf,foo):
 		rf = os.path.join(cfg['tmpdir'],hincog_fn)
 		rf = os.path.join(cfg['tmpdir'],hincog_fn)
 		self.addrgen_incog(name,[],'',in_fmt='hi',desc='hidden incognito data',
 		self.addrgen_incog(name,[],'',in_fmt='hi',desc='hidden incognito data',
-			args=['-H','%s,%s'%(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):
 	def keyaddrgen(self,name,wf,pf=None,check_ref=False,mmtype=None):
 		if cfg['segwit'] and not mmtype:
 		if cfg['segwit'] and not mmtype:
@@ -1937,7 +1932,7 @@ class MMGenTestSuite(object):
 		non_mm_fn = os.path.join(cfg['tmpdir'],non_mmgen_fn)
 		non_mm_fn = os.path.join(cfg['tmpdir'],non_mmgen_fn)
 		add_args = ['-d',cfg['tmpdir'],'-i','brain','-b'+cfg['bw_params'],'-p1','-k',non_mm_fn,'-M',f12]
 		add_args = ['-d',cfg['tmpdir'],'-i','brain','-b'+cfg['bw_params'],'-p1','-k',non_mm_fn,'-M',f12]
 		t = self.txcreate_common(name,sources=['1','2','3','4','14'],non_mmgen_input='4',do_label=1,txdo_args=[f7,f8,f9,f10],add_args=add_args)
 		t = self.txcreate_common(name,sources=['1','2','3','4','14'],non_mmgen_input='4',do_label=1,txdo_args=[f7,f8,f9,f10],add_args=add_args)
-		os.system('rm -f %s/*.sigtx' % cfg['tmpdir'])
+		os.system('rm -f {}/*.sigtx'.format(cfg['tmpdir']))
 		self.txsign4(name,f7,f8,f9,f10,f11,f12,txdo_handle=t)
 		self.txsign4(name,f7,f8,f9,f10,f11,f12,txdo_handle=t)
 		self.txsend(name,'',txdo_handle=t)
 		self.txsend(name,'',txdo_handle=t)
 		os.system('touch ' + os.path.join(cfg['tmpdir'],'txdo'))
 		os.system('touch ' + os.path.join(cfg['tmpdir'],'txdo'))
@@ -1960,7 +1955,7 @@ class MMGenTestSuite(object):
 			t.tx_view(view='terse')
 			t.tx_view(view='terse')
 
 
 		for cnum,desc in (('1','incognito data'),('3','MMGen wallet')):
 		for cnum,desc in (('1','incognito data'),('3','MMGen wallet')):
-			t.passphrase(('%s' % desc),cfgs[cnum]['wpasswd'])
+			t.passphrase('{}'.format(desc),cfgs[cnum]['wpasswd'])
 
 
 		if txdo_handle: return
 		if txdo_handle: return
 		self.txsign_end(t,has_label=True)
 		self.txsign_end(t,has_label=True)
@@ -2037,10 +2032,10 @@ class MMGenTestSuite(object):
 
 
 	def tool_find_incog_data(self,name,f1,f2):
 	def tool_find_incog_data(self,name,f1,f2):
 		i_id = read_from_file(f2).rstrip()
 		i_id = read_from_file(f2).rstrip()
-		vmsg('Incog ID: %s' % cyan(i_id))
+		vmsg('Incog ID: {}'.format(cyan(i_id)))
 		t = MMGenExpect(name,'mmgen-tool',
 		t = MMGenExpect(name,'mmgen-tool',
 				['-d',cfg['tmpdir'],'find_incog_data',f1,i_id])
 				['-d',cfg['tmpdir'],'find_incog_data',f1,i_id])
-		o = t.expect_getend('Incog data for ID %s found at offset ' % i_id)
+		o = t.expect_getend('Incog data for ID {} found at offset '.format(i_id))
 		os.unlink(f1)
 		os.unlink(f1)
 		cmp_or_die(hincog_offset,int(o))
 		cmp_or_die(hincog_offset,int(o))
 
 
@@ -2112,7 +2107,7 @@ class MMGenTestSuite(object):
 	def ref_hincog_conv(self,name,wfk='hic_wallet',add_uopts=[]):
 	def ref_hincog_conv(self,name,wfk='hic_wallet',add_uopts=[]):
 		ic_f = os.path.join(ref_dir,cfg[wfk])
 		ic_f = os.path.join(ref_dir,cfg[wfk])
 		uopts = ['-i','hi','-p','1','-l',str(cfg['seed_len'])] + add_uopts
 		uopts = ['-i','hi','-p','1','-l',str(cfg['seed_len'])] + add_uopts
-		hi_opt = ['-H','%s,%s' % (ic_f,ref_wallet_incog_offset)]
+		hi_opt = ['-H','{},{}'.format(ic_f,ref_wallet_incog_offset)]
 		self.walletconv_in(name,None,'hidden incognito data',uopts+hi_opt,oo=True,pw=True)
 		self.walletconv_in(name,None,'hidden incognito data',uopts+hi_opt,oo=True,pw=True)
 
 
 	def ref_hincog_conv_old(self,name):
 	def ref_hincog_conv_old(self,name):
@@ -2138,7 +2133,7 @@ class MMGenTestSuite(object):
 
 
 	def ref_hincog_conv_out(self,name,extra_uopts=[]):
 	def ref_hincog_conv_out(self,name,extra_uopts=[]):
 		ic_f = os.path.join(cfg['tmpdir'],hincog_fn)
 		ic_f = os.path.join(cfg['tmpdir'],hincog_fn)
-		hi_parms = '%s,%s' % (ic_f,ref_wallet_incog_offset)
+		hi_parms = '{},{}'.format(ic_f,ref_wallet_incog_offset)
 		sl_parm = '-l' + str(cfg['seed_len'])
 		sl_parm = '-l' + str(cfg['seed_len'])
 		self.walletconv_out(name,
 		self.walletconv_out(name,
 			'hidden incognito data', 'hi',
 			'hidden incognito data', 'hi',
@@ -2152,7 +2147,7 @@ class MMGenTestSuite(object):
 		self.walletchk(name,wf,pf=None,pw=True,sid=cfg['seed_id'])
 		self.walletchk(name,wf,pf=None,pw=True,sid=cfg['seed_id'])
 
 
 	def ref_ss_chk(self,name,ss=None):
 	def ref_ss_chk(self,name,ss=None):
-		wf = os.path.join(ref_dir,'%s.%s' % (cfg['seed_id'],ss.ext))
+		wf = os.path.join(ref_dir,'{}.{}'.format(cfg['seed_id'],ss.ext))
 		self.walletchk(name,wf,pf=None,desc=ss.desc,sid=cfg['seed_id'])
 		self.walletchk(name,wf,pf=None,desc=ss.desc,sid=cfg['seed_id'])
 
 
 	def ref_seed_chk(self,name):
 	def ref_seed_chk(self,name):
@@ -2169,7 +2164,7 @@ class MMGenTestSuite(object):
 
 
 	def ref_brain_chk(self,name,bw_file=ref_bw_file):
 	def ref_brain_chk(self,name,bw_file=ref_bw_file):
 		wf = os.path.join(ref_dir,bw_file)
 		wf = os.path.join(ref_dir,bw_file)
-		add_args = ['-l%s' % cfg['seed_len'], '-p'+ref_bw_hash_preset]
+		add_args = ['-l{}'.format(cfg['seed_len']), '-p'+ref_bw_hash_preset]
 		self.walletchk(name,wf,pf=None,add_args=add_args,
 		self.walletchk(name,wf,pf=None,add_args=add_args,
 			desc='brainwallet',sid=cfg['ref_bw_seed_id'])
 			desc='brainwallet',sid=cfg['ref_bw_seed_id'])
 
 
@@ -2179,11 +2174,8 @@ class MMGenTestSuite(object):
 	def ref_hincog_chk(self,name,desc='hidden incognito data'):
 	def ref_hincog_chk(self,name,desc='hidden incognito data'):
 		for wtype,edesc,of_arg in ('hic_wallet','',[]), \
 		for wtype,edesc,of_arg in ('hic_wallet','',[]), \
 								('hic_wallet_old','(old format)',['-O']):
 								('hic_wallet_old','(old format)',['-O']):
-			ic_arg = ['-H%s,%s' % (
-						os.path.join(ref_dir,cfg[wtype]),
-						ref_wallet_incog_offset
-					)]
-			slarg = ['-l%s ' % cfg['seed_len']]
+			ic_arg = ['-H{},{}'.format(os.path.join(ref_dir,cfg[wtype]),ref_wallet_incog_offset)]
+			slarg = ['-l{} '.format(cfg['seed_len'])]
 			hparg = ['-p1']
 			hparg = ['-p1']
 			if wtype == 'hic_wallet_old' and opt.profile: msg('')
 			if wtype == 'hic_wallet_old' and opt.profile: msg('')
 			t = MMGenExpect(name,'mmgen-walletchk',
 			t = MMGenExpect(name,'mmgen-walletchk',
@@ -2325,7 +2317,7 @@ class MMGenTestSuite(object):
 		infile = os.path.join(ref_dir,cfg['seed_id']+'.mmwords')
 		infile = os.path.join(ref_dir,cfg['seed_id']+'.mmwords')
 		t = MMGenExpect(name,'mmgen-walletconv',[usr_rand_arg]+opts+[infile],extra_desc='(convert)')
 		t = MMGenExpect(name,'mmgen-walletconv',[usr_rand_arg]+opts+[infile],extra_desc='(convert)')
 
 
-		add_args = ['-l%s' % cfg['seed_len']]
+		add_args = ['-l{}'.format(cfg['seed_len'])]
 		t.license()
 		t.license()
 		if pw:
 		if pw:
 			t.passphrase_new('new '+desc,cfg['wpasswd'])
 			t.passphrase_new('new '+desc,cfg['wpasswd'])
@@ -3009,13 +3001,13 @@ try:
 			elif arg in cmd_data:
 			elif arg in cmd_data:
 				check_needs_rerun(ts,arg,build=True)
 				check_needs_rerun(ts,arg,build=True)
 			else:
 			else:
-				die(1,'%s: unrecognized command' % arg)
+				die(1,'{}: unrecognized command'.format(arg))
 	else:
 	else:
 		clean()
 		clean()
 		for cmd in cmd_data:
 		for cmd in cmd_data:
 			if cmd == 'info_regtest': break # don't run everything after this by default
 			if cmd == 'info_regtest': break # don't run everything after this by default
 			if cmd[:5] == 'info_':
 			if cmd[:5] == 'info_':
-				msg(green('%sTesting %s' % (('\n','')[bool(opt.resume)],cmd_data[cmd][0])))
+				gmsg('{}Testing {}'.format(('\n','')[bool(opt.resume)],cmd_data[cmd][0]))
 				continue
 				continue
 			ts.do_cmd(cmd)
 			ts.do_cmd(cmd)
 			if cmd is not cmd_data.keys()[-1]: do_between()
 			if cmd is not cmd_data.keys()[-1]: do_between()

+ 14 - 15
test/tooltest.py

@@ -260,8 +260,8 @@ class MMGenToolTestSuite(object):
 		a,b = p.communicate()
 		a,b = p.communicate()
 		retcode = p.wait()
 		retcode = p.wait()
 		if retcode != 0:
 		if retcode != 0:
-			msg('%s\n%s\n%s'%(red('FAILED'),yellow('Command stderr output:'),b))
-			die(1,red('Called process returned with an error (retcode %s)' % retcode))
+			msg('{}\n{}\n{}'.format(red('FAILED'),yellow('Command stderr output:'),b))
+			rdie(1,'Called process returned with an error (retcode {})'.format(retcode))
 		return (a,a.rstrip())[bool(strip)]
 		return (a,a.rstrip())[bool(strip)]
 
 
 	def run_cmd_chk(self,name,f1,f2,kwargs='',extra_msg='',strip_hex=False,add_opts=[]):
 	def run_cmd_chk(self,name,f1,f2,kwargs='',extra_msg='',strip_hex=False,add_opts=[]):
@@ -274,8 +274,8 @@ class MMGenToolTestSuite(object):
 			return (a.lstrip('0') == b.lstrip('0')) if strip_hex else (a == b)
 			return (a.lstrip('0') == b.lstrip('0')) if strip_hex else (a == b)
 		if cmp_equal(ret,idata): ok()
 		if cmp_equal(ret,idata): ok()
 		else:
 		else:
-			die(3,red(
-	"Error: values don't match:\nIn:  %s\nOut: %s" % (repr(idata),repr(ret))))
+			fs = "Error: values don't match:\nIn:  {!r}\nOut: {!r}"
+			rdie(3,fs.format(idata,ret))
 		return ret
 		return ret
 
 
 	def run_cmd_nochk(self,name,f1,kwargs='',add_opts=[]):
 	def run_cmd_nochk(self,name,f1,kwargs='',add_opts=[]):
@@ -286,12 +286,12 @@ class MMGenToolTestSuite(object):
 		return ret
 		return ret
 
 
 	def run_cmd_out(self,name,carg=None,Return=False,kwargs='',fn_idx='',extra_msg='',literal=False,chkdata='',hush=False,add_opts=[]):
 	def run_cmd_out(self,name,carg=None,Return=False,kwargs='',fn_idx='',extra_msg='',literal=False,chkdata='',hush=False,add_opts=[]):
-		if carg: write_to_tmpfile(cfg,'%s%s.in' % (name,fn_idx),carg+'\n')
+		if carg: write_to_tmpfile(cfg,'{}{}.in'.format(name,fn_idx),carg+'\n')
 		ret = self.run_cmd(name,([],[carg])[bool(carg)],kwargs=kwargs,extra_msg=extra_msg,add_opts=add_opts)
 		ret = self.run_cmd(name,([],[carg])[bool(carg)],kwargs=kwargs,extra_msg=extra_msg,add_opts=add_opts)
 		if carg: vmsg('In:   ' + repr(carg))
 		if carg: vmsg('In:   ' + repr(carg))
 		vmsg('Out:  ' + (repr(ret),ret.decode('utf8'))[literal])
 		vmsg('Out:  ' + (repr(ret),ret.decode('utf8'))[literal])
 		if ret or ret == '':
 		if ret or ret == '':
-			write_to_tmpfile(cfg,'%s%s.out' % (name,fn_idx),ret+'\n')
+			write_to_tmpfile(cfg,'{}{}.out'.format(name,fn_idx),ret+'\n')
 			if chkdata:
 			if chkdata:
 				cmp_or_die(ret,chkdata)
 				cmp_or_die(ret,chkdata)
 				return
 				return
@@ -299,7 +299,7 @@ class MMGenToolTestSuite(object):
 			else:
 			else:
 				if not hush: ok()
 				if not hush: ok()
 		else:
 		else:
-			die(3,red("Error for command '%s'" % name))
+			rdie(3,"Error for command '{}'".format(name))
 
 
 	def run_cmd_randinput(self,name,strip=True,add_opts=[]):
 	def run_cmd_randinput(self,name,strip=True,add_opts=[]):
 		s = os.urandom(128)
 		s = os.urandom(128)
@@ -309,7 +309,7 @@ class MMGenToolTestSuite(object):
 		fn = name+'.out'
 		fn = name+'.out'
 		write_to_tmpfile(cfg,fn,ret+'\n')
 		write_to_tmpfile(cfg,fn,ret+'\n')
 		ok()
 		ok()
-		vmsg('Returned: %s' % ret)
+		vmsg('Returned: {}'.format(ret))
 
 
 	# Util
 	# Util
 	def Strtob58(self,name):       self.run_cmd_out(name,getrandstr(16))
 	def Strtob58(self,name):       self.run_cmd_out(name,getrandstr(16))
@@ -328,11 +328,11 @@ class MMGenToolTestSuite(object):
 	def Id8(self,name):     self.run_cmd_randinput(name)
 	def Id8(self,name):     self.run_cmd_randinput(name)
 	def Str2id6(self,name):
 	def Str2id6(self,name):
 		s = getrandstr(120,no_space=True)
 		s = getrandstr(120,no_space=True)
-		s2 = ' %s %s %s %s %s ' % (s[:3],s[3:9],s[9:29],s[29:50],s[50:120])
+		s2 = ' {} {} {} {} {} '.format(s[:3],s[3:9],s[9:29],s[29:50],s[50:120])
 		ret1 = self.run_cmd(name,[s],extra_msg='unspaced input'); ok()
 		ret1 = self.run_cmd(name,[s],extra_msg='unspaced input'); ok()
 		ret2 = self.run_cmd(name,[s2],extra_msg='spaced input')
 		ret2 = self.run_cmd(name,[s2],extra_msg='spaced input')
 		cmp_or_die(ret1,ret2)
 		cmp_or_die(ret1,ret2)
-		vmsg('Returned: %s' % ret1)
+		vmsg('Returned: {}'.format(ret1))
 	def Hash160(self,name):        self.run_cmd_out(name,getrandhex(16))
 	def Hash160(self,name):        self.run_cmd_out(name,getrandhex(16))
 	def Hash256(self,name):        self.run_cmd_out(name,getrandstr(16))
 	def Hash256(self,name):        self.run_cmd_out(name,getrandstr(16))
 	def Hexreverse(self,name):     self.run_cmd_out(name,getrandhex(24))
 	def Hexreverse(self,name):     self.run_cmd_out(name,getrandhex(24))
@@ -488,20 +488,19 @@ if cmd_args:
 		die(1,'Only one command may be specified')
 		die(1,'Only one command may be specified')
 	cmd = cmd_args[0]
 	cmd = cmd_args[0]
 	if cmd in cmd_data:
 	if cmd in cmd_data:
-		msg('Running tests for %s:' % cmd_data[cmd]['desc'])
+		msg('Running tests for {}:'.format(cmd_data[cmd]['desc']))
 		ts.do_cmds(cmd)
 		ts.do_cmds(cmd)
 	elif cmd == 'clean':
 	elif cmd == 'clean':
 		cleandir(cfg['tmpdir'])
 		cleandir(cfg['tmpdir'])
 		sys.exit(0)
 		sys.exit(0)
 	else:
 	else:
-		die(1,"'%s': unrecognized command" % cmd)
+		die(1,"'{}': unrecognized command".format(cmd))
 else:
 else:
 	cleandir(cfg['tmpdir'])
 	cleandir(cfg['tmpdir'])
 	for cmd in cmd_data:
 	for cmd in cmd_data:
-		msg('Running tests for %s:' % cmd_data[cmd]['desc'])
+		msg('Running tests for {}:'.format(cmd_data[cmd]['desc']))
 		ts.do_cmds(cmd)
 		ts.do_cmds(cmd)
 		if cmd is not cmd_data.keys()[-1]: msg('')
 		if cmd is not cmd_data.keys()[-1]: msg('')
 
 
 t = int(time.time()) - start_time
 t = int(time.time()) - start_time
-msg(green(
-	'All requested tests finished OK, elapsed time: %02i:%02i' % (t/60,t%60)))
+gmsg('All requested tests finished OK, elapsed time: {:02}:{:02}'.format(t/60,t%60))