Browse Source

autosign.Signable: relocate methods, improve class inheritance

The MMGen Project 1 week ago
parent
commit
9d655ed467
1 changed files with 94 additions and 93 deletions
  1. 94 93
      mmgen/autosign.py

+ 94 - 93
mmgen/autosign.py

@@ -142,6 +142,7 @@ class Signable:
 		clean_all = False
 		multiple_ok = True
 		action_desc = 'signed'
+		fail_msg = 'failed to sign'
 
 		def __init__(self, parent):
 			self.parent = parent
@@ -149,31 +150,10 @@ class Signable:
 			self.dir = getattr(parent, self.dir_name)
 			self.name = type(self).__name__
 
-		@property
-		def submitted(self):
-			return self._processed('_submitted', self.subext)
-
-		def _processed(self, attrname, ext):
-			if not hasattr(self, attrname):
-				setattr(self, attrname, tuple(f for f in sorted(self.dir.iterdir())
-					if f.name.endswith('.' + ext)))
-			return getattr(self, attrname)
-
 		@property
 		def unsigned(self):
 			return self._unprocessed('_unsigned', self.rawext, self.sigext)
 
-		@property
-		def unsubmitted(self):
-			return self._unprocessed('_unsubmitted', self.sigext, self.subext)
-
-		@property
-		def unsubmitted_raw(self):
-			return self._unprocessed('_unsubmitted_raw', self.rawext, self.subext)
-
-		unsent = unsubmitted
-		unsent_raw = unsubmitted_raw
-
 		def _unprocessed(self, attrname, rawext, sigext):
 			if not hasattr(self, attrname):
 				dirlist = sorted(self.dir.iterdir())
@@ -192,75 +172,15 @@ class Signable:
 				b = '  {}\n'.format('\n  '.join(
 					self.gen_bad_list(sorted(bad_files, key=lambda f: f.name))))))
 
-		def die_wrong_num_txs(self, tx_type, *, msg=None, desc=None, show_dir=False):
-			num_txs = len(getattr(self, tx_type))
-			die('AutosignTXError', '{m}{a} {b} transaction{c} {d} {e}!'.format(
-				m = msg + '\n' if msg else '',
-				a = 'One' if num_txs == 1 else 'More than one' if num_txs else 'No',
-				b = desc or tx_type,
-				c = suf(num_txs),
-				d = 'already present' if num_txs else 'present',
-				e = f'in ‘{getattr(self.parent, self.dir_name)}’'
-					if show_dir else 'on removable device'))
-
-		def check_create_ok(self):
-			if len(self.unsigned):
-				self.die_wrong_num_txs('unsigned', msg='Cannot create transaction')
-			if len(self.unsent):
-				die('AutosignTXError', 'Cannot create transaction: you have an unsent transaction')
-
-		def get_unsubmitted(self, tx_type='unsubmitted'):
-			if len(self.unsubmitted) == 1:
-				return self.unsubmitted[0]
-			else:
-				self.die_wrong_num_txs(tx_type)
-
-		def get_unsent(self):
-			return self.get_unsubmitted('unsent')
-
-		def get_submitted(self):
-			if len(self.submitted) == 0:
-				self.die_wrong_num_txs('submitted')
-			else:
-				return self.submitted
-
-		def get_abortable(self):
-			if len(self.unsent_raw) != 1:
-				self.die_wrong_num_txs('unsent_raw', desc='unsent')
-			if len(self.unsent) > 1:
-				self.die_wrong_num_txs('unsent')
-			if self.unsent:
-				if self.unsent[0].stem != self.unsent_raw[0].stem:
-					die(1, f'{self.unsent[0]}, {self.unsent_raw[0]}: file mismatch')
-			return self.unsent_raw + self.unsent
-
-		def shred_abortable(self):
-			files = self.get_abortable() # raises AutosignTXError if no unsent TXs available
-			keypress_confirm(
-				self.cfg,
-				'The following file{} will be securely deleted:\n{}\nOK?'.format(
-					suf(files),
-					fmt_list(map(str, files), fmt='col', indent='  ')),
-					do_exit = True)
-			for fn in files:
-				msg(f'Shredding file ‘{fn}’')
-				shred_file(self.cfg, fn, iterations=15)
-			sys.exit(0)
-
-		async def get_last_created(self):
-			from .tx import CompletedTX
-			files = [f for f in self.dir.iterdir() if f.name.endswith(self.subext)]
-			return sorted(
-				[await CompletedTX(cfg=self.cfg, filename=str(txfile), quiet_open=True)
-					for txfile in files],
-				key = lambda x: x.timestamp)[-1]
+		def gen_bad_list(self, bad_files):
+			for f in bad_files:
+				yield red(f.name)
 
 	class transaction(base):
 		desc = 'non-automount transaction'
 		rawext = 'rawtx'
 		sigext = 'sigtx'
 		dir_name = 'tx_dir'
-		fail_msg = 'failed to sign'
 		automount = False
 
 		async def sign(self, f):
@@ -321,12 +241,8 @@ class Signable:
 			else:
 				msg('\nNo non-MMGen outputs')
 
-		def gen_bad_list(self, bad_files):
-			for f in bad_files:
-				yield red(f.name)
-
 	class automount_transaction(transaction):
-		desc   = 'automount transaction'
+		desc = 'automount transaction'
 		dir_name = 'txauto_dir'
 		rawext = 'arawtx'
 		sigext = 'asigtx'
@@ -334,7 +250,91 @@ class Signable:
 		multiple_ok = False
 		automount = True
 
-	class xmr_signable(transaction): # mixin class
+		@property
+		def unsubmitted(self):
+			return self._unprocessed('_unsubmitted', self.sigext, self.subext)
+
+		@property
+		def unsubmitted_raw(self):
+			return self._unprocessed('_unsubmitted_raw', self.rawext, self.subext)
+
+		unsent = unsubmitted
+		unsent_raw = unsubmitted_raw
+
+		@property
+		def submitted(self):
+			return self._processed('_submitted', self.subext)
+
+		def _processed(self, attrname, ext):
+			if not hasattr(self, attrname):
+				setattr(self, attrname, tuple(f for f in sorted(self.dir.iterdir())
+					if f.name.endswith('.' + ext)))
+			return getattr(self, attrname)
+
+		def die_wrong_num_txs(self, tx_type, *, msg=None, desc=None, show_dir=False):
+			num_txs = len(getattr(self, tx_type))
+			die('AutosignTXError', '{m}{a} {b} transaction{c} {d} {e}!'.format(
+				m = msg + '\n' if msg else '',
+				a = 'One' if num_txs == 1 else 'More than one' if num_txs else 'No',
+				b = desc or tx_type,
+				c = suf(num_txs),
+				d = 'already present' if num_txs else 'present',
+				e = f'in ‘{getattr(self.parent, self.dir_name)}’'
+					if show_dir else 'on removable device'))
+
+		def check_create_ok(self):
+			if len(self.unsigned):
+				self.die_wrong_num_txs('unsigned', msg='Cannot create transaction')
+			if len(self.unsent):
+				die('AutosignTXError', 'Cannot create transaction: you have an unsent transaction')
+
+		def get_unsubmitted(self, tx_type='unsubmitted'):
+			if len(self.unsubmitted) == 1:
+				return self.unsubmitted[0]
+			else:
+				self.die_wrong_num_txs(tx_type)
+
+		def get_unsent(self):
+			return self.get_unsubmitted('unsent')
+
+		def get_submitted(self):
+			if len(self.submitted) == 0:
+				self.die_wrong_num_txs('submitted')
+			else:
+				return self.submitted
+
+		def get_abortable(self):
+			if len(self.unsent_raw) != 1:
+				self.die_wrong_num_txs('unsent_raw', desc='unsent')
+			if len(self.unsent) > 1:
+				self.die_wrong_num_txs('unsent')
+			if self.unsent:
+				if self.unsent[0].stem != self.unsent_raw[0].stem:
+					die(1, f'{self.unsent[0]}, {self.unsent_raw[0]}: file mismatch')
+			return self.unsent_raw + self.unsent
+
+		def shred_abortable(self):
+			files = self.get_abortable() # raises AutosignTXError if no unsent TXs available
+			keypress_confirm(
+				self.cfg,
+				'The following file{} will be securely deleted:\n{}\nOK?'.format(
+					suf(files),
+					fmt_list(map(str, files), fmt='col', indent='  ')),
+					do_exit = True)
+			for fn in files:
+				msg(f'Shredding file ‘{fn}’')
+				shred_file(self.cfg, fn, iterations=15)
+			sys.exit(0)
+
+		async def get_last_created(self):
+			from .tx import CompletedTX
+			files = [f for f in self.dir.iterdir() if f.name.endswith(self.subext)]
+			return sorted(
+				[await CompletedTX(cfg=self.cfg, filename=str(txfile), quiet_open=True)
+					for txfile in files],
+				key = lambda x: x.timestamp)[-1]
+
+	class xmr_signable: # mixin class
 		automount = True
 
 		def need_daemon_restart(self, m, new_idx):
@@ -346,11 +346,12 @@ class Signable:
 			bmsg('\nAutosign summary:')
 			msg('\n'.join(s.get_info(indent='  ') for s in signables) + self.summary_footer)
 
-	class xmr_transaction(xmr_signable):
+	class xmr_transaction(xmr_signable, automount_transaction):
 		dir_name = 'xmr_tx_dir'
 		desc = 'Monero transaction'
+		rawext = 'rawtx'
+		sigext = 'sigtx'
 		subext = 'subtx'
-		multiple_ok = False
 		summary_footer = ''
 
 		async def sign(self, f):
@@ -366,7 +367,7 @@ class Signable:
 			tx2.write(ask_write=False)
 			return tx2
 
-	class xmr_wallet_outputs_file(xmr_signable):
+	class xmr_wallet_outputs_file(xmr_signable, base):
 		desc = 'Monero wallet outputs file'
 		rawext = 'raw'
 		sigext = 'sig'