From ca86da1c1b679c75f73e2fd56049fdeff55e8ab8 Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Sat, 7 Aug 2021 15:33:28 +0000 Subject: [PATCH] AttrCtrl,Lockable: add autolocking --- mmgen/base_obj.py | 10 +++++++++- mmgen/daemon.py | 6 ------ mmgen/globalvars.py | 1 + mmgen/opts.py | 1 + test/unit_tests_d/ut_lockable.py | 22 ++++++++++++++++++++-- 5 files changed, 31 insertions(+), 9 deletions(-) diff --git a/mmgen/base_obj.py b/mmgen/base_obj.py index 177c8d25..8a5327b7 100755 --- a/mmgen/base_obj.py +++ b/mmgen/base_obj.py @@ -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 = () diff --git a/mmgen/daemon.py b/mmgen/daemon.py index 03565d94..92f41b87 100755 --- a/mmgen/daemon.py +++ b/mmgen/daemon.py @@ -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() diff --git a/mmgen/globalvars.py b/mmgen/globalvars.py index 682474ac..3ef863c9 100755 --- a/mmgen/globalvars.py +++ b/mmgen/globalvars.py @@ -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 diff --git a/mmgen/opts.py b/mmgen/opts.py index 48321883..2c216f4e 100755 --- a/mmgen/opts.py +++ b/mmgen/opts.py @@ -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') diff --git a/test/unit_tests_d/ut_lockable.py b/test/unit_tests_d/ut_lockable.py index cfa49128..34d6ba83 100755 --- a/test/unit_tests_d/ut_lockable.py +++ b/test/unit_tests_d/ut_lockable.py @@ -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')