====================================================================
PyEcore: A Pythonic Implementation of the Eclipse Modeling Framework
====================================================================
|pypi-version| |master-build| |coverage| |code-quality| |license|
.. |master-build| image:: https://travis-ci.org/pyecore/pyecore.svg?branch=master
:target: https://travis-ci.org/pyecore/pyecore
.. |develop-build| image:: https://travis-ci.org/pyecore/pyecore.svg?branch=develop
:target: https://travis-ci.org/pyecore/pyecore
.. |pypi-version| image:: https://badge.fury.io/py/pyecore.svg
:target: https://badge.fury.io/py/pyecore
.. |coverage| image:: https://coveralls.io/repos/github/pyecore/pyecore/badge.svg?branch=master
:target: https://coveralls.io/github/pyecore/pyecore?branch=master
.. |license| image:: https://img.shields.io/badge/license-New%20BSD-blue.svg
:target: https://raw.githubusercontent.com/pyecore/pyecore/master/LICENSE
.. |code-quality| image:: https://api.codacy.com/project/badge/Grade/ed038354821f43e7a4579c6a14185cdf
:target: https://www.codacy.com/app/aranega/pyecore
PyEcore is a Model Driven Engineering (MDE) framework written for Python.
Precisely, it is an implementation of `EMF/Ecore
<https://www.eclipse.org/modeling/emf/>`_ for Python, and it tries to give an
API which is compatible with the original EMF Java implementation.
PyEcore allows you to handle models and metamodels (structured data model), and
gives the key you need for building MDE-based tools and other applications based
on a structured data model. It supports out-of-the-box:
* Data inheritance,
* Two-ways relationship management (opposite references),
* XMI (de)serialization,
* JSON (de)serialization,
* Notification system,
* Reflexive API...
Let's see how we can create a very simple "dynamic" metamodel (as opposed to
static ones, see the `documentation <https://pyecore.readthedocs.io/en/latest/>`_
for more details):
.. code-block:: python
>>> from pyecore.ecore import EClass, EAttribute, EString, EObject
>>> Graph = EClass('Graph') # We create a 'Graph' concept
>>> Node = EClass('Node') # We create a 'Node' concept
>>>
>>> # We add a "name" attribute to the Graph concept
>>> Graph.eStructuralFeatures.append(EAttribute('name', EString,
default_value='new_name'))
>>> # And one on the 'Node' concept
>>> Node.eStructuralFeatures.append(EAttribute('name', EString))
>>>
>>> # We now introduce a containment relation between Graph and Node
>>> contains_nodes = EReference('nodes', Node, upper=-1, containment=True)
>>> Graph.eStructuralFeatures.append(contains_nodes)
>>> # We add an opposite relation between Graph and Node
>>> Node.eStructuralFeatures.append(EReference('owned_by', Graph, eOpposite=contains_nodes))
With this code, we have defined two concepts: ``Graph`` and ``Node``. Both have
a ``name``, and there exists a containment relationship between them. This relation
is bi-directional, which means that each time a ``Node`` object is added to the
``nodes`` relationship of a ``Graph``, the ``owned_by`` relation of the ``Node``
is also updated (it also works the other way around).
Let's create some instances of our freshly created metamodel:
.. code-block:: python
>>> # We create a Graph
>>> g1 = Graph(name='Graph 1')
>>> g1
<pyecore.ecore.Graph at 0x7f0055554dd8>
>>>
>>> # And two node instances
>>> n1 = Node(name='Node 1')
>>> n2 = Node(name='Node 2')
>>> n1, n2
(<pyecore.ecore.Node at 0x7f0055550588>,
<pyecore.ecore.Node at 0x7f00555502b0>)
>>>
>>> # We add them to the Graph
>>> g1.nodes.extend([n1, n2])
>>> g1.nodes
EOrderedSet([<pyecore.ecore.Node object at 0x7f0055550588>,
<pyecore.ecore.Node object at 0x7f00555502b0>])
>>>
>>> # bi-directional references are updated
>>> n1.owned_by
<pyecore.ecore.Graph at 0x7f0055554dd8>
This example gives a quick overview of some of the features you get for free
when using PyEcore.
*The project slowly grows and it still requires more love.*
Installation
============
PyEcore is available on ``pypi``, you can simply install it using ``pip``:
.. code-block:: bash
$ pip install pyecore
The installation can also be performed manually (better in a virtualenv):
.. code-block:: bash
$ python setup.py install
Documentation
=============
You can read the documentation at this address:
https://pyecore.readthedocs.io/en/latest/
Dependencies
============
The dependencies required by pyecore are:
* ordered-set which is used for the ``ordered`` and ``unique`` collections expressed in the metamodel,
* lxml which is used for the XMI parsing.
These dependencies are directly installed if you choose to use ``pip``.
Run the Tests
=============
The tests use `py.test` and 'coverage'. Everything is driven by `Tox`, so in order
to run the tests simply run:
.. code-block:: bash
$ tox
Liberty Regarding the Java EMF Implementation
=============================================
* There is some meta-property that could be missing inside PyEcore. If you see one missing, please open a new ticket!
* Proxies are not "removed" once resolved as in the the Java version, instead they act as transparent proxies and redirect all calls to the 'proxied' object.
* PyEcore is able to automatically load some model/metamodel dependencies on its own.
State
=====
In the current state, the project implements:
* the dynamic/static metamodel definitions,
* reflexive API,
* inheritance,
* enumerations,
* abstract metaclasses,
* runtime typechecking,
* attribute/reference creations,
* collections (attribute/references with upper bound set to ``-1``),
* reference eopposite,
* containment reference,
* introspection,
* select/reject on collections,
* Eclipse XMI import (partially, only single root models),
* Eclipse XMI export (partially, only single root models),
* simple notification/Event system,
* EOperations support,
* code generator for the static part,
* EMF proxies (first version),
* object deletion (first version),
* EMF commands (first version),
* EMF basic command stack,
* EMF very basic Editing Domain,
* JSON import (simple JSON format),
* JSON export (simple JSON format),
* introduce behavior @runtime,
* resources auto-load for some cross-references,
* derived collections,
* multiple roots resources,
* ``xsi:schemaLocation`` support for XMI resources,
* URI mapper like,
* ``EGeneric`` support (first simple version),
* URI converter like
The things that are in the roadmap:
* new implementation of ``EOrderedSet``, ``EList``, ``ESet`` and ``EBag``,
* new implementation of ``EStringToStringMapEntry`` and ``EFeatureMapEntry``,
* improve documentation,
* copy/paste (?).
Existing Projects
=================
There aren't too many projects proposing to handle models and metamodels in Python.
The only projects I found are:
* PyEMOF (http://www.lifl.fr/~marvie/software/pyemof.html)
* EMF4CPP (https://github.com/catedrasaes-umu/emf4cpp)
* PyEMOFUC (http://www.istr.unican.es/pyemofuc/index_En.html)
PyEMOF proposes an implementation of the OMG's EMOF in Python. The project
targets Python2, only supports Class/Primitive Types (no Enumeration), XMI
import/export and does not provide a reflexion layer. The project didn't move
since 2005.
EMF4CPP proposes a C++ implementation of EMF. This implementation also
introduces Python scripts to call the generated C++ code from a Python
environment. It seems that the EMF4CPP does not provide a reflexive layer
either.
PyEMOFUC proposes, like PyEMOF, a pure Python implementation of the OMG's EMOF.
If we stick to a kind of EMF terminology, PyEMOFUC only supports dynamic
metamodels and seems to provide a reflexive layer. The project does not appear
to have moved since a while.
Contributors
============
Thanks for making PyEcore better!
* Mike Pagel (`@moltob <https://github.com/moltob>`_), who is also the author
of `pyecoregen <https://github.com/pyecore/pyecoregen>`_ and `pymultigen <https://github.com/moltob/pymultigen>`_ (on which pyecoregen is based)
* Terry Kingston (`@TerryKingston <https://github.com/TerryKingston>`_)
* Afonso Pinto (`@afonsobspinto <https://github.com/afonsobspinto>`_)
* Andy (`@CFAndy <https://github.com/CFAndy>`_)
* annighoefer (`@annighoefer <https://github.com/annighoefer>`_)
* Rodriguez Facundo (`@rodriguez-facundo <https://github.com/rodriguez-facundo>`_)
* Filippo Ledda (`@filippometacell <https://github.com/filippometacell>`_)
* Ewoud Werkman (`@ewoudwerkman <https://github.com/ewoudwerkman>`_)
* Eugene (`@4ekin <https://github.com/4ekin>`_)
* Alexandre Acebedo (`@aacebedo <https://github.com/aacebedo>`_)
* Jinhu (`@jinhu <https://github.com/jinhu>`_)
* Pablo Campillo (`@pablo-campillo <https://github.com/pablo-campillo>`_)
* Jose Antonio Moral (`@jamoralp <https://github.com/jamoralp>`_)
* Marco Heinemann (`@ubmarco <https://github.com/ubmarco>`_)
* Christian Drabek (`@cdrabek <https://github.com/cdrabek>`_)
* Dan Yeaw (`@danyeaw <https://github.com/danyeaw>`_)
* Arkadiusz Michał Ryś (`@arrys <https://github.com/arrys>`_)
Additional Resources
====================
* `This article <http://modeling-languages.com/pyecore-python-eclipse-modeling-framework>`_
on the blog of Professor Jordi Cabot gives more information and
implementation details about PyEcore.
Raw data
{
"_id": null,
"home_page": "https://github.com/pyecore/pyecore",
"name": "pyecore",
"maintainer": "",
"docs_url": null,
"requires_python": "",
"maintainer_email": "",
"keywords": "model metamodel EMF Ecore MDE",
"author": "Vincent Aranega",
"author_email": "vincent.aranega@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/b6/25/65fdf1704846cc66adc6f2b00384bcffe1728fc338f7c5c0a9431cd2e600/pyecore-0.15.1.tar.gz",
"platform": null,
"description": "====================================================================\nPyEcore: A Pythonic Implementation of the Eclipse Modeling Framework\n====================================================================\n\n|pypi-version| |master-build| |coverage| |code-quality| |license|\n\n.. |master-build| image:: https://travis-ci.org/pyecore/pyecore.svg?branch=master\n :target: https://travis-ci.org/pyecore/pyecore\n\n.. |develop-build| image:: https://travis-ci.org/pyecore/pyecore.svg?branch=develop\n :target: https://travis-ci.org/pyecore/pyecore\n\n.. |pypi-version| image:: https://badge.fury.io/py/pyecore.svg\n :target: https://badge.fury.io/py/pyecore\n\n.. |coverage| image:: https://coveralls.io/repos/github/pyecore/pyecore/badge.svg?branch=master\n :target: https://coveralls.io/github/pyecore/pyecore?branch=master\n\n.. |license| image:: https://img.shields.io/badge/license-New%20BSD-blue.svg\n :target: https://raw.githubusercontent.com/pyecore/pyecore/master/LICENSE\n\n.. |code-quality| image:: https://api.codacy.com/project/badge/Grade/ed038354821f43e7a4579c6a14185cdf\n :target: https://www.codacy.com/app/aranega/pyecore\n\nPyEcore is a Model Driven Engineering (MDE) framework written for Python.\nPrecisely, it is an implementation of `EMF/Ecore\n<https://www.eclipse.org/modeling/emf/>`_ for Python, and it tries to give an\nAPI which is compatible with the original EMF Java implementation.\n\nPyEcore allows you to handle models and metamodels (structured data model), and\ngives the key you need for building MDE-based tools and other applications based\non a structured data model. It supports out-of-the-box:\n\n* Data inheritance,\n* Two-ways relationship management (opposite references),\n* XMI (de)serialization,\n* JSON (de)serialization,\n* Notification system,\n* Reflexive API...\n\nLet's see how we can create a very simple \"dynamic\" metamodel (as opposed to\nstatic ones, see the `documentation <https://pyecore.readthedocs.io/en/latest/>`_\nfor more details):\n\n.. code-block:: python\n\n >>> from pyecore.ecore import EClass, EAttribute, EString, EObject\n >>> Graph = EClass('Graph') # We create a 'Graph' concept\n >>> Node = EClass('Node') # We create a 'Node' concept\n >>>\n >>> # We add a \"name\" attribute to the Graph concept\n >>> Graph.eStructuralFeatures.append(EAttribute('name', EString,\n default_value='new_name'))\n >>> # And one on the 'Node' concept\n >>> Node.eStructuralFeatures.append(EAttribute('name', EString))\n >>>\n >>> # We now introduce a containment relation between Graph and Node\n >>> contains_nodes = EReference('nodes', Node, upper=-1, containment=True)\n >>> Graph.eStructuralFeatures.append(contains_nodes)\n >>> # We add an opposite relation between Graph and Node\n >>> Node.eStructuralFeatures.append(EReference('owned_by', Graph, eOpposite=contains_nodes))\n\nWith this code, we have defined two concepts: ``Graph`` and ``Node``. Both have\na ``name``, and there exists a containment relationship between them. This relation\nis bi-directional, which means that each time a ``Node`` object is added to the\n``nodes`` relationship of a ``Graph``, the ``owned_by`` relation of the ``Node``\nis also updated (it also works the other way around).\n\nLet's create some instances of our freshly created metamodel:\n\n.. code-block:: python\n\n >>> # We create a Graph\n >>> g1 = Graph(name='Graph 1')\n >>> g1\n <pyecore.ecore.Graph at 0x7f0055554dd8>\n >>>\n >>> # And two node instances\n >>> n1 = Node(name='Node 1')\n >>> n2 = Node(name='Node 2')\n >>> n1, n2\n (<pyecore.ecore.Node at 0x7f0055550588>,\n <pyecore.ecore.Node at 0x7f00555502b0>)\n >>>\n >>> # We add them to the Graph\n >>> g1.nodes.extend([n1, n2])\n >>> g1.nodes\n EOrderedSet([<pyecore.ecore.Node object at 0x7f0055550588>,\n <pyecore.ecore.Node object at 0x7f00555502b0>])\n >>>\n >>> # bi-directional references are updated\n >>> n1.owned_by\n <pyecore.ecore.Graph at 0x7f0055554dd8>\n\n\nThis example gives a quick overview of some of the features you get for free\nwhen using PyEcore.\n\n*The project slowly grows and it still requires more love.*\n\nInstallation\n============\n\nPyEcore is available on ``pypi``, you can simply install it using ``pip``:\n\n.. code-block:: bash\n\n $ pip install pyecore\n\nThe installation can also be performed manually (better in a virtualenv):\n\n.. code-block:: bash\n\n $ python setup.py install\n\n\nDocumentation\n=============\n\nYou can read the documentation at this address:\n\nhttps://pyecore.readthedocs.io/en/latest/\n\n\nDependencies\n============\n\nThe dependencies required by pyecore are:\n\n* ordered-set which is used for the ``ordered`` and ``unique`` collections expressed in the metamodel,\n* lxml which is used for the XMI parsing.\n\nThese dependencies are directly installed if you choose to use ``pip``.\n\n\nRun the Tests\n=============\n\nThe tests use `py.test` and 'coverage'. Everything is driven by `Tox`, so in order\nto run the tests simply run:\n\n.. code-block:: bash\n\n $ tox\n\n\nLiberty Regarding the Java EMF Implementation\n=============================================\n\n* There is some meta-property that could be missing inside PyEcore. If you see one missing, please open a new ticket!\n* Proxies are not \"removed\" once resolved as in the the Java version, instead they act as transparent proxies and redirect all calls to the 'proxied' object.\n* PyEcore is able to automatically load some model/metamodel dependencies on its own.\n\nState\n=====\n\nIn the current state, the project implements:\n\n* the dynamic/static metamodel definitions,\n* reflexive API,\n* inheritance,\n* enumerations,\n* abstract metaclasses,\n* runtime typechecking,\n* attribute/reference creations,\n* collections (attribute/references with upper bound set to ``-1``),\n* reference eopposite,\n* containment reference,\n* introspection,\n* select/reject on collections,\n* Eclipse XMI import (partially, only single root models),\n* Eclipse XMI export (partially, only single root models),\n* simple notification/Event system,\n* EOperations support,\n* code generator for the static part,\n* EMF proxies (first version),\n* object deletion (first version),\n* EMF commands (first version),\n* EMF basic command stack,\n* EMF very basic Editing Domain,\n* JSON import (simple JSON format),\n* JSON export (simple JSON format),\n* introduce behavior @runtime,\n* resources auto-load for some cross-references,\n* derived collections,\n* multiple roots resources,\n* ``xsi:schemaLocation`` support for XMI resources,\n* URI mapper like,\n* ``EGeneric`` support (first simple version),\n* URI converter like\n\nThe things that are in the roadmap:\n\n* new implementation of ``EOrderedSet``, ``EList``, ``ESet`` and ``EBag``,\n* new implementation of ``EStringToStringMapEntry`` and ``EFeatureMapEntry``,\n* improve documentation,\n* copy/paste (?).\n\nExisting Projects\n=================\n\nThere aren't too many projects proposing to handle models and metamodels in Python.\nThe only projects I found are:\n\n* PyEMOF (http://www.lifl.fr/~marvie/software/pyemof.html)\n* EMF4CPP (https://github.com/catedrasaes-umu/emf4cpp)\n* PyEMOFUC (http://www.istr.unican.es/pyemofuc/index_En.html)\n\nPyEMOF proposes an implementation of the OMG's EMOF in Python. The project\ntargets Python2, only supports Class/Primitive Types (no Enumeration), XMI\nimport/export and does not provide a reflexion layer. The project didn't move\nsince 2005.\n\nEMF4CPP proposes a C++ implementation of EMF. This implementation also\nintroduces Python scripts to call the generated C++ code from a Python\nenvironment. It seems that the EMF4CPP does not provide a reflexive layer\neither.\n\nPyEMOFUC proposes, like PyEMOF, a pure Python implementation of the OMG's EMOF.\nIf we stick to a kind of EMF terminology, PyEMOFUC only supports dynamic\nmetamodels and seems to provide a reflexive layer. The project does not appear\nto have moved since a while.\n\nContributors\n============\n\nThanks for making PyEcore better!\n\n* Mike Pagel (`@moltob <https://github.com/moltob>`_), who is also the author\n of `pyecoregen <https://github.com/pyecore/pyecoregen>`_ and `pymultigen <https://github.com/moltob/pymultigen>`_ (on which pyecoregen is based)\n* Terry Kingston (`@TerryKingston <https://github.com/TerryKingston>`_)\n* Afonso Pinto (`@afonsobspinto <https://github.com/afonsobspinto>`_)\n* Andy (`@CFAndy <https://github.com/CFAndy>`_)\n* annighoefer (`@annighoefer <https://github.com/annighoefer>`_)\n* Rodriguez Facundo (`@rodriguez-facundo <https://github.com/rodriguez-facundo>`_)\n* Filippo Ledda (`@filippometacell <https://github.com/filippometacell>`_)\n* Ewoud Werkman (`@ewoudwerkman <https://github.com/ewoudwerkman>`_)\n* Eugene (`@4ekin <https://github.com/4ekin>`_)\n* Alexandre Acebedo (`@aacebedo <https://github.com/aacebedo>`_)\n* Jinhu (`@jinhu <https://github.com/jinhu>`_)\n* Pablo Campillo (`@pablo-campillo <https://github.com/pablo-campillo>`_)\n* Jose Antonio Moral (`@jamoralp <https://github.com/jamoralp>`_)\n* Marco Heinemann (`@ubmarco <https://github.com/ubmarco>`_)\n* Christian Drabek (`@cdrabek <https://github.com/cdrabek>`_)\n* Dan Yeaw (`@danyeaw <https://github.com/danyeaw>`_)\n* Arkadiusz Micha\u0142 Ry\u015b (`@arrys <https://github.com/arrys>`_)\n\n\n\nAdditional Resources\n====================\n\n* `This article <http://modeling-languages.com/pyecore-python-eclipse-modeling-framework>`_\n on the blog of Professor Jordi Cabot gives more information and\n implementation details about PyEcore.\n",
"bugtrack_url": null,
"license": "BSD 3-Clause",
"summary": "A Python(ic) Implementation of the Eclipse Modeling Framework (EMF/Ecore)",
"version": "0.15.1",
"project_urls": {
"Homepage": "https://github.com/pyecore/pyecore"
},
"split_keywords": [
"model",
"metamodel",
"emf",
"ecore",
"mde"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "8e951b2b6868c048c5c5a0ed40042cdab076401c3c9ce8e483595448d806b5a6",
"md5": "9e37cb9bdbcd74315307abdda7103d20",
"sha256": "1ac80e6b9a2a97640545797261d7c6229ef106265916a3bd2fbbabad79df1016"
},
"downloads": -1,
"filename": "pyecore-0.15.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "9e37cb9bdbcd74315307abdda7103d20",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 43689,
"upload_time": "2024-03-11T17:11:05",
"upload_time_iso_8601": "2024-03-11T17:11:05.593127Z",
"url": "https://files.pythonhosted.org/packages/8e/95/1b2b6868c048c5c5a0ed40042cdab076401c3c9ce8e483595448d806b5a6/pyecore-0.15.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "b62565fdf1704846cc66adc6f2b00384bcffe1728fc338f7c5c0a9431cd2e600",
"md5": "03b2315891e88ea12f846f68aa822380",
"sha256": "768b9fa9c6357a81ae3ebb72ecbc56218e1ae934e818322e04ba8333f65a671b"
},
"downloads": -1,
"filename": "pyecore-0.15.1.tar.gz",
"has_sig": false,
"md5_digest": "03b2315891e88ea12f846f68aa822380",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 58626,
"upload_time": "2024-03-11T17:11:08",
"upload_time_iso_8601": "2024-03-11T17:11:08.284517Z",
"url": "https://files.pythonhosted.org/packages/b6/25/65fdf1704846cc66adc6f2b00384bcffe1728fc338f7c5c0a9431cd2e600/pyecore-0.15.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-03-11 17:11:08",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "pyecore",
"github_project": "pyecore",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [
{
"name": "ordered-set",
"specs": []
},
{
"name": "lxml",
"specs": []
},
{
"name": "defusedxml",
"specs": []
},
{
"name": "restrictedpython",
"specs": [
[
">=",
"6.1"
],
[
">=",
"5.3"
]
]
},
{
"name": "future_fstrings",
"specs": []
}
],
"tox": true,
"lcname": "pyecore"
}