MMGenListItem: require all immutable attrs to be set in constructor
This commit is contained in:
parent
2df7878ea6
commit
514278d616
5 changed files with 54 additions and 8 deletions
|
|
@ -300,7 +300,7 @@ class AddrListEntry(MMGenListItem):
|
|||
wallet_passwd = MMGenListItemAttr('wallet_passwd','WalletPassword')
|
||||
|
||||
class PasswordListEntry(MMGenListItem):
|
||||
passwd = MMGenImmutableAttr('passwd',str,typeconv=False) # TODO: create Password type
|
||||
passwd = MMGenListItemAttr('passwd',str,typeconv=False) # TODO: create Password type
|
||||
idx = MMGenImmutableAttr('idx','AddrIdx')
|
||||
label = MMGenListItemAttr('label','TwComment',reassign_ok=True)
|
||||
sec = MMGenListItemAttr('sec',PrivKey,typeconv=False)
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ altcoins.eth.tw: Ethereum tracking wallet and related classes for the MMGen suit
|
|||
"""
|
||||
|
||||
from mmgen.common import *
|
||||
from mmgen.obj import ETHAmt,TwLabel,is_coin_addr,is_mmgen_id
|
||||
from mmgen.obj import ETHAmt,TwLabel,is_coin_addr,is_mmgen_id,MMGenListItem,MMGenListItemAttr,MMGenImmutableAttr
|
||||
from mmgen.tw import TrackingWallet,TwAddrList,TwUnspentOutputs
|
||||
from mmgen.addr import AddrData
|
||||
from .contract import Token
|
||||
|
|
@ -295,6 +295,18 @@ Actions: [q]uit view, [p]rint to file, pager [v]iew, [w]ide view,
|
|||
'confirmations': 0, # TODO
|
||||
} for d in wl]
|
||||
|
||||
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__)
|
||||
label = MMGenListItemAttr('label','TwComment',reassign_ok=True)
|
||||
twmmid = MMGenImmutableAttr('twmmid','TwMMGenID')
|
||||
addr = MMGenImmutableAttr('addr','CoinAddr')
|
||||
confs = MMGenImmutableAttr('confs',int,typeconv=False)
|
||||
days = MMGenListItemAttr('days',int,typeconv=False)
|
||||
skip = MMGenListItemAttr('skip',str,typeconv=False,reassign_ok=True)
|
||||
|
||||
class EthereumTokenTwUnspentOutputs(EthereumTwUnspentOutputs):
|
||||
|
||||
disp_type = 'token'
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
class MMGenObject(object):
|
||||
'placeholder - overridden when testing'
|
||||
def immutable_attr_init_check(self): pass
|
||||
|
||||
import os
|
||||
if os.getenv('MMGEN_DEBUG') or os.getenv('MMGEN_TEST_SUITE') or os.getenv('MMGEN_TRACEBACK'):
|
||||
|
|
@ -107,6 +108,24 @@ if os.getenv('MMGEN_DEBUG') or os.getenv('MMGEN_TEST_SUITE') or os.getenv('MMGEN
|
|||
import re
|
||||
return re.sub('\n+','\n',''.join(out))
|
||||
|
||||
# Check that all immutables have been initialized. Expensive, so do only when testing.
|
||||
def immutable_attr_init_check(self):
|
||||
from mmgen.globalvars import g
|
||||
if g.test_suite:
|
||||
from mmgen.util import rdie
|
||||
cls = type(self)
|
||||
for attrname in sorted({a for a in self.valid_attrs if a[0] != '_'}):
|
||||
for o in (cls,cls.__bases__[0]): # assume there's only one base class
|
||||
if attrname in o.__dict__:
|
||||
attr = o.__dict__[attrname]
|
||||
break
|
||||
else:
|
||||
rdie(3,'unable to find descriptor {}.{}'.format(cls.__name__,attrname))
|
||||
if type(attr).__name__ == 'MMGenImmutableAttr':
|
||||
if attrname not in self.__dict__:
|
||||
fs = 'attribute {!r} of {} has not been initialized in constructor!'
|
||||
rdie(3,fs.format(attrname,cls.__name__))
|
||||
|
||||
def print_diff(a,b,from_json=True):
|
||||
if from_json:
|
||||
a = json.dumps(json.loads(a),indent=4).split('\n') if a else []
|
||||
|
|
|
|||
19
mmgen/obj.py
19
mmgen/obj.py
|
|
@ -251,18 +251,31 @@ class MMGenListItem(MMGenObject):
|
|||
|
||||
valid_attrs = None
|
||||
valid_attrs_extra = set()
|
||||
invalid_attrs = {
|
||||
'pfmt',
|
||||
'pmsg',
|
||||
'pdie',
|
||||
'valid_attrs',
|
||||
'valid_attrs_extra',
|
||||
'invalid_attrs',
|
||||
'immutable_attr_init_check',
|
||||
}
|
||||
|
||||
def __init__(self,*args,**kwargs):
|
||||
if self.valid_attrs == None:
|
||||
type(self).valid_attrs = (
|
||||
( {e for e in dir(self) if e[:2] != '__'} | self.valid_attrs_extra ) -
|
||||
{'pfmt','pmsg','pdie','valid_attrs','valid_attrs_extra'} )
|
||||
( {e for e in dir(self) if e[:2] != '__'} | self.valid_attrs_extra ) - self.invalid_attrs )
|
||||
|
||||
if args:
|
||||
raise ValueError('Non-keyword args not allowed')
|
||||
raise ValueError('Non-keyword args not allowed in {!r} constructor'.format(type(self).__name__))
|
||||
|
||||
for k in kwargs:
|
||||
if kwargs[k] != None:
|
||||
setattr(self,k,kwargs[k])
|
||||
|
||||
# Require all immutables to be initialized. Check performed only when testing.
|
||||
self.immutable_attr_init_check()
|
||||
|
||||
# allow only valid attributes to be set
|
||||
def __setattr__(self,name,value):
|
||||
if name not in self.valid_attrs:
|
||||
|
|
|
|||
|
|
@ -247,6 +247,8 @@ class MMGenTxIO(MMGenListItem):
|
|||
class MMGenTxInput(MMGenTxIO):
|
||||
scriptPubKey = MMGenListItemAttr('scriptPubKey','HexStr')
|
||||
sequence = MMGenListItemAttr('sequence',int,typeconv=False)
|
||||
# required by copy_inputs_from_tw()
|
||||
copy_attrs = { 'scriptPubKey','vout','amt','label','mmid','addr','confs','txid' }
|
||||
|
||||
class MMGenTxOutput(MMGenTxIO):
|
||||
is_chg = MMGenListItemAttr('is_chg',bool,typeconv=False)
|
||||
|
|
@ -660,10 +662,10 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
|
|||
# inputs methods
|
||||
def copy_inputs_from_tw(self,tw_unspent_data):
|
||||
self.inputs = MMGenTxInputList()
|
||||
MMGenTxInput() # throwaway instance to initialize cls.valid_attrs
|
||||
for d in tw_unspent_data:
|
||||
t = MMGenTxInput(**{attr:getattr(d,attr) for attr in d.__dict__ if attr in MMGenTxInput.valid_attrs})
|
||||
if d.twmmid.type == 'mmgen': t.mmid = d.twmmid # twmmid -> mmid
|
||||
t = MMGenTxInput(**{attr:getattr(d,attr) for attr in d.__dict__ if attr in MMGenTxInput.copy_attrs})
|
||||
if d.twmmid.type == 'mmgen':
|
||||
t.mmid = d.twmmid # twmmid -> mmid
|
||||
self.inputs.append(t)
|
||||
|
||||
def get_input_sids(self):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue