moved naming of enum types

moved adjusting of the name of enum types from the parameter name to
secop.datatypes.get_datatype

+ ignore additional items in datainfo (must-ignore policy)

Change-Id: Id1bb089c33729f15f06ad51e5c03bb333ef3c307
Reviewed-on: https://forge.frm2.tum.de/review/c/sine2020/secop/playground/+/22513
Tested-by: JenkinsCodeReview <bjoern_pedersen@frm2.tum.de>
Reviewed-by: Markus Zolliker <markus.zolliker@psi.ch>
This commit is contained in:
zolliker 2020-02-25 08:21:45 +01:00
parent 107e1d84b0
commit d021a116f1
4 changed files with 55 additions and 23 deletions

View File

@ -30,7 +30,7 @@ from collections import defaultdict
from secop.lib import mkthread, formatExtendedTraceback, formatExtendedStack from secop.lib import mkthread, formatExtendedTraceback, formatExtendedStack
from secop.lib.asynconn import AsynConn, ConnectionClosed from secop.lib.asynconn import AsynConn, ConnectionClosed
from secop.datatypes import get_datatype from secop.datatypes import get_datatype, EnumType
from secop.protocol.interface import encode_msg_frame, decode_msg from secop.protocol.interface import encode_msg_frame, decode_msg
from secop.protocol.messages import REQUEST2REPLY, ERRORPREFIX, EVENTREPLY, WRITEREQUEST, WRITEREPLY, \ from secop.protocol.messages import REQUEST2REPLY, ERRORPREFIX, EVENTREPLY, WRITEREQUEST, WRITEREPLY, \
READREQUEST, READREPLY, IDENTREQUEST, IDENTPREFIX, ENABLEEVENTSREQUEST, COMMANDREQUEST, DESCRIPTIONREQUEST READREQUEST, READREPLY, IDENTREQUEST, IDENTPREFIX, ENABLEEVENTSREQUEST, COMMANDREQUEST, DESCRIPTIONREQUEST
@ -428,12 +428,13 @@ class SecopClient(ProxyClient):
commands = {} commands = {}
accessibles = moddescr['accessibles'] accessibles = moddescr['accessibles']
for aname, aentry in accessibles.items(): for aname, aentry in accessibles.items():
aentry = dict(aentry, datatype=get_datatype(aentry['datainfo']))
iname = self.internalize_name(aname) iname = self.internalize_name(aname)
datatype = get_datatype(aentry['datainfo'], iname)
aentry = dict(aentry, datatype=datatype)
ident = '%s:%s' % (modname, aname) ident = '%s:%s' % (modname, aname)
self.identifier[modname, iname] = ident self.identifier[modname, iname] = ident
self.internal[ident] = modname, iname self.internal[ident] = modname, iname
if aentry['datainfo']['type'] == 'command': if datatype.IS_COMMAND:
commands[iname] = aentry commands[iname] = aentry
else: else:
parameters[iname] = aentry parameters[iname] = aentry

View File

@ -1066,41 +1066,72 @@ class StatusType(TupleOf):
return TupleOf.__getattr__(self, key) return TupleOf.__getattr__(self, key)
def floatargs(kwds):
return {k: v for k, v in kwds.items() if k in
{'unit', 'fmtstr', 'absolute_resolution', 'relative_resolution'}}
# argumentnames to lambda from spec! # argumentnames to lambda from spec!
# **kwds at the end are for must-ignore policy
DATATYPES = dict( DATATYPES = dict(
bool =BoolType, bool = lambda **kwds:
int =lambda min, max, **kwds: IntRange(minval=min, maxval=max, **kwds), BoolType(),
scaled =lambda scale, min, max, **kwds: ScaledInteger(scale=scale, minval=min*scale, maxval=max*scale, **kwds),
double =lambda min=None, max=None, **kwds: FloatRange(minval=min, maxval=max, **kwds), int = lambda min, max, **kwds:
blob =lambda maxbytes, minbytes=0: BLOBType(minbytes=minbytes, maxbytes=maxbytes), IntRange(minval=min, maxval=max),
string =lambda minchars=0, maxchars=None, isUTF8=False: StringType(minchars=minchars, maxchars=maxchars, isUTF8=isUTF8),
array =lambda maxlen, members, minlen=0: ArrayOf(get_datatype(members), minlen=minlen, maxlen=maxlen), scaled = lambda scale, min, max, **kwds:
tuple =lambda members: TupleOf(*tuple(map(get_datatype, members))), ScaledInteger(scale=scale, minval=min*scale, maxval=max*scale, **floatargs(kwds)),
enum =lambda members: EnumType('', members=members),
struct =lambda members, optional=None: StructOf(optional, double = lambda min=None, max=None, **kwds:
**dict((n, get_datatype(t)) for n, t in list(members.items()))), FloatRange(minval=min, maxval=max, **floatargs(kwds)),
command = lambda argument=None, result=None: CommandType(get_datatype(argument), get_datatype(result)),
limit = lambda members: LimitsType(get_datatype(members)), blob = lambda maxbytes, minbytes=0, **kwds:
BLOBType(minbytes=minbytes, maxbytes=maxbytes),
string = lambda minchars=0, maxchars=None, isUTF8=False, **kwds:
StringType(minchars=minchars, maxchars=maxchars, isUTF8=isUTF8),
array = lambda maxlen, members, minlen=0, pname='', **kwds:
ArrayOf(get_datatype(members, pname), minlen=minlen, maxlen=maxlen),
tuple = lambda members, pname='', **kwds:
TupleOf(*tuple((get_datatype(t, pname) for t in members))),
enum = lambda members, pname='', **kwds:
EnumType(pname, members=members),
struct = lambda members, optional=None, pname='', **kwds:
StructOf(optional, **dict((n, get_datatype(t, pname)) for n, t in list(members.items()))),
command = lambda argument=None, result=None, pname='', **kwds:
CommandType(get_datatype(argument, pname), get_datatype(result)),
limit = lambda members, pname='', **kwds:
LimitsType(get_datatype(members, pname)),
) )
# important for getting the right datatype from formerly jsonified descr. # important for getting the right datatype from formerly jsonified descr.
def get_datatype(json): def get_datatype(json, pname=''):
"""returns a DataType object from description """returns a DataType object from description
inverse of <DataType>.export_datatype() inverse of <DataType>.export_datatype()
the pname argument, if given, is used to name EnumTypes from the parameter name
""" """
if json is None: if json is None:
return json return json
if isinstance(json, list) and len(json) == 2: if isinstance(json, list) and len(json) == 2:
base, args = json # still allow old syntax base, kwargs = json # still allow old syntax
else: else:
try: try:
args = json.copy() kwargs = json.copy()
base = args.pop('type') base = kwargs.pop('type')
except (TypeError, KeyError, AttributeError): except (TypeError, KeyError, AttributeError):
raise BadValueError('a data descriptor must be a dict containing a "type" key, not %r' % json) raise BadValueError('a data descriptor must be a dict containing a "type" key, not %r' % json)
try: try:
return DATATYPES[base](**args) return DATATYPES[base](pname=pname, **kwargs)
except Exception as e: except Exception as e:
print(base, kwargs, repr(e))
raise BadValueError('invalid data descriptor: %r (%s)' % (json, str(e))) raise BadValueError('invalid data descriptor: %r (%s)' % (json, str(e)))

View File

@ -98,7 +98,7 @@ class EnumMember:
# be human readable (for debugging) # be human readable (for debugging)
def __repr__(self): def __repr__(self):
return '<%s.%s (%d)>' % (self.enum.name, self.name, self.value) return '<%s%s (%d)>' % (self.enum.name + '.' if self.enum.name else '', self.name, self.value)
# numeric operations: delegate to int. Do we really need any of those? # numeric operations: delegate to int. Do we really need any of those?

View File

@ -176,7 +176,7 @@ class Module(HasProperties, metaclass=ModuleMeta):
# paramobj might also be a command (not sure if this is needed) # paramobj might also be a command (not sure if this is needed)
if paramobj: if paramobj:
if propname == 'datatype': if propname == 'datatype':
paramobj.setProperty('datatype', get_datatype(cfgdict.pop(k))) paramobj.setProperty('datatype', get_datatype(cfgdict.pop(k), k))
elif propname in paramobj.getProperties(): elif propname in paramobj.getProperties():
paramobj.setProperty(propname, cfgdict.pop(k)) paramobj.setProperty(propname, cfgdict.pop(k))
else: else: