Lockable: allow all non-int attrs to be considered unset
This commit is contained in:
parent
20c9c37c6a
commit
6c4ca8ad52
2 changed files with 27 additions and 4 deletions
|
|
@ -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,'
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue