graphalchemy / graphalchemy / models /

# -*- coding: utf-8 -*-
'''graph model readers'''

from appspace import AppLookupError

from graphalchemy.core import octopus, app, factory
from graphalchemy.mixins.readers import ReaderMixin

__all__ = ['Nodes']
# settings
conf = octopus.G
backends = conf.backends
db = conf.key.db

class Nodes(ReaderMixin, octopus.context.Thing):

    '''graph node model reader'''

    # model finder
    _finder = app(conf.model.finder.node, conf.appspace)
    # direct node reader
    r = factory(, backends, db)
    # direct node writer
    w = factory(conf.write.node, backends, db)

    def __init__(self, model):

        @param model: graph model
        super(Nodes, self).__init__()
        self.model = model

    def anchor(self):
        '''anchor node for a graph model'''
            C = self.model.C
            anchor_link = C.anchor_link
            S = self.S
            userspace = S.userspace
            return, userspace)
        except AppLookupError:
            label = S.anchor.label
            anchor = self.filter_by(C.index, label, label)
            if anchor:
                self.Q.add(anchor, anchor_link, userspace)
                return anchor

    def reference(self):
        '''reference node for a model'''
            S = self.S
            C = self.model.C
            return, S.userspace)
        except AppLookupError:
            label = S.reference.label
            ref = self.filter_by(C.index, label, label)
            if ref:
                self.Q.add(ref, C.reference_link, S.userspace)
                return ref

    def filter(self, index, queries):
        full text search using index

        @param index: name of index
        @param queries: queries built with query builder
        return self.r.filter(index, queries, self.model)

    def filter_by(self, index, key, value):
        filter by keywords

        @param index: index name
        @param key: keyword in index
        @param value: value in index (or second key)
        return self.r.filter_by(
            lambda x: self._finder(element=x)(x),

    def get(self, element):
        get database element by id

        @param element: element id
        return self.model(self.r.get(element))

    def traverse(self, this, tester=None, links=None, unique=None):
        traverse graph, yielding graph elements

        @param this: graph object
        @param tester: filter for traversed elements (default: None)
        @param links: links to traverse (default: None)
        @param unique: how often to traverse the same element (default: None)
        finder = self._finder
        for element in self.r.traverser(this, tester, links, unique):
            yield finder(element=element)(element)

    def walk(self, this, direction=None, label=None, keys=None, end='end'):
        iterate links and yield node from link

        @param this: graph node instance
        @param direction: direction of links (default: None)
        @param label: label for links (default: None)
        @param keys: keys to find on elements (default: None)
        @param end: which end of link to return (default: 'end')
        finder = self._finder
        for element in self.r.walker(this, direction, label, keys, end):
            yield finder(element=element)(element)