fandango.dynamic module¶
Contents
Description¶
@package dynamic <pre> CLASSES FOR TANGO DEVICE SERVER WITH DYNAMIC ATTRIBUTES by Sergi Rubio Manrique, srubio@cells.es ALBA Synchrotron Control Group Created 5th November 2007
- This Module includes several classes:
DynamicDS : template for dynamic attributes and states. DynamicDSTypes : for managing TANGOs Attribute Types DynamicAttribute : allows operations between Tango attributes while maintaining quality and date values
Usage:
- 1.DON’T FORGET TO ADD THIS CALLS IN YOUR DEVICE SERVER
- from dynamic import *
- 2.TO init_device:
- #It is necessary to avoid all devices to have the same property values, should be unnecessary with newest PyTango release self.get_DynDS_properties()
- 3.TO always_executed_hook or read_attr_hardware:
- self.prepare_DynDS() #or DynamicDS.always_executed_hook(self)
- 4.DECLARATION OF CLASSES SHOULD BE:
#class PyPLC(PyTango.Device_3Impl): class PyPLC(DynamicDS): #class PyPLCClass(PyTango.PyDeviceClass): class PyPLCClass(DynamicDSClass):
- NOTE: To make your devices Pogoable again you can substitute this change with 2 calls to:
- addTangoInterface(PyPLC,DynamicDS) and addTangoInterface(PyPLCClass,DynamicDSClass)
This calls must be inserted in the __main__ method of your Class.py file and also at the end of the file.
5.AND THE __init__ METHOD: def __init__(self,cl, name):
#PyTango.Device_3Impl.__init__(self,cl,name) DynamicDS.__init__(self,cl,name,_locals={},useDynStates=True)
#The _locals dictionary allows to parse the commands of the class to be available in attributes declaration: DynamicDS.__init__(self,cl,name,_locals={
‘Command0’: lambda argin: self.Command0(argin), ‘Command1’: lambda _addr,val: self.Command1([_addr,val]), #typical Tango command that requires an array as argument ‘Command2’: lambda argin,VALUE=None: self.Command1([argin,VALUE]), #typical write command, with VALUE defaulting to None only argin is used },useDynStates=False)# This will be stored in the self._locals dictionary, that could be extended later by calling eval_attr(...,_locals={...}). # useDynStates argument allows to switch between generating State using alarm/warning configuration of the attributes # or use the commands introduced in the DynamicDS property (it must be done in __init__ as cannot be changed later). ...
- IF YOU WANT TO USE YOUR OWN METHODS IN THE PROPERTY TEXTS YOU SHOULD CUSTOMIZE evalAttr(Atrr_Name) and evalState(expression)
- Copy it to your device server and edit it, the arguments isREAD and isWRITE allows to differentiate Read/Write access </pre>
Variables¶
DynamicDSTypes¶
- fandango.dynamic.DynamicDSTypes¶
Dictionary that contains the definition of all types available in DynamicDS attributes Tango Type casting in formulas is done using int(value), SPECTRUM(int,value), IMAGE(int,value) for bool,int,float,str types
Classes¶
DynamicServer¶
- class fandango.dynamic.DynamicServer(name='', classes={}, add_debug=False, log='-v2', orb=[])[source]¶
The DynamicServer class provides .util .instance .db .classes to have access to Tango DS internals.
To load your own custom classes you can override the load_class method to modify how classes are generated (see CopyCatDS as example)
DynamicAttribute¶
- class fandango.dynamic.DynamicAttribute(value=None, date=0.0, quality=PyTango._PyTango.AttrQuality.ATTR_VALID)[source]¶
This class provides a background for dynamic attribute management and interoperativity Future subclasses could override the operands of the class to manage quality and date modifications
DynamicDS¶
- class fandango.dynamic.DynamicDS(cl=None, name=None, _globals=None, _locals=None, useDynStates=True)[source]¶
Check fandango.dynamic.__doc__ for more information ...
- ForceAttr(argin, VALUE=None)[source]¶
Description: The arguments are AttributeName and an optional Value.<br> This command will force the value of the Attribute or will return the last forced value (if only one argument is passed).
- ForceVar(argin, VALUE=None, default=None, WRITE=None)[source]¶
Management of “Forced Variables” in dynamic servers
Description: The arguments are VariableName and an optional Value.<br> This command will force the value of a Variable or will return the last forced value (if only one argument is passed).
There are several syntaxes that can be used to call variables. - VAR(“MyVariable”,default=0) : return Value if initialized, else 0 - VAR(“MyVariable”,VALUE) : Writes Value into variable - VAR(“MyVariable”,WRITE=True) : Writes VALUE as passed from a write_attribute() call; reads otherwise - This syntax replaces (VAR(“MyVar”,default=0) if not WRITE else VAR(“MyVar”,VALUE)) - GET(“MyVariable”) : helper to read variable - SET(“MyVariable”,VALUE) : helper to write variable
Parameters: - default – value to initialize variable at first read
- WRITE – if True, VALUE env variable will overwrite VALUE argument
- check_polled_attributes(db=None, new_attr={}, use_admin=False)[source]¶
If a PolledAttribute is removed of the Attributes declaration it can lead to SegmentationFault at Device Startup. polled_attr property must be verified to avoid that.
The method .get_device_class() cannot be called to get the attr_list value for this class, therefore new_attr must be used to add to the valid attributes any attribute added by subclasses Polling configuration configured through properties has preference over the hard-coded values; but it seems that Tango does not always update that and polling periods have to be updated.
- Must be called twice (solved in PyTango8)
- at dyn_attr to remove unwanted attributes from polled_attr
- at prepareDynDS to update polling periods using the admin device
- check_state(set_state=True, current=None)[source]¶
The thread automatically close if there’s no activity for 5 minutes, an always_executed_hook call or a new event will restart the thread.
- static dyn_attr()[source]¶
Dynamic Attributes Creator: It initializes the device from DynamicAttributes and DynamicStates properties. It is called by all DeviceNameClass classes that inherit from DynamicDSClass. It MUST be an static method, to bound dynamic attributes and avoid being read by other devices from the same server. This is why Read/Write attributes are staticmethods also. (in other devices lambda is used)
- evalAttr(aname, WRITE=False, VALUE=None, _locals=None)[source]¶
SPECIFIC METHODS DEFINITION DONE IN self._locals!!! @remark Generators don’t work inside eval!, use lists instead
- evalCommand(cmd, argin=None)[source]¶
This method will execute a command declared using DynamicCommands property
- evalState(formula, _locals={})[source]¶
Overloading the eval method to be used to evaluate State expressions ... To customize it: copy it to your device and add any method you will need @remark Generators don’t work inside eval!, use lists instead
The main difference with evalAttr is that evalState will not Check Dependencies nor push events
- getAttr(aname, default=None, write=False, wvalue=None)[source]¶
Evaluates an attribute and returns its Read value.
- getXAttr(aname, default=None, write=False, wvalue=None)[source]¶
Performs an external Attribute reading, using a DeviceProxy to read own attributes. Argument could be: [attr_name] or [device_name](=State) or [device_name/attr_name]
Returns: Attribute value or None
- getXCommand(cmd, args=None, feedback=None, expected=None)[source]¶
Performs an external Command reading, using a DeviceProxy :param cmd_name: a/b/c/cmd
- get_DynDS_properties(db=None)[source]¶
It forces DynamicDevice properties reading using the Database device. It has to be used as subclasses may not include all Dynamic* properties in their class generation. It is used by self.updateDynamicAttributes() and required in PyTango<3.0.4
- get_attr_formula(aname, full=False)[source]¶
Returns the formula for the given attribute The as_tuple flag will return an attr,formula,compiled tuple
- get_attr_models(attribute)[source]¶
Given a dynamic attribute name or formula, it will return a list of tango models appearing on it
- static load_from_file(filename=None, device=None)[source]¶
This line is put in a separate method to allow subclasses to override this behavior
Functions¶
CreateDynamicCommands¶
- fandango.dynamic.CreateDynamicCommands(ds, ds_class)[source]¶
By convention all dynamic commands have argin=DevVarStringArray, argout=DevVarStringArray This function will check all dynamic devices declared within this server
@todo an special declaration should allow to redefine that! DevComm(typein,typeout,code)
The code to add a new command will be something like: #srubio: it has been added for backward compatibility PyPLC.WriteBit,PyPLCClass.cmd_list[‘WriteBit’]=PyPLC.WriteFlag,[[PyTango.DevVarShortArray, “DEPRECATED, Use WriteFlag instead”], [PyTango.DevVoid, “DEPRECATED, Use WriteFlag instead”]]
raw autodoc¶
- fandango.dynamic.CreateDynamicCommands(ds, ds_class)[source]
By convention all dynamic commands have argin=DevVarStringArray, argout=DevVarStringArray This function will check all dynamic devices declared within this server
@todo an special declaration should allow to redefine that! DevComm(typein,typeout,code)
The code to add a new command will be something like: #srubio: it has been added for backward compatibility PyPLC.WriteBit,PyPLCClass.cmd_list[‘WriteBit’]=PyPLC.WriteFlag,[[PyTango.DevVarShortArray, “DEPRECATED, Use WriteFlag instead”], [PyTango.DevVoid, “DEPRECATED, Use WriteFlag instead”]]
- class fandango.dynamic.DynamicAttribute(value=None, date=0.0, quality=PyTango._PyTango.AttrQuality.ATTR_VALID)[source]
Bases: object
This class provides a background for dynamic attribute management and interoperativity Future subclasses could override the operands of the class to manage quality and date modifications
- qualityOrder = [PyTango._PyTango.AttrQuality.ATTR_VALID, PyTango._PyTango.AttrQuality.ATTR_CHANGING, PyTango._PyTango.AttrQuality.ATTR_WARNING, PyTango._PyTango.AttrQuality.ATTR_ALARM, PyTango._PyTango.AttrQuality.ATTR_INVALID]¶
- class fandango.dynamic.DynamicDS(cl=None, name=None, _globals=None, _locals=None, useDynStates=True)[source]
Bases: PyTango._PyTango.Device_4Impl, fandango.log.Logger
Check fandango.dynamic.__doc__ for more information ...
- EXTENSIONS = {'@COPY:': <function _copy_extension at 0x7eff574f8de8>, '@FILE:': <function _file_extension at 0x7eff574f8e60>, '@ATTR:': <function _attr_extension at 0x7eff574f8ed8>}¶
- ForceAttr(argin, VALUE=None)[source]
Description: The arguments are AttributeName and an optional Value.<br> This command will force the value of the Attribute or will return the last forced value (if only one argument is passed).
- ForceVar(argin, VALUE=None, default=None, WRITE=None)[source]
Management of “Forced Variables” in dynamic servers
Description: The arguments are VariableName and an optional Value.<br> This command will force the value of a Variable or will return the last forced value (if only one argument is passed).
There are several syntaxes that can be used to call variables. - VAR(“MyVariable”,default=0) : return Value if initialized, else 0 - VAR(“MyVariable”,VALUE) : Writes Value into variable - VAR(“MyVariable”,WRITE=True) : Writes VALUE as passed from a write_attribute() call; reads otherwise - This syntax replaces (VAR(“MyVar”,default=0) if not WRITE else VAR(“MyVar”,VALUE)) - GET(“MyVariable”) : helper to read variable - SET(“MyVariable”,VALUE) : helper to write variable
Parameters: - default – value to initialize variable at first read
- WRITE – if True, VALUE env variable will overwrite VALUE argument
- Help(str_format='text')[source]
This command returns help for this device class and its parents
- check_polled_attributes(db=None, new_attr={}, use_admin=False)[source]
If a PolledAttribute is removed of the Attributes declaration it can lead to SegmentationFault at Device Startup. polled_attr property must be verified to avoid that.
The method .get_device_class() cannot be called to get the attr_list value for this class, therefore new_attr must be used to add to the valid attributes any attribute added by subclasses Polling configuration configured through properties has preference over the hard-coded values; but it seems that Tango does not always update that and polling periods have to be updated.
- Must be called twice (solved in PyTango8)
- at dyn_attr to remove unwanted attributes from polled_attr
- at prepareDynDS to update polling periods using the admin device
- static check_property_extensions(prop, value, db=None, extensions={'@COPY:': <function _copy_extension at 0x7eff574f8de8>, '@FILE:': <function _file_extension at 0x7eff574f8e60>, '@ATTR:': <function _attr_extension at 0x7eff574f8ed8>})[source]¶
- check_state(set_state=True, current=None)[source]
The thread automatically close if there’s no activity for 5 minutes, an always_executed_hook call or a new event will restart the thread.
- static dyn_attr()[source]
Dynamic Attributes Creator: It initializes the device from DynamicAttributes and DynamicStates properties. It is called by all DeviceNameClass classes that inherit from DynamicDSClass. It MUST be an static method, to bound dynamic attributes and avoid being read by other devices from the same server. This is why Read/Write attributes are staticmethods also. (in other devices lambda is used)
- dyn_comms = {}¶
- evalAttr(aname, WRITE=False, VALUE=None, _locals=None)[source]
SPECIFIC METHODS DEFINITION DONE IN self._locals!!! @remark Generators don’t work inside eval!, use lists instead
- evalCommand(cmd, argin=None)[source]
This method will execute a command declared using DynamicCommands property
- evalState(formula, _locals={})[source]
Overloading the eval method to be used to evaluate State expressions ... To customize it: copy it to your device and add any method you will need @remark Generators don’t work inside eval!, use lists instead
The main difference with evalAttr is that evalState will not Check Dependencies nor push events
- getAttr(aname, default=None, write=False, wvalue=None)[source]
Evaluates an attribute and returns its Read value.
- getXAttr(aname, default=None, write=False, wvalue=None)[source]
Performs an external Attribute reading, using a DeviceProxy to read own attributes. Argument could be: [attr_name] or [device_name](=State) or [device_name/attr_name]
Returns: Attribute value or None
- getXCommand(cmd, args=None, feedback=None, expected=None)[source]
Performs an external Command reading, using a DeviceProxy :param cmd_name: a/b/c/cmd
- getXDevice(dname)[source]
This method returns a DeviceProxy to the given attribute.
- get_DynDS_properties(db=None)[source]
It forces DynamicDevice properties reading using the Database device. It has to be used as subclasses may not include all Dynamic* properties in their class generation. It is used by self.updateDynamicAttributes() and required in PyTango<3.0.4
- get_attr_formula(aname, full=False)[source]
Returns the formula for the given attribute The as_tuple flag will return an attr,formula,compiled tuple
- get_attr_models(attribute)[source]
Given a dynamic attribute name or formula, it will return a list of tango models appearing on it
- get_dyn_attr_list()[source]
Gets all dynamic attribute names.
- static load_from_file(filename=None, device=None)[source]
This line is put in a separate method to allow subclasses to override this behavior
- parseStaticAttributes(add=True, keep=True)[source]
Parsing StaticAttributes if defined.
- prepare_DynDS()[source]
This code is placed here because its proper execution cannot be guaranteed during init_device().
- setAttr(aname, VALUE)[source]
Evaluates the WRITE part of an Attribute, passing a VALUE.
- updateDynamicAttributes()[source]
Forces dynamic attributes update from properties. @warning : It will DELETE all attributes that does not appear in DynamicAttributes property or StaticAttributes list!
- class fandango.dynamic.DynamicDSClass(name)[source]
Bases: PyTango._PyTango.DeviceClass
- DynDev = None¶
- attr_list = {'MemUsage': [[PyTango._PyTango.CmdArgType.DevDouble, PyTango._PyTango.AttrDataFormat.SCALAR, PyTango._PyTango.AttrWriteType.READ]]}¶
- class_property_list = {'DynamicSpectrumSize': [PyTango._PyTango.CmdArgType.DevLong, 'It will fix the maximum size for all Dynamic Attributes.', [4096]]}¶
- cmd_list = {'updateDynamicAttributes': [[PyTango._PyTango.CmdArgType.DevVoid, 'Reloads properties and updates attributes'], [PyTango._PyTango.CmdArgType.DevVoid, 'Reloads properties and updates attributes'], {'Display level': PyTango._PyTango.DispLevel.EXPERT}], 'getMemUsage': [[PyTango._PyTango.CmdArgType.DevVoid, 'Returns own process RSS memory usage (Kb)'], [PyTango._PyTango.CmdArgType.DevDouble, 'Returns own process RSS memory usage (Kb)'], {'Display level': PyTango._PyTango.DispLevel.EXPERT}], 'Help': [[PyTango._PyTango.CmdArgType.DevVoid, ''], [PyTango._PyTango.CmdArgType.DevString, 'python docstring']], 'evaluateFormula': [[PyTango._PyTango.CmdArgType.DevString, 'formula to evaluate'], [PyTango._PyTango.CmdArgType.DevString, 'formula to evaluate'], {'Display level': PyTango._PyTango.DispLevel.EXPERT}], 'getDynamicConfig': [[PyTango._PyTango.CmdArgType.DevVoid, 'Print current property values'], [PyTango._PyTango.CmdArgType.DevString, 'Print current property values'], {'Display level': PyTango._PyTango.DispLevel.EXPERT}]}¶
- device_property_list = {'KeepTime': [PyTango._PyTango.CmdArgType.DevDouble, 'The kept value will be returned if a kept value is re-asked within this milliseconds time (Cache).', [200]], 'DynamicQualities': [PyTango._PyTango.CmdArgType.DevVarStringArray, 'This property will allow to declare formulas for Attribute Qualities.', []], 'DynamicStates': [PyTango._PyTango.CmdArgType.DevVarStringArray, 'This property will allow to declare new States dinamically based on\ndynamic attributes changes. The function Attr will allow to use the\nvalue of attributes in formulas.\n\n\n\nALARM=Attr(T1)>70\nOK=1', ['#Write here your State formulas']], 'KeepAttributes': [PyTango._PyTango.CmdArgType.DevVarStringArray, "This property can be used to store the values of only needed attributes; values are 'yes', 'no' or a list of attribute names", ['yes']], 'DynamicStatus': [PyTango._PyTango.CmdArgType.DevVarStringArray, 'Each line generated by this property code will be added to status', []], 'UseTaurus': [PyTango._PyTango.CmdArgType.DevBoolean, 'This property manages if Taurus or PyTango will be used to read external attributes.', [False]], 'LogLevel': [PyTango._PyTango.CmdArgType.DevString, 'This property selects the log level (DEBUG/INFO/WARNING/ERROR)', ['INFO']], 'DynamicAttributes': [PyTango._PyTango.CmdArgType.DevVarStringArray, 'Attributes and formulas to create for this device.\nThis Tango Attributes will be generated dynamically using this syntax:\n\tT3=int(SomeCommand(7007)/10.)\n\nSee the class description to know how to make any method available in attributes declaration.\nNOTE:Python generators dont work here, use comprehension lists instead.', ['#Write here your Attribute formulas']], 'LoadFromFile': [PyTango._PyTango.CmdArgType.DevString, 'If not empty, a file where additional attribute formulas can be declared. It will be parsed BEFORE DynamicAttributes', ['no']], 'StartupDelay': [PyTango._PyTango.CmdArgType.DevDouble, 'The device server will wait this time in milliseconds before starting.', [1000]], 'DynamicCommands': [PyTango._PyTango.CmdArgType.DevVarStringArray, "This property will allow to declare new Commands at startup with formulas like: \n\tSendStrings=DevLong(WATTR(NAME+'/Channel',SPECTRUM(str,ARGS)))", ['#Write here your Command formulas']], 'CheckDependencies': [PyTango._PyTango.CmdArgType.DevBoolean, 'This property manages if dependencies between attributes are used to check readability.', [True]], 'UseEvents': [PyTango._PyTango.CmdArgType.DevVarStringArray, 'Value of this property will be yes/true,no/false or a list of attributes that will trigger push_event (if configured from jive)', ['false']]}¶
- get_devs_in_server(MyClass=None)[source]
Method for getting a dictionary with all the devices running in this server
- class fandango.dynamic.DynamicDSType(tangotype, labels, pytype, dimx=1, dimy=1)[source]
Bases: object
Allows to parse all the Tango types for Attributes
- fandango.dynamic.DynamicDSTypes = {'DevVarDoubleImage': <fandango.dynamic.DynamicDSType object at 0x7eff574c4d50>, 'DevUShort': <fandango.dynamic.DynamicDSType object at 0x7eff574c4a10>, 'DevDouble': <fandango.dynamic.DynamicDSType object at 0x7eff574c4ad0>, 'DevLong': <fandango.dynamic.DynamicDSType object at 0x7eff574c4990>, 'DevVarStringImage': <fandango.dynamic.DynamicDSType object at 0x7eff574c4cd0>, 'DevVarShortImage': <fandango.dynamic.DynamicDSType object at 0x7eff574c4c90>, 'DevVarLongImage': <fandango.dynamic.DynamicDSType object at 0x7eff574c4c50>, 'DevVarDoubleArray': <fandango.dynamic.DynamicDSType object at 0x7eff574c4c10>, 'DevVarBooleanArray': <fandango.dynamic.DynamicDSType object at 0x7eff574c4bd0>, 'DevVarLongArray': <fandango.dynamic.DynamicDSType object at 0x7eff574c4b10>, 'DevVarStringArray': <fandango.dynamic.DynamicDSType object at 0x7eff574c4b90>, 'DevVarFloatArray': <fandango.dynamic.DynamicDSType object at 0x7eff574c4c10>, 'DevVarShortArray': <fandango.dynamic.DynamicDSType object at 0x7eff574c4b50>, 'DevULong': <fandango.dynamic.DynamicDSType object at 0x7eff574c4990>, 'DevString': <fandango.dynamic.DynamicDSType object at 0x7eff574c4a50>, 'DevState': <fandango.dynamic.DynamicDSType object at 0x7eff574c4950>, 'DevVarBooleanImage': <fandango.dynamic.DynamicDSType object at 0x7eff574c4d10>, 'DevULong64': <fandango.dynamic.DynamicDSType object at 0x7eff574c49d0>, 'DevShort': <fandango.dynamic.DynamicDSType object at 0x7eff574c4a10>, 'DevLong64': <fandango.dynamic.DynamicDSType object at 0x7eff574c49d0>, 'DevDouble64': <fandango.dynamic.DynamicDSType object at 0x7eff574c4ad0>, 'DevBoolean': <fandango.dynamic.DynamicDSType object at 0x7eff574c4a90>}
Dictionary that contains the definition of all types available in DynamicDS attributes Tango Type casting in formulas is done using int(value), SPECTRUM(int,value), IMAGE(int,value) for bool,int,float,str types
- class fandango.dynamic.DynamicServer(name='', classes={}, add_debug=False, log='-v2', orb=[])[source]
Bases: object
The DynamicServer class provides .util .instance .db .classes to have access to Tango DS internals.
To load your own custom classes you can override the load_class method to modify how classes are generated (see CopyCatDS as example)
- PROPERTY = 'PYTHON_CLASSPATH'¶
- fandango.dynamic.castDynamicType(dims, klass, value)[source]
- fandango.dynamic.isTypeSupported(ttype, n_dim=None)[source]