Provide Properties with a description
useful für gui+auto generated docu Change-Id: I0a2f7dc4b3c745145dd4b03956d15d33731cf980 Reviewed-on: https://forge.frm2.tum.de/review/20949 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:
parent
7c620901c9
commit
95d50fb51e
@ -68,13 +68,17 @@ class Module(HasProperties):
|
||||
# note: the names map to a [datatype, value] list, value comes from the cfg file,
|
||||
# datatype is fixed!
|
||||
properties = {
|
||||
'export': Property(BoolType(), default=True, export=False),
|
||||
'group': Property(StringType(), default='', extname='group'),
|
||||
'description': Property(StringType(), extname='description', mandatory=True),
|
||||
'meaning': Property(TupleOf(StringType(),IntRange(0,50)), default=('',0), extname='meaning'),
|
||||
'visibility': Property(EnumType('visibility', user=1, advanced=2, expert=3), default=1, extname='visibility'),
|
||||
'implementation': Property(StringType(), extname='implementation'),
|
||||
'interface_class': Property(ArrayOf(StringType()), extname='interface_class'),
|
||||
'export': Property('Flag if this Module is to be exported', BoolType(), default=True, export=False),
|
||||
'group': Property('Optional group the Module belongs to', StringType(), default='', extname='group'),
|
||||
'description': Property('Description of the module', StringType(), extname='description', mandatory=True),
|
||||
'meaning': Property('Optional Meaning indicator', TupleOf(StringType(),IntRange(0,50)),
|
||||
default=('',0), extname='meaning'),
|
||||
'visibility': Property('Optional visibility hint', EnumType('visibility', user=1, advanced=2, expert=3),
|
||||
default='user', extname='visibility'),
|
||||
'implementation': Property('Internal name of the implementation class of the module', StringType(),
|
||||
extname='implementation'),
|
||||
'interface_class': Property('Offical highest Interface-class of the module', ArrayOf(StringType()),
|
||||
extname='interface_class'),
|
||||
# what else?
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,8 @@ from __future__ import division, print_function
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
from secop.datatypes import CommandType, DataType, StringType, BoolType, EnumType, DataTypeType, ValueType, OrType
|
||||
from secop.datatypes import CommandType, DataType, StringType, BoolType, EnumType, DataTypeType, ValueType, OrType, \
|
||||
NoneOr
|
||||
from secop.errors import ProgrammingError
|
||||
from secop.properties import HasProperties, Property
|
||||
|
||||
@ -91,18 +92,26 @@ class Parameter(Accessible):
|
||||
"""
|
||||
|
||||
properties = {
|
||||
u'description': Property(StringType(), extname=u'description', mandatory=True),
|
||||
u'datatype': Property(DataTypeType(), extname=u'datatype', mandatory=True),
|
||||
u'unit': Property(StringType(), extname=u'unit', default=''), # goodie, should be on the datatype!
|
||||
u'readonly': Property(BoolType(), extname=u'readonly', default=True),
|
||||
u'group': Property(StringType(), extname=u'group', default=''),
|
||||
u'visibility': Property(EnumType(u'visibility', user=1, advanced=2, expert=3),
|
||||
u'description': Property('Description of the Parameter', StringType(),
|
||||
extname=u'description', mandatory=True),
|
||||
u'datatype': Property('Datatype of the Parameter', DataTypeType(),
|
||||
extname=u'datatype', mandatory=True),
|
||||
u'unit': Property('[legacy] unit of the parameter. This should now be on the datatype!', StringType(),
|
||||
extname=u'unit', default=''), # goodie, should be on the datatype!
|
||||
u'readonly': Property('Is the Parameter readonly? (vs. changeable via SECoP)', BoolType(),
|
||||
extname=u'readonly', default=True),
|
||||
u'group': Property('Optional parameter group this parameter belongs to', StringType(),
|
||||
extname=u'group', default=''),
|
||||
u'visibility': Property('Optional visibility hint', EnumType(u'visibility', user=1, advanced=2, expert=3),
|
||||
extname=u'visibility', default=1),
|
||||
u'constant': Property(ValueType(), extname=u'constant', default=None),
|
||||
u'default': Property(ValueType(), export=False, default=None, mandatory=False),
|
||||
u'export': Property(OrType(BoolType(), StringType()), export=False, default=True),
|
||||
u'poll': Property(ValueType(), export=False, default=True), # check default value!
|
||||
u'optional': Property(BoolType(), export=False, default=False),
|
||||
u'constant': Property('Optional constant value for constant parameters', ValueType(),
|
||||
extname=u'constant', default=None),
|
||||
u'default': Property('Default (startup) value of this parameter if it can not be read from the hardware.',
|
||||
ValueType(), export=False, default=None, mandatory=False),
|
||||
u'export': Property('Is this parameter accessible via SECoP? (vs. internal parameter)',
|
||||
OrType(BoolType(), StringType()), export=False, default=True),
|
||||
u'poll': Property('Polling indicator', ValueType(), export=False, default=True), # check default value!
|
||||
u'optional': Property('[Internal] is this parameter optional?', BoolType(), export=False, default=False),
|
||||
}
|
||||
|
||||
value = None
|
||||
@ -242,18 +251,27 @@ class Command(Accessible):
|
||||
"""
|
||||
# datatype is not listed (handled separately)
|
||||
properties = {
|
||||
u'description': Property(StringType(), extname=u'description', export=True, mandatory=True),
|
||||
u'group': Property(StringType(), extname=u'group', export=True, default=''),
|
||||
u'visibility': Property(EnumType(u'visibility', user=1, advanced=2, expert=3),
|
||||
u'description': Property('Description of the Command', StringType(),
|
||||
extname=u'description', export=True, mandatory=True),
|
||||
u'group': Property('Optional command group of the command.', StringType(),
|
||||
extname=u'group', export=True, default=''),
|
||||
u'visibility': Property('Optional visibility hint', EnumType(u'visibility', user=1, advanced=2, expert=3),
|
||||
extname=u'visibility', export=True, default=1),
|
||||
u'export': Property(OrType(BoolType(), StringType()), export=False, default=True),
|
||||
u'optional': Property(BoolType(), export=False, default=False, settable=False),
|
||||
u'datatype': Property(DataTypeType(), extname=u'datatype', mandatory=True),
|
||||
u'export': Property('[internal] Flag: is the command accessible via SECoP? (vs. pure internal use)',
|
||||
OrType(BoolType(), StringType()), export=False, default=True),
|
||||
u'optional': Property('[internal] is The comamnd optional to implement? (vs. mandatory',
|
||||
BoolType(), export=False, default=False, settable=False),
|
||||
u'datatype': Property('[internal] datatype of the command, auto generated from \'argument\' and \'result\'',
|
||||
DataTypeType(), extname=u'datatype', mandatory=True),
|
||||
u'argument': Property('Datatype of the argument to the command, or None.',
|
||||
NoneOr(DataTypeType()), export=False, mandatory=True),
|
||||
u'result': Property('Datatype of the result from the command, or None.',
|
||||
NoneOr(DataTypeType()), export=False, mandatory=True),
|
||||
}
|
||||
|
||||
def __init__(self, description, argument=None, result=None, ctr=None, **kwds):
|
||||
def __init__(self, description, ctr=None, **kwds):
|
||||
kwds[u'description'] = description
|
||||
kwds[u'datatype'] = CommandType(argument, result)
|
||||
kwds[u'datatype'] = CommandType(kwds.get('argument', None), kwds.get('result', None))
|
||||
super(Command, self).__init__(**kwds)
|
||||
if ctr is not None:
|
||||
self.ctr = ctr
|
||||
|
@ -36,15 +36,16 @@ class Property(object):
|
||||
'''base class holding info about a property
|
||||
|
||||
properties are only sent to the ECS if export is True, or an extname is set
|
||||
if mandatory is True, they MUST have avalue in the cfg file assigned to them.
|
||||
if mandatory is True, they MUST have a value in the cfg file assigned to them.
|
||||
otherwise, this is optional in which case the default value is applied.
|
||||
All values MUST pass the datatype.
|
||||
'''
|
||||
# note: this is inteded to be used on base classes.
|
||||
# the VALUES of the properties are on the instances!
|
||||
def __init__(self, datatype, default=None, extname='', export=False, mandatory=False, settable=True):
|
||||
def __init__(self, description, datatype, default=None, extname='', export=False, mandatory=False, settable=True):
|
||||
if not callable(datatype):
|
||||
raise ValueError(u'datatype MUST be a valid DataType or a basic_validator')
|
||||
self.description = description
|
||||
self.default = datatype.default if default is None else datatype(default)
|
||||
self.datatype = datatype
|
||||
self.extname = unicode(extname)
|
||||
@ -53,8 +54,8 @@ class Property(object):
|
||||
self.settable = settable or mandatory # settable means settable from the cfg file
|
||||
|
||||
def __repr__(self):
|
||||
return u'Property(%s, default=%r, extname=%r, export=%r, mandatory=%r)' % (
|
||||
self.datatype, self.default, self.extname, self.export, self.mandatory)
|
||||
return u'Property(%s, %s, default=%r, extname=%r, export=%r, mandatory=%r)' % (
|
||||
self.description, self.datatype, self.default, self.extname, self.export, self.mandatory)
|
||||
|
||||
|
||||
class Properties(OrderedDict):
|
||||
|
@ -33,12 +33,12 @@ from secop.modules import Drivable, Override, Parameter
|
||||
# test custom property (value.test can be changed in config file)
|
||||
from secop.properties import Property
|
||||
|
||||
Parameter.properties['test'] = Property(StringType(), default='', export=True)
|
||||
Parameter.properties['test'] = Property('A Property for testing purposes', StringType(), default='', export=True)
|
||||
|
||||
|
||||
class CryoBase(Drivable):
|
||||
properties = {
|
||||
'is_cryo': Property(BoolType(), default=True, export=True),
|
||||
'is_cryo': Property('private Flag if this is a cryostat', BoolType(), default=True, export=True),
|
||||
}
|
||||
|
||||
|
||||
|
@ -35,7 +35,7 @@ from secop.properties import Property
|
||||
|
||||
class Parameter(SECoP_Parameter):
|
||||
properties = {
|
||||
'test' : Property(StringType(), default='', mandatory=False, extname='test'),
|
||||
'test' : Property('A property for testing purposes', StringType(), default='', mandatory=False, extname='test'),
|
||||
}
|
||||
|
||||
PERSIST = 101
|
||||
@ -62,7 +62,8 @@ class Switch(Drivable):
|
||||
}
|
||||
|
||||
properties = {
|
||||
'description' : Property(StringType(), default='no description', mandatory=False, extname='description'),
|
||||
'description' : Property('The description of the Module', StringType(),
|
||||
default='no description', mandatory=False, extname='description'),
|
||||
}
|
||||
|
||||
def read_value(self):
|
||||
|
@ -101,7 +101,7 @@ class Temp(Drivable):
|
||||
class Lower(Communicator):
|
||||
"""Communicator returning a lowercase version of the request"""
|
||||
command = {
|
||||
'communicate': Command('lowercase a string', StringType(), StringType(), export='communicate'),
|
||||
'communicate': Command('lowercase a string', argument=StringType(), result=StringType(), export='communicate'),
|
||||
}
|
||||
def do_communicate(self, request):
|
||||
return unicode(request).lower()
|
||||
|
@ -39,7 +39,7 @@ def test_Command():
|
||||
assert cmd.for_export() == {u'datatype': [u'command', {u'argument': None, u'result': None}],
|
||||
u'description': u'do_something'}
|
||||
|
||||
cmd = Command(u'do_something', IntRange(-9,9), IntRange(-1,1))
|
||||
cmd = Command(u'do_something', argument=IntRange(-9,9), result=IntRange(-1,1))
|
||||
assert cmd.description
|
||||
assert isinstance(cmd.argument, IntRange)
|
||||
assert isinstance(cmd.result, IntRange)
|
||||
|
@ -54,7 +54,7 @@ V_test_Property = [
|
||||
def test_Property():
|
||||
for entry in V_test_Property:
|
||||
args, check = entry
|
||||
p = Property(*args)
|
||||
p = Property('', *args)
|
||||
for k,v in check.items():
|
||||
assert getattr(p, k) == v
|
||||
|
||||
@ -62,15 +62,18 @@ def test_Property_basic():
|
||||
with pytest.raises(TypeError):
|
||||
# pylint: disable=no-value-for-parameter
|
||||
Property()
|
||||
with pytest.raises(TypeError):
|
||||
# pylint: disable=no-value-for-parameter
|
||||
Property('')
|
||||
with pytest.raises(ValueError):
|
||||
Property(1)
|
||||
Property(IntRange(), '42', 'extname', False, False)
|
||||
Property('', 1)
|
||||
Property('', IntRange(), '42', 'extname', False, False)
|
||||
|
||||
def test_Properties():
|
||||
p = Properties()
|
||||
with pytest.raises(ProgrammingError):
|
||||
p[1] = 2
|
||||
p['a'] = Property(IntRange(), '42', export=True)
|
||||
p['a'] = Property('', IntRange(), '42', export=True)
|
||||
assert p['a'].default == 42
|
||||
assert p['a'].export is True
|
||||
assert p['a'].extname == u'_a'
|
||||
@ -80,7 +83,7 @@ def test_Properties():
|
||||
del p[1]
|
||||
with pytest.raises(ProgrammingError):
|
||||
del p['a']
|
||||
p['a'] = Property(IntRange(), 0, export=False)
|
||||
p['a'] = Property('', IntRange(), 0, export=False)
|
||||
assert p['a'].default == 0
|
||||
assert p['a'].export is False
|
||||
assert p['a'].extname == ''
|
||||
@ -88,13 +91,13 @@ def test_Properties():
|
||||
|
||||
class c(HasProperties):
|
||||
properties = {
|
||||
'a' : Property(IntRange(), 1),
|
||||
'a' : Property('', IntRange(), 1),
|
||||
}
|
||||
|
||||
class cl(c):
|
||||
properties = {
|
||||
'a' : Property(IntRange(), 3),
|
||||
'b' : Property(FloatRange(), 3.14),
|
||||
'a' : Property('', IntRange(), 3),
|
||||
'b' : Property('', FloatRange(), 3.14),
|
||||
}
|
||||
|
||||
def test_HasProperties():
|
||||
|
Loading…
x
Reference in New Issue
Block a user