Commits

Lynn Rees committed 88847f2

- step

Comments (0)

Files changed (23)

graphalchemy/backends/neo4jem.py

 # -*- coding: utf-8 -*-
-#pylint: disable-msg=w0221
 '''neo4j backends'''
 
+from inspect import ismodule
+
 from lucenequerybuilder import Q
 from stuf.utils import getdefault
 from appspace.six import iteritems
 
 from graphalchemy.backends.utils import Backend, BackendRead
 
-__all__ = ('LinkRead', 'LinkWrite', 'NodeRead', 'NodeWrite', 'embedded')
+__all__ = (
+    'Raw', 'LinkRead', 'LinkWrite', 'NodeRead', 'NodeWrite', 'embedded',
+    'close', 'transaction',
+)
 
 
 def close(db):
 
         @param this: graph object
         @param data: cleaned data
-        @param callback: callback function (default: None)
+        @param callback: callback (default: None)
         '''
         element = this.source
         for k, v in iteritems(data):
 
     '''neo4j link writer'''
 
-    def create(self, link, start, end, callback=None, **kw):
+    def create(self, link, start, end, kw=None, callback=None):
         '''
         create a new graph link
 
         @param link: link name
         @param start: start node for link
         @param end: end node for link
-        @param callback: callback function (default: None)
         @param kw: keywords (default: None)
+        @param callback: callback (default: None)
         '''
-        this = start.source.rels.create(link, end.source, **kw)
+        kw = {} if kw is None else kw
+        this = start.source.rels.create(link, end.source, kw)
         if callback is not None:
             this = callback(this)
         return this
         tv = super(NodeRead, self).traverser(this, links, unique, tester)
         return tv.traverse(this.source).nodes
 
+    #pylint: disable-msg=w0221
     def walker(self, this, direction=None, label=None, keys=None, end=None):
         '''
         iterate links and yield links
         for link in walker:
             lnk = link
             yield getattr(lnk, end)
+    #pylint: enable-msg=w0221
 
 
 class NodeWrite(Write):
 
     '''neo4j node writer'''
 
-    def clone(self, this, model_link, callback=None, **kw):
+    def clone(self, this, model_link, kw=None, callback=None):
         '''
         clone node
 
         @param this: graph object
         @param model_link: model link to clone
-        @param callback: callback function (default: None)
+        @param kw: keywords for links (default: None)
+        @param callback: callback (default: None)
         '''
         # link list
         links = []
                 node_func[id_map[link.end.id]],
                 **dict(link.items())
             )
+        kw = {} if kw is None else kw
         # tie back to original
         fork.rels.create(model_link, this.source, **kw)
         if callback is not None:
             fork = callback(fork)
         return fork
 
-    def create(self, data, link=None, other=None, callback=None, **kw):
+    def create(self, data, link=None, other=None, kw=None, callback=None):
         '''
         create a new graph node
 
-        @param link: link name
-        @param start: start node for link
-        @param end: end node for link
-        @param callback: callback function (default: None)
-        @param kw: keywords (default: None)
+        @param data: data
+        @param link: link kind (default: None)
+        @param other: other node to link to (default: None)
+        @param kw: keywords for links (default: None)
+        @param callback: callback (default: None)
         '''
         # create node
         node = self._db.node(**data)
         # link back to reference
         if link is not None and other is not None:
+            kw = {} if kw is None else kw
             node.rels.create(link, other.source, **kw)
         if callback is not None:
             node = callback(node)
         for link in element.rels:
             link.delete()
         element.delete()
+
+
+__all__ = sorted(name for name, obj in iteritems(locals()) if not any([
+    name.startswith('_'), ismodule(obj)]
+))

graphalchemy/direct/__init__.py

+# -*- coding: utf-8 -*-
+'''graph managers'''

graphalchemy/direct/apps.py

+# -*- coding: utf-8 -*-
+'''graph managers appconf'''
+
+from spine import Pathways
+from appspace import Namespace
+
+__all__ = ['appconf']
+
+
+class Appconf(Pathways):
+
+    class managers(Namespace):
+
+        class element(Namespace):
+            link = 'graphalchemy.managers.elements.Link'
+            node = 'graphalchemy.managers.elements.Node'
+
+        class collection(Namespace):
+            link = 'graphalchemy.managers.collections.Links'
+            node = 'graphalchemy.managers.collections.Nodes'
+
+        class collector(Namespace):
+            link = 'graphalchemy.managers.collectors.Links'
+            node = 'graphalchemy.managers.collectors.Nodes'
+
+        class writer(Namespace):
+            link = 'graphalchemy.managers.writers.Links'
+            node = 'graphalchemy.managers.writers.Nodes'
+
+        class reader(Namespace):
+            link = 'graphalchemy.managers.readers.Links'
+            node = 'graphalchemy.managers.readers.Nodes'
+
+
+appconf = Appconf.create()

graphalchemy/direct/collections.py

+# -*- coding: utf-8 -*-
+'''manager collections'''
+
+from graphalchemy.mixins.collections import LinksMixin, NodesMixin
+
+__all__ = ('Links', 'Nodes')
+
+
+class Links(LinksMixin):
+
+    '''links collection'''
+
+
+class Nodes(NodesMixin):
+
+    '''nodes collection'''

graphalchemy/direct/collectors.py

+# -*- coding: utf-8 -*-
+'''manager collectors'''
+
+from graphalchemy.core import octopus, app
+from graphalchemy.mixins.collectors import LinksMixin, NodesMixin
+
+__all__ = ('Links', 'Nodes')
+
+# settings
+conf = octopus.G
+
+
+class Links(LinksMixin):
+
+    '''manager link collections collector'''
+
+    _collection = app(conf.manager.collection.link, conf.managers)
+
+
+class Nodes(NodesMixin):
+
+    '''manager nodes collections collector'''
+
+    _collection = app(conf.manager.collection.node, conf.managers)

graphalchemy/direct/elements.py

+# -*- coding: utf-8 -*-
+'''manager element models'''
+
+from graphalchemy.core import octopus, app
+from graphalchemy.mixins.elements import LinkMixin, NodeMixin, ThingMixin
+
+__all__ = ('Link', 'Node')
+# settings
+conf = octopus.G
+
+
+class Thing(ThingMixin, octopus.process.Thing):
+
+    '''graph object'''
+
+    # manager links collection
+    _links = app(conf.manager.collector.link, conf.managers)
+
+    @staticmethod
+    def _link():
+        '''link class'''
+        return Link
+
+
+class Link(LinkMixin, Thing):
+
+    '''graph link object'''
+
+    @staticmethod
+    def _node():
+        '''node class'''
+        return Node
+
+
+class Node(NodeMixin, Thing):
+
+    '''graph node object'''
+
+    # manager node collection
+    _nodes = app(conf.manager.collector.node, conf.managers)

graphalchemy/direct/workers.py

+# -*- coding: utf-8 -*-
+'''graph managers'''
+
+from appspace import AppLookupError
+from graphalchemy.mixins.writers import WriterMixin
+from graphalchemy.mixins.readers import ReaderMixin
+from graphalchemy.core import octopus, app, factory, defer
+
+__all__ = ('Links', 'Nodes')
+# settings
+conf = octopus.G
+backends = conf.backends
+db = conf.key.db
+
+
+class Direct(WriterMixin, ReaderMixin, octopus.process.Worker):
+
+    '''direct graph database interface'''
+
+    ###########################################################################
+    ## graph write methods ####################################################
+    ###########################################################################
+
+    @defer
+    def delete(self, this, indices=None):
+        '''
+        delete graph element
+
+        @param this: graph object
+        @param indicies: graph indices (default: None)
+        '''
+        self.w.delete(this, indices)
+
+    @defer
+    def update(self, this, **data):
+        '''
+        update a graph element's properties
+
+        @param this: graph object
+        @param **data: data
+        '''
+        self.w.update(this, data)
+        this._refresh()
+        return this
+
+    ###########################################################################
+    ## graph read methods #####################################################
+    ###########################################################################
+
+    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(index, key, value, self._model)
+
+    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)
+        '''
+        model = self._model
+        for element in self.r.traverser(this, tester, links, unique):
+            yield model(element)
+
+
+class Links(Direct):
+
+    '''direct graph link interface'''
+
+    # graph source
+    _db = app(conf.key.backend, conf.userspace)
+    _model = app(conf.direct.element.link, conf.managers)
+    # direct link reader
+    r = factory(conf.read.link, backends, db)
+    # direct link writer
+    w = factory(conf.write.link, backends, db)
+
+    ###########################################################################
+    ## link write methods #####################################################
+    ###########################################################################
+
+    @defer
+    def create(self, link, start, end, **data):
+        '''
+        create a new graph link
+
+        @param link: link name
+        @param start: start node for link
+        @param end: end node for link
+        @param **data: data
+        '''
+        data.update(_created=self.now(), _uuid=self.Q.uuid())
+        thing = self.w.create(link, start, end, data)
+        thing._refresh()
+        return thing
+
+    ###########################################################################
+    ## link read  methods #####################################################
+    ###########################################################################
+
+    def kind(self, element):
+        '''
+        kind of link
+
+        @param element: graph element
+        '''
+        return self.r.kind(element)
+
+    def walk(self, this, direction=None, label=None, keys=None):
+        '''
+        iterate links and yield graph elements
+
+        @param this: graph object
+        @param direction: direction of links (default: None)
+        @param label: label for links (default: None)
+        @param keys: keys to find on elements (default: None)
+        '''
+        model = self._model
+        for element in self.r.walker(this, direction, label, keys):
+            yield model(element)
+
+
+class Nodes(Direct):
+
+    '''direct graph node interface'''
+
+    _model = app(conf.direct.element.node, conf.managers)
+    # direct node reader
+    r = factory(conf.read.node, backends, db)
+    # direct node writer
+    w = factory(conf.write.node, backends, db)
+
+    ###########################################################################
+    ## node write methods #####################################################
+    ###########################################################################
+
+    @defer
+    def create(self, **data):
+        '''
+        create a new graph node
+
+        @param **data: data
+        '''
+        data.update(_created=self.now(), _uuid=self.Q.uuid())
+        thing = self.w.create(data)
+        thing._refresh()
+        return thing
+
+    ###########################################################################
+    ## link read methods ######################################################
+    ###########################################################################
+
+    def root(self):
+        '''reference root for graph'''
+        try:
+            S = self.S
+            return self.Q.app(S.root, S.userspace)
+        except AppLookupError:
+            root = self.r.root
+            root = self._model(root)
+            self.Q.register(root, S.root, S.userspace)
+            return root
+
+    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')
+        '''
+        model = self._model
+        for element in self.r.walker(this, direction, label, keys, end):
+            yield model(element)

graphalchemy/managers/__init__.py

-# -*- coding: utf-8 -*-
-'''graph managers'''

graphalchemy/managers/apps.py

-# -*- coding: utf-8 -*-
-'''graph managers appconf'''
-
-from spine import Pathways
-from appspace import Namespace
-
-__all__ = ['appconf']
-
-
-class Appconf(Pathways):
-
-    class managers(Namespace):
-
-        class element(Namespace):
-            link = 'graphalchemy.managers.elements.Link'
-            node = 'graphalchemy.managers.elements.Node'
-
-        class collection(Namespace):
-            link = 'graphalchemy.managers.collections.Links'
-            node = 'graphalchemy.managers.collections.Nodes'
-
-        class collector(Namespace):
-            link = 'graphalchemy.managers.collectors.Links'
-            node = 'graphalchemy.managers.collectors.Nodes'
-
-        class writer(Namespace):
-            link = 'graphalchemy.managers.writers.Links'
-            node = 'graphalchemy.managers.writers.Nodes'
-
-        class reader(Namespace):
-            link = 'graphalchemy.managers.readers.Links'
-            node = 'graphalchemy.managers.readers.Nodes'
-
-
-appconf = Appconf.create()

graphalchemy/managers/collections.py

-# -*- coding: utf-8 -*-
-'''manager collections'''
-
-from graphalchemy.mixins.collections import LinksMixin, NodesMixin
-
-__all__ = ('Links', 'Nodes')
-
-
-class Links(LinksMixin):
-
-    '''links collection'''
-
-
-class Nodes(NodesMixin):
-
-    '''nodes collection'''

graphalchemy/managers/collectors.py

-# -*- coding: utf-8 -*-
-'''manager collectors'''
-
-from graphalchemy.core import octopus, app
-from graphalchemy.mixins.collectors import LinksMixin, NodesMixin
-
-__all__ = ('Links', 'Nodes')
-
-# settings
-conf = octopus.G
-
-
-class Links(LinksMixin):
-
-    '''manager link collections collector'''
-
-    _collection = app(conf.manager.collection.link, conf.managers)
-
-
-class Nodes(NodesMixin):
-
-    '''manager nodes collections collector'''
-
-    _collection = app(conf.manager.collection.node, conf.managers)

graphalchemy/managers/core.py

-# -*- coding: utf-8 -*-
-'''graph managers'''
-
-from graphalchemy.core import octopus, app, factory
-from graphalchemy.managers.readers import (
-    Nodes as NodesRead, Links as LinksRead)
-from graphalchemy.managers.writers import (
-    Nodes as NodesWrite, Links as LinksWrite)
-
-__all__ = ('Links', 'Nodes')
-# settings
-conf = octopus.G
-backends = conf.backends
-db = conf.key.db
-
-
-class Links(LinksRead, LinksWrite):
-
-    # graph source
-    _db = app(conf.key.backend, conf.userspace)
-    _model = app(conf.manager.generic.element.link, conf.managers)
-    # direct link reader
-    r = factory(conf.read.link, backends, db)
-    # direct link writer
-    w = factory(conf.write.link, backends, db)
-
-
-class Nodes(NodesRead, NodesWrite):
-
-    _model = app(conf.manager.element.node, conf.managers)
-
-    # direct node reader
-    r = factory(conf.read.node, backends, db)
-    # direct node writer
-    w = factory(conf.write.node, backends, db)
-

graphalchemy/managers/elements.py

-# -*- coding: utf-8 -*-
-'''manager element models'''
-
-from graphalchemy.core import octopus, app
-from graphalchemy.mixins.elements import LinkMixin, NodeMixin, ElementMixin
-
-__all__ = ('Link', 'Node')
-# settings
-conf = octopus.G
-
-
-class Element(ElementMixin, octopus.process.Thing):
-
-    '''graph object'''
-
-    # manager links collection
-    _links = app(conf.manager.collector.link, conf.managers)
-
-    @staticmethod
-    def _link():
-        '''link class'''
-        return Link
-
-
-class Link(LinkMixin, Element):
-
-    '''graph link object'''
-
-    @staticmethod
-    def _node():
-        '''node class'''
-        return Node
-
-
-class Node(NodeMixin, Element):
-
-    '''graph node object'''
-
-    # manager node collection
-    _nodes = app(conf.manager.collector.node, conf.managers)

graphalchemy/managers/readers.py

-# -*- coding: utf-8 -*-
-'''graph readers'''
-
-from appspace import AppLookupError
-
-from graphalchemy.mixins.readers import ReaderMixin
-
-__all__ = ('Links', 'Nodes')
-
-
-class Reader(ReaderMixin):
-
-    '''graph reader base'''
-
-    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(index, key, value, self._model)
-
-    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)
-        '''
-        model = self._model
-        for element in self.r.traverser(this, tester, links, unique):
-            yield model(element)
-
-
-class Links(Reader):
-
-    '''graph link reader'''
-
-    def kind(self, element):
-        '''
-        kind of link
-
-        @param element: graph element
-        '''
-        return self.r.kind(element)
-
-    def walk(self, this, direction=None, label=None, keys=None):
-        '''
-        iterate links and yield graph elements
-
-        @param this: graph object
-        @param direction: direction of links (default: None)
-        @param label: label for links (default: None)
-        @param keys: keys to find on elements (default: None)
-        '''
-        model = self._model
-        for element in self.r.walker(this, direction, label, keys):
-            yield model(element)
-
-
-class Nodes(Reader):
-
-    '''graph manager node reader'''
-
-    def root(self):
-        '''reference root for graph'''
-        try:
-            S = self.S
-            return self.Q.app(S.root, S.userspace)
-        except AppLookupError:
-            root = self.r.root
-            root = self._model(root)
-            self.Q.register(root, S.root, S.userspace)
-            return root
-
-    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')
-        '''
-        model = self._model
-        for element in self.r.walker(this, direction, label, keys, end):
-            yield model(element)

graphalchemy/managers/writers.py

-# -*- coding: utf-8 -*-
-'''graph writer managers'''
-
-from graphalchemy.core import defer
-from graphalchemy.mixins.writers import Writer
-
-
-class WriterMixin(Writer):
-
-    '''graph link writer manager'''
-
-    @defer
-    def update(self, this, **data):
-        '''
-        update a graph element's properties
-
-        @param this: graph object
-        @param **data: data
-        '''
-        self.w.update(this, data)
-        this._refresh()
-        return this
-
-    @defer
-    def delete(self, this, indices=None):
-        '''
-        delete graph element
-
-        @param this: graph object
-        @param indicies: graph indices (default: None)
-        '''
-        self.w.delete(this, indices)
-
-
-class Links(WriterMixin):
-
-    '''graph link writer manager'''
-
-    @defer
-    def create(self, link, start, end, **data):
-        '''
-        create a new graph link
-
-        @param link: link name
-        @param start: start node for link
-        @param end: end node for link
-        @param **data: data
-        '''
-        data.update(_created=self.now(), _uuid=self.Q.uuid())
-        thing = self.w.create(link, start, end, data)
-        thing._refresh()
-        return thing
-
-
-class Nodes(WriterMixin):
-
-    '''graph node writer manager'''
-
-    @defer
-    def create(self, **data):
-        '''
-        create a new graph node
-
-        @param **data: data
-        '''
-        data.update(_created=self.now(), _uuid=self.Q.uuid())
-        thing = self.w.create(data)
-        thing._refresh()
-        return thing

graphalchemy/mixins/elements.py

 conf = getattr(octopus, 'S')
 
 
-class ElementMixin(object):
+class ThingMixin(object):
 
     '''graph element'''
 
         '''
         # element direction
         self.direction = kw.pop('direction', 'outgoing')
-        super(ElementMixin, self).__init__(element, **kw)
+        super(ThingMixin, self).__init__(element, **kw)
 
     @property
     def id(self):
 
     def _refresh(self):
         '''refresh original'''
-        super(ElementMixin, self).sync()
+        super(ThingMixin, self).sync()
         # reset links collector
         self.links.reset()
 

graphalchemy/mixins/readers.py

-# -*- coding: utf-8 -*-
-'''graph reader mixins'''
-
-__all__ = ('Reader Mixin', 'LinksMixin', 'Nodes')
-
-
-class ReaderMixin(object):
-
-    '''graph reader base'''
-
-    def id(self, element):
-        '''
-        graph element identifier
-
-        @param element: a graph element
-        '''
-        return self.r.id(element)
-
-    def properties(self, element):
-        '''
-        fetch a graph model's properties
-
-        @param element: element with properties
-        '''
-        return self.r.properties(element)

graphalchemy/mixins/workers.py

+# -*- coding: utf-8 -*-
+'''graph reader mixins'''
+
+import nanotime
+
+from graphalchemy.core import octopus, defer
+
+__all__ = ('WriterMixin', 'ReaderMixin')
+
+
+class ReaderMixin(object):
+
+    '''graph reader base'''
+
+    def id(self, element):
+        '''
+        graph element identifier
+
+        @param element: a graph element
+        '''
+        return self.r.id(element)
+
+    def properties(self, element):
+        '''
+        fetch a graph model's properties
+
+        @param element: element with properties
+        '''
+        return self.r.properties(element)
+
+
+class WriterMixin(octopus.event.Worker):
+
+    '''graph writer base'''
+
+    @defer
+    def index(self, index, fts=False):
+        '''
+        create link index
+
+        @param index: node index name
+        @param fts: create a full text index (default: False)
+        '''
+        self.w.create_index(index, fts)
+
+    @defer
+    def index_many(self, index, this, indexed):
+        '''
+        index properties on a graph element
+
+        @param index: graph index label
+        @param this: graph object
+        @param indexed: properties to index
+        '''
+        self.w.index_many(self.r.index(index), this, indexed)
+
+    @defer
+    def index_one(self, index, key, value, this):
+        '''
+        index one property of a graph element
+
+        @param index: graph index label
+        @param key: graph element property key
+        @param value: graph element property value
+        @param this: graph object
+        '''
+        self.w.index_one(self.r.index(index), key, value, this)
+
+    @staticmethod
+    def now():
+        '''current time in microseconds'''
+        return nanotime.now().microseconds()

graphalchemy/mixins/writers.py

-# -*- coding: utf-8 -*-
-'''graph writers'''
-
-import nanotime
-
-from graphalchemy.core import octopus, defer
-
-__all__ = ('Links', 'Nodes')
-
-# settings
-conf = octopus.G
-
-
-class Writer(octopus.event.Worker):
-
-    '''graph writer base'''
-
-    @defer
-    def index(self, index, fts=False):
-        '''
-        create link index
-
-        @param index: node index name
-        @param fts: create a full text index (default: False)
-        '''
-        self.w.create_index(index, fts)
-
-    @defer
-    def index_many(self, index, this, indexed):
-        '''
-        index properties on a graph element
-
-        @param index: graph index label
-        @param this: graph object
-        @param indexed: properties to index
-        '''
-        self.w.index_many(self.r.index(index), this, indexed)
-
-    @defer
-    def index_one(self, index, key, value, this):
-        '''
-        index one property of a graph element
-
-        @param index: graph index label
-        @param key: graph element property key
-        @param value: graph element property value
-        @param this: graph object
-        '''
-        self.w.index_one(self.r.index(index), key, value, this)
-
-    @staticmethod
-    def now():
-        '''current time in microseconds'''
-        return nanotime.now().microseconds()

graphalchemy/models/core.py

 from markupsafe import escape
 
 from graphalchemy.errors import ReversionError
-from graphalchemy.mixins.writers import Writer
+from graphalchemy.mixins.writers import WriterMixin
 from graphalchemy.core import octopus, app, factory, defer
 
 __all__ = ['Nodes']
 db = conf.key.db
 
 
-class Nodes(Writer, octopus.workflow.worker):
+class Nodes(WriterMixin, octopus.workflow.worker):
 
     '''graph node writer'''
 

graphalchemy/models/elements.py

 
 
 from graphalchemy.core import octopus, app
-from graphalchemy.mixins.elements import NodeMixin, ElementMixin
+from graphalchemy.mixins.elements import NodeMixin, ThingMixin
 
 __all__ = ['Node']
 # settings
 db = conf.key.db
 
 
-class Node(NodeMixin, ElementMixin, octopus.workflow.Thing):
+class Node(NodeMixin, ThingMixin, octopus.workflow.Thing):
 
     '''node model'''
 

graphalchemy/models/readers.py

 from appspace import AppLookupError
 
 from graphalchemy.core import octopus, app, factory
-from graphalchemy.mixins.readers import ReaderMixin
+from graphalchemy.mixins.workers import ReaderMixin
 
 __all__ = ['Nodes']
 # settings

graphalchemy/models/writers.py

 # -*- coding: utf-8 -*-
 '''graph model writers'''
 
-from graphalchemy.mixins.writers import Writer
+from graphalchemy.mixins.workers import WriterMixin
 from graphalchemy.core import octopus, app, factory
 
 __all__ = ['Nodes']
 db = conf.key.db
 
 
-class Nodes(Writer, octopus.workflow.worker):
+class Nodes(WriterMixin, octopus.workflow.worker):
 
     '''graph node writer'''