diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d049cec5368d5087038ec79a40d09f39645db327 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# exclude pyc files +*.pyc diff --git a/src/dynamic-srv.py b/src/dynamic-srv.py new file mode 100755 index 0000000000000000000000000000000000000000..4ad43915295582b3db5dc3e6845edd87b4c32467 --- /dev/null +++ b/src/dynamic-srv.py @@ -0,0 +1,679 @@ +#!/usr/bin/env python +# "$Name: $"; +# "$Header: $"; +#============================================================================= +# +# file : Dynamic.py +# +# description : Python source for the Dynamic and its commands. +# The class is derived from Device. It represents the +# CORBA servant object which will be accessed from the +# network. All commands which can be executed on the +# Dynamic are implemented in this file. +# +# project : TANGO Device Server +# +# $Author: $ +# +# $Revision: $ +# +# $Log: $ +# +# copyleft : European Synchrotron Radiation Facility +# BP 220, Grenoble 38043 +# FRANCE +# +#============================================================================= +# This file is generated by POGO +# (Program Obviously used to Generate tango Object) +# +# (c) - Software Engineering Group - ESRF +#============================================================================= +# +""" +Dynamic Server. + + + +""" +import sys +import os +sys.path.insert(0, os.path.abspath('.')) + +from UserDict import UserDict +from xmlconfig import (ScriptXmlConfig, IS_COMMAND,READ_WRITE, READ_ONLY, WRITE_ONLY,InvalidFileError ) +import PyTango +import time +import numpy as np + + +import signal + +def fromPyTango2NumpyType(pytango_type): + """ Return the numpy type based on the PyTango type + + usage: + attr=PyTango.AttributeProxy('') + sample=attr.read() + fromPyTango2NumpyType(sample.type) + """ + data_type = np.int32 + if (pytango_type==PyTango.CmdArgType.DevUChar): + data_type=np.uint8 + elif(pytango_type==PyTango.CmdArgType.DevUShort): + data_type = np.uint16 + elif(pytango_type==PyTango.CmdArgType.DevULong): + data_type = np.uint32 + elif(pytango_type==PyTango.CmdArgType.DevShort): + data_type = np.int16 + elif(pytango_type==PyTango.CmdArgType.DevLong): + data_type = np.int32 + elif(pytango_type==PyTango.CmdArgType.DevFloat): + data_type = np.float32 + elif(pytango_type==PyTango.CmdArgType.DevDouble): + data_type = np.float32 #FIXME version 1.2.1 does not support float64 + elif(pytango_type==PyTango.CmdArgType.DevBoolean): + data_type = np.bool + return data_type + + +def fromNumpyType2PyTango(numpy_type): + """ Return the PyTango type based on numpy type + + usage: + attr = numpy.ones((2,2)) + fromNumpyType2PyTango(attr.type) + """ + data_type = PyTango.ArgType.DevDouble + if numpy_type == np.uint8: + data_type = PyTango.ArgType.DevUChar + elif numpy_type == np.uint16: + data_type = PyTango.ArgType.DevUShort + elif numpy_type == np.uint32: + data_type = PyTango.ArgType.DevULong + elif numpy_type == np.uint64: + data_type = PyTango.ArgType.DevULong + elif numpy_type == np.int16: + data_type = PyTango.ArgType.DevShort + elif numpy_type == np.int32: + data_type = PyTango.ArgType.DevLong + elif numpy_type == np.int64: + data_type = PyTango.ArgType.DevLong + elif numpy_type == np.float32: + data_type = PyTango.ArgType.DevDouble + elif numpy_type == np.bool: + data_type = PyTango.ArgType.DevBoolean + return data_type + +def fromNp2Tg(numpy_type): + data_type = "double" + if numpy_type == np.uint8: + data_type = "uchar" + elif numpy_type == np.uint16: + data_type = "ushort" + elif numpy_type == np.uint32: + data_type = "ulong" + elif numpy_type == np.uint64: + data_type = "ulong" + elif numpy_type == np.int16: + data_type = "short" + elif numpy_type == np.int32: + data_type = "long" + elif numpy_type == np.int64: + data_type = "long" + elif numpy_type == np.float32: + data_type = "double" + elif numpy_type == np.bool: + data_type = "boolean" + return data_type + +def dataType2TangoType(opt_type): + if opt_type == "DOUBLE": + typ = PyTango.ArgType.DevDouble + elif opt_type == "SHORT": + typ = PyTango.ArgType.DevShort + elif opt_type == "LONG": + typ = PyTango.ArgType.DevLong + elif opt_type == "USHORT": + typ = PyTango.ArgType.DevUShort + elif opt_type == "ULONG": + typ = PyTango.ArgType.DevULong + elif opt_type == "FLOAT": + typ = PyTango.ArgType.DevFloat + elif opt_type == "UCHAR": + typ = PyTango.ArgType.DevUChar + elif opt_type == "STRING": + typ = PyTango.ArgType.DevString + elif opt_type == "BOOLEAN": + typ = PyTango.ArgType.DevBoolean + else: + PyTango.Except.throw_exception("BadInput", + "BadInput: (name,data_type,[xsize,[ysize]]), received: " + + str(opt_type) , + "processStrings") + return typ + + +def processInputStringArray(inp_array): + """ Process an input array and return the values for the creation of + PyTango Attribute. + + The input array must have: + name = The name of the new PyTango Attribute. + data_type = string DOUBLE,SHORT or LONG strings + optionals: + [X size] = number of data for 1 and 2 d arrays + [Y size] = number of data for 2 d arrays + + it will return: + (name,PyTangoType,[int,[int]]) + """ + #FIXME: process bad input + #print "processing inp",inp_array + name = inp_array[0].lower() + opt_type = inp_array[1].upper() + if opt_type == "DOUBLE": + typ = PyTango.ArgType.DevDouble + elif opt_type == "SHORT": + typ = PyTango.ArgType.DevShort + elif opt_type == "LONG": + typ = PyTango.ArgType.DevLong + elif opt_type == "USHORT": + typ = PyTango.ArgType.DevUShort + elif opt_type == "ULONG": + typ = PyTango.ArgType.DevULong + elif opt_type == "FLOAT": + typ = PyTango.ArgType.DevFloat + elif opt_type == "UCHAR": + typ = PyTango.ArgType.DevUChar + else: + PyTango.Except.throw_exception("BadInput", + "BadInput: (name,data_type,[xsize,[ysize]]), received: " + + str(inp_array) + " name = " +str(name) + " type = " +opt_type, + "processStrings") + + if (len(inp_array) > 3): + y_size = int(inp_array[3]) + x_size = int(inp_array[2]) + return (name,typ,x_size,y_size) + elif (len(inp_array)>2): + x_size = int(inp_array[2]) + return (name,typ,x_size) + else: + return (name,typ) + +#================================================================== +# Dynamic Class Description: +# +# Creation and management of dynamic attributes that will be used for +# pre and pros-processing of Fermi data. +# +#================================================================== +# Device States Description: +# +# DevState.ON : Working +# DevState.FAULT : +#================================================================== + + +class CaseLessDict(UserDict): + def __init__(self): + UserDict.__init__(self) + def __setitem__(self,key,v): + UserDict.__setitem__(self,key.lower(),v) + def __getitem__(self,key): + key_l = key.lower() + return UserDict.__getitem__(self,key_l) + + +class Dynamic(PyTango.Device_4Impl): + +#--------- Add you global variables here -------------------------- + +#------------------------------------------------------------------ +# Device constructor +#------------------------------------------------------------------ + def __init__(self,cl, name): + PyTango.Device_4Impl.__init__(self,cl,name) + Dynamic.init_device(self) + + +#------------------------------------------------------------------ +# Device destructor +#------------------------------------------------------------------ + def delete_device(self): + self.debug_stream("In %s::delete_device()"%self.get_name()) + +#------------------------------------------------------------------ +# Device initialization +#------------------------------------------------------------------ + def init_device(self): + #print "In ", self.get_name(), "::init_device()" + self.set_state(PyTango.DevState.OFF) + self.get_device_properties(self.get_device_class()) + self.myattrs = CaseLessDict() + self.read_functions = CaseLessDict() + self.write_functions = CaseLessDict() + aux = self.FiltersScript.split('/') + path = '/'.join(aux[:-1]) + if path: + if path not in sys.path: + sys.path.insert(0, path) + module_name = aux[-1].replace('.py','') + try: + self.module = __import__(module_name) + except ImportError, ex: + sys.stderr.write(str(ex)+"\n") + self.module = None + self.set_state(PyTango.DevState.FAULT) + self.set_status("Invalid Filters Script " + self.FiltersScript ) + return + + #link to the Tango DB + self.db = PyTango.Database() + + #creation of dynamic attributes. + try: + xml_file = ScriptXmlConfig(self.XmlConfigurator) + except InvalidFileError, ex: + self.warn_stream("Invalid xml file\n") + self.set_state(PyTango.DevState.OFF) + return + for (key, value) in xml_file.entries.items(): + if value.flag == IS_COMMAND: continue + if not (value.handler.lower() == self.get_name().lower() or value.handler.lower() == 'self'): + try: + #print 'creation of attribute proxy: ', str(value.tango_name) + attr_proxy = PyTango.AttributeProxy(str(value.tango_name)) + attr_value = attr_proxy.read() + attr_config = attr_proxy.get_config() + # + if str(attr_config.data_format) == "SCALAR": + attr = PyTango.Attr(str(value.name), attr_config.data_type, attr_config.writable) + elif str(attr_config.data_format) == "SPECTRUM": + attr = PyTango.SpectrumAttr(str(value.name), attr_config.data_type, attr_config.writable,attr_config.max_dim_x) + elif str(attr_config.data_format) == "IMAGE": + attr = PyTango.ImageAttr(str(value.name), attr_config.data_type, attr_config.writable,attr_config.max_dim_x,attr_config.max_dim_y) + # + self.add_attribute(attr, self.read_proxy, self.write_proxy) + self.myattrs[value.name] = attr_proxy + except PyTango.DevFailed, ex: + self.warn_stream("%s" % str(ex)) + continue + if self.myattrs.has_key(value.name): + PyTango.Except.throw_exception("Exist", + "Attribute "+value.name+ " already defined", + "NewAttribute") + tango_type = dataType2TangoType(value.type.upper()) + permission = READ_ONLY + if value.flag == READ_ONLY: + permission = PyTango.AttrWriteType.READ + elif value.flag == READ_WRITE: + permission = PyTango.AttrWriteType.READ_WRITE + elif value.flag == WRITE_ONLY: + #FIXME: check if it is possible to have write only + permission = PyTango.AttrWriteType.READ_WRITE + + # It's possible to define python methods for calculating the attribute value + self.read_functions[value.name] = value.read_function + self.write_functions[value.name] = value.write_function + if value.dimension == 1: + attr = PyTango.Attr(str(value.name), tango_type, permission) + if value.memorized == 1: + attr.set_memorized() + self.add_attribute(attr, self.read_Scalar,self.write_Scalar) + if tango_type == PyTango.ArgType.DevString: + self.myattrs[value.name] = "" + else: + self.myattrs[value.name] = 0 + if value.default: + self.myattrs[value.name] = eval(value.default) + if value.memorized == 1: + dev_attr_props = self.db.get_device_attribute_property(self.get_name(),[value.name]) + attr_prop = dev_attr_props[value.name] + for pr in attr_prop.keys(): + if (pr == '__value') and (tango_type == PyTango.ArgType.DevString): + self.myattrs[value.name] = attr_prop['__value'][0] + elif (pr == '__value') and (tango_type == PyTango.ArgType.DevFloat): + self.myattrs[value.name] = float(attr_prop['__value'][0]) + elif (pr == '__value') and (tango_type == PyTango.ArgType.DevDouble): + self.myattrs[value.name] = float(attr_prop['__value'][0]) + elif (pr == '__value') and (tango_type == PyTango.ArgType.DevBoolean): + self.myattrs[value.name] = bool(attr_prop['__value'][0] == "True") + elif (pr == '__value'): + self.myattrs[value.name] = int(attr_prop['__value'][0]) + elif isinstance(value.dimension, tuple): + sizx = value.dimension[0] + sizy = value.dimension[1] + attr = PyTango.ImageAttr(str(value.name), tango_type, permission,sizx, sizy) + self.add_attribute(attr, self.read_Image, self.write_Image) + if value.default: + self.myattrs[value.name] = eval(value.default) + elif tango_type == PyTango.ArgType.DevString: + self.myattrs[value.name] = [[],[]] + else: + self.myattrs[value.name] = np.zeros((sizy,sizx),fromPyTango2NumpyType(tango_type)) + else : + self.debug_stream("Creation of attribute %s, dimension = %s" % (value.name, str(value.dimension))) + attr = PyTango.SpectrumAttr(str(value.name), tango_type, permission,value.dimension) + self.add_attribute(attr, self.read_Spectrum, self.write_Spectrum) + if value.default: + self.myattrs[value.name] = eval(value.default) + elif tango_type == PyTango.ArgType.DevString: + self.myattrs[value.name] = [] + else: + self.myattrs[value.name] = np.zeros(value.dimension, fromPyTango2NumpyType(tango_type)) + # + self.set_state(PyTango.DevState.ON) + + +#------------------------------------------------------------------ +# Always excuted hook method +#------------------------------------------------------------------ + def always_executed_hook(self): + self.debug_stream("In %s::always_excuted_hook()"%self.get_name()) + + +#================================================================== +# +# Dynamic read/write attribute methods +# +#================================================================== +#------------------------------------------------------------------ +# Read Attribute Hardware +#------------------------------------------------------------------ + def read_attr_hardware(self,data): + self.debug_stream("In %s::read_attr_hardware()" % self.get_name()) + + +#------------------------------------------------------------------ +# Read Scalar attribute +#------------------------------------------------------------------ + def read_Scalar(self, attr): + #print "In ", self.get_name(), "::read_Scalar()" + + # Add your own code here + data = self.read_dynamic_attribute(attr.get_name()) + # + attr.set_value(data) + + +#------------------------------------------------------------------ +# Write Scalar attribute +#------------------------------------------------------------------ + def write_Scalar(self, attr): + #print "In ", self.get_name(), "::write_Scalar()" + + # Add your own code here + value_in = attr.get_write_value(PyTango.ExtractAs.Numpy) + self.write_dynamic_attribute(attr.get_name(), value_in) + +#------------------------------------------------------------------ +# Read Spectrum attribute +#------------------------------------------------------------------ + def read_Spectrum(self, attr): + #print "In ", self.get_name(), "::read_Spectrum()" + + # Add your own code here + data = self.read_dynamic_attribute(attr.get_name()) + # + attr.set_value(data,len(data)) + + +#------------------------------------------------------------------ +# Write Spectrum attribute +#------------------------------------------------------------------ + def write_Spectrum(self, attr): + #print "In ", self.get_name(), "::write_Spectrum()" + # Add your own code here + value_in = attr.get_write_value(PyTango.ExtractAs.Numpy) + # + self.write_dynamic_attribute(attr.get_name(), value_in) + + +#------------------------------------------------------------------ +# Read Image attribute +#------------------------------------------------------------------ + def read_Image(self, attr): + #print "In ", self.get_name(), "::read_Image()" + + # Add your own code here + data = self.read_dynamic_attribute(attr.get_name()) + # + assert isinstance(data,np.ndarray) + #find_zero = np.where(data == 0) + #data[find_zero] = data.max() + attr.set_value(data) + + +#------------------------------------------------------------------ +# Write Image attribute +#------------------------------------------------------------------ + def write_Image(self, attr): + #print "In ", self.get_name(), "::write_Image()" + # Add your own code here + value_in = attr.get_write_value(PyTango.ExtractAs.Numpy) + self.write_dynamic_attribute(attr.get_name(), value_in) + + + def read_proxy(self, attr): + # Add your own code here + val = self.myattrs[attr.get_name()].read() + data = self.myattrs[attr.get_name()] + attr.set_value(val.value,val.dim_x, val.dim_y) + + def write_proxy(self, attr): + val = attr.get_write_value(PyTango.ExtractAs.Numpy) + self.myattrs[attr.get_name()].write(val) + + + +#================================================================== +# +# Dynamic command methods +# +#================================================================== + +#------------------------------------------------------------------ +# NewScalar command: +# +# Description: +# argin: DevVarStringArray Name - of the new scalar attribute\nDOUBLE, SHORT, LONG for the type of the attribute\n +#------------------------------------------------------------------ + def NewScalar(self, argin): + #print "In ", self.get_name(), "::NewScalar()" + # Add your own code here + (name,typ) = processInputStringArray(argin) + attr = PyTango.Attr(name, typ, + PyTango.AttrWriteType.READ_WRITE) + if self.myattrs.has_key(name): + PyTango.Except.throw_exception("Exist","Attribute "+name+ " already defined","NewAttribute") + self.add_attribute(attr, self.read_Scalar, self.write_Scalar,None) + self.myattrs[name] = 0 + + +#------------------------------------------------------------------ +# NewSpectrum command: +# +# Description: +# argin: DevVarStringArray Name - of the new scalar attribute\nDOUBLE, SHORT, LONG for the type of the attribute\nMaxDim of the spectrum +#------------------------------------------------------------------ + def NewSpectrum(self, argin): + #print "In ", self.get_name(), "::NewSpectrum()" + # Add your own code here + + (name,typ,siz) = processInputStringArray(argin) + + attr = PyTango.SpectrumAttr(name, typ, + PyTango.AttrWriteType.READ_WRITE, + siz + ) + if self.myattrs.has_key(name): + PyTango.Except.throw_exception("Exist","Attribute "+name+ " already defined","NewAttribute") + self.add_attribute(attr, self.read_Spectrum, self.write_Spectrum,None) + self.myattrs[name] = np.zeros(siz,fromPyTango2NumpyType(typ)) + + + +#------------------------------------------------------------------ +# NewImage command: +# +# Description: +# argin: DevVarStringArray Name - of the new scalar attribute\nDOUBLE, SHORT, LONG for the type of the attribute\nMaxDimX of the image\nMaxDimY of the image +#------------------------------------------------------------------ + def NewImage(self, argin): + #print "In ", self.get_name(), "::NewImage()" + # Add your own code here + (name,typ,sizx,sizy) = processInputStringArray(argin) + + attr = PyTango.ImageAttr(name, typ, + PyTango.AttrWriteType.READ_WRITE, + sizx, sizy) + if self.myattrs.has_key(name): + PyTango.Except.throw_exception("Exist","Attribute "+name+ " already defined","NewAttribute") + self.add_attribute(attr, self.read_Image, self.write_Image,None) + self.myattrs[name] = np.zeros((sizy,sizx),fromPyTango2NumpyType(typ)) + #print self.myattrs[name].dtype + + +#------------------------------------------------------------------ +# +#------------------------------------------------------------------ + def ClearAll(self): + #print "In ", self.get_name(), "::ClearAll()" + for k in self.myattrs.keys(): + #print ' attempt to remove key = ' ,k + try: + self.remove_attribute(k.lower()) + except : + pass + # + self.myattrs = CaseLessDict() + self.read_functions = CaseLessDict() + self.write_functions = CaseLessDict() + +#================================================================== +# +# DynamicClass class utilities +# +#================================================================== + +#------------------------------------------------------------------ +# +#------------------------------------------------------------------ + def read_dynamic_attribute(self, attr_name): + if self.read_functions[attr_name] != '': + read_method = getattr(self.module,self.read_functions[attr_name]) + num_of_args = read_method.func_code.co_argcount + if num_of_args == 1: + # If method allows an input parameter, + # it's a reference to this class + data = read_method(self) + else: + data = read_method() + else: + data = self.myattrs[attr_name] + return data + + +#------------------------------------------------------------------ +# +#------------------------------------------------------------------ + def write_dynamic_attribute(self, attr_name, value_in): + if self.write_functions[attr_name] != '': + write_method = getattr(self.module,self.write_functions[attr_name]) + num_of_args = write_method.func_code.co_argcount + if num_of_args == 2: + # If method allows two input parameter, + # the first is a reference to this class + value = write_method(self, value_in) + else: + value = write_method(value_in) + else: + value = value_in + self.myattrs[attr_name] = value + if type(value_in) not in (int,float,str,bool,long): + # Only scalar values can be memorized + return + dict_in = {attr_name:{'__value':value_in}} + self.db.put_device_attribute_property(self.get_name(),dict_in) + + +#================================================================== +# +# DynamicClass class definition +# +#================================================================== +class DynamicClass(PyTango.DeviceClass): + + # Class Properties + class_property_list = { + } + + + # Device Properties + device_property_list = { + 'XmlConfigurator': + [PyTango.DevString, + "Path to the xml config file", + [ "./xml_config.xml"] ], + 'FiltersScript': + [PyTango.DevString, + "Path to the python script that will be executed.", + [ "./test/script_test.py"] ], + 'PythonExecutable': + [PyTango.DevString, + "Path to the python executable.", + [ "python"] ], + } + + + # Command definitions + cmd_list = { + 'NewScalar': + [[PyTango.DevVarStringArray, "Name - of the new scalar attribute\nDOUBLE, SHORT, LONG for the type of the attribute\n"], + [PyTango.DevVoid, ""]], + 'NewSpectrum': + [[PyTango.DevVarStringArray, "Name - of the new scalar attribute\nDOUBLE, SHORT, LONG for the type of the attribute\nMaxDim of the spectrum"], + [PyTango.DevVoid, ""]], + 'NewImage': + [[PyTango.DevVarStringArray, "Name - of the new scalar attribute\nDOUBLE, SHORT, LONG for the type of the attribute\nMaxDimX of the image\nMaxDimY of the image"], + [PyTango.DevVoid, ""]], + 'ClearAll': + [[PyTango.DevVoid,""], + [PyTango.DevVoid,""]], + } + + + # Attribute definitions + attr_list = { + } + + +#------------------------------------------------------------------ +# DynamicClass Constructor +#------------------------------------------------------------------ + def __init__(self, name): + PyTango.DeviceClass.__init__(self, name) + self.set_type(name); + #print "In DynamicClass constructor" + + +#================================================================== +# +# Dynamic class main method +# +#================================================================== +if __name__ == '__main__': + try: + py = PyTango.Util(sys.argv) + py.add_TgClass(DynamicClass,Dynamic,'Dynamic') + + U = PyTango.Util.instance() + U.server_init() + U.server_run() + + except PyTango.DevFailed,e: + print '-------> Received a DevFailed exception:',e + except Exception,e: + print '-------> An unforeseen exception occured....',e diff --git a/src/xmlconfig.py b/src/xmlconfig.py new file mode 100644 index 0000000000000000000000000000000000000000..facb63f2dfa68104aa9532d60979afb200ab29c6 --- /dev/null +++ b/src/xmlconfig.py @@ -0,0 +1,197 @@ +# -*- coding: utf-8 -*- +dbg_ = False +import sys +from xml.dom import minidom +from UserDict import UserDict +#rom collections import namedtuple +import traceback + +class InvalidFileError(Exception): + def __init__(self, value): + self.message = value + def __str__(self): + return repr(self.message) + + +import urllib +import StringIO + +def open_anything(source): + """URI, filename, or string --> stream + + This function lets you define parsers that take any input source + (URL, pathname to local or network file, or actual data as a string) + and deal with it in a uniform manner. Returned object is guaranteed + to have all the basic stdio read methods (read, readline, readlines). + Just .close() the object when you're done with it. + + Examples:: + + >>> from xml.dom import minidom + >>> sock = open_anything("http://localhost/kant.xml") + >>> doc = minidom.parse(sock) + >>> sock.close() + >>> sock = open_anything("c:\\inetpub\\wwwroot\\kant.xml") + >>> doc = minidom.parse(sock) + >>> sock.close() + >>> sock = open_anything("<ref id='conjunction'><text>and</text><text>or</text></ref>") + >>> doc = minidom.parse(sock) + >>> sock.close() + """ + if hasattr(source, "read"): + return source + + if source == '-': + return sys.stdin + + # try to open with urllib (if source is http, ftp, or file URL) + + try: + return urllib.urlopen(source) + except (IOError, OSError): + pass + + # try to open with native open function (if source is pathname) + try: + return open(source) + except (IOError, OSError): + pass + + # treat source as string + + return StringIO.StringIO(str(source)) + +def _get_text(nodelist): + """ Extract an string from a xml node data.""" + rc_ = [node.data for node in nodelist + if node.nodeType == node.TEXT_NODE] + return ''.join(rc_).strip().encode('ascii') + +def _get_value(node, tagname): + """ Extract the value from an xml node""" + values = node.getElementsByTagName(tagname) + if len(values) == 0: + return '' + internal_node = values[0] + return _get_text(internal_node.childNodes) + + +READ_ONLY = 0 +READ_WRITE = 1 +WRITE_ONLY = 2 +IS_COMMAND = 3 + +class XmlItem: + + def __init__(self, flag , type, handler, name, tango_name, + description="", default=None, dimension = 1, + memorized = 0 , read_function = '' , write_function = ''): + self.flag = flag + self.type = type + self.handler = handler + self.tango_name = tango_name + self.name = name + self.description = description + self.default = default + self.dimension = dimension + self.memorized = memorized + self.read_function = read_function + self.write_function = write_function + + def __str__(self): + return "Attr %s = %s/%s \n %s \n %s %d \n %s \n %s"% (self.name, self.handler, + self.name, self.description, self.default, + self.memorized, self.read_function, self.write_function) + +class ScriptXmlConfig: + """ + Parser of the XML file in python usefull class + + attributes a dict with: + - flag: read_only, write_only, read_write + - type: short, double, string, + - handler: tango attribute associated + - name: name or label of this attribute + - description: information for the attribute + - memorized: uses Tango Memorize feature, available only for scalar attributes + - default: default value ( WARNING: is loaded using eval() ) + - read_function: name of the function that will be executed for every read operation + - write_function: name of the function that will be executed for every write operation + + """ + def __init__(self, filename): + self.entries = dict() + self.doc = self._load(filename) + self._parse() + + def __str__(self): + return "DaqXmlConfig %s %s"% (str(self.attributes)) + + def _parse(self): + """Parse the xml file""" + try: + self.handle_entries(self.doc.getElementsByTagName("ATTRIBUTES_RO"),flag=READ_ONLY) + self.handle_entries(self.doc.getElementsByTagName("ATTRIBUTES_RW"),flag=READ_WRITE) + self.handle_entries(self.doc.getElementsByTagName("ATTRIBUTES_WO"),flag=WRITE_ONLY) + self.handle_entries(self.doc.getElementsByTagName("COMMANDS"),flag=IS_COMMAND) + except IndexError: + traceback.print_exc() + raise InvalidFileError( + "Failed to parse the configuration file") + @classmethod + def _load(cls, source): + """load XML input source, return parsed XML document + + - a URL of a remote XML file ("http://diveintopython.org/kant.xml") + - a filename of a local XML file ("~/diveintopython/common/py/kant.xml") + - standard input ("-") + - the actual XML document, as a string + """ + sock = open_anything(source) + try: + xmldoc = minidom.parse(sock).documentElement + except Exception, ex: + raise InvalidFileError(str(ex)) + sock.close() + return xmldoc + + def handle_entries(self, elements, flag): + + for group_of_attributes in elements: + attributes = [attribute + for attribute + in group_of_attributes.childNodes if + attribute.nodeType == 1] + for attribute in attributes: + type = _get_value(attribute, 'TYPE') + handler = _get_value(attribute,'HANDLER') + attr = handler +'/' + _get_value(attribute, 'TANGONAME') + name = attribute.nodeName + desc =_get_value(attribute, 'DESCRIPTION') + dimension_s = _get_value(attribute, 'DIMENSION') + if dimension_s == '': + dimension = 1 + elif dimension_s.find('(')>= 0: + dimension = eval(dimension_s) + else: + dimension = int(dimension_s) + memorized_s = _get_value(attribute, 'MEMORIZED') + if memorized_s == '1' and dimension == 1 : + memorized = 1 + else : + memorized = 0 + # + default_v = _get_value(attribute, 'DEFAULT') + # + read_function = _get_value(attribute, 'READ_FUNCTION') + write_function = _get_value(attribute, 'WRITE_FUNCTION') + # + attr_entry = XmlItem(flag, type,handler,name,attr,desc,default_v,dimension,memorized,read_function,write_function) + if dbg_: print attr_entry + self.entries[attr_entry.name] = attr_entry + + + + +if __name__ == "__main__": + xml = ScriptXmlConfig("./scripts/ldm_daq_conf.xml")