Last active
November 5, 2020 09:22
-
-
Save pchampin/ab3d01d2c3c245042dc5 to your computer and use it in GitHub Desktop.
A subclass of rdflib SPARQLUpdateStore with BNode support, for Virtuoso
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from rdflib import BNode, URIRef | |
from rdflib.plugins.stores.sparqlstore import SPARQLUpdateStore, _node_to_sparql, _node_from_result, SPARQL_NS | |
from uuid import uuid4 | |
def _virtuoso_compatible_generator(): | |
return unicode(uuid4().int % 2**61) | |
# monkey patch BNode to make it virtuoso compatible | |
BNode.__new__.func_defaults = (None, _virtuoso_compatible_generator, 'b') | |
def _virtuoso_node_to_sparql(node): | |
if isinstance(node, BNode): | |
return '<nodeID://{}>'.format(node) | |
else: | |
return node.n3() | |
def _virtuoso_node_from_result(element): | |
if element.tag == '{%s}bnode' % SPARQL_NS: | |
return BNode(element.text[9:]) | |
else: | |
return _node_from_result(element) | |
class VSPARQLStore(SPARQLUpdateStore): | |
def __init__(self, endpoint, username, password, **kwargs): | |
SPARQLUpdateStore.__init__(self, endpoint, endpoint, | |
node_to_sparql=_virtuoso_node_to_sparql, | |
node_from_result=_virtuoso_node_from_result, | |
**kwargs) | |
self.setHTTPAuth('digest') | |
self.setCredentials(username, password) | |
if __name__ == "__main__": | |
from rdflib import Namespace, Graph, Literal | |
from rdflib.collection import Collection | |
EX = Namespace('http://example.org/') | |
store = VSPARQLStore('http://localhost:8890/sparql-auth', 'dba', 'dba') | |
g = Graph(store, EX.g) | |
g.remove((None, None, None)) | |
print(len(g)) | |
bn = BNode() | |
g.add((EX.s, EX.pb, bn)) | |
g.add((bn, EX.pb, Literal("foo"))) | |
lh = BNode() | |
g.add((EX.s, EX.pl, lh)) | |
lst = Collection(g, lh, map(Literal, [1,2,3])) | |
print(len(g)) | |
print(g.serialize(format="turtle")) | |
g.remove((None, None, None)) |
... you seem to like living in the danger zone 😄
Monkeypatching obviously isn't that optimal, but to be honest i currently don't see a better way to do this (so being able to also configure BNode creation from a SPARQLStore in a way that doesn't have the potential to break things outside of it) ...
so, suggestions welcome, but till then 👍
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Ok, I found a way to get rid of the global mapping table (revision 2).
It involves an ugly hack (monkeypatching the default parameters of
BNode.__new__
), and is not 100% robust (it will break with BNodes created with an explicit ID, for example those generated by some parsers). So I have mixed feelings about it.