SPARQLWrapper-1.6.4/ 0000755 0001750 0001750 00000000000 12377101654 014675 5 ustar sergio sergio 0000000 0000000 SPARQLWrapper-1.6.4/test/ 0000755 0001750 0001750 00000000000 12377101654 015654 5 ustar sergio sergio 0000000 0000000 SPARQLWrapper-1.6.4/test/wrapper_test.py 0000644 0001750 0001750 00000046131 12377047077 020762 0 ustar sergio sergio 0000000 0000000 # -*- coding: utf-8 -*-
import inspect
import os
import sys
import logging
logging.basicConfig()
import unittest
from urlparse import urlparse
from urllib2 import Request
from cgi import parse_qs
# prefer local copy to the one which is installed
# hack from http://stackoverflow.com/a/6098238/280539
_top_level_path = os.path.realpath(os.path.abspath(os.path.join(
os.path.split(inspect.getfile(inspect.currentframe()))[0],
".."
)))
if _top_level_path not in sys.path:
sys.path.insert(0, _top_level_path)
# end of hack
from SPARQLWrapper import SPARQLWrapper
from SPARQLWrapper import XML, GET, POST, JSON, JSONLD, N3, TURTLE, RDF, SELECT, INSERT
from SPARQLWrapper import URLENCODED, POSTDIRECTLY
from SPARQLWrapper.Wrapper import QueryResult, QueryBadFormed, EndPointNotFound, EndPointInternalError
# we don't want to let Wrapper do real web-requests. so, we are…
# constructing a simple Mock!
from urllib2 import HTTPError
from io import StringIO
import warnings
import SPARQLWrapper.Wrapper as _victim
class FakeResult(object):
def __init__(self, request):
self.request = request
def urlopener(request):
return FakeResult(request)
def urlopener_error_generator(code):
def urlopener_error(request):
raise HTTPError(request.get_full_url, code, '', {}, StringIO(u''))
return urlopener_error
def urlopener_check_data_encoding(request):
if sys.version < '3': # have to write it like this, for 2to3 compatibility
if isinstance(request.data, unicode):
raise TypeError
else:
if isinstance(request.data, str):
raise TypeError
# DONE
class SPARQLWrapper_Test(unittest.TestCase):
@staticmethod
def _get_request(wrapper):
request = wrapper.query().response.request # possible due to mock above
return request
@staticmethod
def _get_parameters_from_request(request):
if request.get_method() == 'GET':
pieces_str = urlparse(request.get_full_url()).query
else:
if sys.version < '3':
pieces_str = request.data
else:
pieces_str = request.data.decode('ascii')
return parse_qs(pieces_str)
@staticmethod
def _get_request_parameters(wrapper):
request = SPARQLWrapper_Test._get_request(wrapper)
parameters = SPARQLWrapper_Test._get_parameters_from_request(request)
return parameters
@staticmethod
def _get_request_parameters_as_bytes(wrapper):
request = SPARQLWrapper_Test._get_request(wrapper)
parameters = SPARQLWrapper_Test._get_parameters_from_request(request)
if sys.version < '3':
return parameters
else:
result = {}
for k,vs in parameters.iteritems():
result[k] = [v.encode('utf-8') for v in vs]
return result
def setUp(self):
self.wrapper = SPARQLWrapper(endpoint='http://example.org/sparql')
_victim.urlopener = urlopener
def testConstructor(self):
try:
SPARQLWrapper()
self.fail("SPARQLWrapper constructor should fail without arguments")
except TypeError:
pass
wrapper = SPARQLWrapper(endpoint='http://example.org/sparql/')
self.assertEqual(XML, wrapper.returnFormat, 'default return format is XML')
self.assertTrue(
wrapper.agent.startswith('sparqlwrapper'),
'default user-agent should start with "sparqlwrapper"'
)
wrapper = SPARQLWrapper(endpoint='http://example.org/sparql/', returnFormat='wrongformat')
self.assertEqual(XML, wrapper.returnFormat, 'default return format is XML')
wrapper = SPARQLWrapper(endpoint='http://example.org/sparql/', defaultGraph='http://example.org/default')
parameters = self._get_request_parameters(wrapper)
self.assertEqual(
['http://example.org/default'],
parameters.get('default-graph-uri'),
'default graph is set'
)
def testReset(self):
self.wrapper.setMethod(POST)
self.wrapper.setQuery('CONSTRUCT WHERE {?a ?b ?c}')
self.wrapper.setReturnFormat(N3)
self.wrapper.addParameter('a', 'b')
request = self._get_request(self.wrapper)
parameters = self._get_parameters_from_request(request)
self.assertEqual('POST', request.get_method())
self.assertTrue(parameters['query'][0].startswith('CONSTRUCT'))
self.assertTrue('rdf+n3' in request.get_header('Accept'))
self.assertTrue('a' in parameters)
self.wrapper.resetQuery()
request = self._get_request(self.wrapper)
parameters = self._get_parameters_from_request(request)
self.assertEqual('GET', request.get_method())
self.assertTrue(parameters['query'][0].startswith('SELECT'))
self.assertFalse('rdf+n3' in request.get_header('Accept'))
self.assertTrue('sparql-results+xml' in request.get_header('Accept'))
self.assertFalse('a' in parameters)
def testSetReturnFormat(self):
self.assertRaises(ValueError, self.wrapper.setReturnFormat, 'nonexistent format')
self.assertEqual(XML, self.wrapper.query().requestedFormat)
self.wrapper.setReturnFormat(JSON)
self.assertEqual(JSON, self.wrapper.query().requestedFormat)
try:
import rdflib_jsonld
self.wrapper.setReturnFormat(JSONLD)
self.assertEqual(JSONLD, self.wrapper.query().requestedFormat)
except ImportError:
self.assertRaises(ValueError, self.wrapper.setReturnFormat, JSONLD)
def testsSupportsReturnFormat(self):
self.assertTrue(self.wrapper.supportsReturnFormat(XML))
self.assertTrue(self.wrapper.supportsReturnFormat(JSON))
self.assertTrue(self.wrapper.supportsReturnFormat(TURTLE))
self.assertTrue(self.wrapper.supportsReturnFormat(N3))
self.assertTrue(self.wrapper.supportsReturnFormat(RDF))
self.assertFalse(self.wrapper.supportsReturnFormat('nonexistent format'))
try:
import rdflib_jsonld
self.assertTrue(self.wrapper.supportsReturnFormat(JSONLD))
except ImportError:
self.assertFalse(self.wrapper.supportsReturnFormat(JSONLD))
def testAddParameter(self):
self.assertFalse(self.wrapper.addParameter('query', 'dummy'))
self.assertTrue(self.wrapper.addParameter('param1', 'value1'))
self.assertTrue(self.wrapper.addParameter('param1', 'value2'))
self.assertTrue(self.wrapper.addParameter('param2', 'value2'))
pieces = self._get_request_parameters(self.wrapper)
self.assertTrue('param1' in pieces)
self.assertEqual(['value1', 'value2'], pieces['param1'])
self.assertTrue('param2' in pieces)
self.assertEqual(['value2'], pieces['param2'])
self.assertNotEqual(['dummy'], 'query')
def testSetCredentials(self):
request = self._get_request(self.wrapper)
self.assertFalse(request.has_header('Authorization'))
self.wrapper.setCredentials('login', 'password')
request = self._get_request(self.wrapper)
self.assertTrue(request.has_header('Authorization'))
# TODO: test for header-value using some external decoder implementation
def testSetQuery(self):
self.wrapper.setQuery('PREFIX example: SELECT * WHERE {?s ?p ?v}')
self.assertEqual(SELECT, self.wrapper.queryType)
self.wrapper.setQuery('PREFIX e: INSERT {e:a e:b e:c}')
self.assertEqual(INSERT, self.wrapper.queryType)
self.wrapper.setQuery("""#CONSTRUCT {?s ?p ?o}
SELECT ?s ?p ?o
WHERE {?s ?p ?o}""")
self.assertEqual(SELECT, self.wrapper.queryType)
with warnings.catch_warnings(record=True) as w:
self.wrapper.setQuery('UNKNOWN {e:a e:b e:c}')
self.assertEqual(SELECT, self.wrapper.queryType, 'unknown queries result in SELECT')
def testSetQueryEncodingIssues(self):
#further details from issue #35
query = u'INSERT DATA { "これはテストです" }'
query_bytes = query.encode('utf-8')
self.wrapper.setMethod(POST)
self.wrapper.setRequestMethod(POSTDIRECTLY)
self.wrapper.setQuery(query)
request = self._get_request(self.wrapper)
self.assertEquals(query_bytes, request.data)
self.wrapper.setQuery(query_bytes)
request = self._get_request(self.wrapper)
self.assertEquals(query_bytes, request.data)
self.wrapper.setRequestMethod(URLENCODED)
self.wrapper.setQuery(query)
parameters = self._get_request_parameters_as_bytes(self.wrapper)
self.assertEquals(query_bytes, parameters['update'][0])
self.wrapper.setQuery(query_bytes)
parameters = self._get_request_parameters_as_bytes(self.wrapper)
self.assertEquals(query_bytes, parameters['update'][0])
try:
self.wrapper.setQuery(query.encode('sjis'))
self.fail()
except UnicodeDecodeError:
self.assertTrue(True)
try:
self.wrapper.setQuery({'foo': 'bar'})
self.fail()
except TypeError:
self.assertTrue(True)
def testSetTimeout(self):
self.wrapper.setTimeout(10)
self.assertEqual(10, self.wrapper.timeout)
self.wrapper.resetQuery()
self.assertEqual(None, self.wrapper.timeout)
def testClearParameter(self):
self.wrapper.addParameter('param1', 'value1')
self.wrapper.addParameter('param1', 'value2')
self.wrapper.addParameter('param2', 'value2')
self.assertFalse(self.wrapper.clearParameter('query'))
self.assertTrue(self.wrapper.clearParameter('param1'))
pieces = self._get_request_parameters(self.wrapper)
self.assertFalse('param1' in pieces)
self.assertTrue('param2' in pieces)
self.assertEqual(['value2'], pieces['param2'])
self.assertFalse(self.wrapper.clearParameter('param1'), 'already cleaned')
def testSetMethod(self):
self.wrapper.setMethod(POST)
request = self._get_request(self.wrapper)
self.assertEqual("POST", request.get_method())
self.wrapper.setMethod(GET)
request = self._get_request(self.wrapper)
self.assertEqual("GET", request.get_method())
def testSetRequestMethod(self):
self.assertEqual(URLENCODED, self.wrapper.requestMethod)
self.wrapper.setRequestMethod(POSTDIRECTLY)
self.assertEqual(POSTDIRECTLY, self.wrapper.requestMethod)
def testIsSparqlUpdateRequest(self):
self.wrapper.setQuery('DELETE WHERE {?s ?p ?o}')
self.assertTrue(self.wrapper.isSparqlUpdateRequest())
self.wrapper.setQuery('DELETE DATA { }')
self.assertTrue(self.wrapper.isSparqlUpdateRequest())
self.wrapper.setQuery("""
PREFIX example:
BASE
DELETE WHERE {?s ?p ?o}
""")
self.assertTrue(self.wrapper.isSparqlUpdateRequest())
self.wrapper.setQuery('WITH DELETE DATA { }')
self.assertTrue(self.wrapper.isSparqlUpdateRequest())
self.wrapper.setQuery('INSERT DATA { }')
self.assertTrue(self.wrapper.isSparqlUpdateRequest())
self.wrapper.setQuery('WITH INSERT DATA { }')
self.assertTrue(self.wrapper.isSparqlUpdateRequest())
self.wrapper.setQuery('CREATE GRAPH ')
self.assertTrue(self.wrapper.isSparqlUpdateRequest())
self.wrapper.setQuery('CLEAR GRAPH ')
self.assertTrue(self.wrapper.isSparqlUpdateRequest())
self.wrapper.setQuery('DROP GRAPH ')
self.assertTrue(self.wrapper.isSparqlUpdateRequest())
self.wrapper.setQuery('MOVE GRAPH TO GRAPH ')
self.assertTrue(self.wrapper.isSparqlUpdateRequest())
self.wrapper.setQuery('LOAD INTO GRAPH ')
self.assertTrue(self.wrapper.isSparqlUpdateRequest())
self.wrapper.setQuery('COPY TO GRAPH ')
self.assertTrue(self.wrapper.isSparqlUpdateRequest())
self.wrapper.setQuery('ADD TO GRAPH ')
self.assertTrue(self.wrapper.isSparqlUpdateRequest())
def testIsSparqlQueryRequest(self):
self.wrapper.setQuery('SELECT * WHERE {?s ?p ?o}')
self.assertTrue(self.wrapper.isSparqlQueryRequest())
self.wrapper.setQuery("""
PREFIX example:
BASE
ASK WHERE {?s ?p ?o}
""")
self.assertTrue(self.wrapper.isSparqlQueryRequest())
self.assertFalse(self.wrapper.isSparqlUpdateRequest())
def testQuery(self):
qr = self.wrapper.query()
self.assertTrue(isinstance(qr, QueryResult))
request = qr.response.request # possible due to mock above
self.assertTrue(isinstance(request, Request))
parameters = self._get_parameters_from_request(request)
self.assertTrue('query' in parameters)
self.assertTrue('update' not in parameters)
self.wrapper.setMethod(POST)
self.wrapper.setQuery('PREFIX e: INSERT {e:a e:b e:c}')
parameters = self._get_request_parameters(self.wrapper)
self.assertTrue('update' in parameters)
self.assertTrue('query' not in parameters)
_victim.urlopener = urlopener_error_generator(400)
try:
self.wrapper.query()
self.fail('should have raised exception')
except QueryBadFormed as e:
# TODO: check exception-format
pass
except:
self.fail('got wrong exception')
_victim.urlopener = urlopener_error_generator(404)
try:
self.wrapper.query()
self.fail('should have raised exception')
except EndPointNotFound as e:
# TODO: check exception-format
pass
except:
self.fail('got wrong exception')
_victim.urlopener = urlopener_error_generator(500)
try:
self.wrapper.query()
self.fail('should have raised exception')
except EndPointInternalError as e:
# TODO: check exception-format
pass
except:
self.fail('got wrong exception')
_victim.urlopener = urlopener_error_generator(999)
try:
self.wrapper.query()
self.fail('should have raised exception')
except HTTPError as e:
# TODO: check exception-format
pass
except:
self.fail('got wrong exception')
def testQueryEncoding(self):
query = 'INSERT DATA { "é" }'
wrapper = SPARQLWrapper('http://example.com:3030/example')
wrapper.setMethod(POST)
wrapper.setRequestMethod(URLENCODED)
wrapper.setQuery(query)
_victim.urlopener = urlopener_check_data_encoding
wrapper.query()
def testQueryAndConvert(self):
_oldQueryResult = _victim.QueryResult
class FakeQueryResult(object):
def __init__(self, result):
pass
def convert(self):
return True
try:
_victim.QueryResult = FakeQueryResult
result = self.wrapper.queryAndConvert()
self.assertEqual(True, result)
finally:
_victim.QueryResult = _oldQueryResult
class QueryResult_Test(unittest.TestCase):
def testConstructor(self):
qr = QueryResult('result')
self.assertEqual('result', qr.response)
try:
format = qr.requestedFormat
self.fail('format is not supposed to be set')
except:
pass
qr = QueryResult(('result', 'format'))
self.assertEqual('result', qr.response)
self.assertEqual('format', qr.requestedFormat)
def testProxyingToResponse(self):
class FakeResponse(object):
def __init__(self):
self.geturl_called = False
self.info_called = False
self.iter_called = False
self.next_called = False
def geturl(self):
self.geturl_called = True
def info(self):
self.info_called = True
return {"key": "value"}
def __iter__(self):
self.iter_called = True
def next(self):
self.next_called = True
result = FakeResponse()
qr = QueryResult(result)
qr.geturl()
qr.__iter__()
qr.next()
self.assertTrue(result.geturl_called)
self.assertTrue(result.iter_called)
self.assertTrue(result.next_called)
info = qr.info()
self.assertTrue(result.info_called)
self.assertEqual('value', info.__getitem__('KEY'), 'keys should be case-insensitive')
def testConvert(self):
class FakeResponse(object):
def __init__(self, content_type):
self.content_type = content_type
def info(self):
return {"Content-type": self.content_type}
def read(self, len):
return ''
def _mime_vs_type(mime, requested_type):
"""
@param mime:
@param requested_type:
@return: number of warnings produced by combo
"""
with warnings.catch_warnings(record=True) as w:
qr = QueryResult((FakeResponse(mime), requested_type))
try:
qr.convert()
except:
pass
return len(w)
self.assertEqual(0, _mime_vs_type("application/sparql-results+xml", XML))
self.assertEqual(0, _mime_vs_type("application/sparql-results+json", JSON))
self.assertEqual(0, _mime_vs_type("text/n3", N3))
self.assertEqual(0, _mime_vs_type("text/turtle", TURTLE))
self.assertEqual(0, _mime_vs_type("application/ld+json", JSON))
self.assertEqual(0, _mime_vs_type("application/ld+json", JSONLD))
self.assertEqual(0, _mime_vs_type("application/rdf+xml", XML))
self.assertEqual(0, _mime_vs_type("application/rdf+xml", RDF))
self.assertEqual(1, _mime_vs_type("application/x-foo-bar", XML), "invalid mime")
self.assertEqual(1, _mime_vs_type("application/sparql-results+xml", N3))
self.assertEqual(1, _mime_vs_type("application/sparql-results+json", XML))
self.assertEqual(1, _mime_vs_type("text/n3", JSON))
self.assertEqual(1, _mime_vs_type("text/turtle", XML))
self.assertEqual(1, _mime_vs_type("application/ld+json", XML))
self.assertEqual(1, _mime_vs_type("application/ld+json", N3))
self.assertEqual(1, _mime_vs_type("application/rdf+xml", JSON))
self.assertEqual(1, _mime_vs_type("application/rdf+xml", N3))
if __name__ == "__main__":
unittest.main()
SPARQLWrapper-1.6.4/test/dbpedia.py 0000755 0001750 0001750 00000022760 12377047077 017640 0 ustar sergio sergio 0000000 0000000 # -*- coding: utf8 -*-
#!/usr/bin/python
import inspect
import os
import sys
# prefer local copy to the one which is installed
# hack from http://stackoverflow.com/a/6098238/280539
_top_level_path = os.path.realpath(os.path.abspath(os.path.join(
os.path.split(inspect.getfile(inspect.currentframe()))[0],
".."
)))
if _top_level_path not in sys.path:
sys.path.insert(0, _top_level_path)
# end of hack
import unittest
try:
from rdflib.graph import ConjunctiveGraph
except ImportError:
from rdflib import ConjunctiveGraph
from SPARQLWrapper import SPARQLWrapper, XML, N3, JSONLD, JSON, POST, GET, SELECT, CONSTRUCT, ASK, DESCRIBE
from SPARQLWrapper.Wrapper import _SPARQL_DEFAULT, _SPARQL_XML, _SPARQL_JSON, _SPARQL_POSSIBLE, _RDF_XML, _RDF_N3, _RDF_JSONLD, _RDF_POSSIBLE
from SPARQLWrapper.SPARQLExceptions import QueryBadFormed
try:
from urllib.error import HTTPError # Python 3
except ImportError:
from urllib2 import HTTPError # Python 2
try:
bytes # Python 2.6 and above
except NameError:
bytes = str
import logging
logging.basicConfig()
endpoint = "http://dbpedia.org/sparql"
prefixes = """
PREFIX rdf:
PREFIX rdfs:
"""
selectQuery = """
SELECT ?label
WHERE {
rdfs:label ?label .
}
"""
constructQuery = """
CONSTRUCT {
_:v rdfs:label ?label .
_:v rdfs:comment "this is only a mock node to test library"
}
WHERE {
rdfs:label ?label .
}
"""
queryBadFormed = """
PREFIX prop:
PREFIX res:
FROM
SELECT ?lat ?long
WHERE {
res:Budapest prop:latitude ?lat;
prop:longitude ?long.
}
"""
queryManyPrefixes = """
PREFIX conf:
PREFIX meta:
PREFIX rdf:
PREFIX rdfs:
PREFIX xsd:
PREFIX owl:
PREFIX dc:
PREFIX dcterms:
PREFIX foaf:
PREFIX skos:
PREFIX geo:
PREFIX dbpedia:
PREFIX o:
PREFIX p:
PREFIX yago:
PREFIX units:
PREFIX geonames:
PREFIX prv:
PREFIX prvTypes:
PREFIX foo:
SELECT ?label
WHERE {
rdfs:label ?label .
}
"""
class SPARQLWrapperTests(unittest.TestCase):
def __generic(self, query, returnFormat, method):
sparql = SPARQLWrapper(endpoint)
sparql.setQuery(prefixes + query)
sparql.setReturnFormat(returnFormat)
sparql.setMethod(method)
try:
result = sparql.query()
except HTTPError:
# An ugly way to get the exception, but the only one that works
# both on Python 2.5 and Python 3.
e = sys.exc_info()[1]
if e.code == 400:
sys.stdout.write("400 Bad Request, probably query is not well formed")
elif e.code == 406:
sys.stdout.write("406 Not Acceptable, maybe query is not well formed")
else:
sys.stdout.write(str(e))
sys.stdout.write("\n")
return False
else:
return result
def testSelectByGETinXML(self):
result = self.__generic(selectQuery, XML, GET)
ct = result.info()["content-type"]
assert True in [one in ct for one in _SPARQL_XML], ct
results = result.convert()
results.toxml()
def testSelectByPOSTinXML(self):
result = self.__generic(selectQuery, XML, POST)
ct = result.info()["content-type"]
assert True in [one in ct for one in _SPARQL_XML], ct
results = result.convert()
results.toxml()
# Virtuoso returns text/rdf+n3. It MUST return SPARQL Results Document in XML (sparql-results+xml), JSON (sparql-results+json), or CSV/TSV (text/csv or text/tab-separated-values) see http://www.w3.org/TR/sparql11-protocol/#query-success
# URI generated http://dbpedia.org/sparql?query=%0A++++PREFIX+rdf%3A+%3Chttp%3A%2F%2Fwww.w3.org%2F1999%2F02%2F22-rdf-syntax-ns%23%3E%0A++++PREFIX+rdfs%3A+%3Chttp%3A%2F%2Fwww.w3.org%2F2000%2F01%2Frdf-schema%23%3E%0A%0A++++SELECT+%3Flabel%0A++++WHERE+%7B%0A++++%3Chttp%3A%2F%2Fdbpedia.org%2Fresource%2FAsturias%3E+rdfs%3Alabel+%3Flabel+.%0A++++%7D%0A
def _testSelectByGETinN3(self):
result = self.__generic(selectQuery, N3, GET)
ct = result.info()["content-type"]
assert True in [one in ct for one in _SPARQL_XML], ct
assert True in [one in ct for one in _SPARQL_POSSIBLE], ct
results = result.convert()
self.assertEqual(type(results), bytes)
def testSelectByGETinJSON(self):
result = self.__generic(selectQuery, JSON, GET)
ct = result.info()["content-type"]
assert True in [one in ct for one in _SPARQL_JSON], ct
results = result.convert()
self.assertEqual(type(results), dict)
def testSelectByPOSTinJSON(self):
result = self.__generic(selectQuery, JSON, POST)
ct = result.info()["content-type"]
assert True in [one in ct for one in _SPARQL_JSON], ct
results = result.convert()
self.assertEqual(type(results), dict)
def testSelectByGETinUnknow(self):
result = self.__generic(selectQuery, "foo", GET)
ct = result.info()["content-type"]
assert True in [one in ct for one in _SPARQL_POSSIBLE], ct
results = result.convert()
def testSelectByPOSTinUnknow(self):
result = self.__generic(selectQuery, "bar", POST)
ct = result.info()["content-type"]
assert True in [one in ct for one in _SPARQL_POSSIBLE], ct
results = result.convert()
def testConstructByGETinXML(self):
result = self.__generic(constructQuery, XML, GET)
ct = result.info()["content-type"]
assert True in [one in ct for one in _RDF_XML], ct
results = result.convert()
self.assertEqual(type(results), ConjunctiveGraph)
def testConstructByPOSTinXML(self):
result = self.__generic(constructQuery, XML, POST)
ct = result.info()["content-type"]
assert True in [one in ct for one in _RDF_XML], ct
results = result.convert()
self.assertEqual(type(results), ConjunctiveGraph)
def testConstructByGETinN3(self):
result = self.__generic(constructQuery, N3, GET)
ct = result.info()["content-type"]
assert True in [one in ct for one in _RDF_N3], ct
results = result.convert()
self.assertEqual(type(results), bytes)
def testConstructByPOSTinN3(self):
result = self.__generic(constructQuery, N3, POST)
ct = result.info()["content-type"]
assert True in [one in ct for one in _RDF_N3], ct
results = result.convert()
self.assertEqual(type(results), bytes)
# Virtuoso returns application/sparql-results+json. It MUST return an RDF graph [RDF-CONCEPTS] serialized, for example, in the RDF/XML syntax [RDF-XML], or an equivalent RDF graph serialization, for SPARQL Query forms DESCRIBE and CONSTRUCT). See http://www.w3.org/TR/sparql11-protocol/#query-success
def _testConstructByGETinJSON(self):
result = self.__generic(constructQuery, JSON, GET)
ct = result.info()["content-type"]
assert True in [one in ct for one in _RDF_POSSIBLE], ct
results = result.convert()
self.assertEqual(type(results), ConjunctiveGraph)
def _testConstructByPOSTinJSON(self):
result = self.__generic(constructQuery, _RDF_JSONLD, POST)
ct = result.info()["content-type"]
assert True in [one in ct for one in _RDF_POSSIBLE], ct
results = result.convert()
self.assertEqual(type(results), bytes)
def testConstructByGETinUnknow(self):
result = self.__generic(constructQuery, "foo", GET)
ct = result.info()["content-type"]
assert True in [one in ct for one in _RDF_POSSIBLE], ct
results = result.convert()
self.assertEqual(type(results), ConjunctiveGraph)
def testConstructByPOSTinUnknow(self):
result = self.__generic(constructQuery, "bar", POST)
ct = result.info()["content-type"]
assert True in [one in ct for one in _RDF_POSSIBLE], ct
results = result.convert()
self.assertEqual(type(results), ConjunctiveGraph)
def testQueryBadFormed(self):
self.assertRaises(QueryBadFormed, self.__generic, queryBadFormed, XML, GET)
# def testQueryManyPrefixes(self):
# result = self.__generic(queryManyPrefixes, XML, GET)
if __name__ == "__main__":
unittest.main()
SPARQLWrapper-1.6.4/AUTHORS.md 0000644 0001750 0001750 00000002476 12377071420 016352 0 ustar sergio sergio 0000000 0000000 # Authors
* Ivan Herman ([@iherman](http://github.com/iherman))
* Sergio Fernández ([@wikier](http://github.com/wikier))
* Carlos Tejo ([@dayures](http://github.com/dayures))
* Alexey Zakhlestin ([@indeyets](http://github.com/indeyets))
# Contributors
* Obey Arthur Liu ([@ArthurLiu](http://github.com/ArthurLiu)): different patches
* Christopher Lenz ([@cmlenz](http://github.com/cmlenz)): feature to allow developers to choose the json module
* Pēteris Caune ([@cuu508](http://github.com/cuu508)): great feedback and patches
* Bogdan Benea ([bugdone@users.sourceforge.net](mailto:bugdone@users.sourceforge.net)), patch for the query regular expresion
* William Waites ([@wwaites](http://github.com/wwaites)): patches for RDFLib3
* Christoph Burgmer ([@cburgmer](http://github.com/cburgmer)): patches for RDFLib3
* Thomas Kluyver ([@takluyver](http://github.com/takluyver)): patches for Python 3.x
* Diego Berrueta ([@berrueta](http://github.com/berrueta)): new function for printing results as table
* Olivier Berger ([@olberger](http://github.com/olberger)): patch regarding raw response for unknown formats
* Benjamin Cogrel ([@bcogrel](http://github.com/bcogrel)): standard query types
* Urs Holzer ([@uholzer](http://github.com/uholzer)): features, patches and testing
* Alf Lervåg ([@alf](http://github.com/alf)): setup patch
SPARQLWrapper-1.6.4/README.md 0000644 0001750 0001750 00000000751 12377047077 016167 0 ustar sergio sergio 0000000 0000000 # SPARQL Endpoint interface to Python
[](https://travis-ci.org/RDFLib/sparqlwrapper)
The distribution contains:
* `SPARQLWrapper`: the Python library. You should copy the directory somewhere into your PYTHONPATH. Alternatively, you can also run the disutils scrips:
python setup.py install
* `test`: some unit tests
* `script`: some scripts to run the library against some SPARQL end-points.
SPARQLWrapper-1.6.4/SPARQLWrapper/ 0000755 0001750 0001750 00000000000 12377101654 017240 5 ustar sergio sergio 0000000 0000000 SPARQLWrapper-1.6.4/SPARQLWrapper/SPARQLExceptions.py 0000644 0001750 0001750 00000002710 12377047077 022666 0 ustar sergio sergio 0000000 0000000 # -*- coding: utf-8 -*-
"""
SPARQL Wrapper exceptions
@authors: U{Ivan Herman}, U{Sergio Fernández}, U{Carlos Tejo Alonso}
@organization: U{World Wide Web Consortium} and U{Foundation CTIC}.
@license: U{W3C® SOFTWARE NOTICE AND LICENSE}
"""
class SPARQLWrapperException(Exception):
"""
Base class for SPARQL Wrapper exceptions
"""
msg = "an exception has occured"
def __init__(self, response=None):
if response:
formatted_msg = "%s: %s. \n\nResponse:\n%s" % (self.__class__.__name__, self.msg, response)
else:
formatted_msg = "%s: %s." % (self.__class__.__name__, self.msg)
super(SPARQLWrapperException, self).__init__(formatted_msg)
class EndPointInternalError(SPARQLWrapperException):
"""
Exception type for 500 Internal Server Error responses.
"""
msg = "endpoint returned code 500 and response"
class QueryBadFormed(SPARQLWrapperException):
"""
Query Bad Formed exception
"""
msg = "a bad request has been sent to the endpoint, probably the sparql query is bad formed"
class EndPointNotFound(SPARQLWrapperException):
"""
End Point Not Found exception
"""
msg = "it was impossible to connect with the endpoint in that address, check if it is correct"
SPARQLWrapper-1.6.4/SPARQLWrapper/Wrapper.py 0000644 0001750 0001750 00000076013 12377047077 021251 0 ustar sergio sergio 0000000 0000000 # -*- coding: utf-8 -*-
# epydoc
#
"""
@var JSON: to be used to set the return format to JSON
@var XML: to be used to set the return format to XML (SPARQL XML format or RDF/XML, depending on the query type). This is the default.
@var TURTLE: to be used to set the return format to Turtle
@var N3: to be used to set the return format to N3 (for most of the SPARQL services this is equivalent to Turtle)
@var RDF: to be used to set the return RDF Graph
@var POST: to be used to set HTTP POST
@var GET: to be used to set HTTP GET. This is the default.
@var SELECT: to be used to set the query type to SELECT. This is, usually, determined automatically.
@var CONSTRUCT: to be used to set the query type to CONSTRUCT. This is, usually, determined automatically.
@var ASK: to be used to set the query type to ASK. This is, usually, determined automatically.
@var DESCRIBE: to be used to set the query type to DESCRIBE. This is, usually, determined automatically.
@see: U{SPARQL Specification}
@authors: U{Ivan Herman}, U{Sergio Fernández}, U{Carlos Tejo Alonso}
@organization: U{World Wide Web Consortium}, U{Salzburg Research} and U{Foundation CTIC}.
@license: U{W3C® SOFTWARE NOTICE AND LICENSE}
@requires: U{RDFLib} package.
"""
import urllib
import urllib2
from urllib2 import urlopen as urlopener # don't change the name: tests override it
import socket
import base64
import re
import sys
import warnings
import jsonlayer
from KeyCaseInsensitiveDict import KeyCaseInsensitiveDict
from SPARQLExceptions import QueryBadFormed, EndPointNotFound, EndPointInternalError
from SPARQLUtils import deprecated
from SPARQLWrapper import __agent__
# Possible output format keys...
JSON = "json"
JSONLD = "json-ld"
XML = "xml"
TURTLE = "n3"
N3 = "n3"
RDF = "rdf"
_allowedFormats = [JSON, XML, TURTLE, N3, RDF]
# Possible HTTP methods
POST = "POST"
GET = "GET"
_allowedRequests = [POST, GET]
# Possible SPARQL/SPARUL query type
SELECT = "SELECT"
CONSTRUCT = "CONSTRUCT"
ASK = "ASK"
DESCRIBE = "DESCRIBE"
INSERT = "INSERT"
DELETE = "DELETE"
CREATE = "CREATE"
CLEAR = "CLEAR"
DROP = "DROP"
LOAD = "LOAD"
COPY = "COPY"
MOVE = "MOVE"
ADD = "ADD"
_allowedQueryTypes = [SELECT, CONSTRUCT, ASK, DESCRIBE, INSERT, DELETE, CREATE, CLEAR, DROP,
LOAD, COPY, MOVE, ADD]
# Possible methods to perform requests
URLENCODED = "urlencoded"
POSTDIRECTLY = "postdirectly"
_REQUEST_METHODS = [URLENCODED, POSTDIRECTLY]
# Possible output format (mime types) that can be converted by the local script. Unfortunately,
# it does not work by simply setting the return format, because there is still a certain level of confusion
# among implementations.
# For example, Joseki returns application/javascript and not the sparql-results+json thing that is required...
# Ie, alternatives should be given...
# Andy Seaborne told me (June 2007) that the right return format is now added to his CVS, ie, future releases of
# joseki will be o.k., too. The situation with turtle and n3 is even more confusing because the text/n3 and text/turtle
# mime types have just been proposed and not yet widely used...
_SPARQL_DEFAULT = ["application/sparql-results+xml", "application/rdf+xml", "*/*"]
_SPARQL_XML = ["application/sparql-results+xml"]
_SPARQL_JSON = ["application/sparql-results+json", "text/javascript", "application/json"]
_RDF_XML = ["application/rdf+xml"]
_RDF_N3 = ["text/rdf+n3", "application/n-triples", "application/turtle", "application/n3", "text/n3", "text/turtle"]
_RDF_JSONLD = ["application/x-json+ld", "application/ld+json"]
_ALL = ["*/*"]
_RDF_POSSIBLE = _RDF_XML + _RDF_N3
_SPARQL_POSSIBLE = _SPARQL_XML + _SPARQL_JSON + _RDF_XML + _RDF_N3
_SPARQL_PARAMS = ["query"]
try:
import rdflib_jsonld
_allowedFormats.append(JSONLD)
_RDF_POSSIBLE = _RDF_POSSIBLE + _RDF_JSONLD
except ImportError:
#warnings.warn("JSON-LD disabled because no suitable support has been found", RuntimeWarning)
pass
# This is very ugly. The fact is that the key for the choice of the output format is not defined.
# Virtuoso uses 'format', joseki uses 'output', rasqual seems to use "results", etc. Lee Feigenbaum
# told me that virtuoso also understand 'output' these days, so I removed 'format'. I do not have
# info about the others yet, ie, for the time being I keep the general mechanism. Hopefully, in a
# future release, I can get rid of that. However, these processors are (hopefully) oblivious to the
# parameters they do not understand. So: just repeat all possibilities in the final URI. UGLY!!!!!!!
_returnFormatSetting = ["format", "output", "results"]
#######################################################################################################
class SPARQLWrapper(object):
"""
Wrapper around an online access to a SPARQL Web entry point.
The same class instance can be reused for subsequent queries. The values of the base Graph URI, return formats, etc,
are retained from one query to the next (in other words, only the query string changes). The instance can also be
reset to its initial values using the L{resetQuery} method.
@cvar pattern: regular expression used to determine whether a query is of type L{CONSTRUCT}, L{SELECT}, L{ASK}, or L{DESCRIBE}.
@type pattern: compiled regular expression (see the C{re} module of Python)
@ivar baseURI: the URI of the SPARQL service
"""
pattern = re.compile(r"""
((?P(\s*BASE\s*<.*?>)\s*)|(?P(\s*PREFIX\s+.+:\s*<.*?>)\s*))*
(?P(CONSTRUCT|SELECT|ASK|DESCRIBE|INSERT|DELETE|CREATE|CLEAR|DROP|LOAD|COPY|MOVE|ADD))
""", re.VERBOSE | re.IGNORECASE)
def __init__(self, endpoint, updateEndpoint=None, returnFormat=XML, defaultGraph=None, agent=__agent__):
"""
Class encapsulating a full SPARQL call.
@param endpoint: string of the SPARQL endpoint's URI
@type endpoint: string
@param updateEndpoint: string of the SPARQL endpoint's URI for update operations (if it's a different one)
@type updateEndpoint: string
@keyword returnFormat: Default: L{XML}.
Can be set to JSON or Turtle/N3
No local check is done, the parameter is simply
sent to the endpoint. Eg, if the value is set to JSON and a construct query is issued, it
is up to the endpoint to react or not, this wrapper does not check.
Possible values:
L{JSON}, L{XML}, L{TURTLE}, L{N3} (constants in this module). The value can also be set via explicit
call, see below.
@type returnFormat: string
@keyword defaultGraph: URI for the default graph. Default is None, the value can be set either via an L{explicit call} or as part of the query string.
@type defaultGraph: string
"""
self.endpoint = endpoint
self.updateEndpoint = updateEndpoint if updateEndpoint else endpoint
self.agent = agent
self.user = None
self.passwd = None
self._defaultGraph = defaultGraph
if returnFormat in _allowedFormats:
self._defaultReturnFormat = returnFormat
else:
self._defaultReturnFormat = XML
self.resetQuery()
def resetQuery(self):
"""Reset the query, ie, return format, query, default or named graph settings, etc,
are reset to their default values."""
self.parameters = {}
if self._defaultGraph:
self.addParameter("default-graph-uri", self._defaultGraph)
self.returnFormat = self._defaultReturnFormat
self.method = GET
self.setQuery("""SELECT * WHERE{ ?s ?p ?o }""")
self.timeout = None
self.requestMethod = URLENCODED
def setReturnFormat(self, format):
"""Set the return format. If not an allowed value, the setting is ignored.
@param format: Possible values: are L{JSON}, L{XML}, L{TURTLE}, L{N3}, L{RDF} (constants in this module). All other cases are ignored.
@type format: str
"""
if format in _allowedFormats :
self.returnFormat = format
elif format == JSONLD:
raise ValueError("Current instance does not support JSON-LD; you might want to install the rdflib-json package.")
else:
raise ValueError("Invalid format '%s'; current instance supports: %s.", (format, ", ".join(_allowedFormats)))
def supportsReturnFormat(self, format):
"""Check if a return format is supported.
@param format: Possible values: are L{JSON}, L{XML}, L{TURTLE}, L{N3}, L{RDF} (constants in this module). All other cases are ignored.
@type format: bool
"""
return (format in _allowedFormats)
def setTimeout(self, timeout):
"""Set the timeout (in seconds) to use for querying the endpoint.
@param timeout: Timeout in seconds.
@type timeout: int
"""
self.timeout = int(timeout)
def setRequestMethod(self, method):
"""Set the internal method to use to perform the request for query or
update operations, either URL-encoded (C{SPARQLWrapper.URLENCODED}) or
POST directly (C{SPARQLWrapper.POSTDIRECTLY}).
Further details at U{http://www.w3.org/TR/sparql11-protocol/#query-operation}
and U{http://www.w3.org/TR/sparql11-protocol/#update-operation}.
@param method: method
@type method: str
"""
if method in _REQUEST_METHODS:
self.requestMethod = method
else:
warnings.warn("invalid update method '%s'" % method, RuntimeWarning)
@deprecated
def addDefaultGraph(self, uri):
"""
Add a default graph URI.
@param uri: URI of the graph
@type uri: string
@deprecated: use addParameter("default-graph-uri", uri) instead of this method
"""
self.addParameter("default-graph-uri", uri)
@deprecated
def addNamedGraph(self, uri):
"""
Add a named graph URI.
@param uri: URI of the graph
@type uri: string
@deprecated: use addParameter("named-graph-uri", uri) instead of this method
"""
self.addParameter("named-graph-uri", uri)
@deprecated
def addExtraURITag(self, key, value):
"""
Some SPARQL endpoints require extra key value pairs.
E.g., in virtuoso, one would add C{should-sponge=soft} to the query forcing
virtuoso to retrieve graphs that are not stored in its local database.
@param key: key of the query part
@type key: string
@param value: value of the query part
@type value: string
@deprecated: use addParameter(key, value) instead of this method
"""
self.addParameter(key, value)
@deprecated
def addCustomParameter(self, name, value):
"""
Method is kept for backwards compatibility. Historically, it "replaces" parameters instead of adding
@param name: name
@type name: string
@param value: value
@type value: string
@rtype: bool
@deprecated: use addParameter(name, value) instead of this method
"""
self.clearParameter(name)
return self.addParameter(name, value)
def addParameter(self, name, value):
"""
Some SPARQL endpoints allow extra key value pairs.
E.g., in virtuoso, one would add C{should-sponge=soft} to the query forcing
virtuoso to retrieve graphs that are not stored in its local database.
@param name: name
@type name: string
@param value: value
@type value: string
@rtype: bool
"""
if name in _SPARQL_PARAMS:
return False
else:
if name not in self.parameters:
self.parameters[name] = []
self.parameters[name].append(value)
return True
def clearParameter(self, name):
"""
Clear the values ofd a concrete parameter.
@param name: name
@type name: string
@rtype: bool
"""
if name in _SPARQL_PARAMS:
return False
else:
try:
del self.parameters[name]
return True
except KeyError:
return False
def setCredentials(self, user, passwd):
"""
Set the credentials for querying the current endpoint
@param user: username
@type user: string
@param passwd: password
@type passwd: string
"""
self.user = user
self.passwd = passwd
def setQuery(self, query):
"""
Set the SPARQL query text. Note: no check is done on the validity of the query
(syntax or otherwise) by this module, except for testing the query type (SELECT,
ASK, etc). Syntax and validity checking is done by the SPARQL service itself.
@param query: query text
@type query: string
@bug: #2320024
"""
if sys.version < '3': # have to write it like this, for 2to3 compatibility
if isinstance(query, unicode):
pass
elif isinstance(query, str):
query = query.decode('utf-8')
else:
raise TypeError('setQuery takes either unicode-strings or utf-8 encoded byte-strings')
else:
if isinstance(query, str):
pass
elif isinstance(query, bytes):
query = query.decode('utf-8')
else:
raise TypeError('setQuery takes either unicode-strings or utf-8 encoded byte-strings')
self.queryString = query
self.queryType = self._parseQueryType(query)
def _parseQueryType(self,query):
"""
Parse the SPARQL query and return its type (ie, L{SELECT}, L{ASK}, etc).
Note that the method returns L{SELECT} if nothing is specified. This is just to get all other
methods running; in fact, this means that the query is erronous, because the query must be,
according to the SPARQL specification, one of Select, Ask, Describe, or Construct. The
SPARQL endpoint should raise an exception (via urllib) for such syntax error.
@param query: query text
@type query: string
@rtype: string
"""
try:
query = query if type(query)==str else query.encode('ascii', 'ignore')
query = re.sub(re.compile("#.*?\n" ), "" , query) # remove all occurance singleline comments (issue #32)
r_queryType = self.pattern.search(query).group("queryType").upper()
except AttributeError:
warnings.warn("not detected query type for query '%s'" % query.replace("\n", " "), RuntimeWarning)
r_queryType = None
if r_queryType in _allowedQueryTypes :
return r_queryType
else :
#raise Exception("Illegal SPARQL Query; must be one of SELECT, ASK, DESCRIBE, or CONSTRUCT")
warnings.warn("unknown query type '%s'" % r_queryType, RuntimeWarning)
return SELECT
def setMethod(self,method):
"""Set the invocation method. By default, this is L{GET}, but can be set to L{POST}.
@param method: should be either L{GET} or L{POST}. Other cases are ignored.
"""
if method in _allowedRequests : self.method = method
def setUseKeepAlive(self):
"""Make urllib2 use keep-alive.
@raise ImportError: when could not be imported urlgrabber.keepalive.HTTPHandler
"""
try:
from urlgrabber.keepalive import HTTPHandler
keepalive_handler = HTTPHandler()
opener = urllib2.build_opener(keepalive_handler)
urllib2.install_opener(opener)
except ImportError:
warnings.warn("urlgrabber not installed in the system. The execution of this method has no effect.")
def isSparqlUpdateRequest(self):
""" Returns TRUE if SPARQLWrapper is configured for executing SPARQL Update request
@return: bool
"""
return self.queryType in [INSERT, DELETE, CREATE, CLEAR, DROP, LOAD, COPY, MOVE, ADD]
def isSparqlQueryRequest(self):
""" Returns TRUE if SPARQLWrapper is configured for executing SPARQL Query request
@return: bool
"""
return not self.isSparqlUpdateRequest()
def _getRequestEncodedParameters(self, query=None):
query_parameters = self.parameters.copy()
if query and type(query) == tuple and len(query) == 2:
#tuple ("query"/"update", queryString)
query_parameters[query[0]] = [query[1]]
# This is very ugly. The fact is that the key for the choice of the output format is not defined.
# Virtuoso uses 'format',sparqler uses 'output'
# However, these processors are (hopefully) oblivious to the parameters they do not understand.
# So: just repeat all possibilities in the final URI. UGLY!!!!!!!
for f in _returnFormatSetting:
query_parameters[f] = [self.returnFormat]
pairs = (
"%s=%s" % (
urllib.quote_plus(param.encode('UTF-8'), safe='/'),
urllib.quote_plus(value.encode('UTF-8'), safe='/')
)
for param, values in query_parameters.items() for value in values
)
return '&'.join(pairs)
def _getAcceptHeader(self):
if self.queryType in [SELECT, ASK]:
if self.returnFormat == XML:
acceptHeader = ",".join(_SPARQL_XML)
elif self.returnFormat == JSON:
acceptHeader = ",".join(_SPARQL_JSON)
else:
acceptHeader = ",".join(_ALL)
elif self.queryType in [INSERT, DELETE]:
acceptHeader = "*/*"
else:
if self.returnFormat == N3 or self.returnFormat == TURTLE:
acceptHeader = ",".join(_RDF_N3)
elif self.returnFormat == XML:
acceptHeader = ",".join(_RDF_XML)
elif self.returnFormat == JSONLD and JSONLD in _allowedFormats:
acceptHeader = ",".join(_RDF_JSONLD)
else:
acceptHeader = ",".join(_ALL)
return acceptHeader
def _createRequest(self):
"""Internal method to create request according a HTTP method. Returns a
C{urllib2.Request} object of the urllib2 Python library
@return: request
"""
request = None
if self.isSparqlUpdateRequest():
#protocol details at http://www.w3.org/TR/sparql11-protocol/#update-operation
uri = self.updateEndpoint
if self.method != POST:
warnings.warn("update operations MUST be done by POST")
if self.requestMethod == POSTDIRECTLY:
request = urllib2.Request(uri + "?" + self._getRequestEncodedParameters())
request.add_header("Content-Type", "application/sparql-update")
request.data = self.queryString.encode('UTF-8')
else: # URL-encoded
request = urllib2.Request(uri)
request.add_header("Content-Type", "application/x-www-form-urlencoded")
request.data = self._getRequestEncodedParameters(("update", self.queryString)).encode('ascii')
else:
#protocol details at http://www.w3.org/TR/sparql11-protocol/#query-operation
uri = self.endpoint
if self.method == POST:
if self.requestMethod == POSTDIRECTLY:
request = urllib2.Request(uri + "?" + self._getRequestEncodedParameters())
request.add_header("Content-Type", "application/sparql-query")
request.data = self.queryString.encode('UTF-8')
else: # URL-encoded
request = urllib2.Request(uri)
request.add_header("Content-Type", "application/x-www-form-urlencoded")
request.data = self._getRequestEncodedParameters(("query", self.queryString)).encode('ascii')
else: # GET
request = urllib2.Request(uri + "?" + self._getRequestEncodedParameters(("query", self.queryString)))
request.add_header("User-Agent", self.agent)
request.add_header("Accept", self._getAcceptHeader())
if self.user and self.passwd:
credentials = "%s:%s" % (self.user, self.passwd)
request.add_header("Authorization", "Basic %s" % base64.encodestring(credentials.encode('utf-8')))
return request
def _query(self):
"""Internal method to execute the query. Returns the output of the
C{urllib2.urlopen} method of the standard Python library
@return: tuples with the raw request plus the expected format
"""
if self.timeout:
socket.setdefaulttimeout(self.timeout)
request = self._createRequest()
try:
response = urlopener(request)
return response, self.returnFormat
except urllib2.HTTPError, e:
if e.code == 400:
raise QueryBadFormed(e.read())
elif e.code == 404:
raise EndPointNotFound(e.read())
elif e.code == 500:
raise EndPointInternalError(e.read())
else:
raise e
def query(self):
"""
Execute the query.
Exceptions can be raised if either the URI is wrong or the HTTP sends back an error (this is also the
case when the query is syntactically incorrect, leading to an HTTP error sent back by the SPARQL endpoint).
The usual urllib2 exceptions are raised, which therefore cover possible SPARQL errors, too.
Note that some combinations of return formats and query types may not make sense. For example,
a SELECT query with Turtle response is meaningless (the output of a SELECT is not a Graph), or a CONSTRUCT
query with JSON output may be a problem because, at the moment, there is no accepted JSON serialization
of RDF (let alone one implemented by SPARQL endpoints). In such cases the returned media type of the result is
unpredictable and may differ from one SPARQL endpoint implementation to the other. (Endpoints usually fall
back to one of the "meaningful" formats, but it is up to the specific implementation to choose which
one that is.)
@return: query result
@rtype: L{QueryResult} instance
"""
return QueryResult(self._query())
def queryAndConvert(self):
"""Macro like method: issue a query and return the converted results.
@return: the converted query result. See the conversion methods for more details.
"""
res = self.query()
return res.convert()
#######################################################################################################
class QueryResult(object):
"""
Wrapper around an a query result. Users should not create instances of this class, it is
generated by a L{SPARQLWrapper.query} call. The results can be
converted to various formats, or used directly.
If used directly: the class gives access to the direct http request results
L{self.response}: it is a file-like object with two additional methods: C{geturl()} to
return the URL of the resource retrieved and
C{info()} that returns the meta-information of the HTTP result as a dictionary-like object
(see the urllib2 standard library module of Python).
For convenience, these methods are also available on the instance. The C{__iter__} and
C{next} methods are also implemented (by mapping them to L{self.response}). This means that the
common idiom::
for l in obj : do_something_with_line(l)
would work, too.
@ivar response: the direct HTTP response; a file-like object, as return by the C{urllib2.urlopen} library call.
"""
def __init__(self,result):
"""
@param result: HTTP response stemming from a L{SPARQLWrapper.query} call, or a tuple with the expected format: (response,format)
"""
if (type(result) == tuple):
self.response = result[0]
self.requestedFormat = result[1]
else:
self.response = result
"""Direct response, see class comments for details"""
def geturl(self):
"""Return the URI of the original call.
@return: URI
@rtype: string
"""
return self.response.geturl()
def info(self):
"""Return the meta-information of the HTTP result.
@return: meta information
@rtype: dictionary
"""
return KeyCaseInsensitiveDict(self.response.info())
def __iter__(self):
"""Return an iterator object. This method is expected for the inclusion
of the object in a standard C{for} loop.
"""
return self.response.__iter__()
def next(self):
"""Method for the standard iterator."""
return self.response.next()
@staticmethod
def setJSONModule(module):
"""Set the Python module for encoding JSON data. If not an allowed value, the setting is ignored.
JSON modules supported:
- ``simplejson``: http://code.google.com/p/simplejson/
- ``cjson``: http://pypi.python.org/pypi/python-cjson
- ``json``: This is the version of ``simplejson`` that is bundled with the
Python standard library since version 2.6
(see http://docs.python.org/library/json.html)
@param module: Possible values: are L{simplejson}, L{cjson}, L{json}. All other cases raise a ValueError exception.
@type module: string
"""
jsonlayer.use(module)
def _convertJSON(self):
"""
Convert a JSON result into a Python dict. This method can be overwritten in a subclass
for a different conversion method.
@return: converted result
@rtype: Python dictionary
"""
return jsonlayer.decode(self.response.read().decode("utf-8"))
def _convertXML(self):
"""
Convert an XML result into a Python dom tree. This method can be overwritten in a
subclass for a different conversion method.
@return: converted result
@rtype: PyXlib DOM node
"""
from xml.dom.minidom import parse
return parse(self.response)
def _convertRDF(self):
"""
Convert a RDF/XML result into an RDFLib triple store. This method can be overwritten
in a subclass for a different conversion method.
@return: converted result
@rtype: RDFLib Graph
"""
try:
from rdflib.graph import ConjunctiveGraph
except ImportError:
from rdflib import ConjunctiveGraph
retval = ConjunctiveGraph()
# this is a strange hack. If the publicID is not set, rdflib (or the underlying xml parser) makes a funny
#(and, as far as I could see, meaningless) error message...
retval.load(self.response, publicID=' ')
return retval
def _convertN3(self):
"""
Convert a RDF Turtle/N3 result into a string. This method can be overwritten in a subclass
for a different conversion method.
@return: converted result
@rtype: string
"""
return self.response.read()
def _convertJSONLD(self):
"""
Convert a RDF JSON-LDresult into an RDFLib triple store. This method can be overwritten
in a subclass for a different conversion method.
@return: converted result
@rtype: RDFLib Graph
"""
from rdflib import ConjunctiveGraph
retval = ConjunctiveGraph()
retval.load(self.response, format='json-ld', publicID=' ')
return retval
def convert(self):
"""
Encode the return value depending on the return format:
- in the case of XML, a DOM top element is returned;
- in the case of JSON, a simplejson conversion will return a dictionary;
- in the case of RDF/XML, the value is converted via RDFLib into a Graph instance.
In all other cases the input simply returned.
@return: the converted query result. See the conversion methods for more details.
"""
def _content_type_in_list(real, expected):
return True in [real.find(mime) != -1 for mime in expected]
def _validate_format(format_name, allowed, mime, requested):
if requested not in allowed:
message = "Format requested was %s, but %s (%s) has been returned by the endpoint"
warnings.warn(message % (requested.upper(), format_name, mime), RuntimeWarning)
if "content-type" in self.info():
ct = self.info()["content-type"]
if _content_type_in_list(ct, _SPARQL_XML):
_validate_format("XML", [XML], ct, self.requestedFormat)
return self._convertXML()
elif _content_type_in_list(ct, _SPARQL_JSON):
_validate_format("JSON", [JSON], ct, self.requestedFormat)
return self._convertJSON()
elif _content_type_in_list(ct, _RDF_XML):
_validate_format("RDF/XML", [RDF, XML], ct, self.requestedFormat)
return self._convertRDF()
elif _content_type_in_list(ct, _RDF_N3):
_validate_format("N3", [N3, TURTLE], ct, self.requestedFormat)
return self._convertN3()
elif _content_type_in_list(ct, _RDF_JSONLD):
_validate_format("JSON(-LD)", [JSONLD, JSON], ct, self.requestedFormat)
return self._convertJSONLD()
warnings.warn("unknown response content type, returning raw response...", RuntimeWarning)
return self.response.read()
def print_results(self, minWidth=None):
results = self._convertJSON()
if minWidth :
width = self.__get_results_width(results, minWidth)
else :
width = self.__get_results_width(results)
index = 0
for var in results["head"]["vars"] :
print ("?" + var).ljust(width[index]),"|",
index += 1
print
print "=" * (sum(width) + 3 * len(width))
for result in results["results"]["bindings"] :
index = 0
for var in results["head"]["vars"] :
print result[var]["value"].ljust(width[index]),"|",
index += 1
print
def __get_results_width(self, results, minWidth=2):
width = []
for var in results["head"]["vars"] :
width.append(max(minWidth, len(var)+1))
for result in results["results"]["bindings"] :
index = 0
for var in results["head"]["vars"] :
width[index] = max(width[index], len(result[var]["value"]))
index =+ 1
return width
SPARQLWrapper-1.6.4/SPARQLWrapper/__init__.py 0000644 0001750 0001750 00000021713 12377101546 021355 0 ustar sergio sergio 0000000 0000000 # -*- coding: utf8 -*-
u"""
This is a wrapper around a SPARQL service. It helps in creating the query URI and,
possibly, convert the result into a more managable format.
The following packages are used:
- for JSON, the U{simplejson} package: C{http://cheeseshop.python.org/pypi/simplejson}
- for RDF/XML, the U{RDFLib}: C{http://rdflib.net}
These packages are imported in a lazy fashion, ie, only when needed. Ie, if the user never intends to use the
JSON format, the C{simplejson} package is not imported and the user does not have to install it.
The package can be downloaded in C{zip} and C{.tar.gz} formats from
U{http://www.ivan-herman.net/Misc/PythonStuff/SPARQL/}. It is also
available from U{Sourceforge} under the project named "C{sparql-wrapper}".
Documentation is included in the distribution.
Basic QUERY Usage
=================
Simple query
------------
The simplest usage of this module looks as follows (using the default, ie, U{XML return format}, and special URI for the
SPARQL Service)::
from SPARQLWrapper import SPARQLWrapper
queryString = "SELECT * WHERE { ?s ?p ?o. }"
sparql = SPARQLWrapper("http://localhost:2020/sparql")
# add a default graph, though that can also be part of the query string
sparql.addDefaultGraph("http://www.example.com/data.rdf")
sparql.setQuery(queryString)
try :
ret = sparql.query()
# ret is a stream with the results in XML, see
except :
deal_with_the_exception()
If C{SPARQLWrapper("http://localhost:2020/sparql",returnFormat=SPARQLWrapper.JSON)} was used, the result would be in
U{JSON format} instead of XML (provided the sparql
processor can return JSON).
Automatic conversion of the results
-----------------------------------
To make processing somewhat easier, the package can do some conversions automatically from the return result. These are:
- for XML, the U{xml.dom.minidom} (C{http://docs.python.org/library/xml.dom.minidom.html}) is
used to convert the result stream into a Python representation of a DOM tree
- for JSON, the U{simplejson} package (C{http://cheeseshop.python.org/pypi/simplejson}) to generate a Python dictionary
There are two ways to generate this conversion:
- use C{ret.convert()} in the return result from C{sparql.query()} in the code above
- use C{sparql.queryAndConvert()} to get the converted result right away if the intermediate stream is not used
For example, in the code below::
try :
sparql.setReturnFormat(SPARQLWrapper.JSON)
ret = sparql.query()
dict = ret.convert()
except:
deal_with_the_exception()
the value of C{dict} is a Python dictionary of the query result, based on the U{JSON format}.
The L{SPARQLWrapper} class can be subclassed by overriding the conversion routines if the user wants to use something else.
Partial interpretation of the results
-------------------------------------
A further help is to offer an extra, partial interpretation of the results, again to cover
most of the practical use cases.
Based on the U{JSON format}, the L{SmartWrapper.Bindings} class
can perform some simple steps in decoding the JSON return results. If L{SPARQLWrapper2}
is used instead of L{SPARQLWrapper}, this result format is generated. Note that this relies on a JSON format only,
ie, it has to be checked whether the SPARQL service can return JSON or not.
Here is a simple code that makes use of this feature::
from SPARQLWrapper import SPARQLWrapper2
queryString = "SELECT ?subj ?prop WHERE { ?subj ?prop ?o. }"
sparql = SPARQLWrapper2("http://localhost:2020/sparql")
# add a default graph, though that can also be in the query string
sparql.addDefaultGraph("http://www.example.com/data.rdf")
sparql.setQuery(queryString)
try :
ret = sparql.query()
print ret.variables # this is an array consisting of "subj" and "prop"
for binding in ret.bindings :
# each binding is a dictionary. Let us just print the results
print "%s: %s (of type %s)" % ("s",binding[u"subj"].value,binding[u"subj"].type)
print "%s: %s (of type %s)" % ("p",binding[u"prop"].value,binding[u"prop"].type)
except:
deal_with_the_exception()
To make this type of code even easier to realize, the C{[]} and C{in} operators are also implemented
on the result of L{SmartWrapper.Bindings}. This can be used to check and find a particular binding (ie, particular row
in the return value). This features becomes particularly useful when the C{OPTIONAL} feature of SPARQL is used. For example::
from SPARQLWrapper import SPARQLWrapper2
queryString = "SELECT ?subj ?o ?opt WHERE { ?subj ?o. OPTIONAL { ?subj ?opt }}"
sparql = SPARQLWrapper2("http://localhost:2020/sparql")
# add a default graph, though that can also be in the query string
sparql.addDefaultGraph("http://www.example.com/data.rdf")
sparql.setQuery(queryString)
try :
ret = sparql.query()
print ret.variables # this is an array consisting of "subj", "o", "opt"
if (u"subj",u"prop",u"opt") in ret :
# there is at least one binding covering the optional "opt", too
bindings = ret[u"subj",u"o",u"opt"]
# bindings is an array of dictionaries with the full bindings
for b in bindings :
subj = b[u"subj"].value
o = b[u"o"].value
opt = b[u"opt"].value
# do something nice with subj, o, and opt
# another way of accessing to values for a single variable:
# take all the bindings of the "subj"
subjbind = ret.getValues(u"subj") # an array of Value instances
...
except:
deal_with_the_exception()
CONSTRUCT, ASK, DESCRIBE
========================
All the examples so far were based on the SELECT queries. If the query includes, eg, the C{CONSTRUCT} keyword then the accepted
return formats should be different: eg, C{SPARQLWrapper.XML} means C{RDF/XML} and most of the SPARQL engines can also return the
results in C{Turtle}. The package, though it does not contain a full SPARQL parser, makes an attempt to determine the query type
when the query is set. This should work in most of the cases (but there is a possibility to set this manually, in case something
goes wrong).
For RDF/XML, the U{RDFLib} (C{http://rdflib.net}) package is used to convert the result into a C{Graph} instance.
GET or POST
===========
By default, all SPARQL services are invoked using HTTP GET. However, POST might be useful if the size of the query
extends a reasonable size; this can be set in the query instance.
Note that some combination may not work yet with all SPARQL processors
(eg, there are implementations where POST+JSON return does not work). Hopefully, this problem will eventually disappear.
Note that SPARQLWrapper only supports nowadays query using POST via URL-encoded.
Acknowledgement
===============
The package was greatly inspired by U{Lee Feigenbaum's similar package for Javascript}.
@summary: Python interface to SPARQL services
@see: U{SPARQL Specification}
@authors: U{Ivan Herman}, U{Sergio Fernández}, U{Carlos Tejo Alonso}
@organization: U{World Wide Web Consortium}, U{Salzburg Research} and U{Foundation CTIC}.
@license: U{W3C® SOFTWARE NOTICE AND LICENSE}
@requires: U{simplejson} package.
@requires: U{RDFLib} package.
"""
__version__ = "1.6.4"
"""The version of SPARQLWrapper"""
__authors__ = "Ivan Herman, Sergio Fernández, Carlos Tejo Alonso, Alexey Zakhlestin"
"""The primary authors of SPARQLWrapper"""
__license__ = "W3C® SOFTWARE NOTICE AND LICENSE, http://www.w3.org/Consortium/Legal/copyright-software"
"""The license governing the use and distribution of SPARQLWrapper"""
__url__ = "http://rdflib.github.io/sparqlwrapper"
"""The URL for SPARQLWrapper's homepage"""
__contact__ = "rdflib-dev@googlegroups.com"
"""Mail list to contact to other people RDFLib and SPARQLWrappers folks and developers"""
__date__ = "2014-08-26"
"""Last update"""
__agent__ = "sparqlwrapper %s (rdflib.github.io/sparqlwrapper)" % __version__
from Wrapper import SPARQLWrapper
from Wrapper import XML, JSON, TURTLE, N3, JSONLD, RDF
from Wrapper import GET, POST
from Wrapper import SELECT, CONSTRUCT, ASK, DESCRIBE, INSERT, DELETE
from Wrapper import URLENCODED, POSTDIRECTLY
from SmartWrapper import SPARQLWrapper2
SPARQLWrapper-1.6.4/SPARQLWrapper/KeyCaseInsensitiveDict.py 0000644 0001750 0001750 00000002111 12377047077 024166 0 ustar sergio sergio 0000000 0000000 # -*- coding: utf-8 -*-
"""
A simple implementation of a key case-insensitive dictionary.
@authors: U{Ivan Herman}, U{Sergio Fernández}, U{Carlos Tejo Alonso}
@organization: U{World Wide Web Consortium} and U{Foundation CTIC}.
@license: U{W3C® SOFTWARE NOTICE AND LICENSE}
"""
class KeyCaseInsensitiveDict(dict):
"""
A simple implementation of a key case-insensitive dictionary
"""
def __init__(self, d={}):
for k, v in d.items():
self[k] = v
def __setitem__(self, key, value):
if (hasattr(key, "lower")):
key = key.lower()
dict.__setitem__(self, key, value)
def __getitem__(self, key):
if (hasattr(key, "lower")):
key = key.lower()
return dict.__getitem__(self, key)
def __delitem__(self, key):
if hasattr(key, "lower"):
key = key.lower()
dict.__delitem__(self, key)
SPARQLWrapper-1.6.4/SPARQLWrapper/SmartWrapper.py 0000644 0001750 0001750 00000031101 12377047077 022245 0 ustar sergio sergio 0000000 0000000 # -*- coding: utf-8 -*-
"""
@see: U{SPARQL Specification}
@authors: U{Ivan Herman}, U{Sergio Fernández}, U{Carlos Tejo Alonso}
@organization: U{World Wide Web Consortium} and U{Foundation CTIC}.
@license: U{W3C® SOFTWARE NOTICE AND LICENSE}
@requires: U{RDFLib} package.
"""
import SPARQLWrapper
from SPARQLWrapper.Wrapper import JSON, SELECT
import urllib2
from types import *
######################################################################################
class Value(object):
"""
Class encapsulating a single binding for a variable.
@cvar URI: the string denoting a URI variable
@cvar Literal: the string denoting a Literal variable
@cvar TypedLiteral: the string denoting a typed literal variable
@cvar BNODE: the string denoting a blank node variable
@ivar variable: The original variable, stored for an easier reference
@type variable: string
@ivar value: Value of the binding
@type value: string
@ivar type: Type of the binding
@type type: string; one of L{Value.URI}, L{Value.Literal}, L{Value.TypedLiteral}, or L{Value.BNODE}
@ivar lang: Language tag of the binding, or C{None} if not set
@type lang: string
@ivar datatype: Datatype of the binding, or C{None} if not set
@type datatype: string (URI)
"""
URI = "uri"
Literal = "literal"
TypedLiteral = "typed-literal"
BNODE = "bnode"
def __init__(self,variable,binding) :
"""
@param variable: the variable for that binding. Stored for an easier reference
@param binding: the binding dictionary part of the return result for a specific binding
"""
self.variable = variable
self.value = binding['value']
self.type = binding['type']
self.lang = None
self.datatype = None
try :
self.lang = binding['xml:lang']
except :
# no lang is set
pass
try :
self.datatype = binding['datatype']
except :
pass
######################################################################################
class Bindings(object):
"""
Class encapsulating one query result, based on the JSON return format. It decodes the
return values to make it a bit more usable for a standard usage. The class consumes the
return value and instantiates a number of attributes that can be consulted directly. See
the list of variables.
The U{Serializing SPARQL Query Results in JSON} explains the details of the
JSON return structures. Very succintly: the return data has "bindings", which means a list of dictionaries. Each
dictionary is a possible binding of the SELECT variables to L{Value} instances. This structure is made a bit
more usable by this class.
@ivar fullResult: The original dictionary of the results, stored for an easier reference
@ivar head: Header part of the return, see the JSON return format document for details
@ivar variables: List of unbounds (variables) of the original query. It is an array of strings. None in the case of an ASK query
@ivar bindings: The final bindings: array of dictionaries, mapping variables to L{Value} instances.
(If unbound, then no value is set in the dictionary; that can be easily checked with
C{var in res.bindings[..]}, for example.)
@ivar askResult: by default, set to False; in case of an ASK query, the result of the query
@type askResult: Boolean
"""
def __init__(self,retval) :
"""
@param retval: the query result, instance of a L{Wrapper.QueryResult}
"""
self.fullResult = retval._convertJSON()
self.head = self.fullResult['head']
self.variables = None
try :
self.variables = self.fullResult['head']['vars']
except :
pass
self.bindings = []
try :
for b in self.fullResult['results']['bindings'] :
# this is a single binding. It is a dictionary per variable; each value is a dictionary again that has to be
# converted into a Value instance
newBind = {}
for key in self.variables :
if key in b :
# there is a real binding for this key
newBind[key] = Value(key,b[key])
self.bindings.append(newBind)
except :
pass
self.askResult = False
try :
self.askResult = self.fullResult["boolean"]
except :
pass
def getValues(self,key) :
"""A shorthand for the retrieval of all bindings for a single key. It is
equivalent to "C{[b[key] for b in self[key]]}"
@param key: possible variable
@return: list of L{Value} instances
"""
try :
return [b[key] for b in self[key]]
except :
return []
def __contains__(self,key) :
"""Emulation of the "C{key in obj}" operator. Key can be a string for a variable or an array/tuple
of strings.
If C{key} is a variable, the return value is C{True} if there is at least one binding where C{key} is
bound. If C{key} is an array or tuple, the return value is C{True} if there is at least one binding
where I{all} variables in C{key} are bound.
@param key: possible variable, or array/tuple of variables
@return: whether there is a binding of the variable in the return
@rtype: Boolean
"""
if len(self.bindings) == 0 : return False
if type(key) is list or type(key) is tuple:
# check first whether they are all really variables
if False in [ k in self.variables for k in key ]: return False
for b in self.bindings :
# try to find a binding where all key elements are present
if False in [ k in b for k in key ] :
# this is not a binding for the key combination, move on...
continue
else :
# yep, this one is good!
return True
return False
else :
if key not in self.variables : return False
for b in self.bindings :
if key in b : return True
return False
def __getitem__(self,key) :
"""Emulation of the C{obj[key]} operator. Slice notation is also available.
The goal is to choose the right bindings among the available ones. The return values are always
arrays of bindings, ie, arrays of dictionaries mapping variable keys to L{Value} instances.
The different value settings mean the followings:
- C{obj[key]} returns the bindings where C{key} has a valid value
- C{obj[key1,key2,...]} returns the bindings where I{all} C{key1,key2,...} have valid values
- C{obj[(key1,key2,...):(nkey1,nkey2,...)]} returns the bindings where all C{key1,key2,...} have
valid values and I{none} of the C{nkey1,nkey2,...} have valid values
- C{obj[:(nkey1,nkey2,...)]} returns the bindings where I{none} of the C{nkey1,nkey2,...} have valid values
In all cases complete bindings are returned, ie, the values for other variables, not present among
the keys in the call, may or may not be present depending on the query results.
@param key: possible variable or array/tuple of keys with possible slice notation
@return: list of bindings
@rtype: array of variable -> L{Value} dictionaries
"""
def _checkKeys(keys) :
if len(keys) == 0 : return False
for k in keys :
if not isinstance(k, basestring) or not k in self.variables: return False
return True
def _nonSliceCase(key) :
if isinstance(key, basestring) and key != "" and key in self.variables :
# unicode or string:
return [key]
elif type(key) is list or type(key) is tuple:
if _checkKeys(key) :
return key
return False
# The arguments should be reduced to arrays of variables, ie, unicode strings
yes_keys = []
no_keys = []
if type(key) is slice :
# Note: None for start or stop is all right
if key.start :
yes_keys = _nonSliceCase(key.start)
if not yes_keys: raise TypeError
if key.stop :
no_keys = _nonSliceCase(key.stop)
if not no_keys: raise TypeError
else :
yes_keys = _nonSliceCase(key)
# got it right, now get the right binding line with the constraints
retval = []
for b in self.bindings :
# first check whether the 'yes' part is all there:
if False in [k in b for k in yes_keys] : continue
if True in [k in b for k in no_keys] : continue
# if we got that far, we shouild be all right!
retval.append(b)
# if retval is of zero length, no hit; an exception should be raised to stay within the python style
if len(retval) == 0 :
raise IndexError
return retval
def convert(self) :
"""This is just a convenience method, returns C{self}.
Although C{Binding} is not a subclass of L{QueryResult}, it is returned as a result by
L{SPARQLWrapper2.query}, just like L{QueryResult} is returned by
L{SPARQLWrapper.SPARQLWrapper.query}. Consequently,
having an empty C{convert} method to imitate L{QueryResult's convert method} may avoid unnecessary problems.
"""
return self
##############################################################################################################
class SPARQLWrapper2(SPARQLWrapper.SPARQLWrapper):
"""Subclass of L{Wrapper} that works with a JSON SELECT return result only. The query result
is automatically set to a L{Bindings} instance. Makes the average query processing a bit simpler..."""
def __init__(self, baseURI, defaultGraph=None):
"""
Class encapsulating a full SPARQL call. In contrast to the L{SPARQLWrapper} superclass, the return format
cannot be set (it is defaulted to L{JSON}).
@param baseURI: string of the SPARQL endpoint's URI
@type baseURI: string
@keyword defaultGraph: URI for the default graph. Default is None, can be set via an explicit call, too
@type defaultGraph: string
"""
super(SPARQLWrapper2, self).__init__(baseURI, returnFormat=JSON, defaultGraph=defaultGraph)
def setReturnFormat(self, format):
"""Set the return format (overriding the L{inherited method}).
This method does nothing; this class instance should work with JSON only. The method is defined
just to avoid possible errors by erronously setting the return format.
When using this class, the user can safely ignore this call.
@param format: return format
"""
pass
def query(self):
"""
Execute the query and do an automatic conversion.
Exceptions can be raised if either the URI is wrong or the HTTP sends back an error.
The usual urllib2 exceptions are raised, which cover possible SPARQL errors, too.
If the query type is I{not} SELECT, the method falls back to the
L{corresponding method in the superclass}.
@return: query result
@rtype: L{Bindings} instance
"""
res = super(SPARQLWrapper2, self).query()
if self.queryType == SELECT:
return Bindings(res)
else:
return res
def queryAndConvert(self):
"""This is here to override the inherited method; it is equivalent to L{query}.
If the query type is I{not} SELECT, the method falls back to the
L{corresponding method in the superclass}.
@return: the converted query result.
"""
if self.queryType == SELECT:
return self.query()
else:
return super(SPARQLWrapper2, self).queryAndConvert()
SPARQLWrapper-1.6.4/SPARQLWrapper/SPARQLUtils.py 0000644 0001750 0001750 00000002003 12377047077 021640 0 ustar sergio sergio 0000000 0000000 # -*- coding: utf8 -*-
"""
SPARQL Wrapper Utils
@authors: U{Ivan Herman}, U{Sergio Fernández}, U{Carlos Tejo Alonso}
@organization: U{World Wide Web Consortium} and U{Foundation CTIC}.
@license: U{W3C SOFTWARE NOTICE AND LICENSE}
"""
import warnings
def deprecated(func):
"""
This is a decorator which can be used to mark functions
as deprecated. It will result in a warning being emmitted
when the function is used.
@see: http://code.activestate.com/recipes/391367/
"""
def newFunc(*args, **kwargs):
warnings.warn("Call to deprecated function %s." % func.__name__, category=DeprecationWarning, stacklevel=2)
return func(*args, **kwargs)
newFunc.__name__ = func.__name__
newFunc.__doc__ = func.__doc__
newFunc.__dict__.update(func.__dict__)
return newFunc
SPARQLWrapper-1.6.4/SPARQLWrapper/jsonlayer.py 0000644 0001750 0001750 00000013033 12377047077 021630 0 ustar sergio sergio 0000000 0000000 # -*- coding: utf-8 -*-
#
# Copyright (C) 2009 Christopher Lenz
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# 3. The name of the author may not be used to endorse or promote
# products derived from this software without specific prior
# written permission.
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Thin abstraction layer over the different available modules for decoding
and encoding JSON data.
This module currently supports the following JSON modules:
- ``simplejson``: http://code.google.com/p/simplejson/
- ``cjson``: http://pypi.python.org/pypi/python-cjson
- ``json``: This is the version of ``simplejson`` that is bundled with the
Python standard library since version 2.6
(see http://docs.python.org/library/json.html)
The default behavior is to use ``simplejson`` if installed, and otherwise
fallback to the standard library module. To explicitly tell SPARQLWrapper
which module to use, invoke the `use()` function with the module name::
import jsonlayer
jsonlayer.use('cjson')
In addition to choosing one of the above modules, you can also configure
SPARQLWrapper to use custom decoding and encoding functions::
import jsonlayer
jsonlayer.use(decode=my_decode, encode=my_encode)
"""
__all__ = ['decode', 'encode', 'use']
_initialized = False
_using = None
_decode = None
_encode = None
def decode(string):
"""Decode the given JSON string.
:param string: the JSON string to decode
:type string: basestring
:return: the corresponding Python data structure
:rtype: object
"""
if not _initialized:
_initialize()
return _decode(string)
def encode(obj):
"""Encode the given object as a JSON string.
:param obj: the Python data structure to encode
:type obj: object
:return: the corresponding JSON string
:rtype: basestring
"""
if not _initialized:
_initialize()
return _encode(obj)
def use(module=None, decode=None, encode=None):
"""Set the JSON library that should be used, either by specifying a known
module name, or by providing a decode and encode function.
The modules "simplejson", "cjson", and "json" are currently supported for
the ``module`` parameter.
If provided, the ``decode`` parameter must be a callable that accepts a
JSON string and returns a corresponding Python data structure. The
``encode`` callable must accept a Python data structure and return the
corresponding JSON string. Exceptions raised by decoding and encoding
should be propagated up unaltered.
:param module: the name of the JSON library module to use, or the module object itself
:type module: str or module
:param decode: a function for decoding JSON strings
:type decode: callable
:param encode: a function for encoding objects as JSON strings
:type encode: callable
"""
global _decode, _encode, _initialized, _using
if module is not None:
if not isinstance(module, basestring):
module = module.__name__
if module not in ('cjson', 'json', 'simplejson'):
raise ValueError('Unsupported JSON module %s' % module)
_using = module
_initialized = False
else:
assert decode is not None and encode is not None
_using = 'custom'
_decode = decode
_encode = encode
_initialized = True
def _initialize():
global _initialized
def _init_simplejson():
global _decode, _encode
import simplejson
_decode = lambda string, loads=simplejson.loads: loads(string)
_encode = lambda obj, dumps=simplejson.dumps: \
dumps(obj, allow_nan=False, ensure_ascii=False)
def _init_cjson():
global _decode, _encode
import cjson
_decode = lambda string, decode=cjson.decode: decode(string)
_encode = lambda obj, encode=cjson.encode: encode(obj)
def _init_stdlib():
global _decode, _encode
json = __import__('json', {}, {})
_decode = lambda string, loads=json.loads: loads(string)
_encode = lambda obj, dumps=json.dumps: \
dumps(obj, allow_nan=False, ensure_ascii=False)
if _using == 'simplejson':
_init_simplejson()
elif _using == 'cjson':
_init_cjson()
elif _using == 'json':
_init_stdlib()
elif _using != 'custom':
try:
_init_simplejson()
except ImportError:
_init_stdlib()
_initialized = True
SPARQLWrapper-1.6.4/setup.py 0000755 0001750 0001750 00000005131 12377071336 016415 0 ustar sergio sergio 0000000 0000000 # -*- coding: utf-8 -*-
import sys
try:
from ez_setup import use_setuptools
use_setuptools()
except:
pass
from setuptools import setup, find_packages
try:
import six
py3 = six.PY3
except:
py3 = sys.version_info[0] >= 3
# grouping requires
_requires = []
_install_requires = []
# rdflib
_requires.append('rdflib')
_install_requires.append('rdflib >= 2.4.2')
# simplejson
if sys.version_info[0:2] < (2, 6):
_requires.append('simplejson')
_install_requires.append('simplejson == 2.0.9')
# metainformation
if py3:
import re
_version_re = re.compile(r'__version__\s*=\s*"(.*)"')
_authors_re = re.compile(r'__authors__\s*=\s*"(.*)"')
_url_re = re.compile(r'__url__\s*=\s*"(.*)"')
for line in open('SPARQLWrapper/__init__.py', encoding='utf-8'):
version_match = _version_re.match(line)
if version_match:
version = version_match.group(1)
authors_match = _authors_re.match(line)
if authors_match:
authors = authors_match.group(1)
url_match = _url_re.match(line)
if url_match:
url = url_match.group(1)
else:
import SPARQLWrapper
version = SPARQLWrapper.__version__
authors = SPARQLWrapper.__authors__
url = SPARQLWrapper.__url__
# actual setup configuration
setup(
name = 'SPARQLWrapper',
version = version,
description = 'SPARQL Endpoint interface to Python',
long_description = 'This is a wrapper around a SPARQL service. It helps in creating the query URI and, possibly, convert the result into a more manageable format.',
license = 'W3C SOFTWARE NOTICE AND LICENSE', # should be removed by PEP 314
author = authors,
author_email = "ivan at ivan-herman net, sergio at wikier org, carlos.tejo at gmail com, indeyets at gmail com",
url = url,
download_url = 'https://github.com/RDFLib/sparqlwrapper/releases',
platforms = ['any'], # should be removed by PEP 314
packages = ['SPARQLWrapper'],
requires = _requires, # used by distutils to create metadata PKG-INFO
install_requires = _install_requires, # used by setuptools to install the dependencies
classifiers = [
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
'License :: OSI Approved :: W3C License',
'Operating System :: OS Independent',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 3',
],
keywords = 'python SPARQL',
use_2to3 = True,
#requires_python = '>=2.5', # Future in PEP 345
#scripts = ['ez_setup.py']
)
SPARQLWrapper-1.6.4/PKG-INFO 0000644 0001750 0001750 00000001663 12377101654 016000 0 ustar sergio sergio 0000000 0000000 Metadata-Version: 1.1
Name: SPARQLWrapper
Version: 1.6.4
Summary: SPARQL Endpoint interface to Python
Home-page: http://rdflib.github.io/sparqlwrapper
Author: Ivan Herman, Sergio Fernández, Carlos Tejo Alonso, Alexey Zakhlestin
Author-email: ivan at ivan-herman net, sergio at wikier org, carlos.tejo at gmail com, indeyets at gmail com
License: W3C SOFTWARE NOTICE AND LICENSE
Download-URL: https://github.com/RDFLib/sparqlwrapper/releases
Description: This is a wrapper around a SPARQL service. It helps in creating the query URI and, possibly, convert the result into a more manageable format.
Keywords: python SPARQL
Platform: any
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: W3C License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 3
Requires: rdflib
SPARQLWrapper-1.6.4/MANIFEST.in 0000644 0001750 0001750 00000000105 12377047077 016437 0 ustar sergio sergio 0000000 0000000 include *.md
exclude Makefile
include test/*.py
include scripts/*.py
SPARQLWrapper-1.6.4/setup.cfg 0000644 0001750 0001750 00000000073 12377101654 016516 0 ustar sergio sergio 0000000 0000000 [egg_info]
tag_build =
tag_date = 0
tag_svn_revision = 0
SPARQLWrapper-1.6.4/MANAGEMENT.md 0000644 0001750 0001750 00000002452 12377047077 016646 0 ustar sergio sergio 0000000 0000000 # Management documentation
The project keeps a very low-profile on managing, so we try to keep it simple.
## Contributions
Every contributor (patchs, pull requests, new features, etc) gets part of ownership by be mentioned as contributor to the project (`AUTHORS.md`).
## Release
### Software
The release process is quite simple, just few things have to be done:
First, do not forget to update the changelog (`ChangeLog.txt` file). That information could be added later to the release at github.
Then you have to [create a release](https://github.com/blog/1547-release-your-software) by tagging the master branch:
git tag x.y.z
git push --tags
And then upload the release to pypi:
python setup.py register sdist --formats=gztar,zip bdist_egg upload
Please, don't forget to increment to the next module (`SPARQLWrapper/__init__.py` file).
### Documentation
In order to provide online documentation, some steps need to be accomplished:
1. First, generate the documentation using [epydoc](http://epydoc.sourceforge.net/) using the makefile
make doc
2. And then upload the documentation generated (`doc` folder) to GitHub Pages (`gh-pages` branch).
3. After that, the online version of the documentation would be available on [GitHub Pages](http://rdflib.github.io/sparqlwrapper/resources/doc).
SPARQLWrapper-1.6.4/scripts/ 0000755 0001750 0001750 00000000000 12377101654 016364 5 ustar sergio sergio 0000000 0000000 SPARQLWrapper-1.6.4/scripts/example-optional.py 0000644 0001750 0001750 00000001400 12377047077 022217 0 ustar sergio sergio 0000000 0000000 #!/usr/bin/python
# -*- coding: utf-8 -*-
from SPARQLWrapper import SPARQLWrapper, JSON, XML, N3, RDF
sparql = SPARQLWrapper("http://dbpedia.org/sparql")
sparql.setQuery("""
PREFIX rdfs:
SELECT ?person ?party
WHERE { ?person
OPTIONAL { ?person ?party }
}
""")
# JSON example
print '\n\n*** JSON Example'
sparql.setReturnFormat(JSON)
results = sparql.query().convert()
for result in results["results"]["bindings"]:
if result.has_key("party"):
print "* " + result["person"]["value"] + " ** " + result["party"]["value"]
else:
print result["person"]["value"]
SPARQLWrapper-1.6.4/scripts/example.py 0000644 0001750 0001750 00000001577 12377047077 020413 0 ustar sergio sergio 0000000 0000000 #!/usr/bin/python
# -*- coding: utf-8 -*-
from SPARQLWrapper import SPARQLWrapper, JSON, XML, N3, RDF
sparql = SPARQLWrapper("http://dbpedia.org/sparql")
sparql.setQuery("""
PREFIX rdfs:
SELECT ?label
WHERE { rdfs:label ?label }
""")
# JSON example
print '\n\n*** JSON Example'
sparql.setReturnFormat(JSON)
results = sparql.query().convert()
for result in results["results"]["bindings"]:
print result["label"]["value"]
# XML example
print '\n\n*** XML Example'
sparql.setReturnFormat(XML)
results = sparql.query().convert()
print results.toxml()
# N3 example
print '\n\n*** N3 Example'
sparql.setReturnFormat(N3)
results = sparql.query().convert()
print results
# RDF example
print '\n\n*** RDF Example'
sparql.setReturnFormat(RDF)
results = sparql.query().convert()
print results.serialize()
SPARQLWrapper-1.6.4/scripts/example-dbpedia.py 0000644 0001750 0001750 00000001360 12377047077 021767 0 ustar sergio sergio 0000000 0000000 #!/usr/bin/python
# -*- coding: utf-8 -*-
from SPARQLWrapper import SPARQLWrapper, JSON
sparql = SPARQLWrapper("http://dbpedia.org/sparql")
sparql.setQuery("""
PREFIX rdfs:
SELECT ?label
WHERE { rdfs:label ?label }
""")
sparql.setReturnFormat(JSON)
results = sparql.query()
results.print_results()
print
sparql.setQuery("""
PREFIX rdfs:
PREFIX dbpo:
SELECT ?subdivision ?label
WHERE {
dbpo:subdivisionName ?subdivision .
?subdivision rdfs:label ?label .
}
""")
sparql.setReturnFormat(JSON)
results = sparql.query()
results.print_results()
SPARQLWrapper-1.6.4/scripts/sparql.py 0000755 0001750 0001750 00000004377 12377047077 020266 0 ustar sergio sergio 0000000 0000000 #!/usr/bin/python
# -*- coding: utf-8 -*-
from SPARQLWrapper import SPARQLWrapper2, SPARQLWrapper, TURTLE
import sys, getopt
localSparqler = "http://localhost:2020/sparql"
localVirtuoso = "http://localhost:8890/sparql"
def main(server,query,sponge=False) :
sparql = SPARQLWrapper2(server)
if sponge : sparql.addExtraURITag("should-sponge","grab-everything")
sparql.setQuery(query)
res = sparql.query()
variables = res.variables
print "Variables:"
print variables
print
print "Bindings:"
for b in res.bindings :
for v in res.variables :
try :
val = b[v]
if val.lang :
str = "%s: %s@%s" % (v,val.value,val.lang)
elif val.datatype :
str = "%s: %s^^%s" % (v,val.value,val.datatype)
else :
str = "%s: %s" % (v,val.value)
except KeyError :
# no binding to that one...
str = "%s: <>" % v
print str.encode('utf-8')
print
# -------------------------------------------------------------------------------------------------------------
server = localSparqler
query = ""
sponge = False
usagetxt="""%s [-s] [-u url] [file]
-s: use local sparqler (default)
-v: use local virtuoso
-u url: server url
-p: issue an extra sponge for virtuoso
file: sparql query file
"""
def usage() :
print usagetxt % sys.argv[0]
sys.exit(1)
if __name__ == '__main__' :
if len(sys.argv) == 1:
usage()
try :
opts,args = getopt.getopt(sys.argv[1:],"shu:pv")
for o,a in opts :
if o == "-s" :
server = localSparqler
elif o == "-v" :
server = localVirtuoso
sponge = True
elif o == "-h" :
print usage
sys.exit(0)
elif o == "-u" :
server = a
elif o == "-p" :
sponge = True
if query == "" and len(args) > 0 :
inp = file(args[0])
query = ""
for l in inp :
query += l
except :
usage()
if query == "" : usage()
main(server,query,sponge)
SPARQLWrapper-1.6.4/SPARQLWrapper.egg-info/ 0000755 0001750 0001750 00000000000 12377101654 020732 5 ustar sergio sergio 0000000 0000000 SPARQLWrapper-1.6.4/SPARQLWrapper.egg-info/PKG-INFO 0000644 0001750 0001750 00000001663 12377101641 022031 0 ustar sergio sergio 0000000 0000000 Metadata-Version: 1.1
Name: SPARQLWrapper
Version: 1.6.4
Summary: SPARQL Endpoint interface to Python
Home-page: http://rdflib.github.io/sparqlwrapper
Author: Ivan Herman, Sergio Fernández, Carlos Tejo Alonso, Alexey Zakhlestin
Author-email: ivan at ivan-herman net, sergio at wikier org, carlos.tejo at gmail com, indeyets at gmail com
License: W3C SOFTWARE NOTICE AND LICENSE
Download-URL: https://github.com/RDFLib/sparqlwrapper/releases
Description: This is a wrapper around a SPARQL service. It helps in creating the query URI and, possibly, convert the result into a more manageable format.
Keywords: python SPARQL
Platform: any
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: W3C License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 3
Requires: rdflib
SPARQLWrapper-1.6.4/SPARQLWrapper.egg-info/dependency_links.txt 0000644 0001750 0001750 00000000001 12377101641 024774 0 ustar sergio sergio 0000000 0000000
SPARQLWrapper-1.6.4/SPARQLWrapper.egg-info/top_level.txt 0000644 0001750 0001750 00000000016 12377101641 023455 0 ustar sergio sergio 0000000 0000000 SPARQLWrapper
SPARQLWrapper-1.6.4/SPARQLWrapper.egg-info/SOURCES.txt 0000644 0001750 0001750 00000001115 12377101641 022610 0 ustar sergio sergio 0000000 0000000 AUTHORS.md
MANAGEMENT.md
MANIFEST.in
README.md
setup.cfg
setup.py
SPARQLWrapper/KeyCaseInsensitiveDict.py
SPARQLWrapper/SPARQLExceptions.py
SPARQLWrapper/SPARQLUtils.py
SPARQLWrapper/SmartWrapper.py
SPARQLWrapper/Wrapper.py
SPARQLWrapper/__init__.py
SPARQLWrapper/jsonlayer.py
SPARQLWrapper.egg-info/PKG-INFO
SPARQLWrapper.egg-info/SOURCES.txt
SPARQLWrapper.egg-info/dependency_links.txt
SPARQLWrapper.egg-info/requires.txt
SPARQLWrapper.egg-info/top_level.txt
scripts/example-dbpedia.py
scripts/example-optional.py
scripts/example.py
scripts/sparql.py
test/dbpedia.py
test/wrapper_test.py SPARQLWrapper-1.6.4/SPARQLWrapper.egg-info/requires.txt 0000644 0001750 0001750 00000000017 12377101641 023324 0 ustar sergio sergio 0000000 0000000 rdflib >= 2.4.2