예제 #1
0
    def __init__(self,
                 external_packages=None,
                 export_icons=False,
                 msl_version='3.2'):
        """
        Creates a new instance of ComponentExporter. Opens up a OMCSession and loads
        all necessary Modelica packages.
        """

        self.external_package_paths = make_paths_safe_for_omc(
            external_packages)

        self.logger = logging.getLogger(
            'py_modelica_exporter.ComponentExporter')
        self.logger.setLevel(logging.NOTSET)

        self.logger.info(
            'Initializing ComponentExporter({0})'.format(external_packages))

        # start om session
        self.omc = OMCSession()

        # load all packages
        self.load_packages(self.external_package_paths)

        self.export_icons = export_icons

        if self.export_icons:
            icon_dir_name = 'Icons'
            if not os.path.isdir(icon_dir_name):
                os.mkdir(icon_dir_name)
            self.icon_exporter = IconExporter(self.omc, icon_dir_name)
    def __init__(self, external_packages=None, export_icons=False, msl_version='3.2'):
        """
        Creates a new instance of ComponentExporter. Opens up a OMCSession and loads
        all necessary Modelica packages.
        """

        self.external_package_paths = make_paths_safe_for_omc(external_packages)

        self.logger = logging.getLogger('py_modelica_exporter.ComponentExporter')
        self.logger.setLevel(logging.NOTSET)

        self.logger.info('Initializing ComponentExporter({0})'.format(external_packages))

        # start om session
        self.omc = OMCSession()

        # load all packages
        self.loadPackages(self.external_package_paths)

        self.export_icons = export_icons

        if self.export_icons:
            icon_dir_name = 'Icons'
            if os.path.isdir(icon_dir_name) == False:
                os.mkdir(icon_dir_name)
            self.icon_exporter = IconExporter(self.omc, icon_dir_name)
예제 #3
0
class ComponentExporter(object):
    """
    Class ComponentExporter is an interface with the OpenModelicaCompiler to facilitate extracting class information
    in a single 'Component' format
    """
    def __init__(self,
                 external_packages=None,
                 export_icons=False,
                 msl_version='3.2'):
        """
        Creates a new instance of ComponentExporter. Opens up a OMCSession and loads
        all necessary Modelica packages.
        """

        self.external_package_paths = make_paths_safe_for_omc(
            external_packages)

        self.logger = logging.getLogger(
            'py_modelica_exporter.ComponentExporter')
        self.logger.setLevel(logging.NOTSET)

        self.logger.info(
            'Initializing ComponentExporter({0})'.format(external_packages))

        # start om session
        self.omc = OMCSession()

        # load all packages
        self.load_packages(self.external_package_paths)

        self.export_icons = export_icons

        if self.export_icons:
            icon_dir_name = 'Icons'
            if not os.path.isdir(icon_dir_name):
                os.mkdir(icon_dir_name)
            self.icon_exporter = IconExporter(self.omc, icon_dir_name)

    def load_packages(self, external_package_paths):
        """
        load all external packages into the OpenModelicaCompiler so individual classes may be explored

        @param external_package_paths:
        @return:
        """

        self.omc.loadModel('Modelica')

        for package_path in external_package_paths:
            if os.path.isfile(package_path):  # make sure the file exists
                if self.omc.loadFile(
                        package_path):  # try to load the package file
                    self.logger.info(
                        'Library loaded from : {0}'.format(package_path))
                else:
                    self.logger.warning(
                        'Failed to load: {0}'.format(package_path))
            else:
                self.logger.warning(
                    'File does not exist! Failed to load: {0}'.format(
                        package_path))

    def get_component_json(self, modelica_uri):
        """
        Extracts component and returns a dictionary
        """
        components = []
        json_result = {
            'exportedComponentClass': modelica_uri,
            'icon_path': None,
            'components': []
        }

        if self.export_icons and os.path.isdir('Icons'):
            json_result['icon_path'] = self.icon_exporter.export_icon(
                modelica_uri)

        try:
            self.extract_component_content(modelica_uri, components)
            [
                json_result['components'].append(component.json())
                for component in components
            ]

        except Exception as exception:
            component = Component()
            component.full_name = 'Exception'
            component.comment = exception.message
            json_result['components'].append(component.json())
            self.logger.info(
                'Could not get information for {0}'.format(modelica_uri))

        return json_result

    def get_icon_only(self, modelica_uri):
        """
        Extracts the icon from the Modelica class
        """
        if self.export_icons and os.path.isdir('Icons'):
            self.icon_exporter.export_icon(modelica_uri)

    def get_component_xml(self, modelica_uri):
        """
        Extracts component and returns a xml tree
        """
        components = []
        self.extract_component_content(modelica_uri, components)

        xml_result = etree.Element("Root")
        xml_result.set("ExportedComponent", modelica_uri)
        [xml_result.append(xml_node.xml()) for xml_node in components]

        return xml_result

    def extract_component_content(self, modelica_uri, components):
        """
        Recursively populates components with extracted_components,
        starting from modelica_uri and goes through the extends.
        """
        component = Component()
        component.full_name = modelica_uri
        component.comment = self.omc.getClassComment(modelica_uri)

        components.append(component)

        try:
            #mo_packages = self.omc.getPackages(modelica_uri)
            mo_replaceables = self.omc.getReplaceables(modelica_uri)
            mo_extends_packages = self.omc.getPackagesFromExtends(modelica_uri)

            for replaceable_package in mo_replaceables:
                package = Package()
                package.name = replaceable_package['name']
                package.value = replaceable_package['value']
                component.packages.append(package)

            for extends_class, extends_package in mo_extends_packages.iteritems(
            ):
                package = Package()
                package.name = extends_package['name']
                package.value = extends_package['value']
                component.packages.append(package)

        except ValueError as value_error_exception:
            if value_error_exception.args[
                    0] == 'Could not parse OMC response.':
                e_msg = 'Could not parse OMC response for getReplaceables({0}) or getPackagesFromExtends()'.format(
                    modelica_uri)
                self.logger.warning(e_msg)
                raise ParsingException

        try:
            mo_components = self.omc.getComponents(modelica_uri)
        except ValueError as value_error_exception:
            if value_error_exception.args[
                    0] == 'Could not parse OMC response.':
                self.logger.warning(
                    'Could not parse OMC response for getComponents({0})'.
                    format(modelica_uri))
                raise ParsingException

        for (mo_type, mo_name, mo_annotation, mo_modification, v_1, v_2, v_3,
             isReplaceable, component_type, v_5, v_6, v_7) in mo_components:

            if self.omc.isConnector(mo_type):
                connector = Connector()
                connector.full_name = mo_type
                connector.name = mo_name
                connector.description = mo_annotation

                modifier_names = self.omc.getComponentModifierNames(
                    modelica_uri, mo_name)
                modifiers = dict()
                modifiers['modifications'] = mo_modification
                for modifier_name in modifier_names:
                    modifier_value = self.omc.getComponentModifierValue(
                        modelica_uri, '{0}.{1}'.format(mo_name, modifier_name))
                    modifiers[modifier_name] = modifier_value
                    connector.modifiers = modifiers

                if (len(component.packages) != 0) and (
                        'Modelica.Fluid.Interfaces.FluidPort_' in mo_type):
                    port_redeclare = self.omc.getPortRedeclares(
                        modelica_uri, mo_type, mo_name)
                    if port_redeclare:
                        for package in component.packages:
                            if port_redeclare[1] == package.name:
                                redeclare_parameter = RedeclareParameter()
                                redeclare_parameter.name = port_redeclare[0]
                                redeclare_parameter.value = port_redeclare[1]
                                #redeclare_parameter.value = package.value

                                connector.redeclare_parameters.append(
                                    redeclare_parameter)
                                break

                component.connectors.append(connector)

            elif component_type == 'parameter':
                parameter = Parameter()
                if mo_modification != 'public':
                    parameter.is_public = False

                parameter.name = mo_name
                parameter.description = mo_annotation
                parameter.full_name = mo_type
                parameter.value = self.omc.getParameterValue(
                    modelica_uri, mo_name)

                value_type = type(parameter.value)

                if value_type == tuple:
                    parameter.dimension = len(
                        parameter.value)  # log the length of the tuple
                elif value_type == str:
                    if parameter.value == '':
                        parameter.dimension = 0  # 0 indicates an empty string
                    elif '[' in parameter.value:
                        semicolon_split = parameter.value.split(';')
                        if len(semicolon_split) > 1:
                            # this means a table with dimension (n,m); should we actually log the values? or only '-1'?
                            parameter.dimension = -1
                        else:
                            # if there are no semicolons, then this is a 1-d array (?)
                            comma_split = parameter.value.split(',')
                            parameter.dimension = len(comma_split)

                for modifier_name in self.omc.getComponentModifierNames(
                        modelica_uri, mo_name):
                    modifier_value = self.omc.getComponentModifierValue(
                        modelica_uri, '{0}.{1}'.format(mo_name, modifier_name))
                    parameter.modifiers.update({modifier_name: modifier_value})

                if self.omc.isType(mo_type):
                    parameter.full_name = get_parameter_base_type_and_modifiers(
                        self.omc, mo_type, parameter.modifiers)

                component.parameters.append(parameter)

            else:
                pass  # the object is not a connector or a parameter

        mo_inheritance_count = self.omc.getInheritanceCount(modelica_uri)

        for i in range(1, mo_inheritance_count + 1):
            extend = Extend()
            mo_extend_class_name = self.omc.getNthInheritedClass(
                modelica_uri, i)

            if mo_extend_class_name in mo_extends_packages:
                redeclare_parameter = RedeclareParameter()
                redeclare_parameter.name = mo_extends_packages[
                    mo_extend_class_name]['name']
                redeclare_parameter.redeclare_type = 'package'
                redeclare_parameter.value = mo_extends_packages[
                    mo_extend_class_name]['value']
                extend.redeclare_parameters.append(redeclare_parameter)

            mo_extend_class_modifiers = self.omc.getExtendsModifierNames(
                modelica_uri, mo_extend_class_name)

            extend.modifiers = {}

            for extend_class_modifier in mo_extend_class_modifiers:
                if '.' in extend_class_modifier:
                    # this is a modifier
                    extend.modifiers[
                        extend_class_modifier] = self.omc.getExtendsModifierValue(
                            modelica_uri, mo_extend_class_name,
                            extend_class_modifier)
                else:
                    # this is a parameter
                    extend_parameter = Parameter()
                    extend_parameter.name = extend_class_modifier
                    extend_parameter.value = self.omc.getExtendsModifierValue(
                        modelica_uri, mo_extend_class_name,
                        extend_class_modifier)
                    extend.parameters.append(extend_parameter)

            extend.full_name = mo_extend_class_name

            component.extends.append(extend)

            self.extract_component_content(mo_extend_class_name, components)

        mo_import_count = self.omc.getImportCount(modelica_uri)
        for i in range(1, mo_import_count + 1):
            import_item = Import()

            mo_import = self.omc.getNthImport(modelica_uri, i)

            import_item.full_name = mo_import[0]
            import_item.id = mo_import[1]
            import_item.kind = mo_import[2]

            component.imports.append(import_item)
class ComponentExporter(object):

    def __init__(self, external_packages=None, export_icons=False, msl_version='3.2'):
        """
        Creates a new instance of ComponentExporter. Opens up a OMCSession and loads
        all necessary Modelica packages.
        """

        self.external_package_paths = make_paths_safe_for_omc(external_packages)

        self.logger = logging.getLogger('py_modelica_exporter.ComponentExporter')
        self.logger.setLevel(logging.NOTSET)

        self.logger.info('Initializing ComponentExporter({0})'.format(external_packages))

        # start om session
        self.omc = OMCSession()

        # load all packages
        self.loadPackages(self.external_package_paths)

        self.export_icons = export_icons

        if self.export_icons:
            icon_dir_name = 'Icons'
            if os.path.isdir(icon_dir_name) == False:
                os.mkdir(icon_dir_name)
            self.icon_exporter = IconExporter(self.omc, icon_dir_name)

    def loadPackages(self, external_package_paths):

        self.omc.loadModel('Modelica')

        for package_path in external_package_paths:
            if os.path.isfile(package_path) == True:                        # make sure the file exists
                if self.omc.loadFile(package_path) == True:         # try to load the package file
                    self.logger.info('Library loaded from : {0}'.format(package_path))
                else:
                    self.logger.warning('Failed to load: {0}'.format(package_path))
            else:
                self.logger.warning('File does not exist! Failed to load: {0}'.format(package_path))

    def get_component_json(self, modelica_uri):
        """
        Extracts component and returns a dictionary
        """
        components = []
        json_result = {'exportedComponentClass': modelica_uri,
                       'icon_path': None,
                       'components': []}

        if self.export_icons and os.path.isdir('Icons'):
            json_result['icon_path'] = self.icon_exporter.export_icon(modelica_uri)

        try:
            self.extract_component_content(modelica_uri, components)
            [json_result['components'].append(component.json()) for component in components]

        except Exception as exception:
            component = Component()
            component.full_name = 'Exception'
            component.comment = exception.message
            json_result['components'].append(component.json())
            self.logger.info('Could not get information for {0}'.format(modelica_uri))

        return json_result

    def get_icon_only(self, modelica_uri):

        if self.export_icons and os.path.isdir('Icons'):
            self.icon_exporter.export_icon(modelica_uri)

    def get_component_xml(self, modelica_uri):
        """
        Extracts component and returns a xml tree
        """
        components =[]
        self.extract_component_content(modelica_uri, components)

        xml_result = etree.Element("Root")
        xml_result.set("ExportedComponent", modelica_uri)
        [xml_result.append(xml_node.xml()) for xml_node in components]

        return xml_result

    def extract_component_content(self, modelica_uri, components):
        """
        Recursively populates components with extracted_components,
        starting from modelica_uri and goes through the extends.
        """
        component = Component()
        component.full_name = modelica_uri
        component.comment = self.omc.getClassComment(modelica_uri)

        components.append(component)

        try:
            #mo_packages = self.omc.getPackages(modelica_uri)
            mo_replaceables = self.omc.getReplaceables(modelica_uri)
            mo_extends_packages = self.omc.getPackagesFromExtends(modelica_uri)

            for replaceable_package in mo_replaceables:
                package = Package()
                package.name = replaceable_package['name']
                package.value = replaceable_package['value']
                component.packages.append(package)

            for extends_class, extends_package in mo_extends_packages.iteritems():
                package = Package()
                package.name = extends_package['name']
                package.value = extends_package['value']
                component.packages.append(package)

        except ValueError as ex:
            if ex.args[0] == 'Could not parse OMC response.':
                self.logger.warning('Could not parse OMC response for getReplaceables({0}) or getPackagesFromExtends()'.format(modelica_uri))
                raise ParsingException

        try:
            mo_components = self.omc.getComponents(modelica_uri)
        except ValueError as ex:
            if ex.args[0] == 'Could not parse OMC response.':
                self.logger.warning('Could not parse OMC response for getComponents({0})'.format(modelica_uri))
                raise ParsingException

        for (mo_type, mo_name, mo_annotation, mo_modification, v1, v2, v3, isReplaceable, component_type, v5, v6, v7) in mo_components:

            if self.omc.isConnector(mo_type):
                connector = Connector()
                connector.full_name = mo_type
                connector.name = mo_name
                connector.description = mo_annotation

                modifier_names = self.omc.getComponentModifierNames(modelica_uri, mo_name)
                modifiers = dict()
                modifiers['modifications'] = mo_modification
                for modifier_name in modifier_names:
                    modifier_value = self.omc.getComponentModifierValue(modelica_uri, '{0}.{1}'.format(mo_name, modifier_name))
                    modifiers[modifier_name] = modifier_value
                    connector.modifiers = modifiers

                if (len(component.packages) != 0) and ('Modelica.Fluid.Interfaces.FluidPort_' in mo_type):
                    portRedeclare = self.omc.getPortRedeclares(modelica_uri, mo_type, mo_name)
                    if portRedeclare:
                        for package in component.packages:
                            if portRedeclare[1] == package.name:
                                redeclare_parameter = RedeclareParameter()
                                redeclare_parameter.name = portRedeclare[0]
                                redeclare_parameter.value = portRedeclare[1]
                                #redeclare_parameter.value = package.value

                                connector.redeclare_parameters.append(redeclare_parameter)
                                break

                component.connectors.append(connector)

            elif component_type == 'parameter':
                parameter = Parameter()
                if mo_modification != 'public':
                    parameter.is_public = False

                parameter.name = mo_name
                parameter.description = mo_annotation
                parameter.full_name = mo_type
                parameter.value = self.omc.getParameterValue(modelica_uri, mo_name)

                value_type = type(parameter.value)

                if value_type == tuple:
                    parameter.dimension = len(parameter.value)  # log the length of the tuple
                elif value_type == str:
                    if parameter.value == '':
                        parameter.dimension = 0  # 0 indicates an empty string
                    elif '[' in parameter.value:
                        semicolon_split = parameter.value.split(';')
                        if len(semicolon_split) > 1:
                            # this means a table with dimension (n,m); should we actually log the values? or only '-1'?
                            parameter.dimension = -1
                        else:
                            # if there are no semicolons, then this is a 1-d array (?)
                            comma_split = parameter.value.split(',')
                            parameter.dimension = len(comma_split)

                for modifier_name in self.omc.getComponentModifierNames(modelica_uri, mo_name):
                    modifier_value = self.omc.getComponentModifierValue(modelica_uri, '{0}.{1}'.format(mo_name, modifier_name))
                    parameter.modifiers.update({modifier_name: modifier_value})

                if self.omc.isType(mo_type):
                    parameter.full_name = get_parameter_base_type_and_modifiers(self.omc, mo_type, parameter.modifiers)

                component.parameters.append(parameter)

            else:
                pass # the object is not a connector or a parameter

        mo_inheritance_count = self.omc.getInheritanceCount(modelica_uri)

        for i in range(1, mo_inheritance_count + 1):
            extend = Extend()
            mo_extend_class_name = self.omc.getNthInheritedClass(modelica_uri, i)

            if mo_extend_class_name in mo_extends_packages:
                redeclare_parameter = RedeclareParameter()
                redeclare_parameter.name = mo_extends_packages[mo_extend_class_name]['name']
                redeclare_parameter.redeclare_type = 'package'
                redeclare_parameter.value = mo_extends_packages[mo_extend_class_name]['value']
                extend.redeclare_parameters.append(redeclare_parameter)

            mo_extend_class_modifiers = self.omc.getExtendsModifierNames(modelica_uri, mo_extend_class_name)

            extend.modifiers = {}

            for mo_extend_class_modifier in mo_extend_class_modifiers:
                if '.' in mo_extend_class_modifier:
                    # this is a modifier
                    extend.modifiers[mo_extend_class_modifier] = self.omc.getExtendsModifierValue(modelica_uri, mo_extend_class_name, mo_extend_class_modifier)
                else:
                    # this is a parameter
                    extend_parameter = Parameter()
                    extend_parameter.name = mo_extend_class_modifier
                    extend_parameter.value = self.omc.getExtendsModifierValue(modelica_uri, mo_extend_class_name, mo_extend_class_modifier)
                    extend.parameters.append(extend_parameter)

            extend.full_name = mo_extend_class_name

            component.extends.append(extend)

            self.extract_component_content(mo_extend_class_name, components)

        # TODO: Shouldn't this be done for all components?
        mo_import_count = self.omc.getImportCount(modelica_uri)
        for i in range(1, mo_import_count + 1):
            import_item = Import()

            mo_import = self.omc.getNthImport(modelica_uri, i)

            import_item.full_name = mo_import[0]
            import_item.id = mo_import[1]
            import_item.kind = mo_import[2]

            component.imports.append(import_item)