Browse Source

minor fixes and cleanups

The MMGen Project 1 year ago
parent
commit
ede7353ea2
6 changed files with 76 additions and 34 deletions
  1. 1 1
      mmgen/main.py
  2. 16 15
      mmgen/obj.py
  3. 5 3
      mmgen/proto/eth/tx/new.py
  4. 6 2
      mmgen/tw/addresses.py
  5. 7 6
      mmgen/tx/new.py
  6. 41 7
      test/cmdtest_py_d/ct_regtest.py

+ 1 - 1
mmgen/main.py

@@ -44,7 +44,7 @@ def launch(*, mod=None, func=None, fqmod=None, package='mmgen'):
 		try:
 			errmsg = str(e.args[0])
 		except:
-			errmsg = repr(e.args[0])
+			errmsg = repr(e.args[0]) if e.args else repr(e)
 
 		from collections import namedtuple
 		from .color import nocolor,yellow,red

+ 16 - 15
mmgen/obj.py

@@ -347,6 +347,7 @@ class MMGenLabel(HiliteStr,InitErrors):
 	color = 'pink'
 	allowed = []
 	forbidden = []
+	first_char = []
 	max_len = 0
 	min_len = 0
 	max_screen_width = 0 # if != 0, overrides max_len
@@ -354,21 +355,18 @@ class MMGenLabel(HiliteStr,InitErrors):
 	def __new__(cls,s):
 		if isinstance(s,cls):
 			return s
-		for k in ( cls.forbidden, cls.allowed ):
-			assert isinstance(k,list)
-			for ch in k:
-				assert isinstance(ch,str) and len(ch) == 1
 		try:
 			s = s.strip()
-			for ch in s:
-				# Allow:    (L)etter,(N)umber,(P)unctuation,(S)ymbol,(Z)space
-				# Disallow: (C)ontrol,(M)combining
-				# Combining characters create width formatting issues, so disallow them for now
-				if unicodedata.category(ch)[0] in ('C','M'):
-					raise ValueError(
-						'{!a}: {} characters not allowed'.format(
-							ch,
-							{ 'C':'control', 'M':'combining' }[unicodedata.category(ch)[0]] ))
+			if not cls.allowed:
+				for ch in s:
+					# Allow:    (L)etter,(N)umber,(P)unctuation,(S)ymbol,(Z)space
+					# Disallow: (C)ontrol,(M)combining
+					# Combining characters create width formatting issues, so disallow them for now
+					if unicodedata.category(ch)[0] in ('C','M'):
+						raise ValueError(
+							'{!a}: {} characters not allowed'.format(
+								ch,
+								{ 'C':'control', 'M':'combining' }[unicodedata.category(ch)[0]] ))
 
 			me = str.__new__(cls,s)
 
@@ -380,11 +378,14 @@ class MMGenLabel(HiliteStr,InitErrors):
 
 			assert len(s) >= cls.min_len, f'too short (<{cls.min_len} symbols)'
 
+			if cls.first_char and s and not s[0] in cls.first_char:
+				raise ValueError('first character not in set ' + ' '.join(cls.first_char))
+
 			if cls.allowed and not set(list(s)).issubset(set(cls.allowed)):
-				raise ValueError('contains non-allowed symbols: ' + ' '.join(set(list(s)) - set(cls.allowed)) )
+				raise ValueError('contains symbols not in set: ' + ' '.join(cls.allowed))
 
 			if cls.forbidden and any(ch in s for ch in cls.forbidden):
-				raise ValueError('contains one of these forbidden symbols: ' + ' '.join(cls.forbidden) )
+				raise ValueError('contains one of these forbidden symbols: ' + ' '.join(cls.forbidden))
 
 			return me
 		except Exception as e:

+ 5 - 3
mmgen/proto/eth/tx/new.py

@@ -79,14 +79,16 @@ class New(Base,TxBase.New):
 		self.txid = MMGenTxID(make_chksum_6(self.serialized).upper())
 
 	async def process_cmd_args(self,cmd_args,ad_f,ad_w):
+
 		lc = len(cmd_args)
+
 		if lc == 0 and self.usr_contract_data and 'Token' not in self.name:
 			return
+
 		if lc != 1:
-			die(1,f'{lc} output{suf(lc)} specified, but Ethereum transactions must have exactly one')
+			die(1, f'{lc} output{suf(lc)} specified, but Ethereum transactions must have exactly one')
 
-		for a in cmd_args:
-			await self.process_cmd_arg(a,ad_f,ad_w)
+		await self.process_cmd_arg(cmd_args[0],ad_f,ad_w)
 
 	def select_unspent(self,unspent):
 		from ....ui import line_input

+ 6 - 2
mmgen/tw/addresses.py

@@ -323,7 +323,10 @@ class TwAddresses(TwView):
 		if start is not None:
 			for d in data[start:]:
 				if d.al_id == al_id:
-					if not d.recvd and (self.cfg.autochg_ignore_labels or not d.comment):
+					if (
+							not d.recvd
+							and (self.cfg.autochg_ignore_labels or not d.comment)
+						):
 						if d.comment:
 							msg('{} {} {} {}{}'.format(
 								yellow('WARNING: address'),
@@ -369,7 +372,8 @@ class TwAddresses(TwView):
 
 		assert isinstance(mmtype,MMGenAddrType)
 
-		res = [self.get_change_address( f'{sid}:{mmtype}', r.bot, r.top ) for sid,r in self.sid_ranges.items()]
+		res = [self.get_change_address(f'{sid}:{mmtype}', r.bot, r.top)
+				for sid,r in self.sid_ranges.items()]
 
 		if any(res):
 			res = list(filter(None,res))

+ 7 - 6
mmgen/tx/new.py

@@ -221,17 +221,18 @@ class New(Base):
 			await self.process_cmd_arg(a,ad_f,ad_w)
 
 		if self.chg_idx is None:
-			die(2,(
-				fmt( self.msg_no_change_output.format(self.dcoin) ).strip()
+			die(2,
+				fmt(self.msg_no_change_output.format(self.dcoin)).strip()
 					if len(self.outputs) == 1 else
-				'ERROR: No change output specified' ))
+				'ERROR: No change output specified')
 
 		if self.has_segwit_outputs() and not self.rpc.info('segwit_is_active'):
-			die(2,f'{gc.proj_name} Segwit address requested on the command line, '
-					+ 'but Segwit is not active on this chain')
+			die(2,
+				f'{gc.proj_name} Segwit address requested on the command line, '
+				'but Segwit is not active on this chain')
 
 		if not self.outputs:
-			die(2,'At least one output must be specified on the command line')
+			die(2, 'At least one output must be specified on the command line')
 
 	async def get_outputs_from_cmdline(self,cmd_args):
 		from ..addrdata import AddrData,TwAddrData

+ 41 - 7
test/cmdtest_py_d/ct_regtest.py

@@ -438,6 +438,11 @@ class CmdTestRegtest(CmdTestBase,CmdTestShared):
 		('bob_auto_chg_bad3',       'error handling for auto change address transaction (no unused addresses)'),
 		('bob_auto_chg_bad4',       'error handling for auto change address transaction by addrtype '
 									'(no unused addresses)'),
+		('bob_auto_chg_bad5',       'error handling (more than one chg address listed)'),
+		('bob_auto_chg_bad6',       'error handling for auto change address transaction '
+									'(more than one chg address, mixed)'),
+		('bob_auto_chg_bad7',       'error handling for auto change address transaction '
+									'(more than one chg address requested)'),
 		('carol_twimport2',          'recreating Carol’s tracking wallet from JSON dump'),
 		('carol_rescan_blockchain',  'rescanning the blockchain (full rescan)'),
 		('carol_auto_chg1',          'creating an automatic change address transaction (C)'),
@@ -1882,16 +1887,19 @@ class CmdTestRegtest(CmdTestBase,CmdTestShared):
 			idx,
 			by_mmtype     = False,
 			include_dest  = True,
-			ignore_labels = False):
+			ignore_labels = False,
+			add_args      = []):
+
 		if mmtype in ('S','B') and not self.proto.cap('segwit'):
 			return 'skip'
 		sid = self._user_sid('bob')
 		t = self.spawn(
 			'mmgen-txcreate',
-				[f'--outdir={self.tr.trash_dir}', '--no-blank', f'--{user}'] +
-				(['--autochg-ignore-labels'] if ignore_labels else []) +
-				[mmtype if by_mmtype else f'{sid}:{mmtype}'] +
-				([self.burn_addr+',0.01'] if include_dest else [])
+				[f'--outdir={self.tr.trash_dir}', '--no-blank', f'--{user}']
+				+ (['--autochg-ignore-labels'] if ignore_labels else [])
+				+ [mmtype if by_mmtype else f'{sid}:{mmtype}']
+				+ ([self.burn_addr+',0.01'] if include_dest else [])
+				+ add_args
 			)
 		return self.txcreate_ui_common(t,
 			menu            = [],
@@ -1949,10 +1957,13 @@ class CmdTestRegtest(CmdTestBase,CmdTestShared):
 	def bob_remove_comment_uua1(self):
 		return self._bob_remove_comment_uua(':C:3')
 
-	def _usr_auto_chg_bad(self,user,al_id,expect):
+	def _usr_auto_chg_bad(self, user, al_id, expect, add_args=[]):
 		t = self.spawn(
 			'mmgen-txcreate',
-			['-d', self.tr.trash_dir, '-B', f'--{user}', self.burn_addr+', 0.01', al_id],
+			['-d', self.tr.trash_dir, '-B', f'--{user}']
+			+ [f'{self.burn_addr},0.01']
+			+ ([al_id] if al_id else [])
+			+ add_args,
 			exit_val = 2)
 		t.expect(expect)
 		return t
@@ -1981,6 +1992,29 @@ class CmdTestRegtest(CmdTestBase,CmdTestShared):
 			'L',
 			'contains no unused addresses of address type' )
 
+	def bob_auto_chg_bad5(self):
+		sid = self._user_sid('bob')
+		return self._usr_auto_chg_bad(
+			'bob',
+			None,
+			'More than one change address listed',
+			add_args = [f'{sid}:C:4', f'{sid}:C:5'])
+
+	def bob_auto_chg_bad6(self):
+		sid = self._user_sid('bob')
+		return self._usr_auto_chg_bad(
+			'bob',
+			'L',
+			'More than one',
+			add_args = [f'{sid}:C:4'])
+
+	def bob_auto_chg_bad7(self):
+		return self._usr_auto_chg_bad(
+			'bob',
+			'L',
+			'More than one change address requested',
+			add_args = ['B'])
+
 	def carol_twimport2(self):
 		u,b = (4,3) if self.proto.cap('segwit') else (3,2)
 		return self.carol_twimport(