Browse Source

MMGenImmutableAttr: allow callable dtype arg, remove 'no_type_check' option

MMGen 5 years ago
parent
commit
174caeebd3
7 changed files with 17 additions and 31 deletions
  1. 2 2
      mmgen/altcoins/eth/tw.py
  2. 1 1
      mmgen/main_autosign.py
  3. 8 6
      mmgen/obj.py
  4. 2 2
      mmgen/tw.py
  5. 1 17
      mmgen/tx.py
  6. 2 3
      test/objattrtest.py
  7. 1 0
      test/objattrtest_py_d/oat_common.py

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

@@ -298,8 +298,8 @@ Actions:         [q]uit view, [p]rint to file, pager [v]iew, [w]ide view,
 	class MMGenTwUnspentOutput(MMGenListItem):
 		txid   = MMGenListItemAttr('txid','CoinTxID')
 		vout   = MMGenListItemAttr('vout',int,typeconv=False)
-		amt    = MMGenImmutableAttr('amt',g.proto.coin_amt.__name__)
-		amt2   = MMGenListItemAttr('amt2',g.proto.coin_amt.__name__)
+		amt    = MMGenImmutableAttr('amt',lambda:g.proto.coin_amt,typeconv=False)
+		amt2   = MMGenListItemAttr('amt2',lambda:g.proto.coin_amt,typeconv=False)
 		label  = MMGenListItemAttr('label','TwComment',reassign_ok=True)
 		twmmid = MMGenImmutableAttr('twmmid','TwMMGenID')
 		addr   = MMGenImmutableAttr('addr','CoinAddr')

+ 1 - 1
mmgen/main_autosign.py

@@ -278,7 +278,7 @@ def print_summary(signed_txs):
 				msg(fs.format(
 					tx.txid.fmt(width=t_wid,color=True) if nm is non_mmgen[0] else ' '*t_wid,
 					nm.addr.fmt(width=a_wid,color=True),
-					nm._amt.hl() + ' ' + yellow(tx.coin)))
+					nm.amt.hl() + ' ' + yellow(tx.coin)))
 	else:
 		msg('No non-MMGen outputs')
 

+ 8 - 6
mmgen/obj.py

@@ -187,11 +187,12 @@ class Int(int,Hilite): pass
 # Reassignment and deletion forbidden
 class MMGenImmutableAttr(object): # Descriptor
 
-	def __init__(self,name,dtype,typeconv=True,no_type_check=False,set_none_ok=False):
+	ok_dtypes = (str,type,type(None),type(lambda:0))
+
+	def __init__(self,name,dtype,typeconv=True,set_none_ok=False):
 		self.typeconv = typeconv
-		self.no_type_check = no_type_check
 		self.set_none_ok = set_none_ok
-		assert isinstance(dtype,(str,type,type(None))),'{!r}: invalid dtype arg'.format(dtype)
+		assert isinstance(dtype,self.ok_dtypes),'{!r}: invalid dtype arg'.format(dtype)
 		self.name = name
 		self.dtype = dtype
 
@@ -201,7 +202,6 @@ class MMGenImmutableAttr(object): # Descriptor
 	# forbid all reassignment
 	def set_attr_ok(self,instance):
 		return not self.name in instance.__dict__
-#		return not hasattr(instance,self.name)
 
 	def __set__(self,instance,value):
 		if not self.set_attr_ok(instance):
@@ -212,8 +212,10 @@ class MMGenImmutableAttr(object): # Descriptor
 		elif self.typeconv:   # convert type
 			instance.__dict__[self.name] = \
 				globals()[self.dtype](value,on_fail='raise') if type(self.dtype) == str else self.dtype(value)
-		else:               # check type
-			if type(value) == self.dtype or self.no_type_check:
+		else:                 # check type
+			if type(value) == self.dtype:
+				instance.__dict__[self.name] = value
+			elif callable(self.dtype) and type(value) == self.dtype():
 				instance.__dict__[self.name] = value
 			else:
 				m = "Attribute '{}' of {} instance must of type {}"

+ 2 - 2
mmgen/tw.py

@@ -63,8 +63,8 @@ Actions: [q]uit view, [p]rint to file, pager [v]iew, [w]ide view, add [l]abel:
 	class MMGenTwUnspentOutput(MMGenListItem):
 		txid     = MMGenListItemAttr('txid','CoinTxID')
 		vout     = MMGenListItemAttr('vout',int,typeconv=False)
-		amt      = MMGenImmutableAttr('amt',g.proto.coin_amt.__name__)
-		amt2     = MMGenListItemAttr('amt2',g.proto.coin_amt.__name__)
+		amt      = MMGenImmutableAttr('amt',lambda:g.proto.coin_amt,typeconv=False)
+		amt2     = MMGenListItemAttr('amt2',lambda:g.proto.coin_amt,typeconv=False)
 		label    = MMGenListItemAttr('label','TwComment',reassign_ok=True)
 		twmmid   = MMGenImmutableAttr('twmmid','TwMMGenID')
 		addr     = MMGenImmutableAttr('addr','CoinAddr')

+ 1 - 17
mmgen/tx.py

@@ -220,7 +220,7 @@ class DeserializedTX(dict,MMGenObject):
 
 class MMGenTxIO(MMGenListItem):
 	vout     = MMGenListItemAttr('vout',int,typeconv=False)
-	_amt     = MMGenImmutableAttr('amt',None,no_type_check=True,typeconv=False)
+	amt      = MMGenImmutableAttr('amt',lambda:g.proto.coin_amt,typeconv=False)
 	label    = MMGenListItemAttr('label','TwComment',reassign_ok=True)
 	mmid     = MMGenListItemAttr('mmid','MMGenID')
 	addr     = MMGenImmutableAttr('addr','CoinAddr')
@@ -228,22 +228,6 @@ class MMGenTxIO(MMGenListItem):
 	txid     = MMGenListItemAttr('txid','CoinTxID')
 	have_wif = MMGenListItemAttr('have_wif',bool,typeconv=False,delete_ok=True)
 
-	valid_attrs_extra = {'amt'}
-
-	# Setting self.amt is runtime-dependent, so make it a property
-	# Make underlying self._amt an MMGenImmutableAttr to prevent reassignment
-	@property
-	def amt(self):
-		if type(self._amt) != g.proto.coin_amt:
-			raise ValueError('{}: invalid coin_amt type (must be {})'.format(type(self._amt),g.proto.coin_amt))
-		return self._amt
-
-	@amt.setter
-	def amt(self,val):
-		if type(val) != g.proto.coin_amt:
-			raise ValueError('{}: invalid coin_amt type (must be {})'.format(type(val),g.proto.coin_amt))
-		self._amt = val
-
 class MMGenTxInput(MMGenTxIO):
 	scriptPubKey = MMGenListItemAttr('scriptPubKey','HexStr')
 	sequence     = MMGenListItemAttr('sequence',int,typeconv=False)

+ 2 - 3
test/objattrtest.py

@@ -51,8 +51,6 @@ opts_data = {
 }
 
 cmd_args = opts.init(opts_data)
-init_coin(g.coin)
-from mmgen.tw import *
 
 pd = namedtuple('permission_bits', ['read_ok','delete_ok','reassign_ok'])
 
@@ -121,7 +119,7 @@ def test_attr(data,obj,attrname,dobj,bits,attrval_type):
 					msg_r(' {}={!r}'.format(k,d[k]))
 
 		if opt.show_nonstandard_init:
-			for k,v in (('typeconv',False),('no_type_check',True),('set_none_ok',True)):
+			for k,v in (('typeconv',False),('set_none_ok',True)):
 				if d[k] == v:
 					msg_r(' {}={}'.format(k,v))
 
@@ -161,4 +159,5 @@ def do_loop():
 		msg(clr('Testing {}'.format(obj)))
 		test_object(test_data,obj)
 
+init_coin(g.coin)
 do_loop()

+ 1 - 0
test/objattrtest_py_d/oat_common.py

@@ -15,6 +15,7 @@ from mmgen.seed import *
 from mmgen.protocol import *
 from mmgen.addr import *
 from mmgen.tx import *
+from mmgen.tw import *
 
 from collections import namedtuple
 atd = namedtuple('attrtest_entry',['attrs','args','kwargs'])