コード例 #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
ファイル: 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
コード例 #3
0
class _CoreBase(object):
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime,
                           default=datetime.utcnow,
                           onupdate=datetime.utcnow)

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

    @classmethod
    def all(cls):
        return db.session.query(cls)
コード例 #4
0
class BidiRelation(db.Model):
    __tablename__ = 'grano_relation_bidi'

    id = db.Column(db.Unicode, primary_key=True)
    created_at = db.Column(db.DateTime)
    updated_at = db.Column(db.DateTime)
    reverse = db.Column(db.Boolean)
    
    relation_id = db.Column(db.Unicode)
    source_id = db.Column(db.Unicode)
    target_id = db.Column(db.Unicode)
    project_id = db.Column(db.Integer)
    schema_id = db.Column(db.Integer)
    author_id = db.Column(db.Integer)
コード例 #5
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)
コード例 #6
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()
コード例 #7
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
コード例 #8
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
コード例 #9
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()
コード例 #10
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()
コード例 #11
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]
コード例 #12
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
コード例 #13
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
コード例 #14
0
    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)
コード例 #15
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
コード例 #16
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()
コード例 #17
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
コード例 #18
0
ファイル: account.py プロジェクト: eocaollai/grano
class Account(db.Model, IntBase):
    __tablename__ = 'account'

    github_id = db.Column(db.Unicode)
    twitter_id = db.Column(db.Unicode)
    facebook_id = db.Column(db.Unicode)

    full_name = db.Column(db.Unicode)
    login = db.Column(db.Unicode)
    email = db.Column(db.Unicode)
    api_key = db.Column(db.Unicode, default=make_token)

    projects = db.relationship('Project', backref='author', lazy='dynamic')
    properties = db.relationship('Property', backref='author', lazy='dynamic')
    relations = db.relationship('Relation', backref='author', lazy='dynamic')
    entities = db.relationship('Entity', backref='author', lazy='dynamic')

    @property
    def display_name(self):
        if self.full_name is not None and len(self.full_name.strip()):
            return self.full_name
        if self.login is not None and len(self.login.strip()):
            return self.login
        return self.email

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

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

    @classmethod
    def by_github_id(cls, github_id):
        q = db.session.query(cls).filter_by(github_id=str(github_id))
        return q.first()

    @classmethod
    def by_twitter_id(cls, twitter_id):
        q = db.session.query(cls).filter_by(twitter_id=str(twitter_id))
        return q.first()

    @classmethod
    def by_facebook_id(cls, facebook_id):
        q = db.session.query(cls).filter_by(facebook_id=str(facebook_id))
        return q.first()
コード例 #19
0
    class Relation(db.Model, RevisionedMixIn, ViewMixIn):
        """ Edge data type. This is never instantiated directly, only through a
        schema definition which will create a joined subtype. """

        __tablename__ = relation_table_name
        id = db.Column(db.String(36), primary_key=True, default=util.make_id)
        serial = db.Column(db.BigInteger,
                           primary_key=True,
                           default=util.make_serial)
        type = db.Column(db.Unicode)

        __mapper_args__ = {'polymorphic_on': type}
        __table_args__ = {'extend_existing': True}

        current = db.Column(db.Boolean)
        created_at = db.Column(db.DateTime, default=datetime.utcnow)

        source_id = db.Column(db.String(36))
        target_id = db.Column(db.String(36))

        def update_values(self, schema, data):
            self.source_id = data.get('source').id
            self.target_id = data.get('target').id

        def as_dict(self):
            return {
                'id': self.id,
                'serial': self.serial,
                'type': self.type,
                'current': self.current,
                'created_at': self.created_at,
                'source': self.source_id,
                'target': self.target_id
            }

        def as_deep_dict(self):
            data = self.as_dict()
            data['source'] = self.source.as_dict()
            data['target'] = self.target.as_dict()
            return data

        def as_nx(self, graph):
            d = util.graph_values(self.as_dict())
            return graph.add_edge(self.source_id, self.target_id, **d)

        def __repr__(self):
            return "<Relation:%s(%s,%s,%s)>" % (self.type, self.id,
                                                self.source_id, self.target_id)
コード例 #20
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
        }
コード例 #21
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()
コード例 #22
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
コード例 #23
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
コード例 #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
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',
コード例 #26
0
 def column(self):
     # TODO: do we also need some typecasting mechanism?
     type_ = ATTRIBUTE_TYPES_DB[self.type]
     return db.Column(self.name, type_)
コード例 #27
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
コード例 #28
0
    class Entity(db.Model, RevisionedMixIn, ViewMixIn):
        """ Node type, never really instantiated directly. """

        __tablename__ = entity_table_name
        id = db.Column(db.String(36), primary_key=True, default=util.make_id)
        serial = db.Column(db.BigInteger,
                           primary_key=True,
                           default=util.make_serial)
        type = db.Column(db.Unicode)

        __mapper_args__ = {'polymorphic_on': type}
        __table_args__ = {'extend_existing': True}

        current = db.Column(db.Boolean)
        created_at = db.Column(db.DateTime, default=datetime.utcnow)
        slug = db.Column(db.Unicode)
        title = db.Column(db.Unicode)
        _fts = db.Column(util.TSVector)

        def update_values(self, schema, data):
            self.title = data.get('title')
            self.slug = util.slugify(self.title)

            text = self.title
            for attribute in schema.attributes:
                text += ' ' + unicode(getattr(self, attribute.name) or '')
            self._fts = util.TSVector.make_text(db.engine, text)

        def delete(self, schema):
            super(Entity, self).delete(schema)
            # TODO: how to get relation schemata?
            #for relation in self.incoming:
            #    relation.delete()

        def as_dict(self):
            return {
                'id': self.id,
                'serial': self.serial,
                'type': self.type,
                'current': self.current,
                'slug': self.slug,
                'title': self.title,
                'created_at': self.created_at
            }

        def as_deep_dict(self):
            data = self.as_dict()
            data['incoming'], data['outgoing'] = [], []
            for rel in self.incoming:
                reldata = rel.as_dict()
                reldata['source'] = rel.source.as_dict()
                data['incoming'].append(reldata)
            for rel in self.outgoing:
                reldata = rel.as_dict()
                reldata['target'] = rel.target.as_dict()
                data['outgoing'].append(reldata)
            return data

        def as_nx(self, graph):
            d = util.graph_values(self.as_dict())
            return graph.add_node(self.id, **d)

        def __repr__(self):
            return "<Entity:%s(%s,%s)>" % (self.type, self.id, self.slug)
コード例 #29
0
class Account(db.Model):
    __tablename__ = 'account'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Unicode)
    fullname = db.Column(db.Unicode)
    email = db.Column(db.Unicode)
    _password = db.Column('password', db.Unicode)

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

    def _set_password(self, password):
        """Hash password on the fly."""
        hashed_password = password

        if isinstance(password, unicode):
            password_8bit = password.encode('UTF-8')
        else:
            password_8bit = password

        salt = sha1()
        salt.update(os.urandom(60))
        hash = sha1()
        hash.update(salt.hexdigest() + password_8bit)
        hashed_password = salt.hexdigest() + hash.hexdigest()

        if not isinstance(hashed_password, unicode):
            hashed_password = hashed_password.decode('UTF-8')

        self._password = hashed_password

    def _get_password(self):
        """Return the password hashed"""
        return self._password

    password = db.synonym('_password', \
        descriptor=property(_get_password, _set_password))

    def validate_password(self, password):
        """
        Check the password against existing credentials.

        :param password: the password that was provided by the user to
            try and authenticate. This is the clear text version that we will
            need to match against the hashed one in the database.
        :type password: unicode object.
        :return: Whether the password is valid.
        :rtype: bool

        """
        hashed_pass = sha1()
        hashed_pass.update(self._password[:40] + password)
        return self._password[40:] == hashed_pass.hexdigest()

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

    def update(self, data):
        self.fullname = data.get('fullname')
        self.email = data.get('email')
        self.password = data.get('password')
        db.session.add(self)
        db.session.flush()

    @property
    def display_name(self):
        return self.fullname or self.name

    def get_id(self):
        return unicode(self.name)

    def is_active(self):
        return True

    def is_anonymous(self):
        return False

    def is_authenticated(self):
        return True

    def as_dict(self):
        return {
            'id': self.id,
            'name': self.name,
            'fullname': self.fullname,
            'created_at': self.created_at,
            'updated_at': self.updated_at,
        }

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

    def __repr__(self):
        return '<Account(%r)>' % (self.name)
コード例 #30
0
class Account(db.Model, IntBase):
    __tablename__ = 'grano_account'

    github_id = db.Column(db.Unicode)
    twitter_id = db.Column(db.Unicode)
    facebook_id = db.Column(db.Unicode)

    full_name = db.Column(db.Unicode)
    login = db.Column(db.Unicode)
    email = db.Column(db.Unicode)
    api_key = db.Column(db.Unicode, default=make_token)

    projects = db.relationship('Project', backref='author', lazy='dynamic')
    pipelines = db.relationship('Pipeline', backref='author', lazy='dynamic')
    files = db.relationship('File', backref='author', lazy='dynamic')
    properties = db.relationship('Property', backref='author', lazy='dynamic')
    relations = db.relationship('Relation', backref='author', lazy='dynamic')
    entities = db.relationship('Entity', backref='author', lazy='dynamic')
    permissions = db.relationship('Permission',
                                  backref='account',
                                  lazy='dynamic',
                                  cascade='all, delete, delete-orphan')

    @property
    def display_name(self):
        if self.full_name is not None and len(self.full_name.strip()):
            return self.full_name
        if self.login is not None and len(self.login.strip()):
            return self.login
        return self.email

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

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

    @classmethod
    def by_github_id(cls, github_id):
        q = db.session.query(cls).filter_by(github_id=str(github_id))
        return q.first()

    @classmethod
    def by_twitter_id(cls, twitter_id):
        q = db.session.query(cls).filter_by(twitter_id=str(twitter_id))
        return q.first()

    @classmethod
    def by_facebook_id(cls, facebook_id):
        q = db.session.query(cls).filter_by(facebook_id=str(facebook_id))
        return q.first()

    def to_dict_index(self):
        return {
            'id': self.id,
            'api_url': url_for('accounts_api.view', id=self.id),
            'display_name': self.display_name
        }

    def to_dict(self):
        data = self.to_dict_index()
        data['login'] = self.login
        data['full_name'] = self.full_name
        data['github_id'] = self.github_id
        data['twitter_id'] = self.twitter_id
        data['facebook_id'] = self.facebook_id
        data['created_at'] = self.created_at
        data['updated_at'] = self.updated_at
        data['email'] = self.email
        return data