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)
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)