summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgromgull <devnull@localhost>2011-03-30 11:07:24 +0200
committergromgull <devnull@localhost>2011-03-30 11:07:24 +0200
commit22ccae3f77e3b5a0c5740d0c9d075a4566b62821 (patch)
tree62182982e7e932407baadf0a2d28ee55b650ed53
parent2484803b4efd2d248806c530bd08b80af7c6b3a0 (diff)
downloadrdflib-22ccae3f77e3b5a0c5740d0c9d075a4566b62821.tar.gz
query result cleanup patch
-rw-r--r--rdflib/plugin.py7
-rw-r--r--rdflib/query.py151
2 files changed, 149 insertions, 9 deletions
diff --git a/rdflib/plugin.py b/rdflib/plugin.py
index 713d8efc..1383cb1c 100644
--- a/rdflib/plugin.py
+++ b/rdflib/plugin.py
@@ -26,13 +26,16 @@ See the `setuptools dynamic discovery of services and plugins`__ for more inform
from rdflib.store import Store
from rdflib.parser import Parser
from rdflib.serializer import Serializer
-from rdflib import query
+from rdflib.query import ResultParser, ResultSerializer
from rdflib.exceptions import Error
entry_points = {'rdf.plugins.store': Store,
'rdf.plugins.serializer': Serializer,
- 'rdf.plugins.parser': Parser}
+ 'rdf.plugins.parser': Parser,
+ 'rdf.plugins.resultparser': ResultParser,
+ 'rdf.plugins.resultserializer': ResultSerializer,
+ }
_plugins = {}
diff --git a/rdflib/query.py b/rdflib/query.py
index f4b82002..6ac80e88 100644
--- a/rdflib/query.py
+++ b/rdflib/query.py
@@ -1,3 +1,14 @@
+
+import os
+import shutil
+import tempfile
+
+from urlparse import urlparse
+from io import BytesIO
+
+
+
+
"""
Query plugin interface.
@@ -16,17 +27,143 @@ class Processor(object):
def query(self, strOrQuery, initBindings={}, initNs={}, DEBUG=False):
pass
+class ResultException(Exception):
+ pass
+
+class EncodeOnlyUnicode(object):
+ """
+ This is a crappy work-around for
+ http://bugs.python.org/issue11649
+
+
+ """
+
+ def __init__(self, stream):
+ self.__stream=stream
+ def write(self, arg):
+ if isinstance(arg, unicode):
+ self.__stream.write(arg.encode("utf-8"))
+ else:
+ self.__stream.write(arg)
+ def __getattr__(self, name):
+ return getattr(self.__stream, name)
+
class Result(object):
"""
- A common class for representing query result in a variety of formats, namely:
+ A common class for representing query result.
+ This is backwards compatible with the old SPARQLResult objects
+ Like before there is a bit of magic that makes this appear like python objects, depending on the type of result.
- xml : as an XML string using the XML result format of the query language
- python: as Python objects
- json : as JSON
+ If the type is "SELECT", this is like a list of list of values
+ If the type is "ASK" this is like a list of a single bool
+ If the type is "CONSTRUCT" or "DESCRIBE" this is like a graph
+
"""
- def __init__(self, pythonResult):
- self.rt = pythonResult
+ def __init__(self, type_):
+
+ if type_ not in ('CONSTRUCT', 'DESCRIBE', 'SELECT', 'ASK'):
+ raise ResultException('Unknown Result type: %s'%type_)
+
+ self.type = type_
+ self.vars=None
+ self.bindings=None
+ self.askAnswer=None
+ self.graph=None
+
+ @staticmethod
+ def parse(source, format='xml'):
+ from rdflib import plugin
+ parser=plugin.get(format, ResultParser)()
+ return parser.parse(source)
- def serialize(self, format='xml'):
+
+ def serialize(self, destination=None, encoding="utf8", format='xml', **args):
+
+ if self.type in ('CONSTRUCT', 'DESCRIBE'):
+ return self.graph.serialize(destination, encoding=encoding, format=format, **args)
+
+ """stolen wholesale from graph.serialize"""
+ from rdflib import plugin
+ serializer=plugin.get(format, ResultSerializer)(self)
+ if destination is None:
+ stream = BytesIO()
+ stream2 = EncodeOnlyUnicode(stream)
+ serializer.serialize(stream2, encoding=encoding, **args)
+ return stream.getvalue()
+ if hasattr(destination, "write"):
+ stream = destination
+ serializer.serialize(stream, encoding=encoding, **args)
+ else:
+ location = destination
+ scheme, netloc, path, params, query, fragment = urlparse(location)
+ if netloc!="":
+ print("WARNING: not saving as location" + \
+ "is not a local file reference")
+ return
+ name = tempfile.mktemp()
+ stream = open(name, 'wb')
+ serializer.serialize(stream, encoding=encoding, **args)
+ stream.close()
+ if hasattr(shutil,"move"):
+ shutil.move(name, path)
+ else:
+ shutil.copy(name, path)
+ os.remove(name)
+
+
+ def __len__(self):
+ if self.type=='ASK': return 1
+ elif self.type=='SELECT': return len(self.bindings)
+ else:
+ return len(self.graph)
+
+ def __iter__(self):
+ if type in ("CONSTRUCT", "DESCRIBE"):
+ for t in self.graph: yield t
+ elif self.type=='ASK':
+ yield self.askAnswer
+ elif self.type=='SELECT':
+ # To remain compatible with the old SPARQLResult behaviour
+ # this iterates over lists of variable bindings
+ for b in self.bindings:
+ yield tuple([b[v] for v in self.vars])
+
+
+ def __getattr__(self,name):
+ if type in ("CONSTRUCT", "DESCRIBE") and self.graph!=None:
+ return self.graph.__getattr__(self,name)
+ else:
+ raise AttributeError("'%s' object has not attribute '%s'"%(self,name))
+
+ def __eq__(self, other):
+ try:
+ if self.type!=other.type: return False
+ if self.type=='ASK':
+ return self.askAnswer==other.askAnswer
+ elif self.type=='SELECT':
+ return self.vars==other.vars and self.bindings==other.bindings
+ else:
+ return self.graph==other.graph
+
+ except:
+ return False
+
+class ResultParser(object):
+
+ def __init__(self):
pass
+
+ def parse(self, source):
+ """return a Result object"""
+ pass # abstract
+
+class ResultSerializer(object):
+
+ def __init__(self, result):
+ self.result=result
+
+ def serialize(self, stream, encoding="utf-8"):
+ """return a string properly serialized"""
+ pass # abstract
+