configpyros.py 8.34 KB
# python c:\srv\develop\pyros\config\configpyros.py
# ----------------------------------------------------------------------------------------------------
# Parameter attributes = section, key, value, type, unit, access, comment, label, reference, timestamp
# ----------------------------------------------------------------------------------------------------
from lxml import etree
import os

class ConfigPyros:
    
    # === Constants
    NO_ERROR = 0
    ERR_FILE_NOT_EXISTS = 100
    ERR_LOAD_ERROR = 200
    ERR_TAG_ROOT_IS_NOT_UNIT = 201
    ERR_TAG_ROOT_HAS_NO_ATTRIBUTE_ALIAS = 202

    # === Private variables
    _last_errno = NO_ERROR
    _config_filename = ""
    _config_filename_mtime = 0
    _config_filename_need_to_be_read = True
    _unit_component_params = []
    _unit_component_params_valid = False
    
    def get_last_errno(self):
        """ Get the last error code
        """
        return self._last_errno
        
    def set_configfile(self, config_filename:str ):
        """ To set the config file name
        
        :param config_filename: A string that contains the full name of the configuration file.
        :type config_filename: string
        """
        if config_filename == "" or config_filename != self._config_filename:
            self._config_filename = config_filename
            self._config_filename_mtime = 0
            self._unit_component_params_valid = False
            self._unit_component_params = []
        self._configfile_verify()
        return
        
    def get_configfile(self):
        """ Get the current config file name
        """
        return self._config_filename
        
    def _configfile_verify(self):
        """ Update parameters of the configuration file (existing, modification date)
        """
        self._config_filename_need_to_be_read = False
        self._last_errno = self.NO_ERROR
        if os.path.isfile(self._config_filename):
            # --- verify the date of last modification of the file
            config_filename_mtime = os.path.getmtime(self._config_filename)
            if config_filename_mtime > self._config_filename_mtime:
                self._config_filename_need_to_be_read = True                
                #### self._config_filename_mtime = config_filename_mtime
        else:
            self._last_errno = self.ERR_FILE_NOT_EXISTS
    
    
    def load(self, verbose:bool = False):
        """ To load the config file if necessary
        
        :Example:
            
        ConfigPyros().load()
        """

        self._configfile_verify()
        errno = self.get_last_errno()
        if errno != self.NO_ERROR:
            return
        if self._config_filename_need_to_be_read == False:
            return

        # --- Read the configuration file and parse it
        self._last_errno = self.NO_ERROR
        unit_component_params = []
        try:
            tree = etree.parse(self._config_filename)
            # --- Get root from the tree
            root = tree.getroot()

            # === Verify the root tag is 'unit'
            verify_unit = root.tag
            if (verify_unit != "unit"):
                self._last_errno = self.ERR_TAG_ROOT_IS_NOT_UNIT
                return
                
            # === Get the alias value of the root tag 'unit'
            alias_unit = root.attrib['alias']
            if (alias_unit == ""):
                self._last_errno = self.ERR_TAG_ROOT_HAS_NO_ATTRIBUTE_ALIAS
                return
            
            # === Get the mount aliases
            alias_mounts = []
            for elem in root.xpath("/unit/mount"):
                # print(elem.tag, elem.attrib)
                alias_mounts.append(elem.attrib['alias'])
            if (verbose==True):
                print("alias_mounts = {}".format(alias_mounts))

            # === Get the channel aliases
            alias_channels = []
            for elem in root.xpath("/unit/channel"):
                # print(elem.tag, elem.attrib)
                alias_channels.append(elem.attrib['alias'])
            if (verbose==True):
                print("alias_channels = {}".format(alias_channels))

            # === Get the association of channels for this mount
            unit_components = []
            for elem in root:
                if elem.tag == "param":
                    attributes = elem.attrib
                    if attributes['section'] != "instanciation":
                        continue
                    alias_param_unit = attributes['value']
                    for alias_mount in alias_mounts:
                        if alias_param_unit == alias_mount:
                            key = attributes['key']
                            dico = {'tag':'mount','instanciation':key,'alias':alias_param_unit}
                            unit_components.append(dico)
                    for alias_channel in alias_channels:
                        if alias_param_unit == alias_channel:
                            key = attributes['key']
                            dico = {'tag':'channel','instanciation':key,'alias':alias_param_unit}
                            unit_components.append(dico)
            if (verbose==True):
                print("unit_components = {}".format(unit_components))

            # === Get detailed informations about the unit components
            for unit_component in unit_components:
                tag = unit_component['tag']
                instanciation = unit_component['instanciation']
                alias = unit_component['alias']
                params = []
                for elem in root:
                    if (elem.tag == tag) and (elem.attrib['alias'] == alias):
                        for el in elem:
                            if (el.tag == "param"):
                                params.append(el.attrib)
                unit_component_params.append({'component':tag, 'instanciation':instanciation, 'alias':alias, 'params':params})
            if (verbose==True):
                print("unit_component_params = {}".format(unit_component_params))
            self._unit_component_params = unit_component_params
            self._unit_component_params_valid = True
            self._config_filename_mtime = os.path.getmtime(self._config_filename)
        except:
            self._last_errno = self.ERR_LOAD_ERROR
        return
    
    def get_paramvalue(self, instanciation:str, section:str, key:str):
        if self._unit_component_params_valid == False:
            return ""
        unit_component_params = self._unit_component_params
        paramvalue = ""
        for unit_component_param in unit_component_params:
            component_instanciation = unit_component_param['instanciation']
            if (component_instanciation == instanciation):
                for param in unit_component_param['params']:
                    param_section = param['section']
                    param_key = param['key']
                    if (param_section == section) and (param_key == key):
                        paramvalue = param['value']
                        break
                if (paramvalue != ""):
                    break
        return paramvalue
    
    def __init__(self, config_filename:str = ""):
        self._last_errno = self.NO_ERROR
        self._unit_component_params = []
        self.set_configfile(config_filename)
    
if __name__ == "__main__":
    # --- Set the filename of the configuration
    config_filename = 'c:/srv/develop/pyros/config/config_unit_simulunit1.xml'
    #config_filename = '/PROJECTS/GFT/SOFT/PYROS_SOFT/CURRENT/config/config_unit_simulunit1.xml'
    # --- Instanciate an object for configuration
    config = ConfigPyros(config_filename)
    #config.set_configfile(config_filename)
    if config.get_last_errno() != config.NO_ERROR:
        print("Error code = {}".format(config.get_last_errno()))
    else:     
        # --- Load the configuration file if needed only (i.e. modified)
        config.load()
        # --- get the parameter value of <mount1/localization/home>
        instanciation = 'mount1'
        section = 'localization'
        key = 'home'
        paramvalue = config.get_paramvalue(instanciation, section, key)
        print("paramvalue <{}/{}/{}> = {}".format(instanciation, section, key,paramvalue))
        #
        #print("unit_component_params = {}".format(unit_component_params))
        #component = unit_component_params[0]
        #params = component['params']
        #print("params = {}".format(params))