fix several regressions from switching to accessibles
also include some basic tests now Change-Id: Ia07892c03f4d72f5da307a79a9827f926940881d Reviewed-on: https://forge.frm2.tum.de/review/18539 Tested-by: JenkinsCodeReview <bjoern_pedersen@frm2.tum.de> Reviewed-by: Enrico Faulhaber <enrico.faulhaber@frm2.tum.de> Tested-by: Enrico Faulhaber <enrico.faulhaber@frm2.tum.de>
This commit is contained in:
@ -65,6 +65,10 @@ class ModuleMeta(type):
|
||||
(so the dispatcher will get notfied of changed values)
|
||||
"""
|
||||
def __new__(mcs, name, bases, attrs):
|
||||
commands = attrs.pop('commands', {})
|
||||
parameters = attrs.pop('parameters', {})
|
||||
overrides = attrs.pop('overrides', {})
|
||||
|
||||
newtype = type.__new__(mcs, name, bases, attrs)
|
||||
if '__constructed__' in attrs:
|
||||
return newtype
|
||||
@ -82,17 +86,15 @@ class ModuleMeta(type):
|
||||
for base in reversed(bases):
|
||||
if hasattr(base, "accessibles"):
|
||||
accessibles_list.append(base.accessibles)
|
||||
for entry in ['accessibles', 'parameters', 'commands', 'overrides']:
|
||||
accessibles_list.append(attrs.get(entry, {}))
|
||||
accessibles = {} # unordered dict of accessibles
|
||||
newtype.parameters = {}
|
||||
for accessibles in [attrs.get('accessibles', {}), parameters, commands, overrides]:
|
||||
accessibles_list.append(accessibles)
|
||||
accessibles = {} # unordered dict of accessibles, will be sorted later
|
||||
for accessibles_dict in accessibles_list:
|
||||
for key, obj in accessibles_dict.items():
|
||||
if isinstance(obj, Override):
|
||||
try:
|
||||
obj = obj.apply(accessibles[key])
|
||||
accessibles[key] = obj
|
||||
newtype.parameters[key] = obj
|
||||
except KeyError:
|
||||
raise ProgrammingError("module %s: %s does not exist"
|
||||
% (name, key))
|
||||
@ -104,16 +106,16 @@ class ModuleMeta(type):
|
||||
# raise ProgrammingError("module %s: %s must not be redefined"
|
||||
# % (name, key))
|
||||
if isinstance(obj, Parameter):
|
||||
newtype.parameters[key] = obj
|
||||
accessibles[key] = obj
|
||||
elif isinstance(obj, Command):
|
||||
# XXX: convert to param with datatype=CommandType???
|
||||
accessibles[key] = obj
|
||||
else:
|
||||
raise ProgrammingError('%r: accessibles entry %r should be a '
|
||||
'Parameter or Command object!' % (name, key))
|
||||
|
||||
# Correct naming of EnumTypes
|
||||
for k, v in newtype.parameters.items():
|
||||
for k, v in accessibles.items():
|
||||
if isinstance(v.datatype, EnumType) and not v.datatype._enum.name:
|
||||
v.datatype._enum.name = k
|
||||
|
||||
@ -123,10 +125,13 @@ class ModuleMeta(type):
|
||||
newtype.accessibles = OrderedDict(sorted(accessibles.items(), key=lambda item: item[1].ctr))
|
||||
|
||||
# check validity of Parameter entries
|
||||
for pname, pobj in newtype.parameters.items():
|
||||
for pname, pobj in newtype.accessibles.items():
|
||||
# XXX: create getters for the units of params ??
|
||||
|
||||
# wrap of reading/writing funcs
|
||||
if isinstance(pobj, Command):
|
||||
# skip commands for now
|
||||
continue
|
||||
rfunc = attrs.get('read_' + pname, None)
|
||||
for base in bases:
|
||||
if rfunc is not None:
|
||||
@ -140,7 +145,7 @@ class ModuleMeta(type):
|
||||
else:
|
||||
# return cached value
|
||||
self.log.debug("rfunc(%s): return cached value" % pname)
|
||||
value = self.parameters[pname].value
|
||||
value = self.accessibles[pname].value
|
||||
setattr(self, pname, value) # important! trigger the setter
|
||||
return value
|
||||
|
||||
@ -159,13 +164,13 @@ class ModuleMeta(type):
|
||||
|
||||
def wrapped_wfunc(self, value, pname=pname, wfunc=wfunc):
|
||||
self.log.debug("wfunc(%s): set %r" % (pname, value))
|
||||
pobj = self.parameters[pname]
|
||||
pobj = self.accessibles[pname]
|
||||
value = pobj.datatype.validate(value)
|
||||
if wfunc:
|
||||
self.log.debug('calling %r(%r)' % (wfunc, value))
|
||||
value = wfunc(self, value) or value
|
||||
# XXX: use setattr or direct manipulation
|
||||
# of self.parameters[pname]?
|
||||
# of self.accessibles[pname]?
|
||||
setattr(self, pname, value)
|
||||
return value
|
||||
|
||||
@ -176,16 +181,16 @@ class ModuleMeta(type):
|
||||
wrapped_wfunc.__wrapped__ = True
|
||||
|
||||
def getter(self, pname=pname):
|
||||
return self.parameters[pname].value
|
||||
return self.accessibles[pname].value
|
||||
|
||||
def setter(self, value, pname=pname):
|
||||
pobj = self.parameters[pname]
|
||||
pobj = self.accessibles[pname]
|
||||
value = pobj.datatype.validate(value)
|
||||
pobj.timestamp = time.time()
|
||||
if (not EVENT_ONLY_ON_CHANGED_VALUES) or (value != pobj.value):
|
||||
pobj.value = value
|
||||
# also send notification
|
||||
if self.parameters[pname].export:
|
||||
if self.accessibles[pname].export:
|
||||
self.log.debug('%s is now %r' % (pname, value))
|
||||
self.DISPATCHER.announce_update(self, pname, pobj)
|
||||
|
||||
@ -194,7 +199,7 @@ class ModuleMeta(type):
|
||||
# check information about Command's
|
||||
for attrname in attrs:
|
||||
if attrname.startswith('do_'):
|
||||
if attrname[3:] not in newtype.commands:
|
||||
if attrname[3:] not in newtype.accessibles:
|
||||
raise ProgrammingError('%r: command %r has to be specified '
|
||||
'explicitly!' % (name, attrname[3:]))
|
||||
attrs['__constructed__'] = True
|
||||
|
Reference in New Issue
Block a user