Repository: matthiaskoenig/libsbgn-python (language: python)

Issue:
notes and extension values are not decoded
Values of notes and extension are stored as bytes in Notes and Extension objects.
It causes issues when those values are exported to an SBGN-ML file (written as strings of bytes).
They should probably be decoded and stored as strings?



Discussion / hints:

Fix patch:
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..711388e
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,20 @@
+# Editor Configuration (http://editorconfig.org)
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 4
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+max_line_length = 88
+
+[*.{json,yml}]
+indent_size = 2
+
+[*.{md,rst}]
+trim_trailing_whitespace = false
+
+[Makefile]
+indent_style = tab
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
new file mode 100644
index 0000000..a662947
--- /dev/null
+++ b/.github/workflows/main.yml
@@ -0,0 +1,89 @@
+name: CI-CD
+
+on:
+  push:
+    branches:
+    - master
+    - develop
+    tags:
+      - '[0-9]+.[0-9]+.[0-9]+'
+      - '[0-9]+.[0-9]+.[0-9]+a[0-9]+'
+  pull_request:
+    branches:
+    - master
+    - develop
+
+jobs:
+  test:
+    runs-on: ${{ matrix.os }}
+    strategy:
+      fail-fast: false
+      matrix:
+        os: [ubuntu-latest]  # [ubuntu-latest, macos-latest, windows-latest]
+        python-version: [3.6, 3.7, 3.8, 3.9]
+
+    steps:
+    - uses: actions/checkout@v2
+    - name: Set up Python ${{ matrix.python-version }}
+      uses: actions/setup-python@v2
+      with:
+        python-version: ${{ matrix.python-version }}
+    - name: Install dependencies
+      run: |
+        python -m pip install --upgrade pip setuptools wheel
+        python -m pip install tox tox-gh-actions
+    - name: Test with tox
+      run:
+        tox -- --cov-report=xml
+    - name: Report coverage
+      shell: bash
+      run: bash <(curl -s https://codecov.io/bash)
+
+  release:
+    needs: test
+    if: startsWith(github.ref, 'refs/tags')
+    runs-on: ${{ matrix.os }}
+    strategy:
+      matrix:
+        os: [ubuntu-latest]
+        python-version: [3.8]
+
+    steps:
+    - uses: actions/checkout@v2
+    - name: Set up Python ${{ matrix.python-version }}
+      uses: actions/setup-python@v2
+      with:
+        python-version: ${{ matrix.python-version }}
+    - name: Get tag
+      id: tag
+      run: echo "::set-output name=version::${GITHUB_REF#refs/tags/}"
+    - name: Install dependencies
+      run: |
+        python -m pip install --upgrade pip setuptools wheel
+        python -m pip install twine
+    - name: Build package
+      run: python setup.py sdist bdist_wheel
+    - name: Check the package
+      run: twine check dist/*
+    - name: Publish to PyPI
+      env:
+        TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
+        TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
+      run:
+        twine upload --skip-existing --non-interactive dist/*
+    - name: Create GitHub release
+      uses: actions/create-release@v1
+      env:
+        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+      with:
+        tag_name: ${{ github.ref }}
+        release_name: ${{ github.ref }}
+        body_path: "release-notes/${{ steps.tag.outputs.version }}.md"
+        draft: false
+        prerelease: false
+    - name: Pull request to master
+      uses: vsoch/pull-request-action@1.0.6
+      env:
+        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+        PULL_REQUEST_FROM_BRANCH: "develop"
+        PULL_REQUEST_BRANCH: "master"
diff --git a/.gitignore b/.gitignore
index 35943f4..8878a6c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,6 +14,8 @@ libsbgnpy.egg-info/
 htmlcov/
 libsbgnpy/examples/sbgn/test-output.sbgn
 libsbgnpy/examples/sbgn/test-output-annotation.sbgn
+coverage.xml
+build/
 
 .cache
 .tox
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 588f34f..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,25 +0,0 @@
-language: python
-cache: pip
-
-python:
-  - "3.5"
-  - "3.6"
-  - "3.7"
-  - "3.8"
-sudo: required
-
-branches:
-  only:
-  - master
-  - develop
-
-# command to install dependencies
-install:
-  - pip install -r requirements.txt
-  - pip install coveralls
-
-# command to run tests
-script:
-  pytest --cov=libsbgnpy
-after_success:
-  coveralls
\ No newline at end of file
diff --git a/DESCRIPTION.rst b/DESCRIPTION.rst
deleted file mode 100644
index 477e86a..0000000
--- a/DESCRIPTION.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-libsbgn python bindings
-=======================
-
-Python bindings for the reading, writing, manipulation and validation
-of files in the Systems Biology Graphical Notation (SBGN) format.
-Information available on the www.sbgn.org.
-
diff --git a/MANIFEST.in b/MANIFEST.in
index 81bbede..96c9066 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,2 +1,3 @@
-include DESCRIPTION.rst README.rst
-recursive-include libsbgnpy *.py *.rst *.xsd *.sbgn *.png
+include README.rst
+include LICENSE
+recursive-include src/libsbgnpy *.py *.rst *.xsd *.sbgn *.png
diff --git a/README.md b/README.md
deleted file mode 100644
index 851e597..0000000
--- a/README.md
+++ /dev/null
@@ -1,112 +0,0 @@
-![libsbgn-python logo](docs_builder/images/libsbgn-python-logo-small.png)  
-[![PyPI version](https://badge.fury.io/py/libsbgnpy.svg)](https://badge.fury.io/py/libsbgnpy)
-[![Documentation Status](https://readthedocs.org/projects/libsbgn-python/badge/?version=latest)](http://libsbgn-python.readthedocs.io/en/latest/?badge=latest)
-[![Build Status](https://travis-ci.org/matthiaskoenig/libsbgn-python.svg?branch=develop)](https://travis-ci.org/matthiaskoenig/libsbgn-python)
-[![License (LGPL version 3)](https://img.shields.io/badge/license-LGPLv3.0-blue.svg?style=flat-square)](http://opensource.org/licenses/LGPL-3.0)
-[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.597155.svg)](https://doi.org/10.5281/zenodo.597155)
-[![Coverage Status](https://coveralls.io/repos/github/matthiaskoenig/libsbgn-python/badge.svg?branch=develop)](https://coveralls.io/github/matthiaskoenig/libsbgn-python?branch=develop)
-# libsbgnpy : Python library for SBGN
-
-
-Python library to work with [SBGN](http://sbgn.github.io/sbgn/). This library is based on the SBGN XML schema and supports reading, 
-writing and validation of SBGN files. Python >=3.5 is supported. 
-The initial library was generated using [generateDS](https://bitbucket.org/dkuhlman/generateds). Additional utility functions for 
-reading, writing and rendering SBGN documents are provided.
-
-Documentation with examples is available at [http://libsbgn-python.readthedocs.io/en/latest/](http://libsbgn-python.readthedocs.io/en/latest/).
-
-* `libsbgn.py` python library
-* `libsbgnTypes.py` SBGN type definitions (GlyphClasses, ArcClasses, Languages)
-* `utils.py` SBGN utility function like writing & reading of files
-* `render.py` SBGN rendering
-* `tests` unittests
-* `examples/` python examples
-* `validation/` validation of SBGN files
-
-To cite libsbgnpy use 
-[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.597155.svg)](https://doi.org/10.5281/zenodo.597155)
-
-## Installation
-The package is available from [pypi](https://pypi.python.org/pypi/libsbgnpy)
-```
-pip install libsbgnpy
-```
-The latest develop version can be installed via
-```
-pip install git+https://github.com/matthiaskoenig/libsbgn-python.git@develop
-```
-
-## Support
-To report bugs, request features or asking questions please file an [issue](https://github.com/matthiaskoenig/libsbgn-python/issues).
-
-## Contributing
-Contributions are very welcome. The easiest way to fix a typo/bug or implement a feature is by 
-following the [contribution guidelines](./CONTRIBUTING.rst).
-
-## Software using libsbgnpy
-
-* [Mimoza](http://mimoza.bordeaux.inria.fr/) takes a model in
-SBML format and visualizes it in several formats (downloadable as a
-COMBINE archive)
-
-## License
-* Source Code: [LGPLv3](http://opensource.org/licenses/LGPL-3.0)
-* Documentation: [CC BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/)
-
-## Python Language Bindings
-The python language bindings were created from the XML schema using
-generateDS and than adapted to include GlyphClasses and ArcClasses.
-```
-/usr/local/bin/generateDS.py -o "libsbgn.py" -s "libsbgnSubs.py" SBGN.xsd
-```
-The necessary constraints for GlyphClasses, ArcClasses and Languages were added and
-some utility functions created.
-
-## ChangeLog
-**v0.2.0**
-- dropping support of python 2.7, 3.4
-- adding support for python 3.7, 3.8
-- fixing render endpoints (#31, #32)
-- fixing documentation builder
-- removing py2 legacy code
-
-**v0.1.7**
-Support for notes and extensions
-
-* Extension and Notes reading and writing
-* Extension and Notes examples
-
-**v0.1.6**
-Improved testing and documentation
-
-* New documentation: http://libsbgn-python.readthedocs.io/en/latest/index.html
-* Some python 3 bugfixes
-* Additional examples 
-* Additional tests, coverage & switch to py-test
-* pep8 fixes
-* tox support and tox testing
-* logo
-
-**v0.1.5**
-
-* py3 support bugfixes
-* SBGN validation with XSD schema
-* update of bindings from latest schema
-* bug fix in writing some attributes
-
-**v0.1.4**
-
-* support for py2.6, 2.7, 3.4, 3.5
-* continuous integration with travis
-
-**v0.1.3**
-
-* unittests added
-* x, y, w, d handled as float instead int according to specification
-
-
-**v0.1.2**
-
-* initial release
-
-&copy; 2016-2020 Matthias König
\ No newline at end of file
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..a68c72f
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,108 @@
+libsbgnpy : Python library for SBGN
+====================================
+
+.. image:: https://github.com/matthiaskoenig/libsbgn-python/workflows/CI-CD/badge.svg
+   :target: https://github.com/matthiaskoenig/libsbgn-python/actions?query=CI-CD
+   :alt: GitHub Actions CI/CD Status
+
+.. image:: https://img.shields.io/pypi/v/libsbgnpy.svg
+   :target: https://pypi.org/project/libsbgnpy/
+   :alt: Current PyPI Version
+
+.. image:: https://img.shields.io/pypi/pyversions/libsbgnpy.svg
+   :target: https://pypi.org/project/libsbgnpy/
+   :alt: Supported Python Versions
+
+.. image:: https://img.shields.io/pypi/l/libsbgnpy.svg
+   :target: http://opensource.org/licenses/LGPL-3.0
+   :alt: GNU Lesser General Public License 3
+
+.. image:: https://codecov.io/gh/matthiaskoenig/libsbgn-python/branch/develop/graph/badge.svg
+   :target: https://codecov.io/gh/matthiaskoenig/libsbgn-python
+   :alt: Codecov
+
+.. image:: https://readthedocs.org/projects/libsbgn-python/badge/?version=latest
+   :target: https://libsbgn-python.readthedocs.io/en/latest/?badge=latest
+   :alt: Documentation Status
+
+.. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.597155.svg
+   :target: https://doi.org/10.5281/zenodo.597155
+   :alt: Zenodo DOI
+
+.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
+   :target: https://github.com/ambv/black
+   :alt: Black
+
+
+Python library to work with the Systems Biology Graphical Notation (`SBGN <http://sbgn.github.io/sbgn/>`__). This library is based on the SBGN XML schema and supports reading, 
+writing and validation of SBGN files.
+
+The initial library was generated using `generateDS <https://pypi.org/project/generateDS/>`__. Additional utility functions for reading, writing, and rendering SBGN documents are provided.
+
+Documentation with examples is available at `https://libsbgn-python.readthedocs.io <https://libsbgn-python.readthedocs.io>`__.
+
+* ``libsbgn.py`` python library
+* ``libsbgnTypes.py`` SBGN type definitions (GlyphClasses, ArcClasses, Languages)
+* ``utils.py`` SBGN utility function like writing & reading of files
+* ``render.py`` SBGN rendering
+* ``test/`` unittests
+* ``examples/`` python examples
+* ``validation/`` validation of SBGN files
+
+
+How to cite
+===========
+.. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.597155.svg
+   :target: https://doi.org/10.5281/zenodo.597155
+   :alt: Zenodo DOI
+
+Installation
+============
+``libsbgnpy`` is available from `pypi <https://pypi.python.org/pypi/libsbgnpy>`__ and
+can be installed via::
+
+    pip install libsbgnpy
+
+Support
+=======
+To report bugs, request features or asking questions please file an `issue <https://github.com/matthiaskoenig/libsbgn-python/issues/new>`__.
+
+License
+=======
+
+* Source Code: `LGPLv3 <http://opensource.org/licenses/LGPL-3.0>`__
+* Documentation: `CC BY-SA 4.0 <http://creativecommons.org/licenses/by-sa/4.0/>`__
+
+The libsbgnpy source is released under both the GPL and LGPL licenses version 2 or
+later. You may choose which license to use the software under.
+
+This program is free software: you can redistribute it and/or modify it under
+the terms of the GNU General Public License or the GNU Lesser General Public
+License as published by the Free Software Foundation, either version 2 of the
+License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+Funding
+=======
+Matthias König is supported by the Federal Ministry of Education and Research (BMBF, Germany)
+within the research network Systems Medicine of the Liver (**LiSyM**, grant number 031L0054).
+
+
+Software using libsbgnpy
+========================
+* `Mimoza <http://mimoza.bordeaux.inria.fr/>`__ takes a model in SBML format and visualizes it in several formats (downloadable as a COMBINE archive).
+
+Python Language Bindings
+========================
+The python language bindings were created from the XML schema using
+generateDS and than adapted to include GlyphClasses and ArcClasses.::
+
+    /usr/local/bin/generateDS.py -o "libsbgn.py" -s "libsbgnSubs.py" SBGN.xsd
+
+The necessary constraints for GlyphClasses, ArcClasses and Languages were added and
+some utility functions created.
+
+© 2016-2020 Matthias König
diff --git a/RELEASE.md b/RELEASE.md
index 92c4b66..d58f0c7 100644
--- a/RELEASE.md
+++ b/RELEASE.md
@@ -1,14 +1,21 @@
-# Release info
-Steps for release are
-* update version number in develop branch
-* update documentation & add changes to changelog
-* merge all develop changes to master via pull request
-* create release from master branch in github
-* release on [pypi](https://pypi.python.org/pypi/libsbgnpy)
+# Release information
+
+## update documentation
+* make necessary updates to notebooks
+* build documentation `cd docs_builder` and `make html`
+
+## make release
+* sort imports (`isort src/libsbgnpy`)
+* code formating (`black src/libsbgnpy`)
+* make sure all tests run (`tox --`)
+* update release notes in `release-notes`
+* commit changes
+* bump version (`bumpversion patch` or `bumpversion` minor)
+* `git push --tags` (triggers release)
+
+* test installation in virtualenv from pypi
 ```
-git branch master
-git pull
-python setup.py sdist
-twine upload dist/*
+mkvirtualenv test --python=python3.8
+(test) pip install libsbgnpy
 ```
-* switch to develop branch and increase version number
\ No newline at end of file
+* merge pull request to master
diff --git a/docs_builder/README.md b/docs_builder/README.md
index 35782dc..ff23d24 100644
--- a/docs_builder/README.md
+++ b/docs_builder/README.md
@@ -15,5 +15,5 @@ make html
 ## Update jupyter notebooks
 ```
 pip install jupyterlab
-ipython kernel install --user --name libsbgn-python
-```
\ No newline at end of file
+ipython kernel install --user --name libsbgnpy
+```
diff --git a/docs_builder/examples.ipynb b/docs_builder/examples.ipynb
index cac8244..469b94c 100644
--- a/docs_builder/examples.ipynb
+++ b/docs_builder/examples.ipynb
@@ -5,7 +5,7 @@
    "metadata": {},
    "source": [
     "# Examples\n",
-    "In this section example use cases of `libsbgn-python` are provided.\n",
+    "In this section example use cases of `libsbgnpy` are provided.\n",
     "\n",
     "## Create SBGN\n",
     "The example demonstrates how to create a `SBGN` document from scratch. This includes creation of the following objects.\n",
@@ -20,7 +20,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 1,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -54,7 +54,7 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "SBGN rendered: /tmp/tmph1_c261o.png\n"
+      "SBGN rendered: /tmp/tmpwf2646f7.png\n"
      ]
     },
     {
@@ -328,8 +328,13 @@
     {
      "data": {
       "text/html": [
-       "<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
-       ".highlight  { background: #f8f8f8; }\n",
+       "<style type=\"text/css\">pre { line-height: 125%; margin: 0; }\n",
+       "td.linenos pre { color: #000000; background-color: #f0f0f0; padding-left: 5px; padding-right: 5px; }\n",
+       "span.linenos { color: #000000; background-color: #f0f0f0; padding-left: 5px; padding-right: 5px; }\n",
+       "td.linenos pre.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n",
+       "span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n",
+       ".highlight .hll { background-color: #ffffcc }\n",
+       ".highlight { background: #f8f8f8; }\n",
        ".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
        ".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
        ".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
@@ -516,8 +521,13 @@
     {
      "data": {
       "text/html": [
-       "<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
-       ".highlight  { background: #f8f8f8; }\n",
+       "<style type=\"text/css\">pre { line-height: 125%; margin: 0; }\n",
+       "td.linenos pre { color: #000000; background-color: #f0f0f0; padding-left: 5px; padding-right: 5px; }\n",
+       "span.linenos { color: #000000; background-color: #f0f0f0; padding-left: 5px; padding-right: 5px; }\n",
+       "td.linenos pre.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n",
+       "span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n",
+       ".highlight .hll { background-color: #ffffcc }\n",
+       ".highlight { background: #f8f8f8; }\n",
        ".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
        ".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
        ".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
@@ -805,8 +815,13 @@
     {
      "data": {
       "text/html": [
-       "<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
-       ".highlight  { background: #f8f8f8; }\n",
+       "<style type=\"text/css\">pre { line-height: 125%; margin: 0; }\n",
+       "td.linenos pre { color: #000000; background-color: #f0f0f0; padding-left: 5px; padding-right: 5px; }\n",
+       "span.linenos { color: #000000; background-color: #f0f0f0; padding-left: 5px; padding-right: 5px; }\n",
+       "td.linenos pre.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n",
+       "span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n",
+       ".highlight .hll { background-color: #ffffcc }\n",
+       ".highlight { background: #f8f8f8; }\n",
        ".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
        ".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
        ".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
@@ -973,7 +988,7 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "<libsbgnpy.libsbgn.sbgn object at 0x7f622f69d850>\n"
+      "<libsbgnpy.libsbgn.sbgn object at 0x7fb5c0d388b0>\n"
      ]
     }
    ],
@@ -1005,7 +1020,7 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "SBGN rendered: /tmp/tmp1a2iqk76.png\n"
+      "SBGN rendered: /tmp/tmpwsj4rf6v.png\n"
      ]
     },
     {
@@ -1044,9 +1059,9 @@
  ],
  "metadata": {
   "kernelspec": {
-   "display_name": "libsbgn-python",
+   "display_name": "libsbgnpy",
    "language": "python",
-   "name": "libsbgn-python"
+   "name": "libsbgnpy"
   },
   "language_info": {
    "codemirror_mode": {
@@ -1058,7 +1073,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.7.6"
+   "version": "3.8.5"
   }
  },
  "nbformat": 4,
diff --git a/docs_builder/introduction.rst b/docs_builder/introduction.rst
index 413288b..bfd8cba 100644
--- a/docs_builder/introduction.rst
+++ b/docs_builder/introduction.rst
@@ -5,20 +5,21 @@ Introduction
 Overview
 ------------
 Python library to work with `SBGN <http://sbgn.github.io/sbgn/>`_. This library is based on the SBGN XML schema and supports reading,
-writing and validation of SBGN files. Python 2 and python 3 are supported.
-The initial library was generated using `generateDS <https://bitbucket.org/dkuhlman/generateds>`_. Additional utility functions for
+writing and validation of SBGN files. Python 3 is supported.
+The initial library was generated using `generateDS <https://pypi.org/project/generateDS/>`_. Additional utility functions for
 reading, writing and rendering SBGN documents are provided.
 
 To cite libsbgnpy use the following BibTex or equivalent::
 
-    @MISC{libsbgnpy,
-      author        = {Matthias König},
-      title         = {libsbgnpy: Python library for SBGN},
-      month         = {Mar.},
-      year          = {2017},
-      doi           = "{10.5281/zenodo.192356}",
-      url           = "{http://dx.doi.org/10.5281/zenodo.438137}",
-      howpublished  = {https://github.com/matthiaskoenig/libsbgn-python/blob/master/README.md}
+    @software{libsbgnpy,
+        author = {Matthias König},
+        title = {{matthiaskoenig/libsbgn-python: libsbgn-python-v0.2.0}},
+        month = mar,
+        year = 2020,
+        publisher = {Zenodo},
+        version = {v0.2.0},
+        doi = {10.5281/zenodo.3712285},
+        url = {https://doi.org/10.5281/zenodo.3712285}
     }
 
 Source code is available from
@@ -36,6 +37,3 @@ The libsbgn-python package is available from `pypi
 
     pip install libsbgnpy
 
-The latest develop version can be installed via::
-
-    pip install git+https://github.com/matthiaskoenig/libsbgn-python.git@develop
diff --git a/libsbgnpy/_version.py b/libsbgnpy/_version.py
deleted file mode 100644
index d3ec452..0000000
--- a/libsbgnpy/_version.py
+++ /dev/null
@@ -1,1 +0,0 @@
-__version__ = "0.2.0"
diff --git a/libsbgnpy/examples/sbgn/notes.sbgn b/libsbgnpy/examples/sbgn/notes.sbgn
deleted file mode 100644
index 40a79cd..0000000
--- a/libsbgnpy/examples/sbgn/notes.sbgn
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<sbgn xmlns="http://sbgn.org/libsbgn/0.2">
-    <map language="process description">
-        <extension>
-        <renderInformation id="example" programName="SBML Layout" programVersion="3.0"
-     xmlns="http://projects.eml.org/bcb/sbml/render/level2">
-        <listOfColorDefinitions>
-        <colorDefinition id="yelloComp" value="#ffffccff" />
-        <colorDefinition id="grayComp" value="#e0e0e0ff" />
-        <colorDefinition id="orange" value="#fa9e2fff" />
-        <colorDefinition id="blue" value="#2958acff" />
-        <colorDefinition id="green" value="#378f5cff" />
-        <colorDefinition id="Color_0" value="#969696" />
-        <colorDefinition id="Color_1" value="#ff9900" />
-        <colorDefinition id="Color_2" value="#000000" />
-        </listOfColorDefinitions>
-        <listOfGradientDefinitions>
-        <linearGradient x1="0%" y1="0%" z1="0%" x2="100%" y2="0%" z2="100%" id="LinearGradient_0" spreadMethod="reflect">
-            <stop offset="0%" stop-color="#ccffff" />
-            <stop offset="100%" stop-color="#ffffff" />
-        </linearGradient>
-        <linearGradient x1="0%" y1="0%" z1="0%" x2="100%" y2="0%" z2="100%" id="OrangeGradient_0" spreadMethod="reflect">
-            <stop offset="0%" stop-color="#ffffff" />
-            <stop offset="100%" stop-color="#fa9e2fff" />
-        </linearGradient>
-        <linearGradient x1="0%" y1="0%" z1="0%" x2="100%" y2="0%" z2="100%" id="BlueGradient_0" spreadMethod="reflect">
-            <stop offset="0%" stop-color="#ffffff" />
-            <stop offset="100%" stop-color="#2958acff" />
-        </linearGradient>
-        <linearGradient x1="0%" y1="0%" z1="0%" x2="100%" y2="0%" z2="100%" id="GreenGradient_0" spreadMethod="reflect">
-            <stop offset="0%" stop-color="#ffffff" />
-            <stop offset="100%" stop-color="#378f5cff" />
-        </linearGradient>
-        </listOfGradientDefinitions>
-        <listOfStyles>
-        <style idList="glyph0 glyph2 glyph14 glyph34 ">
-            <g stroke="Color_2" stroke-width="5" fill="yelloComp" />
-        </style>
-        <style idList="glyph1">
-            <g stroke="Color_2" stroke-width="5" fill="grayComp" />
-        </style>
-        <style idList="glyph8 glyph23 glyph5 glyph12 glyph21 glyph13 glyph4 glyph6 glyph7 glyph20 glyph22">
-            <g stroke="orange" stroke-width="2" fill="OrangeGradient_0" />
-        </style>
-        <style idList="glyph3 glyph47 glyph10 glyph11">
-            <g stroke="blue" stroke-width="2" fill="BlueGradient_0" />
-        </style>
-        <style idList="glyph32 glyph37 glyph37a glyph31 glyph39 glyph40 glyph36 glyph28 glyph35 glyph27 glyph25 glyph26 glyph9 glyph38 glyph38a glyph29 glyph30 glyph46 glyph33">
-            <g stroke="green" stroke-width="2" fill="GreenGradient_0" />
-        </style>
-        <style idList="a38">
-            <g stroke="blue" stroke-width="2"  />
-        </style>
-        </listOfStyles>
-    </renderInformation>
-        </extension>
-    </map>
-</sbgn>
diff --git a/libsbgnpy/libsbgn.py b/libsbgnpy/libsbgn.py
deleted file mode 100644
index 6ca703c..0000000
--- a/libsbgnpy/libsbgn.py
+++ /dev/null
@@ -1,3324 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-# Generated Mon Nov 28 14:10:23 2016 by generateDS.py version 2.24a.
-#
-# Command line options:
-#   ('-o', 'libsbgn.py')
-#   ('-s', 'libsbgnSubs.py')
-#
-# Command line arguments:
-#   SBGN.xsd
-#
-# Command line:
-#   /usr/local/bin/generateDS.py -o "libsbgn.py" -s "libsbgnSubs.py" SBGN.xsd
-#
-# Current working directory (os.getcwd()):
-#   schema
-
-import sys
-import re as re_
-import base64
-import datetime as datetime_
-import warnings as warnings_
-try:
-    from lxml import etree as etree_
-except ImportError:
-    from xml.etree import ElementTree as etree_
-
-from .libsbgnTypes import Language, GlyphClass, ArcClass, Orientation
-
-Validate_simpletypes_ = True
-BaseStrType_ = str
-
-
-def parsexml_(infile, parser=None, **kwargs):
-    if parser is None:
-        # Use the lxml ElementTree compatible parser so that, e.g.,
-        #   we ignore comments.
-        try:
-            parser = etree_.ETCompatXMLParser()
-        except AttributeError:
-            # fallback to xml.etree
-            parser = etree_.XMLParser()
-    doc = etree_.parse(infile, parser=parser, **kwargs)
-    return doc
-
-#
-# User methods
-#
-# Calls to the methods in these classes are generated by generateDS.py.
-# You can replace these methods by re-implementing the following class
-#   in a module named generatedssuper.py.
-
-try:
-    from generatedssuper import GeneratedsSuper
-except ImportError as exp:
-
-    class GeneratedsSuper(object):
-        tzoff_pattern = re_.compile(r'(\+|-)((0\d|1[0-3]):[0-5]\d|14:00)$')
-
-        class _FixedOffsetTZ(datetime_.tzinfo):
-            def __init__(self, offset, name):
-                self.__offset = datetime_.timedelta(minutes=offset)
-                self.__name = name
-
-            def utcoffset(self, dt):
-                return self.__offset
-
-            def tzname(self, dt):
-                return self.__name
-
-            def dst(self, dt):
-                return None
-
-        def gds_format_string(self, input_data, input_name=''):
-            return input_data
-
-        def gds_validate_string(self, input_data, node=None, input_name=''):
-            if not input_data:
-                return ''
-            else:
-                return input_data
-
-        def gds_format_base64(self, input_data, input_name=''):
-            return base64.b64encode(input_data)
-
-        def gds_validate_base64(self, input_data, node=None, input_name=''):
-            return input_data
-
-        def gds_format_integer(self, input_data, input_name=''):
-            return '%d' % input_data
-
-        def gds_validate_integer(self, input_data, node=None, input_name=''):
-            return input_data
-
-        def gds_format_integer_list(self, input_data, input_name=''):
-            return '%s' % ' '.join(input_data)
-
-        def gds_validate_integer_list(
-                self, input_data, node=None, input_name=''):
-            values = input_data.split()
-            for value in values:
-                try:
-                    int(value)
-                except (TypeError, ValueError):
-                    raise_parse_error(node, 'Requires sequence of integers')
-            return values
-
-        def gds_format_float(self, input_data, input_name=''):
-            return ('%.15f' % input_data).rstrip('0')
-
-        def gds_validate_float(self, input_data, node=None, input_name=''):
-            return input_data
-
-        def gds_format_float_list(self, input_data, input_name=''):
-            return '%s' % ' '.join(input_data)
-
-        def gds_validate_float_list(
-                self, input_data, node=None, input_name=''):
-            values = input_data.split()
-            for value in values:
-                try:
-                    float(value)
-                except (TypeError, ValueError):
-                    raise_parse_error(node, 'Requires sequence of floats')
-            return values
-
-        def gds_format_double(self, input_data, input_name=''):
-            return '%e' % input_data
-
-        def gds_validate_double(self, input_data, node=None, input_name=''):
-            return input_data
-
-        def gds_format_double_list(self, input_data, input_name=''):
-            return '%s' % ' '.join(input_data)
-
-        def gds_validate_double_list(
-                self, input_data, node=None, input_name=''):
-            values = input_data.split()
-            for value in values:
-                try:
-                    float(value)
-                except (TypeError, ValueError):
-                    raise_parse_error(node, 'Requires sequence of doubles')
-            return values
-
-        def gds_format_boolean(self, input_data, input_name=''):
-            return ('%s' % input_data).lower()
-
-        def gds_validate_boolean(self, input_data, node=None, input_name=''):
-            return input_data
-
-        def gds_format_boolean_list(self, input_data, input_name=''):
-            return '%s' % ' '.join(input_data)
-
-        def gds_validate_boolean_list(
-                self, input_data, node=None, input_name=''):
-            values = input_data.split()
-            for value in values:
-                if value not in ('true', '1', 'false', '0', ):
-                    raise_parse_error(
-                        node,
-                        'Requires sequence of booleans '
-                        '("true", "1", "false", "0")')
-            return values
-
-        def gds_validate_datetime(self, input_data, node=None, input_name=''):
-            return input_data
-
-        def gds_format_datetime(self, input_data, input_name=''):
-            if input_data.microsecond == 0:
-                _svalue = '%04d-%02d-%02dT%02d:%02d:%02d' % (
-                    input_data.year,
-                    input_data.month,
-                    input_data.day,
-                    input_data.hour,
-                    input_data.minute,
-                    input_data.second,
-                )
-            else:
-                _svalue = '%04d-%02d-%02dT%02d:%02d:%02d.%s' % (
-                    input_data.year,
-                    input_data.month,
-                    input_data.day,
-                    input_data.hour,
-                    input_data.minute,
-                    input_data.second,
-                    ('%f' % (float(input_data.microsecond) / 1000000))[2:],
-                )
-            if input_data.tzinfo is not None:
-                tzoff = input_data.tzinfo.utcoffset(input_data)
-                if tzoff is not None:
-                    total_seconds = tzoff.seconds + (86400 * tzoff.days)
-                    if total_seconds == 0:
-                        _svalue += 'Z'
-                    else:
-                        if total_seconds < 0:
-                            _svalue += '-'
-                            total_seconds *= -1
-                        else:
-                            _svalue += '+'
-                        hours = total_seconds // 3600
-                        minutes = (total_seconds - (hours * 3600)) // 60
-                        _svalue += '{0:02d}:{1:02d}'.format(hours, minutes)
-            return _svalue
-
-        @classmethod
-        def gds_parse_datetime(cls, input_data):
-            tz = None
-            if input_data[-1] == 'Z':
-                tz = GeneratedsSuper._FixedOffsetTZ(0, 'UTC')
-                input_data = input_data[:-1]
-            else:
-                results = GeneratedsSuper.tzoff_pattern.search(input_data)
-                if results is not None:
-                    tzoff_parts = results.group(2).split(':')
-                    tzoff = int(tzoff_parts[0]) * 60 + int(tzoff_parts[1])
-                    if results.group(1) == '-':
-                        tzoff *= -1
-                    tz = GeneratedsSuper._FixedOffsetTZ(
-                        tzoff, results.group(0))
-                    input_data = input_data[:-6]
-            time_parts = input_data.split('.')
-            if len(time_parts) > 1:
-                micro_seconds = int(float('0.' + time_parts[1]) * 1000000)
-                input_data = '%s.%s' % (time_parts[0], micro_seconds, )
-                dt = datetime_.datetime.strptime(
-                    input_data, '%Y-%m-%dT%H:%M:%S.%f')
-            else:
-                dt = datetime_.datetime.strptime(
-                    input_data, '%Y-%m-%dT%H:%M:%S')
-            dt = dt.replace(tzinfo=tz)
-            return dt
-
-        def gds_validate_date(self, input_data, node=None, input_name=''):
-            return input_data
-
-        def gds_format_date(self, input_data, input_name=''):
-            _svalue = '%04d-%02d-%02d' % (
-                input_data.year,
-                input_data.month,
-                input_data.day,
-            )
-            try:
-                if input_data.tzinfo is not None:
-                    tzoff = input_data.tzinfo.utcoffset(input_data)
-                    if tzoff is not None:
-                        total_seconds = tzoff.seconds + (86400 * tzoff.days)
-                        if total_seconds == 0:
-                            _svalue += 'Z'
-                        else:
-                            if total_seconds < 0:
-                                _svalue += '-'
-                                total_seconds *= -1
-                            else:
-                                _svalue += '+'
-                            hours = total_seconds // 3600
-                            minutes = (total_seconds - (hours * 3600)) // 60
-                            _svalue += '{0:02d}:{1:02d}'.format(
-                                hours, minutes)
-            except AttributeError:
-                pass
-            return _svalue
-
-        @classmethod
-        def gds_parse_date(cls, input_data):
-            tz = None
-            if input_data[-1] == 'Z':
-                tz = GeneratedsSuper._FixedOffsetTZ(0, 'UTC')
-                input_data = input_data[:-1]
-            else:
-                results = GeneratedsSuper.tzoff_pattern.search(input_data)
-                if results is not None:
-                    tzoff_parts = results.group(2).split(':')
-                    tzoff = int(tzoff_parts[0]) * 60 + int(tzoff_parts[1])
-                    if results.group(1) == '-':
-                        tzoff *= -1
-                    tz = GeneratedsSuper._FixedOffsetTZ(
-                        tzoff, results.group(0))
-                    input_data = input_data[:-6]
-            dt = datetime_.datetime.strptime(input_data, '%Y-%m-%d')
-            dt = dt.replace(tzinfo=tz)
-            return dt.date()
-
-        def gds_validate_time(self, input_data, node=None, input_name=''):
-            return input_data
-
-        def gds_format_time(self, input_data, input_name=''):
-            if input_data.microsecond == 0:
-                _svalue = '%02d:%02d:%02d' % (
-                    input_data.hour,
-                    input_data.minute,
-                    input_data.second,
-                )
-            else:
-                _svalue = '%02d:%02d:%02d.%s' % (
-                    input_data.hour,
-                    input_data.minute,
-                    input_data.second,
-                    ('%f' % (float(input_data.microsecond) / 1000000))[2:],
-                )
-            if input_data.tzinfo is not None:
-                tzoff = input_data.tzinfo.utcoffset(input_data)
-                if tzoff is not None:
-                    total_seconds = tzoff.seconds + (86400 * tzoff.days)
-                    if total_seconds == 0:
-                        _svalue += 'Z'
-                    else:
-                        if total_seconds < 0:
-                            _svalue += '-'
-                            total_seconds *= -1
-                        else:
-                            _svalue += '+'
-                        hours = total_seconds // 3600
-                        minutes = (total_seconds - (hours * 3600)) // 60
-                        _svalue += '{0:02d}:{1:02d}'.format(hours, minutes)
-            return _svalue
-
-        def gds_validate_simple_patterns(self, patterns, target):
-            # pat is a list of lists of strings/patterns.  We should:
-            # - AND the outer elements
-            # - OR the inner elements
-            found1 = True
-            for patterns1 in patterns:
-                found2 = False
-                for patterns2 in patterns1:
-                    if re_.search(patterns2, target) is not None:
-                        found2 = True
-                        break
-                if not found2:
-                    found1 = False
-                    break
-            return found1
-
-        @classmethod
-        def gds_parse_time(cls, input_data):
-            tz = None
-            if input_data[-1] == 'Z':
-                tz = GeneratedsSuper._FixedOffsetTZ(0, 'UTC')
-                input_data = input_data[:-1]
-            else:
-                results = GeneratedsSuper.tzoff_pattern.search(input_data)
-                if results is not None:
-                    tzoff_parts = results.group(2).split(':')
-                    tzoff = int(tzoff_parts[0]) * 60 + int(tzoff_parts[1])
-                    if results.group(1) == '-':
-                        tzoff *= -1
-                    tz = GeneratedsSuper._FixedOffsetTZ(
-                        tzoff, results.group(0))
-                    input_data = input_data[:-6]
-            if len(input_data.split('.')) > 1:
-                dt = datetime_.datetime.strptime(input_data, '%H:%M:%S.%f')
-            else:
-                dt = datetime_.datetime.strptime(input_data, '%H:%M:%S')
-            dt = dt.replace(tzinfo=tz)
-            return dt.time()
-
-        def gds_str_lower(self, instring):
-            return instring.lower()
-
-        def get_path_(self, node):
-            path_list = []
-            self.get_path_list_(node, path_list)
-            path_list.reverse()
-            path = '/'.join(path_list)
-            return path
-        Tag_strip_pattern_ = re_.compile(r'\{.*\}')
-
-        def get_path_list_(self, node, path_list):
-            if node is None:
-                return
-            tag = GeneratedsSuper.Tag_strip_pattern_.sub('', node.tag)
-            if tag:
-                path_list.append(tag)
-            self.get_path_list_(node.getparent(), path_list)
-
-        def get_class_obj_(self, node, default_class=None):
-            class_obj1 = default_class
-            if 'xsi' in node.nsmap:
-                classname = node.get('{%s}type' % node.nsmap['xsi'])
-                if classname is not None:
-                    names = classname.split(':')
-                    if len(names) == 2:
-                        classname = names[1]
-                    class_obj2 = globals().get(classname)
-                    if class_obj2 is not None:
-                        class_obj1 = class_obj2
-            return class_obj1
-
-        def gds_build_any(self, node, type_name=None):
-            return None
-
-        @classmethod
-        def gds_reverse_node_mapping(cls, mapping):
-            return dict(((v, k) for k, v in mapping.iteritems()))
-
-        @staticmethod
-        def gds_encode(instring):
-            if sys.version_info.major == 2:
-                return instring.encode(ExternalEncoding)
-            else:
-                return instring
-
-    def getSubclassFromModule_(module, class_):
-        '''Get the subclass of a class from a specific module.'''
-        name = class_.__name__ + 'Sub'
-        if hasattr(module, name):
-            return getattr(module, name)
-        else:
-            return None
-
-
-#
-# If you have installed IPython you can uncomment and use the following.
-# IPython is available from http://ipython.scipy.org/.
-#
-
-# from IPython.Shell import IPShellEmbed
-# args = ''
-# ipshell = IPShellEmbed(args,
-#     banner = 'Dropping into IPython',
-# exit_msg = 'Leaving Interpreter, back to program.')
-
-# Then use the following line where and when you want to drop into the
-# IPython shell:
-#    ipshell('<some message> -- Entering ipshell.\nHit Ctrl-D to exit')
-
-#
-# Globals
-#
-
-ExternalEncoding = 'utf8'
-Tag_pattern_ = re_.compile(r'({.*})?(.*)')
-String_cleanup_pat_ = re_.compile(r"[\n\r\s]+")
-Namespace_extract_pat_ = re_.compile(r'{(.*)}(.*)')
-CDATA_pattern_ = re_.compile(r"<!\[CDATA\[.*?\]\]>", re_.DOTALL)
-
-# Change this to redirect the generated superclass module to use a
-# specific subclass module.
-CurrentSubclassModule_ = None
-
-#
-# Support/utility functions.
-#
-
-
-def showIndent(outfile, level, pretty_print=True):
-    if pretty_print:
-        for idx in range(level):
-            outfile.write('    ')
-
-
-def quote_xml(inStr):
-    "Escape markup chars, but do not modify CDATA sections."
-    if not inStr:
-        return ''
-    s1 = (isinstance(inStr, BaseStrType_) and inStr or '%s' % inStr)
-    s2 = ''
-    pos = 0
-    matchobjects = CDATA_pattern_.finditer(s1)
-    for mo in matchobjects:
-        s3 = s1[pos:mo.start()]
-        s2 += quote_xml_aux(s3)
-        s2 += s1[mo.start():mo.end()]
-        pos = mo.end()
-    s3 = s1[pos:]
-    s2 += quote_xml_aux(s3)
-    return s2
-
-
-def quote_xml_aux(inStr):
-    s1 = inStr.replace('&', '&amp;')
-    s1 = s1.replace('<', '&lt;')
-    s1 = s1.replace('>', '&gt;')
-    return s1
-
-
-def quote_attrib(inStr):
-    s1 = (isinstance(inStr, BaseStrType_) and inStr or '%s' % inStr)
-    s1 = s1.replace('&', '&amp;')
-    s1 = s1.replace('<', '&lt;')
-    s1 = s1.replace('>', '&gt;')
-    if '"' in s1:
-        if "'" in s1:
-            s1 = '"%s"' % s1.replace('"', "&quot;")
-        else:
-            s1 = "'%s'" % s1
-    else:
-        s1 = '"%s"' % s1
-    return s1
-
-
-def quote_python(inStr):
-    s1 = inStr
-    if s1.find("'") == -1:
-        if s1.find('\n') == -1:
-            return "'%s'" % s1
-        else:
-            return "'''%s'''" % s1
-    else:
-        if s1.find('"') != -1:
-            s1 = s1.replace('"', '\\"')
-        if s1.find('\n') == -1:
-            return '"%s"' % s1
-        else:
-            return '"""%s"""' % s1
-
-
-def get_all_text_(node):
-    if node.text is not None:
-        text = node.text
-    else:
-        text = ''
-    for child in node:
-        if child.tail is not None:
-            text += child.tail
-    return text
-
-
-def find_attr_value_(attr_name, node):
-    attrs = node.attrib
-    attr_parts = attr_name.split(':')
-    value = None
-    if len(attr_parts) == 1:
-        value = attrs.get(attr_name)
-    elif len(attr_parts) == 2:
-        prefix, name = attr_parts
-        namespace = node.nsmap.get(prefix)
-        if namespace is not None:
-            value = attrs.get('{%s}%s' % (namespace, name, ))
-    return value
-
-
-class GDSParseError(Exception):
-    pass
-
-
-def raise_parse_error(node, msg):
-    msg = '%s (element %s/line %d)' % (msg, node.tag, node.sourceline, )
-    raise GDSParseError(msg)
-
-
-class MixedContainer:
-    # Constants for category:
-    CategoryNone = 0
-    CategoryText = 1
-    CategorySimple = 2
-    CategoryComplex = 3
-    # Constants for content_type:
-    TypeNone = 0
-    TypeText = 1
-    TypeString = 2
-    TypeInteger = 3
-    TypeFloat = 4
-    TypeDecimal = 5
-    TypeDouble = 6
-    TypeBoolean = 7
-    TypeBase64 = 8
-
-    def __init__(self, category, content_type, name, value):
-        self.category = category
-        self.content_type = content_type
-        self.name = name
-        self.value = value
-
-    def getCategory(self):
-        return self.category
-
-    def getContenttype(self, content_type):
-        return self.content_type
-
-    def getValue(self):
-        return self.value
-
-    def getName(self):
-        return self.name
-
-    def export(self, outfile, level, name, namespace, pretty_print=True):
-        if self.category == MixedContainer.CategoryText:
-            # Prevent exporting empty content as empty lines.
-            if self.value.strip():
-                outfile.write(self.value)
-        elif self.category == MixedContainer.CategorySimple:
-            self.exportSimple(outfile, level, name)
-        else:    # category == MixedContainer.CategoryComplex
-            self.value.export(
-                outfile, level, namespace, name, pretty_print=pretty_print)
-
-    def exportSimple(self, outfile, level, name):
-        if self.content_type == MixedContainer.TypeString:
-            outfile.write('<%s>%s</%s>' % (
-                self.name, self.value, self.name))
-        elif self.content_type == MixedContainer.TypeInteger or \
-                self.content_type == MixedContainer.TypeBoolean:
-            outfile.write('<%s>%d</%s>' % (
-                self.name, self.value, self.name))
-        elif self.content_type == MixedContainer.TypeFloat or \
-                self.content_type == MixedContainer.TypeDecimal:
-            outfile.write('<%s>%f</%s>' % (
-                self.name, self.value, self.name))
-        elif self.content_type == MixedContainer.TypeDouble:
-            outfile.write('<%s>%g</%s>' % (
-                self.name, self.value, self.name))
-        elif self.content_type == MixedContainer.TypeBase64:
-            outfile.write('<%s>%s</%s>' % (
-                self.name, base64.b64encode(self.value), self.name))
-
-    def to_etree(self, element):
-        if self.category == MixedContainer.CategoryText:
-            # Prevent exporting empty content as empty lines.
-            if self.value.strip():
-                if len(element) > 0:
-                    if element[-1].tail is None:
-                        element[-1].tail = self.value
-                    else:
-                        element[-1].tail += self.value
-                else:
-                    if element.text is None:
-                        element.text = self.value
-                    else:
-                        element.text += self.value
-        elif self.category == MixedContainer.CategorySimple:
-            subelement = etree_.SubElement(element, '%s' % self.name)
-            subelement.text = self.to_etree_simple()
-        else:    # category == MixedContainer.CategoryComplex
-            self.value.to_etree(element)
-
-    def to_etree_simple(self):
-        if self.content_type == MixedContainer.TypeString:
-            text = self.value
-        elif (self.content_type == MixedContainer.TypeInteger or
-                self.content_type == MixedContainer.TypeBoolean):
-            text = '%d' % self.value
-        elif (self.content_type == MixedContainer.TypeFloat or
-                self.content_type == MixedContainer.TypeDecimal):
-            text = '%f' % self.value
-        elif self.content_type == MixedContainer.TypeDouble:
-            text = '%g' % self.value
-        elif self.content_type == MixedContainer.TypeBase64:
-            text = '%s' % base64.b64encode(self.value)
-        return text
-
-    def exportLiteral(self, outfile, level, name):
-        if self.category == MixedContainer.CategoryText:
-            showIndent(outfile, level)
-            outfile.write(
-                'model_.MixedContainer(%d, %d, "%s", "%s"),\n' % (
-                    self.category, self.content_type, self.name, self.value))
-        elif self.category == MixedContainer.CategorySimple:
-            showIndent(outfile, level)
-            outfile.write(
-                'model_.MixedContainer(%d, %d, "%s", "%s"),\n' % (
-                    self.category, self.content_type, self.name, self.value))
-        else:    # category == MixedContainer.CategoryComplex
-            showIndent(outfile, level)
-            outfile.write(
-                'model_.MixedContainer(%d, %d, "%s",\n' % (
-                    self.category, self.content_type, self.name,))
-            self.value.exportLiteral(outfile, level + 1)
-            showIndent(outfile, level)
-            outfile.write(')\n')
-
-
-class MemberSpec_(object):
-    def __init__(self, name='', data_type='', container=0):
-        self.name = name
-        self.data_type = data_type
-        self.container = container
-
-    def set_name(self, name): self.name = name
-
-    def get_name(self): return self.name
-
-    def set_data_type(self, data_type): self.data_type = data_type
-
-    def get_data_type_chain(self): return self.data_type
-
-    def get_data_type(self):
-        if isinstance(self.data_type, list):
-            if len(self.data_type) > 0:
-                return self.data_type[-1]
-            else:
-                return 'xs:string'
-        else:
-            return self.data_type
-
-    def set_container(self, container): self.container = container
-
-    def get_container(self): return self.container
-
-
-def _cast(typ, value):
-    if typ is None or value is None:
-        return value
-    return typ(value)
-
-#
-# Data representation classes.
-#
-
-
-class SBGNBase(GeneratedsSuper):
-    """The SBGNBase type is the base type of all main components in SBGN.
-    It supports attaching metadata, notes and annotations to
-    components."""
-    subclass = None
-    superclass = None
-
-    def __init__(self, notes=None, extension=None, extensiontype_=None):
-        self.original_tagname_ = None
-        self.notes = notes
-        self.extension = extension
-        self.extensiontype_ = extensiontype_
-
-    def factory(*args_, **kwargs_):
-        if CurrentSubclassModule_ is not None:
-            subclass = getSubclassFromModule_(
-                CurrentSubclassModule_, SBGNBase)
-            if subclass is not None:
-                return subclass(*args_, **kwargs_)
-        if SBGNBase.subclass:
-            return SBGNBase.subclass(*args_, **kwargs_)
-        else:
-            return SBGNBase(*args_, **kwargs_)
-    factory = staticmethod(factory)
-
-    def get_notes(self): return self.notes
-
-    def set_notes(self, notes): self.notes = notes
-
-    def get_extension(self): return self.extension
-
-    def set_extension(self, extension): self.extension = extension
-
-    def get_extensiontype_(self): return self.extensiontype_
-
-    def set_extensiontype_(self, extensiontype_): self.extensiontype_ = extensiontype_
-
-    def hasContent_(self):
-        if (
-            self.notes is not None or
-            self.extension is not None
-        ):
-            return True
-        else:
-            return False
-
-    def write_file(self, outfile, namespace='sbgn'):
-        """ Write SBGN to file.
-
-        This also fixes the issues of the sbgn namespace prefix.
-
-        :param outfile: SBGN file to write
-        :param namespace:
-        :return:
-        """
-        f = open(outfile, 'w')
-        f.write('<?xml version="1.0" encoding="UTF-8"?>\n')
-        self.export(f, level=0, namespace_='sbgn', name_='')
-        f.close()
-
-        # this is a bad hack to remove the namespaces, because
-        # most of the SBGN tools do not support them.
-        import fileinput
-        f = fileinput.input(outfile, inplace=True)
-
-        for line in f:
-            # remove prefix from closing tags, and unnecessary namespace
-            line = line.replace(' xmlns:sbgn="http://sbgn.org/libsbgn/0.2"', '')
-            line = line.replace('sbgn:', '')
-            line = line.replace('<sbgn>', '<sbgn xmlns="http://sbgn.org/libsbgn/0.2">')
-            print(line, end='')
-
-        f.close()
-
-    def export(self, outfile, level, namespace_='sbgn:', name_='sbgn', namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"', pretty_print=True):
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        if self.original_tagname_ is not None:
-            name_ = self.original_tagname_
-        showIndent(outfile, level, pretty_print)
-        outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
-        already_processed = set()
-        self.exportAttributes(outfile, level, already_processed, namespace_, name_='sbgn')
-        if self.hasContent_():
-            outfile.write('>%s' % (eol_, ))
-            self.exportChildren(outfile, level + 1, namespace_='sbgn:', name_='sbgn', pretty_print=pretty_print)
-            showIndent(outfile, level, pretty_print)
-            outfile.write('</%s%s>%s' % (namespace_, name_, eol_))
-        else:
-            outfile.write('/>%s' % (eol_, ))
-
-    def exportAttributes(self, outfile, level, already_processed, namespace_='sbgn:', name_='SBGNBase'):
-        if self.extensiontype_ is not None and 'xsi:type' not in already_processed:
-            already_processed.add('xsi:type')
-            outfile.write(' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"')
-            outfile.write(' xsi:type="%s"' % self.extensiontype_)
-        pass
-
-    def exportChildren(self, outfile, level, namespace_='sbgn:', name_='SBGNBase', fromsubclass_=False, pretty_print=True):
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        if self.notes is not None:
-            self.notes.export(outfile, level, namespace_, name_='notes', pretty_print=pretty_print)
-        if self.extension is not None:
-            self.extension.export(outfile, level, namespace_, name_='extension', pretty_print=pretty_print)
-
-    def build(self, node):
-        already_processed = set()
-        self.buildAttributes(node, node.attrib, already_processed)
-        for child in node:
-            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
-            self.buildChildren(child, node, nodeName_)
-        return self
-
-    def buildAttributes(self, node, attrs, already_processed):
-        value = find_attr_value_('xsi:type', node)
-        if value is not None and 'xsi:type' not in already_processed:
-            already_processed.add('xsi:type')
-            self.extensiontype_ = value
-
-    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
-        if nodeName_ == 'notes':
-            obj_ = notesType.factory()
-            obj_.build(child_)
-            self.notes = obj_
-            obj_.original_tagname_ = 'notes'
-        elif nodeName_ == 'extension':
-            obj_ = extensionType.factory()
-            obj_.build(child_)
-            self.extension = obj_
-            obj_.original_tagname_ = 'extension'
-# end class SBGNBase
-
-
-class point(SBGNBase):
-    """The point element is characterized by PointAttributes, which
-    describe absolute 2D cartesian coordinates. Namely: x
-    (horizontal, from left to right), y (vertical, from top to
-    bottom). The origin is located in the top-left corner of the
-    map. There is no unit: proportions must be preserved, but the
-    maps can be drawn at any scale. In the test files examples, to
-    obtain a drawing similar to the reference *.png file, values in
-    the corresponding *.sbgn file should be read as pixels."""
-    subclass = None
-    superclass = SBGNBase
-
-    def __init__(self, notes=None, extension=None, x=None, y=None):
-        self.original_tagname_ = None
-        super(point, self).__init__(notes, extension, )
-        self.x = _cast(float, x)
-        self.y = _cast(float, y)
-
-    def factory(*args_, **kwargs_):
-        if CurrentSubclassModule_ is not None:
-            subclass = getSubclassFromModule_(
-                CurrentSubclassModule_, point)
-            if subclass is not None:
-                return subclass(*args_, **kwargs_)
-        if point.subclass:
-            return point.subclass(*args_, **kwargs_)
-        else:
-            return point(*args_, **kwargs_)
-    factory = staticmethod(factory)
-
-    def get_x(self): return self.x
-
-    def set_x(self, x): self.x = x
-
-    def get_y(self): return self.y
-
-    def set_y(self, y): self.y = y
-
-    def hasContent_(self):
-        if (
-            super(point, self).hasContent_()
-        ):
-            return True
-        else:
-            return False
-
-    def export(self, outfile, level, namespace_='sbgn:', name_='point', namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"', pretty_print=True):
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        if self.original_tagname_ is not None:
-            name_ = self.original_tagname_
-        showIndent(outfile, level, pretty_print)
-        outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
-        already_processed = set()
-        self.exportAttributes(outfile, level, already_processed, namespace_, name_='point')
-        if self.hasContent_():
-            outfile.write('>%s' % (eol_, ))
-            self.exportChildren(outfile, level + 1, namespace_='sbgn:', name_='point', pretty_print=pretty_print)
-            showIndent(outfile, level, pretty_print)
-            outfile.write('</%s%s>%s' % (namespace_, name_, eol_))
-        else:
-            outfile.write('/>%s' % (eol_, ))
-
-    def exportAttributes(self, outfile, level, already_processed, namespace_='sbgn:', name_='point'):
-        super(point, self).exportAttributes(outfile, level, already_processed, namespace_, name_='point')
-        if self.x is not None and 'x' not in already_processed:
-            already_processed.add('x')
-            outfile.write(' x="%s"' % self.gds_format_float(self.x, input_name='x'))
-        if self.y is not None and 'y' not in already_processed:
-            already_processed.add('y')
-            outfile.write(' y="%s"' % self.gds_format_float(self.y, input_name='y'))
-
-    def exportChildren(self, outfile, level, namespace_='sbgn:', name_='point', fromsubclass_=False, pretty_print=True):
-        super(point, self).exportChildren(outfile, level, namespace_, name_, True, pretty_print=pretty_print)
-
-    def build(self, node):
-        already_processed = set()
-        self.buildAttributes(node, node.attrib, already_processed)
-        for child in node:
-            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
-            self.buildChildren(child, node, nodeName_)
-        return self
-
-    def buildAttributes(self, node, attrs, already_processed):
-        value = find_attr_value_('x', node)
-        if value is not None and 'x' not in already_processed:
-            already_processed.add('x')
-            try:
-                self.x = float(value)
-            except ValueError as exp:
-                raise ValueError('Bad float/double attribute (x): %s' % exp)
-        value = find_attr_value_('y', node)
-        if value is not None and 'y' not in already_processed:
-            already_processed.add('y')
-            try:
-                self.y = float(value)
-            except ValueError as exp:
-                raise ValueError('Bad float/double attribute (y): %s' % exp)
-        super(point, self).buildAttributes(node, attrs, already_processed)
-
-    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
-        super(point, self).buildChildren(child_, node, nodeName_, True)
-        pass
-# end class point
-
-
-class bbox(SBGNBase):
-    """The bbox element describes a rectangle. This rectangle is defined
-    by: PointAttributes corresponding to the 2D coordinates of the
-    top left corner, width and height attributes. The rectangle
-    corresponds to the outer bounding box of a shape. The shape
-    itself can be irregular (for instance in the case of some
-    compartments). In the case of process nodes, the bounding box
-    only concerns the central glyph (square, or circle), the
-    input/output ports are not included, and neither are the lines
-    connecting them to the central glyph. A bbox is required for all
-    glyphs, and is optional for labels."""
-    subclass = None
-    superclass = SBGNBase
-
-    def __init__(self, x=None, y=None, w=None, h=None, notes=None, extension=None):
-        self.original_tagname_ = None
-        super(bbox, self).__init__(notes, extension, )
-        self.w = _cast(float, w)
-        self.h = _cast(float, h)
-        self.x = _cast(float, x)
-        self.y = _cast(float, y)
-
-    def factory(*args_, **kwargs_):
-        if CurrentSubclassModule_ is not None:
-            subclass = getSubclassFromModule_(
-                CurrentSubclassModule_, bbox)
-            if subclass is not None:
-                return subclass(*args_, **kwargs_)
-        if bbox.subclass:
-            return bbox.subclass(*args_, **kwargs_)
-        else:
-            return bbox(*args_, **kwargs_)
-    factory = staticmethod(factory)
-
-    def get_w(self): return self.w
-
-    def set_w(self, w): self.w = w
-
-    def get_h(self): return self.h
-
-    def set_h(self, h): self.h = h
-
-    def get_x(self): return self.x
-
-    def set_x(self, x): self.x = x
-
-    def get_y(self): return self.y
-
-    def set_y(self, y): self.y = y
-
-    def hasContent_(self):
-        if (
-            super(bbox, self).hasContent_()
-        ):
-            return True
-        else:
-            return False
-
-    def export(self, outfile, level, namespace_='sbgn:', name_='bbox', namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"', pretty_print=True):
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        if self.original_tagname_ is not None:
-            name_ = self.original_tagname_
-        showIndent(outfile, level, pretty_print)
-        outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
-        already_processed = set()
-        self.exportAttributes(outfile, level, already_processed, namespace_, name_='bbox')
-        if self.hasContent_():
-            outfile.write('>%s' % (eol_, ))
-            self.exportChildren(outfile, level + 1, namespace_='sbgn:', name_='bbox', pretty_print=pretty_print)
-            showIndent(outfile, level, pretty_print)
-            outfile.write('</%s%s>%s' % (namespace_, name_, eol_))
-        else:
-            outfile.write('/>%s' % (eol_, ))
-
-    def exportAttributes(self, outfile, level, already_processed, namespace_='sbgn:', name_='bbox'):
-        super(bbox, self).exportAttributes(outfile, level, already_processed, namespace_, name_='bbox')
-        if self.w is not None and 'w' not in already_processed:
-            already_processed.add('w')
-            outfile.write(' w="%s"' % self.gds_format_float(self.w, input_name='w'))
-        if self.h is not None and 'h' not in already_processed:
-            already_processed.add('h')
-            outfile.write(' h="%s"' % self.gds_format_float(self.h, input_name='h'))
-        if self.x is not None and 'x' not in already_processed:
-            already_processed.add('x')
-            outfile.write(' x="%s"' % self.gds_format_float(self.x, input_name='x'))
-        if self.y is not None and 'y' not in already_processed:
-            already_processed.add('y')
-            outfile.write(' y="%s"' % self.gds_format_float(self.y, input_name='y'))
-
-    def exportChildren(self, outfile, level, namespace_='sbgn:', name_='bbox', fromsubclass_=False, pretty_print=True):
-        super(bbox, self).exportChildren(outfile, level, namespace_, name_, True, pretty_print=pretty_print)
-
-    def build(self, node):
-        already_processed = set()
-        self.buildAttributes(node, node.attrib, already_processed)
-        for child in node:
-            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
-            self.buildChildren(child, node, nodeName_)
-        return self
-
-    def buildAttributes(self, node, attrs, already_processed):
-        value = find_attr_value_('w', node)
-        if value is not None and 'w' not in already_processed:
-            already_processed.add('w')
-            try:
-                self.w = float(value)
-            except ValueError as exp:
-                raise ValueError('Bad float/double attribute (w): %s' % exp)
-        value = find_attr_value_('h', node)
-        if value is not None and 'h' not in already_processed:
-            already_processed.add('h')
-            try:
-                self.h = float(value)
-            except ValueError as exp:
-                raise ValueError('Bad float/double attribute (h): %s' % exp)
-        value = find_attr_value_('x', node)
-        if value is not None and 'x' not in already_processed:
-            already_processed.add('x')
-            try:
-                self.x = float(value)
-            except ValueError as exp:
-                raise ValueError('Bad float/double attribute (x): %s' % exp)
-        value = find_attr_value_('y', node)
-        if value is not None and 'y' not in already_processed:
-            already_processed.add('y')
-            try:
-                self.y = float(value)
-            except ValueError as exp:
-                raise ValueError('Bad float/double attribute (y): %s' % exp)
-        super(bbox, self).buildAttributes(node, attrs, already_processed)
-
-    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
-        super(bbox, self).buildChildren(child_, node, nodeName_, True)
-        pass
-# end class bbox
-
-
-class label(SBGNBase):
-    """The label element describes the text accompanying a glyph. The text
-    attribute is mandatory. Its position can be specified by a bbox
-    (optional). Tools are free to display the text in any style
-    (font, font-size, etc.) The bbox element of a label is optional.
-    When no bbox is defined, the bbox of the parent glyph is
-    inherited. The label should be drawn centered horizontally and
-    vertically in the bbox. When the bbox is inherited, the label
-    can freely spill outside (just like it can spill outside its
-    parent glyph). An explicit bbox provides a stronger hint
-    regarding what surface the label should cover. It defines an
-    upper boundary outside of which the label should (ideally) not
-    spill. It also represents a preferred size: the surface covered
-    by the label can be smaller, but should ideally be as close as
-    possible to the bbox. In most glyphs (EPNs, unit of information,
-    etc.), the label is supposed to be centered, so the bbox is
-    usually omitted (unless there's a specific hint to be shared
-    concerning the area the label should ideally cover). However,
-    labels can be drawn anywhere inside compartments or complex, so
-    these should preferably have an explicit bbox. Multi-line labels
-    are allowed. Line breaks are encoded as &#xA; as specified by
-    the XML standard."""
-    subclass = None
-    superclass = SBGNBase
-
-    def __init__(self, notes=None, extension=None, text=None, bbox=None):
-        self.original_tagname_ = None
-        super(label, self).__init__(notes, extension, )
-        self.text = _cast(None, text)
-        self.bbox = bbox
-
-    def factory(*args_, **kwargs_):
-        if CurrentSubclassModule_ is not None:
-            subclass = getSubclassFromModule_(
-                CurrentSubclassModule_, label)
-            if subclass is not None:
-                return subclass(*args_, **kwargs_)
-        if label.subclass:
-            return label.subclass(*args_, **kwargs_)
-        else:
-            return label(*args_, **kwargs_)
-    factory = staticmethod(factory)
-
-    def get_bbox(self): return self.bbox
-
-    def set_bbox(self, bbox): self.bbox = bbox
-
-    def get_text(self): return self.text
-
-    def set_text(self, text): self.text = text
-
-    def hasContent_(self):
-        if (
-            self.bbox is not None or
-            super(label, self).hasContent_()
-        ):
-            return True
-        else:
-            return False
-
-    def export(self, outfile, level, namespace_='sbgn:', name_='label', namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"', pretty_print=True):
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        if self.original_tagname_ is not None:
-            name_ = self.original_tagname_
-        showIndent(outfile, level, pretty_print)
-        outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
-        already_processed = set()
-        self.exportAttributes(outfile, level, already_processed, namespace_, name_='label')
-        if self.hasContent_():
-            outfile.write('>%s' % (eol_, ))
-            self.exportChildren(outfile, level + 1, namespace_='sbgn:', name_='label', pretty_print=pretty_print)
-            showIndent(outfile, level, pretty_print)
-            outfile.write('</%s%s>%s' % (namespace_, name_, eol_))
-        else:
-            outfile.write('/>%s' % (eol_, ))
-
-    def exportAttributes(self, outfile, level, already_processed, namespace_='sbgn:', name_='label'):
-        super(label, self).exportAttributes(outfile, level, already_processed, namespace_, name_='label')
-        if self.text is not None and 'text' not in already_processed:
-            already_processed.add('text')
-            outfile.write(' text=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.text), input_name='text')), ))
-
-    def exportChildren(self, outfile, level, namespace_='sbgn:', name_='label', fromsubclass_=False, pretty_print=True):
-        super(label, self).exportChildren(outfile, level, namespace_, name_, True, pretty_print=pretty_print)
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        if self.bbox is not None:
-            self.bbox.export(outfile, level, namespace_='sbgn:', name_='bbox', pretty_print=pretty_print)
-
-    def build(self, node):
-        already_processed = set()
-        self.buildAttributes(node, node.attrib, already_processed)
-        for child in node:
-            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
-            self.buildChildren(child, node, nodeName_)
-        return self
-
-    def buildAttributes(self, node, attrs, already_processed):
-        value = find_attr_value_('text', node)
-        if value is not None and 'text' not in already_processed:
-            already_processed.add('text')
-            self.text = value
-        super(label, self).buildAttributes(node, attrs, already_processed)
-
-    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
-        if nodeName_ == 'bbox':
-            obj_ = bbox.factory()
-            obj_.build(child_)
-            self.bbox = obj_
-            obj_.original_tagname_ = 'bbox'
-        super(label, self).buildChildren(child_, node, nodeName_, True)
-# end class label
-
-
-class sbgn(SBGNBase):
-    """The sbgn element is the root of any SBGNML document. Currently each
-    document must contain exactly one map element."""
-    subclass = None
-    superclass = SBGNBase
-
-    def __init__(self, notes=None, extension=None, map=None):
-        self.original_tagname_ = None
-        super(sbgn, self).__init__(notes, extension, )
-        self.map = map
-
-    def factory(*args_, **kwargs_):
-        if CurrentSubclassModule_ is not None:
-            subclass = getSubclassFromModule_(
-                CurrentSubclassModule_, sbgn)
-            if subclass is not None:
-                return subclass(*args_, **kwargs_)
-        if sbgn.subclass:
-            return sbgn.subclass(*args_, **kwargs_)
-        else:
-            return sbgn(*args_, **kwargs_)
-    factory = staticmethod(factory)
-
-    def get_map(self): return self.map
-
-    def set_map(self, map): self.map = map
-
-    def hasContent_(self):
-        if (
-            self.map is not None or
-            super(sbgn, self).hasContent_()
-        ):
-            return True
-        else:
-            return False
-
-    def export(self, outfile, level, namespace_='sbgn:', name_='sbgn', namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"', pretty_print=True):
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        if self.original_tagname_ is not None:
-            name_ = self.original_tagname_
-        showIndent(outfile, level, pretty_print)
-        outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
-        already_processed = set()
-        self.exportAttributes(outfile, level, already_processed, namespace_, name_='sbgn')
-        if self.hasContent_():
-            outfile.write('>%s' % (eol_, ))
-            self.exportChildren(outfile, level + 1, namespace_='sbgn:', name_='sbgn', pretty_print=pretty_print)
-            showIndent(outfile, level, pretty_print)
-            outfile.write('</%s%s>%s' % (namespace_, name_, eol_))
-        else:
-            outfile.write('/>%s' % (eol_, ))
-
-    def exportAttributes(self, outfile, level, already_processed, namespace_='sbgn:', name_='sbgn'):
-        super(sbgn, self).exportAttributes(outfile, level, already_processed, namespace_, name_='sbgn')
-
-    def exportChildren(self, outfile, level, namespace_='sbgn:', name_='sbgn', fromsubclass_=False, pretty_print=True):
-        super(sbgn, self).exportChildren(outfile, level, namespace_, name_, True, pretty_print=pretty_print)
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        if self.map is not None:
-            self.map.export(outfile, level, namespace_='sbgn:', name_='map', pretty_print=pretty_print)
-
-    def build(self, node):
-        already_processed = set()
-        self.buildAttributes(node, node.attrib, already_processed)
-        for child in node:
-            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
-            self.buildChildren(child, node, nodeName_)
-        return self
-
-    def buildAttributes(self, node, attrs, already_processed):
-        super(sbgn, self).buildAttributes(node, attrs, already_processed)
-
-    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
-        if nodeName_ == 'map':
-            obj_ = map.factory()
-            obj_.build(child_)
-            self.map = obj_
-            obj_.original_tagname_ = 'map'
-        super(sbgn, self).buildChildren(child_, node, nodeName_, True)
-# end class sbgn
-
-
-class map(SBGNBase):
-    """The map element describes a single SBGN PD map. It contains a list
-    of glyph elements and a list of arc elements. These lists can be
-    of any size (possibly empty). Language of the map: one of three
-    sublanguages defined by SBGN. Different languages have different
-    restrictions on the usage of sub-elements (that are not encoded
-    in this schema but must be validated with an external validator)"""
-    subclass = None
-    superclass = SBGNBase
-
-    def __init__(self, notes=None, extension=None, language=None, bbox=None, glyph=None, arc=None, arcgroup=None):
-        self.original_tagname_ = None
-        super(map, self).__init__(notes, extension, )
-        self.set_language(language)
-        self.bbox = bbox
-        if glyph is None:
-            self.glyph = []
-        else:
-            self.glyph = glyph
-        if arc is None:
-            self.arc = []
-        else:
-            self.arc = arc
-        if arcgroup is None:
-            self.arcgroup = []
-        else:
-            self.arcgroup = arcgroup
-
-    def factory(*args_, **kwargs_):
-        if CurrentSubclassModule_ is not None:
-            subclass = getSubclassFromModule_(
-                CurrentSubclassModule_, map)
-            if subclass is not None:
-                return subclass(*args_, **kwargs_)
-        if map.subclass:
-            return map.subclass(*args_, **kwargs_)
-        else:
-            return map(*args_, **kwargs_)
-    factory = staticmethod(factory)
-
-    def get_bbox(self): return self.bbox
-
-    def set_bbox(self, bbox): self.bbox = bbox
-
-    def get_glyph(self): return self.glyph
-
-    def set_glyph(self, glyph): self.glyph = glyph
-
-    def add_glyph(self, value): self.glyph.append(value)
-
-    def insert_glyph_at(self, index, value): self.glyph.insert(index, value)
-
-    def replace_glyph_at(self, index, value): self.glyph[index] = value
-
-    def get_arc(self): return self.arc
-
-    def set_arc(self, arc): self.arc = arc
-
-    def add_arc(self, value): self.arc.append(value)
-
-    def insert_arc_at(self, index, value): self.arc.insert(index, value)
-
-    def replace_arc_at(self, index, value): self.arc[index] = value
-
-    def get_arcgroup(self): return self.arcgroup
-
-    def set_arcgroup(self, arcgroup): self.arcgroup = arcgroup
-
-    def add_arcgroup(self, value): self.arcgroup.append(value)
-
-    def insert_arcgroup_at(self, index, value): self.arcgroup.insert(index, value)
-
-    def replace_arcgroup_at(self, index, value): self.arcgroup[index] = value
-
-    def get_language(self):
-        """ Get the Language.
-        :return: Language instance.
-        """
-        return Language(self.language)
-
-    def set_language(self, language):
-        """ Sets the language and checks that within allowed values.
-        :param language:
-        :return:
-        """
-        if language and not isinstance(language, Language):
-            raise TypeError('language must be of type Language')
-        if language:
-            self.language = _cast(None, language.value)
-        else:
-            self.language = _cast(None, language)
-
-    def hasContent_(self):
-        if (
-            self.bbox is not None or
-            self.glyph or
-            self.arc or
-            self.arcgroup or
-            super(map, self).hasContent_()
-        ):
-            return True
-        else:
-            return False
-
-    def export(self, outfile, level, namespace_='sbgn:', name_='map', namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"', pretty_print=True):
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        if self.original_tagname_ is not None:
-            name_ = self.original_tagname_
-        showIndent(outfile, level, pretty_print)
-        outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
-        already_processed = set()
-        self.exportAttributes(outfile, level, already_processed, namespace_, name_='map')
-        if self.hasContent_():
-            outfile.write('>%s' % (eol_, ))
-            self.exportChildren(outfile, level + 1, namespace_='sbgn:', name_='map', pretty_print=pretty_print)
-            showIndent(outfile, level, pretty_print)
-            outfile.write('</%s%s>%s' % (namespace_, name_, eol_))
-        else:
-            outfile.write('/>%s' % (eol_, ))
-
-    def exportAttributes(self, outfile, level, already_processed, namespace_='sbgn:', name_='map'):
-        super(map, self).exportAttributes(outfile, level, already_processed, namespace_, name_='map')
-        if self.language is not None and 'language' not in already_processed:
-            already_processed.add('language')
-            outfile.write(' language=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.language), input_name='language')), ))
-
-    def exportChildren(self, outfile, level, namespace_='sbgn:', name_='map', fromsubclass_=False, pretty_print=True):
-        super(map, self).exportChildren(outfile, level, namespace_, name_, True, pretty_print=pretty_print)
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        if self.bbox is not None:
-            self.bbox.export(outfile, level, namespace_='sbgn:', name_='bbox', pretty_print=pretty_print)
-        for glyph_ in self.glyph:
-            glyph_.export(outfile, level, namespace_='sbgn:', name_='glyph', pretty_print=pretty_print)
-        for arc_ in self.arc:
-            arc_.export(outfile, level, namespace_='sbgn:', name_='arc', pretty_print=pretty_print)
-        for arcgroup_ in self.arcgroup:
-            arcgroup_.export(outfile, level, namespace_='sbgn:', name_='arcgroup', pretty_print=pretty_print)
-
-    def build(self, node):
-        already_processed = set()
-        self.buildAttributes(node, node.attrib, already_processed)
-        for child in node:
-            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
-            self.buildChildren(child, node, nodeName_)
-        return self
-
-    def buildAttributes(self, node, attrs, already_processed):
-        value = find_attr_value_('language', node)
-        if value is not None and 'language' not in already_processed:
-            already_processed.add('language')
-            self.language = value
-        super(map, self).buildAttributes(node, attrs, already_processed)
-
-    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
-        if nodeName_ == 'bbox':
-            obj_ = bbox.factory()
-            obj_.build(child_)
-            self.bbox = obj_
-            obj_.original_tagname_ = 'bbox'
-        elif nodeName_ == 'glyph':
-            obj_ = glyph.factory()
-            obj_.build(child_)
-            self.glyph.append(obj_)
-            obj_.original_tagname_ = 'glyph'
-        elif nodeName_ == 'arc':
-            obj_ = arc.factory()
-            obj_.build(child_)
-            self.arc.append(obj_)
-            obj_.original_tagname_ = 'arc'
-        elif nodeName_ == 'arcgroup':
-            obj_ = arcgroup.factory()
-            obj_.build(child_)
-            self.arcgroup.append(obj_)
-            obj_.original_tagname_ = 'arcgroup'
-        super(map, self).buildChildren(child_, node, nodeName_, True)
-# end class map
-
-
-class port(SBGNBase):
-    """The port element describes an anchor point which arcs can refer to
-    as a source or target. It consists in: absolute 2D cartesian
-    coordinates (PointAttribute), a unique id attribute. Two port
-    elements are required for process nodes. They represent the
-    extremity of the two "arms" which protrude on both sides of the
-    core of the glyph (= square or circle shape). Other glyphs don't
-    need ports (but can use them if desired). The xsd:ID type is an
-    alphanumeric identifier, starting with a letter. Port IDs often
-    contain the ID of their glyph, followed by a local port number
-    (e.g. glyph4.1, glyph4.2, etc.) However, this style convention
-    is not mandatory, and IDs should never be interpreted as
-    carrying any meaning."""
-    subclass = None
-    superclass = SBGNBase
-
-    def __init__(self, notes=None, extension=None, id=None, x=None, y=None):
-        self.original_tagname_ = None
-        super(port, self).__init__(notes, extension, )
-        self.id = _cast(None, id)
-        self.x = _cast(float, x)
-        self.y = _cast(float, y)
-
-    def factory(*args_, **kwargs_):
-        if CurrentSubclassModule_ is not None:
-            subclass = getSubclassFromModule_(
-                CurrentSubclassModule_, port)
-            if subclass is not None:
-                return subclass(*args_, **kwargs_)
-        if port.subclass:
-            return port.subclass(*args_, **kwargs_)
-        else:
-            return port(*args_, **kwargs_)
-    factory = staticmethod(factory)
-
-    def get_id(self): return self.id
-
-    def set_id(self, id): self.id = id
-
-    def get_x(self): return self.x
-
-    def set_x(self, x): self.x = x
-
-    def get_y(self): return self.y
-
-    def set_y(self, y): self.y = y
-
-    def hasContent_(self):
-        if (
-            super(port, self).hasContent_()
-        ):
-            return True
-        else:
-            return False
-
-    def export(self, outfile, level, namespace_='sbgn:', name_='port', namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"', pretty_print=True):
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        if self.original_tagname_ is not None:
-            name_ = self.original_tagname_
-        showIndent(outfile, level, pretty_print)
-        outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
-        already_processed = set()
-        self.exportAttributes(outfile, level, already_processed, namespace_, name_='port')
-        if self.hasContent_():
-            outfile.write('>%s' % (eol_, ))
-            self.exportChildren(outfile, level + 1, namespace_='sbgn:', name_='port', pretty_print=pretty_print)
-            showIndent(outfile, level, pretty_print)
-            outfile.write('</%s%s>%s' % (namespace_, name_, eol_))
-        else:
-            outfile.write('/>%s' % (eol_, ))
-
-    def exportAttributes(self, outfile, level, already_processed, namespace_='sbgn:', name_='port'):
-        super(port, self).exportAttributes(outfile, level, already_processed, namespace_, name_='port')
-        if self.id is not None and 'id' not in already_processed:
-            already_processed.add('id')
-            outfile.write(' id=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.id), input_name='id')), ))
-        if self.x is not None and 'x' not in already_processed:
-            already_processed.add('x')
-            outfile.write(' x="%s"' % self.gds_format_float(self.x, input_name='x'))
-        if self.y is not None and 'y' not in already_processed:
-            already_processed.add('y')
-            outfile.write(' y="%s"' % self.gds_format_float(self.y, input_name='y'))
-
-    def exportChildren(self, outfile, level, namespace_='sbgn:', name_='port', fromsubclass_=False, pretty_print=True):
-        super(port, self).exportChildren(outfile, level, namespace_, name_, True, pretty_print=pretty_print)
-
-    def build(self, node):
-        already_processed = set()
-        self.buildAttributes(node, node.attrib, already_processed)
-        for child in node:
-            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
-            self.buildChildren(child, node, nodeName_)
-        return self
-
-    def buildAttributes(self, node, attrs, already_processed):
-        value = find_attr_value_('id', node)
-        if value is not None and 'id' not in already_processed:
-            already_processed.add('id')
-            self.id = value
-        value = find_attr_value_('x', node)
-        if value is not None and 'x' not in already_processed:
-            already_processed.add('x')
-            try:
-                self.x = float(value)
-            except ValueError as exp:
-                raise ValueError('Bad float/double attribute (x): %s' % exp)
-        value = find_attr_value_('y', node)
-        if value is not None and 'y' not in already_processed:
-            already_processed.add('y')
-            try:
-                self.y = float(value)
-            except ValueError as exp:
-                raise ValueError('Bad float/double attribute (y): %s' % exp)
-        super(port, self).buildAttributes(node, attrs, already_processed)
-
-    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
-        super(port, self).buildChildren(child_, node, nodeName_, True)
-        pass
-# end class port
-
-
-class glyph(SBGNBase):
-    """The glyph element is: either a stand-alone, high-level SBGN glyph
-    (EPN, PN, compartment, etc), or a sub-glyph (state variable,
-    unit of information, inside of a complex, ...) In the first
-    case, it appears directly in the glyph list of the map. In the
-    second case, it is a child of another glyph element. The text
-    inside a glyph is described: either by a label element
-    (optional) [process nodes can't have one], or by a state element
-    (optional) [for state variables only]. The class attribute
-    defines the semantic of the glyph, and influences: the way that
-    glyph should be rendered, the overall syntactic validity of the
-    map. The various classes encompass the following PD SBGN
-    elements: Entity Pool Nodes (EPN), Process Nodes (PN), Logic
-    Operator Nodes, Sub-glyphs on Nodes (State Variable, Unit of
-    Information), Sub-glyphs on Arcs (Stoichiometry Label), Other
-    glyphs (Compartment, Submap, Tag, Terminal). And the following
-    ER SBGN elements Entities (Entity, Outcome) Other (Annotation,
-    Phenotype) Auxiliary on glyps (Existence, Location) Auxiliary on
-    arcs (Cardinality) Delay operator implicit xor The orientation
-    attribute is used to express how to draw asymmetric glyphs. In
-    PD, the orientation of Process Nodes is either horizontal or
-    vertical. It refers to an (imaginary) line connecting the two
-    in/out sides of the PN. In PD, the orientation of Tags and
-    Terminals can be left, right, up or down. It refers to the
-    direction the arrow side of the glyph is pointing at. The xsd:ID
-    type is an alphanumeric identifier, starting with a letter. It
-    is recommended to generate meaningless IDs (e.g. "glyph1234")
-    and avoid IDs with a meaning (e.g. "epn_ethanol") Reference to
-    the ID of the compartment that this glyph is part of. Only use
-    this if there is at least one explicit compartment present in
-    the diagram. Compartments are only used in PD and AF, and thus
-    this attribute as well. For PD, this should be used only for
-    EPN's. In case there are no compartments, entities that can have
-    a location, such as EPN's, are implicit member of an invisible
-    compartment that encompasses the whole map. In that case, this
-    attribute must be omitted. The compartment order attribute can
-    be used to define a drawing order for compartments. It enables
-    tools to draw compartments in the correct order especially in
-    the case of overlapping compartments. Compartments are only used
-    in PD and AF, and thus this attribute as well. The attribute is
-    of type float, the attribute value has not to be unique.
-    Compartments with higher compartment order are drawn on top. The
-    attribute is optional and should only be used for compartments."""
-    subclass = None
-    superclass = SBGNBase
-
-    def __init__(self, notes=None, extension=None, class_=None, orientation=Orientation.HORIZONTAL, id=None, compartmentRef=None, compartmentOrder=None, label=None, state=None, clone=None, callout=None, entity=None, bbox=None, glyph_member=None, port=None):
-        self.original_tagname_ = None
-        super(glyph, self).__init__(notes, extension, )
-        self.set_class(class_)
-        self.set_orientation(orientation)
-        self.id = _cast(None, id)
-        self.compartmentRef = _cast(None, compartmentRef)
-        self.compartmentOrder = _cast(float, compartmentOrder)
-        self.label = label
-        self.state = state
-        self.clone = clone
-        self.callout = callout
-        self.entity = entity
-        self.bbox = bbox
-        if glyph_member is None:
-            self.glyph = []
-        else:
-            self.glyph = glyph_member
-        if port is None:
-            self.port = []
-        else:
-            self.port = port
-
-    def factory(*args_, **kwargs_):
-        if CurrentSubclassModule_ is not None:
-            subclass = getSubclassFromModule_(
-                CurrentSubclassModule_, glyph)
-            if subclass is not None:
-                return subclass(*args_, **kwargs_)
-        if glyph.subclass:
-            return glyph.subclass(*args_, **kwargs_)
-        else:
-            return glyph(*args_, **kwargs_)
-    factory = staticmethod(factory)
-
-    def get_label(self): return self.label
-
-    def set_label(self, label): self.label = label
-
-    def get_state(self): return self.state
-
-    def set_state(self, state): self.state = state
-
-    def get_clone(self): return self.clone
-
-    def set_clone(self, clone): self.clone = clone
-
-    def get_callout(self): return self.callout
-
-    def set_callout(self, callout): self.callout = callout
-
-    def get_entity(self): return self.entity
-
-    def set_entity(self, entity): self.entity = entity
-
-    def get_bbox(self): return self.bbox
-
-    def set_bbox(self, bbox): self.bbox = bbox
-
-    def get_glyph(self): return self.glyph
-
-    def set_glyph(self, glyph): self.glyph = glyph
-
-    def add_glyph(self, value): self.glyph.append(value)
-
-    def insert_glyph_at(self, index, value): self.glyph.insert(index, value)
-
-    def replace_glyph_at(self, index, value): self.glyph[index] = value
-
-    def get_port(self): return self.port
-
-    def set_port(self, port): self.port = port
-
-    def add_port(self, value): self.port.append(value)
-
-    def insert_port_at(self, index, value): self.port.insert(index, value)
-
-    def replace_port_at(self, index, value): self.port[index] = value
-
-    def get_class(self):
-        """ Get the Language.
-        :return: Language instance.
-        """
-        return GlyphClass(self.class_)
-
-    def set_class(self, class_):
-        """ Sets the class and checks that in allowed GlyphClasses
-        :param class_:
-        :return:
-        """
-        if class_ and not isinstance(class_, GlyphClass):
-            raise TypeError('class must be of type GlyphClass')
-        if class_:
-            self.class_ = _cast(None, class_.value)
-        else:
-            self.class_ = _cast(None, class_)
-
-    def get_orientation(self):
-        """ Get orientation.
-        :return: Orientation instance.
-        """
-        return Orientation(self.orientation)
-
-    def set_orientation(self, orientation):
-        """ Sets orientation and checks that allowed Orientation.
-
-        :param orientation:
-        :return:
-        """
-        if not isinstance(orientation, Orientation):
-            raise TypeError('orientation must be of type Orientation')
-        self.orientation = _cast(None, orientation.value)
-
-    def get_id(self): return self.id
-
-    def set_id(self, id): self.id = id
-
-    def get_compartmentRef(self): return self.compartmentRef
-
-    def set_compartmentRef(self, compartmentRef): self.compartmentRef = compartmentRef
-
-    def get_compartmentOrder(self): return self.compartmentOrder
-
-    def set_compartmentOrder(self, compartmentOrder): self.compartmentOrder = compartmentOrder
-
-    def hasContent_(self):
-        if (
-            self.label is not None or
-            self.state is not None or
-            self.clone is not None or
-            self.callout is not None or
-            self.entity is not None or
-            self.bbox is not None or
-            self.glyph or
-            self.port or
-            super(glyph, self).hasContent_()
-        ):
-            return True
-        else:
-            return False
-
-    def export(self, outfile, level, namespace_='sbgn:', name_='glyph', namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"', pretty_print=True):
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        if self.original_tagname_ is not None:
-            name_ = self.original_tagname_
-        showIndent(outfile, level, pretty_print)
-        outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
-        already_processed = set()
-        self.exportAttributes(outfile, level, already_processed, namespace_, name_='glyph')
-        if self.hasContent_():
-            outfile.write('>%s' % (eol_, ))
-            self.exportChildren(outfile, level + 1, namespace_='sbgn:', name_='glyph', pretty_print=pretty_print)
-            showIndent(outfile, level, pretty_print)
-            outfile.write('</%s%s>%s' % (namespace_, name_, eol_))
-        else:
-            outfile.write('/>%s' % (eol_, ))
-
-    def exportAttributes(self, outfile, level, already_processed, namespace_='sbgn:', name_='glyph'):
-        super(glyph, self).exportAttributes(outfile, level, already_processed, namespace_, name_='glyph')
-        if self.class_ is not None and 'class_' not in already_processed:
-            already_processed.add('class_')
-            outfile.write(' class=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.class_), input_name='class')), ))
-        if self.orientation != "horizontal" and 'orientation' not in already_processed:
-            already_processed.add('orientation')
-            outfile.write(' orientation=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.orientation), input_name='orientation')), ))
-        if self.id is not None and 'id' not in already_processed:
-            already_processed.add('id')
-            outfile.write(' id=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.id), input_name='id')), ))
-        if self.compartmentRef is not None and 'compartmentRef' not in already_processed:
-            already_processed.add('compartmentRef')
-            outfile.write(' compartmentRef=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.compartmentRef), input_name='compartmentRef')), ))
-        if self.compartmentOrder is not None and 'compartmentOrder' not in already_processed:
-            already_processed.add('compartmentOrder')
-            outfile.write(' compartmentOrder="%s"' % self.gds_format_float(self.compartmentOrder, input_name='compartmentOrder'))
-
-    def exportChildren(self, outfile, level, namespace_='sbgn:', name_='glyph', fromsubclass_=False, pretty_print=True):
-        super(glyph, self).exportChildren(outfile, level, namespace_, name_, True, pretty_print=pretty_print)
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        if self.label is not None:
-            self.label.export(outfile, level, namespace_='sbgn:', name_='label', pretty_print=pretty_print)
-        if self.state is not None:
-            self.state.export(outfile, level, namespace_, name_='state', pretty_print=pretty_print)
-        if self.clone is not None:
-            self.clone.export(outfile, level, namespace_, name_='clone', pretty_print=pretty_print)
-        if self.callout is not None:
-            self.callout.export(outfile, level, namespace_, name_='callout', pretty_print=pretty_print)
-        if self.entity is not None:
-            self.entity.export(outfile, level, namespace_, name_='entity', pretty_print=pretty_print)
-        if self.bbox is not None:
-            self.bbox.export(outfile, level, namespace_='sbgn:', name_='bbox', pretty_print=pretty_print)
-        for glyph_ in self.glyph:
-            glyph_.export(outfile, level, namespace_='sbgn:', name_='glyph', pretty_print=pretty_print)
-        for port_ in self.port:
-            port_.export(outfile, level, namespace_='sbgn:', name_='port', pretty_print=pretty_print)
-
-    def build(self, node):
-        already_processed = set()
-        self.buildAttributes(node, node.attrib, already_processed)
-        for child in node:
-            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
-            self.buildChildren(child, node, nodeName_)
-        return self
-
-    def buildAttributes(self, node, attrs, already_processed):
-        value = find_attr_value_('class', node)
-        if value is not None and 'class' not in already_processed:
-            already_processed.add('class')
-            self.class_ = value
-        value = find_attr_value_('orientation', node)
-        if value is not None and 'orientation' not in already_processed:
-            already_processed.add('orientation')
-            self.orientation = value
-        value = find_attr_value_('id', node)
-        if value is not None and 'id' not in already_processed:
-            already_processed.add('id')
-            self.id = value
-        value = find_attr_value_('compartmentRef', node)
-        if value is not None and 'compartmentRef' not in already_processed:
-            already_processed.add('compartmentRef')
-            self.compartmentRef = value
-        value = find_attr_value_('compartmentOrder', node)
-        if value is not None and 'compartmentOrder' not in already_processed:
-            already_processed.add('compartmentOrder')
-            try:
-                self.compartmentOrder = float(value)
-            except ValueError as exp:
-                raise ValueError('Bad float/double attribute (compartmentOrder): %s' % exp)
-        super(glyph, self).buildAttributes(node, attrs, already_processed)
-
-    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
-        if nodeName_ == 'label':
-            obj_ = label.factory()
-            obj_.build(child_)
-            self.label = obj_
-            obj_.original_tagname_ = 'label'
-        elif nodeName_ == 'state':
-            obj_ = stateType.factory()
-            obj_.build(child_)
-            self.state = obj_
-            obj_.original_tagname_ = 'state'
-        elif nodeName_ == 'clone':
-            obj_ = cloneType.factory()
-            obj_.build(child_)
-            self.clone = obj_
-            obj_.original_tagname_ = 'clone'
-        elif nodeName_ == 'callout':
-            obj_ = calloutType.factory()
-            obj_.build(child_)
-            self.callout = obj_
-            obj_.original_tagname_ = 'callout'
-        elif nodeName_ == 'entity':
-            obj_ = entityType.factory()
-            obj_.build(child_)
-            self.entity = obj_
-            obj_.original_tagname_ = 'entity'
-        elif nodeName_ == 'bbox':
-            obj_ = bbox.factory()
-            obj_.build(child_)
-            self.bbox = obj_
-            obj_.original_tagname_ = 'bbox'
-        elif nodeName_ == 'glyph':
-            obj_ = glyph.factory()
-            obj_.build(child_)
-            self.glyph.append(obj_)
-            obj_.original_tagname_ = 'glyph'
-        elif nodeName_ == 'port':
-            obj_ = port.factory()
-            obj_.build(child_)
-            self.port.append(obj_)
-            obj_.original_tagname_ = 'port'
-        super(glyph, self).buildChildren(child_, node, nodeName_, True)
-# end class glyph
-
-
-class arcgroup(SBGNBase):
-    """The arc group describes a set of arcs and glyphs that together have
-    a relation. For example For ER: interaction arcs around an
-    interaction glyph, ... Note that, in spite of the name, an
-    arcgroup contains both arcs and glyphs. The class attribute
-    defines the semantic of the arcgroup."""
-    subclass = None
-    superclass = SBGNBase
-
-    def __init__(self, notes=None, extension=None, class_=None, glyph=None, arc=None):
-        self.original_tagname_ = None
-        super(arcgroup, self).__init__(notes, extension, )
-        self.class_ = _cast(None, class_)
-        if glyph is None:
-            self.glyph = []
-        else:
-            self.glyph = glyph
-        if arc is None:
-            self.arc = []
-        else:
-            self.arc = arc
-
-    def factory(*args_, **kwargs_):
-        if CurrentSubclassModule_ is not None:
-            subclass = getSubclassFromModule_(
-                CurrentSubclassModule_, arcgroup)
-            if subclass is not None:
-                return subclass(*args_, **kwargs_)
-        if arcgroup.subclass:
-            return arcgroup.subclass(*args_, **kwargs_)
-        else:
-            return arcgroup(*args_, **kwargs_)
-    factory = staticmethod(factory)
-
-    def get_glyph(self): return self.glyph
-
-    def set_glyph(self, glyph): self.glyph = glyph
-
-    def add_glyph(self, value): self.glyph.append(value)
-
-    def insert_glyph_at(self, index, value): self.glyph.insert(index, value)
-
-    def replace_glyph_at(self, index, value): self.glyph[index] = value
-
-    def get_arc(self): return self.arc
-
-    def set_arc(self, arc): self.arc = arc
-
-    def add_arc(self, value): self.arc.append(value)
-
-    def insert_arc_at(self, index, value): self.arc.insert(index, value)
-
-    def replace_arc_at(self, index, value): self.arc[index] = value
-
-    def get_class(self): return self.class_
-
-    def set_class(self, class_): self.class_ = class_
-
-    def hasContent_(self):
-        if (
-            self.glyph or
-            self.arc or
-            super(arcgroup, self).hasContent_()
-        ):
-            return True
-        else:
-            return False
-
-    def export(self, outfile, level, namespace_='sbgn:', name_='arcgroup', namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"', pretty_print=True):
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        if self.original_tagname_ is not None:
-            name_ = self.original_tagname_
-        showIndent(outfile, level, pretty_print)
-        outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
-        already_processed = set()
-        self.exportAttributes(outfile, level, already_processed, namespace_, name_='arcgroup')
-        if self.hasContent_():
-            outfile.write('>%s' % (eol_, ))
-            self.exportChildren(outfile, level + 1, namespace_='sbgn:', name_='arcgroup', pretty_print=pretty_print)
-            showIndent(outfile, level, pretty_print)
-            outfile.write('</%s%s>%s' % (namespace_, name_, eol_))
-        else:
-            outfile.write('/>%s' % (eol_, ))
-
-    def exportAttributes(self, outfile, level, already_processed, namespace_='sbgn:', name_='arcgroup'):
-        super(arcgroup, self).exportAttributes(outfile, level, already_processed, namespace_, name_='arcgroup')
-        if self.class_ is not None and 'class_' not in already_processed:
-            already_processed.add('class_')
-            outfile.write(' class=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.class_), input_name='class')), ))
-
-    def exportChildren(self, outfile, level, namespace_='sbgn:', name_='arcgroup', fromsubclass_=False, pretty_print=True):
-        super(arcgroup, self).exportChildren(outfile, level, namespace_, name_, True, pretty_print=pretty_print)
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        for glyph_ in self.glyph:
-            glyph_.export(outfile, level, namespace_='sbgn:', name_='glyph', pretty_print=pretty_print)
-        for arc_ in self.arc:
-            arc_.export(outfile, level, namespace_='sbgn:', name_='arc', pretty_print=pretty_print)
-
-    def build(self, node):
-        already_processed = set()
-        self.buildAttributes(node, node.attrib, already_processed)
-        for child in node:
-            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
-            self.buildChildren(child, node, nodeName_)
-        return self
-
-    def buildAttributes(self, node, attrs, already_processed):
-        value = find_attr_value_('class', node)
-        if value is not None and 'class' not in already_processed:
-            already_processed.add('class')
-            self.class_ = value
-        super(arcgroup, self).buildAttributes(node, attrs, already_processed)
-
-    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
-        if nodeName_ == 'glyph':
-            obj_ = glyph.factory()
-            obj_.build(child_)
-            self.glyph.append(obj_)
-            obj_.original_tagname_ = 'glyph'
-        elif nodeName_ == 'arc':
-            obj_ = arc.factory()
-            obj_.build(child_)
-            self.arc.append(obj_)
-            obj_.original_tagname_ = 'arc'
-        super(arcgroup, self).buildChildren(child_, node, nodeName_, True)
-# end class arcgroup
-
-
-class arc(SBGNBase):
-    """The arc element describes an SBGN arc between two SBGN nodes. It
-    contains: For PD: an optional stoichiometry marker, For ER: an
-    optional cardinality marker, zero or more ports (influence
-    targets), and zero or more outcomes, a mandatory source and
-    target (glyph or port), a geometric description of its whole
-    path, from start to end. This path can involve any number of
-    straight lines or quadratic/cubic Bezier curves. The class
-    attribute defines the semantic of the arc, and influences: the
-    way that arc should be rendered, the overall syntactic validity
-    of the map. The various classes encompass all possible types of
-    SBGN arcs: production and consumption arcs, all types of
-    modification arcs, logic arcs, equivalence arcs. To express a
-    reversible reaction, use production arcs on both sides of the
-    Process Node. The xsd:ID type is an alphanumeric identifier,
-    starting with a letter. The source attribute can refer: either
-    to the id of a glyph, or to the id of a port on a glyph. The
-    target attribute can refer: either to the id of a glyph, or to
-    the id of a port on a glyph."""
-    subclass = None
-    superclass = SBGNBase
-
-    def __init__(self, notes=None, extension=None, class_=None, id=None, source=None, target=None, glyph=None, port=None, start=None, next=None, end=None):
-        self.original_tagname_ = None
-        super(arc, self).__init__(notes, extension, )
-        self.set_class(class_)
-        self.id = _cast(None, id)
-        self.source = _cast(None, source)
-        self.target = _cast(None, target)
-        if glyph is None:
-            self.glyph = []
-        else:
-            self.glyph = glyph
-        if port is None:
-            self.port = []
-        else:
-            self.port = port
-        self.start = start
-        if next is None:
-            self.next = []
-        else:
-            self.next = next
-        self.end = end
-
-    def factory(*args_, **kwargs_):
-        if CurrentSubclassModule_ is not None:
-            subclass = getSubclassFromModule_(
-                CurrentSubclassModule_, arc)
-            if subclass is not None:
-                return subclass(*args_, **kwargs_)
-        if arc.subclass:
-            return arc.subclass(*args_, **kwargs_)
-        else:
-            return arc(*args_, **kwargs_)
-    factory = staticmethod(factory)
-
-    def get_glyph(self): return self.glyph
-
-    def set_glyph(self, glyph): self.glyph = glyph
-
-    def add_glyph(self, value): self.glyph.append(value)
-
-    def insert_glyph_at(self, index, value): self.glyph.insert(index, value)
-
-    def replace_glyph_at(self, index, value): self.glyph[index] = value
-
-    def get_port(self): return self.port
-
-    def set_port(self, port): self.port = port
-
-    def add_port(self, value): self.port.append(value)
-
-    def insert_port_at(self, index, value): self.port.insert(index, value)
-
-    def replace_port_at(self, index, value): self.port[index] = value
-
-    def get_start(self): return self.start
-
-    def set_start(self, start): self.start = start
-
-    def get_next(self): return self.next
-
-    def set_next(self, next): self.next = next
-
-    def add_next(self, value): self.next.append(value)
-
-    def insert_next_at(self, index, value): self.next.insert(index, value)
-
-    def replace_next_at(self, index, value): self.next[index] = value
-
-    def get_end(self): return self.end
-
-    def set_end(self, end): self.end = end
-
-    def get_class(self):
-        """ Get the ArcClass. """
-        return ArcClass(self.class_)
-
-    def set_class(self, class_):
-        """ Set the ArcClass.
-        :param class_:
-        :return:
-        """
-        if class_ and not isinstance(class_, ArcClass):
-            raise TypeError('class must be of type ArcClass')
-        if class_:
-            self.class_ = _cast(None, class_.value)
-        else:
-            self.class_ = _cast(None, class_)
-
-    def get_id(self): return self.id
-
-    def set_id(self, id): self.id = id
-
-    def get_source(self): return self.source
-
-    def set_source(self, source): self.source = source
-
-    def get_target(self): return self.target
-
-    def set_target(self, target): self.target = target
-
-    def hasContent_(self):
-        if (
-            self.glyph or
-            self.port or
-            self.start is not None or
-            self.next or
-            self.end is not None or
-            super(arc, self).hasContent_()
-        ):
-            return True
-        else:
-            return False
-
-    def export(self, outfile, level, namespace_='sbgn:', name_='arc', namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"', pretty_print=True):
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        if self.original_tagname_ is not None:
-            name_ = self.original_tagname_
-        showIndent(outfile, level, pretty_print)
-        outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
-        already_processed = set()
-        self.exportAttributes(outfile, level, already_processed, namespace_, name_='arc')
-        if self.hasContent_():
-            outfile.write('>%s' % (eol_, ))
-            self.exportChildren(outfile, level + 1, namespace_='sbgn:', name_='arc', pretty_print=pretty_print)
-            showIndent(outfile, level, pretty_print)
-            outfile.write('</%s%s>%s' % (namespace_, name_, eol_))
-        else:
-            outfile.write('/>%s' % (eol_, ))
-
-    def exportAttributes(self, outfile, level, already_processed, namespace_='sbgn:', name_='arc'):
-        super(arc, self).exportAttributes(outfile, level, already_processed, namespace_, name_='arc')
-        if self.class_ is not None and 'class_' not in already_processed:
-            already_processed.add('class_')
-            outfile.write(' class=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.class_), input_name='class')), ))
-        if self.id is not None and 'id' not in already_processed:
-            already_processed.add('id')
-            outfile.write(' id=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.id), input_name='id')), ))
-        if self.source is not None and 'source' not in already_processed:
-            already_processed.add('source')
-            outfile.write(' source=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.source), input_name='source')), ))
-        if self.target is not None and 'target' not in already_processed:
-            already_processed.add('target')
-            outfile.write(' target=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.target), input_name='target')), ))
-
-    def exportChildren(self, outfile, level, namespace_='sbgn:', name_='arc', fromsubclass_=False, pretty_print=True):
-        super(arc, self).exportChildren(outfile, level, namespace_, name_, True, pretty_print=pretty_print)
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        for glyph_ in self.glyph:
-            glyph_.export(outfile, level, namespace_='sbgn:', name_='glyph', pretty_print=pretty_print)
-        for port_ in self.port:
-            port_.export(outfile, level, namespace_='sbgn:', name_='port', pretty_print=pretty_print)
-        if self.start is not None:
-            self.start.export(outfile, level, namespace_, name_='start', pretty_print=pretty_print)
-        for next_ in self.next:
-            next_.export(outfile, level, namespace_, name_='next', pretty_print=pretty_print)
-        if self.end is not None:
-            self.end.export(outfile, level, namespace_, name_='end', pretty_print=pretty_print)
-
-    def build(self, node):
-        already_processed = set()
-        self.buildAttributes(node, node.attrib, already_processed)
-        for child in node:
-            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
-            self.buildChildren(child, node, nodeName_)
-        return self
-
-    def buildAttributes(self, node, attrs, already_processed):
-        value = find_attr_value_('class', node)
-        if value is not None and 'class' not in already_processed:
-            already_processed.add('class')
-            self.class_ = value
-        value = find_attr_value_('id', node)
-        if value is not None and 'id' not in already_processed:
-            already_processed.add('id')
-            self.id = value
-        value = find_attr_value_('source', node)
-        if value is not None and 'source' not in already_processed:
-            already_processed.add('source')
-            self.source = value
-        value = find_attr_value_('target', node)
-        if value is not None and 'target' not in already_processed:
-            already_processed.add('target')
-            self.target = value
-        super(arc, self).buildAttributes(node, attrs, already_processed)
-
-    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
-        if nodeName_ == 'glyph':
-            obj_ = glyph.factory()
-            obj_.build(child_)
-            self.glyph.append(obj_)
-            obj_.original_tagname_ = 'glyph'
-        elif nodeName_ == 'port':
-            obj_ = port.factory()
-            obj_.build(child_)
-            self.port.append(obj_)
-            obj_.original_tagname_ = 'port'
-        elif nodeName_ == 'start':
-            obj_ = startType.factory()
-            obj_.build(child_)
-            self.start = obj_
-            obj_.original_tagname_ = 'start'
-        elif nodeName_ == 'next':
-            obj_ = nextType.factory()
-            obj_.build(child_)
-            self.next.append(obj_)
-            obj_.original_tagname_ = 'next'
-        elif nodeName_ == 'end':
-            obj_ = endType.factory()
-            obj_.build(child_)
-            self.end = obj_
-            obj_.original_tagname_ = 'end'
-        super(arc, self).buildChildren(child_, node, nodeName_, True)
-# end class arc
-
-
-class notesType(GeneratedsSuper):
-    subclass = None
-    superclass = None
-
-    def __init__(self, anytypeobjs_=None):
-        self.original_tagname_ = None
-        if anytypeobjs_ is None:
-            self.anytypeobjs_ = []
-        else:
-            self.anytypeobjs_ = anytypeobjs_
-
-    def factory(*args_, **kwargs_):
-        if CurrentSubclassModule_ is not None:
-            subclass = getSubclassFromModule_(
-                CurrentSubclassModule_, notesType)
-            if subclass is not None:
-                return subclass(*args_, **kwargs_)
-        if notesType.subclass:
-            return notesType.subclass(*args_, **kwargs_)
-        else:
-            return notesType(*args_, **kwargs_)
-    factory = staticmethod(factory)
-
-    def get_anytypeobjs_(self): return self.anytypeobjs_
-
-    def set_anytypeobjs_(self, anytypeobjs_): self.anytypeobjs_ = anytypeobjs_
-
-    def add_anytypeobjs_(self, value): self.anytypeobjs_.append(value)
-
-    def insert_anytypeobjs_(self, index, value): self._anytypeobjs_[index] = value
-
-    def hasContent_(self):
-        if (
-            self.anytypeobjs_
-        ):
-            return True
-        else:
-            return False
-
-    def export(self, outfile, level, namespace_='sbgn:', name_='notesType', namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"', pretty_print=True):
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        if self.original_tagname_ is not None:
-            name_ = self.original_tagname_
-        showIndent(outfile, level, pretty_print)
-        outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
-        already_processed = set()
-        self.exportAttributes(outfile, level, already_processed, namespace_, name_='notesType')
-        if self.hasContent_():
-            outfile.write('>%s' % (eol_, ))
-            self.exportChildren(outfile, level + 1, namespace_='sbgn:', name_='notesType', pretty_print=pretty_print)
-            showIndent(outfile, level, pretty_print)
-            outfile.write('</%s%s>%s' % (namespace_, name_, eol_))
-        else:
-            outfile.write('/>%s' % (eol_, ))
-
-    def exportAttributes(self, outfile, level, already_processed, namespace_='sbgn:', name_='notesType'):
-        pass
-
-    def exportChildren(self, outfile, level, namespace_='sbgn:', name_='notesType', fromsubclass_=False, pretty_print=True):
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        for obj_ in self.anytypeobjs_:
-            obj_.export(outfile, level, namespace_, pretty_print=pretty_print)
-
-    def build(self, node):
-        already_processed = set()
-        self.buildAttributes(node, node.attrib, already_processed)
-        for child in node:
-            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
-            self.buildChildren(child, node, nodeName_)
-        return self
-
-    def buildAttributes(self, node, attrs, already_processed):
-        pass
-
-    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
-        obj_ = self.gds_build_any(child_, 'notesType')
-        if obj_ is not None:
-            self.add_anytypeobjs_(obj_)
-# end class notesType
-
-
-class extensionType(GeneratedsSuper):
-    subclass = None
-    superclass = None
-
-    def __init__(self, anytypeobjs_=None):
-        self.original_tagname_ = None
-        if anytypeobjs_ is None:
-            self.anytypeobjs_ = []
-        else:
-            self.anytypeobjs_ = anytypeobjs_
-
-    def factory(*args_, **kwargs_):
-        if CurrentSubclassModule_ is not None:
-            subclass = getSubclassFromModule_(
-                CurrentSubclassModule_, extensionType)
-            if subclass is not None:
-                return subclass(*args_, **kwargs_)
-        if extensionType.subclass:
-            return extensionType.subclass(*args_, **kwargs_)
-        else:
-            return extensionType(*args_, **kwargs_)
-    factory = staticmethod(factory)
-
-    def get_anytypeobjs_(self): return self.anytypeobjs_
-
-    def set_anytypeobjs_(self, anytypeobjs_): self.anytypeobjs_ = anytypeobjs_
-
-    def add_anytypeobjs_(self, value): self.anytypeobjs_.append(value)
-
-    def insert_anytypeobjs_(self, index, value): self._anytypeobjs_[index] = value
-
-    def hasContent_(self):
-        if (
-            self.anytypeobjs_
-        ):
-            return True
-        else:
-            return False
-
-    def export(self, outfile, level, namespace_='sbgn:', name_='extensionType', namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"', pretty_print=True):
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        if self.original_tagname_ is not None:
-            name_ = self.original_tagname_
-        showIndent(outfile, level, pretty_print)
-        outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
-        already_processed = set()
-        self.exportAttributes(outfile, level, already_processed, namespace_, name_='extensionType')
-        if self.hasContent_():
-            outfile.write('>%s' % (eol_, ))
-            self.exportChildren(outfile, level + 1, namespace_='sbgn:', name_='extensionType', pretty_print=pretty_print)
-            showIndent(outfile, level, pretty_print)
-            outfile.write('</%s%s>%s' % (namespace_, name_, eol_))
-        else:
-            outfile.write('/>%s' % (eol_, ))
-
-    def exportAttributes(self, outfile, level, already_processed, namespace_='sbgn:', name_='extensionType'):
-        pass
-
-    def exportChildren(self, outfile, level, namespace_='sbgn:', name_='extensionType', fromsubclass_=False, pretty_print=True):
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        for obj_ in self.anytypeobjs_:
-            obj_.export(outfile, level, namespace_, pretty_print=pretty_print)
-
-    def build(self, node):
-        already_processed = set()
-        self.buildAttributes(node, node.attrib, already_processed)
-        for child in node:
-            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
-            self.buildChildren(child, node, nodeName_)
-        return self
-
-    def buildAttributes(self, node, attrs, already_processed):
-        pass
-
-    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
-        obj_ = self.gds_build_any(child_, 'extensionType')
-        if obj_ is not None:
-            self.add_anytypeobjs_(obj_)
-# end class extensionType
-
-
-class stateType(GeneratedsSuper):
-    """The value attribute represents the state of the variable. It can be:
-    either from a predefined set of string (P, S, etc.) which
-    correspond to specific SBO terms (cf. SBGN specs), or any
-    arbitrary string. The variable attribute describes the site
-    where the modification described by the value attribute occurs.
-    It is: optional when there is only one state variable on the
-    parent EPN, required when there is more than one state variable
-    the parent EPN."""
-    subclass = None
-    superclass = None
-
-    def __init__(self, value=None, variable=None):
-        self.original_tagname_ = None
-        self.value = _cast(None, value)
-        self.variable = _cast(None, variable)
-
-    def factory(*args_, **kwargs_):
-        if CurrentSubclassModule_ is not None:
-            subclass = getSubclassFromModule_(
-                CurrentSubclassModule_, stateType)
-            if subclass is not None:
-                return subclass(*args_, **kwargs_)
-        if stateType.subclass:
-            return stateType.subclass(*args_, **kwargs_)
-        else:
-            return stateType(*args_, **kwargs_)
-    factory = staticmethod(factory)
-
-    def get_value(self): return self.value
-
-    def set_value(self, value): self.value = value
-
-    def get_variable(self): return self.variable
-
-    def set_variable(self, variable): self.variable = variable
-
-    def hasContent_(self):
-        if (
-
-        ):
-            return True
-        else:
-            return False
-
-    def export(self, outfile, level, namespace_='sbgn:', name_='stateType', namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"', pretty_print=True):
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        if self.original_tagname_ is not None:
-            name_ = self.original_tagname_
-        showIndent(outfile, level, pretty_print)
-        outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
-        already_processed = set()
-        self.exportAttributes(outfile, level, already_processed, namespace_, name_='stateType')
-        if self.hasContent_():
-            outfile.write('>%s' % (eol_, ))
-            self.exportChildren(outfile, level + 1, namespace_='sbgn:', name_='stateType', pretty_print=pretty_print)
-            outfile.write('</%s%s>%s' % (namespace_, name_, eol_))
-        else:
-            outfile.write('/>%s' % (eol_, ))
-
-    def exportAttributes(self, outfile, level, already_processed, namespace_='sbgn:', name_='stateType'):
-        if self.value is not None and 'value' not in already_processed:
-            already_processed.add('value')
-            outfile.write(' value=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.value), input_name='value')), ))
-        if self.variable is not None and 'variable' not in already_processed:
-            already_processed.add('variable')
-            outfile.write(' variable=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.variable), input_name='variable')), ))
-
-    def exportChildren(self, outfile, level, namespace_='sbgn:', name_='stateType', fromsubclass_=False, pretty_print=True):
-        pass
-
-    def build(self, node):
-        already_processed = set()
-        self.buildAttributes(node, node.attrib, already_processed)
-        for child in node:
-            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
-            self.buildChildren(child, node, nodeName_)
-        return self
-
-    def buildAttributes(self, node, attrs, already_processed):
-        value = find_attr_value_('value', node)
-        if value is not None and 'value' not in already_processed:
-            already_processed.add('value')
-            self.value = value
-        value = find_attr_value_('variable', node)
-        if value is not None and 'variable' not in already_processed:
-            already_processed.add('variable')
-            self.variable = value
-
-    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
-        pass
-# end class stateType
-
-
-class cloneType(GeneratedsSuper):
-    subclass = None
-    superclass = None
-
-    def __init__(self, label=None):
-        self.original_tagname_ = None
-        self.label = label
-
-    def factory(*args_, **kwargs_):
-        if CurrentSubclassModule_ is not None:
-            subclass = getSubclassFromModule_(
-                CurrentSubclassModule_, cloneType)
-            if subclass is not None:
-                return subclass(*args_, **kwargs_)
-        if cloneType.subclass:
-            return cloneType.subclass(*args_, **kwargs_)
-        else:
-            return cloneType(*args_, **kwargs_)
-    factory = staticmethod(factory)
-
-    def get_label(self): return self.label
-
-    def set_label(self, label): self.label = label
-
-    def hasContent_(self):
-        if (
-            self.label is not None
-        ):
-            return True
-        else:
-            return False
-
-    def export(self, outfile, level, namespace_='sbgn:', name_='cloneType', namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"', pretty_print=True):
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        if self.original_tagname_ is not None:
-            name_ = self.original_tagname_
-        showIndent(outfile, level, pretty_print)
-        outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
-        already_processed = set()
-        self.exportAttributes(outfile, level, already_processed, namespace_, name_='cloneType')
-        if self.hasContent_():
-            outfile.write('>%s' % (eol_, ))
-            self.exportChildren(outfile, level + 1, namespace_='sbgn:', name_='cloneType', pretty_print=pretty_print)
-            showIndent(outfile, level, pretty_print)
-            outfile.write('</%s%s>%s' % (namespace_, name_, eol_))
-        else:
-            outfile.write('/>%s' % (eol_, ))
-
-    def exportAttributes(self, outfile, level, already_processed, namespace_='sbgn:', name_='cloneType'):
-        pass
-
-    def exportChildren(self, outfile, level, namespace_='sbgn:', name_='cloneType', fromsubclass_=False, pretty_print=True):
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        if self.label is not None:
-            self.label.export(outfile, level, namespace_='sbgn:', name_='label', pretty_print=pretty_print)
-
-    def build(self, node):
-        already_processed = set()
-        self.buildAttributes(node, node.attrib, already_processed)
-        for child in node:
-            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
-            self.buildChildren(child, node, nodeName_)
-        return self
-
-    def buildAttributes(self, node, attrs, already_processed):
-        pass
-
-    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
-        if nodeName_ == 'label':
-            obj_ = label.factory()
-            obj_.build(child_)
-            self.label = obj_
-            obj_.original_tagname_ = 'label'
-# end class cloneType
-
-
-class calloutType(GeneratedsSuper):
-    subclass = None
-    superclass = None
-
-    def __init__(self, target=None, point=None):
-        self.original_tagname_ = None
-        self.target = _cast(None, target)
-        self.point = point
-
-    def factory(*args_, **kwargs_):
-        if CurrentSubclassModule_ is not None:
-            subclass = getSubclassFromModule_(
-                CurrentSubclassModule_, calloutType)
-            if subclass is not None:
-                return subclass(*args_, **kwargs_)
-        if calloutType.subclass:
-            return calloutType.subclass(*args_, **kwargs_)
-        else:
-            return calloutType(*args_, **kwargs_)
-    factory = staticmethod(factory)
-
-    def get_point(self): return self.point
-
-    def set_point(self, point): self.point = point
-
-    def get_target(self): return self.target
-
-    def set_target(self, target): self.target = target
-
-    def set_target(self, target):
-        if isinstance(target, glyph):
-            self.target = target.get_id()
-        else:
-            self.target = target
-
-    def hasContent_(self):
-        if (
-            self.point is not None
-        ):
-            return True
-        else:
-            return False
-
-    def export(self, outfile, level, namespace_='sbgn:', name_='calloutType', namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"', pretty_print=True):
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        if self.original_tagname_ is not None:
-            name_ = self.original_tagname_
-        showIndent(outfile, level, pretty_print)
-        outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
-        already_processed = set()
-        self.exportAttributes(outfile, level, already_processed, namespace_, name_='calloutType')
-        if self.hasContent_():
-            outfile.write('>%s' % (eol_, ))
-            self.exportChildren(outfile, level + 1, namespace_='sbgn:', name_='calloutType', pretty_print=pretty_print)
-            showIndent(outfile, level, pretty_print)
-            outfile.write('</%s%s>%s' % (namespace_, name_, eol_))
-        else:
-            outfile.write('/>%s' % (eol_, ))
-
-    def exportAttributes(self, outfile, level, already_processed, namespace_='sbgn:', name_='calloutType'):
-        if self.target is not None and 'target' not in already_processed:
-            already_processed.add('target')
-            outfile.write(' target=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.target), input_name='target')), ))
-
-    def exportChildren(self, outfile, level, namespace_='sbgn:', name_='calloutType', fromsubclass_=False, pretty_print=True):
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        if self.point is not None:
-            self.point.export(outfile, level, namespace_='sbgn:', name_='point', pretty_print=pretty_print)
-
-    def build(self, node):
-        already_processed = set()
-        self.buildAttributes(node, node.attrib, already_processed)
-        for child in node:
-            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
-            self.buildChildren(child, node, nodeName_)
-        return self
-
-    def buildAttributes(self, node, attrs, already_processed):
-        value = find_attr_value_('target', node)
-        if value is not None and 'target' not in already_processed:
-            already_processed.add('target')
-            self.target = value
-
-    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
-        if nodeName_ == 'point':
-            obj_ = point.factory()
-            obj_.build(child_)
-            self.point = obj_
-            obj_.original_tagname_ = 'point'
-# end class calloutType
-
-
-class entityType(GeneratedsSuper):
-    subclass = None
-    superclass = None
-
-    def __init__(self, name=None):
-        self.original_tagname_ = None
-        self.name = _cast(None, name)
-
-    def factory(*args_, **kwargs_):
-        if CurrentSubclassModule_ is not None:
-            subclass = getSubclassFromModule_(
-                CurrentSubclassModule_, entityType)
-            if subclass is not None:
-                return subclass(*args_, **kwargs_)
-        if entityType.subclass:
-            return entityType.subclass(*args_, **kwargs_)
-        else:
-            return entityType(*args_, **kwargs_)
-    factory = staticmethod(factory)
-
-    def get_name(self): return self.name
-
-    def set_name(self, name): self.name = name
-
-    def hasContent_(self):
-        if (
-
-        ):
-            return True
-        else:
-            return False
-
-    def export(self, outfile, level, namespace_='sbgn:', name_='entityType', namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"', pretty_print=True):
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        if self.original_tagname_ is not None:
-            name_ = self.original_tagname_
-        showIndent(outfile, level, pretty_print)
-        outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
-        already_processed = set()
-        self.exportAttributes(outfile, level, already_processed, namespace_, name_='entityType')
-        if self.hasContent_():
-            outfile.write('>%s' % (eol_, ))
-            self.exportChildren(outfile, level + 1, namespace_='sbgn:', name_='entityType', pretty_print=pretty_print)
-            outfile.write('</%s%s>%s' % (namespace_, name_, eol_))
-        else:
-            outfile.write('/>%s' % (eol_, ))
-
-    def exportAttributes(self, outfile, level, already_processed, namespace_='sbgn:', name_='entityType'):
-        if self.name is not None and 'name' not in already_processed:
-            already_processed.add('name')
-            outfile.write(' name=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.name), input_name='name')), ))
-
-    def exportChildren(self, outfile, level, namespace_='sbgn:', name_='entityType', fromsubclass_=False, pretty_print=True):
-        pass
-
-    def build(self, node):
-        already_processed = set()
-        self.buildAttributes(node, node.attrib, already_processed)
-        for child in node:
-            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
-            self.buildChildren(child, node, nodeName_)
-        return self
-
-    def buildAttributes(self, node, attrs, already_processed):
-        value = find_attr_value_('name', node)
-        if value is not None and 'name' not in already_processed:
-            already_processed.add('name')
-            self.name = value
-
-    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
-        pass
-# end class entityType
-
-
-class startType(GeneratedsSuper):
-    subclass = None
-    superclass = None
-
-    def __init__(self, x=None, y=None):
-        self.original_tagname_ = None
-        self.x = _cast(float, x)
-        self.y = _cast(float, y)
-
-    def factory(*args_, **kwargs_):
-        if CurrentSubclassModule_ is not None:
-            subclass = getSubclassFromModule_(
-                CurrentSubclassModule_, startType)
-            if subclass is not None:
-                return subclass(*args_, **kwargs_)
-        if startType.subclass:
-            return startType.subclass(*args_, **kwargs_)
-        else:
-            return startType(*args_, **kwargs_)
-    factory = staticmethod(factory)
-
-    def get_x(self): return self.x
-
-    def set_x(self, x): self.x = x
-
-    def get_y(self): return self.y
-
-    def set_y(self, y): self.y = y
-
-    def hasContent_(self):
-        if (
-
-        ):
-            return True
-        else:
-            return False
-
-    def export(self, outfile, level, namespace_='sbgn:', name_='startType', namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"', pretty_print=True):
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        if self.original_tagname_ is not None:
-            name_ = self.original_tagname_
-        showIndent(outfile, level, pretty_print)
-        outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
-        already_processed = set()
-        self.exportAttributes(outfile, level, already_processed, namespace_, name_='startType')
-        if self.hasContent_():
-            outfile.write('>%s' % (eol_, ))
-            self.exportChildren(outfile, level + 1, namespace_='sbgn:', name_='startType', pretty_print=pretty_print)
-            outfile.write('</%s%s>%s' % (namespace_, name_, eol_))
-        else:
-            outfile.write('/>%s' % (eol_, ))
-
-    def exportAttributes(self, outfile, level, already_processed, namespace_='sbgn:', name_='startType'):
-        if self.x is not None and 'x' not in already_processed:
-            already_processed.add('x')
-            outfile.write(' x="%s"' % self.gds_format_float(self.x, input_name='x'))
-        if self.y is not None and 'y' not in already_processed:
-            already_processed.add('y')
-            outfile.write(' y="%s"' % self.gds_format_float(self.y, input_name='y'))
-
-    def exportChildren(self, outfile, level, namespace_='sbgn:', name_='startType', fromsubclass_=False, pretty_print=True):
-        pass
-
-    def build(self, node):
-        already_processed = set()
-        self.buildAttributes(node, node.attrib, already_processed)
-        for child in node:
-            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
-            self.buildChildren(child, node, nodeName_)
-        return self
-
-    def buildAttributes(self, node, attrs, already_processed):
-        value = find_attr_value_('x', node)
-        if value is not None and 'x' not in already_processed:
-            already_processed.add('x')
-            try:
-                self.x = float(value)
-            except ValueError as exp:
-                raise ValueError('Bad float/double attribute (x): %s' % exp)
-        value = find_attr_value_('y', node)
-        if value is not None and 'y' not in already_processed:
-            already_processed.add('y')
-            try:
-                self.y = float(value)
-            except ValueError as exp:
-                raise ValueError('Bad float/double attribute (y): %s' % exp)
-
-    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
-        pass
-# end class startType
-
-
-class nextType(GeneratedsSuper):
-    """List of control points, used when the path describes a curve. The
-    number of points describes the degree of the Bezier curve:
-    linear (0), quadratic (1) or cubic (2)"""
-    subclass = None
-    superclass = None
-
-    def __init__(self, x=None, y=None, point=None):
-        self.original_tagname_ = None
-        self.x = _cast(float, x)
-        self.y = _cast(float, y)
-        if point is None:
-            self.point = []
-        else:
-            self.point = point
-
-    def factory(*args_, **kwargs_):
-        if CurrentSubclassModule_ is not None:
-            subclass = getSubclassFromModule_(
-                CurrentSubclassModule_, nextType)
-            if subclass is not None:
-                return subclass(*args_, **kwargs_)
-        if nextType.subclass:
-            return nextType.subclass(*args_, **kwargs_)
-        else:
-            return nextType(*args_, **kwargs_)
-    factory = staticmethod(factory)
-
-    def get_point(self): return self.point
-
-    def set_point(self, point): self.point = point
-
-    def add_point(self, value): self.point.append(value)
-
-    def insert_point_at(self, index, value): self.point.insert(index, value)
-
-    def replace_point_at(self, index, value): self.point[index] = value
-
-    def get_x(self): return self.x
-
-    def set_x(self, x): self.x = x
-
-    def get_y(self): return self.y
-
-    def set_y(self, y): self.y = y
-
-    def hasContent_(self):
-        if (
-            self.point
-        ):
-            return True
-        else:
-            return False
-
-    def export(self, outfile, level, namespace_='sbgn:', name_='nextType', namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"', pretty_print=True):
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        if self.original_tagname_ is not None:
-            name_ = self.original_tagname_
-        showIndent(outfile, level, pretty_print)
-        outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
-        already_processed = set()
-        self.exportAttributes(outfile, level, already_processed, namespace_, name_='nextType')
-        if self.hasContent_():
-            outfile.write('>%s' % (eol_, ))
-            self.exportChildren(outfile, level + 1, namespace_='sbgn:', name_='nextType', pretty_print=pretty_print)
-            showIndent(outfile, level, pretty_print)
-            outfile.write('</%s%s>%s' % (namespace_, name_, eol_))
-        else:
-            outfile.write('/>%s' % (eol_, ))
-
-    def exportAttributes(self, outfile, level, already_processed, namespace_='sbgn:', name_='nextType'):
-        if self.x is not None and 'x' not in already_processed:
-            already_processed.add('x')
-            outfile.write(' x="%s"' % self.gds_format_float(self.x, input_name='x'))
-        if self.y is not None and 'y' not in already_processed:
-            already_processed.add('y')
-            outfile.write(' y="%s"' % self.gds_format_float(self.y, input_name='y'))
-
-    def exportChildren(self, outfile, level, namespace_='sbgn:', name_='nextType', fromsubclass_=False, pretty_print=True):
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        for point_ in self.point:
-            point_.export(outfile, level, namespace_='sbgn:', name_='point', pretty_print=pretty_print)
-
-    def build(self, node):
-        already_processed = set()
-        self.buildAttributes(node, node.attrib, already_processed)
-        for child in node:
-            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
-            self.buildChildren(child, node, nodeName_)
-        return self
-
-    def buildAttributes(self, node, attrs, already_processed):
-        value = find_attr_value_('x', node)
-        if value is not None and 'x' not in already_processed:
-            already_processed.add('x')
-            try:
-                self.x = float(value)
-            except ValueError as exp:
-                raise ValueError('Bad float/double attribute (x): %s' % exp)
-        value = find_attr_value_('y', node)
-        if value is not None and 'y' not in already_processed:
-            already_processed.add('y')
-            try:
-                self.y = float(value)
-            except ValueError as exp:
-                raise ValueError('Bad float/double attribute (y): %s' % exp)
-
-    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
-        if nodeName_ == 'point':
-            obj_ = point.factory()
-            obj_.build(child_)
-            self.point.append(obj_)
-            obj_.original_tagname_ = 'point'
-# end class nextType
-
-
-class endType(GeneratedsSuper):
-    """List of control points, used when the path describes a curve. The
-    number of points describes the degree of the Bezier curve:
-    linear (0), quadratic (1) or cubic (2)"""
-    subclass = None
-    superclass = None
-
-    def __init__(self, x=None, y=None, point=None):
-        self.original_tagname_ = None
-        self.x = _cast(float, x)
-        self.y = _cast(float, y)
-        if point is None:
-            self.point = []
-        else:
-            self.point = point
-
-    def factory(*args_, **kwargs_):
-        if CurrentSubclassModule_ is not None:
-            subclass = getSubclassFromModule_(
-                CurrentSubclassModule_, endType)
-            if subclass is not None:
-                return subclass(*args_, **kwargs_)
-        if endType.subclass:
-            return endType.subclass(*args_, **kwargs_)
-        else:
-            return endType(*args_, **kwargs_)
-    factory = staticmethod(factory)
-
-    def get_point(self): return self.point
-
-    def set_point(self, point): self.point = point
-
-    def add_point(self, value): self.point.append(value)
-
-    def insert_point_at(self, index, value): self.point.insert(index, value)
-
-    def replace_point_at(self, index, value): self.point[index] = value
-
-    def get_x(self): return self.x
-
-    def set_x(self, x): self.x = x
-
-    def get_y(self): return self.y
-
-    def set_y(self, y): self.y = y
-
-    def hasContent_(self):
-        if (
-            self.point
-        ):
-            return True
-        else:
-            return False
-
-    def export(self, outfile, level, namespace_='sbgn:', name_='endType', namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"', pretty_print=True):
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        if self.original_tagname_ is not None:
-            name_ = self.original_tagname_
-        showIndent(outfile, level, pretty_print)
-        outfile.write('<%s%s%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
-        already_processed = set()
-        self.exportAttributes(outfile, level, already_processed, namespace_, name_='endType')
-        if self.hasContent_():
-            outfile.write('>%s' % (eol_, ))
-            self.exportChildren(outfile, level + 1, namespace_='sbgn:', name_='endType', pretty_print=pretty_print)
-            showIndent(outfile, level, pretty_print)
-            outfile.write('</%s%s>%s' % (namespace_, name_, eol_))
-        else:
-            outfile.write('/>%s' % (eol_, ))
-
-    def exportAttributes(self, outfile, level, already_processed, namespace_='sbgn:', name_='endType'):
-        if self.x is not None and 'x' not in already_processed:
-            already_processed.add('x')
-            outfile.write(' x="%s"' % self.gds_format_float(self.x, input_name='x'))
-        if self.y is not None and 'y' not in already_processed:
-            already_processed.add('y')
-            outfile.write(' y="%s"' % self.gds_format_float(self.y, input_name='y'))
-
-    def exportChildren(self, outfile, level, namespace_='sbgn:', name_='endType', fromsubclass_=False, pretty_print=True):
-        if pretty_print:
-            eol_ = '\n'
-        else:
-            eol_ = ''
-        for point_ in self.point:
-            point_.export(outfile, level, namespace_='sbgn:', name_='point', pretty_print=pretty_print)
-
-    def build(self, node):
-        already_processed = set()
-        self.buildAttributes(node, node.attrib, already_processed)
-        for child in node:
-            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
-            self.buildChildren(child, node, nodeName_)
-        return self
-
-    def buildAttributes(self, node, attrs, already_processed):
-        value = find_attr_value_('x', node)
-        if value is not None and 'x' not in already_processed:
-            already_processed.add('x')
-            try:
-                self.x = float(value)
-            except ValueError as exp:
-                raise ValueError('Bad float/double attribute (x): %s' % exp)
-        value = find_attr_value_('y', node)
-        if value is not None and 'y' not in already_processed:
-            already_processed.add('y')
-            try:
-                self.y = float(value)
-            except ValueError as exp:
-                raise ValueError('Bad float/double attribute (y): %s' % exp)
-
-    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
-        if nodeName_ == 'point':
-            obj_ = point.factory()
-            obj_.build(child_)
-            self.point.append(obj_)
-            obj_.original_tagname_ = 'point'
-# end class endType
-
-
-GDSClassesMapping = {
-    'callout': calloutType,
-    'clone': cloneType,
-    'end': endType,
-    'entity': entityType,
-    'extension': extensionType,
-    'next': nextType,
-    'notes': notesType,
-    'start': startType,
-    'state': stateType,
-}
-
-
-USAGE_TEXT = """
-Usage: python <Parser>.py [ -s ] <in_xml_file>
-"""
-
-
-def usage():
-    print(USAGE_TEXT)
-    sys.exit(1)
-
-
-def get_root_tag(node):
-    tag = Tag_pattern_.match(node.tag).groups()[-1]
-    rootClass = GDSClassesMapping.get(tag)
-    if rootClass is None:
-        rootClass = globals().get(tag)
-    return tag, rootClass
-
-
-def parse(inFileName, silence=False):
-    parser = None
-    doc = parsexml_(inFileName, parser)
-    rootNode = doc.getroot()
-    rootTag, rootClass = get_root_tag(rootNode)
-    if rootClass is None:
-        rootTag = 'SBGNBase'
-        rootClass = SBGNBase
-    rootObj = rootClass.factory()
-    rootObj.build(rootNode)
-    # Enable Python to collect the space used by the DOM.
-    doc = None
-    if not silence:
-        sys.stdout.write('<?xml version="1.0" ?>\n')
-        rootObj.export(
-            sys.stdout, 0, name_=rootTag,
-            namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"',
-            pretty_print=True)
-    return rootObj
-
-
-def parseEtree(inFileName, silence=False):
-    parser = None
-    doc = parsexml_(inFileName, parser)
-    rootNode = doc.getroot()
-    rootTag, rootClass = get_root_tag(rootNode)
-    if rootClass is None:
-        rootTag = 'SBGNBase'
-        rootClass = SBGNBase
-    rootObj = rootClass.factory()
-    rootObj.build(rootNode)
-    # Enable Python to collect the space used by the DOM.
-    doc = None
-    mapping = {}
-    rootElement = rootObj.to_etree(None, name_=rootTag, mapping_=mapping)
-    reverse_mapping = rootObj.gds_reverse_node_mapping(mapping)
-    if not silence:
-        content = etree_.tostring(
-            rootElement, pretty_print=True,
-            xml_declaration=True, encoding="utf-8")
-        sys.stdout.write(content)
-        sys.stdout.write('\n')
-    return rootObj, rootElement, mapping, reverse_mapping
-
-
-def parseString(inString, silence=False):
-    from StringIO import StringIO
-    parser = None
-    doc = parsexml_(StringIO(inString), parser)
-    rootNode = doc.getroot()
-    rootTag, rootClass = get_root_tag(rootNode)
-    if rootClass is None:
-        rootTag = 'SBGNBase'
-        rootClass = SBGNBase
-    rootObj = rootClass.factory()
-    rootObj.build(rootNode)
-    # Enable Python to collect the space used by the DOM.
-    doc = None
-    if not silence:
-        sys.stdout.write('<?xml version="1.0" ?>\n')
-        rootObj.export(
-            sys.stdout, 0, name_=rootTag,
-            namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"')
-    return rootObj
-
-
-def parseLiteral(inFileName, silence=False):
-    parser = None
-    doc = parsexml_(inFileName, parser)
-    rootNode = doc.getroot()
-    rootTag, rootClass = get_root_tag(rootNode)
-    if rootClass is None:
-        rootTag = 'SBGNBase'
-        rootClass = SBGNBase
-    rootObj = rootClass.factory()
-    rootObj.build(rootNode)
-    # Enable Python to collect the space used by the DOM.
-    doc = None
-    if not silence:
-        sys.stdout.write('#from libsbgn import *\n\n')
-        sys.stdout.write('import libsbgn as model_\n\n')
-        sys.stdout.write('rootObj = model_.rootClass(\n')
-        rootObj.exportLiteral(sys.stdout, 0, name_=rootTag)
-        sys.stdout.write(')\n')
-    return rootObj
-
-
-def main():
-    args = sys.argv[1:]
-    if len(args) == 1:
-        parse(args[0])
-    else:
-        usage()
-
-
-if __name__ == '__main__':
-    # import pdb; pdb.set_trace()
-    main()
-
-
-__all__ = [
-    "SBGNBase",
-    "arc",
-    "arcgroup",
-    "bbox",
-    "calloutType",
-    "cloneType",
-    "endType",
-    "entityType",
-    "extensionType",
-    "glyph",
-    "label",
-    "map",
-    "nextType",
-    "notesType",
-    "point",
-    "port",
-    "sbgn",
-    "startType",
-    "stateType"
-]
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..771bdb3
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,9 @@
+[build-system]
+requires = [
+  'setuptools>=40.6.0',
+  'wheel'
+]
+
+[tool.black]
+line-length = 88
+python-version = ['py38']
diff --git a/release-notes/0.2.0.md b/release-notes/0.2.0.md
new file mode 100644
index 0000000..61003bd
--- /dev/null
+++ b/release-notes/0.2.0.md
@@ -0,0 +1,46 @@
+## Release notes for libsbgnpy
+**v0.2.0**
+- dropping support of python 2.7, 3.4
+- adding support for python 3.7, 3.8
+- fixing render endpoints (#31, #32)
+- fixing documentation builder
+- removing py2 legacy code
+
+**v0.1.7**
+Support for notes and extensions
+
+* Extension and Notes reading and writing
+* Extension and Notes examples
+
+**v0.1.6**
+Improved testing and documentation
+
+* New documentation: http://libsbgn-python.readthedocs.io/en/latest/index.html
+* Some python 3 bugfixes
+* Additional examples 
+* Additional tests, coverage & switch to py-test
+* pep8 fixes
+* tox support and tox testing
+* logo
+
+**v0.1.5**
+
+* py3 support bugfixes
+* SBGN validation with XSD schema
+* update of bindings from latest schema
+* bug fix in writing some attributes
+
+**v0.1.4**
+
+* support for py2.6, 2.7, 3.4, 3.5
+* continuous integration with travis
+
+**v0.1.3**
+
+* unittests added
+* x, y, w, d handled as float instead int according to specification
+
+
+**v0.1.2**
+
+* initial release
diff --git a/release-notes/0.2.2.md b/release-notes/0.2.2.md
new file mode 100644
index 0000000..ec08589
--- /dev/null
+++ b/release-notes/0.2.2.md
@@ -0,0 +1,7 @@
+## Release notes for libsbgnpy 0.2.2
+- dropping support of python 3.5
+- adding support for python 3.9
+- moved to github actions (dropping travis)
+- isort and black code formating
+- automatic release pipeline
+- Fix #34, correct decoding of notes and extensions
diff --git a/requirements.txt b/requirements.txt
deleted file mode 100644
index 5d7b069..0000000
--- a/requirements.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-lxml
-requests
-
-# testing
-pytest
-pytest-cov
-
diff --git a/setup.cfg b/setup.cfg
index 79bc678..e1ad366 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,5 +1,89 @@
+[bumpversion]
+current_version = 0.2.2
+commit = True
+tag = True
+parse = (?P<major>\d+)
+	\.(?P<minor>\d+)
+	\.(?P<patch>\d+)
+	(?P<release>[a]*)(?P<num>\d*)
+serialize =
+	{major}.{minor}.{patch}{release}{num}
+	{major}.{minor}.{patch}
+tag_name = {new_version}
+
+[metadata]
+name = libsbgnpy
+url = https://github.com/matthiaskoenig/libsbgn-python
+download_url = https://pypi.org/project/libsbgnpy
+project_urls =
+	Source Code = https://github.com/matthiaskoenig/libsbgn-python
+	Documentation = https://libsbgnpy.readthedocs.io
+	Bug Tracker = https://github.com/matthiaskoenig/libsbgn-python/issues
+author = Matthias Koenig
+author_email = konigmatt@googlemail.com
+maintainer = Matthias Koenig
+maintainer_email = konigmatt@googlemail.com
+classifiers =
+	Development Status :: 5 - Production/Stable
+	Intended Audience :: Science/Research
+	License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)
+	Operating System :: OS Independent
+	Programming Language :: Python :: 3.6
+	Programming Language :: Python :: 3.7
+	Programming Language :: Python :: 3.8
+	Programming Language :: Python :: 3.9
+	Programming Language :: Python :: Implementation :: CPython
+	Topic :: Scientific/Engineering
+	Topic :: Scientific/Engineering :: Bio-Informatics
+license = LGPL-3.0
+description = Python library for SBGN.
+long_description = file: README.rst
+long_description_content_type = text/x-rst
+keywords =
+	modeling
+	standardization
+	SBGN
+	libsbgn
+
+[options]
+zip_safe = True
+python_requires = >=3.6
+install_requires =
+	lxml
+	requests
+tests_require =
+	tox
+packages = find:
+package_dir =
+	= src
+include_package_data = True
+
+[options.packages.find]
+where = src
+
+[options.extras_require]
+development =
+	black
+	bump2version
+	isort
+	tox
+	pytest>=6.1
+	pytest-cov>=2.8.1
+
 [bdist_wheel]
-# This flag says that the code is written to work on both Python 2 and Python
-# 3. If at all possible, it is good practice to do this. If you cannot, you
-# will need to generate wheels for each Python version that you support.
-universal=1
+universal = 1
+
+[bumpversion:part:release]
+optional_value = placeholder
+first_value = placeholder
+values =
+	placeholder
+	a
+
+[bumpversion:file:setup.py]
+search = version="{current_version}"
+replace = version="{new_version}"
+
+[bumpversion:file:src/libsbgnpy/__init__.py]
+search = __version__ = "{current_version}"
+replace = __version__ = "{new_version}"
diff --git a/setup.py b/setup.py
index 0cda303..db85dff 100644
--- a/setup.py
+++ b/setup.py
@@ -1,77 +1,6 @@
 #!/usr/bin/env python
-# -*- coding: utf-8 -*-
-"""
-Setup module for libsbgn-python.
+from setuptools import setup
 
-source distribution generation via
-python setup.py sdist
-"""
 
-# Always prefer setuptools over distutils
-from setuptools import setup, find_packages
-from codecs import open  # To use a consistent encoding
-from os import path
-import re
-
-here = path.abspath(path.dirname(__file__))
-
-# get the version
-VERSIONFILE = "libsbgnpy/_version.py"
-verstrline = open(VERSIONFILE, "rt").read()
-VSRE = r"^__version__ = ['\"]([^'\"]*)['\"]"
-mo = re.search(VSRE, verstrline, re.M)
-if mo:
-    verstr = mo.group(1)
-else:
-    raise RuntimeError("Unable to find version string in %s." % (VERSIONFILE,))
-
-
-# Get the long description from the relevant file
-with open(path.join(here, 'DESCRIPTION.rst'), encoding='utf-8') as f:
-    long_description = f.read()
-
-setup(
-    name='libsbgnpy',
-
-    # Versions should comply with PEP440.  For a discussion on single-sourcing
-    # the version across setup.py and the project code, see
-    # https://packaging.python.org/en/latest/single_source_version.html
-    version=verstr,
-
-    description='libsbgn python bindings',
-    long_description=long_description,
-    url='https://github.com/matthiaskoenig/libsbgn-python',
-    author='Matthias König',
-    author_email='konigmatt@googlemail.com',
-    license='LGPLv3',
-    classifiers=[
-        'Development Status :: 5 - Production/Stable',
-        'Intended Audience :: Science/Research',
-        'Topic :: Scientific/Engineering :: Visualization',
-        'License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)',
-
-        # Specify the Python versions you support here. In particular, ensure
-        # that you indicate whether you support Python 2, Python 3 or both.
-
-        'Programming Language :: Python :: 3',
-        'Programming Language :: Python :: 3.5',
-        'Programming Language :: Python :: 3.6',
-    ],
-
-    # What does your project relate to?
-    keywords='SBGN, libsbgn',
-    packages=find_packages(),
-    install_requires=[
-        'lxml',
-        'requests',
-    ],
-    python_requires='>=3.5',
-
-    # include the package data (SBGN, XSD)
-    include_package_data=True,
-
-    # Prevent the package manager to install a python egg, 
-    # instead you'll get a real directory with files in it.
-    zip_safe=False,
-
-)
+if __name__ == "__main__":
+    setup(version="0.2.2")
diff --git a/libsbgnpy/__init__.py b/src/libsbgnpy/__init__.py
similarity index 77%
rename from libsbgnpy/__init__.py
rename to src/libsbgnpy/__init__.py
index 8db7b83..3c43b7e 100644
--- a/libsbgnpy/__init__.py
+++ b/src/libsbgnpy/__init__.py
@@ -1,4 +1,4 @@
-from ._version import __version__
+__version__ = "0.2.2"
 
 from libsbgnpy.libsbgnSubs import Notes, Extension
 from libsbgnpy.libsbgnTypes import Language, GlyphClass, ArcClass
diff --git a/libsbgnpy/examples/__init__.py b/src/libsbgnpy/examples/__init__.py
similarity index 100%
rename from libsbgnpy/examples/__init__.py
rename to src/libsbgnpy/examples/__init__.py
diff --git a/libsbgnpy/examples/extension_example.py b/src/libsbgnpy/examples/extension_example.py
similarity index 90%
rename from libsbgnpy/examples/extension_example.py
rename to src/libsbgnpy/examples/extension_example.py
index 6e0f05b..5d05650 100644
--- a/libsbgnpy/examples/extension_example.py
+++ b/src/libsbgnpy/examples/extension_example.py
@@ -3,13 +3,11 @@
 Write and read extension information.
 see https://github.com/sbgn/sbgn/wiki/SBGN-ML_Extensions
 """
-from libsbgnpy import libsbgn
-from libsbgnpy import utils
-from libsbgnpy import Extension, Language
+from libsbgnpy import Extension, Language, libsbgn, utils
 
 
 def write_map_extension(f):
-    """ Write extension information on map.
+    """Write extension information on map.
 
     :param f: file input
     :return: None
@@ -19,7 +17,8 @@ def write_map_extension(f):
     map.set_language(Language.PD)
     sbgn.set_map(map)
 
-    extension = Extension("""<renderInformation id="example" programName="SBML Layout" programVersion="3.0"
+    extension = Extension(
+        """<renderInformation id="example" programName="SBML Layout" programVersion="3.0"
      xmlns="http://projects.eml.org/bcb/sbml/render/level2">
         <listOfColorDefinitions>
         <colorDefinition id="yelloComp" value="#ffffccff" />
@@ -69,7 +68,8 @@ def write_map_extension(f):
             <g stroke="blue" stroke-width="2"  />
         </style>
         </listOfStyles>
-    </renderInformation>""")
+    </renderInformation>"""
+    )
     map.set_extension(extension)
 
     print(utils.write_to_string(sbgn))
@@ -77,7 +77,7 @@ def write_map_extension(f):
 
 
 def read_map_extension(f):
-    """ Read notes from glyphs.
+    """Read notes from glyphs.
 
     :param f: file input
     :return: None
@@ -94,7 +94,7 @@ def read_map_extension(f):
 
 
 if __name__ == "__main__":
-    f = 'sbgn/notes.sbgn'
+    f = "sbgn/notes.sbgn"
     write_map_extension(f)
-    print("_" * 80, '\n')
+    print("_" * 80, "\n")
     read_map_extension(f)
diff --git a/libsbgnpy/examples/info_example.py b/src/libsbgnpy/examples/info_example.py
similarity index 77%
rename from libsbgnpy/examples/info_example.py
rename to src/libsbgnpy/examples/info_example.py
index 3e87d74..12f68f7 100644
--- a/libsbgnpy/examples/info_example.py
+++ b/src/libsbgnpy/examples/info_example.py
@@ -3,6 +3,7 @@
 Display information from SBGN files.
 """
 import os
+
 import libsbgnpy.libsbgn as libsbgn  # import the bindings
 from libsbgnpy.utils import print_bbox  # some additional helpers
 
@@ -12,49 +13,49 @@ def info_example():
 
     # file to process
     dir = os.path.dirname(os.path.realpath(__file__))
-    f_in = os.path.join(dir, 'sbgn/adh.sbgn')
+    f_in = os.path.join(dir, "sbgn/adh.sbgn")
 
     # sbgn and map
     sbgn = libsbgn.parse(f_in)
     map = sbgn.get_map()
-    print('Language:', map.get_language())
+    print("Language:", map.get_language())
 
     # get bbox for map
-    '''<bbox x="0" y="0" w="363" h="253"/>'''
+    """<bbox x="0" y="0" w="363" h="253"/>"""
     box = map.get_bbox()
-    print('x, y, w, h : ', box.get_x(), box.get_y(), box.get_w(), box.get_h())
+    print("x, y, w, h : ", box.get_x(), box.get_y(), box.get_w(), box.get_h())
 
     # glyphs
-    '''
+    """
     <glyph class="simple chemical" id="glyph1">
             <label text="Ethanol"/> <!-- fontsize="" etc -->
             <!-- Line breaks are allowed in the text attribute -->
             <bbox x="40" y="120" w="60" h="60"/>
         </glyph>
-    '''
+    """
     glyphs = map.get_glyph()
     for g in glyphs:
         cls = g.get_class()
         print(cls, g.get_id())
         label = g.get_label()
-        if cls == 'simple chemical':
-            print('label: ', label.get_text())
+        if cls == "simple chemical":
+            print("label: ", label.get_text())
 
-        if cls == 'process':
+        if cls == "process":
             for p in g.get_port():
-                print('port ', p.get_id(), p.get_x(), p.get_y())
+                print("port ", p.get_id(), p.get_x(), p.get_y())
 
         box = g.get_bbox()
         print_bbox(box)
         print
 
     # arcs
-    '''
+    """
         <arc class="consumption" source="glyph_nad" target="pn1.1" id="a06">
             <start x="95" y="202" />
             <end x="136" y="180" />
         </arc>
-    '''
+    """
     arcs = map.get_arc()
     for a in arcs:
         print(a.get_class(), a.get_source(), a.get_target(), a.get_id())
diff --git a/libsbgnpy/examples/notes_example.py b/src/libsbgnpy/examples/notes_example.py
similarity index 83%
rename from libsbgnpy/examples/notes_example.py
rename to src/libsbgnpy/examples/notes_example.py
index 0176e4d..814148f 100644
--- a/libsbgnpy/examples/notes_example.py
+++ b/src/libsbgnpy/examples/notes_example.py
@@ -3,12 +3,11 @@
 Write and read notes information.
 Notes must be XML elements in a <notes>Tag</notes>
 """
-from libsbgnpy import libsbgn, Notes, Language
-from libsbgnpy import utils
+from libsbgnpy import Language, Notes, libsbgn, utils
 
 
 def write_glyph_notes(f):
-    """ Set notes on element.
+    """Set notes on element.
 
     :return: None
     """
@@ -29,10 +28,12 @@ def write_glyph_notes(f):
     g.set_bbox(bbox)
     map.add_glyph(g)
 
-    notes = Notes("""
+    notes = Notes(
+        """
     <body xmlns="http://www.w3.org/1999/xhtml">
         This is an example note describing the INSR glyph.
-    </body>""")
+    </body>"""
+    )
     g.set_notes(notes)
 
     print(utils.write_to_string(sbgn))
@@ -40,7 +41,7 @@ def write_glyph_notes(f):
 
 
 def read_glyph_notes(f):
-    """ Read notes from glyphs.
+    """Read notes from glyphs.
 
     :return: None
     """
@@ -58,7 +59,7 @@ def read_glyph_notes(f):
 
 
 if __name__ == "__main__":
-    f = 'sbgn/notes.sbgn'
+    f = "sbgn/notes.sbgn"
     write_glyph_notes(f)
-    print("_"*80, '\n')
+    print("_" * 80, "\n")
     read_glyph_notes(f)
diff --git a/libsbgnpy/examples/read_example.py b/src/libsbgnpy/examples/read_example.py
similarity index 91%
rename from libsbgnpy/examples/read_example.py
rename to src/libsbgnpy/examples/read_example.py
index 5eb53f7..884a045 100644
--- a/libsbgnpy/examples/read_example.py
+++ b/src/libsbgnpy/examples/read_example.py
@@ -3,7 +3,7 @@
 
 
 def read_sbgn_01(f):
-    """ Read example file and display content.
+    """Read example file and display content.
 
     :param f: SBGN file to read
     :return: sbgn
@@ -33,4 +33,4 @@ def read_sbgn_01(f):
 
 
 if __name__ == "__main__":
-    read_sbgn_01('sbgn/adh.sbgn')
+    read_sbgn_01("sbgn/adh.sbgn")
diff --git a/libsbgnpy/examples/sbgn/adh.sbgn b/src/libsbgnpy/examples/sbgn/adh.sbgn
similarity index 100%
rename from libsbgnpy/examples/sbgn/adh.sbgn
rename to src/libsbgnpy/examples/sbgn/adh.sbgn
diff --git a/libsbgnpy/examples/sbgn/glycolysis.sbgn b/src/libsbgnpy/examples/sbgn/glycolysis.sbgn
similarity index 100%
rename from libsbgnpy/examples/sbgn/glycolysis.sbgn
rename to src/libsbgnpy/examples/sbgn/glycolysis.sbgn
diff --git a/libsbgnpy/examples/sbgn/neuronal_muscle_signalling_color.sbgn b/src/libsbgnpy/examples/sbgn/neuronal_muscle_signalling_color.sbgn
similarity index 100%
rename from libsbgnpy/examples/sbgn/neuronal_muscle_signalling_color.sbgn
rename to src/libsbgnpy/examples/sbgn/neuronal_muscle_signalling_color.sbgn
diff --git a/src/libsbgnpy/examples/sbgn/notes.sbgn b/src/libsbgnpy/examples/sbgn/notes.sbgn
new file mode 100644
index 0000000..87d402e
--- /dev/null
+++ b/src/libsbgnpy/examples/sbgn/notes.sbgn
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<sbgn xmlns="http://sbgn.org/libsbgn/0.2">
+    <map language="process description">
+        <glyph id="g1">
+            <notes>
+            <body xmlns="http://www.w3.org/1999/xhtml">
+        This is an example note describing the INSR glyph.
+    </body>
+            </notes>
+            <bbox w="80." h="40." x="100." y="100."/>
+        </glyph>
+    </map>
+</sbgn>
diff --git a/libsbgnpy/examples/write_example.py b/src/libsbgnpy/examples/write_example.py
similarity index 71%
rename from libsbgnpy/examples/write_example.py
rename to src/libsbgnpy/examples/write_example.py
index 4974341..39d0b1d 100644
--- a/libsbgnpy/examples/write_example.py
+++ b/src/libsbgnpy/examples/write_example.py
@@ -4,11 +4,11 @@
 """
 
 import libsbgnpy.libsbgn as libsbgn
-from libsbgnpy.libsbgnTypes import GlyphClass, ArcClass, Language, Orientation
+from libsbgnpy.libsbgnTypes import ArcClass, GlyphClass, Language, Orientation
 
 
 def write_sbgn_01(f):
-    """ Create SBGN and write to file.
+    """Create SBGN and write to file.
 
     Macromolecule box with label.
 
@@ -41,7 +41,7 @@ def write_sbgn_01(f):
 
 
 def write_sbgn_02(f):
-    """ Create SBGN document and write to file.
+    """Create SBGN document and write to file.
 
     :param f:
     :return:
@@ -68,46 +68,48 @@ def write_sbgn_02(f):
 
     # create some glyphs
     # class attribute is named 'class_' ! in glyphs and arcs
-    '''
+    """
         <glyph class="simple chemical" id="glyph1">
             <label text="Ethanol"/> <!-- fontsize="" etc -->
             <!-- Line breaks are allowed in the text attribute -->
             <bbox x="40" y="120" w="60" h="60"/>
         </glyph>
-    '''
+    """
     # glyphs with labels
-    g = libsbgn.glyph(class_=GlyphClass.SIMPLE_CHEMICAL, id='glyph1')
-    g.set_label(libsbgn.label(text='Ethanol'))
+    g = libsbgn.glyph(class_=GlyphClass.SIMPLE_CHEMICAL, id="glyph1")
+    g.set_label(libsbgn.label(text="Ethanol"))
     g.set_bbox(libsbgn.bbox(x=40, y=120, w=60, h=60))
     map.add_glyph(g)
 
-    g = libsbgn.glyph(class_=GlyphClass.SIMPLE_CHEMICAL, id='glyph_ethanal')
-    g.set_label(libsbgn.label(text='Ethanal'))
+    g = libsbgn.glyph(class_=GlyphClass.SIMPLE_CHEMICAL, id="glyph_ethanal")
+    g.set_label(libsbgn.label(text="Ethanal"))
     g.set_bbox(libsbgn.bbox(x=220, y=110, w=60, h=60))
     map.add_glyph(g)
 
-    g = libsbgn.glyph(class_=GlyphClass.MACROMOLECULE, id='glyph_adh1')
-    g.set_label(libsbgn.label(text='ADH1'))
+    g = libsbgn.glyph(class_=GlyphClass.MACROMOLECULE, id="glyph_adh1")
+    g.set_label(libsbgn.label(text="ADH1"))
     g.set_bbox(libsbgn.bbox(x=106, y=20, w=108, h=60))
     map.add_glyph(g)
 
-    g = libsbgn.glyph(class_=GlyphClass.SIMPLE_CHEMICAL, id='glyph_h')
-    g.set_label(libsbgn.label(text='H+'))
+    g = libsbgn.glyph(class_=GlyphClass.SIMPLE_CHEMICAL, id="glyph_h")
+    g.set_label(libsbgn.label(text="H+"))
     g.set_bbox(libsbgn.bbox(x=220, y=190, w=60, h=60))
     map.add_glyph(g)
 
-    g = libsbgn.glyph(class_=GlyphClass.SIMPLE_CHEMICAL, id='glyph_nad')
-    g.set_label(libsbgn.label(text='NAD+'))
+    g = libsbgn.glyph(class_=GlyphClass.SIMPLE_CHEMICAL, id="glyph_nad")
+    g.set_label(libsbgn.label(text="NAD+"))
     g.set_bbox(libsbgn.bbox(x=40, y=190, w=60, h=60))
     map.add_glyph(g)
 
-    g = libsbgn.glyph(class_=GlyphClass.SIMPLE_CHEMICAL, id='glyph_nadh')
-    g.set_label(libsbgn.label(text='NADH'))
+    g = libsbgn.glyph(class_=GlyphClass.SIMPLE_CHEMICAL, id="glyph_nadh")
+    g.set_label(libsbgn.label(text="NADH"))
     g.set_bbox(libsbgn.bbox(x=300, y=150, w=60, h=60))
     map.add_glyph(g)
 
     # glyph with ports (process)
-    g = libsbgn.glyph(class_=GlyphClass.PROCESS, id='pn1', orientation=Orientation.HORIZONTAL)
+    g = libsbgn.glyph(
+        class_=GlyphClass.PROCESS, id="pn1", orientation=Orientation.HORIZONTAL
+    )
     g.set_bbox(libsbgn.bbox(x=148, y=168, w=24, h=24))
     g.add_port(libsbgn.port(x=136, y=180, id="pn1.1"))
     g.add_port(libsbgn.port(x=184, y=180, id="pn1.2"))
@@ -115,32 +117,44 @@ def write_sbgn_02(f):
 
     # arcs
     # create arcs and set the start and end points
-    a = libsbgn.arc(class_=ArcClass.CONSUMPTION, source="glyph1", target="pn1.1", id="a01")
+    a = libsbgn.arc(
+        class_=ArcClass.CONSUMPTION, source="glyph1", target="pn1.1", id="a01"
+    )
     a.set_start(libsbgn.startType(x=98, y=160))
     a.set_end(libsbgn.endType(x=136, y=180))
     map.add_arc(a)
 
-    a = libsbgn.arc(class_=ArcClass.PRODUCTION, source="pn1.2", target="glyph_nadh", id="a02")
+    a = libsbgn.arc(
+        class_=ArcClass.PRODUCTION, source="pn1.2", target="glyph_nadh", id="a02"
+    )
     a.set_start(libsbgn.startType(x=184, y=180))
     a.set_end(libsbgn.endType(x=300, y=180))
     map.add_arc(a)
 
-    a = libsbgn.arc(class_=ArcClass.CATALYSIS, source="glyph_adh1", target="pn1", id="a03")
+    a = libsbgn.arc(
+        class_=ArcClass.CATALYSIS, source="glyph_adh1", target="pn1", id="a03"
+    )
     a.set_start(libsbgn.startType(x=160, y=80))
     a.set_end(libsbgn.endType(x=160, y=168))
     map.add_arc(a)
 
-    a = libsbgn.arc(class_=ArcClass.PRODUCTION, source="pn1.2", target="glyph_h", id="a04")
+    a = libsbgn.arc(
+        class_=ArcClass.PRODUCTION, source="pn1.2", target="glyph_h", id="a04"
+    )
     a.set_start(libsbgn.startType(x=184, y=180))
     a.set_end(libsbgn.endType(x=224, y=202))
     map.add_arc(a)
 
-    a = libsbgn.arc(class_=ArcClass.PRODUCTION, source="pn1.2", target="glyph_ethanal", id="a05")
+    a = libsbgn.arc(
+        class_=ArcClass.PRODUCTION, source="pn1.2", target="glyph_ethanal", id="a05"
+    )
     a.set_start(libsbgn.startType(x=184, y=180))
     a.set_end(libsbgn.endType(x=224, y=154))
     map.add_arc(a)
 
-    a = libsbgn.arc(class_=ArcClass.CONSUMPTION, source="glyph_nad", target="pn1.1", id="a06")
+    a = libsbgn.arc(
+        class_=ArcClass.CONSUMPTION, source="glyph_nad", target="pn1.1", id="a06"
+    )
     a.set_start(libsbgn.startType(x=95, y=202))
     a.set_end(libsbgn.endType(x=136, y=180))
     map.add_arc(a)
@@ -150,12 +164,13 @@ def write_sbgn_02(f):
 
 
 def write_sbgn_03(f):
-    """ Create SBGN with annotation and write to file.
+    """Create SBGN with annotation and write to file.
 
     :param f: file to write
     :return:
     """
-    from libsbgnpy.libsbgn import sbgn, map, glyph, point, calloutType, bbox, label
+    from libsbgnpy.libsbgn import bbox, calloutType, glyph, label, map, point, sbgn
+
     doc = sbgn()
     m = map()
     m.set_language(Language.PD)
diff --git a/src/libsbgnpy/libsbgn.py b/src/libsbgnpy/libsbgn.py
new file mode 100644
index 0000000..d89bd53
--- /dev/null
+++ b/src/libsbgnpy/libsbgn.py
@@ -0,0 +1,4545 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Generated Mon Nov 28 14:10:23 2016 by generateDS.py version 2.24a.
+#
+# Command line options:
+#   ('-o', 'libsbgn.py')
+#   ('-s', 'libsbgnSubs.py')
+#
+# Command line arguments:
+#   SBGN.xsd
+#
+# Command line:
+#   /usr/local/bin/generateDS.py -o "libsbgn.py" -s "libsbgnSubs.py" SBGN.xsd
+#
+# Current working directory (os.getcwd()):
+#   schema
+
+import base64
+import datetime as datetime_
+import re as re_
+import sys
+import warnings as warnings_
+
+
+try:
+    from lxml import etree as etree_
+except ImportError:
+    from xml.etree import ElementTree as etree_
+
+from .libsbgnTypes import ArcClass, GlyphClass, Language, Orientation
+
+
+Validate_simpletypes_ = True
+BaseStrType_ = str
+
+
+def parsexml_(infile, parser=None, **kwargs):
+    if parser is None:
+        # Use the lxml ElementTree compatible parser so that, e.g.,
+        #   we ignore comments.
+        try:
+            parser = etree_.ETCompatXMLParser()
+        except AttributeError:
+            # fallback to xml.etree
+            parser = etree_.XMLParser()
+    doc = etree_.parse(infile, parser=parser, **kwargs)
+    return doc
+
+
+#
+# User methods
+#
+# Calls to the methods in these classes are generated by generateDS.py.
+# You can replace these methods by re-implementing the following class
+#   in a module named generatedssuper.py.
+
+try:
+    from generatedssuper import GeneratedsSuper
+except ImportError as exp:
+
+    class GeneratedsSuper(object):
+        tzoff_pattern = re_.compile(r"(\+|-)((0\d|1[0-3]):[0-5]\d|14:00)$")
+
+        class _FixedOffsetTZ(datetime_.tzinfo):
+            def __init__(self, offset, name):
+                self.__offset = datetime_.timedelta(minutes=offset)
+                self.__name = name
+
+            def utcoffset(self, dt):
+                return self.__offset
+
+            def tzname(self, dt):
+                return self.__name
+
+            def dst(self, dt):
+                return None
+
+        def gds_format_string(self, input_data, input_name=""):
+            return input_data
+
+        def gds_validate_string(self, input_data, node=None, input_name=""):
+            if not input_data:
+                return ""
+            else:
+                return input_data
+
+        def gds_format_base64(self, input_data, input_name=""):
+            return base64.b64encode(input_data)
+
+        def gds_validate_base64(self, input_data, node=None, input_name=""):
+            return input_data
+
+        def gds_format_integer(self, input_data, input_name=""):
+            return "%d" % input_data
+
+        def gds_validate_integer(self, input_data, node=None, input_name=""):
+            return input_data
+
+        def gds_format_integer_list(self, input_data, input_name=""):
+            return "%s" % " ".join(input_data)
+
+        def gds_validate_integer_list(self, input_data, node=None, input_name=""):
+            values = input_data.split()
+            for value in values:
+                try:
+                    int(value)
+                except (TypeError, ValueError):
+                    raise_parse_error(node, "Requires sequence of integers")
+            return values
+
+        def gds_format_float(self, input_data, input_name=""):
+            return ("%.15f" % input_data).rstrip("0")
+
+        def gds_validate_float(self, input_data, node=None, input_name=""):
+            return input_data
+
+        def gds_format_float_list(self, input_data, input_name=""):
+            return "%s" % " ".join(input_data)
+
+        def gds_validate_float_list(self, input_data, node=None, input_name=""):
+            values = input_data.split()
+            for value in values:
+                try:
+                    float(value)
+                except (TypeError, ValueError):
+                    raise_parse_error(node, "Requires sequence of floats")
+            return values
+
+        def gds_format_double(self, input_data, input_name=""):
+            return "%e" % input_data
+
+        def gds_validate_double(self, input_data, node=None, input_name=""):
+            return input_data
+
+        def gds_format_double_list(self, input_data, input_name=""):
+            return "%s" % " ".join(input_data)
+
+        def gds_validate_double_list(self, input_data, node=None, input_name=""):
+            values = input_data.split()
+            for value in values:
+                try:
+                    float(value)
+                except (TypeError, ValueError):
+                    raise_parse_error(node, "Requires sequence of doubles")
+            return values
+
+        def gds_format_boolean(self, input_data, input_name=""):
+            return ("%s" % input_data).lower()
+
+        def gds_validate_boolean(self, input_data, node=None, input_name=""):
+            return input_data
+
+        def gds_format_boolean_list(self, input_data, input_name=""):
+            return "%s" % " ".join(input_data)
+
+        def gds_validate_boolean_list(self, input_data, node=None, input_name=""):
+            values = input_data.split()
+            for value in values:
+                if value not in (
+                    "true",
+                    "1",
+                    "false",
+                    "0",
+                ):
+                    raise_parse_error(
+                        node,
+                        "Requires sequence of booleans " '("true", "1", "false", "0")',
+                    )
+            return values
+
+        def gds_validate_datetime(self, input_data, node=None, input_name=""):
+            return input_data
+
+        def gds_format_datetime(self, input_data, input_name=""):
+            if input_data.microsecond == 0:
+                _svalue = "%04d-%02d-%02dT%02d:%02d:%02d" % (
+                    input_data.year,
+                    input_data.month,
+                    input_data.day,
+                    input_data.hour,
+                    input_data.minute,
+                    input_data.second,
+                )
+            else:
+                _svalue = "%04d-%02d-%02dT%02d:%02d:%02d.%s" % (
+                    input_data.year,
+                    input_data.month,
+                    input_data.day,
+                    input_data.hour,
+                    input_data.minute,
+                    input_data.second,
+                    ("%f" % (float(input_data.microsecond) / 1000000))[2:],
+                )
+            if input_data.tzinfo is not None:
+                tzoff = input_data.tzinfo.utcoffset(input_data)
+                if tzoff is not None:
+                    total_seconds = tzoff.seconds + (86400 * tzoff.days)
+                    if total_seconds == 0:
+                        _svalue += "Z"
+                    else:
+                        if total_seconds < 0:
+                            _svalue += "-"
+                            total_seconds *= -1
+                        else:
+                            _svalue += "+"
+                        hours = total_seconds // 3600
+                        minutes = (total_seconds - (hours * 3600)) // 60
+                        _svalue += "{0:02d}:{1:02d}".format(hours, minutes)
+            return _svalue
+
+        @classmethod
+        def gds_parse_datetime(cls, input_data):
+            tz = None
+            if input_data[-1] == "Z":
+                tz = GeneratedsSuper._FixedOffsetTZ(0, "UTC")
+                input_data = input_data[:-1]
+            else:
+                results = GeneratedsSuper.tzoff_pattern.search(input_data)
+                if results is not None:
+                    tzoff_parts = results.group(2).split(":")
+                    tzoff = int(tzoff_parts[0]) * 60 + int(tzoff_parts[1])
+                    if results.group(1) == "-":
+                        tzoff *= -1
+                    tz = GeneratedsSuper._FixedOffsetTZ(tzoff, results.group(0))
+                    input_data = input_data[:-6]
+            time_parts = input_data.split(".")
+            if len(time_parts) > 1:
+                micro_seconds = int(float("0." + time_parts[1]) * 1000000)
+                input_data = "%s.%s" % (
+                    time_parts[0],
+                    micro_seconds,
+                )
+                dt = datetime_.datetime.strptime(input_data, "%Y-%m-%dT%H:%M:%S.%f")
+            else:
+                dt = datetime_.datetime.strptime(input_data, "%Y-%m-%dT%H:%M:%S")
+            dt = dt.replace(tzinfo=tz)
+            return dt
+
+        def gds_validate_date(self, input_data, node=None, input_name=""):
+            return input_data
+
+        def gds_format_date(self, input_data, input_name=""):
+            _svalue = "%04d-%02d-%02d" % (
+                input_data.year,
+                input_data.month,
+                input_data.day,
+            )
+            try:
+                if input_data.tzinfo is not None:
+                    tzoff = input_data.tzinfo.utcoffset(input_data)
+                    if tzoff is not None:
+                        total_seconds = tzoff.seconds + (86400 * tzoff.days)
+                        if total_seconds == 0:
+                            _svalue += "Z"
+                        else:
+                            if total_seconds < 0:
+                                _svalue += "-"
+                                total_seconds *= -1
+                            else:
+                                _svalue += "+"
+                            hours = total_seconds // 3600
+                            minutes = (total_seconds - (hours * 3600)) // 60
+                            _svalue += "{0:02d}:{1:02d}".format(hours, minutes)
+            except AttributeError:
+                pass
+            return _svalue
+
+        @classmethod
+        def gds_parse_date(cls, input_data):
+            tz = None
+            if input_data[-1] == "Z":
+                tz = GeneratedsSuper._FixedOffsetTZ(0, "UTC")
+                input_data = input_data[:-1]
+            else:
+                results = GeneratedsSuper.tzoff_pattern.search(input_data)
+                if results is not None:
+                    tzoff_parts = results.group(2).split(":")
+                    tzoff = int(tzoff_parts[0]) * 60 + int(tzoff_parts[1])
+                    if results.group(1) == "-":
+                        tzoff *= -1
+                    tz = GeneratedsSuper._FixedOffsetTZ(tzoff, results.group(0))
+                    input_data = input_data[:-6]
+            dt = datetime_.datetime.strptime(input_data, "%Y-%m-%d")
+            dt = dt.replace(tzinfo=tz)
+            return dt.date()
+
+        def gds_validate_time(self, input_data, node=None, input_name=""):
+            return input_data
+
+        def gds_format_time(self, input_data, input_name=""):
+            if input_data.microsecond == 0:
+                _svalue = "%02d:%02d:%02d" % (
+                    input_data.hour,
+                    input_data.minute,
+                    input_data.second,
+                )
+            else:
+                _svalue = "%02d:%02d:%02d.%s" % (
+                    input_data.hour,
+                    input_data.minute,
+                    input_data.second,
+                    ("%f" % (float(input_data.microsecond) / 1000000))[2:],
+                )
+            if input_data.tzinfo is not None:
+                tzoff = input_data.tzinfo.utcoffset(input_data)
+                if tzoff is not None:
+                    total_seconds = tzoff.seconds + (86400 * tzoff.days)
+                    if total_seconds == 0:
+                        _svalue += "Z"
+                    else:
+                        if total_seconds < 0:
+                            _svalue += "-"
+                            total_seconds *= -1
+                        else:
+                            _svalue += "+"
+                        hours = total_seconds // 3600
+                        minutes = (total_seconds - (hours * 3600)) // 60
+                        _svalue += "{0:02d}:{1:02d}".format(hours, minutes)
+            return _svalue
+
+        def gds_validate_simple_patterns(self, patterns, target):
+            # pat is a list of lists of strings/patterns.  We should:
+            # - AND the outer elements
+            # - OR the inner elements
+            found1 = True
+            for patterns1 in patterns:
+                found2 = False
+                for patterns2 in patterns1:
+                    if re_.search(patterns2, target) is not None:
+                        found2 = True
+                        break
+                if not found2:
+                    found1 = False
+                    break
+            return found1
+
+        @classmethod
+        def gds_parse_time(cls, input_data):
+            tz = None
+            if input_data[-1] == "Z":
+                tz = GeneratedsSuper._FixedOffsetTZ(0, "UTC")
+                input_data = input_data[:-1]
+            else:
+                results = GeneratedsSuper.tzoff_pattern.search(input_data)
+                if results is not None:
+                    tzoff_parts = results.group(2).split(":")
+                    tzoff = int(tzoff_parts[0]) * 60 + int(tzoff_parts[1])
+                    if results.group(1) == "-":
+                        tzoff *= -1
+                    tz = GeneratedsSuper._FixedOffsetTZ(tzoff, results.group(0))
+                    input_data = input_data[:-6]
+            if len(input_data.split(".")) > 1:
+                dt = datetime_.datetime.strptime(input_data, "%H:%M:%S.%f")
+            else:
+                dt = datetime_.datetime.strptime(input_data, "%H:%M:%S")
+            dt = dt.replace(tzinfo=tz)
+            return dt.time()
+
+        def gds_str_lower(self, instring):
+            return instring.lower()
+
+        def get_path_(self, node):
+            path_list = []
+            self.get_path_list_(node, path_list)
+            path_list.reverse()
+            path = "/".join(path_list)
+            return path
+
+        Tag_strip_pattern_ = re_.compile(r"\{.*\}")
+
+        def get_path_list_(self, node, path_list):
+            if node is None:
+                return
+            tag = GeneratedsSuper.Tag_strip_pattern_.sub("", node.tag)
+            if tag:
+                path_list.append(tag)
+            self.get_path_list_(node.getparent(), path_list)
+
+        def get_class_obj_(self, node, default_class=None):
+            class_obj1 = default_class
+            if "xsi" in node.nsmap:
+                classname = node.get("{%s}type" % node.nsmap["xsi"])
+                if classname is not None:
+                    names = classname.split(":")
+                    if len(names) == 2:
+                        classname = names[1]
+                    class_obj2 = globals().get(classname)
+                    if class_obj2 is not None:
+                        class_obj1 = class_obj2
+            return class_obj1
+
+        def gds_build_any(self, node, type_name=None):
+            return None
+
+        @classmethod
+        def gds_reverse_node_mapping(cls, mapping):
+            return dict(((v, k) for k, v in mapping.iteritems()))
+
+        @staticmethod
+        def gds_encode(instring):
+            if sys.version_info.major == 2:
+                return instring.encode(ExternalEncoding)
+            else:
+                return instring
+
+    def getSubclassFromModule_(module, class_):
+        """Get the subclass of a class from a specific module."""
+        name = class_.__name__ + "Sub"
+        if hasattr(module, name):
+            return getattr(module, name)
+        else:
+            return None
+
+
+#
+# If you have installed IPython you can uncomment and use the following.
+# IPython is available from http://ipython.scipy.org/.
+#
+
+# from IPython.Shell import IPShellEmbed
+# args = ''
+# ipshell = IPShellEmbed(args,
+#     banner = 'Dropping into IPython',
+# exit_msg = 'Leaving Interpreter, back to program.')
+
+# Then use the following line where and when you want to drop into the
+# IPython shell:
+#    ipshell('<some message> -- Entering ipshell.\nHit Ctrl-D to exit')
+
+#
+# Globals
+#
+
+ExternalEncoding = "utf8"
+Tag_pattern_ = re_.compile(r"({.*})?(.*)")
+String_cleanup_pat_ = re_.compile(r"[\n\r\s]+")
+Namespace_extract_pat_ = re_.compile(r"{(.*)}(.*)")
+CDATA_pattern_ = re_.compile(r"<!\[CDATA\[.*?\]\]>", re_.DOTALL)
+
+# Change this to redirect the generated superclass module to use a
+# specific subclass module.
+CurrentSubclassModule_ = None
+
+#
+# Support/utility functions.
+#
+
+
+def showIndent(outfile, level, pretty_print=True):
+    if pretty_print:
+        for idx in range(level):
+            outfile.write("    ")
+
+
+def quote_xml(inStr):
+    "Escape markup chars, but do not modify CDATA sections."
+    if not inStr:
+        return ""
+    s1 = isinstance(inStr, BaseStrType_) and inStr or "%s" % inStr
+    s2 = ""
+    pos = 0
+    matchobjects = CDATA_pattern_.finditer(s1)
+    for mo in matchobjects:
+        s3 = s1[pos : mo.start()]
+        s2 += quote_xml_aux(s3)
+        s2 += s1[mo.start() : mo.end()]
+        pos = mo.end()
+    s3 = s1[pos:]
+    s2 += quote_xml_aux(s3)
+    return s2
+
+
+def quote_xml_aux(inStr):
+    s1 = inStr.replace("&", "&amp;")
+    s1 = s1.replace("<", "&lt;")
+    s1 = s1.replace(">", "&gt;")
+    return s1
+
+
+def quote_attrib(inStr):
+    s1 = isinstance(inStr, BaseStrType_) and inStr or "%s" % inStr
+    s1 = s1.replace("&", "&amp;")
+    s1 = s1.replace("<", "&lt;")
+    s1 = s1.replace(">", "&gt;")
+    if '"' in s1:
+        if "'" in s1:
+            s1 = '"%s"' % s1.replace('"', "&quot;")
+        else:
+            s1 = "'%s'" % s1
+    else:
+        s1 = '"%s"' % s1
+    return s1
+
+
+def quote_python(inStr):
+    s1 = inStr
+    if s1.find("'") == -1:
+        if s1.find("\n") == -1:
+            return "'%s'" % s1
+        else:
+            return "'''%s'''" % s1
+    else:
+        if s1.find('"') != -1:
+            s1 = s1.replace('"', '\\"')
+        if s1.find("\n") == -1:
+            return '"%s"' % s1
+        else:
+            return '"""%s"""' % s1
+
+
+def get_all_text_(node):
+    if node.text is not None:
+        text = node.text
+    else:
+        text = ""
+    for child in node:
+        if child.tail is not None:
+            text += child.tail
+    return text
+
+
+def find_attr_value_(attr_name, node):
+    attrs = node.attrib
+    attr_parts = attr_name.split(":")
+    value = None
+    if len(attr_parts) == 1:
+        value = attrs.get(attr_name)
+    elif len(attr_parts) == 2:
+        prefix, name = attr_parts
+        namespace = node.nsmap.get(prefix)
+        if namespace is not None:
+            value = attrs.get(
+                "{%s}%s"
+                % (
+                    namespace,
+                    name,
+                )
+            )
+    return value
+
+
+class GDSParseError(Exception):
+    pass
+
+
+def raise_parse_error(node, msg):
+    msg = "%s (element %s/line %d)" % (
+        msg,
+        node.tag,
+        node.sourceline,
+    )
+    raise GDSParseError(msg)
+
+
+class MixedContainer:
+    # Constants for category:
+    CategoryNone = 0
+    CategoryText = 1
+    CategorySimple = 2
+    CategoryComplex = 3
+    # Constants for content_type:
+    TypeNone = 0
+    TypeText = 1
+    TypeString = 2
+    TypeInteger = 3
+    TypeFloat = 4
+    TypeDecimal = 5
+    TypeDouble = 6
+    TypeBoolean = 7
+    TypeBase64 = 8
+
+    def __init__(self, category, content_type, name, value):
+        self.category = category
+        self.content_type = content_type
+        self.name = name
+        self.value = value
+
+    def getCategory(self):
+        return self.category
+
+    def getContenttype(self, content_type):
+        return self.content_type
+
+    def getValue(self):
+        return self.value
+
+    def getName(self):
+        return self.name
+
+    def export(self, outfile, level, name, namespace, pretty_print=True):
+        if self.category == MixedContainer.CategoryText:
+            # Prevent exporting empty content as empty lines.
+            if self.value.strip():
+                outfile.write(self.value)
+        elif self.category == MixedContainer.CategorySimple:
+            self.exportSimple(outfile, level, name)
+        else:  # category == MixedContainer.CategoryComplex
+            self.value.export(
+                outfile, level, namespace, name, pretty_print=pretty_print
+            )
+
+    def exportSimple(self, outfile, level, name):
+        if self.content_type == MixedContainer.TypeString:
+            outfile.write("<%s>%s</%s>" % (self.name, self.value, self.name))
+        elif (
+            self.content_type == MixedContainer.TypeInteger
+            or self.content_type == MixedContainer.TypeBoolean
+        ):
+            outfile.write("<%s>%d</%s>" % (self.name, self.value, self.name))
+        elif (
+            self.content_type == MixedContainer.TypeFloat
+            or self.content_type == MixedContainer.TypeDecimal
+        ):
+            outfile.write("<%s>%f</%s>" % (self.name, self.value, self.name))
+        elif self.content_type == MixedContainer.TypeDouble:
+            outfile.write("<%s>%g</%s>" % (self.name, self.value, self.name))
+        elif self.content_type == MixedContainer.TypeBase64:
+            outfile.write(
+                "<%s>%s</%s>" % (self.name, base64.b64encode(self.value), self.name)
+            )
+
+    def to_etree(self, element):
+        if self.category == MixedContainer.CategoryText:
+            # Prevent exporting empty content as empty lines.
+            if self.value.strip():
+                if len(element) > 0:
+                    if element[-1].tail is None:
+                        element[-1].tail = self.value
+                    else:
+                        element[-1].tail += self.value
+                else:
+                    if element.text is None:
+                        element.text = self.value
+                    else:
+                        element.text += self.value
+        elif self.category == MixedContainer.CategorySimple:
+            subelement = etree_.SubElement(element, "%s" % self.name)
+            subelement.text = self.to_etree_simple()
+        else:  # category == MixedContainer.CategoryComplex
+            self.value.to_etree(element)
+
+    def to_etree_simple(self):
+        if self.content_type == MixedContainer.TypeString:
+            text = self.value
+        elif (
+            self.content_type == MixedContainer.TypeInteger
+            or self.content_type == MixedContainer.TypeBoolean
+        ):
+            text = "%d" % self.value
+        elif (
+            self.content_type == MixedContainer.TypeFloat
+            or self.content_type == MixedContainer.TypeDecimal
+        ):
+            text = "%f" % self.value
+        elif self.content_type == MixedContainer.TypeDouble:
+            text = "%g" % self.value
+        elif self.content_type == MixedContainer.TypeBase64:
+            text = "%s" % base64.b64encode(self.value)
+        return text
+
+    def exportLiteral(self, outfile, level, name):
+        if self.category == MixedContainer.CategoryText:
+            showIndent(outfile, level)
+            outfile.write(
+                'model_.MixedContainer(%d, %d, "%s", "%s"),\n'
+                % (self.category, self.content_type, self.name, self.value)
+            )
+        elif self.category == MixedContainer.CategorySimple:
+            showIndent(outfile, level)
+            outfile.write(
+                'model_.MixedContainer(%d, %d, "%s", "%s"),\n'
+                % (self.category, self.content_type, self.name, self.value)
+            )
+        else:  # category == MixedContainer.CategoryComplex
+            showIndent(outfile, level)
+            outfile.write(
+                'model_.MixedContainer(%d, %d, "%s",\n'
+                % (
+                    self.category,
+                    self.content_type,
+                    self.name,
+                )
+            )
+            self.value.exportLiteral(outfile, level + 1)
+            showIndent(outfile, level)
+            outfile.write(")\n")
+
+
+class MemberSpec_(object):
+    def __init__(self, name="", data_type="", container=0):
+        self.name = name
+        self.data_type = data_type
+        self.container = container
+
+    def set_name(self, name):
+        self.name = name
+
+    def get_name(self):
+        return self.name
+
+    def set_data_type(self, data_type):
+        self.data_type = data_type
+
+    def get_data_type_chain(self):
+        return self.data_type
+
+    def get_data_type(self):
+        if isinstance(self.data_type, list):
+            if len(self.data_type) > 0:
+                return self.data_type[-1]
+            else:
+                return "xs:string"
+        else:
+            return self.data_type
+
+    def set_container(self, container):
+        self.container = container
+
+    def get_container(self):
+        return self.container
+
+
+def _cast(typ, value):
+    if typ is None or value is None:
+        return value
+    return typ(value)
+
+
+#
+# Data representation classes.
+#
+
+
+class SBGNBase(GeneratedsSuper):
+    """The SBGNBase type is the base type of all main components in SBGN.
+    It supports attaching metadata, notes and annotations to
+    components."""
+
+    subclass = None
+    superclass = None
+
+    def __init__(self, notes=None, extension=None, extensiontype_=None):
+        self.original_tagname_ = None
+        self.notes = notes
+        self.extension = extension
+        self.extensiontype_ = extensiontype_
+
+    def factory(*args_, **kwargs_):
+        if CurrentSubclassModule_ is not None:
+            subclass = getSubclassFromModule_(CurrentSubclassModule_, SBGNBase)
+            if subclass is not None:
+                return subclass(*args_, **kwargs_)
+        if SBGNBase.subclass:
+            return SBGNBase.subclass(*args_, **kwargs_)
+        else:
+            return SBGNBase(*args_, **kwargs_)
+
+    factory = staticmethod(factory)
+
+    def get_notes(self):
+        return self.notes
+
+    def set_notes(self, notes):
+        self.notes = notes
+
+    def get_extension(self):
+        return self.extension
+
+    def set_extension(self, extension):
+        self.extension = extension
+
+    def get_extensiontype_(self):
+        return self.extensiontype_
+
+    def set_extensiontype_(self, extensiontype_):
+        self.extensiontype_ = extensiontype_
+
+    def hasContent_(self):
+        if self.notes is not None or self.extension is not None:
+            return True
+        else:
+            return False
+
+    def write_file(self, outfile, namespace="sbgn"):
+        """Write SBGN to file.
+
+        This also fixes the issues of the sbgn namespace prefix.
+
+        :param outfile: SBGN file to write
+        :param namespace:
+        :return:
+        """
+        f = open(outfile, "w")
+        f.write('<?xml version="1.0" encoding="UTF-8"?>\n')
+        self.export(f, level=0, namespace_="sbgn", name_="")
+        f.close()
+
+        # this is a bad hack to remove the namespaces, because
+        # most of the SBGN tools do not support them.
+        import fileinput
+
+        f = fileinput.input(outfile, inplace=True)
+
+        for line in f:
+            # remove prefix from closing tags, and unnecessary namespace
+            line = line.replace(' xmlns:sbgn="http://sbgn.org/libsbgn/0.2"', "")
+            line = line.replace("sbgn:", "")
+            line = line.replace("<sbgn>", '<sbgn xmlns="http://sbgn.org/libsbgn/0.2">')
+            print(line, end="")
+
+        f.close()
+
+    def export(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="sbgn",
+        namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"',
+        pretty_print=True,
+    ):
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        if self.original_tagname_ is not None:
+            name_ = self.original_tagname_
+        showIndent(outfile, level, pretty_print)
+        outfile.write(
+            "<%s%s%s"
+            % (
+                namespace_,
+                name_,
+                namespacedef_ and " " + namespacedef_ or "",
+            )
+        )
+        already_processed = set()
+        self.exportAttributes(
+            outfile, level, already_processed, namespace_, name_="sbgn"
+        )
+        if self.hasContent_():
+            outfile.write(">%s" % (eol_,))
+            self.exportChildren(
+                outfile,
+                level + 1,
+                namespace_="sbgn:",
+                name_="sbgn",
+                pretty_print=pretty_print,
+            )
+            showIndent(outfile, level, pretty_print)
+            outfile.write("</%s%s>%s" % (namespace_, name_, eol_))
+        else:
+            outfile.write("/>%s" % (eol_,))
+
+    def exportAttributes(
+        self, outfile, level, already_processed, namespace_="sbgn:", name_="SBGNBase"
+    ):
+        if self.extensiontype_ is not None and "xsi:type" not in already_processed:
+            already_processed.add("xsi:type")
+            outfile.write(' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"')
+            outfile.write(' xsi:type="%s"' % self.extensiontype_)
+        pass
+
+    def exportChildren(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="SBGNBase",
+        fromsubclass_=False,
+        pretty_print=True,
+    ):
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        if self.notes is not None:
+            self.notes.export(
+                outfile, level, namespace_, name_="notes", pretty_print=pretty_print
+            )
+        if self.extension is not None:
+            self.extension.export(
+                outfile, level, namespace_, name_="extension", pretty_print=pretty_print
+            )
+
+    def build(self, node):
+        already_processed = set()
+        self.buildAttributes(node, node.attrib, already_processed)
+        for child in node:
+            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+            self.buildChildren(child, node, nodeName_)
+        return self
+
+    def buildAttributes(self, node, attrs, already_processed):
+        value = find_attr_value_("xsi:type", node)
+        if value is not None and "xsi:type" not in already_processed:
+            already_processed.add("xsi:type")
+            self.extensiontype_ = value
+
+    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+        if nodeName_ == "notes":
+            obj_ = notesType.factory()
+            obj_.build(child_)
+            self.notes = obj_
+            obj_.original_tagname_ = "notes"
+        elif nodeName_ == "extension":
+            obj_ = extensionType.factory()
+            obj_.build(child_)
+            self.extension = obj_
+            obj_.original_tagname_ = "extension"
+
+
+# end class SBGNBase
+
+
+class point(SBGNBase):
+    """The point element is characterized by PointAttributes, which
+    describe absolute 2D cartesian coordinates. Namely: x
+    (horizontal, from left to right), y (vertical, from top to
+    bottom). The origin is located in the top-left corner of the
+    map. There is no unit: proportions must be preserved, but the
+    maps can be drawn at any scale. In the test files examples, to
+    obtain a drawing similar to the reference *.png file, values in
+    the corresponding *.sbgn file should be read as pixels."""
+
+    subclass = None
+    superclass = SBGNBase
+
+    def __init__(self, notes=None, extension=None, x=None, y=None):
+        self.original_tagname_ = None
+        super(point, self).__init__(
+            notes,
+            extension,
+        )
+        self.x = _cast(float, x)
+        self.y = _cast(float, y)
+
+    def factory(*args_, **kwargs_):
+        if CurrentSubclassModule_ is not None:
+            subclass = getSubclassFromModule_(CurrentSubclassModule_, point)
+            if subclass is not None:
+                return subclass(*args_, **kwargs_)
+        if point.subclass:
+            return point.subclass(*args_, **kwargs_)
+        else:
+            return point(*args_, **kwargs_)
+
+    factory = staticmethod(factory)
+
+    def get_x(self):
+        return self.x
+
+    def set_x(self, x):
+        self.x = x
+
+    def get_y(self):
+        return self.y
+
+    def set_y(self, y):
+        self.y = y
+
+    def hasContent_(self):
+        if super(point, self).hasContent_():
+            return True
+        else:
+            return False
+
+    def export(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="point",
+        namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"',
+        pretty_print=True,
+    ):
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        if self.original_tagname_ is not None:
+            name_ = self.original_tagname_
+        showIndent(outfile, level, pretty_print)
+        outfile.write(
+            "<%s%s%s"
+            % (
+                namespace_,
+                name_,
+                namespacedef_ and " " + namespacedef_ or "",
+            )
+        )
+        already_processed = set()
+        self.exportAttributes(
+            outfile, level, already_processed, namespace_, name_="point"
+        )
+        if self.hasContent_():
+            outfile.write(">%s" % (eol_,))
+            self.exportChildren(
+                outfile,
+                level + 1,
+                namespace_="sbgn:",
+                name_="point",
+                pretty_print=pretty_print,
+            )
+            showIndent(outfile, level, pretty_print)
+            outfile.write("</%s%s>%s" % (namespace_, name_, eol_))
+        else:
+            outfile.write("/>%s" % (eol_,))
+
+    def exportAttributes(
+        self, outfile, level, already_processed, namespace_="sbgn:", name_="point"
+    ):
+        super(point, self).exportAttributes(
+            outfile, level, already_processed, namespace_, name_="point"
+        )
+        if self.x is not None and "x" not in already_processed:
+            already_processed.add("x")
+            outfile.write(' x="%s"' % self.gds_format_float(self.x, input_name="x"))
+        if self.y is not None and "y" not in already_processed:
+            already_processed.add("y")
+            outfile.write(' y="%s"' % self.gds_format_float(self.y, input_name="y"))
+
+    def exportChildren(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="point",
+        fromsubclass_=False,
+        pretty_print=True,
+    ):
+        super(point, self).exportChildren(
+            outfile, level, namespace_, name_, True, pretty_print=pretty_print
+        )
+
+    def build(self, node):
+        already_processed = set()
+        self.buildAttributes(node, node.attrib, already_processed)
+        for child in node:
+            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+            self.buildChildren(child, node, nodeName_)
+        return self
+
+    def buildAttributes(self, node, attrs, already_processed):
+        value = find_attr_value_("x", node)
+        if value is not None and "x" not in already_processed:
+            already_processed.add("x")
+            try:
+                self.x = float(value)
+            except ValueError as exp:
+                raise ValueError("Bad float/double attribute (x): %s" % exp)
+        value = find_attr_value_("y", node)
+        if value is not None and "y" not in already_processed:
+            already_processed.add("y")
+            try:
+                self.y = float(value)
+            except ValueError as exp:
+                raise ValueError("Bad float/double attribute (y): %s" % exp)
+        super(point, self).buildAttributes(node, attrs, already_processed)
+
+    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+        super(point, self).buildChildren(child_, node, nodeName_, True)
+        pass
+
+
+# end class point
+
+
+class bbox(SBGNBase):
+    """The bbox element describes a rectangle. This rectangle is defined
+    by: PointAttributes corresponding to the 2D coordinates of the
+    top left corner, width and height attributes. The rectangle
+    corresponds to the outer bounding box of a shape. The shape
+    itself can be irregular (for instance in the case of some
+    compartments). In the case of process nodes, the bounding box
+    only concerns the central glyph (square, or circle), the
+    input/output ports are not included, and neither are the lines
+    connecting them to the central glyph. A bbox is required for all
+    glyphs, and is optional for labels."""
+
+    subclass = None
+    superclass = SBGNBase
+
+    def __init__(self, x=None, y=None, w=None, h=None, notes=None, extension=None):
+        self.original_tagname_ = None
+        super(bbox, self).__init__(
+            notes,
+            extension,
+        )
+        self.w = _cast(float, w)
+        self.h = _cast(float, h)
+        self.x = _cast(float, x)
+        self.y = _cast(float, y)
+
+    def factory(*args_, **kwargs_):
+        if CurrentSubclassModule_ is not None:
+            subclass = getSubclassFromModule_(CurrentSubclassModule_, bbox)
+            if subclass is not None:
+                return subclass(*args_, **kwargs_)
+        if bbox.subclass:
+            return bbox.subclass(*args_, **kwargs_)
+        else:
+            return bbox(*args_, **kwargs_)
+
+    factory = staticmethod(factory)
+
+    def get_w(self):
+        return self.w
+
+    def set_w(self, w):
+        self.w = w
+
+    def get_h(self):
+        return self.h
+
+    def set_h(self, h):
+        self.h = h
+
+    def get_x(self):
+        return self.x
+
+    def set_x(self, x):
+        self.x = x
+
+    def get_y(self):
+        return self.y
+
+    def set_y(self, y):
+        self.y = y
+
+    def hasContent_(self):
+        if super(bbox, self).hasContent_():
+            return True
+        else:
+            return False
+
+    def export(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="bbox",
+        namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"',
+        pretty_print=True,
+    ):
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        if self.original_tagname_ is not None:
+            name_ = self.original_tagname_
+        showIndent(outfile, level, pretty_print)
+        outfile.write(
+            "<%s%s%s"
+            % (
+                namespace_,
+                name_,
+                namespacedef_ and " " + namespacedef_ or "",
+            )
+        )
+        already_processed = set()
+        self.exportAttributes(
+            outfile, level, already_processed, namespace_, name_="bbox"
+        )
+        if self.hasContent_():
+            outfile.write(">%s" % (eol_,))
+            self.exportChildren(
+                outfile,
+                level + 1,
+                namespace_="sbgn:",
+                name_="bbox",
+                pretty_print=pretty_print,
+            )
+            showIndent(outfile, level, pretty_print)
+            outfile.write("</%s%s>%s" % (namespace_, name_, eol_))
+        else:
+            outfile.write("/>%s" % (eol_,))
+
+    def exportAttributes(
+        self, outfile, level, already_processed, namespace_="sbgn:", name_="bbox"
+    ):
+        super(bbox, self).exportAttributes(
+            outfile, level, already_processed, namespace_, name_="bbox"
+        )
+        if self.w is not None and "w" not in already_processed:
+            already_processed.add("w")
+            outfile.write(' w="%s"' % self.gds_format_float(self.w, input_name="w"))
+        if self.h is not None and "h" not in already_processed:
+            already_processed.add("h")
+            outfile.write(' h="%s"' % self.gds_format_float(self.h, input_name="h"))
+        if self.x is not None and "x" not in already_processed:
+            already_processed.add("x")
+            outfile.write(' x="%s"' % self.gds_format_float(self.x, input_name="x"))
+        if self.y is not None and "y" not in already_processed:
+            already_processed.add("y")
+            outfile.write(' y="%s"' % self.gds_format_float(self.y, input_name="y"))
+
+    def exportChildren(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="bbox",
+        fromsubclass_=False,
+        pretty_print=True,
+    ):
+        super(bbox, self).exportChildren(
+            outfile, level, namespace_, name_, True, pretty_print=pretty_print
+        )
+
+    def build(self, node):
+        already_processed = set()
+        self.buildAttributes(node, node.attrib, already_processed)
+        for child in node:
+            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+            self.buildChildren(child, node, nodeName_)
+        return self
+
+    def buildAttributes(self, node, attrs, already_processed):
+        value = find_attr_value_("w", node)
+        if value is not None and "w" not in already_processed:
+            already_processed.add("w")
+            try:
+                self.w = float(value)
+            except ValueError as exp:
+                raise ValueError("Bad float/double attribute (w): %s" % exp)
+        value = find_attr_value_("h", node)
+        if value is not None and "h" not in already_processed:
+            already_processed.add("h")
+            try:
+                self.h = float(value)
+            except ValueError as exp:
+                raise ValueError("Bad float/double attribute (h): %s" % exp)
+        value = find_attr_value_("x", node)
+        if value is not None and "x" not in already_processed:
+            already_processed.add("x")
+            try:
+                self.x = float(value)
+            except ValueError as exp:
+                raise ValueError("Bad float/double attribute (x): %s" % exp)
+        value = find_attr_value_("y", node)
+        if value is not None and "y" not in already_processed:
+            already_processed.add("y")
+            try:
+                self.y = float(value)
+            except ValueError as exp:
+                raise ValueError("Bad float/double attribute (y): %s" % exp)
+        super(bbox, self).buildAttributes(node, attrs, already_processed)
+
+    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+        super(bbox, self).buildChildren(child_, node, nodeName_, True)
+        pass
+
+
+# end class bbox
+
+
+class label(SBGNBase):
+    """The label element describes the text accompanying a glyph. The text
+    attribute is mandatory. Its position can be specified by a bbox
+    (optional). Tools are free to display the text in any style
+    (font, font-size, etc.) The bbox element of a label is optional.
+    When no bbox is defined, the bbox of the parent glyph is
+    inherited. The label should be drawn centered horizontally and
+    vertically in the bbox. When the bbox is inherited, the label
+    can freely spill outside (just like it can spill outside its
+    parent glyph). An explicit bbox provides a stronger hint
+    regarding what surface the label should cover. It defines an
+    upper boundary outside of which the label should (ideally) not
+    spill. It also represents a preferred size: the surface covered
+    by the label can be smaller, but should ideally be as close as
+    possible to the bbox. In most glyphs (EPNs, unit of information,
+    etc.), the label is supposed to be centered, so the bbox is
+    usually omitted (unless there's a specific hint to be shared
+    concerning the area the label should ideally cover). However,
+    labels can be drawn anywhere inside compartments or complex, so
+    these should preferably have an explicit bbox. Multi-line labels
+    are allowed. Line breaks are encoded as &#xA; as specified by
+    the XML standard."""
+
+    subclass = None
+    superclass = SBGNBase
+
+    def __init__(self, notes=None, extension=None, text=None, bbox=None):
+        self.original_tagname_ = None
+        super(label, self).__init__(
+            notes,
+            extension,
+        )
+        self.text = _cast(None, text)
+        self.bbox = bbox
+
+    def factory(*args_, **kwargs_):
+        if CurrentSubclassModule_ is not None:
+            subclass = getSubclassFromModule_(CurrentSubclassModule_, label)
+            if subclass is not None:
+                return subclass(*args_, **kwargs_)
+        if label.subclass:
+            return label.subclass(*args_, **kwargs_)
+        else:
+            return label(*args_, **kwargs_)
+
+    factory = staticmethod(factory)
+
+    def get_bbox(self):
+        return self.bbox
+
+    def set_bbox(self, bbox):
+        self.bbox = bbox
+
+    def get_text(self):
+        return self.text
+
+    def set_text(self, text):
+        self.text = text
+
+    def hasContent_(self):
+        if self.bbox is not None or super(label, self).hasContent_():
+            return True
+        else:
+            return False
+
+    def export(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="label",
+        namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"',
+        pretty_print=True,
+    ):
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        if self.original_tagname_ is not None:
+            name_ = self.original_tagname_
+        showIndent(outfile, level, pretty_print)
+        outfile.write(
+            "<%s%s%s"
+            % (
+                namespace_,
+                name_,
+                namespacedef_ and " " + namespacedef_ or "",
+            )
+        )
+        already_processed = set()
+        self.exportAttributes(
+            outfile, level, already_processed, namespace_, name_="label"
+        )
+        if self.hasContent_():
+            outfile.write(">%s" % (eol_,))
+            self.exportChildren(
+                outfile,
+                level + 1,
+                namespace_="sbgn:",
+                name_="label",
+                pretty_print=pretty_print,
+            )
+            showIndent(outfile, level, pretty_print)
+            outfile.write("</%s%s>%s" % (namespace_, name_, eol_))
+        else:
+            outfile.write("/>%s" % (eol_,))
+
+    def exportAttributes(
+        self, outfile, level, already_processed, namespace_="sbgn:", name_="label"
+    ):
+        super(label, self).exportAttributes(
+            outfile, level, already_processed, namespace_, name_="label"
+        )
+        if self.text is not None and "text" not in already_processed:
+            already_processed.add("text")
+            outfile.write(
+                " text=%s"
+                % (
+                    self.gds_encode(
+                        self.gds_format_string(
+                            quote_attrib(self.text), input_name="text"
+                        )
+                    ),
+                )
+            )
+
+    def exportChildren(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="label",
+        fromsubclass_=False,
+        pretty_print=True,
+    ):
+        super(label, self).exportChildren(
+            outfile, level, namespace_, name_, True, pretty_print=pretty_print
+        )
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        if self.bbox is not None:
+            self.bbox.export(
+                outfile,
+                level,
+                namespace_="sbgn:",
+                name_="bbox",
+                pretty_print=pretty_print,
+            )
+
+    def build(self, node):
+        already_processed = set()
+        self.buildAttributes(node, node.attrib, already_processed)
+        for child in node:
+            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+            self.buildChildren(child, node, nodeName_)
+        return self
+
+    def buildAttributes(self, node, attrs, already_processed):
+        value = find_attr_value_("text", node)
+        if value is not None and "text" not in already_processed:
+            already_processed.add("text")
+            self.text = value
+        super(label, self).buildAttributes(node, attrs, already_processed)
+
+    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+        if nodeName_ == "bbox":
+            obj_ = bbox.factory()
+            obj_.build(child_)
+            self.bbox = obj_
+            obj_.original_tagname_ = "bbox"
+        super(label, self).buildChildren(child_, node, nodeName_, True)
+
+
+# end class label
+
+
+class sbgn(SBGNBase):
+    """The sbgn element is the root of any SBGNML document. Currently each
+    document must contain exactly one map element."""
+
+    subclass = None
+    superclass = SBGNBase
+
+    def __init__(self, notes=None, extension=None, map=None):
+        self.original_tagname_ = None
+        super(sbgn, self).__init__(
+            notes,
+            extension,
+        )
+        self.map = map
+
+    def factory(*args_, **kwargs_):
+        if CurrentSubclassModule_ is not None:
+            subclass = getSubclassFromModule_(CurrentSubclassModule_, sbgn)
+            if subclass is not None:
+                return subclass(*args_, **kwargs_)
+        if sbgn.subclass:
+            return sbgn.subclass(*args_, **kwargs_)
+        else:
+            return sbgn(*args_, **kwargs_)
+
+    factory = staticmethod(factory)
+
+    def get_map(self):
+        return self.map
+
+    def set_map(self, map):
+        self.map = map
+
+    def hasContent_(self):
+        if self.map is not None or super(sbgn, self).hasContent_():
+            return True
+        else:
+            return False
+
+    def export(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="sbgn",
+        namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"',
+        pretty_print=True,
+    ):
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        if self.original_tagname_ is not None:
+            name_ = self.original_tagname_
+        showIndent(outfile, level, pretty_print)
+        outfile.write(
+            "<%s%s%s"
+            % (
+                namespace_,
+                name_,
+                namespacedef_ and " " + namespacedef_ or "",
+            )
+        )
+        already_processed = set()
+        self.exportAttributes(
+            outfile, level, already_processed, namespace_, name_="sbgn"
+        )
+        if self.hasContent_():
+            outfile.write(">%s" % (eol_,))
+            self.exportChildren(
+                outfile,
+                level + 1,
+                namespace_="sbgn:",
+                name_="sbgn",
+                pretty_print=pretty_print,
+            )
+            showIndent(outfile, level, pretty_print)
+            outfile.write("</%s%s>%s" % (namespace_, name_, eol_))
+        else:
+            outfile.write("/>%s" % (eol_,))
+
+    def exportAttributes(
+        self, outfile, level, already_processed, namespace_="sbgn:", name_="sbgn"
+    ):
+        super(sbgn, self).exportAttributes(
+            outfile, level, already_processed, namespace_, name_="sbgn"
+        )
+
+    def exportChildren(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="sbgn",
+        fromsubclass_=False,
+        pretty_print=True,
+    ):
+        super(sbgn, self).exportChildren(
+            outfile, level, namespace_, name_, True, pretty_print=pretty_print
+        )
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        if self.map is not None:
+            self.map.export(
+                outfile,
+                level,
+                namespace_="sbgn:",
+                name_="map",
+                pretty_print=pretty_print,
+            )
+
+    def build(self, node):
+        already_processed = set()
+        self.buildAttributes(node, node.attrib, already_processed)
+        for child in node:
+            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+            self.buildChildren(child, node, nodeName_)
+        return self
+
+    def buildAttributes(self, node, attrs, already_processed):
+        super(sbgn, self).buildAttributes(node, attrs, already_processed)
+
+    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+        if nodeName_ == "map":
+            obj_ = map.factory()
+            obj_.build(child_)
+            self.map = obj_
+            obj_.original_tagname_ = "map"
+        super(sbgn, self).buildChildren(child_, node, nodeName_, True)
+
+
+# end class sbgn
+
+
+class map(SBGNBase):
+    """The map element describes a single SBGN PD map. It contains a list
+    of glyph elements and a list of arc elements. These lists can be
+    of any size (possibly empty). Language of the map: one of three
+    sublanguages defined by SBGN. Different languages have different
+    restrictions on the usage of sub-elements (that are not encoded
+    in this schema but must be validated with an external validator)"""
+
+    subclass = None
+    superclass = SBGNBase
+
+    def __init__(
+        self,
+        notes=None,
+        extension=None,
+        language=None,
+        bbox=None,
+        glyph=None,
+        arc=None,
+        arcgroup=None,
+    ):
+        self.original_tagname_ = None
+        super(map, self).__init__(
+            notes,
+            extension,
+        )
+        self.set_language(language)
+        self.bbox = bbox
+        if glyph is None:
+            self.glyph = []
+        else:
+            self.glyph = glyph
+        if arc is None:
+            self.arc = []
+        else:
+            self.arc = arc
+        if arcgroup is None:
+            self.arcgroup = []
+        else:
+            self.arcgroup = arcgroup
+
+    def factory(*args_, **kwargs_):
+        if CurrentSubclassModule_ is not None:
+            subclass = getSubclassFromModule_(CurrentSubclassModule_, map)
+            if subclass is not None:
+                return subclass(*args_, **kwargs_)
+        if map.subclass:
+            return map.subclass(*args_, **kwargs_)
+        else:
+            return map(*args_, **kwargs_)
+
+    factory = staticmethod(factory)
+
+    def get_bbox(self):
+        return self.bbox
+
+    def set_bbox(self, bbox):
+        self.bbox = bbox
+
+    def get_glyph(self):
+        return self.glyph
+
+    def set_glyph(self, glyph):
+        self.glyph = glyph
+
+    def add_glyph(self, value):
+        self.glyph.append(value)
+
+    def insert_glyph_at(self, index, value):
+        self.glyph.insert(index, value)
+
+    def replace_glyph_at(self, index, value):
+        self.glyph[index] = value
+
+    def get_arc(self):
+        return self.arc
+
+    def set_arc(self, arc):
+        self.arc = arc
+
+    def add_arc(self, value):
+        self.arc.append(value)
+
+    def insert_arc_at(self, index, value):
+        self.arc.insert(index, value)
+
+    def replace_arc_at(self, index, value):
+        self.arc[index] = value
+
+    def get_arcgroup(self):
+        return self.arcgroup
+
+    def set_arcgroup(self, arcgroup):
+        self.arcgroup = arcgroup
+
+    def add_arcgroup(self, value):
+        self.arcgroup.append(value)
+
+    def insert_arcgroup_at(self, index, value):
+        self.arcgroup.insert(index, value)
+
+    def replace_arcgroup_at(self, index, value):
+        self.arcgroup[index] = value
+
+    def get_language(self):
+        """Get the Language.
+        :return: Language instance.
+        """
+        return Language(self.language)
+
+    def set_language(self, language):
+        """Sets the language and checks that within allowed values.
+        :param language:
+        :return:
+        """
+        if language and not isinstance(language, Language):
+            raise TypeError("language must be of type Language")
+        if language:
+            self.language = _cast(None, language.value)
+        else:
+            self.language = _cast(None, language)
+
+    def hasContent_(self):
+        if (
+            self.bbox is not None
+            or self.glyph
+            or self.arc
+            or self.arcgroup
+            or super(map, self).hasContent_()
+        ):
+            return True
+        else:
+            return False
+
+    def export(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="map",
+        namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"',
+        pretty_print=True,
+    ):
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        if self.original_tagname_ is not None:
+            name_ = self.original_tagname_
+        showIndent(outfile, level, pretty_print)
+        outfile.write(
+            "<%s%s%s"
+            % (
+                namespace_,
+                name_,
+                namespacedef_ and " " + namespacedef_ or "",
+            )
+        )
+        already_processed = set()
+        self.exportAttributes(
+            outfile, level, already_processed, namespace_, name_="map"
+        )
+        if self.hasContent_():
+            outfile.write(">%s" % (eol_,))
+            self.exportChildren(
+                outfile,
+                level + 1,
+                namespace_="sbgn:",
+                name_="map",
+                pretty_print=pretty_print,
+            )
+            showIndent(outfile, level, pretty_print)
+            outfile.write("</%s%s>%s" % (namespace_, name_, eol_))
+        else:
+            outfile.write("/>%s" % (eol_,))
+
+    def exportAttributes(
+        self, outfile, level, already_processed, namespace_="sbgn:", name_="map"
+    ):
+        super(map, self).exportAttributes(
+            outfile, level, already_processed, namespace_, name_="map"
+        )
+        if self.language is not None and "language" not in already_processed:
+            already_processed.add("language")
+            outfile.write(
+                " language=%s"
+                % (
+                    self.gds_encode(
+                        self.gds_format_string(
+                            quote_attrib(self.language), input_name="language"
+                        )
+                    ),
+                )
+            )
+
+    def exportChildren(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="map",
+        fromsubclass_=False,
+        pretty_print=True,
+    ):
+        super(map, self).exportChildren(
+            outfile, level, namespace_, name_, True, pretty_print=pretty_print
+        )
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        if self.bbox is not None:
+            self.bbox.export(
+                outfile,
+                level,
+                namespace_="sbgn:",
+                name_="bbox",
+                pretty_print=pretty_print,
+            )
+        for glyph_ in self.glyph:
+            glyph_.export(
+                outfile,
+                level,
+                namespace_="sbgn:",
+                name_="glyph",
+                pretty_print=pretty_print,
+            )
+        for arc_ in self.arc:
+            arc_.export(
+                outfile,
+                level,
+                namespace_="sbgn:",
+                name_="arc",
+                pretty_print=pretty_print,
+            )
+        for arcgroup_ in self.arcgroup:
+            arcgroup_.export(
+                outfile,
+                level,
+                namespace_="sbgn:",
+                name_="arcgroup",
+                pretty_print=pretty_print,
+            )
+
+    def build(self, node):
+        already_processed = set()
+        self.buildAttributes(node, node.attrib, already_processed)
+        for child in node:
+            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+            self.buildChildren(child, node, nodeName_)
+        return self
+
+    def buildAttributes(self, node, attrs, already_processed):
+        value = find_attr_value_("language", node)
+        if value is not None and "language" not in already_processed:
+            already_processed.add("language")
+            self.language = value
+        super(map, self).buildAttributes(node, attrs, already_processed)
+
+    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+        if nodeName_ == "bbox":
+            obj_ = bbox.factory()
+            obj_.build(child_)
+            self.bbox = obj_
+            obj_.original_tagname_ = "bbox"
+        elif nodeName_ == "glyph":
+            obj_ = glyph.factory()
+            obj_.build(child_)
+            self.glyph.append(obj_)
+            obj_.original_tagname_ = "glyph"
+        elif nodeName_ == "arc":
+            obj_ = arc.factory()
+            obj_.build(child_)
+            self.arc.append(obj_)
+            obj_.original_tagname_ = "arc"
+        elif nodeName_ == "arcgroup":
+            obj_ = arcgroup.factory()
+            obj_.build(child_)
+            self.arcgroup.append(obj_)
+            obj_.original_tagname_ = "arcgroup"
+        super(map, self).buildChildren(child_, node, nodeName_, True)
+
+
+# end class map
+
+
+class port(SBGNBase):
+    """The port element describes an anchor point which arcs can refer to
+    as a source or target. It consists in: absolute 2D cartesian
+    coordinates (PointAttribute), a unique id attribute. Two port
+    elements are required for process nodes. They represent the
+    extremity of the two "arms" which protrude on both sides of the
+    core of the glyph (= square or circle shape). Other glyphs don't
+    need ports (but can use them if desired). The xsd:ID type is an
+    alphanumeric identifier, starting with a letter. Port IDs often
+    contain the ID of their glyph, followed by a local port number
+    (e.g. glyph4.1, glyph4.2, etc.) However, this style convention
+    is not mandatory, and IDs should never be interpreted as
+    carrying any meaning."""
+
+    subclass = None
+    superclass = SBGNBase
+
+    def __init__(self, notes=None, extension=None, id=None, x=None, y=None):
+        self.original_tagname_ = None
+        super(port, self).__init__(
+            notes,
+            extension,
+        )
+        self.id = _cast(None, id)
+        self.x = _cast(float, x)
+        self.y = _cast(float, y)
+
+    def factory(*args_, **kwargs_):
+        if CurrentSubclassModule_ is not None:
+            subclass = getSubclassFromModule_(CurrentSubclassModule_, port)
+            if subclass is not None:
+                return subclass(*args_, **kwargs_)
+        if port.subclass:
+            return port.subclass(*args_, **kwargs_)
+        else:
+            return port(*args_, **kwargs_)
+
+    factory = staticmethod(factory)
+
+    def get_id(self):
+        return self.id
+
+    def set_id(self, id):
+        self.id = id
+
+    def get_x(self):
+        return self.x
+
+    def set_x(self, x):
+        self.x = x
+
+    def get_y(self):
+        return self.y
+
+    def set_y(self, y):
+        self.y = y
+
+    def hasContent_(self):
+        if super(port, self).hasContent_():
+            return True
+        else:
+            return False
+
+    def export(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="port",
+        namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"',
+        pretty_print=True,
+    ):
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        if self.original_tagname_ is not None:
+            name_ = self.original_tagname_
+        showIndent(outfile, level, pretty_print)
+        outfile.write(
+            "<%s%s%s"
+            % (
+                namespace_,
+                name_,
+                namespacedef_ and " " + namespacedef_ or "",
+            )
+        )
+        already_processed = set()
+        self.exportAttributes(
+            outfile, level, already_processed, namespace_, name_="port"
+        )
+        if self.hasContent_():
+            outfile.write(">%s" % (eol_,))
+            self.exportChildren(
+                outfile,
+                level + 1,
+                namespace_="sbgn:",
+                name_="port",
+                pretty_print=pretty_print,
+            )
+            showIndent(outfile, level, pretty_print)
+            outfile.write("</%s%s>%s" % (namespace_, name_, eol_))
+        else:
+            outfile.write("/>%s" % (eol_,))
+
+    def exportAttributes(
+        self, outfile, level, already_processed, namespace_="sbgn:", name_="port"
+    ):
+        super(port, self).exportAttributes(
+            outfile, level, already_processed, namespace_, name_="port"
+        )
+        if self.id is not None and "id" not in already_processed:
+            already_processed.add("id")
+            outfile.write(
+                " id=%s"
+                % (
+                    self.gds_encode(
+                        self.gds_format_string(quote_attrib(self.id), input_name="id")
+                    ),
+                )
+            )
+        if self.x is not None and "x" not in already_processed:
+            already_processed.add("x")
+            outfile.write(' x="%s"' % self.gds_format_float(self.x, input_name="x"))
+        if self.y is not None and "y" not in already_processed:
+            already_processed.add("y")
+            outfile.write(' y="%s"' % self.gds_format_float(self.y, input_name="y"))
+
+    def exportChildren(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="port",
+        fromsubclass_=False,
+        pretty_print=True,
+    ):
+        super(port, self).exportChildren(
+            outfile, level, namespace_, name_, True, pretty_print=pretty_print
+        )
+
+    def build(self, node):
+        already_processed = set()
+        self.buildAttributes(node, node.attrib, already_processed)
+        for child in node:
+            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+            self.buildChildren(child, node, nodeName_)
+        return self
+
+    def buildAttributes(self, node, attrs, already_processed):
+        value = find_attr_value_("id", node)
+        if value is not None and "id" not in already_processed:
+            already_processed.add("id")
+            self.id = value
+        value = find_attr_value_("x", node)
+        if value is not None and "x" not in already_processed:
+            already_processed.add("x")
+            try:
+                self.x = float(value)
+            except ValueError as exp:
+                raise ValueError("Bad float/double attribute (x): %s" % exp)
+        value = find_attr_value_("y", node)
+        if value is not None and "y" not in already_processed:
+            already_processed.add("y")
+            try:
+                self.y = float(value)
+            except ValueError as exp:
+                raise ValueError("Bad float/double attribute (y): %s" % exp)
+        super(port, self).buildAttributes(node, attrs, already_processed)
+
+    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+        super(port, self).buildChildren(child_, node, nodeName_, True)
+        pass
+
+
+# end class port
+
+
+class glyph(SBGNBase):
+    """The glyph element is: either a stand-alone, high-level SBGN glyph
+    (EPN, PN, compartment, etc), or a sub-glyph (state variable,
+    unit of information, inside of a complex, ...) In the first
+    case, it appears directly in the glyph list of the map. In the
+    second case, it is a child of another glyph element. The text
+    inside a glyph is described: either by a label element
+    (optional) [process nodes can't have one], or by a state element
+    (optional) [for state variables only]. The class attribute
+    defines the semantic of the glyph, and influences: the way that
+    glyph should be rendered, the overall syntactic validity of the
+    map. The various classes encompass the following PD SBGN
+    elements: Entity Pool Nodes (EPN), Process Nodes (PN), Logic
+    Operator Nodes, Sub-glyphs on Nodes (State Variable, Unit of
+    Information), Sub-glyphs on Arcs (Stoichiometry Label), Other
+    glyphs (Compartment, Submap, Tag, Terminal). And the following
+    ER SBGN elements Entities (Entity, Outcome) Other (Annotation,
+    Phenotype) Auxiliary on glyps (Existence, Location) Auxiliary on
+    arcs (Cardinality) Delay operator implicit xor The orientation
+    attribute is used to express how to draw asymmetric glyphs. In
+    PD, the orientation of Process Nodes is either horizontal or
+    vertical. It refers to an (imaginary) line connecting the two
+    in/out sides of the PN. In PD, the orientation of Tags and
+    Terminals can be left, right, up or down. It refers to the
+    direction the arrow side of the glyph is pointing at. The xsd:ID
+    type is an alphanumeric identifier, starting with a letter. It
+    is recommended to generate meaningless IDs (e.g. "glyph1234")
+    and avoid IDs with a meaning (e.g. "epn_ethanol") Reference to
+    the ID of the compartment that this glyph is part of. Only use
+    this if there is at least one explicit compartment present in
+    the diagram. Compartments are only used in PD and AF, and thus
+    this attribute as well. For PD, this should be used only for
+    EPN's. In case there are no compartments, entities that can have
+    a location, such as EPN's, are implicit member of an invisible
+    compartment that encompasses the whole map. In that case, this
+    attribute must be omitted. The compartment order attribute can
+    be used to define a drawing order for compartments. It enables
+    tools to draw compartments in the correct order especially in
+    the case of overlapping compartments. Compartments are only used
+    in PD and AF, and thus this attribute as well. The attribute is
+    of type float, the attribute value has not to be unique.
+    Compartments with higher compartment order are drawn on top. The
+    attribute is optional and should only be used for compartments."""
+
+    subclass = None
+    superclass = SBGNBase
+
+    def __init__(
+        self,
+        notes=None,
+        extension=None,
+        class_=None,
+        orientation=Orientation.HORIZONTAL,
+        id=None,
+        compartmentRef=None,
+        compartmentOrder=None,
+        label=None,
+        state=None,
+        clone=None,
+        callout=None,
+        entity=None,
+        bbox=None,
+        glyph_member=None,
+        port=None,
+    ):
+        self.original_tagname_ = None
+        super(glyph, self).__init__(
+            notes,
+            extension,
+        )
+        self.set_class(class_)
+        self.set_orientation(orientation)
+        self.id = _cast(None, id)
+        self.compartmentRef = _cast(None, compartmentRef)
+        self.compartmentOrder = _cast(float, compartmentOrder)
+        self.label = label
+        self.state = state
+        self.clone = clone
+        self.callout = callout
+        self.entity = entity
+        self.bbox = bbox
+        if glyph_member is None:
+            self.glyph = []
+        else:
+            self.glyph = glyph_member
+        if port is None:
+            self.port = []
+        else:
+            self.port = port
+
+    def factory(*args_, **kwargs_):
+        if CurrentSubclassModule_ is not None:
+            subclass = getSubclassFromModule_(CurrentSubclassModule_, glyph)
+            if subclass is not None:
+                return subclass(*args_, **kwargs_)
+        if glyph.subclass:
+            return glyph.subclass(*args_, **kwargs_)
+        else:
+            return glyph(*args_, **kwargs_)
+
+    factory = staticmethod(factory)
+
+    def get_label(self):
+        return self.label
+
+    def set_label(self, label):
+        self.label = label
+
+    def get_state(self):
+        return self.state
+
+    def set_state(self, state):
+        self.state = state
+
+    def get_clone(self):
+        return self.clone
+
+    def set_clone(self, clone):
+        self.clone = clone
+
+    def get_callout(self):
+        return self.callout
+
+    def set_callout(self, callout):
+        self.callout = callout
+
+    def get_entity(self):
+        return self.entity
+
+    def set_entity(self, entity):
+        self.entity = entity
+
+    def get_bbox(self):
+        return self.bbox
+
+    def set_bbox(self, bbox):
+        self.bbox = bbox
+
+    def get_glyph(self):
+        return self.glyph
+
+    def set_glyph(self, glyph):
+        self.glyph = glyph
+
+    def add_glyph(self, value):
+        self.glyph.append(value)
+
+    def insert_glyph_at(self, index, value):
+        self.glyph.insert(index, value)
+
+    def replace_glyph_at(self, index, value):
+        self.glyph[index] = value
+
+    def get_port(self):
+        return self.port
+
+    def set_port(self, port):
+        self.port = port
+
+    def add_port(self, value):
+        self.port.append(value)
+
+    def insert_port_at(self, index, value):
+        self.port.insert(index, value)
+
+    def replace_port_at(self, index, value):
+        self.port[index] = value
+
+    def get_class(self):
+        """Get the Language.
+        :return: Language instance.
+        """
+        return GlyphClass(self.class_)
+
+    def set_class(self, class_):
+        """Sets the class and checks that in allowed GlyphClasses
+        :param class_:
+        :return:
+        """
+        if class_ and not isinstance(class_, GlyphClass):
+            raise TypeError("class must be of type GlyphClass")
+        if class_:
+            self.class_ = _cast(None, class_.value)
+        else:
+            self.class_ = _cast(None, class_)
+
+    def get_orientation(self):
+        """Get orientation.
+        :return: Orientation instance.
+        """
+        return Orientation(self.orientation)
+
+    def set_orientation(self, orientation):
+        """Sets orientation and checks that allowed Orientation.
+
+        :param orientation:
+        :return:
+        """
+        if not isinstance(orientation, Orientation):
+            raise TypeError("orientation must be of type Orientation")
+        self.orientation = _cast(None, orientation.value)
+
+    def get_id(self):
+        return self.id
+
+    def set_id(self, id):
+        self.id = id
+
+    def get_compartmentRef(self):
+        return self.compartmentRef
+
+    def set_compartmentRef(self, compartmentRef):
+        self.compartmentRef = compartmentRef
+
+    def get_compartmentOrder(self):
+        return self.compartmentOrder
+
+    def set_compartmentOrder(self, compartmentOrder):
+        self.compartmentOrder = compartmentOrder
+
+    def hasContent_(self):
+        if (
+            self.label is not None
+            or self.state is not None
+            or self.clone is not None
+            or self.callout is not None
+            or self.entity is not None
+            or self.bbox is not None
+            or self.glyph
+            or self.port
+            or super(glyph, self).hasContent_()
+        ):
+            return True
+        else:
+            return False
+
+    def export(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="glyph",
+        namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"',
+        pretty_print=True,
+    ):
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        if self.original_tagname_ is not None:
+            name_ = self.original_tagname_
+        showIndent(outfile, level, pretty_print)
+        outfile.write(
+            "<%s%s%s"
+            % (
+                namespace_,
+                name_,
+                namespacedef_ and " " + namespacedef_ or "",
+            )
+        )
+        already_processed = set()
+        self.exportAttributes(
+            outfile, level, already_processed, namespace_, name_="glyph"
+        )
+        if self.hasContent_():
+            outfile.write(">%s" % (eol_,))
+            self.exportChildren(
+                outfile,
+                level + 1,
+                namespace_="sbgn:",
+                name_="glyph",
+                pretty_print=pretty_print,
+            )
+            showIndent(outfile, level, pretty_print)
+            outfile.write("</%s%s>%s" % (namespace_, name_, eol_))
+        else:
+            outfile.write("/>%s" % (eol_,))
+
+    def exportAttributes(
+        self, outfile, level, already_processed, namespace_="sbgn:", name_="glyph"
+    ):
+        super(glyph, self).exportAttributes(
+            outfile, level, already_processed, namespace_, name_="glyph"
+        )
+        if self.class_ is not None and "class_" not in already_processed:
+            already_processed.add("class_")
+            outfile.write(
+                " class=%s"
+                % (
+                    self.gds_encode(
+                        self.gds_format_string(
+                            quote_attrib(self.class_), input_name="class"
+                        )
+                    ),
+                )
+            )
+        if self.orientation != "horizontal" and "orientation" not in already_processed:
+            already_processed.add("orientation")
+            outfile.write(
+                " orientation=%s"
+                % (
+                    self.gds_encode(
+                        self.gds_format_string(
+                            quote_attrib(self.orientation), input_name="orientation"
+                        )
+                    ),
+                )
+            )
+        if self.id is not None and "id" not in already_processed:
+            already_processed.add("id")
+            outfile.write(
+                " id=%s"
+                % (
+                    self.gds_encode(
+                        self.gds_format_string(quote_attrib(self.id), input_name="id")
+                    ),
+                )
+            )
+        if (
+            self.compartmentRef is not None
+            and "compartmentRef" not in already_processed
+        ):
+            already_processed.add("compartmentRef")
+            outfile.write(
+                " compartmentRef=%s"
+                % (
+                    self.gds_encode(
+                        self.gds_format_string(
+                            quote_attrib(self.compartmentRef),
+                            input_name="compartmentRef",
+                        )
+                    ),
+                )
+            )
+        if (
+            self.compartmentOrder is not None
+            and "compartmentOrder" not in already_processed
+        ):
+            already_processed.add("compartmentOrder")
+            outfile.write(
+                ' compartmentOrder="%s"'
+                % self.gds_format_float(
+                    self.compartmentOrder, input_name="compartmentOrder"
+                )
+            )
+
+    def exportChildren(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="glyph",
+        fromsubclass_=False,
+        pretty_print=True,
+    ):
+        super(glyph, self).exportChildren(
+            outfile, level, namespace_, name_, True, pretty_print=pretty_print
+        )
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        if self.label is not None:
+            self.label.export(
+                outfile,
+                level,
+                namespace_="sbgn:",
+                name_="label",
+                pretty_print=pretty_print,
+            )
+        if self.state is not None:
+            self.state.export(
+                outfile, level, namespace_, name_="state", pretty_print=pretty_print
+            )
+        if self.clone is not None:
+            self.clone.export(
+                outfile, level, namespace_, name_="clone", pretty_print=pretty_print
+            )
+        if self.callout is not None:
+            self.callout.export(
+                outfile, level, namespace_, name_="callout", pretty_print=pretty_print
+            )
+        if self.entity is not None:
+            self.entity.export(
+                outfile, level, namespace_, name_="entity", pretty_print=pretty_print
+            )
+        if self.bbox is not None:
+            self.bbox.export(
+                outfile,
+                level,
+                namespace_="sbgn:",
+                name_="bbox",
+                pretty_print=pretty_print,
+            )
+        for glyph_ in self.glyph:
+            glyph_.export(
+                outfile,
+                level,
+                namespace_="sbgn:",
+                name_="glyph",
+                pretty_print=pretty_print,
+            )
+        for port_ in self.port:
+            port_.export(
+                outfile,
+                level,
+                namespace_="sbgn:",
+                name_="port",
+                pretty_print=pretty_print,
+            )
+
+    def build(self, node):
+        already_processed = set()
+        self.buildAttributes(node, node.attrib, already_processed)
+        for child in node:
+            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+            self.buildChildren(child, node, nodeName_)
+        return self
+
+    def buildAttributes(self, node, attrs, already_processed):
+        value = find_attr_value_("class", node)
+        if value is not None and "class" not in already_processed:
+            already_processed.add("class")
+            self.class_ = value
+        value = find_attr_value_("orientation", node)
+        if value is not None and "orientation" not in already_processed:
+            already_processed.add("orientation")
+            self.orientation = value
+        value = find_attr_value_("id", node)
+        if value is not None and "id" not in already_processed:
+            already_processed.add("id")
+            self.id = value
+        value = find_attr_value_("compartmentRef", node)
+        if value is not None and "compartmentRef" not in already_processed:
+            already_processed.add("compartmentRef")
+            self.compartmentRef = value
+        value = find_attr_value_("compartmentOrder", node)
+        if value is not None and "compartmentOrder" not in already_processed:
+            already_processed.add("compartmentOrder")
+            try:
+                self.compartmentOrder = float(value)
+            except ValueError as exp:
+                raise ValueError(
+                    "Bad float/double attribute (compartmentOrder): %s" % exp
+                )
+        super(glyph, self).buildAttributes(node, attrs, already_processed)
+
+    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+        if nodeName_ == "label":
+            obj_ = label.factory()
+            obj_.build(child_)
+            self.label = obj_
+            obj_.original_tagname_ = "label"
+        elif nodeName_ == "state":
+            obj_ = stateType.factory()
+            obj_.build(child_)
+            self.state = obj_
+            obj_.original_tagname_ = "state"
+        elif nodeName_ == "clone":
+            obj_ = cloneType.factory()
+            obj_.build(child_)
+            self.clone = obj_
+            obj_.original_tagname_ = "clone"
+        elif nodeName_ == "callout":
+            obj_ = calloutType.factory()
+            obj_.build(child_)
+            self.callout = obj_
+            obj_.original_tagname_ = "callout"
+        elif nodeName_ == "entity":
+            obj_ = entityType.factory()
+            obj_.build(child_)
+            self.entity = obj_
+            obj_.original_tagname_ = "entity"
+        elif nodeName_ == "bbox":
+            obj_ = bbox.factory()
+            obj_.build(child_)
+            self.bbox = obj_
+            obj_.original_tagname_ = "bbox"
+        elif nodeName_ == "glyph":
+            obj_ = glyph.factory()
+            obj_.build(child_)
+            self.glyph.append(obj_)
+            obj_.original_tagname_ = "glyph"
+        elif nodeName_ == "port":
+            obj_ = port.factory()
+            obj_.build(child_)
+            self.port.append(obj_)
+            obj_.original_tagname_ = "port"
+        super(glyph, self).buildChildren(child_, node, nodeName_, True)
+
+
+# end class glyph
+
+
+class arcgroup(SBGNBase):
+    """The arc group describes a set of arcs and glyphs that together have
+    a relation. For example For ER: interaction arcs around an
+    interaction glyph, ... Note that, in spite of the name, an
+    arcgroup contains both arcs and glyphs. The class attribute
+    defines the semantic of the arcgroup."""
+
+    subclass = None
+    superclass = SBGNBase
+
+    def __init__(self, notes=None, extension=None, class_=None, glyph=None, arc=None):
+        self.original_tagname_ = None
+        super(arcgroup, self).__init__(
+            notes,
+            extension,
+        )
+        self.class_ = _cast(None, class_)
+        if glyph is None:
+            self.glyph = []
+        else:
+            self.glyph = glyph
+        if arc is None:
+            self.arc = []
+        else:
+            self.arc = arc
+
+    def factory(*args_, **kwargs_):
+        if CurrentSubclassModule_ is not None:
+            subclass = getSubclassFromModule_(CurrentSubclassModule_, arcgroup)
+            if subclass is not None:
+                return subclass(*args_, **kwargs_)
+        if arcgroup.subclass:
+            return arcgroup.subclass(*args_, **kwargs_)
+        else:
+            return arcgroup(*args_, **kwargs_)
+
+    factory = staticmethod(factory)
+
+    def get_glyph(self):
+        return self.glyph
+
+    def set_glyph(self, glyph):
+        self.glyph = glyph
+
+    def add_glyph(self, value):
+        self.glyph.append(value)
+
+    def insert_glyph_at(self, index, value):
+        self.glyph.insert(index, value)
+
+    def replace_glyph_at(self, index, value):
+        self.glyph[index] = value
+
+    def get_arc(self):
+        return self.arc
+
+    def set_arc(self, arc):
+        self.arc = arc
+
+    def add_arc(self, value):
+        self.arc.append(value)
+
+    def insert_arc_at(self, index, value):
+        self.arc.insert(index, value)
+
+    def replace_arc_at(self, index, value):
+        self.arc[index] = value
+
+    def get_class(self):
+        return self.class_
+
+    def set_class(self, class_):
+        self.class_ = class_
+
+    def hasContent_(self):
+        if self.glyph or self.arc or super(arcgroup, self).hasContent_():
+            return True
+        else:
+            return False
+
+    def export(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="arcgroup",
+        namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"',
+        pretty_print=True,
+    ):
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        if self.original_tagname_ is not None:
+            name_ = self.original_tagname_
+        showIndent(outfile, level, pretty_print)
+        outfile.write(
+            "<%s%s%s"
+            % (
+                namespace_,
+                name_,
+                namespacedef_ and " " + namespacedef_ or "",
+            )
+        )
+        already_processed = set()
+        self.exportAttributes(
+            outfile, level, already_processed, namespace_, name_="arcgroup"
+        )
+        if self.hasContent_():
+            outfile.write(">%s" % (eol_,))
+            self.exportChildren(
+                outfile,
+                level + 1,
+                namespace_="sbgn:",
+                name_="arcgroup",
+                pretty_print=pretty_print,
+            )
+            showIndent(outfile, level, pretty_print)
+            outfile.write("</%s%s>%s" % (namespace_, name_, eol_))
+        else:
+            outfile.write("/>%s" % (eol_,))
+
+    def exportAttributes(
+        self, outfile, level, already_processed, namespace_="sbgn:", name_="arcgroup"
+    ):
+        super(arcgroup, self).exportAttributes(
+            outfile, level, already_processed, namespace_, name_="arcgroup"
+        )
+        if self.class_ is not None and "class_" not in already_processed:
+            already_processed.add("class_")
+            outfile.write(
+                " class=%s"
+                % (
+                    self.gds_encode(
+                        self.gds_format_string(
+                            quote_attrib(self.class_), input_name="class"
+                        )
+                    ),
+                )
+            )
+
+    def exportChildren(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="arcgroup",
+        fromsubclass_=False,
+        pretty_print=True,
+    ):
+        super(arcgroup, self).exportChildren(
+            outfile, level, namespace_, name_, True, pretty_print=pretty_print
+        )
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        for glyph_ in self.glyph:
+            glyph_.export(
+                outfile,
+                level,
+                namespace_="sbgn:",
+                name_="glyph",
+                pretty_print=pretty_print,
+            )
+        for arc_ in self.arc:
+            arc_.export(
+                outfile,
+                level,
+                namespace_="sbgn:",
+                name_="arc",
+                pretty_print=pretty_print,
+            )
+
+    def build(self, node):
+        already_processed = set()
+        self.buildAttributes(node, node.attrib, already_processed)
+        for child in node:
+            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+            self.buildChildren(child, node, nodeName_)
+        return self
+
+    def buildAttributes(self, node, attrs, already_processed):
+        value = find_attr_value_("class", node)
+        if value is not None and "class" not in already_processed:
+            already_processed.add("class")
+            self.class_ = value
+        super(arcgroup, self).buildAttributes(node, attrs, already_processed)
+
+    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+        if nodeName_ == "glyph":
+            obj_ = glyph.factory()
+            obj_.build(child_)
+            self.glyph.append(obj_)
+            obj_.original_tagname_ = "glyph"
+        elif nodeName_ == "arc":
+            obj_ = arc.factory()
+            obj_.build(child_)
+            self.arc.append(obj_)
+            obj_.original_tagname_ = "arc"
+        super(arcgroup, self).buildChildren(child_, node, nodeName_, True)
+
+
+# end class arcgroup
+
+
+class arc(SBGNBase):
+    """The arc element describes an SBGN arc between two SBGN nodes. It
+    contains: For PD: an optional stoichiometry marker, For ER: an
+    optional cardinality marker, zero or more ports (influence
+    targets), and zero or more outcomes, a mandatory source and
+    target (glyph or port), a geometric description of its whole
+    path, from start to end. This path can involve any number of
+    straight lines or quadratic/cubic Bezier curves. The class
+    attribute defines the semantic of the arc, and influences: the
+    way that arc should be rendered, the overall syntactic validity
+    of the map. The various classes encompass all possible types of
+    SBGN arcs: production and consumption arcs, all types of
+    modification arcs, logic arcs, equivalence arcs. To express a
+    reversible reaction, use production arcs on both sides of the
+    Process Node. The xsd:ID type is an alphanumeric identifier,
+    starting with a letter. The source attribute can refer: either
+    to the id of a glyph, or to the id of a port on a glyph. The
+    target attribute can refer: either to the id of a glyph, or to
+    the id of a port on a glyph."""
+
+    subclass = None
+    superclass = SBGNBase
+
+    def __init__(
+        self,
+        notes=None,
+        extension=None,
+        class_=None,
+        id=None,
+        source=None,
+        target=None,
+        glyph=None,
+        port=None,
+        start=None,
+        next=None,
+        end=None,
+    ):
+        self.original_tagname_ = None
+        super(arc, self).__init__(
+            notes,
+            extension,
+        )
+        self.set_class(class_)
+        self.id = _cast(None, id)
+        self.source = _cast(None, source)
+        self.target = _cast(None, target)
+        if glyph is None:
+            self.glyph = []
+        else:
+            self.glyph = glyph
+        if port is None:
+            self.port = []
+        else:
+            self.port = port
+        self.start = start
+        if next is None:
+            self.next = []
+        else:
+            self.next = next
+        self.end = end
+
+    def factory(*args_, **kwargs_):
+        if CurrentSubclassModule_ is not None:
+            subclass = getSubclassFromModule_(CurrentSubclassModule_, arc)
+            if subclass is not None:
+                return subclass(*args_, **kwargs_)
+        if arc.subclass:
+            return arc.subclass(*args_, **kwargs_)
+        else:
+            return arc(*args_, **kwargs_)
+
+    factory = staticmethod(factory)
+
+    def get_glyph(self):
+        return self.glyph
+
+    def set_glyph(self, glyph):
+        self.glyph = glyph
+
+    def add_glyph(self, value):
+        self.glyph.append(value)
+
+    def insert_glyph_at(self, index, value):
+        self.glyph.insert(index, value)
+
+    def replace_glyph_at(self, index, value):
+        self.glyph[index] = value
+
+    def get_port(self):
+        return self.port
+
+    def set_port(self, port):
+        self.port = port
+
+    def add_port(self, value):
+        self.port.append(value)
+
+    def insert_port_at(self, index, value):
+        self.port.insert(index, value)
+
+    def replace_port_at(self, index, value):
+        self.port[index] = value
+
+    def get_start(self):
+        return self.start
+
+    def set_start(self, start):
+        self.start = start
+
+    def get_next(self):
+        return self.next
+
+    def set_next(self, next):
+        self.next = next
+
+    def add_next(self, value):
+        self.next.append(value)
+
+    def insert_next_at(self, index, value):
+        self.next.insert(index, value)
+
+    def replace_next_at(self, index, value):
+        self.next[index] = value
+
+    def get_end(self):
+        return self.end
+
+    def set_end(self, end):
+        self.end = end
+
+    def get_class(self):
+        """ Get the ArcClass. """
+        return ArcClass(self.class_)
+
+    def set_class(self, class_):
+        """Set the ArcClass.
+        :param class_:
+        :return:
+        """
+        if class_ and not isinstance(class_, ArcClass):
+            raise TypeError("class must be of type ArcClass")
+        if class_:
+            self.class_ = _cast(None, class_.value)
+        else:
+            self.class_ = _cast(None, class_)
+
+    def get_id(self):
+        return self.id
+
+    def set_id(self, id):
+        self.id = id
+
+    def get_source(self):
+        return self.source
+
+    def set_source(self, source):
+        self.source = source
+
+    def get_target(self):
+        return self.target
+
+    def set_target(self, target):
+        self.target = target
+
+    def hasContent_(self):
+        if (
+            self.glyph
+            or self.port
+            or self.start is not None
+            or self.next
+            or self.end is not None
+            or super(arc, self).hasContent_()
+        ):
+            return True
+        else:
+            return False
+
+    def export(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="arc",
+        namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"',
+        pretty_print=True,
+    ):
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        if self.original_tagname_ is not None:
+            name_ = self.original_tagname_
+        showIndent(outfile, level, pretty_print)
+        outfile.write(
+            "<%s%s%s"
+            % (
+                namespace_,
+                name_,
+                namespacedef_ and " " + namespacedef_ or "",
+            )
+        )
+        already_processed = set()
+        self.exportAttributes(
+            outfile, level, already_processed, namespace_, name_="arc"
+        )
+        if self.hasContent_():
+            outfile.write(">%s" % (eol_,))
+            self.exportChildren(
+                outfile,
+                level + 1,
+                namespace_="sbgn:",
+                name_="arc",
+                pretty_print=pretty_print,
+            )
+            showIndent(outfile, level, pretty_print)
+            outfile.write("</%s%s>%s" % (namespace_, name_, eol_))
+        else:
+            outfile.write("/>%s" % (eol_,))
+
+    def exportAttributes(
+        self, outfile, level, already_processed, namespace_="sbgn:", name_="arc"
+    ):
+        super(arc, self).exportAttributes(
+            outfile, level, already_processed, namespace_, name_="arc"
+        )
+        if self.class_ is not None and "class_" not in already_processed:
+            already_processed.add("class_")
+            outfile.write(
+                " class=%s"
+                % (
+                    self.gds_encode(
+                        self.gds_format_string(
+                            quote_attrib(self.class_), input_name="class"
+                        )
+                    ),
+                )
+            )
+        if self.id is not None and "id" not in already_processed:
+            already_processed.add("id")
+            outfile.write(
+                " id=%s"
+                % (
+                    self.gds_encode(
+                        self.gds_format_string(quote_attrib(self.id), input_name="id")
+                    ),
+                )
+            )
+        if self.source is not None and "source" not in already_processed:
+            already_processed.add("source")
+            outfile.write(
+                " source=%s"
+                % (
+                    self.gds_encode(
+                        self.gds_format_string(
+                            quote_attrib(self.source), input_name="source"
+                        )
+                    ),
+                )
+            )
+        if self.target is not None and "target" not in already_processed:
+            already_processed.add("target")
+            outfile.write(
+                " target=%s"
+                % (
+                    self.gds_encode(
+                        self.gds_format_string(
+                            quote_attrib(self.target), input_name="target"
+                        )
+                    ),
+                )
+            )
+
+    def exportChildren(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="arc",
+        fromsubclass_=False,
+        pretty_print=True,
+    ):
+        super(arc, self).exportChildren(
+            outfile, level, namespace_, name_, True, pretty_print=pretty_print
+        )
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        for glyph_ in self.glyph:
+            glyph_.export(
+                outfile,
+                level,
+                namespace_="sbgn:",
+                name_="glyph",
+                pretty_print=pretty_print,
+            )
+        for port_ in self.port:
+            port_.export(
+                outfile,
+                level,
+                namespace_="sbgn:",
+                name_="port",
+                pretty_print=pretty_print,
+            )
+        if self.start is not None:
+            self.start.export(
+                outfile, level, namespace_, name_="start", pretty_print=pretty_print
+            )
+        for next_ in self.next:
+            next_.export(
+                outfile, level, namespace_, name_="next", pretty_print=pretty_print
+            )
+        if self.end is not None:
+            self.end.export(
+                outfile, level, namespace_, name_="end", pretty_print=pretty_print
+            )
+
+    def build(self, node):
+        already_processed = set()
+        self.buildAttributes(node, node.attrib, already_processed)
+        for child in node:
+            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+            self.buildChildren(child, node, nodeName_)
+        return self
+
+    def buildAttributes(self, node, attrs, already_processed):
+        value = find_attr_value_("class", node)
+        if value is not None and "class" not in already_processed:
+            already_processed.add("class")
+            self.class_ = value
+        value = find_attr_value_("id", node)
+        if value is not None and "id" not in already_processed:
+            already_processed.add("id")
+            self.id = value
+        value = find_attr_value_("source", node)
+        if value is not None and "source" not in already_processed:
+            already_processed.add("source")
+            self.source = value
+        value = find_attr_value_("target", node)
+        if value is not None and "target" not in already_processed:
+            already_processed.add("target")
+            self.target = value
+        super(arc, self).buildAttributes(node, attrs, already_processed)
+
+    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+        if nodeName_ == "glyph":
+            obj_ = glyph.factory()
+            obj_.build(child_)
+            self.glyph.append(obj_)
+            obj_.original_tagname_ = "glyph"
+        elif nodeName_ == "port":
+            obj_ = port.factory()
+            obj_.build(child_)
+            self.port.append(obj_)
+            obj_.original_tagname_ = "port"
+        elif nodeName_ == "start":
+            obj_ = startType.factory()
+            obj_.build(child_)
+            self.start = obj_
+            obj_.original_tagname_ = "start"
+        elif nodeName_ == "next":
+            obj_ = nextType.factory()
+            obj_.build(child_)
+            self.next.append(obj_)
+            obj_.original_tagname_ = "next"
+        elif nodeName_ == "end":
+            obj_ = endType.factory()
+            obj_.build(child_)
+            self.end = obj_
+            obj_.original_tagname_ = "end"
+        super(arc, self).buildChildren(child_, node, nodeName_, True)
+
+
+# end class arc
+
+
+class notesType(GeneratedsSuper):
+    subclass = None
+    superclass = None
+
+    def __init__(self, anytypeobjs_=None):
+        self.original_tagname_ = None
+        if anytypeobjs_ is None:
+            self.anytypeobjs_ = []
+        else:
+            self.anytypeobjs_ = anytypeobjs_
+
+    def factory(*args_, **kwargs_):
+        if CurrentSubclassModule_ is not None:
+            subclass = getSubclassFromModule_(CurrentSubclassModule_, notesType)
+            if subclass is not None:
+                return subclass(*args_, **kwargs_)
+        if notesType.subclass:
+            return notesType.subclass(*args_, **kwargs_)
+        else:
+            return notesType(*args_, **kwargs_)
+
+    factory = staticmethod(factory)
+
+    def get_anytypeobjs_(self):
+        return self.anytypeobjs_
+
+    def set_anytypeobjs_(self, anytypeobjs_):
+        self.anytypeobjs_ = anytypeobjs_
+
+    def add_anytypeobjs_(self, value):
+        self.anytypeobjs_.append(value)
+
+    def insert_anytypeobjs_(self, index, value):
+        self._anytypeobjs_[index] = value
+
+    def hasContent_(self):
+        if self.anytypeobjs_:
+            return True
+        else:
+            return False
+
+    def export(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="notesType",
+        namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"',
+        pretty_print=True,
+    ):
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        if self.original_tagname_ is not None:
+            name_ = self.original_tagname_
+        showIndent(outfile, level, pretty_print)
+        outfile.write(
+            "<%s%s%s"
+            % (
+                namespace_,
+                name_,
+                namespacedef_ and " " + namespacedef_ or "",
+            )
+        )
+        already_processed = set()
+        self.exportAttributes(
+            outfile, level, already_processed, namespace_, name_="notesType"
+        )
+        if self.hasContent_():
+            outfile.write(">%s" % (eol_,))
+            self.exportChildren(
+                outfile,
+                level + 1,
+                namespace_="sbgn:",
+                name_="notesType",
+                pretty_print=pretty_print,
+            )
+            showIndent(outfile, level, pretty_print)
+            outfile.write("</%s%s>%s" % (namespace_, name_, eol_))
+        else:
+            outfile.write("/>%s" % (eol_,))
+
+    def exportAttributes(
+        self, outfile, level, already_processed, namespace_="sbgn:", name_="notesType"
+    ):
+        pass
+
+    def exportChildren(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="notesType",
+        fromsubclass_=False,
+        pretty_print=True,
+    ):
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        for obj_ in self.anytypeobjs_:
+            obj_.export(outfile, level, namespace_, pretty_print=pretty_print)
+
+    def build(self, node):
+        already_processed = set()
+        self.buildAttributes(node, node.attrib, already_processed)
+        for child in node:
+            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+            self.buildChildren(child, node, nodeName_)
+        return self
+
+    def buildAttributes(self, node, attrs, already_processed):
+        pass
+
+    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+        obj_ = self.gds_build_any(child_, "notesType")
+        if obj_ is not None:
+            self.add_anytypeobjs_(obj_)
+
+
+# end class notesType
+
+
+class extensionType(GeneratedsSuper):
+    subclass = None
+    superclass = None
+
+    def __init__(self, anytypeobjs_=None):
+        self.original_tagname_ = None
+        if anytypeobjs_ is None:
+            self.anytypeobjs_ = []
+        else:
+            self.anytypeobjs_ = anytypeobjs_
+
+    def factory(*args_, **kwargs_):
+        if CurrentSubclassModule_ is not None:
+            subclass = getSubclassFromModule_(CurrentSubclassModule_, extensionType)
+            if subclass is not None:
+                return subclass(*args_, **kwargs_)
+        if extensionType.subclass:
+            return extensionType.subclass(*args_, **kwargs_)
+        else:
+            return extensionType(*args_, **kwargs_)
+
+    factory = staticmethod(factory)
+
+    def get_anytypeobjs_(self):
+        return self.anytypeobjs_
+
+    def set_anytypeobjs_(self, anytypeobjs_):
+        self.anytypeobjs_ = anytypeobjs_
+
+    def add_anytypeobjs_(self, value):
+        self.anytypeobjs_.append(value)
+
+    def insert_anytypeobjs_(self, index, value):
+        self._anytypeobjs_[index] = value
+
+    def hasContent_(self):
+        if self.anytypeobjs_:
+            return True
+        else:
+            return False
+
+    def export(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="extensionType",
+        namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"',
+        pretty_print=True,
+    ):
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        if self.original_tagname_ is not None:
+            name_ = self.original_tagname_
+        showIndent(outfile, level, pretty_print)
+        outfile.write(
+            "<%s%s%s"
+            % (
+                namespace_,
+                name_,
+                namespacedef_ and " " + namespacedef_ or "",
+            )
+        )
+        already_processed = set()
+        self.exportAttributes(
+            outfile, level, already_processed, namespace_, name_="extensionType"
+        )
+        if self.hasContent_():
+            outfile.write(">%s" % (eol_,))
+            self.exportChildren(
+                outfile,
+                level + 1,
+                namespace_="sbgn:",
+                name_="extensionType",
+                pretty_print=pretty_print,
+            )
+            showIndent(outfile, level, pretty_print)
+            outfile.write("</%s%s>%s" % (namespace_, name_, eol_))
+        else:
+            outfile.write("/>%s" % (eol_,))
+
+    def exportAttributes(
+        self,
+        outfile,
+        level,
+        already_processed,
+        namespace_="sbgn:",
+        name_="extensionType",
+    ):
+        pass
+
+    def exportChildren(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="extensionType",
+        fromsubclass_=False,
+        pretty_print=True,
+    ):
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        for obj_ in self.anytypeobjs_:
+            obj_.export(outfile, level, namespace_, pretty_print=pretty_print)
+
+    def build(self, node):
+        already_processed = set()
+        self.buildAttributes(node, node.attrib, already_processed)
+        for child in node:
+            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+            self.buildChildren(child, node, nodeName_)
+        return self
+
+    def buildAttributes(self, node, attrs, already_processed):
+        pass
+
+    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+        obj_ = self.gds_build_any(child_, "extensionType")
+        if obj_ is not None:
+            self.add_anytypeobjs_(obj_)
+
+
+# end class extensionType
+
+
+class stateType(GeneratedsSuper):
+    """The value attribute represents the state of the variable. It can be:
+    either from a predefined set of string (P, S, etc.) which
+    correspond to specific SBO terms (cf. SBGN specs), or any
+    arbitrary string. The variable attribute describes the site
+    where the modification described by the value attribute occurs.
+    It is: optional when there is only one state variable on the
+    parent EPN, required when there is more than one state variable
+    the parent EPN."""
+
+    subclass = None
+    superclass = None
+
+    def __init__(self, value=None, variable=None):
+        self.original_tagname_ = None
+        self.value = _cast(None, value)
+        self.variable = _cast(None, variable)
+
+    def factory(*args_, **kwargs_):
+        if CurrentSubclassModule_ is not None:
+            subclass = getSubclassFromModule_(CurrentSubclassModule_, stateType)
+            if subclass is not None:
+                return subclass(*args_, **kwargs_)
+        if stateType.subclass:
+            return stateType.subclass(*args_, **kwargs_)
+        else:
+            return stateType(*args_, **kwargs_)
+
+    factory = staticmethod(factory)
+
+    def get_value(self):
+        return self.value
+
+    def set_value(self, value):
+        self.value = value
+
+    def get_variable(self):
+        return self.variable
+
+    def set_variable(self, variable):
+        self.variable = variable
+
+    def hasContent_(self):
+        if ():
+            return True
+        else:
+            return False
+
+    def export(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="stateType",
+        namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"',
+        pretty_print=True,
+    ):
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        if self.original_tagname_ is not None:
+            name_ = self.original_tagname_
+        showIndent(outfile, level, pretty_print)
+        outfile.write(
+            "<%s%s%s"
+            % (
+                namespace_,
+                name_,
+                namespacedef_ and " " + namespacedef_ or "",
+            )
+        )
+        already_processed = set()
+        self.exportAttributes(
+            outfile, level, already_processed, namespace_, name_="stateType"
+        )
+        if self.hasContent_():
+            outfile.write(">%s" % (eol_,))
+            self.exportChildren(
+                outfile,
+                level + 1,
+                namespace_="sbgn:",
+                name_="stateType",
+                pretty_print=pretty_print,
+            )
+            outfile.write("</%s%s>%s" % (namespace_, name_, eol_))
+        else:
+            outfile.write("/>%s" % (eol_,))
+
+    def exportAttributes(
+        self, outfile, level, already_processed, namespace_="sbgn:", name_="stateType"
+    ):
+        if self.value is not None and "value" not in already_processed:
+            already_processed.add("value")
+            outfile.write(
+                " value=%s"
+                % (
+                    self.gds_encode(
+                        self.gds_format_string(
+                            quote_attrib(self.value), input_name="value"
+                        )
+                    ),
+                )
+            )
+        if self.variable is not None and "variable" not in already_processed:
+            already_processed.add("variable")
+            outfile.write(
+                " variable=%s"
+                % (
+                    self.gds_encode(
+                        self.gds_format_string(
+                            quote_attrib(self.variable), input_name="variable"
+                        )
+                    ),
+                )
+            )
+
+    def exportChildren(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="stateType",
+        fromsubclass_=False,
+        pretty_print=True,
+    ):
+        pass
+
+    def build(self, node):
+        already_processed = set()
+        self.buildAttributes(node, node.attrib, already_processed)
+        for child in node:
+            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+            self.buildChildren(child, node, nodeName_)
+        return self
+
+    def buildAttributes(self, node, attrs, already_processed):
+        value = find_attr_value_("value", node)
+        if value is not None and "value" not in already_processed:
+            already_processed.add("value")
+            self.value = value
+        value = find_attr_value_("variable", node)
+        if value is not None and "variable" not in already_processed:
+            already_processed.add("variable")
+            self.variable = value
+
+    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+        pass
+
+
+# end class stateType
+
+
+class cloneType(GeneratedsSuper):
+    subclass = None
+    superclass = None
+
+    def __init__(self, label=None):
+        self.original_tagname_ = None
+        self.label = label
+
+    def factory(*args_, **kwargs_):
+        if CurrentSubclassModule_ is not None:
+            subclass = getSubclassFromModule_(CurrentSubclassModule_, cloneType)
+            if subclass is not None:
+                return subclass(*args_, **kwargs_)
+        if cloneType.subclass:
+            return cloneType.subclass(*args_, **kwargs_)
+        else:
+            return cloneType(*args_, **kwargs_)
+
+    factory = staticmethod(factory)
+
+    def get_label(self):
+        return self.label
+
+    def set_label(self, label):
+        self.label = label
+
+    def hasContent_(self):
+        if self.label is not None:
+            return True
+        else:
+            return False
+
+    def export(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="cloneType",
+        namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"',
+        pretty_print=True,
+    ):
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        if self.original_tagname_ is not None:
+            name_ = self.original_tagname_
+        showIndent(outfile, level, pretty_print)
+        outfile.write(
+            "<%s%s%s"
+            % (
+                namespace_,
+                name_,
+                namespacedef_ and " " + namespacedef_ or "",
+            )
+        )
+        already_processed = set()
+        self.exportAttributes(
+            outfile, level, already_processed, namespace_, name_="cloneType"
+        )
+        if self.hasContent_():
+            outfile.write(">%s" % (eol_,))
+            self.exportChildren(
+                outfile,
+                level + 1,
+                namespace_="sbgn:",
+                name_="cloneType",
+                pretty_print=pretty_print,
+            )
+            showIndent(outfile, level, pretty_print)
+            outfile.write("</%s%s>%s" % (namespace_, name_, eol_))
+        else:
+            outfile.write("/>%s" % (eol_,))
+
+    def exportAttributes(
+        self, outfile, level, already_processed, namespace_="sbgn:", name_="cloneType"
+    ):
+        pass
+
+    def exportChildren(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="cloneType",
+        fromsubclass_=False,
+        pretty_print=True,
+    ):
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        if self.label is not None:
+            self.label.export(
+                outfile,
+                level,
+                namespace_="sbgn:",
+                name_="label",
+                pretty_print=pretty_print,
+            )
+
+    def build(self, node):
+        already_processed = set()
+        self.buildAttributes(node, node.attrib, already_processed)
+        for child in node:
+            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+            self.buildChildren(child, node, nodeName_)
+        return self
+
+    def buildAttributes(self, node, attrs, already_processed):
+        pass
+
+    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+        if nodeName_ == "label":
+            obj_ = label.factory()
+            obj_.build(child_)
+            self.label = obj_
+            obj_.original_tagname_ = "label"
+
+
+# end class cloneType
+
+
+class calloutType(GeneratedsSuper):
+    subclass = None
+    superclass = None
+
+    def __init__(self, target=None, point=None):
+        self.original_tagname_ = None
+        self.target = _cast(None, target)
+        self.point = point
+
+    def factory(*args_, **kwargs_):
+        if CurrentSubclassModule_ is not None:
+            subclass = getSubclassFromModule_(CurrentSubclassModule_, calloutType)
+            if subclass is not None:
+                return subclass(*args_, **kwargs_)
+        if calloutType.subclass:
+            return calloutType.subclass(*args_, **kwargs_)
+        else:
+            return calloutType(*args_, **kwargs_)
+
+    factory = staticmethod(factory)
+
+    def get_point(self):
+        return self.point
+
+    def set_point(self, point):
+        self.point = point
+
+    def get_target(self):
+        return self.target
+
+    def set_target(self, target):
+        self.target = target
+
+    def set_target(self, target):
+        if isinstance(target, glyph):
+            self.target = target.get_id()
+        else:
+            self.target = target
+
+    def hasContent_(self):
+        if self.point is not None:
+            return True
+        else:
+            return False
+
+    def export(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="calloutType",
+        namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"',
+        pretty_print=True,
+    ):
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        if self.original_tagname_ is not None:
+            name_ = self.original_tagname_
+        showIndent(outfile, level, pretty_print)
+        outfile.write(
+            "<%s%s%s"
+            % (
+                namespace_,
+                name_,
+                namespacedef_ and " " + namespacedef_ or "",
+            )
+        )
+        already_processed = set()
+        self.exportAttributes(
+            outfile, level, already_processed, namespace_, name_="calloutType"
+        )
+        if self.hasContent_():
+            outfile.write(">%s" % (eol_,))
+            self.exportChildren(
+                outfile,
+                level + 1,
+                namespace_="sbgn:",
+                name_="calloutType",
+                pretty_print=pretty_print,
+            )
+            showIndent(outfile, level, pretty_print)
+            outfile.write("</%s%s>%s" % (namespace_, name_, eol_))
+        else:
+            outfile.write("/>%s" % (eol_,))
+
+    def exportAttributes(
+        self, outfile, level, already_processed, namespace_="sbgn:", name_="calloutType"
+    ):
+        if self.target is not None and "target" not in already_processed:
+            already_processed.add("target")
+            outfile.write(
+                " target=%s"
+                % (
+                    self.gds_encode(
+                        self.gds_format_string(
+                            quote_attrib(self.target), input_name="target"
+                        )
+                    ),
+                )
+            )
+
+    def exportChildren(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="calloutType",
+        fromsubclass_=False,
+        pretty_print=True,
+    ):
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        if self.point is not None:
+            self.point.export(
+                outfile,
+                level,
+                namespace_="sbgn:",
+                name_="point",
+                pretty_print=pretty_print,
+            )
+
+    def build(self, node):
+        already_processed = set()
+        self.buildAttributes(node, node.attrib, already_processed)
+        for child in node:
+            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+            self.buildChildren(child, node, nodeName_)
+        return self
+
+    def buildAttributes(self, node, attrs, already_processed):
+        value = find_attr_value_("target", node)
+        if value is not None and "target" not in already_processed:
+            already_processed.add("target")
+            self.target = value
+
+    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+        if nodeName_ == "point":
+            obj_ = point.factory()
+            obj_.build(child_)
+            self.point = obj_
+            obj_.original_tagname_ = "point"
+
+
+# end class calloutType
+
+
+class entityType(GeneratedsSuper):
+    subclass = None
+    superclass = None
+
+    def __init__(self, name=None):
+        self.original_tagname_ = None
+        self.name = _cast(None, name)
+
+    def factory(*args_, **kwargs_):
+        if CurrentSubclassModule_ is not None:
+            subclass = getSubclassFromModule_(CurrentSubclassModule_, entityType)
+            if subclass is not None:
+                return subclass(*args_, **kwargs_)
+        if entityType.subclass:
+            return entityType.subclass(*args_, **kwargs_)
+        else:
+            return entityType(*args_, **kwargs_)
+
+    factory = staticmethod(factory)
+
+    def get_name(self):
+        return self.name
+
+    def set_name(self, name):
+        self.name = name
+
+    def hasContent_(self):
+        if ():
+            return True
+        else:
+            return False
+
+    def export(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="entityType",
+        namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"',
+        pretty_print=True,
+    ):
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        if self.original_tagname_ is not None:
+            name_ = self.original_tagname_
+        showIndent(outfile, level, pretty_print)
+        outfile.write(
+            "<%s%s%s"
+            % (
+                namespace_,
+                name_,
+                namespacedef_ and " " + namespacedef_ or "",
+            )
+        )
+        already_processed = set()
+        self.exportAttributes(
+            outfile, level, already_processed, namespace_, name_="entityType"
+        )
+        if self.hasContent_():
+            outfile.write(">%s" % (eol_,))
+            self.exportChildren(
+                outfile,
+                level + 1,
+                namespace_="sbgn:",
+                name_="entityType",
+                pretty_print=pretty_print,
+            )
+            outfile.write("</%s%s>%s" % (namespace_, name_, eol_))
+        else:
+            outfile.write("/>%s" % (eol_,))
+
+    def exportAttributes(
+        self, outfile, level, already_processed, namespace_="sbgn:", name_="entityType"
+    ):
+        if self.name is not None and "name" not in already_processed:
+            already_processed.add("name")
+            outfile.write(
+                " name=%s"
+                % (
+                    self.gds_encode(
+                        self.gds_format_string(
+                            quote_attrib(self.name), input_name="name"
+                        )
+                    ),
+                )
+            )
+
+    def exportChildren(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="entityType",
+        fromsubclass_=False,
+        pretty_print=True,
+    ):
+        pass
+
+    def build(self, node):
+        already_processed = set()
+        self.buildAttributes(node, node.attrib, already_processed)
+        for child in node:
+            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+            self.buildChildren(child, node, nodeName_)
+        return self
+
+    def buildAttributes(self, node, attrs, already_processed):
+        value = find_attr_value_("name", node)
+        if value is not None and "name" not in already_processed:
+            already_processed.add("name")
+            self.name = value
+
+    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+        pass
+
+
+# end class entityType
+
+
+class startType(GeneratedsSuper):
+    subclass = None
+    superclass = None
+
+    def __init__(self, x=None, y=None):
+        self.original_tagname_ = None
+        self.x = _cast(float, x)
+        self.y = _cast(float, y)
+
+    def factory(*args_, **kwargs_):
+        if CurrentSubclassModule_ is not None:
+            subclass = getSubclassFromModule_(CurrentSubclassModule_, startType)
+            if subclass is not None:
+                return subclass(*args_, **kwargs_)
+        if startType.subclass:
+            return startType.subclass(*args_, **kwargs_)
+        else:
+            return startType(*args_, **kwargs_)
+
+    factory = staticmethod(factory)
+
+    def get_x(self):
+        return self.x
+
+    def set_x(self, x):
+        self.x = x
+
+    def get_y(self):
+        return self.y
+
+    def set_y(self, y):
+        self.y = y
+
+    def hasContent_(self):
+        if ():
+            return True
+        else:
+            return False
+
+    def export(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="startType",
+        namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"',
+        pretty_print=True,
+    ):
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        if self.original_tagname_ is not None:
+            name_ = self.original_tagname_
+        showIndent(outfile, level, pretty_print)
+        outfile.write(
+            "<%s%s%s"
+            % (
+                namespace_,
+                name_,
+                namespacedef_ and " " + namespacedef_ or "",
+            )
+        )
+        already_processed = set()
+        self.exportAttributes(
+            outfile, level, already_processed, namespace_, name_="startType"
+        )
+        if self.hasContent_():
+            outfile.write(">%s" % (eol_,))
+            self.exportChildren(
+                outfile,
+                level + 1,
+                namespace_="sbgn:",
+                name_="startType",
+                pretty_print=pretty_print,
+            )
+            outfile.write("</%s%s>%s" % (namespace_, name_, eol_))
+        else:
+            outfile.write("/>%s" % (eol_,))
+
+    def exportAttributes(
+        self, outfile, level, already_processed, namespace_="sbgn:", name_="startType"
+    ):
+        if self.x is not None and "x" not in already_processed:
+            already_processed.add("x")
+            outfile.write(' x="%s"' % self.gds_format_float(self.x, input_name="x"))
+        if self.y is not None and "y" not in already_processed:
+            already_processed.add("y")
+            outfile.write(' y="%s"' % self.gds_format_float(self.y, input_name="y"))
+
+    def exportChildren(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="startType",
+        fromsubclass_=False,
+        pretty_print=True,
+    ):
+        pass
+
+    def build(self, node):
+        already_processed = set()
+        self.buildAttributes(node, node.attrib, already_processed)
+        for child in node:
+            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+            self.buildChildren(child, node, nodeName_)
+        return self
+
+    def buildAttributes(self, node, attrs, already_processed):
+        value = find_attr_value_("x", node)
+        if value is not None and "x" not in already_processed:
+            already_processed.add("x")
+            try:
+                self.x = float(value)
+            except ValueError as exp:
+                raise ValueError("Bad float/double attribute (x): %s" % exp)
+        value = find_attr_value_("y", node)
+        if value is not None and "y" not in already_processed:
+            already_processed.add("y")
+            try:
+                self.y = float(value)
+            except ValueError as exp:
+                raise ValueError("Bad float/double attribute (y): %s" % exp)
+
+    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+        pass
+
+
+# end class startType
+
+
+class nextType(GeneratedsSuper):
+    """List of control points, used when the path describes a curve. The
+    number of points describes the degree of the Bezier curve:
+    linear (0), quadratic (1) or cubic (2)"""
+
+    subclass = None
+    superclass = None
+
+    def __init__(self, x=None, y=None, point=None):
+        self.original_tagname_ = None
+        self.x = _cast(float, x)
+        self.y = _cast(float, y)
+        if point is None:
+            self.point = []
+        else:
+            self.point = point
+
+    def factory(*args_, **kwargs_):
+        if CurrentSubclassModule_ is not None:
+            subclass = getSubclassFromModule_(CurrentSubclassModule_, nextType)
+            if subclass is not None:
+                return subclass(*args_, **kwargs_)
+        if nextType.subclass:
+            return nextType.subclass(*args_, **kwargs_)
+        else:
+            return nextType(*args_, **kwargs_)
+
+    factory = staticmethod(factory)
+
+    def get_point(self):
+        return self.point
+
+    def set_point(self, point):
+        self.point = point
+
+    def add_point(self, value):
+        self.point.append(value)
+
+    def insert_point_at(self, index, value):
+        self.point.insert(index, value)
+
+    def replace_point_at(self, index, value):
+        self.point[index] = value
+
+    def get_x(self):
+        return self.x
+
+    def set_x(self, x):
+        self.x = x
+
+    def get_y(self):
+        return self.y
+
+    def set_y(self, y):
+        self.y = y
+
+    def hasContent_(self):
+        if self.point:
+            return True
+        else:
+            return False
+
+    def export(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="nextType",
+        namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"',
+        pretty_print=True,
+    ):
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        if self.original_tagname_ is not None:
+            name_ = self.original_tagname_
+        showIndent(outfile, level, pretty_print)
+        outfile.write(
+            "<%s%s%s"
+            % (
+                namespace_,
+                name_,
+                namespacedef_ and " " + namespacedef_ or "",
+            )
+        )
+        already_processed = set()
+        self.exportAttributes(
+            outfile, level, already_processed, namespace_, name_="nextType"
+        )
+        if self.hasContent_():
+            outfile.write(">%s" % (eol_,))
+            self.exportChildren(
+                outfile,
+                level + 1,
+                namespace_="sbgn:",
+                name_="nextType",
+                pretty_print=pretty_print,
+            )
+            showIndent(outfile, level, pretty_print)
+            outfile.write("</%s%s>%s" % (namespace_, name_, eol_))
+        else:
+            outfile.write("/>%s" % (eol_,))
+
+    def exportAttributes(
+        self, outfile, level, already_processed, namespace_="sbgn:", name_="nextType"
+    ):
+        if self.x is not None and "x" not in already_processed:
+            already_processed.add("x")
+            outfile.write(' x="%s"' % self.gds_format_float(self.x, input_name="x"))
+        if self.y is not None and "y" not in already_processed:
+            already_processed.add("y")
+            outfile.write(' y="%s"' % self.gds_format_float(self.y, input_name="y"))
+
+    def exportChildren(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="nextType",
+        fromsubclass_=False,
+        pretty_print=True,
+    ):
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        for point_ in self.point:
+            point_.export(
+                outfile,
+                level,
+                namespace_="sbgn:",
+                name_="point",
+                pretty_print=pretty_print,
+            )
+
+    def build(self, node):
+        already_processed = set()
+        self.buildAttributes(node, node.attrib, already_processed)
+        for child in node:
+            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+            self.buildChildren(child, node, nodeName_)
+        return self
+
+    def buildAttributes(self, node, attrs, already_processed):
+        value = find_attr_value_("x", node)
+        if value is not None and "x" not in already_processed:
+            already_processed.add("x")
+            try:
+                self.x = float(value)
+            except ValueError as exp:
+                raise ValueError("Bad float/double attribute (x): %s" % exp)
+        value = find_attr_value_("y", node)
+        if value is not None and "y" not in already_processed:
+            already_processed.add("y")
+            try:
+                self.y = float(value)
+            except ValueError as exp:
+                raise ValueError("Bad float/double attribute (y): %s" % exp)
+
+    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+        if nodeName_ == "point":
+            obj_ = point.factory()
+            obj_.build(child_)
+            self.point.append(obj_)
+            obj_.original_tagname_ = "point"
+
+
+# end class nextType
+
+
+class endType(GeneratedsSuper):
+    """List of control points, used when the path describes a curve. The
+    number of points describes the degree of the Bezier curve:
+    linear (0), quadratic (1) or cubic (2)"""
+
+    subclass = None
+    superclass = None
+
+    def __init__(self, x=None, y=None, point=None):
+        self.original_tagname_ = None
+        self.x = _cast(float, x)
+        self.y = _cast(float, y)
+        if point is None:
+            self.point = []
+        else:
+            self.point = point
+
+    def factory(*args_, **kwargs_):
+        if CurrentSubclassModule_ is not None:
+            subclass = getSubclassFromModule_(CurrentSubclassModule_, endType)
+            if subclass is not None:
+                return subclass(*args_, **kwargs_)
+        if endType.subclass:
+            return endType.subclass(*args_, **kwargs_)
+        else:
+            return endType(*args_, **kwargs_)
+
+    factory = staticmethod(factory)
+
+    def get_point(self):
+        return self.point
+
+    def set_point(self, point):
+        self.point = point
+
+    def add_point(self, value):
+        self.point.append(value)
+
+    def insert_point_at(self, index, value):
+        self.point.insert(index, value)
+
+    def replace_point_at(self, index, value):
+        self.point[index] = value
+
+    def get_x(self):
+        return self.x
+
+    def set_x(self, x):
+        self.x = x
+
+    def get_y(self):
+        return self.y
+
+    def set_y(self, y):
+        self.y = y
+
+    def hasContent_(self):
+        if self.point:
+            return True
+        else:
+            return False
+
+    def export(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="endType",
+        namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"',
+        pretty_print=True,
+    ):
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        if self.original_tagname_ is not None:
+            name_ = self.original_tagname_
+        showIndent(outfile, level, pretty_print)
+        outfile.write(
+            "<%s%s%s"
+            % (
+                namespace_,
+                name_,
+                namespacedef_ and " " + namespacedef_ or "",
+            )
+        )
+        already_processed = set()
+        self.exportAttributes(
+            outfile, level, already_processed, namespace_, name_="endType"
+        )
+        if self.hasContent_():
+            outfile.write(">%s" % (eol_,))
+            self.exportChildren(
+                outfile,
+                level + 1,
+                namespace_="sbgn:",
+                name_="endType",
+                pretty_print=pretty_print,
+            )
+            showIndent(outfile, level, pretty_print)
+            outfile.write("</%s%s>%s" % (namespace_, name_, eol_))
+        else:
+            outfile.write("/>%s" % (eol_,))
+
+    def exportAttributes(
+        self, outfile, level, already_processed, namespace_="sbgn:", name_="endType"
+    ):
+        if self.x is not None and "x" not in already_processed:
+            already_processed.add("x")
+            outfile.write(' x="%s"' % self.gds_format_float(self.x, input_name="x"))
+        if self.y is not None and "y" not in already_processed:
+            already_processed.add("y")
+            outfile.write(' y="%s"' % self.gds_format_float(self.y, input_name="y"))
+
+    def exportChildren(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_="endType",
+        fromsubclass_=False,
+        pretty_print=True,
+    ):
+        if pretty_print:
+            eol_ = "\n"
+        else:
+            eol_ = ""
+        for point_ in self.point:
+            point_.export(
+                outfile,
+                level,
+                namespace_="sbgn:",
+                name_="point",
+                pretty_print=pretty_print,
+            )
+
+    def build(self, node):
+        already_processed = set()
+        self.buildAttributes(node, node.attrib, already_processed)
+        for child in node:
+            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+            self.buildChildren(child, node, nodeName_)
+        return self
+
+    def buildAttributes(self, node, attrs, already_processed):
+        value = find_attr_value_("x", node)
+        if value is not None and "x" not in already_processed:
+            already_processed.add("x")
+            try:
+                self.x = float(value)
+            except ValueError as exp:
+                raise ValueError("Bad float/double attribute (x): %s" % exp)
+        value = find_attr_value_("y", node)
+        if value is not None and "y" not in already_processed:
+            already_processed.add("y")
+            try:
+                self.y = float(value)
+            except ValueError as exp:
+                raise ValueError("Bad float/double attribute (y): %s" % exp)
+
+    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+        if nodeName_ == "point":
+            obj_ = point.factory()
+            obj_.build(child_)
+            self.point.append(obj_)
+            obj_.original_tagname_ = "point"
+
+
+# end class endType
+
+
+GDSClassesMapping = {
+    "callout": calloutType,
+    "clone": cloneType,
+    "end": endType,
+    "entity": entityType,
+    "extension": extensionType,
+    "next": nextType,
+    "notes": notesType,
+    "start": startType,
+    "state": stateType,
+}
+
+
+USAGE_TEXT = """
+Usage: python <Parser>.py [ -s ] <in_xml_file>
+"""
+
+
+def usage():
+    print(USAGE_TEXT)
+    sys.exit(1)
+
+
+def get_root_tag(node):
+    tag = Tag_pattern_.match(node.tag).groups()[-1]
+    rootClass = GDSClassesMapping.get(tag)
+    if rootClass is None:
+        rootClass = globals().get(tag)
+    return tag, rootClass
+
+
+def parse(inFileName, silence=False):
+    parser = None
+    doc = parsexml_(inFileName, parser)
+    rootNode = doc.getroot()
+    rootTag, rootClass = get_root_tag(rootNode)
+    if rootClass is None:
+        rootTag = "SBGNBase"
+        rootClass = SBGNBase
+    rootObj = rootClass.factory()
+    rootObj.build(rootNode)
+    # Enable Python to collect the space used by the DOM.
+    doc = None
+    if not silence:
+        sys.stdout.write('<?xml version="1.0" ?>\n')
+        rootObj.export(
+            sys.stdout,
+            0,
+            name_=rootTag,
+            namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"',
+            pretty_print=True,
+        )
+    return rootObj
+
+
+def parseEtree(inFileName, silence=False):
+    parser = None
+    doc = parsexml_(inFileName, parser)
+    rootNode = doc.getroot()
+    rootTag, rootClass = get_root_tag(rootNode)
+    if rootClass is None:
+        rootTag = "SBGNBase"
+        rootClass = SBGNBase
+    rootObj = rootClass.factory()
+    rootObj.build(rootNode)
+    # Enable Python to collect the space used by the DOM.
+    doc = None
+    mapping = {}
+    rootElement = rootObj.to_etree(None, name_=rootTag, mapping_=mapping)
+    reverse_mapping = rootObj.gds_reverse_node_mapping(mapping)
+    if not silence:
+        content = etree_.tostring(
+            rootElement, pretty_print=True, xml_declaration=True, encoding="utf-8"
+        )
+        sys.stdout.write(content)
+        sys.stdout.write("\n")
+    return rootObj, rootElement, mapping, reverse_mapping
+
+
+def parseString(inString, silence=False):
+    from StringIO import StringIO
+
+    parser = None
+    doc = parsexml_(StringIO(inString), parser)
+    rootNode = doc.getroot()
+    rootTag, rootClass = get_root_tag(rootNode)
+    if rootClass is None:
+        rootTag = "SBGNBase"
+        rootClass = SBGNBase
+    rootObj = rootClass.factory()
+    rootObj.build(rootNode)
+    # Enable Python to collect the space used by the DOM.
+    doc = None
+    if not silence:
+        sys.stdout.write('<?xml version="1.0" ?>\n')
+        rootObj.export(
+            sys.stdout,
+            0,
+            name_=rootTag,
+            namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"',
+        )
+    return rootObj
+
+
+def parseLiteral(inFileName, silence=False):
+    parser = None
+    doc = parsexml_(inFileName, parser)
+    rootNode = doc.getroot()
+    rootTag, rootClass = get_root_tag(rootNode)
+    if rootClass is None:
+        rootTag = "SBGNBase"
+        rootClass = SBGNBase
+    rootObj = rootClass.factory()
+    rootObj.build(rootNode)
+    # Enable Python to collect the space used by the DOM.
+    doc = None
+    if not silence:
+        sys.stdout.write("#from libsbgn import *\n\n")
+        sys.stdout.write("import libsbgn as model_\n\n")
+        sys.stdout.write("rootObj = model_.rootClass(\n")
+        rootObj.exportLiteral(sys.stdout, 0, name_=rootTag)
+        sys.stdout.write(")\n")
+    return rootObj
+
+
+def main():
+    args = sys.argv[1:]
+    if len(args) == 1:
+        parse(args[0])
+    else:
+        usage()
+
+
+if __name__ == "__main__":
+    # import pdb; pdb.set_trace()
+    main()
+
+
+__all__ = [
+    "SBGNBase",
+    "arc",
+    "arcgroup",
+    "bbox",
+    "calloutType",
+    "cloneType",
+    "endType",
+    "entityType",
+    "extensionType",
+    "glyph",
+    "label",
+    "map",
+    "nextType",
+    "notesType",
+    "point",
+    "port",
+    "sbgn",
+    "startType",
+    "stateType",
+]
diff --git a/libsbgnpy/libsbgnSubs.py b/src/libsbgnpy/libsbgnSubs.py
similarity index 73%
rename from libsbgnpy/libsbgnSubs.py
rename to src/libsbgnpy/libsbgnSubs.py
index bc6c8ce..7c46584 100644
--- a/libsbgnpy/libsbgnSubs.py
+++ b/src/libsbgnpy/libsbgnSubs.py
@@ -12,7 +12,7 @@
 
 
 def _process_xml_input(input):
-    """ Helper function for input to Notes and Extension.
+    """Helper function for input to Notes and Extension.
 
     :param input: xml_string
     :return: anytypeobjs_
@@ -24,7 +24,6 @@ def _process_xml_input(input):
 
 
 class _Information(object):
-
     def __str__(self):
         if type(self.anytypeobjs_) in (list, tuple):
             return str(self.anytypeobjs_[0])
@@ -34,17 +33,24 @@ def __str__(self):
     def hasContent_(self):
         return self.anytypeobjs_ is not None
 
-    def export(self, outfile, level, namespace_='sbgn:', name_=None,
-               namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"', pretty_print=True):
-        """ Custom export function.
+    def export(
+        self,
+        outfile,
+        level,
+        namespace_="sbgn:",
+        name_=None,
+        namespacedef_='xmlns:sbgn="http://sbgn.org/libsbgn/0.2"',
+        pretty_print=True,
+    ):
+        """Custom export function.
 
         Necessary to provide handling for the xsd:any.
         """
         name_ = self.__class__.__name__.lower()
         if pretty_print:
-            eol_ = '\n'
+            eol_ = "\n"
         else:
-            eol_ = ''
+            eol_ = ""
 
         if self.hasContent_():
             # notes defined as sequence, so handle the normal case of just having string
@@ -52,27 +58,33 @@ def export(self, outfile, level, namespace_='sbgn:', name_=None,
             if type(self.anytypeobjs_) not in [list, tuple]:
                 notes_items = [notes_items]
             showIndent(outfile, level, pretty_print)
-            outfile.write('<%s%s%s>%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', eol_))
+            outfile.write(
+                "<%s%s%s>%s"
+                % (namespace_, name_, namespacedef_ and " " + namespacedef_ or "", eol_)
+            )
             for obj_ in notes_items:
                 showIndent(outfile, level, pretty_print)
-                outfile.write('%s%s' % (obj_, eol_))
+                outfile.write("%s%s" % (obj_, eol_))
             showIndent(outfile, level, pretty_print)
-            outfile.write('</%s%s%s>%s' % (namespace_, name_, namespacedef_ and ' ' + namespacedef_ or '', eol_))
+            outfile.write(
+                "</%s%s%s>%s"
+                % (namespace_, name_, namespacedef_ and " " + namespacedef_ or "", eol_)
+            )
 
     def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
-        """ Custom build function.
+        """Custom build function.
 
         Necessary to provide handling for the xsd:any.
         """
         # This is the lxml.etree._Element, in first version going via strings
-        obj_ = etree_.tostring(child_, pretty_print=False)
+        obj_ = etree_.tostring(child_, pretty_print=False, encoding="unicode")
         # print('obj_', obj_)
         if obj_ is not None:
             self.add_anytypeobjs_(obj_)
 
 
 class Notes(_Information, supermod.notesType):
-    """ SBGN Notes class.
+    """SBGN Notes class.
 
     The optional SBGN element named 'notes', present on every major SBGN
     component type, is intended as a place for storing optional
@@ -85,14 +97,18 @@ class Notes(_Information, supermod.notesType):
 
     The format of 'notes' elements must be XHTML 1.0 (http://www.w3.org/1999/xhtml).
     """
+
     def __init__(self, xml_string=None):
-        super(Notes, self).__init__(_process_xml_input(xml_string), )
+        super(Notes, self).__init__(
+            _process_xml_input(xml_string),
+        )
+
 
 supermod.notesType.subclass = Notes
 
 
 class Extension(_Information, supermod.extensionType):
-    """ SBGN Extension class.
+    """SBGN Extension class.
 
     Any well-formed XML content, and with each top-level element placed in a unique XML namespace; see text.
     Whereas Notes is a container for content to be shown directly to humans, Extension is a container for
@@ -102,6 +118,9 @@ class Extension(_Information, supermod.extensionType):
     """
 
     def __init__(self, xml_string=None):
-        super(Extension, self).__init__(_process_xml_input(xml_string), )
+        super(Extension, self).__init__(
+            _process_xml_input(xml_string),
+        )
+
 
 supermod.extensionType.subclass = Extension
diff --git a/libsbgnpy/libsbgnTypes.py b/src/libsbgnpy/libsbgnTypes.py
similarity index 99%
rename from libsbgnpy/libsbgnTypes.py
rename to src/libsbgnpy/libsbgnTypes.py
index c012c7f..8b560eb 100644
--- a/libsbgnpy/libsbgnTypes.py
+++ b/src/libsbgnpy/libsbgnTypes.py
@@ -11,6 +11,7 @@ class Language(Enum):
     """
     Enum representing the three languages of SBGN.
     """
+
     AF = "activity flow"
     ER = "entity relationship"
     PD = "process description"
@@ -32,6 +33,7 @@ class GlyphClass(Enum):
     Enumeration with all possible values for the class attribute of Glyphs in SBGN-ML.
     This includes both top-level glyphs and sub-glyphs.
     """
+
     # glyphs
     UNSPECIFIED_ENTITY = "unspecified entity"
     SIMPLE_CHEMICAL = "simple chemical"
@@ -89,6 +91,7 @@ class ArcClass(Enum):
     """
     Enumeration with all possible values for the class attribute of Arcs in SBGN-ML.
     """
+
     # arcs
     PRODUCTION = "production"
     CONSUMPTION = "consumption"
diff --git a/libsbgnpy/misc/__init__.py b/src/libsbgnpy/misc/__init__.py
similarity index 100%
rename from libsbgnpy/misc/__init__.py
rename to src/libsbgnpy/misc/__init__.py
diff --git a/libsbgnpy/misc/sbgn_sbo_mapping.txt b/src/libsbgnpy/misc/sbgn_sbo_mapping.txt
similarity index 100%
rename from libsbgnpy/misc/sbgn_sbo_mapping.txt
rename to src/libsbgnpy/misc/sbgn_sbo_mapping.txt
diff --git a/libsbgnpy/misc/sbo2sbgn.py b/src/libsbgnpy/misc/sbo2sbgn.py
similarity index 73%
rename from libsbgnpy/misc/sbo2sbgn.py
rename to src/libsbgnpy/misc/sbo2sbgn.py
index 10b0749..71e131e 100644
--- a/libsbgnpy/misc/sbo2sbgn.py
+++ b/src/libsbgnpy/misc/sbo2sbgn.py
@@ -14,15 +14,15 @@ def _clean_line(line):
     :param line:
     :return:
     """
-    tokens = [item.strip() for item in line.split('!')]
-    sbo = tokens[0].split(' ')[1]
-    sbgn = tokens[1].replace('.', "")
+    tokens = [item.strip() for item in line.split("!")]
+    sbo = tokens[0].split(" ")[1]
+    sbgn = tokens[1].replace(".", "")
     return sbo, sbgn
 
 
 def _is_sbo(sbo_term):
     """ Check is sbo_term is really a SBO term."""
-    res = re.search('^SBO:\d{7}$', sbo_term)
+    res = re.search("^SBO:\d{7}$", sbo_term)
     return res is not None
 
 
@@ -44,14 +44,14 @@ def write_sbo2sbgn(outfile, sbo2sbgn):
     """
     Write the sorted entries
     """
-    with open(outfile, 'w') as f_out:
+    with open(outfile, "w") as f_out:
         for sbo in sorted(sbo2sbgn.keys()):
             sbgn_set = sorted(sbo2sbgn[sbo])
             if not _is_sbo(sbo):
-                print('Not SBO:', sbo, sbgn_set)
+                print("Not SBO:", sbo, sbgn_set)
             else:
                 # print(sbo, ':', sbgn_set)
-                f_out.write('{}\t{}{}'.format(sbo, sbgn_set, os.linesep))
+                f_out.write("{}\t{}{}".format(sbo, sbgn_set, os.linesep))
 
 
 if __name__ == "__main__":
@@ -59,8 +59,8 @@ def write_sbo2sbgn(outfile, sbo2sbgn):
     Cleanup of mapping and writing to file.
     """
     dir = os.path.dirname(os.path.abspath(__file__))
-    infile = os.path.join(dir, 'sbgn_sbo_mapping.txt')
-    outfile = os.path.join(dir, 'sbo_sbgn_map.txt')
+    infile = os.path.join(dir, "sbgn_sbo_mapping.txt")
+    outfile = os.path.join(dir, "sbo_sbgn_map.txt")
 
     sbo2sbgn = read_sbo2sbgn(infile)
     print(sbo2sbgn)
diff --git a/libsbgnpy/misc/sbo_sbgn_map.txt b/src/libsbgnpy/misc/sbo_sbgn_map.txt
similarity index 100%
rename from libsbgnpy/misc/sbo_sbgn_map.txt
rename to src/libsbgnpy/misc/sbo_sbgn_map.txt
diff --git a/libsbgnpy/render.py b/src/libsbgnpy/render.py
similarity index 77%
rename from libsbgnpy/render.py
rename to src/libsbgnpy/render.py
index c48a380..4114962 100644
--- a/libsbgnpy/render.py
+++ b/src/libsbgnpy/render.py
@@ -6,15 +6,18 @@
 For documentation see
 http://sysbioapps.dyndns.org/Home/Services
 """
-from libsbgnpy import utils
-import requests
 import tempfile
 
+import requests
+
+from libsbgnpy import utils
+
+
 RENDER_URL = "http://sysbioapps.spdns.org/Layout"
 
 
 def render_sbgn(sbgn, image_file, file_format="png"):
-    """ Render given sbgn object to image.
+    """Render given sbgn object to image.
 
     Currently supports the following file_formats:
     - "png"
@@ -29,8 +32,10 @@ def render_sbgn(sbgn, image_file, file_format="png"):
     """
     if file_format is not "png":
         raise ValueError("Only png rendering supported.")
-    if not image_file.endswith('.{}'.format(file_format)):
-        raise ValueError("The filename must end in <.file_format>, e.g. for png it must end in <.png>.")
+    if not image_file.endswith(".{}".format(file_format)):
+        raise ValueError(
+            "The filename must end in <.file_format>, e.g. for png it must end in <.png>."
+        )
 
     # Create temporary file
     f_in = tempfile.NamedTemporaryFile(suffix=".sbgn")
@@ -38,13 +43,13 @@ def render_sbgn(sbgn, image_file, file_format="png"):
 
     # Call webservice for rendering
     files = [
-        ('file', open(f_in.name, 'rb')),
+        ("file", open(f_in.name, "rb")),
     ]
 
     r = requests.post("{}/GenerateImage".format(RENDER_URL), files=files)
     r.raise_for_status()
 
-    with open(image_file, 'wb') as fd:
+    with open(image_file, "wb") as fd:
         for chunk in r.iter_content(chunk_size=128):
             fd.write(chunk)
-    print('SBGN rendered:', image_file)
+    print("SBGN rendered:", image_file)
diff --git a/libsbgnpy/schema/README.md b/src/libsbgnpy/schema/README.md
similarity index 100%
rename from libsbgnpy/schema/README.md
rename to src/libsbgnpy/schema/README.md
diff --git a/libsbgnpy/schema/SBGN.xsd b/src/libsbgnpy/schema/SBGN.xsd
similarity index 100%
rename from libsbgnpy/schema/SBGN.xsd
rename to src/libsbgnpy/schema/SBGN.xsd
diff --git a/libsbgnpy/schema/__init__.py b/src/libsbgnpy/schema/__init__.py
similarity index 100%
rename from libsbgnpy/schema/__init__.py
rename to src/libsbgnpy/schema/__init__.py
diff --git a/libsbgnpy/utils.py b/src/libsbgnpy/utils.py
similarity index 77%
rename from libsbgnpy/utils.py
rename to src/libsbgnpy/utils.py
index 8fd657b..f67bcd0 100644
--- a/libsbgnpy/utils.py
+++ b/src/libsbgnpy/utils.py
@@ -6,7 +6,7 @@
 
 
 def read_from_file(f, silence=True):
-    """ Read an sbgn file (without validating against the schema).
+    """Read an sbgn file (without validating against the schema).
 
     :param silence: display no information
     :param f: file to read
@@ -18,7 +18,7 @@ def read_from_file(f, silence=True):
 
 
 def write_to_file(sbgn, f):
-    """ Write sbgn object to file.
+    """Write sbgn object to file.
 
     :param sbgn:
     :param f:
@@ -28,23 +28,24 @@ def write_to_file(sbgn, f):
 
 
 def write_to_string(sbgn):
-    """ Write SBGN to string.
+    """Write SBGN to string.
     Returns None if problems.
 
     :param sbgn: sbgn object
     :return: SBGN xml string
     """
     import tempfile
-    f = tempfile.NamedTemporaryFile(suffix='.sbgn')
+
+    f = tempfile.NamedTemporaryFile(suffix=".sbgn")
     write_to_file(sbgn, f.name)
-    with open(f.name, 'rt') as fin:
+    with open(f.name, "rt") as fin:
         sbgn_str = fin.read()
         return sbgn_str
     return None
 
 
 def get_version(f):
-    """ SBGN version.
+    """SBGN version.
 
     1: xmlns="http://sbgn.org/libsbgn/0.1
     2: xmlns="http://sbgn.org/libsbgn/0.2
@@ -55,17 +56,18 @@ def get_version(f):
     """
     import re
     from xml.etree import ElementTree
+
     tree = ElementTree.parse(f)
     root = tree.getroot()
     tag = root.tag
     m = re.search(r"\d\.\d", tag)
     version = m.group(0)  # full version, i.e. 0.2 or similar
-    tokens = version.split('.')
+    tokens = version.split(".")
     return int(tokens[-1])
 
 
 def get_language(f):
-    """ SBGN language of the map.
+    """SBGN language of the map.
     Returns a Language value.
 
     :param f:
@@ -77,11 +79,11 @@ def get_language(f):
 
 
 def print_bbox(b):
-    """ Print bounding box representation.
+    """Print bounding box representation.
 
     :param b:
     :type b:
     :return:
     :rtype:
     """
-    print('x, y, w, h : ', b.get_x(), b.get_y(), b.get_w(), b.get_h())
+    print("x, y, w, h : ", b.get_x(), b.get_y(), b.get_w(), b.get_h())
diff --git a/libsbgnpy/validation/__init__.py b/src/libsbgnpy/validation/__init__.py
similarity index 100%
rename from libsbgnpy/validation/__init__.py
rename to src/libsbgnpy/validation/__init__.py
diff --git a/libsbgnpy/validation/rules/sbgn_af.sch b/src/libsbgnpy/validation/rules/sbgn_af.sch
similarity index 100%
rename from libsbgnpy/validation/rules/sbgn_af.sch
rename to src/libsbgnpy/validation/rules/sbgn_af.sch
diff --git a/libsbgnpy/validation/rules/sbgn_er.sch b/src/libsbgnpy/validation/rules/sbgn_er.sch
similarity index 100%
rename from libsbgnpy/validation/rules/sbgn_er.sch
rename to src/libsbgnpy/validation/rules/sbgn_er.sch
diff --git a/libsbgnpy/validation/rules/sbgn_pd.sch b/src/libsbgnpy/validation/rules/sbgn_pd.sch
similarity index 100%
rename from libsbgnpy/validation/rules/sbgn_pd.sch
rename to src/libsbgnpy/validation/rules/sbgn_pd.sch
diff --git a/libsbgnpy/validation/schematron/ExtractSchFromRNG.xsl b/src/libsbgnpy/validation/schematron/ExtractSchFromRNG.xsl
similarity index 100%
rename from libsbgnpy/validation/schematron/ExtractSchFromRNG.xsl
rename to src/libsbgnpy/validation/schematron/ExtractSchFromRNG.xsl
diff --git a/libsbgnpy/validation/schematron/ExtractSchFromXSD.xsl b/src/libsbgnpy/validation/schematron/ExtractSchFromXSD.xsl
similarity index 100%
rename from libsbgnpy/validation/schematron/ExtractSchFromXSD.xsl
rename to src/libsbgnpy/validation/schematron/ExtractSchFromXSD.xsl
diff --git a/libsbgnpy/validation/schematron/iso-schematron-xslt1.zip b/src/libsbgnpy/validation/schematron/iso-schematron-xslt1.zip
similarity index 100%
rename from libsbgnpy/validation/schematron/iso-schematron-xslt1.zip
rename to src/libsbgnpy/validation/schematron/iso-schematron-xslt1.zip
diff --git a/libsbgnpy/validation/schematron/iso-schematron-xslt2.zip b/src/libsbgnpy/validation/schematron/iso-schematron-xslt2.zip
similarity index 100%
rename from libsbgnpy/validation/schematron/iso-schematron-xslt2.zip
rename to src/libsbgnpy/validation/schematron/iso-schematron-xslt2.zip
diff --git a/libsbgnpy/validation/schematron/iso_abstract_expand.xsl b/src/libsbgnpy/validation/schematron/iso_abstract_expand.xsl
similarity index 100%
rename from libsbgnpy/validation/schematron/iso_abstract_expand.xsl
rename to src/libsbgnpy/validation/schematron/iso_abstract_expand.xsl
diff --git a/libsbgnpy/validation/schematron/iso_dsdl_include.xsl b/src/libsbgnpy/validation/schematron/iso_dsdl_include.xsl
similarity index 100%
rename from libsbgnpy/validation/schematron/iso_dsdl_include.xsl
rename to src/libsbgnpy/validation/schematron/iso_dsdl_include.xsl
diff --git a/libsbgnpy/validation/schematron/iso_schematron_message.xsl b/src/libsbgnpy/validation/schematron/iso_schematron_message.xsl
similarity index 100%
rename from libsbgnpy/validation/schematron/iso_schematron_message.xsl
rename to src/libsbgnpy/validation/schematron/iso_schematron_message.xsl
diff --git a/libsbgnpy/validation/schematron/iso_schematron_skeleton_for_xslt1.xsl b/src/libsbgnpy/validation/schematron/iso_schematron_skeleton_for_xslt1.xsl
similarity index 100%
rename from libsbgnpy/validation/schematron/iso_schematron_skeleton_for_xslt1.xsl
rename to src/libsbgnpy/validation/schematron/iso_schematron_skeleton_for_xslt1.xsl
diff --git a/libsbgnpy/validation/schematron/iso_svrl_for_xslt1.xsl b/src/libsbgnpy/validation/schematron/iso_svrl_for_xslt1.xsl
similarity index 100%
rename from libsbgnpy/validation/schematron/iso_svrl_for_xslt1.xsl
rename to src/libsbgnpy/validation/schematron/iso_svrl_for_xslt1.xsl
diff --git a/libsbgnpy/validation/schematron/readme.txt b/src/libsbgnpy/validation/schematron/readme.txt
similarity index 100%
rename from libsbgnpy/validation/schematron/readme.txt
rename to src/libsbgnpy/validation/schematron/readme.txt
diff --git a/libsbgnpy/validation/schematron/schematron-skeleton-api.htm b/src/libsbgnpy/validation/schematron/schematron-skeleton-api.htm
similarity index 100%
rename from libsbgnpy/validation/schematron/schematron-skeleton-api.htm
rename to src/libsbgnpy/validation/schematron/schematron-skeleton-api.htm
diff --git a/libsbgnpy/validation/validator.py b/src/libsbgnpy/validation/validator.py
similarity index 81%
rename from libsbgnpy/validation/validator.py
rename to src/libsbgnpy/validation/validator.py
index adba6cd..b14f0d0 100644
--- a/libsbgnpy/validation/validator.py
+++ b/src/libsbgnpy/validation/validator.py
@@ -6,22 +6,22 @@
 At this point only the XSD validation is implemented.
 see [#7](https://github.com/matthiaskoenig/libsbgn-python/issues/7)
 """
-import sys
 import os
-from lxml import isoschematron
-from lxml import etree
+import sys
 from enum import Enum
-import libsbgnpy.utils as utils
 
+from lxml import etree, isoschematron
+
+import libsbgnpy.utils as utils
 from libsbgnpy.libsbgnTypes import Language
 
 
 dir = os.path.dirname(os.path.realpath(__file__))
-XSD_SCHEMA = os.path.join(dir, '../schema/SBGN.xsd')
+XSD_SCHEMA = os.path.join(dir, "../schema/SBGN.xsd")
 
 
 def validate_xsd(f):
-    """ Validate SBGN file against XSD schema.
+    """Validate SBGN file against XSD schema.
 
     :param f: file to validate
     :return: Returns None if valid, the error log otherwise.
@@ -33,7 +33,7 @@ def validate_xsd(f):
     if not is_valid:
         log = xmlschema.error_log
         error = log.last_error
-        sys.stderr.write(str(log) + '\n')
+        sys.stderr.write(str(log) + "\n")
         return log
 
     return None
@@ -76,12 +76,13 @@ def get_rule_id(self):
         return self.rule_id
 
     def __str__(self):
-        return "{} at diagnosticId={}; ruleId={} Message: {}".format(self.severity,
-                                                                     self.diagnostic_id, self.rule_id, self.message)
+        return "{} at diagnosticId={}; ruleId={} Message: {}".format(
+            self.severity, self.diagnostic_id, self.rule_id, self.message
+        )
 
 
 def validate_schematron(f_sbgn):
-    """ Validate SBGN file with schematron.
+    """Validate SBGN file with schematron.
 
     In Java this does the XSL Transformations on the ruleset and the exported Pathway Object
     and then invokes the SAX parser through "parseSVRL" method on the transformation's result.
@@ -94,16 +95,16 @@ def validate_schematron(f_sbgn):
     # schema for language
     language = utils.get_language(f_sbgn)
     if language == Language.AF:
-        lang = 'af'
+        lang = "af"
     elif language == Language.PD:
-        lang = 'pd'
+        lang = "pd"
     elif language == language.ER:
-        lang = 'er'
-    f_schema = os.path.join(dir, 'rules/sbgn_{}.sch'.format(lang))
+        lang = "er"
+    f_schema = os.path.join(dir, "rules/sbgn_{}.sch".format(lang))
     print(f_schema)
 
     # Create an svrl file via subsequent xslt transformations
-    f_xsl = os.path.join(dir, 'schematron/iso_svrl_for_xslt1.xsl')
+    f_xsl = os.path.join(dir, "schematron/iso_svrl_for_xslt1.xsl")
 
     # prepare schematron rules via transformation
     doc_schema = etree.parse(f_schema)
@@ -111,17 +112,17 @@ def validate_schematron(f_sbgn):
     doc_xslt = etree.parse(f_xsl)
     transform_1 = etree.XSLT(doc_xslt)
     doc_sct = transform_1(doc_schema)
-    print('*' * 80)
+    print("*" * 80)
     print(etree.tostring(doc_sct, pretty_print=True))
-    print('*' * 80)
+    print("*" * 80)
 
     # validation via transformation
     doc_sbgn = etree.parse(f_sbgn)
     transform_2 = etree.XSLT(doc_sct)
     doc_svrlt = transform_2(doc_sbgn)
-    print('*' * 80)
+    print("*" * 80)
     print(etree.tostring(doc_svrlt, pretty_print=True))
-    print('*' * 80)
+    print("*" * 80)
 
     # from lxml.isoschematron import Schematron
     # schematron = Schematron(doc_schema)
@@ -134,7 +135,7 @@ def validate_schematron(f_sbgn):
     # f = "../examples/sbgn/glycolysis.sbgn"
 
     xsd_valid = validate_xsd(f) is None
-    print('XSD valid ({}): {}'.format(f, xsd_valid))
+    print("XSD valid ({}): {}".format(f, xsd_valid))
 
     sct_valid = validate_schematron(f)
-    print('Schematron valid ({}): {}'.format(f, xsd_valid))
+    print("Schematron valid ({}): {}".format(f, xsd_valid))
diff --git a/tox.ini b/tox.ini
index 10c05ac..397e28b 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,20 +1,100 @@
 [tox]
-envlist = pep8, py35, py36, py37, py38
+envlist = isort, black, flake8, safety, py3{6,7,8,9}
+
+[gh-actions]
+# We ignore flake8 for the time being because there are tons of things to fix.
+python =
+    3.6: py36
+    3.7: py37
+    3.8: isort, black, safety, py38
+    3.9: py39
 
 [testenv]
 deps=
-    -rrequirements.txt
     pytest
     pytest-cov
+    pytest-raises
+commands =
+    pytest --cov=libsbgnpy --cov-report=term --cov-report=xml
 
+[testenv:isort]
+skip_install = True
+deps=
+    isort >=5.5,<6
 commands=
-    pytest libsbgnpy
+    isort --check-only --diff {toxinidir}/src/libsbgnpy {toxinidir}/setup.py
 
-[testenv:pep8]
+[testenv:black]
 skip_install = True
-deps =
-    -rrequirements.txt
-    pep8
-commands =
-    # ignoring too long lines E501 in addition to defaults
-    pep8 --show-source libsbgnpy --ignore=E121,E123,E126,E226,E24,E704,E501
\ No newline at end of file
+deps=
+    black
+commands=
+    black --check --diff {toxinidir}/src/libsbgnpy {toxinidir}/setup.py --exclude resources
+
+[testenv:flake8]
+skip_install = True
+deps=
+    flake8
+    flake8-docstrings
+    flake8-bugbear
+commands=
+    flake8 {toxinidir}/src/libsbgnpy {toxinidir}/setup.py
+
+[testenv:safety]
+deps=
+    safety
+commands=
+    safety check --full-report
+
+################################################################################
+# Testing tools configuration                                                  #
+################################################################################
+
+[pytest]
+testpaths =
+    src/libsbgnpy/test
+markers =
+    raises
+
+[coverage:paths]
+source =
+    src/libsbgnpy
+    */site-packages/libsbgnpy
+
+[coverage:run]
+branch = true
+parallel = true
+omit =
+    */libsbgnpy/test/*
+
+[coverage:report]
+exclude_lines =
+# Have to re-enable the standard pragma
+    pragma: no cover
+precision = 2
+omit =
+    */libsbgnpy/test/*
+
+[isort]
+skip = __init__.py
+line_length = 88
+indent = 4
+multi_line_output = 3
+include_trailing_comma = true
+force_grid_wrap = 0
+use_parentheses = true
+lines_after_imports = 2
+known_first_party = libsbgnpy
+known_third_party =
+    requests
+    lxml
+
+[flake8]
+exclude =
+    __init__.py
+max-line-length = 88
+# The following conflict with `black` which is the more pedantic.
+ignore =
+    E203
+    W503
+    D202


Test patch:
diff --git a/libsbgnpy/examples/sbgn/test-output-01.sbgn b/src/libsbgnpy/examples/sbgn/test-output-01.sbgn
similarity index 100%
rename from libsbgnpy/examples/sbgn/test-output-01.sbgn
rename to src/libsbgnpy/examples/sbgn/test-output-01.sbgn
diff --git a/libsbgnpy/examples/sbgn/test-output-02.sbgn b/src/libsbgnpy/examples/sbgn/test-output-02.sbgn
similarity index 100%
rename from libsbgnpy/examples/sbgn/test-output-02.sbgn
rename to src/libsbgnpy/examples/sbgn/test-output-02.sbgn
diff --git a/libsbgnpy/examples/sbgn/test-output-03.sbgn b/src/libsbgnpy/examples/sbgn/test-output-03.sbgn
similarity index 100%
rename from libsbgnpy/examples/sbgn/test-output-03.sbgn
rename to src/libsbgnpy/examples/sbgn/test-output-03.sbgn
diff --git a/libsbgnpy/tests/__init__.py b/src/libsbgnpy/test/__init__.py
similarity index 100%
rename from libsbgnpy/tests/__init__.py
rename to src/libsbgnpy/test/__init__.py
diff --git a/libsbgnpy/tests/test-files/AF/AF_Reference_Card.png b/src/libsbgnpy/test/test-files/AF/AF_Reference_Card.png
similarity index 100%
rename from libsbgnpy/tests/test-files/AF/AF_Reference_Card.png
rename to src/libsbgnpy/test/test-files/AF/AF_Reference_Card.png
diff --git a/libsbgnpy/tests/test-files/AF/AF_Reference_Card.sbgn b/src/libsbgnpy/test/test-files/AF/AF_Reference_Card.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/AF/AF_Reference_Card.sbgn
rename to src/libsbgnpy/test/test-files/AF/AF_Reference_Card.sbgn
diff --git a/libsbgnpy/tests/test-files/AF/activity-nodes.gml b/src/libsbgnpy/test/test-files/AF/activity-nodes.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/AF/activity-nodes.gml
rename to src/libsbgnpy/test/test-files/AF/activity-nodes.gml
diff --git a/libsbgnpy/tests/test-files/AF/activity-nodes.png b/src/libsbgnpy/test/test-files/AF/activity-nodes.png
similarity index 100%
rename from libsbgnpy/tests/test-files/AF/activity-nodes.png
rename to src/libsbgnpy/test/test-files/AF/activity-nodes.png
diff --git a/libsbgnpy/tests/test-files/AF/activity-nodes.sbgn b/src/libsbgnpy/test/test-files/AF/activity-nodes.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/AF/activity-nodes.sbgn
rename to src/libsbgnpy/test/test-files/AF/activity-nodes.sbgn
diff --git a/libsbgnpy/tests/test-files/AF/auxiliary-units.gml b/src/libsbgnpy/test/test-files/AF/auxiliary-units.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/AF/auxiliary-units.gml
rename to src/libsbgnpy/test/test-files/AF/auxiliary-units.gml
diff --git a/libsbgnpy/tests/test-files/AF/auxiliary-units.png b/src/libsbgnpy/test/test-files/AF/auxiliary-units.png
similarity index 100%
rename from libsbgnpy/tests/test-files/AF/auxiliary-units.png
rename to src/libsbgnpy/test/test-files/AF/auxiliary-units.png
diff --git a/libsbgnpy/tests/test-files/AF/auxiliary-units.sbgn b/src/libsbgnpy/test/test-files/AF/auxiliary-units.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/AF/auxiliary-units.sbgn
rename to src/libsbgnpy/test/test-files/AF/auxiliary-units.sbgn
diff --git a/libsbgnpy/tests/test-files/AF/compartment.gml b/src/libsbgnpy/test/test-files/AF/compartment.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/AF/compartment.gml
rename to src/libsbgnpy/test/test-files/AF/compartment.gml
diff --git a/libsbgnpy/tests/test-files/AF/compartment.png b/src/libsbgnpy/test/test-files/AF/compartment.png
similarity index 100%
rename from libsbgnpy/tests/test-files/AF/compartment.png
rename to src/libsbgnpy/test/test-files/AF/compartment.png
diff --git a/libsbgnpy/tests/test-files/AF/compartment.sbgn b/src/libsbgnpy/test/test-files/AF/compartment.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/AF/compartment.sbgn
rename to src/libsbgnpy/test/test-files/AF/compartment.sbgn
diff --git a/libsbgnpy/tests/test-files/AF/delay.gml b/src/libsbgnpy/test/test-files/AF/delay.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/AF/delay.gml
rename to src/libsbgnpy/test/test-files/AF/delay.gml
diff --git a/libsbgnpy/tests/test-files/AF/delay.png b/src/libsbgnpy/test/test-files/AF/delay.png
similarity index 100%
rename from libsbgnpy/tests/test-files/AF/delay.png
rename to src/libsbgnpy/test/test-files/AF/delay.png
diff --git a/libsbgnpy/tests/test-files/AF/delay.sbgn b/src/libsbgnpy/test/test-files/AF/delay.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/AF/delay.sbgn
rename to src/libsbgnpy/test/test-files/AF/delay.sbgn
diff --git a/libsbgnpy/tests/test-files/AF/modulation.gml b/src/libsbgnpy/test/test-files/AF/modulation.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/AF/modulation.gml
rename to src/libsbgnpy/test/test-files/AF/modulation.gml
diff --git a/libsbgnpy/tests/test-files/AF/modulation.png b/src/libsbgnpy/test/test-files/AF/modulation.png
similarity index 100%
rename from libsbgnpy/tests/test-files/AF/modulation.png
rename to src/libsbgnpy/test/test-files/AF/modulation.png
diff --git a/libsbgnpy/tests/test-files/AF/modulation.sbgn b/src/libsbgnpy/test/test-files/AF/modulation.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/AF/modulation.sbgn
rename to src/libsbgnpy/test/test-files/AF/modulation.sbgn
diff --git a/libsbgnpy/tests/test-files/AF/submap.gml b/src/libsbgnpy/test/test-files/AF/submap.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/AF/submap.gml
rename to src/libsbgnpy/test/test-files/AF/submap.gml
diff --git a/libsbgnpy/tests/test-files/AF/submap.png b/src/libsbgnpy/test/test-files/AF/submap.png
similarity index 100%
rename from libsbgnpy/tests/test-files/AF/submap.png
rename to src/libsbgnpy/test/test-files/AF/submap.png
diff --git a/libsbgnpy/tests/test-files/AF/submap.sbgn b/src/libsbgnpy/test/test-files/AF/submap.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/AF/submap.sbgn
rename to src/libsbgnpy/test/test-files/AF/submap.sbgn
diff --git a/libsbgnpy/tests/test-files/AF/submap_expanded.gml b/src/libsbgnpy/test/test-files/AF/submap_expanded.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/AF/submap_expanded.gml
rename to src/libsbgnpy/test/test-files/AF/submap_expanded.gml
diff --git a/libsbgnpy/tests/test-files/AF/submap_expanded.png b/src/libsbgnpy/test/test-files/AF/submap_expanded.png
similarity index 100%
rename from libsbgnpy/tests/test-files/AF/submap_expanded.png
rename to src/libsbgnpy/test/test-files/AF/submap_expanded.png
diff --git a/libsbgnpy/tests/test-files/AF/submap_expanded.sbgn b/src/libsbgnpy/test/test-files/AF/submap_expanded.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/AF/submap_expanded.sbgn
rename to src/libsbgnpy/test/test-files/AF/submap_expanded.sbgn
diff --git a/libsbgnpy/tests/test-files/AF/submaps_all-in-one.sbgn b/src/libsbgnpy/test/test-files/AF/submaps_all-in-one.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/AF/submaps_all-in-one.sbgn
rename to src/libsbgnpy/test/test-files/AF/submaps_all-in-one.sbgn
diff --git a/libsbgnpy/tests/test-files/AF/two_edges_between_two_activities.gml b/src/libsbgnpy/test/test-files/AF/two_edges_between_two_activities.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/AF/two_edges_between_two_activities.gml
rename to src/libsbgnpy/test/test-files/AF/two_edges_between_two_activities.gml
diff --git a/libsbgnpy/tests/test-files/AF/two_edges_between_two_activities.png b/src/libsbgnpy/test/test-files/AF/two_edges_between_two_activities.png
similarity index 100%
rename from libsbgnpy/tests/test-files/AF/two_edges_between_two_activities.png
rename to src/libsbgnpy/test/test-files/AF/two_edges_between_two_activities.png
diff --git a/libsbgnpy/tests/test-files/AF/two_edges_between_two_activities.sbgn b/src/libsbgnpy/test/test-files/AF/two_edges_between_two_activities.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/AF/two_edges_between_two_activities.sbgn
rename to src/libsbgnpy/test/test-files/AF/two_edges_between_two_activities.sbgn
diff --git a/libsbgnpy/tests/test-files/ER/ER_Reference_Card.png b/src/libsbgnpy/test/test-files/ER/ER_Reference_Card.png
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/ER_Reference_Card.png
rename to src/libsbgnpy/test/test-files/ER/ER_Reference_Card.png
diff --git a/libsbgnpy/tests/test-files/ER/ER_Reference_Card.sbgn b/src/libsbgnpy/test/test-files/ER/ER_Reference_Card.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/ER_Reference_Card.sbgn
rename to src/libsbgnpy/test/test-files/ER/ER_Reference_Card.sbgn
diff --git a/libsbgnpy/tests/test-files/ER/OR gate.gml b/src/libsbgnpy/test/test-files/ER/OR gate.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/OR gate.gml
rename to src/libsbgnpy/test/test-files/ER/OR gate.gml
diff --git a/libsbgnpy/tests/test-files/ER/OR gate.png b/src/libsbgnpy/test/test-files/ER/OR gate.png
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/OR gate.png
rename to src/libsbgnpy/test/test-files/ER/OR gate.png
diff --git a/libsbgnpy/tests/test-files/ER/OR gate.sbgn b/src/libsbgnpy/test/test-files/ER/OR gate.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/OR gate.sbgn
rename to src/libsbgnpy/test/test-files/ER/OR gate.sbgn
diff --git a/libsbgnpy/tests/test-files/ER/absolute inhibition.gml b/src/libsbgnpy/test/test-files/ER/absolute inhibition.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/absolute inhibition.gml
rename to src/libsbgnpy/test/test-files/ER/absolute inhibition.gml
diff --git a/libsbgnpy/tests/test-files/ER/absolute inhibition.png b/src/libsbgnpy/test/test-files/ER/absolute inhibition.png
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/absolute inhibition.png
rename to src/libsbgnpy/test/test-files/ER/absolute inhibition.png
diff --git a/libsbgnpy/tests/test-files/ER/absolute inhibition.sbgn b/src/libsbgnpy/test/test-files/ER/absolute inhibition.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/absolute inhibition.sbgn
rename to src/libsbgnpy/test/test-files/ER/absolute inhibition.sbgn
diff --git a/libsbgnpy/tests/test-files/ER/absolute stimulation.png b/src/libsbgnpy/test/test-files/ER/absolute stimulation.png
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/absolute stimulation.png
rename to src/libsbgnpy/test/test-files/ER/absolute stimulation.png
diff --git a/libsbgnpy/tests/test-files/ER/absolute stimulation.sbgn b/src/libsbgnpy/test/test-files/ER/absolute stimulation.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/absolute stimulation.sbgn
rename to src/libsbgnpy/test/test-files/ER/absolute stimulation.sbgn
diff --git a/libsbgnpy/tests/test-files/ER/binary-no-outcome.gml b/src/libsbgnpy/test/test-files/ER/binary-no-outcome.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/binary-no-outcome.gml
rename to src/libsbgnpy/test/test-files/ER/binary-no-outcome.gml
diff --git a/libsbgnpy/tests/test-files/ER/binary-no-outcome.png b/src/libsbgnpy/test/test-files/ER/binary-no-outcome.png
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/binary-no-outcome.png
rename to src/libsbgnpy/test/test-files/ER/binary-no-outcome.png
diff --git a/libsbgnpy/tests/test-files/ER/binary-no-outcome.sbgn b/src/libsbgnpy/test/test-files/ER/binary-no-outcome.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/binary-no-outcome.sbgn
rename to src/libsbgnpy/test/test-files/ER/binary-no-outcome.sbgn
diff --git a/libsbgnpy/tests/test-files/ER/binary-with-perturbation-and-phenotype.gml b/src/libsbgnpy/test/test-files/ER/binary-with-perturbation-and-phenotype.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/binary-with-perturbation-and-phenotype.gml
rename to src/libsbgnpy/test/test-files/ER/binary-with-perturbation-and-phenotype.gml
diff --git a/libsbgnpy/tests/test-files/ER/binary-with-perturbation-and-phenotype.png b/src/libsbgnpy/test/test-files/ER/binary-with-perturbation-and-phenotype.png
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/binary-with-perturbation-and-phenotype.png
rename to src/libsbgnpy/test/test-files/ER/binary-with-perturbation-and-phenotype.png
diff --git a/libsbgnpy/tests/test-files/ER/binary-with-perturbation-and-phenotype.sbgn b/src/libsbgnpy/test/test-files/ER/binary-with-perturbation-and-phenotype.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/binary-with-perturbation-and-phenotype.sbgn
rename to src/libsbgnpy/test/test-files/ER/binary-with-perturbation-and-phenotype.sbgn
diff --git a/libsbgnpy/tests/test-files/ER/cis.gml b/src/libsbgnpy/test/test-files/ER/cis.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/cis.gml
rename to src/libsbgnpy/test/test-files/ER/cis.gml
diff --git a/libsbgnpy/tests/test-files/ER/cis.png b/src/libsbgnpy/test/test-files/ER/cis.png
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/cis.png
rename to src/libsbgnpy/test/test-files/ER/cis.png
diff --git a/libsbgnpy/tests/test-files/ER/cis.sbgn b/src/libsbgnpy/test/test-files/ER/cis.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/cis.sbgn
rename to src/libsbgnpy/test/test-files/ER/cis.sbgn
diff --git a/libsbgnpy/tests/test-files/ER/delay.gml b/src/libsbgnpy/test/test-files/ER/delay.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/delay.gml
rename to src/libsbgnpy/test/test-files/ER/delay.gml
diff --git a/libsbgnpy/tests/test-files/ER/delay.png b/src/libsbgnpy/test/test-files/ER/delay.png
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/delay.png
rename to src/libsbgnpy/test/test-files/ER/delay.png
diff --git a/libsbgnpy/tests/test-files/ER/delay.sbgn b/src/libsbgnpy/test/test-files/ER/delay.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/delay.sbgn
rename to src/libsbgnpy/test/test-files/ER/delay.sbgn
diff --git a/libsbgnpy/tests/test-files/ER/existence_variable.gml b/src/libsbgnpy/test/test-files/ER/existence_variable.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/existence_variable.gml
rename to src/libsbgnpy/test/test-files/ER/existence_variable.gml
diff --git a/libsbgnpy/tests/test-files/ER/existence_variable.png b/src/libsbgnpy/test/test-files/ER/existence_variable.png
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/existence_variable.png
rename to src/libsbgnpy/test/test-files/ER/existence_variable.png
diff --git a/libsbgnpy/tests/test-files/ER/existence_variable.sbgn b/src/libsbgnpy/test/test-files/ER/existence_variable.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/existence_variable.sbgn
rename to src/libsbgnpy/test/test-files/ER/existence_variable.sbgn
diff --git a/libsbgnpy/tests/test-files/ER/implicit_xor.gml b/src/libsbgnpy/test/test-files/ER/implicit_xor.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/implicit_xor.gml
rename to src/libsbgnpy/test/test-files/ER/implicit_xor.gml
diff --git a/libsbgnpy/tests/test-files/ER/implicit_xor.png b/src/libsbgnpy/test/test-files/ER/implicit_xor.png
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/implicit_xor.png
rename to src/libsbgnpy/test/test-files/ER/implicit_xor.png
diff --git a/libsbgnpy/tests/test-files/ER/implicit_xor.sbgn b/src/libsbgnpy/test/test-files/ER/implicit_xor.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/implicit_xor.sbgn
rename to src/libsbgnpy/test/test-files/ER/implicit_xor.sbgn
diff --git a/libsbgnpy/tests/test-files/ER/invisible node.gml b/src/libsbgnpy/test/test-files/ER/invisible node.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/invisible node.gml
rename to src/libsbgnpy/test/test-files/ER/invisible node.gml
diff --git a/libsbgnpy/tests/test-files/ER/invisible node.png b/src/libsbgnpy/test/test-files/ER/invisible node.png
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/invisible node.png
rename to src/libsbgnpy/test/test-files/ER/invisible node.png
diff --git a/libsbgnpy/tests/test-files/ER/invisible node.sbgn b/src/libsbgnpy/test/test-files/ER/invisible node.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/invisible node.sbgn
rename to src/libsbgnpy/test/test-files/ER/invisible node.sbgn
diff --git a/libsbgnpy/tests/test-files/ER/location.gml b/src/libsbgnpy/test/test-files/ER/location.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/location.gml
rename to src/libsbgnpy/test/test-files/ER/location.gml
diff --git a/libsbgnpy/tests/test-files/ER/location.png b/src/libsbgnpy/test/test-files/ER/location.png
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/location.png
rename to src/libsbgnpy/test/test-files/ER/location.png
diff --git a/libsbgnpy/tests/test-files/ER/location.sbgn b/src/libsbgnpy/test/test-files/ER/location.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/location.sbgn
rename to src/libsbgnpy/test/test-files/ER/location.sbgn
diff --git a/libsbgnpy/tests/test-files/ER/outcome-dual.gml b/src/libsbgnpy/test/test-files/ER/outcome-dual.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/outcome-dual.gml
rename to src/libsbgnpy/test/test-files/ER/outcome-dual.gml
diff --git a/libsbgnpy/tests/test-files/ER/outcome-dual.png b/src/libsbgnpy/test/test-files/ER/outcome-dual.png
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/outcome-dual.png
rename to src/libsbgnpy/test/test-files/ER/outcome-dual.png
diff --git a/libsbgnpy/tests/test-files/ER/outcome-dual.sbgn b/src/libsbgnpy/test/test-files/ER/outcome-dual.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/outcome-dual.sbgn
rename to src/libsbgnpy/test/test-files/ER/outcome-dual.sbgn
diff --git a/libsbgnpy/tests/test-files/ER/outcome-simplified.gml b/src/libsbgnpy/test/test-files/ER/outcome-simplified.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/outcome-simplified.gml
rename to src/libsbgnpy/test/test-files/ER/outcome-simplified.gml
diff --git a/libsbgnpy/tests/test-files/ER/outcome-simplified.png b/src/libsbgnpy/test/test-files/ER/outcome-simplified.png
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/outcome-simplified.png
rename to src/libsbgnpy/test/test-files/ER/outcome-simplified.png
diff --git a/libsbgnpy/tests/test-files/ER/outcome-simplified.sbgn b/src/libsbgnpy/test/test-files/ER/outcome-simplified.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/outcome-simplified.sbgn
rename to src/libsbgnpy/test/test-files/ER/outcome-simplified.sbgn
diff --git a/libsbgnpy/tests/test-files/ER/phosphorylation.gml b/src/libsbgnpy/test/test-files/ER/phosphorylation.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/phosphorylation.gml
rename to src/libsbgnpy/test/test-files/ER/phosphorylation.gml
diff --git a/libsbgnpy/tests/test-files/ER/phosphorylation.png b/src/libsbgnpy/test/test-files/ER/phosphorylation.png
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/phosphorylation.png
rename to src/libsbgnpy/test/test-files/ER/phosphorylation.png
diff --git a/libsbgnpy/tests/test-files/ER/phosphorylation.sbgn b/src/libsbgnpy/test/test-files/ER/phosphorylation.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/phosphorylation.sbgn
rename to src/libsbgnpy/test/test-files/ER/phosphorylation.sbgn
diff --git a/libsbgnpy/tests/test-files/ER/ternary-interaction.gml b/src/libsbgnpy/test/test-files/ER/ternary-interaction.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/ternary-interaction.gml
rename to src/libsbgnpy/test/test-files/ER/ternary-interaction.gml
diff --git a/libsbgnpy/tests/test-files/ER/ternary-interaction.png b/src/libsbgnpy/test/test-files/ER/ternary-interaction.png
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/ternary-interaction.png
rename to src/libsbgnpy/test/test-files/ER/ternary-interaction.png
diff --git a/libsbgnpy/tests/test-files/ER/ternary-interaction.sbgn b/src/libsbgnpy/test/test-files/ER/ternary-interaction.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/ternary-interaction.sbgn
rename to src/libsbgnpy/test/test-files/ER/ternary-interaction.sbgn
diff --git a/libsbgnpy/tests/test-files/ER/ternary-with-cardinality.gml b/src/libsbgnpy/test/test-files/ER/ternary-with-cardinality.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/ternary-with-cardinality.gml
rename to src/libsbgnpy/test/test-files/ER/ternary-with-cardinality.gml
diff --git a/libsbgnpy/tests/test-files/ER/ternary-with-cardinality.png b/src/libsbgnpy/test/test-files/ER/ternary-with-cardinality.png
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/ternary-with-cardinality.png
rename to src/libsbgnpy/test/test-files/ER/ternary-with-cardinality.png
diff --git a/libsbgnpy/tests/test-files/ER/ternary-with-cardinality.sbgn b/src/libsbgnpy/test/test-files/ER/ternary-with-cardinality.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/ternary-with-cardinality.sbgn
rename to src/libsbgnpy/test/test-files/ER/ternary-with-cardinality.sbgn
diff --git a/libsbgnpy/tests/test-files/ER/ternary-with-perturbation-and-phenotype.gml b/src/libsbgnpy/test/test-files/ER/ternary-with-perturbation-and-phenotype.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/ternary-with-perturbation-and-phenotype.gml
rename to src/libsbgnpy/test/test-files/ER/ternary-with-perturbation-and-phenotype.gml
diff --git a/libsbgnpy/tests/test-files/ER/ternary-with-perturbation-and-phenotype.png b/src/libsbgnpy/test/test-files/ER/ternary-with-perturbation-and-phenotype.png
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/ternary-with-perturbation-and-phenotype.png
rename to src/libsbgnpy/test/test-files/ER/ternary-with-perturbation-and-phenotype.png
diff --git a/libsbgnpy/tests/test-files/ER/ternary-with-perturbation-and-phenotype.sbgn b/src/libsbgnpy/test/test-files/ER/ternary-with-perturbation-and-phenotype.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/ternary-with-perturbation-and-phenotype.sbgn
rename to src/libsbgnpy/test/test-files/ER/ternary-with-perturbation-and-phenotype.sbgn
diff --git a/libsbgnpy/tests/test-files/ER/trans.gml b/src/libsbgnpy/test/test-files/ER/trans.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/trans.gml
rename to src/libsbgnpy/test/test-files/ER/trans.gml
diff --git a/libsbgnpy/tests/test-files/ER/trans.png b/src/libsbgnpy/test/test-files/ER/trans.png
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/trans.png
rename to src/libsbgnpy/test/test-files/ER/trans.png
diff --git a/libsbgnpy/tests/test-files/ER/trans.sbgn b/src/libsbgnpy/test/test-files/ER/trans.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/ER/trans.sbgn
rename to src/libsbgnpy/test/test-files/ER/trans.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/PD_Reference_Card.png b/src/libsbgnpy/test/test-files/PD/PD_Reference_Card.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/PD_Reference_Card.png
rename to src/libsbgnpy/test/test-files/PD/PD_Reference_Card.png
diff --git a/libsbgnpy/tests/test-files/PD/PD_Reference_Card.sbgn b/src/libsbgnpy/test/test-files/PD/PD_Reference_Card.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/PD_Reference_Card.sbgn
rename to src/libsbgnpy/test/test-files/PD/PD_Reference_Card.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/activated_stat1alpha_induction_of_the_irf1_gene.png b/src/libsbgnpy/test/test-files/PD/activated_stat1alpha_induction_of_the_irf1_gene.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/activated_stat1alpha_induction_of_the_irf1_gene.png
rename to src/libsbgnpy/test/test-files/PD/activated_stat1alpha_induction_of_the_irf1_gene.png
diff --git a/libsbgnpy/tests/test-files/PD/activated_stat1alpha_induction_of_the_irf1_gene.sbgn b/src/libsbgnpy/test/test-files/PD/activated_stat1alpha_induction_of_the_irf1_gene.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/activated_stat1alpha_induction_of_the_irf1_gene.sbgn
rename to src/libsbgnpy/test/test-files/PD/activated_stat1alpha_induction_of_the_irf1_gene.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/adh.gml b/src/libsbgnpy/test/test-files/PD/adh.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/adh.gml
rename to src/libsbgnpy/test/test-files/PD/adh.gml
diff --git a/libsbgnpy/tests/test-files/PD/adh.png b/src/libsbgnpy/test/test-files/PD/adh.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/adh.png
rename to src/libsbgnpy/test/test-files/PD/adh.png
diff --git a/libsbgnpy/tests/test-files/PD/adh.sbgn b/src/libsbgnpy/test/test-files/PD/adh.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/adh.sbgn
rename to src/libsbgnpy/test/test-files/PD/adh.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/and.gml b/src/libsbgnpy/test/test-files/PD/and.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/and.gml
rename to src/libsbgnpy/test/test-files/PD/and.gml
diff --git a/libsbgnpy/tests/test-files/PD/and.png b/src/libsbgnpy/test/test-files/PD/and.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/and.png
rename to src/libsbgnpy/test/test-files/PD/and.png
diff --git a/libsbgnpy/tests/test-files/PD/and.sbgn b/src/libsbgnpy/test/test-files/PD/and.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/and.sbgn
rename to src/libsbgnpy/test/test-files/PD/and.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/annotation.png b/src/libsbgnpy/test/test-files/PD/annotation.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/annotation.png
rename to src/libsbgnpy/test/test-files/PD/annotation.png
diff --git a/libsbgnpy/tests/test-files/PD/annotation.sbgn b/src/libsbgnpy/test/test-files/PD/annotation.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/annotation.sbgn
rename to src/libsbgnpy/test/test-files/PD/annotation.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/bool-expr-pd.png b/src/libsbgnpy/test/test-files/PD/bool-expr-pd.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/bool-expr-pd.png
rename to src/libsbgnpy/test/test-files/PD/bool-expr-pd.png
diff --git a/libsbgnpy/tests/test-files/PD/bool-expr-pd.sbgn b/src/libsbgnpy/test/test-files/PD/bool-expr-pd.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/bool-expr-pd.sbgn
rename to src/libsbgnpy/test/test-files/PD/bool-expr-pd.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/clone-marker.gml b/src/libsbgnpy/test/test-files/PD/clone-marker.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/clone-marker.gml
rename to src/libsbgnpy/test/test-files/PD/clone-marker.gml
diff --git a/libsbgnpy/tests/test-files/PD/clone-marker.png b/src/libsbgnpy/test/test-files/PD/clone-marker.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/clone-marker.png
rename to src/libsbgnpy/test/test-files/PD/clone-marker.png
diff --git a/libsbgnpy/tests/test-files/PD/clone-marker.sbgn b/src/libsbgnpy/test/test-files/PD/clone-marker.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/clone-marker.sbgn
rename to src/libsbgnpy/test/test-files/PD/clone-marker.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/compartmentOrder1.png b/src/libsbgnpy/test/test-files/PD/compartmentOrder1.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/compartmentOrder1.png
rename to src/libsbgnpy/test/test-files/PD/compartmentOrder1.png
diff --git a/libsbgnpy/tests/test-files/PD/compartmentOrder1.sbgn b/src/libsbgnpy/test/test-files/PD/compartmentOrder1.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/compartmentOrder1.sbgn
rename to src/libsbgnpy/test/test-files/PD/compartmentOrder1.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/compartmentOrder2.png b/src/libsbgnpy/test/test-files/PD/compartmentOrder2.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/compartmentOrder2.png
rename to src/libsbgnpy/test/test-files/PD/compartmentOrder2.png
diff --git a/libsbgnpy/tests/test-files/PD/compartmentOrder2.sbgn b/src/libsbgnpy/test/test-files/PD/compartmentOrder2.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/compartmentOrder2.sbgn
rename to src/libsbgnpy/test/test-files/PD/compartmentOrder2.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/compartments.gml b/src/libsbgnpy/test/test-files/PD/compartments.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/compartments.gml
rename to src/libsbgnpy/test/test-files/PD/compartments.gml
diff --git a/libsbgnpy/tests/test-files/PD/compartments.png b/src/libsbgnpy/test/test-files/PD/compartments.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/compartments.png
rename to src/libsbgnpy/test/test-files/PD/compartments.png
diff --git a/libsbgnpy/tests/test-files/PD/compartments.sbgn b/src/libsbgnpy/test/test-files/PD/compartments.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/compartments.sbgn
rename to src/libsbgnpy/test/test-files/PD/compartments.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/edgerouting.gml b/src/libsbgnpy/test/test-files/PD/edgerouting.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/edgerouting.gml
rename to src/libsbgnpy/test/test-files/PD/edgerouting.gml
diff --git a/libsbgnpy/tests/test-files/PD/edgerouting.png b/src/libsbgnpy/test/test-files/PD/edgerouting.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/edgerouting.png
rename to src/libsbgnpy/test/test-files/PD/edgerouting.png
diff --git a/libsbgnpy/tests/test-files/PD/edgerouting.sbgn b/src/libsbgnpy/test/test-files/PD/edgerouting.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/edgerouting.sbgn
rename to src/libsbgnpy/test/test-files/PD/edgerouting.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/glycolysis.png b/src/libsbgnpy/test/test-files/PD/glycolysis.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/glycolysis.png
rename to src/libsbgnpy/test/test-files/PD/glycolysis.png
diff --git a/libsbgnpy/tests/test-files/PD/glycolysis.sbgn b/src/libsbgnpy/test/test-files/PD/glycolysis.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/glycolysis.sbgn
rename to src/libsbgnpy/test/test-files/PD/glycolysis.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/insulin-like_growth_factor_signaling.png b/src/libsbgnpy/test/test-files/PD/insulin-like_growth_factor_signaling.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/insulin-like_growth_factor_signaling.png
rename to src/libsbgnpy/test/test-files/PD/insulin-like_growth_factor_signaling.png
diff --git a/libsbgnpy/tests/test-files/PD/insulin-like_growth_factor_signaling.sbgn b/src/libsbgnpy/test/test-files/PD/insulin-like_growth_factor_signaling.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/insulin-like_growth_factor_signaling.sbgn
rename to src/libsbgnpy/test/test-files/PD/insulin-like_growth_factor_signaling.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/labeledCloneMarker.png b/src/libsbgnpy/test/test-files/PD/labeledCloneMarker.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/labeledCloneMarker.png
rename to src/libsbgnpy/test/test-files/PD/labeledCloneMarker.png
diff --git a/libsbgnpy/tests/test-files/PD/labeledCloneMarker.sbgn b/src/libsbgnpy/test/test-files/PD/labeledCloneMarker.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/labeledCloneMarker.sbgn
rename to src/libsbgnpy/test/test-files/PD/labeledCloneMarker.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/mapk_cascade.png b/src/libsbgnpy/test/test-files/PD/mapk_cascade.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/mapk_cascade.png
rename to src/libsbgnpy/test/test-files/PD/mapk_cascade.png
diff --git a/libsbgnpy/tests/test-files/PD/mapk_cascade.sbgn b/src/libsbgnpy/test/test-files/PD/mapk_cascade.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/mapk_cascade.sbgn
rename to src/libsbgnpy/test/test-files/PD/mapk_cascade.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/mixed_arcs.png b/src/libsbgnpy/test/test-files/PD/mixed_arcs.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/mixed_arcs.png
rename to src/libsbgnpy/test/test-files/PD/mixed_arcs.png
diff --git a/libsbgnpy/tests/test-files/PD/multimer.gml b/src/libsbgnpy/test/test-files/PD/multimer.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/multimer.gml
rename to src/libsbgnpy/test/test-files/PD/multimer.gml
diff --git a/libsbgnpy/tests/test-files/PD/multimer.png b/src/libsbgnpy/test/test-files/PD/multimer.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/multimer.png
rename to src/libsbgnpy/test/test-files/PD/multimer.png
diff --git a/libsbgnpy/tests/test-files/PD/multimer.sbgn b/src/libsbgnpy/test/test-files/PD/multimer.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/multimer.sbgn
rename to src/libsbgnpy/test/test-files/PD/multimer.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/multimer2.gml b/src/libsbgnpy/test/test-files/PD/multimer2.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/multimer2.gml
rename to src/libsbgnpy/test/test-files/PD/multimer2.gml
diff --git a/libsbgnpy/tests/test-files/PD/multimer2.png b/src/libsbgnpy/test/test-files/PD/multimer2.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/multimer2.png
rename to src/libsbgnpy/test/test-files/PD/multimer2.png
diff --git a/libsbgnpy/tests/test-files/PD/multimer2.sbgn b/src/libsbgnpy/test/test-files/PD/multimer2.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/multimer2.sbgn
rename to src/libsbgnpy/test/test-files/PD/multimer2.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/neuronal_muscle_signalling.png b/src/libsbgnpy/test/test-files/PD/neuronal_muscle_signalling.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/neuronal_muscle_signalling.png
rename to src/libsbgnpy/test/test-files/PD/neuronal_muscle_signalling.png
diff --git a/libsbgnpy/tests/test-files/PD/neuronal_muscle_signalling.sbgn b/src/libsbgnpy/test/test-files/PD/neuronal_muscle_signalling.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/neuronal_muscle_signalling.sbgn
rename to src/libsbgnpy/test/test-files/PD/neuronal_muscle_signalling.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/neuronal_muscle_signalling_color.png b/src/libsbgnpy/test/test-files/PD/neuronal_muscle_signalling_color.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/neuronal_muscle_signalling_color.png
rename to src/libsbgnpy/test/test-files/PD/neuronal_muscle_signalling_color.png
diff --git a/libsbgnpy/tests/test-files/PD/neuronal_muscle_signalling_color.sbgn b/src/libsbgnpy/test/test-files/PD/neuronal_muscle_signalling_color.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/neuronal_muscle_signalling_color.sbgn
rename to src/libsbgnpy/test/test-files/PD/neuronal_muscle_signalling_color.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/or-simple.gml b/src/libsbgnpy/test/test-files/PD/or-simple.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/or-simple.gml
rename to src/libsbgnpy/test/test-files/PD/or-simple.gml
diff --git a/libsbgnpy/tests/test-files/PD/or-simple.png b/src/libsbgnpy/test/test-files/PD/or-simple.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/or-simple.png
rename to src/libsbgnpy/test/test-files/PD/or-simple.png
diff --git a/libsbgnpy/tests/test-files/PD/or-simple.sbgn b/src/libsbgnpy/test/test-files/PD/or-simple.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/or-simple.sbgn
rename to src/libsbgnpy/test/test-files/PD/or-simple.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/protein_degradation.gml b/src/libsbgnpy/test/test-files/PD/protein_degradation.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/protein_degradation.gml
rename to src/libsbgnpy/test/test-files/PD/protein_degradation.gml
diff --git a/libsbgnpy/tests/test-files/PD/protein_degradation.png b/src/libsbgnpy/test/test-files/PD/protein_degradation.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/protein_degradation.png
rename to src/libsbgnpy/test/test-files/PD/protein_degradation.png
diff --git a/libsbgnpy/tests/test-files/PD/protein_degradation.sbgn b/src/libsbgnpy/test/test-files/PD/protein_degradation.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/protein_degradation.sbgn
rename to src/libsbgnpy/test/test-files/PD/protein_degradation.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/reversible-verticalpn.gml b/src/libsbgnpy/test/test-files/PD/reversible-verticalpn.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/reversible-verticalpn.gml
rename to src/libsbgnpy/test/test-files/PD/reversible-verticalpn.gml
diff --git a/libsbgnpy/tests/test-files/PD/reversible-verticalpn.png b/src/libsbgnpy/test/test-files/PD/reversible-verticalpn.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/reversible-verticalpn.png
rename to src/libsbgnpy/test/test-files/PD/reversible-verticalpn.png
diff --git a/libsbgnpy/tests/test-files/PD/reversible-verticalpn.sbgn b/src/libsbgnpy/test/test-files/PD/reversible-verticalpn.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/reversible-verticalpn.sbgn
rename to src/libsbgnpy/test/test-files/PD/reversible-verticalpn.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/states.gml b/src/libsbgnpy/test/test-files/PD/states.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/states.gml
rename to src/libsbgnpy/test/test-files/PD/states.gml
diff --git a/libsbgnpy/tests/test-files/PD/states.png b/src/libsbgnpy/test/test-files/PD/states.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/states.png
rename to src/libsbgnpy/test/test-files/PD/states.png
diff --git a/libsbgnpy/tests/test-files/PD/states.sbgn b/src/libsbgnpy/test/test-files/PD/states.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/states.sbgn
rename to src/libsbgnpy/test/test-files/PD/states.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/statesType2.png b/src/libsbgnpy/test/test-files/PD/statesType2.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/statesType2.png
rename to src/libsbgnpy/test/test-files/PD/statesType2.png
diff --git a/libsbgnpy/tests/test-files/PD/statesType2.sbgn b/src/libsbgnpy/test/test-files/PD/statesType2.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/statesType2.sbgn
rename to src/libsbgnpy/test/test-files/PD/statesType2.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/statesType3.png b/src/libsbgnpy/test/test-files/PD/statesType3.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/statesType3.png
rename to src/libsbgnpy/test/test-files/PD/statesType3.png
diff --git a/libsbgnpy/tests/test-files/PD/stoichiometry.gml b/src/libsbgnpy/test/test-files/PD/stoichiometry.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/stoichiometry.gml
rename to src/libsbgnpy/test/test-files/PD/stoichiometry.gml
diff --git a/libsbgnpy/tests/test-files/PD/stoichiometry.png b/src/libsbgnpy/test/test-files/PD/stoichiometry.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/stoichiometry.png
rename to src/libsbgnpy/test/test-files/PD/stoichiometry.png
diff --git a/libsbgnpy/tests/test-files/PD/stoichiometry.sbgn b/src/libsbgnpy/test/test-files/PD/stoichiometry.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/stoichiometry.sbgn
rename to src/libsbgnpy/test/test-files/PD/stoichiometry.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/submap.gml b/src/libsbgnpy/test/test-files/PD/submap.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/submap.gml
rename to src/libsbgnpy/test/test-files/PD/submap.gml
diff --git a/libsbgnpy/tests/test-files/PD/submap.png b/src/libsbgnpy/test/test-files/PD/submap.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/submap.png
rename to src/libsbgnpy/test/test-files/PD/submap.png
diff --git a/libsbgnpy/tests/test-files/PD/submap.sbgn b/src/libsbgnpy/test/test-files/PD/submap.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/submap.sbgn
rename to src/libsbgnpy/test/test-files/PD/submap.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/submap_expanded.gml b/src/libsbgnpy/test/test-files/PD/submap_expanded.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/submap_expanded.gml
rename to src/libsbgnpy/test/test-files/PD/submap_expanded.gml
diff --git a/libsbgnpy/tests/test-files/PD/submap_expanded.png b/src/libsbgnpy/test/test-files/PD/submap_expanded.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/submap_expanded.png
rename to src/libsbgnpy/test/test-files/PD/submap_expanded.png
diff --git a/libsbgnpy/tests/test-files/PD/submap_expanded.sbgn b/src/libsbgnpy/test/test-files/PD/submap_expanded.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/submap_expanded.sbgn
rename to src/libsbgnpy/test/test-files/PD/submap_expanded.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/submaps_MAPKcascade.sbgn b/src/libsbgnpy/test/test-files/PD/submaps_MAPKcascade.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/submaps_MAPKcascade.sbgn
rename to src/libsbgnpy/test/test-files/PD/submaps_MAPKcascade.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/utf8_test_case_with_byte_order_mark.gml b/src/libsbgnpy/test/test-files/PD/utf8_test_case_with_byte_order_mark.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/utf8_test_case_with_byte_order_mark.gml
rename to src/libsbgnpy/test/test-files/PD/utf8_test_case_with_byte_order_mark.gml
diff --git a/libsbgnpy/tests/test-files/PD/utf8_test_case_with_byte_order_mark.png b/src/libsbgnpy/test/test-files/PD/utf8_test_case_with_byte_order_mark.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/utf8_test_case_with_byte_order_mark.png
rename to src/libsbgnpy/test/test-files/PD/utf8_test_case_with_byte_order_mark.png
diff --git a/libsbgnpy/tests/test-files/PD/utf8_test_case_with_byte_order_mark.sbgn b/src/libsbgnpy/test/test-files/PD/utf8_test_case_with_byte_order_mark.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/utf8_test_case_with_byte_order_mark.sbgn
rename to src/libsbgnpy/test/test-files/PD/utf8_test_case_with_byte_order_mark.sbgn
diff --git a/libsbgnpy/tests/test-files/PD/utf8_test_case_without_byte_order_mark.gml b/src/libsbgnpy/test/test-files/PD/utf8_test_case_without_byte_order_mark.gml
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/utf8_test_case_without_byte_order_mark.gml
rename to src/libsbgnpy/test/test-files/PD/utf8_test_case_without_byte_order_mark.gml
diff --git a/libsbgnpy/tests/test-files/PD/utf8_test_case_without_byte_order_mark.png b/src/libsbgnpy/test/test-files/PD/utf8_test_case_without_byte_order_mark.png
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/utf8_test_case_without_byte_order_mark.png
rename to src/libsbgnpy/test/test-files/PD/utf8_test_case_without_byte_order_mark.png
diff --git a/libsbgnpy/tests/test-files/PD/utf8_test_case_without_byte_order_mark.sbgn b/src/libsbgnpy/test/test-files/PD/utf8_test_case_without_byte_order_mark.sbgn
similarity index 100%
rename from libsbgnpy/tests/test-files/PD/utf8_test_case_without_byte_order_mark.sbgn
rename to src/libsbgnpy/test/test-files/PD/utf8_test_case_without_byte_order_mark.sbgn
diff --git a/libsbgnpy/tests/test_examples.py b/src/libsbgnpy/test/test_examples.py
similarity index 70%
rename from libsbgnpy/tests/test_examples.py
rename to src/libsbgnpy/test/test_examples.py
index cc4d461..7839c6e 100644
--- a/libsbgnpy/tests/test_examples.py
+++ b/src/libsbgnpy/test/test_examples.py
@@ -4,9 +4,11 @@
 Test the example scripts in the examples folder.
 """
 import os
+
+from libsbgnpy.examples.info_example import info_example
 from libsbgnpy.examples.read_example import read_sbgn_01
 from libsbgnpy.examples.write_example import write_sbgn_01, write_sbgn_02, write_sbgn_03
-from libsbgnpy.examples.info_example import info_example
+
 
 directory = os.path.dirname(os.path.realpath(__file__))
 
@@ -14,13 +16,13 @@
 def test_read_examples():
     """ Parse SBGN file test. """
     files = [
-        'sbgn/adh.sbgn',
-        'sbgn/glycolysis.sbgn',
-        'sbgn/test-output-01.sbgn',
-        'sbgn/test-output-02.sbgn'
+        "sbgn/adh.sbgn",
+        "sbgn/glycolysis.sbgn",
+        "sbgn/test-output-01.sbgn",
+        "sbgn/test-output-02.sbgn",
     ]
     for f_in in files:
-        f = os.path.join(directory, '../examples/{0}'.format(f_in))
+        f = os.path.join(directory, "../examples/{0}".format(f_in))
         sbgn = read_sbgn_01(f)
         assert sbgn is not None
 
@@ -28,25 +30,25 @@ def test_read_examples():
 def test_write_example_01():
     """ Write SBGN file test. """
     f_out = "sbgn/test-output-01.sbgn"
-    f = os.path.join(directory, '../examples/{0}'.format(f_out))
+    f = os.path.join(directory, "../examples/{0}".format(f_out))
     write_sbgn_01(f)
 
 
 def test_write_example_02():
     f_out = "sbgn/test-output-02.sbgn"
-    f = os.path.join(directory, '../examples/{0}'.format(f_out))
+    f = os.path.join(directory, "../examples/{0}".format(f_out))
     write_sbgn_02(f)
 
 
 def test_write_example_03():
     f_out = "sbgn/test-output-03.sbgn"
-    f = os.path.join(directory, '../examples/{0}'.format(f_out))
+    f = os.path.join(directory, "../examples/{0}".format(f_out))
     write_sbgn_03(f)
 
 
 def test_write_read_example_01():
     f_out = "sbgn/test-output-01.sbgn"
-    f = os.path.join(directory, '../examples/{0}'.format(f_out))
+    f = os.path.join(directory, "../examples/{0}".format(f_out))
     write_sbgn_01(f)
     sbgn = read_sbgn_01(f)
     assert sbgn is not None
@@ -54,7 +56,7 @@ def test_write_read_example_01():
 
 def test_write_read_example_02():
     f_out = "sbgn/test-output-02.sbgn"
-    f = os.path.join(directory, '../examples/{0}'.format(f_out))
+    f = os.path.join(directory, "../examples/{0}".format(f_out))
     write_sbgn_02(f)
     sbgn = read_sbgn_01(f)
     assert sbgn is not None
@@ -62,7 +64,7 @@ def test_write_read_example_02():
 
 def test_write_read_example_03():
     f_out = "sbgn/test-output-03.sbgn"
-    f = os.path.join(directory, '../examples/{0}'.format(f_out))
+    f = os.path.join(directory, "../examples/{0}".format(f_out))
     write_sbgn_03(f)
     sbgn = read_sbgn_01(f)
     assert sbgn is not None
diff --git a/libsbgnpy/tests/test_libsbgn.py b/src/libsbgnpy/test/test_libsbgn.py
similarity index 83%
rename from libsbgnpy/tests/test_libsbgn.py
rename to src/libsbgnpy/test/test_libsbgn.py
index 73eafe8..8d1ccd4 100644
--- a/libsbgnpy/tests/test_libsbgn.py
+++ b/src/libsbgnpy/test/test_libsbgn.py
@@ -2,8 +2,9 @@
 Example tests.
 """
 import pytest
+
 import libsbgnpy.libsbgn as libsbgn
-from libsbgnpy.libsbgnTypes import Language, GlyphClass, ArcClass, Orientation
+from libsbgnpy.libsbgnTypes import ArcClass, GlyphClass, Language, Orientation
 
 
 @pytest.fixture
@@ -24,14 +25,15 @@ def sbgn():
     # class attribute is named 'class_' ! in glyphs and arcs
 
     # glyphs with labels
-    g = libsbgn.glyph(class_=GlyphClass.SIMPLE_CHEMICAL, id='glyph1')
-    g.set_label(libsbgn.label(text='Ethanol'))
+    g = libsbgn.glyph(class_=GlyphClass.SIMPLE_CHEMICAL, id="glyph1")
+    g.set_label(libsbgn.label(text="Ethanol"))
     g.set_bbox(libsbgn.bbox(x=40, y=120, w=60, h=60))
     sbgn_map.add_glyph(g)
 
     # glyph with ports (process)
-    g = libsbgn.glyph(class_=GlyphClass.PROCESS, id='pn1',
-                      orientation=Orientation.HORIZONTAL)
+    g = libsbgn.glyph(
+        class_=GlyphClass.PROCESS, id="pn1", orientation=Orientation.HORIZONTAL
+    )
     g.set_bbox(libsbgn.bbox(x=148, y=168, w=24, h=24))
     g.add_port(libsbgn.port(x=136, y=180, id="pn1.1"))
     g.add_port(libsbgn.port(x=184, y=180, id="pn1.2"))
@@ -39,7 +41,9 @@ def sbgn():
 
     # arcs
     # create arcs and set the start and end points
-    a = libsbgn.arc(class_=ArcClass.CONSUMPTION, source="glyph1", target="pn1.1", id="a01")
+    a = libsbgn.arc(
+        class_=ArcClass.CONSUMPTION, source="glyph1", target="pn1.1", id="a01"
+    )
     a.set_start(libsbgn.startType(x=98, y=160))
     a.set_end(libsbgn.endType(x=136, y=180))
     sbgn_map.add_arc(a)
@@ -103,7 +107,7 @@ def test_glyph_classes(sbgn):
 
 def test_glyph_labels(sbgn):
     glyphs = sbgn.get_map().get_glyph()
-    assert glyphs[0].get_label().get_text() == 'Ethanol'
+    assert glyphs[0].get_label().get_text() == "Ethanol"
 
 
 def test_glyph_bboxes(sbgn):
@@ -127,11 +131,11 @@ def test_glyph_ports(sbgn):
     ports = glyphs[1].get_port()
     assert ports[0].get_x() == 136
     assert ports[0].get_y() == 180
-    assert ports[0].get_id() == 'pn1.1'
+    assert ports[0].get_id() == "pn1.1"
 
     assert ports[1].get_x() == 184
     assert ports[1].get_y() == 180
-    assert ports[1].get_id() == 'pn1.2'
+    assert ports[1].get_id() == "pn1.2"
 
 
 def test_arc_exists(sbgn):
@@ -154,11 +158,11 @@ def test_arc_end(sbgn):
 
 
 def test_glyph_class(sbgn):
-    g1 = libsbgn.glyph(class_=GlyphClass.SIMPLE_CHEMICAL, id='glyph1')
-    assert g1.get_id() == 'glyph1'
+    g1 = libsbgn.glyph(class_=GlyphClass.SIMPLE_CHEMICAL, id="glyph1")
+    assert g1.get_id() == "glyph1"
     assert g1.get_class() == GlyphClass.SIMPLE_CHEMICAL
 
-    g2 = libsbgn.glyph(id='glyph1')
+    g2 = libsbgn.glyph(id="glyph1")
     g2.set_class(GlyphClass.SIMPLE_CHEMICAL)
-    assert g2.get_id() == 'glyph1'
+    assert g2.get_id() == "glyph1"
     assert g2.get_class() == GlyphClass.SIMPLE_CHEMICAL
diff --git a/libsbgnpy/tests/test_py3.py b/src/libsbgnpy/test/test_py3.py
similarity index 75%
rename from libsbgnpy/tests/test_py3.py
rename to src/libsbgnpy/test/test_py3.py
index fa361ea..48861a3 100644
--- a/libsbgnpy/tests/test_py3.py
+++ b/src/libsbgnpy/test/test_py3.py
@@ -1,7 +1,7 @@
 import tempfile
 
 from libsbgnpy import libsbgn
-from libsbgnpy.libsbgnTypes import Language, GlyphClass, ArcClass
+from libsbgnpy.libsbgnTypes import ArcClass, GlyphClass, Language
 
 
 def test_basestring_issue():
@@ -21,7 +21,7 @@ def test_basestring_issue():
     sbgn_map.set_bbox(box)
 
     # glyphs with labels
-    for comp in ('Cytoplasm', ):
+    for comp in ("Cytoplasm",):
         c_id = comp
         c_name = comp
         (x, y), (w, h) = (10, 10), (90, 90)
@@ -30,7 +30,7 @@ def test_basestring_issue():
         g.set_bbox(libsbgn.bbox(x, y, w, h))
         sbgn_map.add_glyph(g)
 
-    s2xy = {'H2': (20, 20), 'O2': (20, 80), 'H2O': (80, 60)}
+    s2xy = {"H2": (20, 20), "O2": (20, 80), "H2O": (80, 60)}
     for species, (x, y) in s2xy.items():
         s_id = species
         s_name = species
@@ -38,20 +38,24 @@ def test_basestring_issue():
         glyph_type = GlyphClass.SIMPLE_CHEMICAL
 
         (w, h) = (5, 5)
-        g = libsbgn.glyph(class_=glyph_type, id=s_id, compartmentRef='Cytoplasm')
-        g.set_label(libsbgn.label(text=s_name,
-                                  bbox=libsbgn.bbox(x + w * 0.1, y + h * 0.1, w * 0.8, h * 0.8)))
+        g = libsbgn.glyph(class_=glyph_type, id=s_id, compartmentRef="Cytoplasm")
+        g.set_label(
+            libsbgn.label(
+                text=s_name,
+                bbox=libsbgn.bbox(x + w * 0.1, y + h * 0.1, w * 0.8, h * 0.8),
+            )
+        )
         g.set_bbox(libsbgn.bbox(x, y, w, h))
         sbgn_map.add_glyph(g)
 
     # glyph with ports (process)
-    r_id = 'Water'
+    r_id = "Water"
     (x, y), (w, h) = (60, 60), (4, 4)
     g = libsbgn.glyph(class_=GlyphClass.PROCESS, id=r_id)
     g.set_bbox(libsbgn.bbox(x, y, w, h))
 
     in_port = None
-    for s_id in ('O2', 'H2'):
+    for s_id in ("O2", "H2"):
         edge_id = "-".join(sorted((s_id, r_id)))
 
         if not in_port:
@@ -60,15 +64,18 @@ def test_basestring_issue():
             g.add_port(in_port)
 
         sref_id = s_id
-        a = libsbgn.arc(class_=ArcClass.CONSUMPTION,
-                        target=in_port.get_id(),
-                        source=sref_id, id="a_%s_%s" % (s_id, r_id))
+        a = libsbgn.arc(
+            class_=ArcClass.CONSUMPTION,
+            target=in_port.get_id(),
+            source=sref_id,
+            id="a_%s_%s" % (s_id, r_id),
+        )
         s_x, s_y = s2xy[s_id]
         a.set_start(libsbgn.startType(x=s_x, y=s_y))
         a.set_end(libsbgn.endType(x=in_port.get_x(), y=in_port.get_y()))
         sbgn_map.add_arc(a)
     out_port = None
-    for s_id in ('H2O', ):
+    for s_id in ("H2O",):
         edge_id = "-".join(sorted((s_id, r_id)))
 
         if not out_port:
@@ -76,8 +83,12 @@ def test_basestring_issue():
             out_port = libsbgn.port(x=port_x, y=port_y, id="%s__out" % r_id)
             g.add_port(out_port)
         sref_id = s_id
-        a = libsbgn.arc(class_=ArcClass.PRODUCTION, target=sref_id, source=out_port.get_id(),
-                        id="a_%s_%s" % (r_id, s_id))
+        a = libsbgn.arc(
+            class_=ArcClass.PRODUCTION,
+            target=sref_id,
+            source=out_port.get_id(),
+            id="a_%s_%s" % (r_id, s_id),
+        )
         s_x, s_y = s2xy[s_id]
         a.set_end(libsbgn.startType(x=s_x, y=s_y))
         a.set_start(libsbgn.endType(x=out_port.get_x(), y=out_port.get_y()))
diff --git a/libsbgnpy/tests/test_render.py b/src/libsbgnpy/test/test_render.py
similarity index 76%
rename from libsbgnpy/tests/test_render.py
rename to src/libsbgnpy/test/test_render.py
index e551bde..7b104bf 100644
--- a/libsbgnpy/tests/test_render.py
+++ b/src/libsbgnpy/test/test_render.py
@@ -1,18 +1,18 @@
 """
 Tests the SBGN render functions.
 """
-import pytest
 import os
 import tempfile
 
-from libsbgnpy import utils
-from libsbgnpy import render
+import pytest
+
+from libsbgnpy import render, utils
 
 
 @pytest.fixture
 def f_adh():
     directory = os.path.dirname(os.path.realpath(__file__))
-    f = os.path.join(directory, '../examples/sbgn/adh.sbgn')
+    f = os.path.join(directory, "../examples/sbgn/adh.sbgn")
     return f
 
 
diff --git a/libsbgnpy/tests/test_subclasses.py b/src/libsbgnpy/test/test_subclasses.py
similarity index 92%
rename from libsbgnpy/tests/test_subclasses.py
rename to src/libsbgnpy/test/test_subclasses.py
index 0b0e867..d464b31 100644
--- a/libsbgnpy/tests/test_subclasses.py
+++ b/src/libsbgnpy/test/test_subclasses.py
@@ -2,9 +2,9 @@
 Test Notes and Extensions.
 """
 import tempfile
-from libsbgnpy import libsbgn, Notes, Extension, Language
-from libsbgnpy import utils
-from libsbgnpy.examples import notes_example, extension_example
+
+from libsbgnpy import Extension, Language, Notes, libsbgn, utils
+from libsbgnpy.examples import extension_example, notes_example
 
 
 def test_create_notes():
@@ -25,10 +25,12 @@ def test_create_notes():
     g.set_bbox(bbox)
     map.add_glyph(g)
 
-    notes = Notes("""
+    notes = Notes(
+        """
        <body xmlns="http://www.w3.org/1999/xhtml">
            This is an example note describing the INSR glyph.
-       </body>""")
+       </body>"""
+    )
     g.set_notes(notes)
     assert g.get_notes() is not None
 
@@ -78,7 +80,8 @@ def test_create_extension():
     map.set_language(Language.PD)
     sbgn.set_map(map)
 
-    extension = Extension("""<renderInformation id="example" programName="SBML Layout" programVersion="3.0"
+    extension = Extension(
+        """<renderInformation id="example" programName="SBML Layout" programVersion="3.0"
         xmlns="http://projects.eml.org/bcb/sbml/render/level2">
            <listOfColorDefinitions>
            <colorDefinition id="yelloComp" value="#ffffccff" />
@@ -128,7 +131,8 @@ def test_create_extension():
                <g stroke="blue" stroke-width="2"  />
            </style>
            </listOfStyles>
-       </renderInformation>""")
+       </renderInformation>"""
+    )
     map.set_extension(extension)
 
     assert map.get_extension() is not None
@@ -143,7 +147,8 @@ def test_read_extension():
     map.set_language(Language.PD)
     sbgn.set_map(map)
 
-    extension = Extension("""<renderInformation id="example" programName="SBML Layout" programVersion="3.0"
+    extension = Extension(
+        """<renderInformation id="example" programName="SBML Layout" programVersion="3.0"
         xmlns="http://projects.eml.org/bcb/sbml/render/level2">
            <listOfColorDefinitions>
            <colorDefinition id="yelloComp" value="#ffffccff" />
@@ -155,7 +160,8 @@ def test_read_extension():
            <colorDefinition id="Color_1" value="#ff9900" />
            <colorDefinition id="Color_2" value="#000000" />
            </listOfColorDefinitions>
-       </renderInformation>""")
+       </renderInformation>"""
+    )
 
     map.set_extension(extension)
     assert map.get_extension() is not None
diff --git a/libsbgnpy/tests/test_testfiles.py b/src/libsbgnpy/test/test_testfiles.py
similarity index 86%
rename from libsbgnpy/tests/test_testfiles.py
rename to src/libsbgnpy/test/test_testfiles.py
index 92fc582..a3b339a 100644
--- a/libsbgnpy/tests/test_testfiles.py
+++ b/src/libsbgnpy/test/test_testfiles.py
@@ -3,16 +3,18 @@
 """
 Read all the test files.
 """
-import unittest
-import tempfile
 import os
+import tempfile
+import unittest
+
 import libsbgnpy.libsbgn as libsbgn
 
+
 ##############################################
 # Test files
 ##############################################
 current_dir = os.path.dirname(os.path.realpath(__file__))
-testfile_dir = os.path.join(current_dir, 'test-files')
+testfile_dir = os.path.join(current_dir, "test-files")
 
 
 def find_sbgn_files(directory):
@@ -24,6 +26,7 @@ def find_sbgn_files(directory):
                 sbgn_files.append(f)
     return sbgn_files
 
+
 sbgn_files = find_sbgn_files(directory=testfile_dir)
 ##############################################
 
@@ -32,20 +35,21 @@ class TestSBGNFile(unittest.TestCase):
     """
     Dummy test class. Test methods are attached.
     """
+
     pass
 
 
 def create_method(f):
-    """ Test function generator.
+    """Test function generator.
 
     :param f:
     :return:
     """
 
     def f_expected(self):
-        print('*' * 80)
+        print("*" * 80)
         print(f)
-        print('*' * 80)
+        print("*" * 80)
         sbgn = libsbgn.parse(f)
         self.assertTrue(sbgn is not None)
 
@@ -55,12 +59,13 @@ def f_expected(self):
 
     return f_expected
 
+
 # Add test functions for files
 for k, f in enumerate(sbgn_files):
     test_method = create_method(f)
-    test_method.__name__ = 'test_%s' % k
+    test_method.__name__ = "test_%s" % k
     setattr(TestSBGNFile, test_method.__name__, test_method)
     del test_method
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     unittest.main()
diff --git a/libsbgnpy/tests/test_utils.py b/src/libsbgnpy/test/test_utils.py
similarity index 86%
rename from libsbgnpy/tests/test_utils.py
rename to src/libsbgnpy/test/test_utils.py
index bdde2c8..bb54b7f 100644
--- a/libsbgnpy/tests/test_utils.py
+++ b/src/libsbgnpy/test/test_utils.py
@@ -1,10 +1,11 @@
 """
 Tests the SBGN utility functions.
 """
-import pytest
 import os
 import tempfile
 
+import pytest
+
 from libsbgnpy import utils as utils
 from libsbgnpy.libsbgnTypes import Language
 
@@ -12,7 +13,7 @@
 @pytest.fixture
 def f_adh():
     directory = os.path.dirname(os.path.realpath(__file__))
-    f = os.path.join(directory, '../examples/sbgn/adh.sbgn')
+    f = os.path.join(directory, "../examples/sbgn/adh.sbgn")
     return f
 
 
@@ -23,7 +24,7 @@ def test_read_from_file(f_adh):
 
 def test_write_to_file(f_adh):
     sbgn = utils.read_from_file(f_adh)
-    f_out = tempfile.NamedTemporaryFile(suffix='.sbgn')
+    f_out = tempfile.NamedTemporaryFile(suffix=".sbgn")
     utils.write_to_file(sbgn, f_out.name)
     sbgn2 = utils.read_from_file(f_out)
     assert sbgn2 is not None
@@ -34,7 +35,7 @@ def test_write_to_string(f_adh):
     sbgn_str = utils.write_to_string(sbgn)
 
     assert sbgn_str is not None
-    assert 'xml' in sbgn_str
+    assert "xml" in sbgn_str
 
 
 def test_get_version(f_adh):
diff --git a/libsbgnpy/tests/test_validator.py b/src/libsbgnpy/test/test_validator.py
similarity index 74%
rename from libsbgnpy/tests/test_validator.py
rename to src/libsbgnpy/test/test_validator.py
index abd98bc..10644d5 100644
--- a/libsbgnpy/tests/test_validator.py
+++ b/src/libsbgnpy/test/test_validator.py
@@ -1,18 +1,20 @@
 import os
+
 from libsbgnpy.validation import validator
 
+
 directory = os.path.dirname(os.path.realpath(__file__))
 
 
 def test_validate_xsd_01():
     """ Test XSD validation. """
-    f = os.path.join(directory, '../examples/sbgn/adh.sbgn')
+    f = os.path.join(directory, "../examples/sbgn/adh.sbgn")
     is_valid = validator.validate_xsd(f) is None
     assert is_valid
 
 
 def test_validate_xsd_02():
     """ Test XSD validation. """
-    f = os.path.join(directory, '../examples/sbgn/glycolysis.sbgn')
+    f = os.path.join(directory, "../examples/sbgn/glycolysis.sbgn")
     is_valid = validator.validate_xsd(f) is None
     assert is_valid
diff --git a/libsbgnpy/validation/error-test-files/AF/af10101-fail.sbgn b/src/libsbgnpy/validation/error-test-files/AF/af10101-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/AF/af10101-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/AF/af10101-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/AF/af10101-pass.sbgn b/src/libsbgnpy/validation/error-test-files/AF/af10101-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/AF/af10101-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/AF/af10101-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/AF/af10102-fail-1.sbgn b/src/libsbgnpy/validation/error-test-files/AF/af10102-fail-1.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/AF/af10102-fail-1.sbgn
rename to src/libsbgnpy/validation/error-test-files/AF/af10102-fail-1.sbgn
diff --git a/libsbgnpy/validation/error-test-files/AF/af10102-fail-2.sbgn b/src/libsbgnpy/validation/error-test-files/AF/af10102-fail-2.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/AF/af10102-fail-2.sbgn
rename to src/libsbgnpy/validation/error-test-files/AF/af10102-fail-2.sbgn
diff --git a/libsbgnpy/validation/error-test-files/AF/af10102-fail-3.sbgn b/src/libsbgnpy/validation/error-test-files/AF/af10102-fail-3.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/AF/af10102-fail-3.sbgn
rename to src/libsbgnpy/validation/error-test-files/AF/af10102-fail-3.sbgn
diff --git a/libsbgnpy/validation/error-test-files/AF/af10102-fail-4.sbgn b/src/libsbgnpy/validation/error-test-files/AF/af10102-fail-4.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/AF/af10102-fail-4.sbgn
rename to src/libsbgnpy/validation/error-test-files/AF/af10102-fail-4.sbgn
diff --git a/libsbgnpy/validation/error-test-files/AF/af10102-pass.sbgn b/src/libsbgnpy/validation/error-test-files/AF/af10102-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/AF/af10102-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/AF/af10102-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/AF/af10103-fail.sbgn b/src/libsbgnpy/validation/error-test-files/AF/af10103-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/AF/af10103-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/AF/af10103-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/AF/af10103-pass.sbgn b/src/libsbgnpy/validation/error-test-files/AF/af10103-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/AF/af10103-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/AF/af10103-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/AF/af10104-fail.sbgn b/src/libsbgnpy/validation/error-test-files/AF/af10104-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/AF/af10104-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/AF/af10104-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/AF/af10104-pass.sbgn b/src/libsbgnpy/validation/error-test-files/AF/af10104-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/AF/af10104-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/AF/af10104-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/AF/af10109-fail.sbgn b/src/libsbgnpy/validation/error-test-files/AF/af10109-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/AF/af10109-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/AF/af10109-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/AF/af10109-pass.sbgn b/src/libsbgnpy/validation/error-test-files/AF/af10109-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/AF/af10109-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/AF/af10109-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/AF/af10110-fail.sbgn b/src/libsbgnpy/validation/error-test-files/AF/af10110-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/AF/af10110-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/AF/af10110-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/AF/af10111-fail.sbgn b/src/libsbgnpy/validation/error-test-files/AF/af10111-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/AF/af10111-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/AF/af10111-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/AF/af10111-pass.sbgn b/src/libsbgnpy/validation/error-test-files/AF/af10111-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/AF/af10111-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/AF/af10111-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/AF/af10112-fail.sbgn b/src/libsbgnpy/validation/error-test-files/AF/af10112-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/AF/af10112-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/AF/af10112-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/AF/af10113-fail.sbgn b/src/libsbgnpy/validation/error-test-files/AF/af10113-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/AF/af10113-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/AF/af10113-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/ER/er10103-fail.sbgn b/src/libsbgnpy/validation/error-test-files/ER/er10103-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/ER/er10103-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/ER/er10103-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/ER/er10103-pass.sbgn b/src/libsbgnpy/validation/error-test-files/ER/er10103-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/ER/er10103-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/ER/er10103-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/ER/er10104-fail.sbgn b/src/libsbgnpy/validation/error-test-files/ER/er10104-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/ER/er10104-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/ER/er10104-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/ER/er10104-pass.sbgn b/src/libsbgnpy/validation/error-test-files/ER/er10104-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/ER/er10104-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/ER/er10104-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/ER/er10106-fail-1.sbgn b/src/libsbgnpy/validation/error-test-files/ER/er10106-fail-1.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/ER/er10106-fail-1.sbgn
rename to src/libsbgnpy/validation/error-test-files/ER/er10106-fail-1.sbgn
diff --git a/libsbgnpy/validation/error-test-files/ER/er10106-fail-2.sbgn b/src/libsbgnpy/validation/error-test-files/ER/er10106-fail-2.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/ER/er10106-fail-2.sbgn
rename to src/libsbgnpy/validation/error-test-files/ER/er10106-fail-2.sbgn
diff --git a/libsbgnpy/validation/error-test-files/ER/er10106-fail-3.sbgn b/src/libsbgnpy/validation/error-test-files/ER/er10106-fail-3.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/ER/er10106-fail-3.sbgn
rename to src/libsbgnpy/validation/error-test-files/ER/er10106-fail-3.sbgn
diff --git a/libsbgnpy/validation/error-test-files/ER/er10106-fail-4.sbgn b/src/libsbgnpy/validation/error-test-files/ER/er10106-fail-4.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/ER/er10106-fail-4.sbgn
rename to src/libsbgnpy/validation/error-test-files/ER/er10106-fail-4.sbgn
diff --git a/libsbgnpy/validation/error-test-files/ER/er10106-fail-5.sbgn b/src/libsbgnpy/validation/error-test-files/ER/er10106-fail-5.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/ER/er10106-fail-5.sbgn
rename to src/libsbgnpy/validation/error-test-files/ER/er10106-fail-5.sbgn
diff --git a/libsbgnpy/validation/error-test-files/ER/er10106-fail-6.sbgn b/src/libsbgnpy/validation/error-test-files/ER/er10106-fail-6.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/ER/er10106-fail-6.sbgn
rename to src/libsbgnpy/validation/error-test-files/ER/er10106-fail-6.sbgn
diff --git a/libsbgnpy/validation/error-test-files/ER/er10106-pass.sbgn b/src/libsbgnpy/validation/error-test-files/ER/er10106-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/ER/er10106-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/ER/er10106-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/ER/er10107-fail-1.sbgn b/src/libsbgnpy/validation/error-test-files/ER/er10107-fail-1.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/ER/er10107-fail-1.sbgn
rename to src/libsbgnpy/validation/error-test-files/ER/er10107-fail-1.sbgn
diff --git a/libsbgnpy/validation/error-test-files/ER/er10107-fail-2.sbgn b/src/libsbgnpy/validation/error-test-files/ER/er10107-fail-2.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/ER/er10107-fail-2.sbgn
rename to src/libsbgnpy/validation/error-test-files/ER/er10107-fail-2.sbgn
diff --git a/libsbgnpy/validation/error-test-files/ER/er10107-fail-3.sbgn b/src/libsbgnpy/validation/error-test-files/ER/er10107-fail-3.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/ER/er10107-fail-3.sbgn
rename to src/libsbgnpy/validation/error-test-files/ER/er10107-fail-3.sbgn
diff --git a/libsbgnpy/validation/error-test-files/ER/er10107-fail-4.sbgn b/src/libsbgnpy/validation/error-test-files/ER/er10107-fail-4.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/ER/er10107-fail-4.sbgn
rename to src/libsbgnpy/validation/error-test-files/ER/er10107-fail-4.sbgn
diff --git a/libsbgnpy/validation/error-test-files/ER/er10107-fail-5.sbgn b/src/libsbgnpy/validation/error-test-files/ER/er10107-fail-5.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/ER/er10107-fail-5.sbgn
rename to src/libsbgnpy/validation/error-test-files/ER/er10107-fail-5.sbgn
diff --git a/libsbgnpy/validation/error-test-files/ER/er10107-fail-6.sbgn b/src/libsbgnpy/validation/error-test-files/ER/er10107-fail-6.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/ER/er10107-fail-6.sbgn
rename to src/libsbgnpy/validation/error-test-files/ER/er10107-fail-6.sbgn
diff --git a/libsbgnpy/validation/error-test-files/ER/er10107-pass.sbgn b/src/libsbgnpy/validation/error-test-files/ER/er10107-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/ER/er10107-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/ER/er10107-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/ER/er10108-fail-1.sbgn b/src/libsbgnpy/validation/error-test-files/ER/er10108-fail-1.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/ER/er10108-fail-1.sbgn
rename to src/libsbgnpy/validation/error-test-files/ER/er10108-fail-1.sbgn
diff --git a/libsbgnpy/validation/error-test-files/ER/er10108-fail-2.sbgn b/src/libsbgnpy/validation/error-test-files/ER/er10108-fail-2.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/ER/er10108-fail-2.sbgn
rename to src/libsbgnpy/validation/error-test-files/ER/er10108-fail-2.sbgn
diff --git a/libsbgnpy/validation/error-test-files/ER/er10108-pass.sbgn b/src/libsbgnpy/validation/error-test-files/ER/er10108-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/ER/er10108-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/ER/er10108-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/ER/er10109-fail.sbgn b/src/libsbgnpy/validation/error-test-files/ER/er10109-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/ER/er10109-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/ER/er10109-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/ER/er10109-pass.sbgn b/src/libsbgnpy/validation/error-test-files/ER/er10109-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/ER/er10109-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/ER/er10109-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/ER/er10111-fail.sbgn b/src/libsbgnpy/validation/error-test-files/ER/er10111-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/ER/er10111-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/ER/er10111-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/ER/er10111-pass.sbgn b/src/libsbgnpy/validation/error-test-files/ER/er10111-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/ER/er10111-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/ER/er10111-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/ER/er20001-fail.sbgn b/src/libsbgnpy/validation/error-test-files/ER/er20001-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/ER/er20001-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/ER/er20001-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/ER/er20001-pass.sbgn b/src/libsbgnpy/validation/error-test-files/ER/er20001-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/ER/er20001-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/ER/er20001-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10101-fail.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10101-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10101-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10101-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10101-pass.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10101-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10101-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10101-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10102-fail.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10102-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10102-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10102-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10102-pass.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10102-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10102-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10102-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10103-fail.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10103-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10103-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10103-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10103-pass.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10103-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10103-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10103-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10104-fail.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10104-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10104-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10104-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10104-pass.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10104-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10104-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10104-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10105-fail.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10105-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10105-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10105-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10105-pass.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10105-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10105-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10105-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10106-fail.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10106-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10106-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10106-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10106-pass.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10106-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10106-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10106-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10107-fail.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10107-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10107-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10107-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10107-pass.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10107-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10107-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10107-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10108-fail.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10108-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10108-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10108-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10108-pass.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10108-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10108-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10108-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10109-fail-1.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10109-fail-1.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10109-fail-1.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10109-fail-1.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10109-fail-2.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10109-fail-2.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10109-fail-2.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10109-fail-2.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10109-fail-3.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10109-fail-3.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10109-fail-3.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10109-fail-3.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10109-fail-4.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10109-fail-4.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10109-fail-4.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10109-fail-4.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10109-fail-5.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10109-fail-5.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10109-fail-5.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10109-fail-5.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10109-pass.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10109-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10109-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10109-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10110-fail-1.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10110-fail-1.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10110-fail-1.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10110-fail-1.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10110-fail-2.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10110-fail-2.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10110-fail-2.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10110-fail-2.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10110-fail-3.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10110-fail-3.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10110-fail-3.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10110-fail-3.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10110-fail-4.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10110-fail-4.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10110-fail-4.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10110-fail-4.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10110-fail-5.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10110-fail-5.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10110-fail-5.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10110-fail-5.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10110-pass.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10110-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10110-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10110-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10111-fail-2.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10111-fail-2.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10111-fail-2.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10111-fail-2.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10111-fail.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10111-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10111-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10111-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10111-pass.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10111-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10111-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10111-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10112-fail-1.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10112-fail-1.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10112-fail-1.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10112-fail-1.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10112-fail-2.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10112-fail-2.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10112-fail-2.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10112-fail-2.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10112-pass.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10112-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10112-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10112-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10124-fail.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10124-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10124-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10124-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10124-pass.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10124-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10124-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10124-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10125-fail.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10125-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10125-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10125-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10126-fail.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10126-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10126-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10126-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10126-pass.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10126-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10126-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10126-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10127-fail.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10127-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10127-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10127-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10127-pass.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10127-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10127-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10127-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10128-fail.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10128-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10128-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10128-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10128-pass.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10128-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10128-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10128-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10131-fail.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10131-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10131-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10131-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10131-pass.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10131-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10131-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10131-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10132-fail.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10132-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10132-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10132-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10132-pass.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10132-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10132-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10132-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10140-fail.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10140-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10140-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10140-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10140-pass.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10140-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10140-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10140-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10141-fail.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10141-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10141-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10141-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10141-pass.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10141-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10141-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10141-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10142-fail.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10142-fail.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10142-fail.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10142-fail.sbgn
diff --git a/libsbgnpy/validation/error-test-files/PD/pd10142-pass.sbgn b/src/libsbgnpy/validation/error-test-files/PD/pd10142-pass.sbgn
similarity index 100%
rename from libsbgnpy/validation/error-test-files/PD/pd10142-pass.sbgn
rename to src/libsbgnpy/validation/error-test-files/PD/pd10142-pass.sbgn
diff --git a/libsbgnpy/validation/error-test-files/error_notes.txt b/src/libsbgnpy/validation/error-test-files/error_notes.txt
similarity index 100%
rename from libsbgnpy/validation/error-test-files/error_notes.txt
rename to src/libsbgnpy/validation/error-test-files/error_notes.txt