from sqlalchemy import create_engine from sqlalchemy import MetaData, Table, Column, ForeignKey, UniqueConstraint from sqlalchemy import types as ty from sqlalchemy.orm import relationship from sqlalchemy.ext.declarative import as_declarative, declared_attr from functools import partial from . import Session engine = create_engine('sqlite:///:memory:', echo=True) Session.configure(bind=engine) ReqColumn = partial(Column, nullable = False) convention = { 'ix': "ix_%(column_0_label)s", 'uq': "uq_%(table_name)s_%(column_0_name)s", 'ck': "ck_%(table_name)s_%(column_0_name)s", 'fk': "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s", 'pk': "pk_%(table_name)s" } metadata = MetaData(naming_convention = convention) try: from sqlalchemy_repr import RepresentableBase as Base except ImportError: Base = object class _QueryProperty(object): def __get__(self, obj, type): return Session().query(type) @as_declarative(metadata = metadata) class Model(Base): id = Column(ty.Integer, primary_key=True) @declared_attr def __tablename__ (cls): return cls.__name__.lower() query = _QueryProperty() @classmethod def get_by(cls, *args, **kwargs): return cls.query.filter_by(*args, **kwargs).first() @classmethod def get(cls, *args, **kwargs): return cls.query.get(*args, **kwargs) class Prefix(Model): prefix = Column(ty.Unicode, index = True, unique = True) builtin = ReqColumn(ty.Boolean, default = False) pseudo = ReqColumn(ty.Boolean, default = False) def __init__(self, name): self.name = name class Tag(Model): name = ReqColumn(ty.Unicode) prefix_id = Column(ty.Integer, ForeignKey(Prefix.id)) prefix = relationship('Prefix', backref='tag') implications = relationship('Tag', secondary = 'tag_x_tag', primaryjoin = 'Tag.id == tag_x_tag.c.tag_id', secondaryjoin = 'Tag.id == tag_x_tag.c.implies_tag_id', backref='implied_by') def __init__(self, name, prefix = None): self.name = name self.prefix = prefix def implies(self, other): self.implications.append(other) def remove_implication(self, other): self.implications.remove(other) class Document(Model): description = Column(ty.Unicode) created = ReqColumn(ty.DateTime) content = ReqColumn(ty.LargeBinary) original_path = Column(ty.Unicode) direction = Column(ty.Boolean) tags = relationship('Tag', secondary = 'document_x_tag') Table('document_x_tag', Model.metadata, Column('document_id', ty.Integer, ForeignKey(Document.id)), Column('tag_id', ty.Integer, ForeignKey(Tag.id)), UniqueConstraint('document_id', 'tag_id', name = 'uq_document_x_tag') ) Table('tag_x_tag', Model.metadata, Column('tag_id', ty.Integer, ForeignKey(Tag.id)), Column('implies_tag_id', ty.Integer, ForeignKey(Tag.id)), UniqueConstraint('tag_id', 'implies_tag_id', name = 'uq_tag_x_tag') )