Switch descriptive data to new format

Change-Id: Ic8afe976564824d14394ed6a1b4b36df226648df
This commit is contained in:
Enrico Faulhaber 2017-07-10 16:33:37 +02:00
parent 2d27c6dd93
commit 8a63a6c63f
3 changed files with 83 additions and 12 deletions

View File

@ -27,6 +27,7 @@ import serial
from select import select from select import select
import threading import threading
import Queue import Queue
from collections import OrderedDict
import mlzlog import mlzlog
@ -151,7 +152,17 @@ class Client(object):
stopflag = False stopflag = False
def __init__(self, opts, autoconnect=True): def __init__(self, opts, autoconnect=True):
self.log = mlzlog.log.getChild('client', True) if 'testing' not in opts:
self.log = mlzlog.log.getChild('client', True)
else:
class logStub(object):
def info(self, *args):
pass
debug = info
error = info
warning = info
exception = info
self.log = logStub()
self._cache = dict() self._cache = dict()
if 'device' in opts: if 'device' in opts:
# serial port # serial port
@ -161,11 +172,15 @@ class Client(object):
self.connection = serial.Serial( self.connection = serial.Serial(
devport, baudrate=baudrate, timeout=1) devport, baudrate=baudrate, timeout=1)
self.connection.callbacks = [] self.connection.callbacks = []
else: elif 'testing' not in opts:
host = opts.pop('connectto', 'localhost') host = opts.pop('connectto', 'localhost')
port = int(opts.pop('port', 10767)) port = int(opts.pop('port', 10767))
self.contactPoint = "tcp://%s:%d" % (host, port) self.contactPoint = "tcp://%s:%d" % (host, port)
self.connection = TCPConnection(host, port) self.connection = TCPConnection(host, port)
else:
self.contactPoint = 'testing'
self.connection = opts.pop('testing')
# maps an expected reply to a list containing a single Event() # maps an expected reply to a list containing a single Event()
# upon rcv of that reply, entry is appended with False and # upon rcv of that reply, entry is appended with False and
# the data of the reply. # the data of the reply.
@ -305,15 +320,43 @@ class Client(object):
def _getDescribingParameterData(self, module, parameter): def _getDescribingParameterData(self, module, parameter):
return self._getDescribingModuleData(module)['parameters'][parameter] return self._getDescribingModuleData(module)['parameters'][parameter]
def _issueDescribe(self): def _decode_list_to_ordereddict(self, data):
_, self.equipment_id, self.describing_data = self._communicate( # takes a list of 2*N <key>, <value> entries and
'describe') # return an orderedDict from it
result = OrderedDict()
while len(data) > 1:
key = data.pop(0)
value = data.pop(0)
result[key] = value
return result
for module, moduleData in self.describing_data['modules'].items(): def _decode_substruct(self, specialkeys=[], data={}):
for parameter, parameterData in moduleData['parameters'].items(): # take a dict and move all keys which are not in specialkeys
datatype = get_datatype(parameterData['datatype']) # into a 'properties' subdict
self.describing_data['modules'][module]['parameters'] \ # specialkeys entries are converted from list to ordereddict
[parameter]['datatype'] = datatype result = {}
for k in specialkeys:
result[k] = self._decode_list_to_ordereddict(data.pop(k, []))
result['properties'] = data
return result
def _issueDescribe(self):
_, self.equipment_id, describing_data = self._communicate('describe')
try:
describing_data = self._decode_substruct(['modules'], describing_data)
for modname, module in describing_data['modules'].items():
describing_data['modules'][modname] = self._decode_substruct(['parameters', 'commands'], module)
self.describing_data = describing_data
for module, moduleData in self.describing_data['modules'].items():
for parameter, parameterData in moduleData['parameters'].items():
datatype = get_datatype(parameterData['datatype'])
self.describing_data['modules'][module]['parameters'] \
[parameter]['datatype'] = datatype
except Exception as exc:
print formatException(verbose=True)
raise
def register_callback(self, module, parameter, cb): def register_callback(self, module, parameter, cb):
self.log.debug('registering callback %r for %s:%s' % self.log.debug('registering callback %r for %s:%s' %

View File

@ -79,7 +79,11 @@ def formatExtendedFrame(frame):
ret.append('\n') ret.append('\n')
return ret return ret
def formatExtendedTraceback(etype, value, tb): def formatExtendedTraceback(exc_info=None):
if exc_info is None:
etype, value, tb = sys.exc_info()
else:
etype, value, tb = exc_info
ret = ['Traceback (most recent call last):\n'] ret = ['Traceback (most recent call last):\n']
while tb is not None: while tb is not None:
frame = tb.tb_frame frame = tb.tb_frame
@ -116,10 +120,12 @@ def formatExtendedStack(level=1):
f = f.f_back f = f.f_back
return ''.join(ret).rstrip('\n') return ''.join(ret).rstrip('\n')
def formatException(cut=0, exc_info=None): def formatException(cut=0, exc_info=None, verbose=False):
"""Format an exception with traceback, but leave out the first `cut` """Format an exception with traceback, but leave out the first `cut`
number of frames. number of frames.
""" """
if verbose:
return formatExtendedTraceback(exc_info)
if exc_info is None: if exc_info is None:
typ, val, tb = sys.exc_info() typ, val, tb = sys.exc_info()
else: else:

View File

@ -208,6 +208,28 @@ class Dispatcher(object):
return {} return {}
def get_descriptive_data(self): def get_descriptive_data(self):
"""returns a python object which upon serialisation results in the descriptive data"""
# XXX: be lazy and cache this?
# format: {[{[{[, specific entries first
result = {'modules': []}
for modulename in self._export:
module = self.get_module(modulename)
# some of these need rework !
mod_desc = {'parameters':[], 'commands':[]}
for pname, param in self.list_module_params(modulename, only_static=True).items():
mod_desc['parameters'].extend([pname, param])
for cname, cmd in self.list_module_cmds(modulename).items():
mod_desc['commands'].extend([cname, cmd])
for propname, prop in module.PROPERTIES.items():
mod_desc[propname] = prop
result['modules'].extend([modulename, mod_desc])
result['equipment_id'] = self.equipment_id
result['firmware'] = 'The SECoP playground'
result['version'] = "2017.07"
# XXX: what else?
return result
def get_descriptive_data_old(self):
# XXX: be lazy and cache this? # XXX: be lazy and cache this?
result = {'modules': {}} result = {'modules': {}}
for modulename in self._export: for modulename in self._export: