Source code for ordf.handler.rdf

"""
This module implements some triplestores. Most basic but least 
scalable is the storage that comes with `RDFLib`_. More advanced
and scalable but more complicated to set up is `4store`_.

RDFLib Basic Storage -- :class:`RDFLib`
---------------------------------------
.. autoclass:: RDFLib
   :show-inheritance:

4Store Quad-Store -- :class:`FourStore`
---------------------------------------
.. autoclass:: FourStore
   :show-inheritance:

.. _RDFLib: http://www.rdflib.net/
.. _4store: http://4store.org/
"""

__all__ = ["RDFLib", "FourStore"]

from rdflib import plugin
from rdflib.store import Store
from ordf.graph import Graph, _Graph, ConjunctiveGraph
from ordf.utils import get_identifier
from ordf.handler import HandlerPlugin
from logging import getLogger

[docs]class RDFLib(HandlerPlugin): """ The RDFLib handler can use any of the back-ends that are supported by rdflib itself. The constructor takes a *store* keyword argument that specifies which to use. This defaults to *"IOMemory"* which is not terribly useful. Initialisation arguments for the store should be passed as positional arguments, for example:: RDFLib("/some/where/data", store="Sleepycat") or the equivalent in the configuration file,:: rdflib.args = /some/where/data rdflib.store = Sleepycat """ def __init__(self, *av, **kw): kw = kw.copy() store = kw.setdefault("store", "IOMemory") del kw["store"] self.log = getLogger(__name__ + "." + self.__class__.__name__) if isinstance(store, basestring): store_cls = plugin.get(store, Store) self.log.info("Initialising %s storage" % store_cls.__name__) store = store_cls(*av, **kw) self.store = store def __getitem__(self, k): ## Careful, the graph in the store is to be treated ## as read-only unless a set operation is made. ## Unfortunately this means we have to copy it ident = get_identifier(k) orig = Graph(self.store, identifier=ident) new = Graph(identifier=ident) new += orig return new def __setitem__(self, k, g): assert isinstance(g, _Graph) old = Graph(self.store, identifier=get_identifier(k)) old.remove((None, None, None)) for statement in g.triples((None, None, None)): old.add(statement) if hasattr(self.store, "sync"): self.store.sync() def __delitem__(self, k): old = Graph(self.store, identifier=get_identifier(k)) old.remove((None, None, None)) if hasattr(self.store, "sync"): self.store.sync() def append(self, g): old = Graph(self.store, identifier=g.identifier) old += g if hasattr(self.store, "sync"): self.store.sync() def remove(self, g): del self[g] def query(self, *av, **kw): if hasattr(self.store, "query"): return self.store.query(*av, **kw) else: g = ConjunctiveGraph(self.store) return g.query(*av, **kw) def commit(self): self.store.commit() def rollback(self): self.store.rollback()
[docs]class FourStore(RDFLib): """ Use of this back-end requires the `py4s`_ bindings to `4store`_. It also requires 4store to be built from the `multiclient branch`_ to support multiple simultaneous client connections. Initialisation takes a comma-separated string of arguments, only the first, the name of the *kb* is required. For example:: FourStore("kbname") FourStore("kbname,soft_limit=-1") or equivalently in the configuration file:: fourstore.args = kbname fourstore.args = kbname,soft_limit=-1 .. _py4s: http://github.com/wwaites/py4s .. _multiclient branch: http://github.com/wwaites/4store """ def __init__(self, config): from py4s import LazyFourStore self.store = LazyFourStore(config) def __setitem__(self, k, g): assert isinstance(g, _Graph) ident = get_identifier(k) cursor = self.store.cursor() cursor.add_graph(g, replace=True) def __delitem__(self, k): ident = get_identifier(k) cursor = self.store.cursor() cursor.delete_graph(ident) def append(self, frag): ident = get_identifier(frag) cursor = self.store.cursor() cursor.add_graph(frag, replace=False) def query(self, *av, **kw): return self.store.query(*av, **kw)