summaryrefslogtreecommitdiff
path: root/archivist/model.py
blob: ce360f3045e04c574279c6e3a2e12886666996d8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
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')
        )