all: rename parameters to accessibles in module classes

+ make accesses to <module>.parameters work again

Change-Id: I91c09b0f9f5f28d78cd644f83a96c8772e5977e5
Reviewed-on: https://forge.frm2.tum.de/review/20249
Tested-by: JenkinsCodeReview <bjoern_pedersen@frm2.tum.de>
Reviewed-by: Markus Zolliker <markus.zolliker@psi.ch>
Reviewed-by: Enrico Faulhaber <enrico.faulhaber@frm2.tum.de>
Tested-by: Enrico Faulhaber <enrico.faulhaber@frm2.tum.de>
This commit is contained in:
Enrico Faulhaber 2019-03-27 17:08:57 +01:00
parent 08a92029a9
commit 4068516178
8 changed files with 36 additions and 35 deletions

View File

@ -206,5 +206,10 @@ class ModuleMeta(type):
if attrname[3:] not in newtype.accessibles:
raise ProgrammingError('%r: command %r has to be specified '
'explicitly!' % (name, attrname[3:]))
# provide properties to 'filter' out the parameters/commands
newtype.parameters = dict((k,v) for k,v in newtype.accessibles.items() if isinstance(v, Parameter))
newtype.commands = dict((k,v) for k,v in newtype.accessibles.items() if isinstance(v, Command))
attrs['__constructed__'] = True
return newtype

View File

@ -74,7 +74,7 @@ class Module(object):
}
# properties, parameter and commands are auto-merged upon subclassing
parameters = {}
accessibles = {}
commands = {}
# reference to the dispatcher (used for sending async updates)
@ -246,7 +246,7 @@ class Readable(Module):
DISABLED = 500,
UNKNOWN = 0,
)
parameters = {
accessibles = {
'value': Parameter('current value of the Module', readonly=True,
default=0., datatype=FloatRange(),
unit='', poll=True,
@ -313,7 +313,7 @@ class Writable(Readable):
providing a settable 'target' parameter to those of a Readable
"""
parameters = {
accessibles = {
'target': Parameter('target value of the Module',
default=0., readonly=False, datatype=FloatRange(),
),

View File

@ -35,7 +35,7 @@ from secop.modules import Drivable, Override, Parameter, Readable
class Switch(Drivable):
"""switch it on or off....
"""
parameters = {
accessibles = {
'value': Override('current state (on or off)',
datatype=EnumType(on=1, off=0), default=0,
),
@ -77,7 +77,7 @@ class Switch(Drivable):
return self.Status.BUSY, info
def _update(self):
started = self.accessibles['target'].timestamp
started = self.parameters['target'].timestamp
info = ''
if self.target > self.value:
info = 'waiting for ON'
@ -97,7 +97,7 @@ class Switch(Drivable):
class MagneticField(Drivable):
"""a liquid magnet
"""
parameters = {
accessibles = {
'value': Override('current field in T',
unit='T', datatype=FloatRange(-15, 15), default=0,
),
@ -117,7 +117,7 @@ class MagneticField(Drivable):
datatype=StringType(), export=False,
),
}
Status = Enum(Drivable.Status, PERSIST=101, PREPARE=301, RAMP=302, FINISH=303)
Status = Enum(Drivable.Status, PERSIST=101, PREPARE=301, RAMPING=302, FINISH=303)
overrides = {
'status' : Override(datatype=TupleOf(EnumType(Status), StringType())),
}
@ -148,7 +148,7 @@ class MagneticField(Drivable):
elif self._state == self._state.enum.switch_off:
return (self.Status.FINISH, self._state.name)
elif self._state == self._state.enum.ramp:
return (self.Status.RAMP, self._state.name)
return (self.Status.RAMPING, self._state.name)
return (self.Status.ERROR, self._state.name)
def _thread(self):
@ -197,7 +197,7 @@ class MagneticField(Drivable):
class CoilTemp(Readable):
"""a coil temperature
"""
parameters = {
accessibles = {
'value': Override('Coil temperatur',
unit='K', datatype=FloatRange(), default=0,
),
@ -213,7 +213,7 @@ class CoilTemp(Readable):
class SampleTemp(Drivable):
"""a sample temperature
"""
parameters = {
accessibles = {
'value': Override('Sample temperature',
unit='K', datatype=FloatRange(), default=10,
),
@ -260,7 +260,7 @@ class Label(Readable):
of several subdevices. used for demoing connections between
modules.
"""
parameters = {
accessibles = {
'system': Parameter("Name of the magnet system",
datatype=StringType, export=False,
),
@ -305,7 +305,7 @@ class Label(Readable):
class DatatypesTest(Readable):
"""for demoing all datatypes
"""
parameters = {
accessibles = {
'enum': Parameter('enum', datatype=EnumType(boo=None, faar=None, z=9),
readonly=False, default=1),
'tupleof': Parameter('tuple of int, float and str',
@ -327,7 +327,7 @@ class DatatypesTest(Readable):
class ArrayTest(Readable):
parameters = {
accessibles = {
"x": Parameter('value', datatype=ArrayOf(FloatRange(), 0, 100000),
default = 100000 * [0]),
}

View File

@ -54,7 +54,7 @@ class Heater(Drivable):
class name indicates it to be some heating element,
but the implementation may do anything
"""
parameters = {
accessibles = {
'maxheaterpower': Parameter('maximum allowed heater power',
datatype=FloatRange(0, 100), unit='W',
),
@ -73,7 +73,7 @@ class Temp(Drivable):
class name indicates it to be some temperature controller,
but the implementation may do anything
"""
parameters = {
accessibles = {
'sensor': Parameter(
"Sensor number or calibration id",
datatype=StringType(

View File

@ -59,7 +59,7 @@ except ImportError:
class EpicsReadable(Readable):
"""EpicsDrivable handles a Drivable interfacing to EPICS v4"""
# Commmon parameter for all EPICS devices
parameters = {
accessibles = {
'value': Parameter('EPICS generic value',
datatype=FloatRange(),
default=300.0,),
@ -119,7 +119,7 @@ class EpicsReadable(Readable):
class EpicsDrivable(Drivable):
"""EpicsDrivable handles a Drivable interfacing to EPICS v4"""
# Commmon parameter for all EPICS devices
parameters = {
accessibles = {
'target': Parameter('EPICS generic target', datatype=FloatRange(),
default=300.0, readonly=False),
'value': Parameter('EPICS generic value', datatype=FloatRange(),
@ -192,7 +192,7 @@ class EpicsDrivable(Drivable):
class EpicsTempCtrl(EpicsDrivable):
parameters = {
accessibles = {
# TODO: restrict possible values with oneof datatype
'heaterrange': Parameter('Heater range', datatype=StringType(),
default='Off', readonly=False,),

View File

@ -48,7 +48,7 @@ class GarfieldMagnet(SequencerMixin, Drivable):
the symmetry setting selects which.
"""
parameters = {
accessibles = {
'subdev_currentsource': Parameter('(bipolar) Powersupply', datatype=StringType(), readonly=True, export=False),
'subdev_enable': Parameter('Switch to set for on/off', datatype=StringType(), readonly=True, export=False),
'subdev_polswitch': Parameter('Switch to set for polarity', datatype=StringType(), readonly=True, export=False),

View File

@ -163,7 +163,7 @@ class PyTangoDevice(Module):
execution and attribute operations with logging and exception mapping.
"""
parameters = {
accessibles = {
'comtries': Parameter('Maximum retries for communication',
datatype=IntRange(1, 100), default=3, readonly=False,
group='communication'),
@ -430,7 +430,7 @@ class AnalogOutput(PyTangoDevice, Drivable):
controllers, ...
"""
parameters = {
accessibles = {
'userlimits': Parameter('User defined limits of device value',
datatype=TupleOf(FloatRange(), FloatRange()),
default=(float('-Inf'), float('+Inf')),
@ -608,7 +608,7 @@ class Actuator(AnalogOutput):
"""
# for secop: support the speed and ramp parameters
parameters = {
accessibles = {
'speed': Parameter('The speed of changing the value',
unit='main/s', readonly=False, datatype=FloatRange(0),
),
@ -648,7 +648,7 @@ class Motor(Actuator):
It has the ability to move a real object from one place to another place.
"""
parameters = {
accessibles = {
'refpos': Parameter('Reference position',
datatype=FloatRange(), unit='main',
),
@ -688,7 +688,7 @@ class TemperatureController(Actuator):
"""A temperature control loop device.
"""
parameters = {
accessibles = {
'p': Parameter('Proportional control Parameter', datatype=FloatRange(),
readonly=False, group='pid',
),
@ -763,7 +763,7 @@ class PowerSupply(Actuator):
"""A power supply (voltage and current) device.
"""
parameters = {
accessibles = {
'ramp': Parameter('Current/voltage ramp', unit='main/min',
datatype=FloatRange(), readonly=False, poll=30,),
'voltage': Parameter('Actual voltage', unit='V',
@ -801,7 +801,7 @@ class NamedDigitalInput(DigitalInput):
"""A DigitalInput with numeric values mapped to names.
"""
parameters = {
accessibles = {
'mapping': Parameter('A dictionary mapping state names to integers',
datatype=StringType(), export=False), # XXX:!!!
}
@ -824,7 +824,7 @@ class PartialDigitalInput(NamedDigitalInput):
bit width accessed.
"""
parameters = {
accessibles = {
'startbit': Parameter('Number of the first bit',
datatype=IntRange(0), default=0),
'bitwidth': Parameter('Number of bits',
@ -868,7 +868,7 @@ class NamedDigitalOutput(DigitalOutput):
"""A DigitalOutput with numeric values mapped to names.
"""
parameters = {
accessibles = {
'mapping': Parameter('A dictionary mapping state names to integers',
datatype=StringType(), export=False),
}
@ -894,7 +894,7 @@ class PartialDigitalOutput(NamedDigitalOutput):
bit width accessed.
"""
parameters = {
accessibles = {
'startbit': Parameter('Number of the first bit',
datatype=IntRange(0), default=0),
'bitwidth': Parameter('Number of bits',
@ -925,7 +925,7 @@ class StringIO(PyTangoDevice, Module):
receives strings.
"""
parameters = {
accessibles = {
'bustimeout': Parameter('Communication timeout',
datatype=FloatRange(), readonly=False,
unit='s', group='communication'),

View File

@ -23,7 +23,7 @@
from __future__ import division, print_function
# no fixtures needed
import pytest
#import pytest
from secop.datatypes import BoolType, EnumType, FloatRange
from secop.metaclass import ModuleMeta
@ -138,10 +138,6 @@ def test_ModuleMeta():
assert acs is not None
else: # do not check object or mixin
acs = {}
with pytest.raises(AttributeError):
assert baseclass.commands
with pytest.raises(AttributeError):
assert baseclass.parameters
for n, o in acs.items():
# check that class accessibles are not reused as instance accessibles
assert o not in params_found