Integration with Python and pyEcore

Introduction

There are currently two ways to create and build Energy Systems with Python. The first is to use the XSD created from the Ecore model and use an XSD to Python class generator to generate python classes. There are a few generators available, but we have useful result with generateDS. You can read here more for this approach.

An alternative is using pyEcore. PyEcore is the python equivalent of the Eclipse EMF Ecore implementation. This means that the ESDL meta-model is at runtime available to you for reading, writing and changing ESDL instances. This section provides some examples to use pyEcore to do just that. PyEcore offers two ways:

  • Using a dynamic instance of the model. This means that at runtime the Ecore-model is read and Python classes are dynamically instantiated.

  • Using a static instance of the model. This means that you first generate Python classes from the Ecore model (similar to the XSD-approach) and import these in your project.

The pyEcore approach provides some benefits above the XSD approach:

  • In the transformation from Ecore to XSD, some information is lost, which makes validation more difficult.

  • Assigning a value to a cross-reference will automatically set the eOpposite() of it, e.g. in the case of the connectedTo reference of a Port

  • Type checking when assigning values to e.g. a reference or a primitive type.

  • Since pyEcore is using the ESDL Ecore model as a basis and can create a dynamic instance of the model at runtime, there is no need for generating files/classes before you can use a new version of the core model. Especially during development of the ESDL ecore model this approach is convenient. The downside is that auto completion in the IDE (e.g. PyCharm) is not available.

  • All Python objects created for ESDL (both dynamic and static) inherit from the EClass class (similar to the Java generated files). This means that you can query the meta model at runtime and get e.g. the contents of the class using eclass.eContents. Also notification support is available, if your code needs to know when parts of the model are changed. See the pyEcore documentation at https://pyecore.readthedocs.io/en/latest/user/quickstart.html for more information and features.

Currently pyEcore support the XMI format for storing models and model instances. As ESDL is currently not using the XMI features, but only the XMLResource in the plugins, you need to register esdl-files with the XMLResource, otherwise the XMI namespace and the XMI version information is added to the ESDL-file when saving, giving errors when loading this file in Eclipse with the ESDL plugins. To use XMLResources you need to download the file attached at the end of this page and import it in your project (as done in all the examples below).

Prerequisites

You can install pyecore and pyecoregen using pip

pip install pyecore
pip install pyecoregen

Using dynamic instances to work with ESDL files

Creating and storing an ESDL file using dynamic instances can then be done as follows. Note that there is no need to generated classes first, nor clone the ESDL-repository on github, as the ESDL Ecore model is automatically downloaded from github.

Creating and storing Energy Systems

Loading ESDL models

Loading an ESDL instance is as follows:

Using the generated classes to create ESDL

To have the Python classes available offline and use auto-completion in your favorite Python Editor, PyEcoreGen can be used to generate the ESDL-classes from the esdl.ecore model. On the command line do the following: $ pyecoregen -e https://raw.githubusercontent.com/EnergyTransition/ESDL/master/esdl/model/esdl.ecore -o . --auto-register-package

This creates an esdl/folder and and esdl.py that contain all the classes from the ESDL model. More information about pyEcoreGen can be found here.

There is also an alternative way to generate classes programmatically by executing the following code:

Loading ESDL files using the generated Python classes

Use the following code to use the generated classes in your Python code:

Show attributes and their values of Python classes

When you try to print() e.g. an Energy System, you see something like: print(es) you get the following information that does not show the attributes of the EnergySystem, but that it is an object of type esdl.esdl.EnergySystem at a certain memory location: <esdl.esdl.EnergySystem object at 0x000002A66FE60390> A convenient method to print the results of an object is the following code. That code creates a dictionary from the EClass with all its attributes and their values.

If you now do aprint(attr_to_dict(es)) you get the following output for the Municipality Example found here:

You can also change the __repr__ of the classes, e.g. by changing the __repr__ of the python_class attribute, e.g. EnergySystem.python_class.__repr__ = lambda x: 'EnergySystem(name={})'.format(x.name)

Manipulating and saving ESDL files

The following example lets you create and save Energy Systems using the generated ESDL classes:

XMLResource support for PyEcore

Use the following file to support XMLResources instead of the default XMIResource support of PyEcore

Last updated