diff options
| author | gromgull <devnull@localhost> | 2011-03-30 11:07:24 +0200 |
|---|---|---|
| committer | gromgull <devnull@localhost> | 2011-03-30 11:07:24 +0200 |
| commit | 22ccae3f77e3b5a0c5740d0c9d075a4566b62821 (patch) | |
| tree | 62182982e7e932407baadf0a2d28ee55b650ed53 | |
| parent | 2484803b4efd2d248806c530bd08b80af7c6b3a0 (diff) | |
| download | rdflib-22ccae3f77e3b5a0c5740d0c9d075a4566b62821.tar.gz | |
query result cleanup patch
| -rw-r--r-- | rdflib/plugin.py | 7 | ||||
| -rw-r--r-- | rdflib/query.py | 151 |
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 + |
