Hi,
I have a number of patches that I applied to the code I'm working
with. Here is a list:
unescaped.patch: checks the for non-allowed characters in the RDF/XML parser
order_by.patch: support for simple ORDER BY (without function calls)
and for LIMIT
python_2_5.patch: makes it possible to use rdflib with python 2.5. It
is a quick fix, and might not be the correct way to solve things (see
__cmp__ in Literal and URIRef)
regex.patch: changes a simple typo for regex with three args
(regex(?name, "^ali", "i"))
sparql_optionals.patch: already mapped BNodes did not match any
bindings in the _bind method in sparql.py. It made the Optional.py
test-case to work correctly.
xml_output.patch: omits the namespace for elements (<sparql:result>
becomes <result>) and include line breaks and indentation.
I did not have any problems running this with the unit-tests. Hope
some of it can be of any use...:)
Cheers,
Mikael
Index: rdflib/sparql/bison/SPARQLEvaluate.py
===================================================================
--- rdflib/sparql/bison/SPARQLEvaluate.py (revision 866)
+++ rdflib/sparql/bison/SPARQLEvaluate.py (working copy)
@@ -17,7 +17,7 @@
from Util import ListRedirect
from Operators import *
from FunctionLibrary import *
-from SolutionModifier import DESCENDING_ORDER
+from SolutionModifier import ASCENDING_ORDER
from Query import AskQuery, SelectQuery
DEBUG = False
@@ -379,14 +379,23 @@
orderBy = []
orderAsc = []
for orderCond in query.query.solutionModifier.orderClause:
- expr = orderCond.expression.reduce()
- assert isinstance(expr,Variable),"Support for ORDER BY with anything other than a variable is not supported: %s"%expr
- orderBy.append(expr)
- orderAsc.append(orderCond.order == DESCENDING_ORDER)
+ # is it a variable?
+ if isinstance(orderCond,Variable):
+ orderBy.append(orderCond)
+ orderAsc.append(ASCENDING_ORDER)
+ # is it another expression, only variables are supported
+ else:
+ expr = orderCond.expression
+ assert isinstance(expr,Variable),"Support for ORDER BY with anything other than a variable is not supported: %s"%expr
+ orderBy.append(expr)
+ orderAsc.append(orderCond.order == ASCENDING_ORDER)
+
+ limit = query.query.solutionModifier.limitClause and int(query.query.solutionModifier.limitClause) or None
+
offset = query.query.solutionModifier.offsetClause and int(query.query.solutionModifier.offsetClause) or 0
return result.select(query.query.variables,
query.query.distinct,
- query.query.solutionModifier.limitClause,
+ limit,
orderBy,
orderAsc,
offset
Index: rdflib/Graph.py
===================================================================
--- rdflib/Graph.py (revision 866)
+++ rdflib/Graph.py (working copy)
@@ -1,3 +1,5 @@
+from __future__ import generators
+
__doc__="""
Instanciating Graphs with default store (IOMemory) and default identifier (a BNode):
@@ -144,7 +146,6 @@
"""
-from __future__ import generators
from cStringIO import StringIO
from rdflib import URIRef, BNode, Namespace, Literal, Variable
from rdflib import RDF, RDFS
Index: rdflib/Literal.py
===================================================================
--- rdflib/Literal.py (revision 866)
+++ rdflib/Literal.py (working copy)
@@ -137,11 +137,17 @@
s = super(Literal, self).__add__(val)
return Literal(s, self.language, self.datatype)
+ def __cmp__(self, other):
+ result = cmp(unicode(self), unicode(other))
+ if result == 0:
+ return self.__eq__(other)
+ return result
+
def __eq__(self, other):
if other==None:
return False
elif isinstance(other, Literal):
- result = self.__cmp__(other)==False
+ result = cmp(unicode(self), unicode(other)) == False
if result==True:
if self.datatype == None or self.datatype == '' :
if not(other.datatype == None or other.datatype == '') :
Index: rdflib/URIRef.py
===================================================================
--- rdflib/URIRef.py (revision 866)
+++ rdflib/URIRef.py (working copy)
@@ -14,7 +14,7 @@
class URIRef(Identifier):
__slots__ = ()
-
+
def __new__(cls, value, base=None):
if base is not None:
ends_in_hash = value.endswith("#")
@@ -60,6 +60,15 @@
else:
return self
+ def __cmp__(self, other):
+ return cmp(unicode(self), unicode(other))
+
+ def __eq__(self, other):
+ if isinstance(other, Literal):
+ return other.__eq__(self)
+
+ return unicode(self) == unicode(other)
+
def __reduce__(self):
return (URIRef, (unicode(self),))
Index: rdflib/sparql/bison/SPARQLEvaluate.py
===================================================================
--- rdflib/sparql/bison/SPARQLEvaluate.py (revision 866)
+++ rdflib/sparql/bison/SPARQLEvaluate.py (working copy)
@@ -149,7 +150,7 @@
elif isinstance(expr,ParsedREGEXInvocation):
return 'sparqlOperators.regex(%s,%s%s)%s'%(mapToOperator(expr.arg1,prolog,combinationArg),
mapToOperator(expr.arg2,prolog,combinationArg),
- expr.arg3 and ','+expr.arg3 or '',
+ expr.arg3 and ',"'+expr.arg3 + '"' or '',
combinationInvokation)
elif isinstance(expr,BuiltinFunctionCall):
normBuiltInName = FUNCTION_NAMES[expr.name].lower()
Index: rdflib/sparql/sparql.py
===================================================================
--- rdflib/sparql/sparql.py (revision 866)
+++ rdflib/sparql/sparql.py (working copy)
@@ -1144,8 +1175,6 @@
return None
else :
return self.bindings[r]
- elif isinstance(r,(BNode)):
- return self.bindings.get(r)
else :
return r
Index: rdflib/syntax/parsers/RDFXMLHandler.py
===================================================================
--- rdflib/syntax/parsers/RDFXMLHandler.py (revision 866)
+++ rdflib/syntax/parsers/RDFXMLHandler.py (working copy)
@@ -38,6 +38,7 @@
from xml.sax.saxutils import handler, quoteattr, escape
from urlparse import urljoin, urldefrag
+import re
RDFNS = RDF.RDFNS
@@ -206,11 +207,19 @@
# element handler
parent = property(get_parent)
+ def is_escaped_uri(self, uri):
+ esc_uri = re.compile(r'[\[\]\{}\|\^`<>" \\]')
+ find_esc = esc_uri.search(uri)
+ if find_esc != None:
+ self.error("URI character " + str(find_esc.end()) + " is not properly escaped")
+ return True
+
def absolutize(self, uri):
- result = urljoin(self.current.base, uri, allow_fragments=1)
- if uri and uri[-1]=="#" and result[-1]!="#":
- result = "%s#" % result
- return URIRef(result)
+ if self.is_escaped_uri(uri):
+ result = urljoin(self.current.base, uri, allow_fragments=1)
+ if uri and uri[-1]=="#" and result[-1]!="#":
+ result = "%s#" % result
+ return URIRef(result)
def convert(self, name, qname, attrs):
if name[0] is None:
Index: rdflib/sparql/QueryResult.py
===================================================================
--- rdflib/sparql/QueryResult.py (revision 866)
+++ rdflib/sparql/QueryResult.py (working copy)
@@ -11,14 +11,18 @@
writer = XMLGenerator(output, encoding)
writer.startDocument()
writer.startPrefixMapping(u'sparql',SPARQL_XML_NAMESPACE)
- writer.startPrefixMapping(u'xml' ,u'http://www.w3.org/XML/1998/namespace')
- writer.startElementNS((SPARQL_XML_NAMESPACE, u'sparql'), u'sparql', AttributesNSImpl({}, {}))
+ writer.startPrefixMapping(u'xml', u'http://www.w3.org/XML/1998/namespace')
+ writer.startElementNS((None, u'sparql'), u'', AttributesNSImpl({}, {}))
self.writer = writer
self._output = output
self._encoding = encoding
+ self._endline = "\n"
+ self._tab = "\t"
+ self._output.write(self._endline)
def write_header(self,allvarsL):
- self.writer.startElementNS((SPARQL_XML_NAMESPACE, u'head'), u'head', AttributesNSImpl({}, {}))
+ self.writer.startElementNS((None, u'head'), u'head', AttributesNSImpl({}, {}))
+ self._output.write(self._endline)
for i in xrange(0,len(allvarsL)) :
attr_vals = {
(None, u'name'): unicode(allvarsL[i][1:]),
@@ -26,11 +30,14 @@
attr_qnames = {
(None, u'name'): u'name',
}
- self.writer.startElementNS((SPARQL_XML_NAMESPACE, u'variable'),
+ self._output.write(self._tab)
+ self.writer.startElementNS((None, u'variable'),
u'variable',
AttributesNSImpl(attr_vals, attr_qnames))
- self.writer.endElementNS((SPARQL_XML_NAMESPACE, u'variable'), u'variable')
- self.writer.endElementNS((SPARQL_XML_NAMESPACE, u'head'), u'head')
+ self.writer.endElementNS((None, u'variable'), u'variable')
+ self._output.write(self._endline)
+ self.writer.endElementNS((None, u'head'), u'head')
+ self._output.write(self._endline)
def write_results_header(self,orderBy,distinct):
attr_vals = {
@@ -41,35 +48,51 @@
(None, u'ordered') : u'ordered',
(None, u'distinct') : u'distinct'
}
- self.writer.startElementNS((SPARQL_XML_NAMESPACE, u'results'),
+ self.writer.startElementNS((None, u'results'),
u'results',
AttributesNSImpl(attr_vals, attr_qnames))
+ self._output.write(self._endline)
+
+ def write_start_result(self):
+ self._output.write(self._tab)
+ self.writer.startElementNS((None, u'result'), u'result', AttributesNSImpl({}, {}))
+ self._output.write(self._endline)
- def write_result(self,name,val):
+ def write_end_result(self):
+ self._output.write(self._tab)
+ self.writer.endElementNS((None, u'result'), u'result')
+ self._output.write(self._endline)
+
+ def write_binding(self,name,val):
if val:
- self.writer.startElementNS((SPARQL_XML_NAMESPACE, u'result'), u'result', AttributesNSImpl({}, {}))
attr_vals = {
(None, u'name') : unicode(name),
}
attr_qnames = {
(None, u'name') : u'name',
}
- self.writer.startElementNS((SPARQL_XML_NAMESPACE, u'binding'),
+ self._output.write(self._tab*2)
+ self.writer.startElementNS((None, u'binding'),
u'binding',
AttributesNSImpl(attr_vals, attr_qnames))
+ self._output.write(self._endline)
if isinstance(val,URIRef) :
- self.writer.startElementNS((SPARQL_XML_NAMESPACE, u'uri'),
+ self._output.write(self._tab*3)
+ self.writer.startElementNS((None, u'uri'),
u'uri',
AttributesNSImpl(attr_vals, attr_qnames))
self.writer.characters(val)
- self.writer.endElementNS((SPARQL_XML_NAMESPACE, u'uri'),u'uri')
+ self.writer.endElementNS((None, u'uri'),u'uri')
+ self._output.write(self._endline)
elif isinstance(val,BNode) :
- self.writer.startElementNS((SPARQL_XML_NAMESPACE, u'bnode'),
+ self._output.write(self._tab*3)
+ self.writer.startElementNS((None, u'bnode'),
u'bnode',
AttributesNSImpl(attr_vals, attr_qnames))
self.writer.characters(val)
- self.writer.endElementNS((SPARQL_XML_NAMESPACE, u'bnode'),u'bnode')
+ self.writer.endElementNS((None, u'bnode'),u'bnode')
+ self._output.write(self._endline)
elif isinstance(val,Literal) :
attr_vals = {}
attr_qnames = {}
@@ -80,21 +103,26 @@
attr_vals[(None,u'datatype')] = val.datatype
attr_qnames[(None,u'datatype')] = u'datatype'
- self.writer.startElementNS((SPARQL_XML_NAMESPACE, u'literal'),
+ self._output.write(self._tab*3)
+ self.writer.startElementNS((None, u'literal'),
u'literal',
AttributesNSImpl(attr_vals, attr_qnames))
self.writer.characters(val)
- self.writer.endElementNS((SPARQL_XML_NAMESPACE, u'literal'),u'literal')
+ self.writer.endElementNS((None, u'literal'),u'literal')
+ self._output.write(self._endline)
else:
raise Exception("Unsupported RDF term: %s"%val)
- self.writer.endElementNS((SPARQL_XML_NAMESPACE, u'binding'),u'binding')
- self.writer.endElementNS((SPARQL_XML_NAMESPACE, u'result'), u'result')
+ self._output.write(self._tab*2)
+ self.writer.endElementNS((None, u'binding'),u'binding')
+ self._output.write(self._endline)
def close(self):
- self.writer.endElementNS((SPARQL_XML_NAMESPACE, u'results'), u'results')
- self.writer.endElementNS((SPARQL_XML_NAMESPACE, u'sparql'), u'sparql')
+ self.writer.endElementNS((None, u'results'), u'results')
+ self._output.write(self._endline)
+ self.writer.endElementNS((None, u'sparql'), u'sparql')
+ self._output.write(self._endline)
self.writer.endDocument()
def retToJSON(val) :
@@ -219,16 +247,19 @@
writer.write_results_header(self.orderBy,self.distinct)
for i in xrange(0,len(self.selected)) :
hit = self.selected[i]
+ writer.write_start_result()
if len(self.selectionF) == 0 :
for j in xrange(0,len(allvarsL)) :
- writer.write_result(allvarsL[j][1:],hit[j])
+ writer.write_binding(allvarsL[j][1:],hit[j])
elif len(self.selectionF) == 1 :
- writer.write_result(self.selectionF[0][1:],hit)
+ writer.write_binding(self.selectionF[0][1:],hit)
else:
+
for j in xrange(0,len(self.selectionF)) :
- writer.write_result(self.selectionF[j][1:],hit[j])
+ writer.write_binding(self.selectionF[j][1:],hit[j])
+ writer.write_end_result()
writer.close()
return out.getvalue()
return retval
else :
- raise Exception("Result format not implemented: %s"%format)
\ No newline at end of file
+ raise Exception("Result format not implemented: %s"%format)
from rdflib import ConjunctiveGraph, plugin
from rdflib.store import Store
from StringIO import StringIO
import unittest
test_data = """
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
_:a rdf:type foaf:Person .
_:a foaf:name "Alice" .
_:a foaf:mbox <mailto:[EMAIL PROTECTED]> .
_:a foaf:mbox <mailto:[EMAIL PROTECTED]> .
_:b rdf:type foaf:Person .
_:b foaf:name "Bob" .
"""
class OptionalTest(unittest.TestCase):
def _query(self, query):
graph = ConjunctiveGraph(plugin.get('IOMemory',Store)())
graph.parse(StringIO(test_data), format="n3")
return graph.query(query)
def testOptional(self):
correct = set([('Alice', 'mailto:[EMAIL PROTECTED]'), ('Alice', 'mailto:[EMAIL PROTECTED]'), ('Bob', 'None')])
test_query = """
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name ?mbox
WHERE { ?x foaf:name ?name .
OPTIONAL { ?x foaf:mbox ?mbox }
}
"""
res = self._query(test_query)
# print "\n", [(str(n), str(m)) for (n,m) in res]
self.assertEqual(set([(str(name), str(mail)) for (name, mail) in res]), correct)
def main():
unittest.main()
if __name__ == '__main__':
main()
_______________________________________________
Dev mailing list
[email protected]
http://rdflib.net/mailman/listinfo/dev