Lockable: allow all non-int attrs to be considered unset

This commit is contained in:
The MMGen Project 2021-08-04 10:47:19 +00:00
commit 6c4ca8ad52
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
2 changed files with 27 additions and 4 deletions

View file

@ -70,20 +70,21 @@ class Lockable(AttrCtrl):
- if an attribute's name is in _reset_ok, read-only restrictions are bypassed and only
AttrCtrl checking is performed
An attribute is considered unset if its value is None, or if it is present in the instance
__dict__, if _use_class_attr is True.
An attribute is considered unset if its value is None, or if it evaluates to False but is
not zero; or if it is not present in the instance __dict__ when _use_class_attr is True.
"""
_set_ok = ()
_reset_ok = ()
def __setattr__(self,name,value):
if self._lock and hasattr(self,name):
val = getattr(self,name)
if name not in (self._set_ok + self._reset_ok):
raise AttributeError(f'attribute {name!r} of {type(self).__name__} object is read-only')
elif name not in self._reset_ok:
#print(self.__dict__)
if not (
getattr(self,name) is None or
val is None or (not (val == 0) and not val) or
( self._use_class_attr and name not in self.__dict__ ) ):
raise AttributeError(
f'attribute {name!r} of {type(self).__name__} object is already set,'

View file

@ -11,6 +11,7 @@ class unit_test(object):
def run_test(self,name,ut):
from mmgen.base_obj import AttrCtrl,Lockable
from decimal import Decimal
qmsg_r('Testing class AttrCtrl...')
@ -38,7 +39,7 @@ class unit_test(object):
qmsg_r('Testing class Lockable...')
class MyLockable(Lockable): # class has no attrs, like UserOpts
_set_ok = ('foo','baz')
_set_ok = ('foo','baz','alpha','beta','gamma','delta','epsilon')
_reset_ok = ('bar','baz')
lc = MyLockable()
@ -46,6 +47,14 @@ class unit_test(object):
lc.bar = 'barval'
lc.baz = 1
lc.qux = 1
# are these considered set?
lc.alpha = 0 # yes
lc.beta = False # yes
lc.gamma = Decimal('0') # yes
lc.delta = 0.0 # yes
lc.epsilon = [] # no
lc.lock()
lc.foo = 'fooval2'
@ -54,6 +63,8 @@ class unit_test(object):
lc.baz = 2
lc.baz = 3
lc.epsilon = [0]
class MyLockableClsCheck(Lockable): # class has attrs, like GlobalContext
_use_class_attr = True
_set_ok = ('foo','baz')
@ -86,6 +97,12 @@ class unit_test(object):
def bad9(): lc.x = 1
def bad10(): lcc.x = 1
def bad11(): lc.alpha = 0
def bad12(): lc.beta = False
def bad13(): lc.gamma = Decimal('0')
def bad14(): lc.delta = float(0)
def bad15(): lc.epsilon = [0]
ut.process_bad_data((
('attr (1)', 'AttributeError', 'has no attr', bad1 ),
('attr (2)', 'AttributeError', 'has no attr', bad9 ),
@ -97,6 +114,11 @@ class unit_test(object):
("attr (can't set)", 'AttributeError', 'read-only', bad7 ),
("attr (can't reset)", 'AttributeError', 'reset', bad3 ),
("attr (can't reset)", 'AttributeError', 'reset', bad8 ),
("attr (can't reset)", 'AttributeError', 'reset', bad11 ),
("attr (can't reset)", 'AttributeError', 'reset', bad12 ),
("attr (can't reset)", 'AttributeError', 'reset', bad13 ),
("attr (can't reset)", 'AttributeError', 'reset', bad14 ),
("attr (can't reset)", 'AttributeError', 'reset', bad15 ),
))
qmsg('OK')