Skip to content

Instantly share code, notes, and snippets.

@M0r13n
Last active July 16, 2023 12:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save M0r13n/927f97c591d13f0d8bb1665760514f4b to your computer and use it in GitHub Desktop.
Save M0r13n/927f97c591d13f0d8bb1665760514f4b to your computer and use it in GitHub Desktop.
Read Sparx Enterprise Architect files (.qea) using SQLite and SQLAlchemy
"""
Requires sqlalchemy and sqlalchemy_mixins. Install via pip
"""
import pathlib
import typing
from sqlalchemy import ForeignKey, Text, create_engine, Column, Integer, String
from sqlalchemy.orm import create_session, relationship, declarative_base
from sqlalchemy_mixins import ReprMixin
db_file = pathlib.Path(__file__).parent.joinpath('model.qea')
engine = create_engine(f'sqlite:////{str(db_file.absolute())}')
session = create_session(engine)
Base = declarative_base()
class BaseModel(Base, ReprMixin):
"""
This is the base model that every Sqlalchemy model class should inherit from.
"""
__abstract__ = True
pass
class SQLiteSequence(BaseModel):
__tablename__ = 'sqlite_sequence'
name = Column(String, primary_key=True)
seq = Column(Integer)
class Diagram(BaseModel):
# Declarative meta data for sql-alchemy
__tablename__ = 't_diagram'
__repr_attrs__ = ['name']
diagram_id = Column(Integer, primary_key=True)
name = Column(Text)
diagram_type = Column(Text)
# Relations
package_id = Column(Integer, ForeignKey('t_package.package_id'))
package = relationship('Package', back_populates='diagrams', )
parentid = Column(Integer, ForeignKey('t_diagram.diagram_id'))
parent = relationship('Diagram', remote_side=[diagram_id])
objects = relationship('Object', back_populates='diagram')
class Package(BaseModel):
# Declarative meta data for sql-alchemy
__tablename__ = 't_package'
__repr_attrs__ = ['name']
package_id = Column(Integer, primary_key=True)
name = Column(Text)
parent_id = Column(Integer, ForeignKey('t_package.package_id'))
parent = relationship('Package', remote_side=[package_id])
objects = relationship(
'Object', back_populates='package')
diagrams = relationship(
'Diagram', back_populates='package')
class Object(BaseModel):
# Declarative meta data for sql-alchemy
__tablename__ = 't_object'
__repr_attrs__ = ['name', 'classifier', 'parent']
object_id = Column(Integer, primary_key=True)
object_type = Column(Text)
name = Column(Text)
note = Column(Text)
multiplicity = Column(Text)
cardinality = Column(Text)
# Relations
parentid = Column(Integer, ForeignKey('t_object.object_id'))
parent = relationship('Object', remote_side=[object_id])
diagram_id = Column(Integer, ForeignKey('t_diagram.diagram_id'))
diagram = relationship('Diagram', back_populates='objects')
package_id = Column(Integer, ForeignKey('t_package.package_id'))
package = relationship('Package', back_populates='objects')
classifier = Column(Integer)
class Connector(BaseModel):
# Declarative meta data for sql-alchemy
__tablename__ = 't_connector'
__repr_attrs__ = ['name', 'connector_type']
connector_id = Column(Integer, primary_key=True)
name = Column(Text)
direction = Column(Text)
connector_type = Column(Text)
sourcerole = Column(Text)
# Relations
start_object_id = Column(Integer, ForeignKey('t_object.object_id'))
end_object_id = Column(Integer, ForeignKey('t_object.object_id'))
start = relationship('Object', backref='leaving',
foreign_keys=[start_object_id])
end = relationship('Object', backref='incoming',
foreign_keys=[end_object_id])
# Load data from the table
packages = session.query(Package).all()
for pkg in packages:
print(pkg)
diagram: Diagram
for diagram in pkg.diagrams:
print('\t', diagram)
obj: Object
for obj in pkg.objects:
print('\t', obj)
print('\t', 'Leaving:')
for conn in obj.leaving:
print('\t\t\t', conn)
print('\t', 'Incoming:')
for conn in obj.incoming:
print('\t\t\t', conn)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment