コード例 #1
0
class File(db.Model, IntBase):
    __tablename__ = 'grano_file'

    file_name = db.Column(db.Unicode)
    mime_type = db.Column(db.Unicode)

    project_id = db.Column(db.Integer, db.ForeignKey('grano_project.id'))
    author_id = db.Column(db.Integer, db.ForeignKey('grano_account.id'))

    data = db.Column(db.LargeBinary)

    properties = db.relationship('Property', backref='value_file',
        cascade='all, delete, delete-orphan', lazy='dynamic')

    @property
    def fh(self):
        return StringIO(self.data)


    def to_dict_index(self):
        return {
            'id': self.id,
            'project': self.project.to_dict_index(),
            'api_url': url_for('files_api.view', id=self.id),
            'serve_api_url': url_for('files_api.serve', id=self.id),
            'file_name': self.file_name,
            'mime_type': self.mime_type
        }


    def to_dict(self):
        """ Full serialization of the file metadata. """
        return self.to_dict_index()
コード例 #2
0
class Pipeline(db.Model, IntBase):
    __tablename__ = 'grano_pipeline'

    STATUS_PENDING = 'pending'
    STATUS_RUNNING = 'running'
    STATUS_FAILED = 'failed'
    STATUS_COMPLETE = 'complete'

    operation = db.Column(db.Unicode)
    label = db.Column(db.Unicode)
    status = db.Column(db.Unicode)
    percent_complete = db.Column(db.Integer, default=int)

    project_id = db.Column(db.Integer, db.ForeignKey('grano_project.id'))
    author_id = db.Column(db.Integer, db.ForeignKey('grano_account.id'))

    config = db.Column(MutableDict.as_mutable(JSONEncodedDict))

    started_at = db.Column(db.DateTime, default=datetime.utcnow)
    ended_at = db.Column(db.DateTime)

    entries = db.relationship('LogEntry',
                              backref='pipeline',
                              lazy='dynamic',
                              cascade='all, delete, delete-orphan')

    def has_errors(self):
        q = self.entries.filter_by(level=logging.ERROR)
        return q.count() > 0

    def to_dict_index(self):
        return {
            'id': self.id,
            'label': self.label,
            'project': self.project.to_dict_short() if self.project else None,
            'author': self.author.to_dict_index(),
            'api_url': url_for('pipelines_api.view', id=self.id),
            'operation': self.operation,
            'status': self.status,
            'created_at': self.created_at,
            'updated_at': self.updated_at,
            'started_at': self.started_at,
            'ended_at': self.ended_at,
            'config': self.config,
            'percent_complete': self.percent_complete
        }

    def to_dict(self):
        """ Full serialization of the file metadata. """
        data = self.to_dict_index()
        return data
コード例 #3
0
class EntityProperty(Property):
    __mapper_args__ = {'polymorphic_identity': 'entity'}

    entity_id = db.Column(db.Unicode(), db.ForeignKey('entity.id'), index=True)

    def _set_obj(self, obj):
        self.entity = obj
コード例 #4
0
ファイル: schema.py プロジェクト: eocaollai/grano
class Schema(db.Model, IntBase):
    __tablename__ = 'schema'

    name = db.Column(db.Unicode())
    label = db.Column(db.Unicode())
    label_in = db.Column(db.Unicode())
    label_out = db.Column(db.Unicode())
    hidden = db.Column(db.Boolean())
    obj = db.Column(db.Unicode())

    attributes = db.relationship(Attribute, backref='schema', lazy='joined')
    properties = db.relationship(Property, backref='schema', lazy='dynamic')
    relations = db.relationship('Relation', backref='schema', lazy='dynamic')
    project_id = db.Column(db.Integer, db.ForeignKey('project.id'))

    def get_attribute(self, name):
        for attribute in self.attributes:
            if attribute.name == name:
                return attribute

    @classmethod
    def by_name(cls, project, name):
        q = db.session.query(cls).filter_by(name=name)
        q = q.filter_by(project=project)
        return q.first()

    @classmethod
    def by_obj_name(cls, project, obj, name):
        q = db.session.query(cls)
        q = q.filter_by(project=project)
        q = q.filter_by(name=name)
        q = q.filter_by(obj=obj)
        return q.first()
コード例 #5
0
ファイル: project.py プロジェクト: j-norwood-young/grano
class Project(db.Model, IntBase):
    __tablename__ = 'grano_project'

    slug = db.Column(db.Unicode)
    label = db.Column(db.Unicode)
    private = db.Column(db.Boolean, default=False)
    settings = db.Column(MutableDict.as_mutable(JSONEncodedDict))

    author_id = db.Column(db.Integer, db.ForeignKey('grano_account.id'))

    relations = db.relationship('Relation', backref='project', lazy='dynamic',
        cascade='all, delete, delete-orphan')
    entities = db.relationship('Entity', backref='project', lazy='dynamic',
        cascade='all, delete, delete-orphan')
    pipelines = db.relationship('Pipeline', backref='project', lazy='dynamic',
        cascade='all, delete, delete-orphan')
    schemata = db.relationship('Schema', backref='project', lazy='dynamic',
        cascade='all, delete, delete-orphan')
    permissions = db.relationship('Permission', backref='project', lazy='dynamic',
        cascade='all, delete, delete-orphan')
    files = db.relationship('File', backref='project', lazy='dynamic',
        cascade='all, delete, delete-orphan')
    

    def get_attribute(self, obj, name):
        for schema in self.schemata:
            if schema.obj == obj:
                for attr in schema.attributes:
                    if attr.name == name:
                        return attr


    @classmethod
    def by_slug(cls, slug):
        q = db.session.query(cls).filter_by(slug=slug)
        return q.first()


    def to_dict_index(self):
        return {
            'slug': self.slug,
            'label': self.label,
            'private': self.private,
            'api_url': url_for('projects_api.view', slug=self.slug),
            'entities_count': self.entities.count(),
            'relations_count': self.relations.count()
        }


    def to_dict(self):
        data = self.to_dict_index()
        data['settings'] = self.settings
        data['author'] = self.author.to_dict_index()
        data['schemata_index_url'] = url_for('schemata_api.index', slug=self.slug)
        data['entities_index_url'] = url_for('entities_api.index', project=self.slug)
        data['relations_index_url'] = url_for('relations_api.index', project=self.slug)
        return data
コード例 #6
0
ファイル: relation.py プロジェクト: eocaollai/grano
class Relation(db.Model, UUIDBase, PropertyBase):
    __tablename__ = 'relation'
    PropertyClass = RelationProperty

    schema_id = db.Column(db.Integer, db.ForeignKey('schema.id'), index=True)
    source_id = db.Column(db.Unicode, db.ForeignKey('entity.id'), index=True)
    target_id = db.Column(db.Unicode, db.ForeignKey('entity.id'), index=True)
    project_id = db.Column(db.Integer, db.ForeignKey('project.id'))
    author_id = db.Column(db.Integer, db.ForeignKey('account.id'))

    properties = db.relationship(RelationProperty,
                                 order_by=RelationProperty.created_at.desc(),
                                 backref='relation',
                                 lazy='dynamic')

    @property
    def schemata(self):
        return [self.schema]
コード例 #7
0
class RelationProperty(Property):
    __mapper_args__ = {'polymorphic_identity': 'relation'}

    relation_id = db.Column(db.Unicode(),
                            db.ForeignKey('relation.id'),
                            index=True)

    def _set_obj(self, obj):
        self.relation = obj
コード例 #8
0
ファイル: relation.py プロジェクト: j-norwood-young/grano
class Relation(db.Model, UUIDBase, PropertyBase):
    __tablename__ = 'grano_relation'
    #PropertyClass = RelationProperty

    schema_id = db.Column(db.Integer, db.ForeignKey('grano_schema.id'), index=True)
    source_id = db.Column(db.Unicode, db.ForeignKey('grano_entity.id'), index=True)
    target_id = db.Column(db.Unicode, db.ForeignKey('grano_entity.id'), index=True)
    project_id = db.Column(db.Integer, db.ForeignKey('grano_project.id'))
    author_id = db.Column(db.Integer, db.ForeignKey('grano_account.id'))

    properties = db.relationship(Property,
                                 order_by=Property.created_at.desc(),
                                 cascade='all, delete, delete-orphan',
                                 backref='relation', lazy='dynamic')

    @property
    def schemata(self):
        return [self.schema]

    def to_dict_base(self):
        return {
            'id': self.id,
            'properties': {},
            'project': self.project.to_dict_index(),
            'api_url': url_for('relations_api.view', id=self.id),
            'schema': self.schema.to_dict_index(),
            'source': self.source.to_dict_index(),
            'target': self.target.to_dict_index()
        }

    def to_dict(self):
        data = self.to_dict_base()
        for prop in self.active_properties:
            name, prop = prop.to_dict_kv()
            data['properties'][name] = prop
        return data

    def to_dict_index(self):
        data = self.to_dict_base()
        for prop in self.active_properties:
            name, prop = prop.to_dict_kv()
            data['properties'][name] = prop
        return data
コード例 #9
0
class Attribute(db.Model, IntBase):
    __tablename__ = 'grano_attribute'

    DATATYPES = {
        'string': 'value_string',
        'integer': 'value_integer',
        'float': 'value_float',
        'datetime': 'value_datetime',
        'boolean': 'value_boolean',
        'file': 'value_file_id'
    }

    name = db.Column(db.Unicode())
    label = db.Column(db.Unicode())
    description = db.Column(db.Unicode())
    hidden = db.Column(db.Boolean())
    datatype = db.Column(db.Unicode())

    schema_id = db.Column(db.Integer, db.ForeignKey('grano_schema.id'))
    properties = db.relationship('Property',
                                 backref='attribute',
                                 cascade='all, delete, delete-orphan',
                                 lazy='dynamic')

    @property
    def value_column(self):
        return self.DATATYPES.get(self.datatype)

    @classmethod
    def all_named(cls, name):
        q = db.session.query(cls)
        q = q.filter_by(name=name)
        return q.all()

    @classmethod
    def by_schema_and_name(cls, schema, name):
        q = db.session.query(cls)
        q = q.filter_by(schema=schema)
        q = q.filter_by(name=name)
        return q.first()

    def to_index(self):
        return {
            'name': self.name,
            'label': self.label,
            'datatype': self.datatype
        }

    def to_dict(self):
        data = self.to_index()
        data['id'] = self.id
        data['hidden'] = self.hidden
        if self.description and len(self.description):
            data['description'] = self.description
        return data
コード例 #10
0
class Attribute(db.Model):
    """ Attributes are specific properties of a schema for either an entity or
    a relation. They materialize as columns on the joined sub-table for the
    schema. """
    __tablename__ = 'schema_attribute'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Unicode)
    label = db.Column(db.Unicode)
    type = db.Column(db.Unicode)
    help = db.Column(db.Unicode)
    missing = db.Column(db.Unicode)

    schema_id = db.Column(db.Integer, db.ForeignKey('schema.id'))
    schema = db.relationship(Schema,
                             backref=db.backref('attributes', lazy='dynamic'))

    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, onupdate=datetime.utcnow)

    @classmethod
    def create(cls, name, data):
        obj = cls()
        obj.update(name, data)
        return obj

    def update(self, name, data):
        self.name = name
        self.label = data.get('label')
        self.type = data.get('type')
        self.help = data.get('help')
        self.missing = data.get('missing')
        db.session.add(self)
        db.session.flush()

    def delete(self):
        db.session.delete(self)

    def as_dict(self):
        return {
            'label': self.label,
            'type': self.type,
            'help': self.help,
            'missing': self.missing
        }

    @property
    def column(self):
        # TODO: do we also need some typecasting mechanism?
        type_ = ATTRIBUTE_TYPES_DB[self.type]
        return db.Column(self.name, type_)

    def __repr__(self):
        return "<Attribute(%s,%s)>" % (self.id, self.name)
コード例 #11
0
class Property(db.Model, IntBase):
    __tablename__ = 'property'

    schema_id = db.Column(db.Integer, db.ForeignKey('schema.id'))
    author_id = db.Column(db.Integer, db.ForeignKey('account.id'))

    name = db.Column(db.Unicode(), index=True)
    value = db.Column(db.Unicode())
    source_url = db.Column(db.Unicode())
    active = db.Column(db.Boolean())

    obj = db.Column(db.String(20))
    __mapper_args__ = {'polymorphic_on': obj}

    def to_dict(self):
        return {
            'name': self.name,
            'schema': self.schema.name,
            'value': self.value,
            'source_url': self.source_url,
            'active': self.active
        }
コード例 #12
0
ファイル: property.py プロジェクト: j-norwood-young/grano
class Property(db.Model, IntBase):
    __tablename__ = 'grano_property'

    schema_id = db.Column(db.Integer, db.ForeignKey('grano_schema.id'))
    attribute_id = db.Column(db.Integer, db.ForeignKey('grano_attribute.id'))
    author_id = db.Column(db.Integer, db.ForeignKey('grano_account.id'))

    entity_id = db.Column(db.Unicode(),
                          db.ForeignKey('grano_entity.id'),
                          index=True,
                          nullable=True)
    relation_id = db.Column(db.Unicode(),
                            db.ForeignKey('grano_relation.id'),
                            index=True,
                            nullable=True)

    name = db.Column(db.Unicode(), index=True)

    value_string = db.Column(db.Unicode())
    value_integer = db.Column(db.Integer())
    value_float = db.Column(db.Float())
    value_datetime = db.Column(db.DateTime())
    value_boolean = db.Column(db.Boolean())
    value_file_id = db.Column(db.Integer(), db.ForeignKey('grano_file.id'))

    source_url = db.Column(db.Unicode())
    active = db.Column(db.Boolean())

    @property
    def value(self):
        # check file column first since file uses both
        # value_string and value_file_id
        if self.value_file_id is not None:
            return self.value_file_id
        for column in Attribute.DATATYPES.values():
            value = getattr(self, column)
            if value is not None:
                return value

    def to_dict_index(self):
        data = {'value': self.value, 'source_url': self.source_url}
        if self.value_file_id is not None:
            data['file_url'] = self.value_string
        return data

    def to_dict_kv(self):
        return self.name, self.to_dict_index()

    def to_dict(self):
        name, data = self.to_dict_index()
        data['id'] = self.id
        data['name'] = name
        data['created_at'] = self.created_at
        data['updated_at'] = self.updated_at
        data['active'] = self.active
        return data
コード例 #13
0
class Attribute(db.Model, IntBase):
    __tablename__ = 'attribute'

    name = db.Column(db.Unicode())
    label = db.Column(db.Unicode())
    description = db.Column(db.Unicode())
    hidden = db.Column(db.Boolean())
    schema_id = db.Column(db.Integer, db.ForeignKey('schema.id'))

    @classmethod
    def by_name(cls, schema, name):
        q = db.session.query(cls)
        q = q.filter_by(schema=schema)
        q = q.filter_by(name=name)
        return q.first()
コード例 #14
0
ファイル: permission.py プロジェクト: j-norwood-young/grano
class Permission(db.Model, IntBase):
    __tablename__ = 'grano_permission'

    reader = db.Column(db.Boolean)
    editor = db.Column(db.Boolean)
    admin = db.Column(db.Boolean)

    account_id = db.Column(db.Integer, db.ForeignKey('grano_account.id'))
    project_id = db.Column(db.Integer, db.ForeignKey('grano_project.id'))

    @classmethod
    def by_project_and_id(cls, project, id):
        q = db.session.query(cls).filter_by(id=id)
        q = q.filter_by(project=project)
        return q.first()

    def to_dict_index(self):
        return {
            'id':
            self.id,
            'reader':
            self.reader,
            'editor':
            self.editor,
            'admin':
            self.admin,
            'project':
            self.project.to_dict_index(),
            'account':
            self.account.to_dict_index(),
            'api_url':
            url_for('permissions_api.view', slug=self.project.slug, id=self.id)
        }

    def to_dict(self):
        return self.to_dict_index()
コード例 #15
0
class Project(db.Model, IntBase):
    __tablename__ = 'project'

    slug = db.Column(db.Unicode)
    label = db.Column(db.Unicode)
    settings = db.Column(MutableDict.as_mutable(JSONEncodedDict))

    author_id = db.Column(db.Integer, db.ForeignKey('account.id'))

    relations = db.relationship('Relation', backref='project', lazy='dynamic')
    entities = db.relationship('Entity', backref='project', lazy='dynamic')
    schemata = db.relationship('Schema', backref='project', lazy='dynamic')

    @classmethod
    def by_slug(cls, slug):
        q = db.session.query(cls).filter_by(slug=slug)
        return q.first()
コード例 #16
0
class LogEntry(db.Model, IntBase):
    __tablename__ = 'grano_log_entry'

    pipeline_id = db.Column(db.Integer, db.ForeignKey('grano_pipeline.id'))

    level = db.Column(db.Integer)
    message = db.Column(db.Unicode)
    error = db.Column(db.Unicode)

    details = db.Column(MutableDict.as_mutable(JSONEncodedDict))

    def to_dict_index(self):
        return {
            'id':
            self.id,
            'level':
            self.level,
            'message':
            self.message,
            'error':
            self.error,
            'api_url':
            url_for('log_entries_api.view_entry',
                    pipeline_id=self.pipeline.id,
                    id=self.id),
            'created_at':
            self.created_at,
            'updated_at':
            self.updated_at
        }

    def to_dict(self):
        """ Full serialization of the file metadata. """
        data = self.to_dict_index()
        data['details'] = self.details
        return data
コード例 #17
0
class Property(db.Model, IntBase):
    __tablename__ = 'grano_property'

    attribute_id = db.Column(db.Integer, db.ForeignKey('grano_attribute.id'))
    author_id = db.Column(db.Integer, db.ForeignKey('grano_account.id'))

    entity_id = db.Column(db.Unicode(),
                          db.ForeignKey('grano_entity.id'),
                          index=True,
                          nullable=True)
    relation_id = db.Column(db.Unicode(),
                            db.ForeignKey('grano_relation.id'),
                            index=True,
                            nullable=True)

    name = db.Column(db.Unicode(), index=True)

    value_string = db.Column(db.Unicode())
    value_integer = db.Column(db.Integer())
    value_float = db.Column(db.Float())
    value_datetime = db.Column(db.DateTime())
    value_datetime_precision = db.Column(
        db.Enum(*DATETIME_PRECISION, native_enum=False))
    value_boolean = db.Column(db.Boolean())
    value_file_id = db.Column(db.Integer(), db.ForeignKey('grano_file.id'))

    source_url = db.Column(db.Unicode())
    active = db.Column(db.Boolean())

    @property
    def value(self):
        # check file column first since file uses both
        # value_string and value_file_id
        if self.value_file_id is not None:
            return self.value_file_id
        for column in Attribute.DATATYPES.values():
            value = getattr(self, column)
            if value is not None:
                return value

    @classmethod
    def type_column(self, value):
        for name, typ in VALUE_COLUMNS.items():
            if isinstance(value, typ):
                return name
        return 'value_string'

    def to_dict_index(self):
        data = {'value': self.value, 'source_url': self.source_url}
        if self.value_file_id is not None:
            data['file_url'] = self.value_string
        elif self.value_datetime is not None:
            data['value_precision'] = self.value_datetime_precision
        return data

    def to_dict_kv(self):
        return self.name, self.to_dict_index()

    def to_dict(self):
        name, data = self.to_dict_index()
        data['id'] = self.id
        data['name'] = name
        data['created_at'] = self.created_at
        data['updated_at'] = self.updated_at
        data['active'] = self.active
        return data
コード例 #18
0
class Entity(db.Model, UUIDBase, PropertyBase):
    __tablename__ = 'grano_entity'

    same_as = db.Column(db.Unicode,
                        db.ForeignKey('grano_entity.id'),
                        nullable=True)
    project_id = db.Column(db.Integer, db.ForeignKey('grano_project.id'))
    author_id = db.Column(db.Integer, db.ForeignKey('grano_account.id'))
    schema_id = db.Column(db.Integer,
                          db.ForeignKey('grano_schema.id'),
                          index=True)

    degree_in = db.Column(db.Integer)
    degree_out = db.Column(db.Integer)
    degree = db.Column(db.Integer)

    inbound = db.relationship('Relation',
                              lazy='dynamic',
                              backref='target',
                              primaryjoin='Entity.id==Relation.target_id',
                              cascade='all, delete, delete-orphan')
    outbound = db.relationship('Relation',
                               lazy='dynamic',
                               backref='source',
                               primaryjoin='Entity.id==Relation.source_id',
                               cascade='all, delete, delete-orphan')

    properties = db.relationship(Property,
                                 backref='entity',
                                 order_by=Property.created_at.desc(),
                                 cascade='all, delete, delete-orphan',
                                 lazy='joined')

    @property
    def names(self):
        return [p for p in self.properties if p.name == 'name']

    @classmethod
    def by_name(cls, project, name, only_active=False):
        q = cls.by_name_many(project, name, only_active=only_active)
        return q.first()

    @classmethod
    def by_name_many(cls, project, name, only_active=False):
        q = db.session.query(cls)
        q = q.filter(cls.project == project)
        q = cls._filter_property(q, 'name', name, only_active=only_active)
        return q

    def to_dict_index(self):
        """ Convert an entity to the REST API form. """
        data = {
            'id': self.id,
            'degree': self.degree,
            'degree_in': self.degree_in,
            'degree_out': self.degree_out,
            'project': self.project.to_dict_short(),
            'schema': self.schema.to_dict_index(),
            'api_url': url_for('entities_api.view', id=self.id),
            'properties': {}
        }

        for prop in self.active_properties:
            name, prop = prop.to_dict_kv()
            data['properties'][name] = prop

        if self.same_as:
            data['same_as'] = self.same_as
            data['same_as_url'] = url_for('entities_api.view', id=self.same_as)
        return data

    def to_dict(self):
        """ Full serialization of the entity. """
        data = self.to_dict_index()
        data['created_at'] = self.created_at
        data['updated_at'] = self.updated_at

        if data['degree_in'] > 0:
            data['inbound_url'] = url_for('relations_api.index',
                                          target=self.id)

        if data['degree_out'] > 0:
            data['outbound_url'] = url_for('relations_api.index',
                                           source=self.id)
        return data

    def to_index(self):
        """ Convert an entity to a form appropriate for search indexing. """
        data = self.to_dict()

        data['names'] = []
        for prop in self.properties:
            if prop.name == 'name':
                data['names'].append(prop.value)

        return data
コード例 #19
0
from grano.core import db
from grano.model.common import UUIDBase, PropertyBase

from grano.model.schema import Schema
from grano.model.relation import Relation
from grano.model.property import EntityProperty

entity_schema = db.Table(
    'entity_schema',
    db.Column('entity_id', db.Unicode, db.ForeignKey('entity.id')),
    db.Column('schema_id', db.Integer, db.ForeignKey('schema.id')))


class Entity(db.Model, UUIDBase, PropertyBase):
    __tablename__ = 'entity'
    PropertyClass = EntityProperty

    same_as = db.Column(db.Unicode, db.ForeignKey('entity.id'), nullable=True)
    project_id = db.Column(db.Integer, db.ForeignKey('project.id'))
    author_id = db.Column(db.Integer, db.ForeignKey('account.id'))

    schemata = db.relationship('Schema',
                               secondary=entity_schema,
                               backref=db.backref('entities', lazy='dynamic'))

    inbound = db.relationship('Relation',
                              lazy='dynamic',
                              backref='target',
                              primaryjoin='Entity.id==Relation.target_id')
    outbound = db.relationship('Relation',
                               lazy='dynamic',
コード例 #20
0
class Entity(db.Model, UUIDBase, PropertyBase):
    __tablename__ = 'entity'
    PropertyClass = EntityProperty

    same_as = db.Column(db.Unicode, db.ForeignKey('entity.id'), nullable=True)
    project_id = db.Column(db.Integer, db.ForeignKey('project.id'))
    author_id = db.Column(db.Integer, db.ForeignKey('account.id'))

    schemata = db.relationship('Schema',
                               secondary=entity_schema,
                               backref=db.backref('entities', lazy='dynamic'))

    inbound = db.relationship('Relation',
                              lazy='dynamic',
                              backref='target',
                              primaryjoin='Entity.id==Relation.target_id')
    outbound = db.relationship('Relation',
                               lazy='dynamic',
                               backref='source',
                               primaryjoin='Entity.id==Relation.source_id')

    properties = db.relationship(EntityProperty,
                                 backref='entity',
                                 order_by=EntityProperty.created_at.desc(),
                                 lazy='joined')

    @property
    def names(self):
        return [p for p in self.properties if p.name == 'name']

    @classmethod
    def by_name(cls, project, name, only_active=False):
        q = db.session.query(cls)
        a = q.filter(cls.project == project)
        q = cls._filter_property(q, 'name', name, only_active=only_active)
        return q.first()

    @property
    def inbound_schemata(self):
        from grano.model.relation import Relation
        q = db.session.query(Schema)
        q = q.join(Schema.relations)
        q = q.filter(Relation.target_id == self.id)
        return q.distinct()

    def inbound_by_schema(self, schema):
        q = self.inbound.filter_by(schema=schema)
        return q

    @property
    def outbound_schemata(self):
        from grano.model.relation import Relation
        q = db.session.query(Schema)
        q = q.join(Schema.relations)
        q = q.filter(Relation.source_id == self.id)
        return q.distinct()

    def outbound_by_schema(self, schema):
        q = self.outbound.filter_by(schema=schema)
        return q

    @property
    def degree(self):
        return self.inbound.count() + self.outbound.count()
コード例 #21
0
class Query(db.Model):
    """
    A query object is a stored raw query to be run against the
    network to generate a report.
    """
    __tablename__ = 'query'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Unicode)
    label = db.Column(db.Unicode)
    query = db.Column(db.Unicode)

    network_id = db.Column(db.Integer, db.ForeignKey('network.id'))
    network = db.relationship('Network',
                              backref=db.backref('queries', lazy='dynamic'))

    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, onupdate=datetime.utcnow)

    @classmethod
    def create(cls, network, data):
        obj = cls()
        obj.network = network
        obj.update(data)
        return obj

    def update(self, data):
        self.name = str(data.get('name'))
        self.label = data.get('label')
        self.query = data.get('query')
        db.session.add(self)
        db.session.flush()

    def delete(self):
        db.session.delete(self)

    def as_dict(self):
        return {
            'id': self.id,
            'name': self.name,
            'label': self.label,
            'query': self.query
        }

    def run(self, **kw):
        conn = safe_engine().connect()
        for rs in chain(self.network.relation_schemata,
                        self.network.entity_schemata):
            q = rs.cls.view()
            conn.execute(text(str(q)), current=True)
        return conn.execute(text(self.query), **kw)

    @classmethod
    def by_name(self, network, name):
        q = db.session.query(Query)
        q = q.filter_by(network=network)
        q = q.filter_by(name=name)
        return q.first()

    @classmethod
    def all(self, network):
        q = db.session.query(Query)
        q = q.filter_by(network=network)
        return q

    def __repr__(self):
        return "<Query(%s,%s)>" % (self.id, self.name)
コード例 #22
0
ファイル: schema.py プロジェクト: j-norwood-young/grano
class Schema(db.Model, IntBase):
    __tablename__ = 'grano_schema'

    name = db.Column(db.Unicode())
    label = db.Column(db.Unicode())
    hidden = db.Column(db.Boolean())
    obj = db.Column(db.Unicode())
    meta = db.Column(MutableDict.as_mutable(JSONEncodedDict))

    attributes = db.relationship(Attribute,
                                 backref='schema',
                                 lazy='dynamic',
                                 cascade='all, delete, delete-orphan')
    properties = db.relationship(Property,
                                 backref='schema',
                                 lazy='dynamic',
                                 cascade='all, delete, delete-orphan')
    relations = db.relationship('Relation',
                                backref='schema',
                                lazy='dynamic',
                                cascade='all, delete, delete-orphan')
    project_id = db.Column(db.Integer, db.ForeignKey('grano_project.id'))

    def get_attribute(self, name):
        for attribute in self.attributes:
            if attribute.name == name:
                return attribute

    @classmethod
    def by_name(cls, project, name):
        q = db.session.query(cls).filter_by(name=name)
        q = q.filter_by(project=project)
        return q.first()

    @classmethod
    def by_obj_name(cls, project, obj, name):
        q = db.session.query(cls)
        q = q.filter_by(project=project)
        q = q.filter_by(name=name)
        q = q.filter_by(obj=obj)
        return q.first()

    def to_dict_index(self):
        return {
            'name':
            self.name,
            'default':
            self.name == ENTITY_DEFAULT_SCHEMA,
            'label':
            self.label,
            'hidden':
            self.hidden,
            'meta':
            self.meta,
            'obj':
            self.obj,
            'api_url':
            url_for('schemata_api.view',
                    slug=self.project.slug,
                    name=self.name)
        }

    def to_dict(self):
        data = self.to_dict_index()
        data['id'] = self.id
        data['project'] = self.project.to_dict_index()
        data['attributes'] = [a.to_dict() for a in self.attributes]
        return data
コード例 #23
0
class Schema(db.Model, IntBase):
    __tablename__ = 'grano_schema'

    name = db.Column(db.Unicode())
    label = db.Column(db.Unicode())
    hidden = db.Column(db.Boolean())
    obj = db.Column(db.Unicode())
    meta = db.Column(MutableDict.as_mutable(JSONEncodedDict))
    project_id = db.Column(db.Integer, db.ForeignKey('grano_project.id'))
    parent_id = db.Column(db.Integer, db.ForeignKey('grano_schema.id'),
                          nullable=True)

    local_attributes = db.relationship(Attribute, backref='schema',
                                       lazy='dynamic',
                                       cascade='all, delete, delete-orphan')
    relations = db.relationship('Relation', backref='schema', lazy='dynamic',
                                cascade='all, delete, delete-orphan')
    entities = db.relationship('Entity', backref='schema', lazy='dynamic',
                               cascade='all, delete, delete-orphan')
    children = db.relationship('Schema', lazy='dynamic',
                               backref=db.backref('parent',
                                                  remote_side='Schema.id'))

    @property
    def inherited_attributes(self):
        if self.parent is None:
            return []
        return self.parent.attributes

    @property
    def attributes(self):
        return list(self.local_attributes) + self.inherited_attributes

    def get_attribute(self, name):
        for attribute in self.attributes:
            if attribute.name == name:
                return attribute

    def is_circular(self, path=None):
        if path is None:
            path = []
        if self.name in path:
            return True
        elif self.parent is None:
            return False
        else:
            path.append(self.name)
            return self.parent.is_circular(path)

    def is_parent(self, other):
        if self.parent is None:
            return False
        if self.parent == other:
            return True
        return self.parent.is_parent(other)

    def common_parent(self, other):
        if self == other or self.is_parent(other):
            return self
        return self.common_parent(other.parent)

    @classmethod
    def by_name(cls, project, name):
        q = db.session.query(cls).filter_by(name=name)
        q = q.filter_by(project=project)
        return q.first()

    @classmethod
    def by_obj_name(cls, project, obj, name):
        q = db.session.query(cls)
        q = q.filter_by(project=project)
        q = q.filter_by(name=name)
        q = q.filter_by(obj=obj)
        return q.first()

    def to_dict_index(self):
        return {
            'name': self.name,
            'label': self.label,
            'hidden': self.hidden,
            'obj': self.obj,
            'api_url': url_for('schemata_api.view',
                               slug=self.project.slug,
                               name=self.name)
        }

    def to_dict(self):
        data = self.to_dict_index()
        data['id'] = self.id
        data['meta'] = self.meta
        if self.parent is not None:
            data['parent'] = self.parent.to_dict_index()
        else:
            data['parent'] = None
        data['project'] = self.project.to_dict_short()
        data['attributes'] = [a.to_dict() for a in self.local_attributes]
        for attr in self.inherited_attributes:
            d = attr.to_dict()
            d['inherited'] = True
            data['attributes'].append(d)
        return data
コード例 #24
0
class Schema(db.Model):
    """ A schema defines a specific subtype of either an entity or a relation.
    This can mean any graph element, such as a person, company or other actor
    type for entities - or a type of social, economic or political link for a
    relation (e.g. ownership, school attendance, ..).

    A schema is defined through a model structure that contains necessary
    metadata to handle the schema both internally and via the user interface.
    """
    __tablename__ = 'schema'

    ENTITY = 'entity'
    RELATION = 'relation'
    TYPES = [ENTITY, RELATION]

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Unicode)
    label = db.Column(db.Unicode)
    entity = db.Column(db.Unicode)

    network_id = db.Column(db.Integer, db.ForeignKey('network.id'))
    network = db.relationship('Network',
                              backref=db.backref('schemata', lazy='dynamic'))

    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, onupdate=datetime.utcnow)

    @classmethod
    def create(cls, network, entity, data):
        obj = cls()
        obj.update(network, entity, data)
        return obj

    def update(self, network, entity, data):
        self.network = network
        self.name = str(data.get('name'))
        self.label = data.get('label')
        self.entity = entity
        db.session.add(self)
        db.session.flush()
        attributes = data.get('attributes', {})
        for attribute in self.attributes:
            if attribute.name in attributes:
                del attributes[attribute.name]
            else:
                attribute.delete()
        for name, data in attributes.items():
            attr = Attribute.create(name, data)
            self.attributes.append(attr)
        db.session.flush()
        self.migrate()

    def migrate(self):
        self._make_cls()
        table = self._cls.__table__
        if not table.exists(db.engine):
            table.create(db.engine)
        else:
            table.metadata.bind = db.engine
            for attribute in self.attributes:
                try:
                    col = table.c[attribute.name]
                    col.create()
                except Exception as e:
                    #log.exception(e)
                    pass

    def delete(self):
        for attribute in self.attributes:
            attribute.delete()
        db.session.delete(self)

    @property
    def cls(self):
        if not hasattr(self, '_cls'):
            self._make_cls()
        return self._cls

    @property
    def parent_cls(self):
        return {
            self.ENTITY: self.network.Entity,
            self.RELATION: self.network.Relation,
        }.get(self.entity)

    def _make_cls(self):
        """ Generate a new type, mapped through SQLAlchemy. This will be a
        joined subtable to either an entity or a relation and retain a copy
        of its composite primary key plus any attributes defined in the
        schema. """
        prefix = self.parent_cls.__tablename__

        # inherit primary key:
        cls = {
            '__tablename__': prefix + '__' + self.name,
            'id': db.Column(db.String(36), primary_key=True),
            'serial': db.Column(db.BigInteger, primary_key=True)
        }

        # set up inheritance:
        cls['__mapper_args__'] = {
            'polymorphic_identity':
            self.name,
            'inherit_condition':
            db.and_(cls['id'] == self.parent_cls.id,
                    cls['serial'] == self.parent_cls.serial)
        }
        cls['__table_args__'] = {'extend_existing': True}

        # set up the specific attributes:
        for attribute in self.attributes:
            cls[attribute.name] = attribute.column

        # make an as_dict method:
        def as_dict(ins):
            d = self.parent_cls.as_dict(ins)
            for attribute in self.attributes:
                d[attribute.name] = \
                    getattr(ins, attribute.name)
            return d

        cls['as_dict'] = as_dict

        self._cls = type(str(self.name), (self.parent_cls, ), cls)

    def as_dict(self):
        attrs = [(a.name, a.as_dict()) for a in self.attributes]
        return {
            'id': self.id,
            'name': self.name,
            'label': self.label,
            'entity': self.entity,
            'attributes': dict(attrs)
        }

    def __repr__(self):
        return "<Schema(%s,%s)>" % (self.id, self.name)
コード例 #25
0
class Entity(db.Model, UUIDBase, PropertyBase):
    __tablename__ = 'grano_entity'

    same_as = db.Column(db.Unicode,
                        db.ForeignKey('grano_entity.id'),
                        nullable=True)
    project_id = db.Column(db.Integer, db.ForeignKey('grano_project.id'))
    author_id = db.Column(db.Integer, db.ForeignKey('grano_account.id'))

    schemata = db.relationship('Schema',
                               secondary=entity_schema,
                               backref=db.backref('entities', lazy='dynamic'))
    inbound = db.relationship('Relation',
                              lazy='dynamic',
                              backref='target',
                              primaryjoin='Entity.id==Relation.target_id',
                              cascade='all, delete, delete-orphan')
    outbound = db.relationship('Relation',
                               lazy='dynamic',
                               backref='source',
                               primaryjoin='Entity.id==Relation.source_id',
                               cascade='all, delete, delete-orphan')

    properties = db.relationship(Property,
                                 backref='entity',
                                 order_by=Property.created_at.desc(),
                                 cascade='all, delete, delete-orphan',
                                 lazy='joined')

    status = db.Column(db.Integer, default=0)

    @property
    def names(self):
        return [p for p in self.properties if p.name == 'name']

    @classmethod
    def by_name(cls, project, name, only_active=False):
        q = cls.by_name_many(project, name, only_active=only_active)
        return q.first()

    @classmethod
    def by_name_many(cls, project, name, only_active=False):
        q = db.session.query(cls)
        q = q.filter(cls.project == project)
        attr = project.get_attribute('entity', 'name')
        q = cls._filter_property(q, [attr], name, only_active=only_active)
        return q

    @classmethod
    def by_id_many(cls, ids, account=None):
        from grano.model import Project, Permission
        q = db.session.query(cls)
        q = q.filter(cls.id.in_(ids))
        if account is not None:
            q = q.join(Project)
            q = q.outerjoin(Permission)
            q = q.filter(
                or_(
                    Project.private == False,  # noqa
                    and_(Permission.reader == True,
                         Permission.account == account)))
        id_map = {}
        for e in q.all():
            id_map[e.id] = e
        return id_map

    @property
    def inbound_schemata(self):
        from grano.model.relation import Relation
        q = db.session.query(Schema)
        q = q.join(Schema.relations)
        q = q.filter(Relation.target_id == self.id)
        return q.distinct()

    def inbound_by_schema(self, schema):
        q = self.inbound.filter_by(schema=schema)
        return q

    @property
    def outbound_schemata(self):
        from grano.model.relation import Relation
        q = db.session.query(Schema)
        q = q.join(Schema.relations)
        q = q.filter(Relation.source_id == self.id)
        return q.distinct()

    def outbound_by_schema(self, schema):
        q = self.outbound.filter_by(schema=schema)
        return q

    @property
    def degree(self):
        return self.inbound.count() + self.outbound.count()

    def to_dict_index(self):
        """ Convert an entity to the REST API form. """
        data = {
            'id': self.id,
            'status': self.status,
            'project': self.project.to_dict_index(),
            'api_url': url_for('entities_api.view', id=self.id),
            'properties': {}
        }

        data['schemata'] = [s.to_dict_index() for s in self.schemata]

        for prop in self.active_properties:
            name, prop = prop.to_dict_kv()
            data['properties'][name] = prop

        if self.same_as:
            data['same_as'] = self.same_as
            data['same_as_url'] = url_for('entities_api.view', id=self.same_as)
        return data

    def to_dict(self):
        """ Full serialization of the entity. """
        data = self.to_dict_index()
        data['created_at'] = self.created_at
        data['updated_at'] = self.updated_at

        data['inbound_relations'] = self.inbound.count()
        if data['inbound_relations'] > 0:
            data['inbound_url'] = url_for('relations_api.index',
                                          target=self.id)

        data['outbound_relations'] = self.outbound.count()
        if data['outbound_relations'] > 0:
            data['outbound_url'] = url_for('relations_api.index',
                                           source=self.id)
        return data

    def to_index(self):
        """ Convert an entity to a form appropriate for search indexing. """
        data = self.to_dict()
        data['degree'] = self.degree

        data['names'] = []
        for prop in self.properties:
            if prop.name == 'name':
                data['names'].append(prop.value)

        return data