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: if attrname[3:] not in newtype.accessibles:
raise ProgrammingError('%r: command %r has to be specified ' raise ProgrammingError('%r: command %r has to be specified '
'explicitly!' % (name, attrname[3:])) '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 attrs['__constructed__'] = True
return newtype return newtype

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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