AttrCtrl,Lockable: forbid relocking, perform additional check
This commit is contained in:
parent
92ebb62490
commit
d7b0133bf4
2 changed files with 24 additions and 1 deletions
|
|
@ -24,7 +24,7 @@ class AttrCtrlMeta(type):
|
|||
def __call__(cls,*args,**kwargs):
|
||||
instance = super().__call__(*args,**kwargs)
|
||||
if instance._autolock:
|
||||
instance._lock = True
|
||||
instance.lock()
|
||||
return instance
|
||||
|
||||
class AttrCtrl(metaclass=AttrCtrlMeta):
|
||||
|
|
@ -45,7 +45,10 @@ class AttrCtrl(metaclass=AttrCtrlMeta):
|
|||
self._lock = True
|
||||
|
||||
def __setattr__(self,name,value):
|
||||
|
||||
if self._lock:
|
||||
assert name != '_lock', 'lock can be set only once'
|
||||
|
||||
def do_error(name,value,ref_val):
|
||||
raise AttributeError(
|
||||
f'{value!r}: invalid value for attribute {name!r}'
|
||||
|
|
@ -84,6 +87,13 @@ class Lockable(AttrCtrl):
|
|||
_set_ok = ()
|
||||
_reset_ok = ()
|
||||
|
||||
def lock(self):
|
||||
for name in ('_set_ok','_reset_ok'):
|
||||
for attr in getattr(self,name):
|
||||
assert hasattr(self,attr), (
|
||||
f'attribute {attr!r} in {name!r} not found in {type(self).__name__} object {id(self)}' )
|
||||
super().lock()
|
||||
|
||||
def __setattr__(self,name,value):
|
||||
if self._lock and hasattr(self,name):
|
||||
val = getattr(self,name)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ class unit_test(object):
|
|||
qmsg_r('Testing class AttrCtrl...')
|
||||
|
||||
class MyAttrCtrl(AttrCtrl):
|
||||
_autolock = False
|
||||
foo = 'fooval'
|
||||
ac = MyAttrCtrl()
|
||||
ac.lock()
|
||||
|
|
@ -23,7 +24,11 @@ class unit_test(object):
|
|||
ac.foo = 'new fooval'
|
||||
ac.foo = 'new fooval2'
|
||||
|
||||
class MyAttrCtrlAutolock(AttrCtrl): pass
|
||||
aca = MyAttrCtrlAutolock()
|
||||
|
||||
class MyAttrCtrlClsCheck(AttrCtrl):
|
||||
_autolock = False
|
||||
_use_class_attr = True
|
||||
foo = 'fooval'
|
||||
bar = None
|
||||
|
|
@ -97,6 +102,10 @@ class unit_test(object):
|
|||
assert lca._lock == True
|
||||
assert lca.foo == True
|
||||
|
||||
class MyLockableBad(Lockable):
|
||||
_set_ok = ('foo','bar')
|
||||
foo = 1
|
||||
|
||||
qmsg('OK')
|
||||
qmsg_r('Checking error handling...')
|
||||
vmsg('')
|
||||
|
|
@ -119,6 +128,8 @@ class unit_test(object):
|
|||
def bad15(): lc.epsilon = [0]
|
||||
|
||||
def bad16(): lca.foo = None
|
||||
def bad17(): lb = MyLockableBad()
|
||||
def bad18(): aca.lock()
|
||||
|
||||
ut.process_bad_data((
|
||||
('attr (1)', 'AttributeError', 'has no attr', bad1 ),
|
||||
|
|
@ -137,6 +148,8 @@ class unit_test(object):
|
|||
("attr (can't reset)", 'AttributeError', 'reset', bad14 ),
|
||||
("attr (can't reset)", 'AttributeError', 'reset', bad15 ),
|
||||
("attr (can't set)", 'AttributeError', 'read-only', bad16 ),
|
||||
("attr (bad _set_ok)", 'AssertionError', 'not found in',bad17 ),
|
||||
("call to lock()", 'AssertionError', 'only once', bad18 ),
|
||||
))
|
||||
|
||||
qmsg('OK')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue