changes according to new syntax decided on vidconf 2019-08-07

- modules and accessibles are changed back to a JSON object
- datatype is changed from a JSON array with 2 elements to
  a JSON object with one element, with the basic type as key
- the client side is kept compatible with the old syntax

Change-Id: Icd640bbcdec26a895c96720e107e874529340a73
Reviewed-on: https://forge.frm2.tum.de/review/c/sine2020/secop/playground/+/21032
Tested-by: JenkinsCodeReview <bjoern_pedersen@frm2.tum.de>
Reviewed-by: Markus Zolliker <markus.zolliker@psi.ch>
This commit is contained in:
zolliker 2019-08-19 17:41:45 +02:00
parent ec9a02f5c1
commit 6772455dba
5 changed files with 150 additions and 152 deletions

View File

@ -136,8 +136,8 @@ class FloatRange(DataType):
raise BadValueError(u'relative_resolution MUST be >=0') raise BadValueError(u'relative_resolution MUST be >=0')
def export_datatype(self): def export_datatype(self):
return [u'double', {k: getattr(self, k) for k, v in self._defaults.items() return {u'double': {k: getattr(self, k) for k, v in self._defaults.items()
if v != getattr(self, k)}] if v != getattr(self, k)}}
def __call__(self, value): def __call__(self, value):
try: try:
@ -147,11 +147,11 @@ class FloatRange(DataType):
prec = max(abs(value * self.relative_resolution), self.absolute_resolution) prec = max(abs(value * self.relative_resolution), self.absolute_resolution)
if self.min - prec <= value <= self.max + prec: if self.min - prec <= value <= self.max + prec:
return min(max(value, self.min), self.max) return min(max(value, self.min), self.max)
raise BadValueError(u'%g should be a float between %g and %g' % raise BadValueError(u'%.14g should be a float between %.14g and %.14g' %
(value, self.min, self.max)) (value, self.min, self.max))
def __repr__(self): def __repr__(self):
items = [u'%s=%r' % (k,v) for k,v in self.export_datatype()[1].items()] items = [u'%s=%r' % (k,v) for k,v in self.export_datatype()['double'].items()]
return u'FloatRange(%s)' % (', '.join(items)) return u'FloatRange(%s)' % (', '.join(items))
def export_value(self, value): def export_value(self, value):
@ -187,7 +187,7 @@ class IntRange(DataType):
raise BadValueError(u'Max must be larger then min!') raise BadValueError(u'Max must be larger then min!')
def export_datatype(self): def export_datatype(self):
return [u'int', {"min": self.min, "max": self.max}] return {u'int': {"min": self.min, "max": self.max}}
def __call__(self, value): def __call__(self, value):
try: try:
@ -260,7 +260,7 @@ class ScaledInteger(DataType):
info['scale'] = self.scale info['scale'] = self.scale
info['min'] = int((self.min + self.scale * 0.5) // self.scale) info['min'] = int((self.min + self.scale * 0.5) // self.scale)
info['max'] = int((self.max + self.scale * 0.5) // self.scale) info['max'] = int((self.max + self.scale * 0.5) // self.scale)
return [u'scaled', info] return {u'scaled': info}
def __call__(self, value): def __call__(self, value):
try: try:
@ -279,7 +279,7 @@ class ScaledInteger(DataType):
return value # return 'actual' value (which is more discrete than a float) return value # return 'actual' value (which is more discrete than a float)
def __repr__(self): def __repr__(self):
hints = self.export_datatype()[1] hints = self.export_datatype()['scaled']
hints.pop('scale') hints.pop('scale')
items = ['%g' % self.scale] items = ['%g' % self.scale]
for k,v in hints.items(): for k,v in hints.items():
@ -322,7 +322,7 @@ class EnumType(DataType):
return EnumType(self._enum) return EnumType(self._enum)
def export_datatype(self): def export_datatype(self):
return [u'enum'] + [{u"members":dict((m.name, m.value) for m in self._enum.members)}] return {u'enum': {u"members":dict((m.name, m.value) for m in self._enum.members)}}
def __repr__(self): def __repr__(self):
return u"EnumType(%r, %s)" % (self._enum.name, ', '.join(u'%s=%d' %(m.name, m.value) for m in self._enum.members)) return u"EnumType(%r, %s)" % (self._enum.name, ', '.join(u'%s=%d' %(m.name, m.value) for m in self._enum.members))
@ -367,7 +367,7 @@ class BLOBType(DataType):
self.default = b'\0' * self.minsize self.default = b'\0' * self.minsize
def export_datatype(self): def export_datatype(self):
return [u'blob', dict(min=self.minsize, max=self.maxsize)] return {u'blob': dict(min=self.minsize, max=self.maxsize)}
def __repr__(self): def __repr__(self):
return u'BLOB(%d, %d)' % (self.minsize, self.maxsize) return u'BLOB(%d, %d)' % (self.minsize, self.maxsize)
@ -418,7 +418,7 @@ class StringType(DataType):
self.default = u' ' * self.minsize self.default = u' ' * self.minsize
def export_datatype(self): def export_datatype(self):
return [u'string', dict(min=self.minsize, max=self.maxsize)] return {u'string': dict(min=self.minsize, max=self.maxsize)}
def __repr__(self): def __repr__(self):
return u'StringType(%d, %d)' % (self.minsize, self.maxsize) return u'StringType(%d, %d)' % (self.minsize, self.maxsize)
@ -479,7 +479,7 @@ class BoolType(DataType):
default = False default = False
def export_datatype(self): def export_datatype(self):
return [u'bool', {}] return {u'bool': {}}
def __repr__(self): def __repr__(self):
return u'BoolType()' return u'BoolType()'
@ -541,8 +541,8 @@ class ArrayOf(DataType):
self.default = [members.default] * self.minsize self.default = [members.default] * self.minsize
def export_datatype(self): def export_datatype(self):
return [u'array', dict(min=self.minsize, max=self.maxsize, return {u'array': dict(min=self.minsize, max=self.maxsize,
members=self.members.export_datatype())] members=self.members.export_datatype())}
def __repr__(self): def __repr__(self):
return u'ArrayOf(%s, %s, %s)' % ( return u'ArrayOf(%s, %s, %s)' % (
@ -600,7 +600,7 @@ class TupleOf(DataType):
self.default = tuple(el.default for el in members) self.default = tuple(el.default for el in members)
def export_datatype(self): def export_datatype(self):
return [u'tuple', dict(members=[subtype.export_datatype() for subtype in self.members])] return {u'tuple': dict(members=[subtype.export_datatype() for subtype in self.members])}
def __repr__(self): def __repr__(self):
return u'TupleOf(%s)' % u', '.join([repr(st) for st in self.members]) return u'TupleOf(%s)' % u', '.join([repr(st) for st in self.members])
@ -659,10 +659,10 @@ class StructOf(DataType):
self.default = dict((k,el.default) for k, el in members.items()) self.default = dict((k,el.default) for k, el in members.items())
def export_datatype(self): def export_datatype(self):
res = [u'struct', dict(members=dict((n, s.export_datatype()) res = {u'struct': dict(members=dict((n, s.export_datatype())
for n, s in list(self.members.items())))] for n, s in list(self.members.items())))}
if self.optional: if self.optional:
res[1]['optional'] = self.optional res['struct']['optional'] = self.optional
return res return res
def __repr__(self): def __repr__(self):
@ -728,11 +728,12 @@ class CommandType(DataType):
def export_datatype(self): def export_datatype(self):
a, r = self.argument, self.result a, r = self.argument, self.result
props = {}
if a is not None: if a is not None:
a = a.export_datatype() props['argument'] = a.export_datatype()
if r is not None: if r is not None:
r = r.export_datatype() props['result'] = r.export_datatype()
return [u'command', dict(argument=a, result=r)] return {u'command': props}
def __repr__(self): def __repr__(self):
argstr = repr(self.argument) if self.argument else '' argstr = repr(self.argument) if self.argument else ''
@ -875,12 +876,12 @@ DATATYPES = dict(
int =lambda min, max, **kwds: IntRange(minval=min, maxval=max, **kwds), 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), 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), double =lambda min=None, max=None, **kwds: FloatRange(minval=min, maxval=max, **kwds),
blob =lambda min=0, max=None: BLOBType(minsize=min, maxsize=max), blob =lambda max, min=0: BLOBType(minsize=min, maxsize=max),
string =lambda min=0, max=None: StringType(minsize=min, maxsize=max), string =lambda max, min=0: StringType(minsize=min, maxsize=max),
array =lambda min, max, members: ArrayOf(get_datatype(members), minsize=min, maxsize=max), array =lambda max, members, min=0: ArrayOf(get_datatype(members), minsize=min, maxsize=max),
tuple =lambda members=[]: TupleOf(*map(get_datatype, members)), tuple =lambda members: TupleOf(*map(get_datatype, members)),
enum =lambda members={}: EnumType('', members=members), enum =lambda members: EnumType('', members=members),
struct =lambda optional=None, members=None: StructOf(optional, struct =lambda members, optional=None: StructOf(optional,
**dict((n, get_datatype(t)) for n, t in list(members.items()))), **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)), command = lambda argument=None, result=None: CommandType(get_datatype(argument), get_datatype(result)),
) )
@ -894,15 +895,13 @@ def get_datatype(json):
""" """
if json is None: if json is None:
return json return json
if not isinstance(json, list): if isinstance(json, list) and len(json) == 2:
raise BadValueError( base, args = json # still allow old syntax
u'Can not interpret datatype %r, it should be a list!' % json) elif isinstance(json, dict) and len(json) == 1:
if len(json) != 2: base, args = tuple(json.items())[0]
raise BadValueError(u'Can not interpret datatype %r, it should be a list of 2 elements!' % json) else:
base, args = json raise BadValueError('a data descriptor must be a dict (len=1), not %r' % json)
if base in DATATYPES: try:
try: return DATATYPES[base](**args)
return DATATYPES[base](**args) except (TypeError, AttributeError, KeyError):
except (TypeError, AttributeError): raise BadValueError(u'invalid data descriptor: %r' % json)
raise BadValueError(u'Invalid datatype descriptor in %r' % json)
raise BadValueError(u'can not convert %r to datatype: unknown descriptor!' % json)

View File

@ -39,6 +39,7 @@ Interface to the modules:
from __future__ import division, print_function from __future__ import division, print_function
import threading import threading
from collections import OrderedDict
from time import time as currenttime from time import time as currenttime
from secop.errors import SECoPServerError as InternalError from secop.errors import SECoPServerError as InternalError
@ -173,21 +174,20 @@ class Dispatcher(object):
self.log.debug(u'export_accessibles(%r)' % modulename) self.log.debug(u'export_accessibles(%r)' % modulename)
if modulename in self._export: if modulename in self._export:
# omit export=False params! # omit export=False params!
res = [] res = OrderedDict()
for aobj in self.get_module(modulename).accessibles.values(): for aobj in self.get_module(modulename).accessibles.values():
if aobj.export: if aobj.export:
res.append([aobj.export, aobj.for_export()]) res[aobj.export] = aobj.for_export()
self.log.debug(u'list accessibles for module %s -> %r' % self.log.debug(u'list accessibles for module %s -> %r' %
(modulename, res)) (modulename, res))
return res return res
self.log.debug(u'-> module is not to be exported!') self.log.debug(u'-> module is not to be exported!')
return [] return OrderedDict()
def get_descriptive_data(self): def get_descriptive_data(self):
"""returns a python object which upon serialisation results in the descriptive data""" """returns a python object which upon serialisation results in the descriptive data"""
# XXX: be lazy and cache this? # XXX: be lazy and cache this?
# format: {[{[{[, specific entries first result = {u'modules': OrderedDict()}
result = {u'modules': []}
for modulename in self._export: for modulename in self._export:
module = self.get_module(modulename) module = self.get_module(modulename)
if not module.properties.get('export', False): if not module.properties.get('export', False):
@ -196,10 +196,10 @@ class Dispatcher(object):
mod_desc = {u'accessibles': self.export_accessibles(modulename)} mod_desc = {u'accessibles': self.export_accessibles(modulename)}
mod_desc.update(module.exportProperties()) mod_desc.update(module.exportProperties())
mod_desc.pop('export', False) mod_desc.pop('export', False)
result[u'modules'].append([modulename, mod_desc]) result[u'modules'][modulename] = mod_desc
result[u'equipment_id'] = self.equipment_id result[u'equipment_id'] = self.equipment_id
result[u'firmware'] = u'FRAPPY - The Python Framework for SECoP' result[u'firmware'] = u'FRAPPY - The Python Framework for SECoP'
result[u'version'] = u'2019.05' result[u'version'] = u'2019.08'
result.update(self.nodeprops) result.update(self.nodeprops)
return result return result

View File

@ -26,7 +26,7 @@ from __future__ import division, print_function
IDENTREQUEST = u'*IDN?' # literal IDENTREQUEST = u'*IDN?' # literal
# literal! first part is fixed! # literal! first part is fixed!
IDENTREPLY = u'SINE2020&ISSE,SECoP,V2019-03-20,v1.0 RC1' IDENTREPLY = u'SINE2020&ISSE,SECoP,V2019-08-20,v1.0 RC2'
DESCRIPTIONREQUEST = u'describe' # literal DESCRIPTIONREQUEST = u'describe' # literal
DESCRIPTIONREPLY = u'describing' # +<id> +json DESCRIPTIONREPLY = u'describing' # +<id> +json

View File

@ -49,7 +49,7 @@ def test_DataType():
def test_FloatRange(): def test_FloatRange():
dt = FloatRange(-3.14, 3.14) dt = FloatRange(-3.14, 3.14)
copytest(dt) copytest(dt)
assert dt.export_datatype() == [u'double', {u'min':-3.14, u'max':3.14}] assert dt.export_datatype() == {u'double': {u'min':-3.14, u'max':3.14}}
with pytest.raises(ValueError): with pytest.raises(ValueError):
dt(9) dt(9)
@ -68,18 +68,18 @@ def test_FloatRange():
FloatRange(u'x', u'Y') FloatRange(u'x', u'Y')
# check that unit can be changed # check that unit can be changed
dt.unit = u'K' dt.unit = u'K'
assert dt.export_datatype() == [u'double', {u'min':-3.14, u'max':3.14, u'unit': u'K'}] assert dt.export_datatype() == {u'double': {u'min':-3.14, u'max':3.14, u'unit': u'K'}}
dt = FloatRange() dt = FloatRange()
copytest(dt) copytest(dt)
assert dt.export_datatype() == [u'double', {}] assert dt.export_datatype() == {u'double': {}}
dt = FloatRange(unit=u'X', fmtstr=u'%.2f', absolute_resolution=1, dt = FloatRange(unit=u'X', fmtstr=u'%.2f', absolute_resolution=1,
relative_resolution=0.1) relative_resolution=0.1)
copytest(dt) copytest(dt)
assert dt.export_datatype() == [u'double', {u'unit':u'X', u'fmtstr':u'%.2f', assert dt.export_datatype() == {u'double': {u'unit':u'X', u'fmtstr':u'%.2f',
u'absolute_resolution':1.0, u'absolute_resolution':1.0,
u'relative_resolution':0.1}] u'relative_resolution':0.1}}
assert dt(4) == 4 assert dt(4) == 4
assert dt.format_value(3.14) == u'3.14 X' assert dt.format_value(3.14) == u'3.14 X'
assert dt.format_value(3.14, u'') == u'3.14' assert dt.format_value(3.14, u'') == u'3.14'
@ -89,7 +89,7 @@ def test_FloatRange():
def test_IntRange(): def test_IntRange():
dt = IntRange(-3, 3) dt = IntRange(-3, 3)
copytest(dt) copytest(dt)
assert dt.export_datatype() == [u'int', {u'min':-3, u'max':3}] assert dt.export_datatype() == {u'int': {u'min':-3, u'max':3}}
with pytest.raises(ValueError): with pytest.raises(ValueError):
dt(9) dt(9)
@ -106,16 +106,16 @@ def test_IntRange():
dt = IntRange() dt = IntRange()
copytest(dt) copytest(dt)
assert dt.export_datatype()[0] == u'int' assert tuple(dt.export_datatype()) == ('int',)
assert dt.export_datatype()[1][u'min'] < 0 < dt.export_datatype()[1][u'max'] assert dt.export_datatype()['int'][u'min'] < 0 < dt.export_datatype()['int'][u'max']
assert dt.export_datatype() == [u'int', {u'max': 16777216, u'min': -16777216}] assert dt.export_datatype() == {u'int': {u'max': 16777216, u'min': -16777216}}
assert dt.format_value(42) == u'42' assert dt.format_value(42) == u'42'
def test_ScaledInteger(): def test_ScaledInteger():
dt = ScaledInteger(0.01, -3, 3) dt = ScaledInteger(0.01, -3, 3)
copytest(dt) copytest(dt)
# serialisation of datatype contains limits on the 'integer' value # serialisation of datatype contains limits on the 'integer' value
assert dt.export_datatype() == [u'scaled', {u'scale':0.01, u'min':-300, u'max':300}] assert dt.export_datatype() == {u'scaled': {u'scale':0.01, u'min':-300, u'max':300}}
with pytest.raises(ValueError): with pytest.raises(ValueError):
dt(9) dt(9)
@ -135,7 +135,7 @@ def test_ScaledInteger():
ScaledInteger(scale=-10, minval=1, maxval=2) ScaledInteger(scale=-10, minval=1, maxval=2)
# check that unit can be changed # check that unit can be changed
dt.unit = u'A' dt.unit = u'A'
assert dt.export_datatype() == [u'scaled', {u'scale':0.01, u'min':-300, u'max':300, u'unit': u'A'}] assert dt.export_datatype() == {u'scaled': {u'scale':0.01, u'min':-300, u'max':300, u'unit': u'A'}}
assert dt.export_value(0.0001) == int(0) assert dt.export_value(0.0001) == int(0)
assert dt.export_value(2.71819) == int(272) assert dt.export_value(2.71819) == int(272)
@ -144,10 +144,10 @@ def test_ScaledInteger():
dt = ScaledInteger(0.003, 0, 1, unit=u'X', fmtstr=u'%.1f', dt = ScaledInteger(0.003, 0, 1, unit=u'X', fmtstr=u'%.1f',
absolute_resolution=0.001, relative_resolution=1e-5) absolute_resolution=0.001, relative_resolution=1e-5)
copytest(dt) copytest(dt)
assert dt.export_datatype() == [u'scaled', {u'scale':0.003, u'min':0, u'max':333, assert dt.export_datatype() == {u'scaled': {u'scale':0.003, u'min':0, u'max':333,
u'unit':u'X', u'fmtstr':u'%.1f', u'unit':u'X', u'fmtstr':u'%.1f',
u'absolute_resolution':0.001, u'absolute_resolution':0.001,
u'relative_resolution':1e-5}] u'relative_resolution':1e-5}}
assert dt(0.4) == 0.399 assert dt(0.4) == 0.399
assert dt.format_value(0.4) == u'0.4 X' assert dt.format_value(0.4) == u'0.4 X'
assert dt.format_value(0.4, u'') == u'0.4' assert dt.format_value(0.4, u'') == u'0.4'
@ -166,7 +166,7 @@ def test_EnumType():
dt = EnumType(u'dt', a=3, c=7, stuff=1) dt = EnumType(u'dt', a=3, c=7, stuff=1)
copytest(dt) copytest(dt)
assert dt.export_datatype() == [u'enum', dict(members=dict(a=3, c=7, stuff=1))] assert dt.export_datatype() == {u'enum': dict(members=dict(a=3, c=7, stuff=1))}
with pytest.raises(ValueError): with pytest.raises(ValueError):
dt(9) dt(9)
@ -201,14 +201,14 @@ def test_BLOBType():
# test constructor catching illegal arguments # test constructor catching illegal arguments
dt = BLOBType() dt = BLOBType()
copytest(dt) copytest(dt)
assert dt.export_datatype() == [u'blob', {u'min':0, u'max':255}] assert dt.export_datatype() == {u'blob': {u'min':0, u'max':255}}
dt = BLOBType(10) dt = BLOBType(10)
copytest(dt) copytest(dt)
assert dt.export_datatype() == [u'blob', {u'min':10, u'max':10}] assert dt.export_datatype() == {u'blob': {u'min':10, u'max':10}}
dt = BLOBType(3, 10) dt = BLOBType(3, 10)
copytest(dt) copytest(dt)
assert dt.export_datatype() == [u'blob', {u'min':3, u'max':10}] assert dt.export_datatype() == {u'blob': {u'min':3, u'max':10}}
with pytest.raises(ValueError): with pytest.raises(ValueError):
dt(9) dt(9)
@ -235,11 +235,11 @@ def test_StringType():
copytest(dt) copytest(dt)
dt = StringType(12) dt = StringType(12)
copytest(dt) copytest(dt)
assert dt.export_datatype() == [u'string', {u'min':12, u'max':12}] assert dt.export_datatype() == {u'string': {u'min':12, u'max':12}}
dt = StringType(4, 11) dt = StringType(4, 11)
copytest(dt) copytest(dt)
assert dt.export_datatype() == [u'string', {u'min':4, u'max':11}] assert dt.export_datatype() == {u'string': {u'min':4, u'max':11}}
with pytest.raises(ValueError): with pytest.raises(ValueError):
dt(9) dt(9)
@ -264,7 +264,8 @@ def test_StringType():
def test_TextType(): def test_TextType():
# test constructor catching illegal arguments # test constructor catching illegal arguments
dt = TextType(12) dt = TextType(12)
assert dt.export_datatype() == [u'string', {u'min':0, u'max':12}] copytest(dt)
assert dt.export_datatype() == {u'string': {u'min':0, u'max':12}}
with pytest.raises(ValueError): with pytest.raises(ValueError):
dt(9) dt(9)
@ -286,7 +287,7 @@ def test_BoolType():
# test constructor catching illegal arguments # test constructor catching illegal arguments
dt = BoolType() dt = BoolType()
copytest(dt) copytest(dt)
assert dt.export_datatype() == [u'bool', {}] assert dt.export_datatype() == {u'bool': {}}
with pytest.raises(ValueError): with pytest.raises(ValueError):
dt(9) dt(9)
@ -318,16 +319,16 @@ def test_ArrayOf():
ArrayOf(-3, IntRange(-10,10)) ArrayOf(-3, IntRange(-10,10))
dt = ArrayOf(IntRange(-10, 10), 5) dt = ArrayOf(IntRange(-10, 10), 5)
copytest(dt) copytest(dt)
assert dt.export_datatype() == [u'array', {u'min':5, u'max':5, assert dt.export_datatype() == {u'array': {u'min':5, u'max':5,
u'members':[u'int', {u'min':-10, u'members':{u'int': {u'min':-10,
u'max':10}]}] u'max':10}}}}
dt = ArrayOf(FloatRange(-10, 10, unit=u'Z'), 1, 3) dt = ArrayOf(FloatRange(-10, 10, unit=u'Z'), 1, 3)
copytest(dt) copytest(dt)
assert dt.export_datatype() == [u'array', {u'min':1, u'max':3, assert dt.export_datatype() == {u'array': {u'min':1, u'max':3,
u'members':[u'double', {u'min':-10, u'members':{u'double': {u'min':-10,
u'max':10, u'max':10,
u'unit':u'Z'}]}] u'unit':u'Z'}}}}
with pytest.raises(ValueError): with pytest.raises(ValueError):
dt(9) dt(9)
with pytest.raises(ValueError): with pytest.raises(ValueError):
@ -350,9 +351,9 @@ def test_TupleOf():
dt = TupleOf(IntRange(-10, 10), BoolType()) dt = TupleOf(IntRange(-10, 10), BoolType())
copytest(dt) copytest(dt)
assert dt.export_datatype() == [u'tuple', {u'members':[[u'int', {u'min':-10, assert dt.export_datatype() == {u'tuple': {u'members':[{u'int': {u'min':-10,
u'max':10}], u'max':10}},
[u'bool', {}]]}] {u'bool': {}}]}}
with pytest.raises(ValueError): with pytest.raises(ValueError):
dt(9) dt(9)
@ -377,12 +378,12 @@ def test_StructOf():
dt = StructOf(a_string=StringType(0, 55), an_int=IntRange(0, 999), dt = StructOf(a_string=StringType(0, 55), an_int=IntRange(0, 999),
optional=[u'an_int']) optional=[u'an_int'])
copytest(dt) copytest(dt)
assert dt.export_datatype() == [u'struct', {u'members':{u'a_string': assert dt.export_datatype() == {u'struct': {u'members':{u'a_string':
[u'string', {u'min':0, u'max':55}], {u'string': {u'min':0, u'max':55}},
u'an_int': u'an_int':
[u'int', {u'min':0, u'max':999}],}, {u'int': {u'min':0, u'max':999}},},
u'optional':[u'an_int'], u'optional':[u'an_int'],
}] }}
with pytest.raises(ValueError): with pytest.raises(ValueError):
dt(9) dt(9)
@ -403,14 +404,14 @@ def test_StructOf():
def test_Command(): def test_Command():
dt = CommandType() dt = CommandType()
assert dt.export_datatype() == [u'command', {u'argument':None, u'result':None}] assert dt.export_datatype() == {u'command': {}}
dt = CommandType(IntRange(-1,1)) dt = CommandType(IntRange(-1,1))
assert dt.export_datatype() == [u'command', {u'argument':[u'int', {u'min':-1, u'max':1}], u'result':None}] assert dt.export_datatype() == {u'command': {u'argument':{u'int': {u'min':-1, u'max':1}}}}
dt = CommandType(IntRange(-1,1), IntRange(-3,3)) dt = CommandType(IntRange(-1,1), IntRange(-3,3))
assert dt.export_datatype() == [u'command', {u'argument':[u'int', {u'min':-1, u'max':1}], assert dt.export_datatype() == {u'command': {u'argument':{u'int': {u'min':-1, u'max':1}},
u'result':[u'int', {u'min':-3, u'max':3}]}] u'result':{u'int': {u'min':-3, u'max':3}}}}
def test_get_datatype(): def test_get_datatype():
@ -421,148 +422,146 @@ def test_get_datatype():
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype(str) get_datatype(str)
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'undefined']) get_datatype({u'undefined': {}})
assert isinstance(get_datatype([u'bool', {}]), BoolType) assert isinstance(get_datatype({u'bool': {}}), BoolType)
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'bool']) get_datatype([u'bool'])
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'bool', 3]) get_datatype({u'bool': 3})
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'int', {u'min':-10}]) get_datatype({u'int': {u'min':-10}})
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'int', {u'max':10}]) get_datatype({u'int': {u'max':10}})
assert isinstance(get_datatype([u'int', {u'min':-10, u'max':10}]), IntRange) assert isinstance(get_datatype({u'int': {u'min':-10, u'max':10}}), IntRange)
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'int', {u'min':10, u'max':-10}]) get_datatype({u'int': {u'min':10, u'max':-10}})
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'int']) get_datatype([u'int'])
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'int', {}]) get_datatype({u'int': {}})
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'int', 1, 2]) get_datatype({u'int': 1, u'x': 2})
assert isinstance(get_datatype([u'double', {}]), FloatRange) assert isinstance(get_datatype({u'double': {}}), FloatRange)
assert isinstance(get_datatype([u'double', {u'min':-2.718}]), FloatRange) assert isinstance(get_datatype({u'double': {u'min':-2.718}}), FloatRange)
assert isinstance(get_datatype([u'double', {u'max':3.14}]), FloatRange) assert isinstance(get_datatype({u'double': {u'max':3.14}}), FloatRange)
assert isinstance(get_datatype([u'double', {u'min':-9.9, u'max':11.1}]), assert isinstance(get_datatype({u'double': {u'min':-9.9, u'max':11.1}}),
FloatRange) FloatRange)
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'double']) get_datatype([u'double'])
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'double', {u'min':10, u'max':-10}]) get_datatype({u'double': {u'min':10, u'max':-10}})
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'double', 1, 2]) get_datatype({u'double': {}, u'x': 2})
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'scaled', {u'scale':0.01,u'min':-2.718}]) get_datatype({u'scaled': {u'scale':0.01,u'min':-2.718}})
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'scaled', {u'scale':0.02,u'max':3.14}]) get_datatype({u'scaled': {u'scale':0.02,u'max':3.14}})
assert isinstance(get_datatype([u'scaled', {u'scale':0.03, assert isinstance(get_datatype({u'scaled': {u'scale':0.03,
u'min':-99, u'min':-99,
u'max':111}]), ScaledInteger) u'max':111}}), ScaledInteger)
dt = ScaledInteger(scale=0.03, minval=0, maxval=9.9) dt = ScaledInteger(scale=0.03, minval=0, maxval=9.9)
assert dt.export_datatype() == [u'scaled', {u'max':330, u'min':0, u'scale':0.03}] assert dt.export_datatype() == {u'scaled': {u'max':330, u'min':0, u'scale':0.03}}
assert get_datatype(dt.export_datatype()).export_datatype() == dt.export_datatype() assert get_datatype(dt.export_datatype()).export_datatype() == dt.export_datatype()
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'scaled']) # dict missing get_datatype([u'scaled']) # dict missing
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'scaled', {u'min':-10, u'max':10}]) # no scale get_datatype({u'scaled': {u'min':-10, u'max':10}}) # no scale
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'scaled', {u'min':10, u'max':-10}]) # limits reversed get_datatype({u'scaled': {u'min':10, u'max':-10}}) # limits reversed
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'scaled', {}, 1, 2]) # trailing data get_datatype({u'scaled': {u'min':10, u'max':-10, u'x': 2}})
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'enum']) get_datatype([u'enum'])
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'enum', dict(a=-2)]) get_datatype({u'enum': dict(a=-2)})
assert isinstance(get_datatype([u'enum', {u'members':dict(a=-2)}]), EnumType) assert isinstance(get_datatype({u'enum': {u'members':dict(a=-2)}}), EnumType)
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'enum', 10, -10]) get_datatype({u'enum': dict(a=-2), u'x': 1})
with pytest.raises(ValueError):
get_datatype([u'enum', [1, 2, 3]])
assert isinstance(get_datatype([u'blob', {u'max':1}]), BLOBType) assert isinstance(get_datatype({u'blob': {u'max':1}}), BLOBType)
assert isinstance(get_datatype([u'blob', {u'min':1, u'max':10}]), BLOBType) assert isinstance(get_datatype({u'blob': {u'min':1, u'max':10}}), BLOBType)
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'blob', {u'min':10, u'max':1}]) get_datatype({u'blob': {u'min':10, u'max':1}})
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'blob', {u'min':10, u'max':-10}]) get_datatype({u'blob': {u'min':10, u'max':-10}})
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'blob', 10, -10, 1]) get_datatype({u'blob': {u'min':10, u'max':-10}, u'x': 0})
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'string']) get_datatype([u'string'])
assert isinstance(get_datatype([u'string', {u'min':1}]), StringType) assert isinstance(get_datatype({u'string': {u'max':1}}), StringType)
assert isinstance(get_datatype([u'string', {u'min':1, u'max':10}]), StringType) assert isinstance(get_datatype({u'string': {u'min':1, u'max':10}}), StringType)
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'string', {u'min':10, u'max':1}]) get_datatype({u'string': {u'min':10, u'max':1}})
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'string', {u'min':10, u'max':-10}]) get_datatype({u'string': {u'min':10, u'max':-10}})
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'string', 10, -10, 1]) get_datatype({u'string': {u'min':10, u'max':-10, u'x': 0}})
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'array']) get_datatype([u'array'])
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'array', 1]) get_datatype({u'array': 1})
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'array', [1], 2, 3]) get_datatype({u'array': [1]})
assert isinstance(get_datatype([u'array', {u'min':1, u'max':1, assert isinstance(get_datatype({u'array': {u'min':1, u'max':1,
u'members':[u'blob', {u'max':1}]}] u'members':{u'blob': {u'max':1}}}}
), ArrayOf) ), ArrayOf)
assert isinstance(get_datatype([u'array', {u'min':1, u'max':1, assert isinstance(get_datatype({u'array': {u'min':1, u'max':1,
u'members':[u'blob', {u'max':1}]}] u'members':{u'blob': {u'max':1}}}}
).members, BLOBType) ).members, BLOBType)
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'array', {u'members':[u'blob', {u'max':1}], u'min':-10}]) get_datatype({u'array': {u'members':{u'blob': {u'max':1}}, u'min':-10}})
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'array', {u'members':[u'blob', {u'max':1}], get_datatype({u'array': {u'members':{u'blob': {u'max':1}},
u'min':10, 'max':1}]) u'min':10, 'max':1}})
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'array', [u'blob', 1], 10, -10]) get_datatype({u'array': {u'blob': dict(max=4)}, u'max': 10})
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'tuple']) get_datatype([u'tuple'])
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'tuple', 1]) get_datatype({u'tuple': 1})
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'tuple', [1], 2, 3]) get_datatype([u'tuple', [1], 2, 3])
assert isinstance(get_datatype([u'tuple', {u'members':[[u'blob', assert isinstance(get_datatype({u'tuple': {u'members':[{u'blob':
{u'max':1}]]}]), TupleOf) {u'max':1}}]}}), TupleOf)
assert isinstance(get_datatype([u'tuple', {u'members':[[u'blob', assert isinstance(get_datatype({u'tuple': {u'members':[{u'blob':
{u'max':1}]]}]).members[0], BLOBType) {u'max':1}}]}}).members[0], BLOBType)
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'tuple', {}]) get_datatype({u'tuple': {}})
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'tuple', 10, -10]) get_datatype([u'tuple', 10, -10])
assert isinstance(get_datatype([u'tuple', {u'members':[[u'blob', {u'max':1}], assert isinstance(get_datatype({u'tuple': {u'members':[{u'blob': {u'max':1}},
[u'bool',{}]]}]), TupleOf) {u'bool':{}}]}}), TupleOf)
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'struct']) get_datatype([u'struct'])
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'struct', 1]) get_datatype({u'struct': 1})
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'struct', [1], 2, 3]) get_datatype([u'struct', [1], 2, 3])
assert isinstance(get_datatype([u'struct', {u'members': assert isinstance(get_datatype({u'struct': {u'members':
{u'name': [u'blob', {u'max':1}]}}]), StructOf) {u'name': {u'blob': {u'max':1}}}}}), StructOf)
assert isinstance(get_datatype([u'struct', {u'members': assert isinstance(get_datatype({u'struct': {u'members':
{u'name': [u'blob', {u'max':1}]}}]).members[u'name'], BLOBType) {u'name': {u'blob': {u'max':1}}}}}).members[u'name'], BLOBType)
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'struct', {}]) get_datatype({u'struct': {}})
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_datatype([u'struct', {u'members':[1,2,3]}]) get_datatype({u'struct': {u'members':[1,2,3]}})

View File

@ -36,18 +36,18 @@ def test_Command():
assert cmd.ctr assert cmd.ctr
assert cmd.argument is None assert cmd.argument is None
assert cmd.result is None assert cmd.result is None
assert cmd.for_export() == {u'datatype': [u'command', {u'argument': None, u'result': None}], assert cmd.for_export() == {u'datatype': {u'command': {}},
u'description': u'do_something'} u'description': u'do_something'}
cmd = Command(u'do_something', argument=IntRange(-9,9), result=IntRange(-1,1)) cmd = Command(u'do_something', argument=IntRange(-9,9), result=IntRange(-1,1))
assert cmd.description assert cmd.description
assert isinstance(cmd.argument, IntRange) assert isinstance(cmd.argument, IntRange)
assert isinstance(cmd.result, IntRange) assert isinstance(cmd.result, IntRange)
assert cmd.for_export() == {u'datatype': [u'command', {u'argument': [u'int', {u'min':-9, u'max':9}], assert cmd.for_export() == {u'datatype': {u'command': {u'argument': {u'int': {u'min':-9, u'max':9}},
u'result': [u'int', {u'min':-1, u'max':1}]}], u'result': {u'int': {u'min':-1, u'max':1}}}},
u'description': u'do_something'} u'description': u'do_something'}
assert cmd.exportProperties() == {u'datatype': [u'command', {u'argument': [u'int', {u'max': 9, u'min': -9}], assert cmd.exportProperties() == {u'datatype': {u'command': {u'argument': {u'int': {u'max': 9, u'min': -9}},
u'result': [u'int', {u'max': 1, u'min': -1}]}], u'result': {u'int': {u'max': 1, u'min': -1}}}},
u'description': u'do_something'} u'description': u'do_something'}