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.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.messages import REQUEST2REPLY, ERRORPREFIX, EVENTREPLY, WRITEREQUEST, WRITEREPLY, \
READREQUEST, READREPLY, IDENTREQUEST, IDENTPREFIX, ENABLEEVENTSREQUEST, COMMANDREQUEST, DESCRIPTIONREQUEST
@ -428,12 +428,13 @@ class SecopClient(ProxyClient):
commands = {}
accessibles = moddescr['accessibles']
for aname, aentry in accessibles.items():
aentry = dict(aentry, datatype=get_datatype(aentry['datainfo']))
iname = self.internalize_name(aname)
datatype = get_datatype(aentry['datainfo'], iname)
aentry = dict(aentry, datatype=datatype)
ident = '%s:%s' % (modname, aname)
self.identifier[modname, iname] = ident
self.internal[ident] = modname, iname
if aentry['datainfo']['type'] == 'command':
if datatype.IS_COMMAND:
commands[iname] = aentry
else:
parameters[iname] = aentry

View File

@ -1066,41 +1066,72 @@ class StatusType(TupleOf):
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!
# **kwds at the end are for must-ignore policy
DATATYPES = dict(
bool =BoolType,
int =lambda min, max, **kwds: IntRange(minval=min, maxval=max, **kwds),
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),
blob =lambda maxbytes, minbytes=0: BLOBType(minbytes=minbytes, maxbytes=maxbytes),
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),
tuple =lambda members: TupleOf(*tuple(map(get_datatype, members))),
enum =lambda members: EnumType('', members=members),
struct =lambda members, optional=None: StructOf(optional,
**dict((n, get_datatype(t)) for n, t in list(members.items()))),
command = lambda argument=None, result=None: CommandType(get_datatype(argument), get_datatype(result)),
limit = lambda members: LimitsType(get_datatype(members)),
bool = lambda **kwds:
BoolType(),
int = lambda min, max, **kwds:
IntRange(minval=min, maxval=max),
scaled = lambda scale, min, max, **kwds:
ScaledInteger(scale=scale, minval=min*scale, maxval=max*scale, **floatargs(kwds)),
double = lambda min=None, max=None, **kwds:
FloatRange(minval=min, maxval=max, **floatargs(kwds)),
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.
def get_datatype(json):
def get_datatype(json, pname=''):
"""returns a DataType object from description
inverse of <DataType>.export_datatype()
the pname argument, if given, is used to name EnumTypes from the parameter name
"""
if json is None:
return json
if isinstance(json, list) and len(json) == 2:
base, args = json # still allow old syntax
base, kwargs = json # still allow old syntax
else:
try:
args = json.copy()
base = args.pop('type')
kwargs = json.copy()
base = kwargs.pop('type')
except (TypeError, KeyError, AttributeError):
raise BadValueError('a data descriptor must be a dict containing a "type" key, not %r' % json)
try:
return DATATYPES[base](**args)
return DATATYPES[base](pname=pname, **kwargs)
except Exception as e:
print(base, kwargs, repr(e))
raise BadValueError('invalid data descriptor: %r (%s)' % (json, str(e)))

View File

@ -98,7 +98,7 @@ class EnumMember:
# be human readable (for debugging)
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?

View File

@ -176,7 +176,7 @@ class Module(HasProperties, metaclass=ModuleMeta):
# paramobj might also be a command (not sure if this is needed)
if paramobj:
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():
paramobj.setProperty(propname, cfgdict.pop(k))
else: