AttrCtrl,Lockable: add autolocking

This commit is contained in:
The MMGen Project 2021-08-07 15:33:28 +00:00
commit ca86da1c1b
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
5 changed files with 30 additions and 8 deletions

View file

@ -20,7 +20,14 @@
base_obj.py: base objects with no internal imports for the MMGen suite
"""
class AttrCtrl:
class AttrCtrlMeta(type):
def __call__(cls,*args,**kwargs):
instance = super().__call__(*args,**kwargs)
if instance._autolock:
instance._lock = True
return instance
class AttrCtrl(metaclass=AttrCtrlMeta):
"""
After instance is locked, forbid setting any attribute if the attribute is not present
in either the class or instance dict.
@ -29,6 +36,7 @@ class AttrCtrl:
attribute, if _use_class_attr is True. If the instance or class attribute is set
to None, no type checking is performed.
"""
_autolock = True
_lock = False
_use_class_attr = False
_skip_type_check = ()

View file

@ -309,8 +309,6 @@ class MoneroWalletDaemon(RPCDaemon):
['--stagenet', self.network == 'testnet'],
)
self.lock()
class CoinDaemon(Daemon):
networks = ('mainnet','testnet','regtest')
cfg_file_hdr = ''
@ -439,8 +437,6 @@ class CoinDaemon(Daemon):
self.init_subclass()
self.lock()
def init_datadir(self):
if self.test_suite:
return os.path.join('test','daemons',self.coin.lower())
@ -774,5 +770,3 @@ class erigon_rpcdaemon(RPCDaemon):
['--http.api=eth,web3,txpool'],
[f'--http.port={self.rpc_port}'],
)
self.lock()

View file

@ -40,6 +40,7 @@ class GlobalContext(Lockable):
2 - environmental vars
3 - command line
"""
_autolock = False
_set_ok = ('user_entropy','session')
_reset_ok = ('stdout','stderr','accept_defaults')
_use_class_attr = True

View file

@ -27,6 +27,7 @@ from .base_obj import Lockable
import mmgen.share.Opts
class UserOpts(Lockable):
_autolock = False
_set_ok = ('usr_randchars',)
_reset_ok = ('quiet','verbose','yes')

View file

@ -39,6 +39,7 @@ class unit_test(object):
qmsg_r('Testing class Lockable...')
class MyLockable(Lockable): # class has no attrs, like UserOpts
_autolock = False
_set_ok = ('foo','baz','alpha','beta','gamma','delta','epsilon')
_reset_ok = ('bar','baz')
@ -66,6 +67,7 @@ class unit_test(object):
lc.epsilon = [0]
class MyLockableClsCheck(Lockable): # class has attrs, like GlobalContext
_autolock = False
_use_class_attr = True
_set_ok = ('foo','baz')
_reset_ok = ('bar','baz')
@ -82,9 +84,22 @@ class unit_test(object):
lcc.bar = 3 # bar is in reset list
lcc.baz = 3.2
lcc.baz = 3.1 # baz is in both lists
qmsg('OK')
qmsg('Checking error handling:')
qmsg('OK')
qmsg_r('Testing class Lockable with autolock...')
class MyLockableAutolock(Lockable):
def __init__(self):
self.foo = True
lca = MyLockableAutolock()
assert lca._autolock == True
assert lca._lock == True
assert lca.foo == True
qmsg('OK')
qmsg_r('Checking error handling...')
vmsg('')
def bad1(): ac.x = 1
def bad2(): acc.foo = 1
@ -103,6 +118,8 @@ class unit_test(object):
def bad14(): lc.delta = float(0)
def bad15(): lc.epsilon = [0]
def bad16(): lca.foo = None
ut.process_bad_data((
('attr (1)', 'AttributeError', 'has no attr', bad1 ),
('attr (2)', 'AttributeError', 'has no attr', bad9 ),
@ -119,6 +136,7 @@ class unit_test(object):
("attr (can't reset)", 'AttributeError', 'reset', bad13 ),
("attr (can't reset)", 'AttributeError', 'reset', bad14 ),
("attr (can't reset)", 'AttributeError', 'reset', bad15 ),
("attr (can't set)", 'AttributeError', 'read-only', bad16 ),
))
qmsg('OK')