Source

graphalchemy / graphalchemy / models / workers.py

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

from itertools import count
from functools import partial

from markupsafe import escape
from stuf.utils import getcls

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 worker'''

    # graph source
    _db = app(conf.key.backend, conf.userspace)
    # model finder
    _finder = app(conf.model.finder.node, conf.models)
    # model query
    _query = app(conf.model.reader.node, conf.models)
    # model user
    _using = app(conf.model.writer.node, conf.models)
    # node reader
    _r = factory(conf.read.node, backends, db)
    # node writer
    _w = factory(conf.write.node, backends, db)
    # direct
    direct = factory(conf.direct.worker.node, conf.directs, conf.key.session)
    # raw
    raw = factory(conf.raw, conf.appspace, conf.key.session)

    def _prepare(self, thing):
        # snapshot if flag set
        if thing.L.versioned:
            self.using(getcls(thing)).snapshot(thing)
        super(Nodes, self)._prepare(thing)

    def _preprocess(self, thing, model):
        '''
        pre-process graph element

        @param thing: graph object
        '''
        esc = escape
        for k in model.L.escaped:
            thing[k] = esc(thing[k])
        thing['_modified'] = self.now()
        # slug field
        self._autoslug(thing, model)

    def _autoslug(self, properties, model):
        '''
        auto slug an element

        @param properties: graph element properties
        '''
        L = model.L
        slug_from = L.slug_from
        if not slug_from:
            return
        slug = tmpslug = self.Q.slugify(properties[slug_from])
        slug_field = L.slug_field
        # loop until unique slug is located
        filter_by = self._r.filter_by
        index = L.index
        for cnt in count(1):
            prev = filter_by(index, slug_field, tmpslug)
            if not prev:
                break
            tmpslug = '{slug}-{count}'.format(slug=slug, count=cnt)
        # add slug
        properties[slug_field] = tmpslug

    def _postprocess(self, thing, model):
        '''
        postprocess graph node

        @param thing: graph object
        '''
        thing = model(thing)
        L = model.L
        index = L.index
        index_one = self.index_one
        # index created date
        if index:
            index_one(index, 'created', self.now(), thing)
        # index any listed properties
        if L.indexed:
            self.index_many(index, thing, L.indexed)
        # add a slug if present
        slug_from = L.slug_from
        if slug_from:
            index_one(index, slug_from, getattr(thing, slug_from), thing)
        # index properties that support full text search
        if L.fts_indexed:
            self.index_many(L.fts_index, thing, L.fts_indexed)
        return thing

    @defer
    def _create(self, thing):
        '''
        create a new graph node

        @param data: data
        '''
        model = getcls(thing)
        L = model.L
        data = thing.final
        data.update(_created=self.now(), _model=L.name, _uuid=self.Q.uuid())
        # number of versions to maintain
        if L.versioned:
            data['_versions'] = 0
        self._preprocess(data, model)
        thing = self._w.create(
            data,
            L.reference_link,
            self.query(model).reference(),
            partial(self._postprocess, model=model),
        )
        thing._refresh()

    @defer
    def _update(self, thing):
        '''
        update a graph element's properties

        @param thing: graph object
        '''
        model = getcls(thing)
        data = self.final
        self._preprocess(data)
        self._w.update(thing, data, partial(self._postprocess, model=model))
        thing._refresh()

    def query(self, model):
        '''
        query using a graph model

        @param model: graph model
        '''
        return self._query(model)

    def remove(self, thing):
        self._w.delete(thing)
        del thing

    def using(self, model):
        '''
        use graph model

        @param model: graph model
        '''
        return self._using(model)
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.