Skip to main content

Motra is a librairie providing model transformations facilities to PyEcore. The goal of the librairie is to propose a set of embedded DSLs in Python for models to models transformations (M2M) and model to text transformations (M2T) with advanced traceability mechanism. Here are some characteristics about Motra M2M:

  • it proposes a semantic close to QVTo, imperative, based on mappings where the execution order is defined by the developer in each mapping,

  • it supports multiple input and multiple outputs,

  • each mapping result is cached and when a mapping is called twice with a same set of parameters, the exact same created object is returned,

  • by default, any object created in a mapping that is not explicitaly placed in a container is automatically added as model root,

  • used metamodels are automatically registered for smooth load/save of any models.

  • it supports mapping polymorphism without having to rely on manual coding a dispatch with a disjunct (if the mappings own the same name)

Documentation

WIP, at the moment, please refer to transformations examples in examples. To avoid the need to load/install special metamodels, all the transformations examples are given directly over Ecore. The transformations are gathered in simple modules depending to their characteristics: in-place, in-out, endogenous or exogenous.

M2M Quick start

Each transformation must be defined in it’s own Python module (even if multiple transformations can be defined in one module).

# import the input and output metamodels
import ghmde  # based on https://github.com/kolovos/datasets/blob/master/github-mde/ghmde.ecore
import graph  # based on a simple graph metamodel

# import motra for utils and for M2M transformation definition
import motra
from motra import m2m

# M2M transformation "signature" definition
ghmde2graph = m2m.Transformation('ghmde2graph',
                                 inputs=['ghmde_model'],
                                 outputs=['graph_model'])


# defines the entry point of the transformation
@ghmde2graph.main
def main(ghmde_model, graph_model):
    print('Transforming repository to graph', graph_model)
    for f in motra.objects_of_kind(ghmde_model, ghmde.File):
        file2node(f)
    for repository in motra.objects_of_kind(ghmde_model, ghmde.Repository):
        repository2graph(repository, postfix='_graph')
    # m2m.objects_of_kind

# defines a first mapping transforming Files in Node
@ghmde2graph.mapping
def file2node(self: ghmde.File) -> Node:
    result.name = self.path   # The "result" variable is automatically created and injected in the current context


# defines a conditional mapping from Repository to Graph
def does_not_starts_with(self, postfix):
    return not self.name.startswith(postfix)

@ghmde2graph.mapping(when=does_not_starts_with)
def repository2graph(self: ghmde.Repository, postfix: str) -> Graph:
    result.name = self.name + postfix
    for repo_file in self.files:
        result.nodes.append(file2node(repo_file))

Then, it can be imported and directly used from another module. Currently, there is no default runner, but there will be in the future, a way of defining models transformations chains.

# Import the transformation
from transfo_example import ghmde2graph

# Just run it. Input can be a "Resource" or directly a file
result_context = ghmde2graph.run(ghmde_model="input_model.xmi")*

# A result context gives access to:
# * the inputs
# * the outputs
# * the execution trace (still WIP)
# * the transformation definition
# * the used resource set for this transformation
result_context.inputs.ghmde_model.save(output="input_copy.xmi")
result_context.outputs.graph_model.save(output="test.xmi")

M2T Quick start

As for M2M, a M2T transformation must be defined in it’s own Python module (even if multiple transformations can be defined in one module as defined in the module examples/m2t/sample.py). Each template code is written as __doc__ of template functions.

from motra import m2t
import pyecore.ecore as ecore

# M2T transformation "signature" definition
ecore2simplejava = m2t.Transformation("ecore2simplejava")

# Definition of the main entry point.
# At the moment, entry-point cannot have "when=" parameter
# The special <%motra:file ><%/motra:file> is used to specify blocs
# where the code must be written. Multiple "file" tags can be introduced by template.
@ecore2simplejava.main
def eclass2class(self: ecore.EClass):
    """
<%motra:file path="examples/outputs/${self.ePackage.name}/${self.name}.java">
public class ${self.name.capitalize()} {
    % for feature in self.eStructuralFeatures:
    // ${override(feature)}
    ${feature2attribute(feature)}
    % endfor
}
</%motra:file>
"""

@ecore2simplejava.template(
    when=lambda self: self.many
)
def feature2attribute(self: ecore.EAttribute):
    """List<${self.eType.name}> ${self.name}; // many attribute"""


@ecore2simplejava.template
def feature2attribute(self: ecore.EAttribute):
    """${self.eType.name} ${self.name}; // single attribute"""


@ecore2simplejava.template(
    when=lambda self: self.many
)
def feature2attribute(self: ecore.EReference):
    """List<${self.eType.name}> ${self.name}; // many reference"""


@ecore2simplejava.template
def feature2attribute(self: ecore.EReference):
    """List<${self.eType.name}> ${self.name}; // single reference"""


@ecore2simplejava.template
def override(self: ecore.EAttribute):
    """Attribut ${self.name}: ${self.eType.name} [${self.lowerBound}..${upper2symbol(self)}]"""


@ecore2simplejava.template
def override(self: ecore.EReference):
    """Reference ${self.name}: ${self.eType.name} [${self.lowerBound}..${upper2symbol(self)}]"""


@ecore2simplejava.helper
def upper2symbol(self: ecore.EStructuralFeature):
    return '*' if self.many else self.upperBound

Then, it can be imported and directly used from another module. Currently, there is no default runner, but there will be in the future, a way of defining models transformations chains.

# Import the transformation
from examples.m2t.sample import ecore2simplejava

# Just run it. Input can be a "Resource", a model or directly a file
ecore2simplejava.run('examples/inputs/input.ecore')

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

motra-0.1.1.tar.gz (12.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

motra-0.1.1-py3-none-any.whl (10.7 kB view details)

Uploaded Python 3

File details

Details for the file motra-0.1.1.tar.gz.

File metadata

  • Download URL: motra-0.1.1.tar.gz
  • Upload date:
  • Size: 12.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.2 CPython/3.9.1

File hashes

Hashes for motra-0.1.1.tar.gz
Algorithm Hash digest
SHA256 484921b53449ff5f616b6e1f2eae8fd217b6424f8a0e4bb835e9257c5e81be68
MD5 83aa7d905c6fc6e34865cd4a3e4b5128
BLAKE2b-256 73932f6f71c692d442a1c0b25f7777dde2811920ee706eb7a85afa98ed6f53d9

See more details on using hashes here.

File details

Details for the file motra-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: motra-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 10.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.2 CPython/3.9.1

File hashes

Hashes for motra-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 1c97e4f7f678e81a755882f888b63459670a52183b79f05ced3053f0b8a28292
MD5 c2d325809c627d7146d0aa5668dd17cc
BLAKE2b-256 d32cd5716fab006e568ebf6c286108cef78f5fe596cf42890fa37dafaf943540

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 files

0.1.0

2 files

0.0.4

2 files

0.0.3

2 files

0.0.2

2 files

0.0.1

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page