Source code for pysd.translators.xmile.xmile_file

"""
The XmileFile class allows reading the original Xmile model file and
parsing it into Section elements. The final result can be exported to an
AbstractModel class in order to build a model in another programming language.
"""
from typing import Union
from pathlib import Path
from lxml import etree

from ..structures.abstract_model import AbstractModel

from .xmile_section import Section
from .xmile_utils import supported_extensions


[docs] class XmileFile(): """ The XmileFile class allows parsing an Xmile file. When the object is created, the model file is automatically opened and parsed with lxml.etree. Parameters ---------- xmile_path: str or pathlib.Path Path to the Xmile model. """ def __init__(self, xmile_path: Union[str, Path]): self.xmile_path = Path(xmile_path) self.root_path = self.xmile_path.parent self.xmile_root = self._get_root() self.ns = self.xmile_root.nsmap[None] # namespace of the xmile self.view_elements = None def __str__(self): # pragma: no cover return "\nXmile model file, loaded from:\n\t%s\n" % self.xmile_path @property def _verbose(self) -> str: # pragma: no cover """Get model information.""" text = self.__str__() for section in self.sections: text += section._verbose return text @property def verbose(self): # pragma: no cover """Print model information to standard output.""" print(self._verbose) def _get_root(self) -> etree._Element: """ Read an Xmile file and assign its content to self.model_text Returns ------- lxml.etree._Element: parsed xml object """ # check for model extension if self.xmile_path.suffix.lower() not in supported_extensions: raise ValueError( "The file to translate, '%s' " % self.xmile_path + "is not a Xmile model. It must end with any of " + "%s extensions." % ', '.join(supported_extensions) ) return etree.parse( str(self.xmile_path), parser=etree.XMLParser(encoding="utf-8", recover=True) ).getroot()
[docs] def parse(self, parse_all: bool = True) -> None: """ Create a XmileSection object from the model content and parse it. As macros are currently not supported, all models will have a single section. This function should split the macros in independent sections in the future. Parameters ---------- parse_all: bool (optional) If True, the created XmileSection objects will be automatically parsed. Otherwise, these objects will only be added to self.sections but not parsed. Default is True. """ # TODO: in order to make macros work we need to split them here # in several sections # We keep everything in a single section self.sections = [Section( name="__main__", path=self.xmile_path.with_suffix(".py"), section_type="main", params=[], returns=[], content_root=self.xmile_root, namespace=self.ns, split=False, views_dict=None)] if parse_all: for section in self.sections: section.parse()
[docs] def get_abstract_model(self) -> AbstractModel: """ Get Abstract Model used for building. This, method should be called after parsing the model (self.parse). This automatically calls the get_abstract_section method from the model sections. Returns ------- AbstractModel: AbstractModel Abstract Model object that can be used for building the model in another language. """ return AbstractModel( original_path=self.xmile_path, sections=tuple(section.get_abstract_section() for section in self.sections))