Source

graphalchemy / graphalchemy / models / writers.py

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

from graphalchemy.errors import ReversionError
from graphalchemy.mixins.workers import WriterMixin
from graphalchemy.core import octopus, app, factory, defer

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


class Nodes(WriterMixin, octopus.workflow.Worker):

    '''graph node writer'''

    # graph source
    _db = app(conf.key.backend, conf.userspace)
    # model finder
    _finder = app(conf.model.finder.node, conf.models)
    # direct node reader
    _r = factory(conf.read.node, backends, db)
    # direct node writer
    _w = factory(conf.write.node, backends, db)

    def __init__(self, model):
        '''
        init

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

    @defer
    def anchor(self, **kw):
        '''create an anchor node'''
        model = self.model
        L = model.L
        name = L.name
        G = self.G.anchor
        label = G.label
        index_one = self.index_one
        def callback(node): #@IgnorePep8
            node = self._finder(element=node)(node)
            # put in root index
            root_index = L.root_index
            if root_index:
                index_one(root_index, label, name, node)
            # put in model index
            index = L.index
            if index:
                index_one(index, label, label, node)
            return node
        data = dict(
            _created=self.now(),
            _uuid=self.Q.uuid(),
            text=G.description.format(name=name),
        )
        data.update(kw)
        return self._w.create(
            data,
            L.reference_link,
            model.nodes.reference(),
            callback,
        )

    @defer
    def fork(self, thing):
        '''
        clone a graph node

        @param thing: graph object
        '''
        created = self.now()
        model = self.model
        L = model.L
        index = L.index
        G = self.G.fork
        if index:
            # create callback
            index_one = self.index_one
            def callback(fork): #@IgnorePep8
                # add hash
                fork['_hash'] = thing.hash_current()
                # refer back to original
                fork['_forked'] = thing.id
                fork = model(fork)
                # index fork
                index_one(index, G.label, thing.id, fork)
                # index forked time
                index_one(index, G.created, created, fork)
                return fork
        else:
            callback = None
        return self._w.clone(thing, L.fork_link, callback, _created=created)

    @defer
    def refer(self, **kw):
        '''create a reference node'''
        finder = self._finder
        model = self.model
        L = model.L
        name = L.name
        G = self.G.reference
        label = G.label
        w = self._w
        index_one = w.index_one
        create_index = w.create_index
        r = self._r
        def callback(node): #@IgnorePep8
            node = finder(element=node)(node)
            # put in root index
            root_index = r.index(L.root_index)
            index_one(root_index, label, name, node)
            # create any main index
            index = L.index
            if index:
                index_one(create_index(index), label, label, node)
            # create any full text index
            fts_index = L.get('fts_index', False)
            if fts_index:
                create_index(fts_index, fts=True)
            return node
        root = r.root
        h = self
        data = dict(
            _created=h.now(),
            _uuid=self.Q.uuid(),
            text=G.description.format(name=name),
        )
        data.update(kw)
        return w.create(
            data, L.reference_link, finder(element=root)(root), callback,
        )

    @defer
    def revert(self, thing, snapshot):
        '''
        change a graph node to an older snapshot

        @param thing: graph object
        @param snapshot: snapshot to revert to
        '''
        if thing.L.versioned:
            self.snapshot(thing)
            self.update(
                thing,
                self._r.filter_by(self.G.snapshot.label, snapshot).properties,
            )
            self.snapshot(thing)
        raise ReversionError('could not revert snapshot {0}'.format(snapshot))

    @defer
    def snapshot(self, thing):
        '''
        capture changes between different versions of a graph node

        @param thing: graph object
        @param diff: differences between two versions of a graph node
        '''
        diff = thing.diff()
        created = self.now()
        # populate diff
        diff.update(
            _created=created,
            _versioned=thing.id,
            _hash=thing.hash_diff(),
            _version=thing._version()
        )
        G = self.G.version
        model = self.model
        L = model.L
        index = L.index
        if index:
            # create callback if index
            index_one = self.index_one
            def callback(snapshot): #@IgnorePep8
                snapshot = model(snapshot)
                # index snapshot with parent snapshot
                index_one(index, G.reference, thing.id, snapshot)
                # index snapshot as snapshot
                index_one(index, G.label, snapshot.id, snapshot)
                # index versioned time
                index_one(index, G.created, created, snapshot)
                return snapshot
        else:
            callback = None
        # create snapshot and link back to previous snapshot
        thing._refresh()
        return self._w.create(
            diff, L.version_link, thing, callback, _created=created,
        )
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.