1# -*- coding: utf-8 -*- 2import inspect 3import os 4import sys 5 6import logging 7 8import unittest 9import urllib2 10from urlparse import urlparse, parse_qsl, parse_qs 11from urllib2 import Request 12import time 13 14logging.basicConfig() 15 16# prefer local copy to the one which is installed 17# hack from http://stackoverflow.com/a/6098238/280539 18_top_level_path = os.path.realpath(os.path.abspath(os.path.join( 19 os.path.split(inspect.getfile(inspect.currentframe()))[0], 20 ".." 21))) 22if _top_level_path not in sys.path: 23 sys.path.insert(0, _top_level_path) 24# end of hack 25 26# we don't want to let Wrapper do real web-requests. so, we are… 27# constructing a simple Mock! 28from urllib2 import HTTPError 29 30from io import StringIO 31import warnings 32warnings.simplefilter("always") 33 34import SPARQLWrapper.Wrapper as _victim 35 36from SPARQLWrapper import SPARQLWrapper 37from SPARQLWrapper import XML, GET, POST, JSON, JSONLD, N3, TURTLE, RDF, SELECT, INSERT, RDFXML, CSV, TSV 38from SPARQLWrapper import URLENCODED, POSTDIRECTLY 39from SPARQLWrapper import BASIC, DIGEST 40from SPARQLWrapper.Wrapper import QueryResult, QueryBadFormed, EndPointNotFound, EndPointInternalError, Unauthorized, URITooLong 41 42 43class FakeResult(object): 44 def __init__(self, request): 45 self.request = request 46 47 48def urlopener(request): 49 return FakeResult(request) 50 51 52def urlopener_error_generator(code): 53 def urlopener_error(request): 54 raise HTTPError(request.get_full_url, code, '', {}, StringIO(u'')) 55 56 return urlopener_error 57 58 59def urlopener_check_data_encoding(request): 60 if sys.version < '3': # have to write it like this, for 2to3 compatibility 61 if isinstance(request.data, unicode): 62 raise TypeError 63 else: 64 if isinstance(request.data, str): 65 raise TypeError 66# DONE 67 68class TestCase(unittest.TestCase): 69 70 def assertIsInstance(self, obj, cls, msg=None, *args, **kwargs): 71 """Python < v2.7 compatibility. Assert 'obj' is instance of 'cls'""" 72 try: 73 f = super(TestCase, self).assertIsInstance 74 except AttributeError: 75 self.assertTrue(isinstance(obj, cls), *args, **kwargs) 76 else: 77 f(obj, cls, *args, **kwargs) 78 79 def assertIsNone(self, obj, msg=None, *args, **kwargs): 80 """Python < v2.7 compatibility. Assert 'obj' is None""" 81 try: 82 f = super(TestCase, self).assertIsNone 83 except AttributeError: 84 self.assertEqual(obj, None, *args, **kwargs) 85 else: 86 f(obj, *args, **kwargs) 87 88 89class SPARQLWrapper_Test(TestCase): 90 91 @staticmethod 92 def _get_request(wrapper): 93 return wrapper.query().response.request # possible due to mock above 94 95 @staticmethod 96 def _get_parameters_from_request(request): 97 if request.get_method() == 'GET': 98 pieces_str = urlparse(request.get_full_url()).query 99 else: 100 if sys.version < '3': 101 pieces_str = request.data 102 else: 103 pieces_str = request.data.decode('ascii') 104 105 return parse_qs(pieces_str) 106 107 @staticmethod 108 def _get_request_parameters(wrapper): 109 request = SPARQLWrapper_Test._get_request(wrapper) 110 parameters = SPARQLWrapper_Test._get_parameters_from_request(request) 111 112 return parameters 113 114 @staticmethod 115 def _get_request_parameters_as_bytes(wrapper): 116 request = SPARQLWrapper_Test._get_request(wrapper) 117 parameters = SPARQLWrapper_Test._get_parameters_from_request(request) 118 119 if sys.version < '3': 120 return parameters 121 else: 122 result = {} 123 for k, vs in parameters.iteritems(): 124 result[k] = [v.encode('utf-8') for v in vs] 125 return result 126 127 @classmethod 128 def setUpClass(cls): 129 urllib2._opener = None # clear value. Due to the order of test execution, the value of urllib2._opener contains, for instance, keepalive.keepalive.HTTPHandler 130 131 def setUp(self): 132 self.wrapper = SPARQLWrapper(endpoint='http://example.org/sparql') 133 _victim.urlopener = urlopener 134 135 def testConstructor(self): 136 try: 137 SPARQLWrapper() 138 self.fail("SPARQLWrapper constructor should fail without arguments") 139 except TypeError: 140 pass 141 142 wrapper = SPARQLWrapper(endpoint='http://example.org/sparql/') 143 144 self.assertEqual(XML, wrapper.returnFormat, 'default return format is XML') 145 self.assertTrue( 146 wrapper.agent.startswith('sparqlwrapper'), 147 'default user-agent should start with "sparqlwrapper"' 148 ) 149 150 wrapper = SPARQLWrapper(endpoint='http://example.org/sparql/', returnFormat='wrongformat') 151 self.assertEqual(XML, wrapper.returnFormat, 'default return format is XML') 152 153 wrapper = SPARQLWrapper(endpoint='http://example.org/sparql/', defaultGraph='http://example.org/default') 154 parameters = self._get_request_parameters(wrapper) 155 self.assertEqual( 156 ['http://example.org/default'], 157 parameters.get('default-graph-uri'), 158 'default graph is set' 159 ) 160 161 def testReset(self): 162 self.wrapper.setMethod(POST) 163 self.wrapper.setQuery('CONSTRUCT WHERE {?a ?b ?c}') 164 self.wrapper.setReturnFormat(N3) 165 self.wrapper.addParameter('a', 'b') 166 self.wrapper.setOnlyConneg(True) 167 168 request = self._get_request(self.wrapper) 169 parameters = self._get_parameters_from_request(request) 170 onlyConneg = self.wrapper.onlyConneg 171 172 self.assertEqual('POST', request.get_method()) 173 self.assertTrue(parameters['query'][0].startswith('CONSTRUCT')) 174 self.assertTrue('rdf+n3' in request.get_header('Accept')) 175 self.assertTrue('a' in parameters) 176 self.assertTrue(onlyConneg) 177 178 self.wrapper.resetQuery() 179 180 request = self._get_request(self.wrapper) 181 parameters = self._get_parameters_from_request(request) 182 onlyConneg = self.wrapper.onlyConneg 183 184 self.assertEqual('GET', request.get_method()) 185 self.assertTrue(parameters['query'][0].startswith('SELECT')) 186 self.assertFalse('rdf+n3' in request.get_header('Accept')) 187 self.assertTrue('sparql-results+xml' in request.get_header('Accept')) 188 self.assertFalse('a' in parameters) 189 self.assertFalse('a' in parameters) 190 self.assertTrue(onlyConneg) 191 192 def testSetReturnFormat(self): 193 with warnings.catch_warnings(record=True) as w: 194 self.wrapper.setReturnFormat('nonexistent format') 195 self.assertEqual(1, len(w), "Warning due to non expected format") 196 197 self.assertEqual(XML, self.wrapper.query().requestedFormat) 198 199 self.wrapper.setReturnFormat(JSON) 200 self.assertEqual(JSON, self.wrapper.query().requestedFormat) 201 202 try: 203 import rdflib_jsonld 204 self.wrapper.setReturnFormat(JSONLD) 205 self.assertEqual(JSONLD, self.wrapper.query().requestedFormat) 206 except ImportError: 207 self.assertRaises(ValueError, self.wrapper.setReturnFormat, JSONLD) 208 209 def testsSupportsReturnFormat(self): 210 self.assertTrue(self.wrapper.supportsReturnFormat(XML)) 211 self.assertTrue(self.wrapper.supportsReturnFormat(JSON)) 212 self.assertTrue(self.wrapper.supportsReturnFormat(TURTLE)) 213 self.assertTrue(self.wrapper.supportsReturnFormat(N3)) 214 self.assertTrue(self.wrapper.supportsReturnFormat(RDF)) 215 self.assertTrue(self.wrapper.supportsReturnFormat(RDFXML)) 216 self.assertTrue(self.wrapper.supportsReturnFormat(CSV)) 217 self.assertTrue(self.wrapper.supportsReturnFormat(TSV)) 218 self.assertFalse(self.wrapper.supportsReturnFormat('nonexistent format')) 219 220 try: 221 import rdflib_jsonld 222 self.assertTrue(self.wrapper.supportsReturnFormat(JSONLD)) 223 except ImportError: 224 self.assertFalse(self.wrapper.supportsReturnFormat(JSONLD)) 225 226 227 def testAddParameter(self): 228 self.assertFalse(self.wrapper.addParameter('query', 'dummy')) 229 self.assertTrue(self.wrapper.addParameter('param1', 'value1')) 230 self.assertTrue(self.wrapper.addParameter('param1', 'value2')) 231 self.assertTrue(self.wrapper.addParameter('param2', 'value2')) 232 233 pieces = self._get_request_parameters(self.wrapper) 234 235 self.assertTrue('param1' in pieces) 236 self.assertEqual(['value1', 'value2'], pieces['param1']) 237 self.assertTrue('param2' in pieces) 238 self.assertEqual(['value2'], pieces['param2']) 239 self.assertNotEqual(['dummy'], 'query') 240 241 def testSetCredentials(self): 242 request = self._get_request(self.wrapper) 243 self.assertFalse(request.has_header('Authorization')) 244 245 self.wrapper.setCredentials('login', 'password') 246 request = self._get_request(self.wrapper) 247 self.assertTrue(request.has_header('Authorization')) 248 249 # expected header for login:password 250 # should succeed for python 3 since pull request #72 251 self.assertEqual("Basic bG9naW46cGFzc3dvcmQ=", request.get_header('Authorization')) 252 253 def testAddCustomHttpHeader(self): 254 request = self._get_request(self.wrapper) 255 self.assertFalse(request.has_header('Foo')) 256 257 # Add new header field name 258 self.wrapper.addCustomHttpHeader('Foo', 'bar') 259 request = self._get_request(self.wrapper) 260 self.assertTrue(request.has_header('Foo')) 261 self.assertEqual("bar", request.get_header('Foo')) 262 263 # Override a new field name 264 self.wrapper.addCustomHttpHeader('Foo', 'bar') 265 request = self._get_request(self.wrapper) 266 self.assertTrue(request.has_header('Foo')) 267 self.assertEqual("bar", request.get_header('Foo')) 268 self.wrapper.addCustomHttpHeader('Foo', 'bar_2') 269 request = self._get_request(self.wrapper) 270 self.assertTrue(request.has_header('Foo')) 271 self.assertEqual("bar_2", request.get_header('Foo')) 272 273 # Override header field name 274 self.wrapper.addCustomHttpHeader('User-agent', 'Another UA') 275 request = self._get_request(self.wrapper) 276 self.assertEqual("Another UA", request.get_header('User-agent')) 277 278 def testClearCustomHttpHeader(self): 279 request = self._get_request(self.wrapper) 280 self.assertFalse(request.has_header('Foo')) 281 282 # Add new header field name 283 self.wrapper.addCustomHttpHeader('Foo_1', 'bar_1') 284 self.wrapper.addCustomHttpHeader('Foo_2', 'bar_2') 285 self.wrapper.addCustomHttpHeader('Foo_3', 'bar_3') 286 287 288 self.assertFalse(self.wrapper.clearCustomHttpHeader('Foo_4')) 289 self.assertTrue(self.wrapper.clearCustomHttpHeader('Foo_3')) 290 291 customHttpHeaders = self.wrapper.customHttpHeaders 292 293 self.assertTrue('Foo_1' in customHttpHeaders) 294 self.assertTrue('Foo_2' in customHttpHeaders) 295 self.assertEqual('bar_1', customHttpHeaders['Foo_1']) 296 self.assertEqual('bar_2', customHttpHeaders['Foo_2']) 297 298 self.assertFalse(self.wrapper.clearCustomHttpHeader('Foo_3'), 'already cleaned') 299 300 301 def testSetHTTPAuth(self): 302 self.assertRaises(TypeError, self.wrapper.setHTTPAuth, 123) 303 self.wrapper.setCredentials('login', 'password') 304 request = self._get_request(self.wrapper) 305 self.assertTrue(request.has_header('Authorization')) 306 self.assertIsNone(urllib2._opener) 307 308 self.wrapper.setHTTPAuth(DIGEST) 309 self.assertIsNone(urllib2._opener) 310 request = self._get_request(self.wrapper) 311 self.assertFalse(request.has_header('Authorization')) 312 self.assertEqual(self.wrapper.http_auth, DIGEST) 313 self.assertIsInstance(urllib2._opener, urllib2.OpenerDirector) 314 315 self.wrapper.setHTTPAuth(DIGEST) 316 self.wrapper.setCredentials('login', 'password') 317 request = self._get_request(self.wrapper) 318 self.assertEqual(self.wrapper.http_auth, DIGEST) 319 self.assertEqual(self.wrapper.user, "login") 320 self.assertEqual(self.wrapper.passwd, "password") 321 self.assertEqual(self.wrapper.realm, "SPARQL") 322 self.assertNotEqual(self.wrapper.realm, "SPARQL Endpoint") 323 324 self.wrapper.setHTTPAuth(DIGEST) 325 self.wrapper.setCredentials('login', 'password', realm="SPARQL Endpoint") 326 request = self._get_request(self.wrapper) 327 self.assertEqual(self.wrapper.http_auth, DIGEST) 328 self.assertEqual(self.wrapper.user, "login") 329 self.assertEqual(self.wrapper.passwd, "password") 330 self.assertEqual(self.wrapper.realm, "SPARQL Endpoint") 331 self.assertNotEqual(self.wrapper.realm, "SPARQL") 332 333 self.assertRaises(ValueError, self.wrapper.setHTTPAuth, 'OAuth') 334 335 self.wrapper.http_auth = "OAuth" 336 self.assertRaises(NotImplementedError, self._get_request, self.wrapper) 337 338 def testSetQuery(self): 339 self.wrapper.setQuery('PREFIX example: <http://example.org/INSERT/> SELECT * WHERE {?s ?p ?v}') 340 self.assertEqual(SELECT, self.wrapper.queryType) 341 342 self.wrapper.setQuery('PREFIX e: <http://example.org/> INSERT {e:a e:b e:c}') 343 self.assertEqual(INSERT, self.wrapper.queryType) 344 345 self.wrapper.setQuery("""#CONSTRUCT {?s ?p ?o} 346 SELECT ?s ?p ?o 347 WHERE {?s ?p ?o}""") 348 self.assertEqual(SELECT, self.wrapper.queryType) 349 350 with warnings.catch_warnings(record=True) as w: 351 self.wrapper.setQuery('UNKNOWN {e:a e:b e:c}') 352 self.assertEqual(SELECT, self.wrapper.queryType, 'unknown queries result in SELECT') 353 354 def testSetQueryEncodingIssues(self): 355 #further details from issue #35 356 query = u'INSERT DATA { <urn:michel> <urn:says> "これはテストです" }' 357 query_bytes = query.encode('utf-8') 358 359 self.wrapper.setMethod(POST) 360 self.wrapper.setRequestMethod(POSTDIRECTLY) 361 362 self.wrapper.setQuery(query) 363 request = self._get_request(self.wrapper) 364 self.assertEquals(query_bytes, request.data) 365 366 self.wrapper.setQuery(query_bytes) 367 request = self._get_request(self.wrapper) 368 self.assertEquals(query_bytes, request.data) 369 370 self.wrapper.setRequestMethod(URLENCODED) 371 372 self.wrapper.setQuery(query) 373 parameters = self._get_request_parameters_as_bytes(self.wrapper) 374 self.assertEquals(query_bytes, parameters['update'][0]) 375 376 self.wrapper.setQuery(query_bytes) 377 parameters = self._get_request_parameters_as_bytes(self.wrapper) 378 self.assertEquals(query_bytes, parameters['update'][0]) 379 380 try: 381 self.wrapper.setQuery(query.encode('sjis')) 382 self.fail() 383 except UnicodeDecodeError: 384 self.assertTrue(True) 385 386 try: 387 self.wrapper.setQuery({'foo': 'bar'}) 388 self.fail() 389 except TypeError: 390 self.assertTrue(True) 391 392 def testSetTimeout(self): 393 self.wrapper.setTimeout(10) 394 self.assertEqual(10, self.wrapper.timeout) 395 396 self.wrapper.resetQuery() 397 self.assertEqual(None, self.wrapper.timeout) 398 399 def testClearParameter(self): 400 self.wrapper.addParameter('param1', 'value1') 401 self.wrapper.addParameter('param1', 'value2') 402 self.wrapper.addParameter('param2', 'value2') 403 404 self.assertFalse(self.wrapper.clearParameter('query')) 405 self.assertTrue(self.wrapper.clearParameter('param1')) 406 407 pieces = self._get_request_parameters(self.wrapper) 408 409 self.assertFalse('param1' in pieces) 410 self.assertTrue('param2' in pieces) 411 self.assertEqual(['value2'], pieces['param2']) 412 413 self.assertFalse(self.wrapper.clearParameter('param1'), 'already cleaned') 414 415 def testSetMethod(self): 416 self.wrapper.setMethod(POST) 417 request = self._get_request(self.wrapper) 418 419 self.assertEqual("POST", request.get_method()) 420 421 self.wrapper.setMethod(GET) 422 request = self._get_request(self.wrapper) 423 424 self.assertEqual("GET", request.get_method()) 425 426 def testSetRequestMethod(self): 427 self.assertEqual(URLENCODED, self.wrapper.requestMethod) 428 429 self.wrapper.setRequestMethod(POSTDIRECTLY) 430 self.assertEqual(POSTDIRECTLY, self.wrapper.requestMethod) 431 432 def testIsSparqlUpdateRequest(self): 433 self.wrapper.setQuery('DELETE WHERE {?s ?p ?o}') 434 self.assertTrue(self.wrapper.isSparqlUpdateRequest()) 435 436 self.wrapper.setQuery('DELETE DATA { <urn:john> <urn:likes> <urn:surfing> }') 437 self.assertTrue(self.wrapper.isSparqlUpdateRequest()) 438 439 self.wrapper.setQuery(""" 440 PREFIX example: <http://example.org/SELECT/> 441 BASE <http://example.org/SELECT> 442 DELETE WHERE {?s ?p ?o} 443 """) 444 self.assertTrue(self.wrapper.isSparqlUpdateRequest()) 445 446 self.wrapper.setQuery('WITH <urn:graph> DELETE DATA { <urn:john> <urn:likes> <urn:surfing> }') 447 self.assertTrue(self.wrapper.isSparqlUpdateRequest()) 448 449 self.wrapper.setQuery('INSERT DATA { <urn:john> <urn:likes> <urn:surfing> }') 450 self.assertTrue(self.wrapper.isSparqlUpdateRequest()) 451 452 self.wrapper.setQuery('WITH <urn:graph> INSERT DATA { <urn:john> <urn:likes> <urn:surfing> }') 453 self.assertTrue(self.wrapper.isSparqlUpdateRequest()) 454 455 self.wrapper.setQuery('CREATE GRAPH <urn:graph>') 456 self.assertTrue(self.wrapper.isSparqlUpdateRequest()) 457 458 self.wrapper.setQuery('CLEAR GRAPH <urn:graph>') 459 self.assertTrue(self.wrapper.isSparqlUpdateRequest()) 460 461 self.wrapper.setQuery('DROP GRAPH <urn:graph>') 462 self.assertTrue(self.wrapper.isSparqlUpdateRequest()) 463 464 self.wrapper.setQuery('MOVE GRAPH <urn:graph1> TO GRAPH <urn:graph2>') 465 self.assertTrue(self.wrapper.isSparqlUpdateRequest()) 466 467 self.wrapper.setQuery('LOAD <http://localhost/file.rdf> INTO GRAPH <urn:graph>') 468 self.assertTrue(self.wrapper.isSparqlUpdateRequest()) 469 470 self.wrapper.setQuery('COPY <urn:graph1> TO GRAPH <urn:graph2>') 471 self.assertTrue(self.wrapper.isSparqlUpdateRequest()) 472 473 self.wrapper.setQuery('ADD <urn:graph1> TO GRAPH <urn:graph2>') 474 self.assertTrue(self.wrapper.isSparqlUpdateRequest()) 475 476 def testIsSparqlQueryRequest(self): 477 self.wrapper.setQuery('SELECT * WHERE {?s ?p ?o}') 478 self.assertTrue(self.wrapper.isSparqlQueryRequest()) 479 480 self.wrapper.setQuery(""" 481 PREFIX example: <http://example.org/DELETE/> 482 BASE <http://example.org/MODIFY> 483 ASK WHERE {?s ?p ?o} 484 """) 485 self.assertTrue(self.wrapper.isSparqlQueryRequest()) 486 self.assertFalse(self.wrapper.isSparqlUpdateRequest()) 487 488 def testQuery(self): 489 qr = self.wrapper.query() 490 self.assertTrue(isinstance(qr, QueryResult)) 491 492 request = qr.response.request # possible due to mock above 493 self.assertTrue(isinstance(request, Request)) 494 495 parameters = self._get_parameters_from_request(request) 496 self.assertTrue('query' in parameters) 497 self.assertTrue('update' not in parameters) 498 499 self.wrapper.setMethod(POST) 500 self.wrapper.setQuery('PREFIX e: <http://example.org/> INSERT {e:a e:b e:c}') 501 parameters = self._get_request_parameters(self.wrapper) 502 self.assertTrue('update' in parameters) 503 self.assertTrue('query' not in parameters) 504 #_returnFormatSetting = ["format", "output", "results"] 505 self.assertTrue('format' not in parameters) 506 self.assertTrue('output' not in parameters) 507 self.assertTrue('results' not in parameters) 508 509 _victim.urlopener = urlopener_error_generator(400) 510 try: 511 self.wrapper.query() 512 self.fail('should have raised exception') 513 except QueryBadFormed as e: 514 # TODO: check exception-format 515 pass 516 except: 517 self.fail('got wrong exception') 518 519 _victim.urlopener = urlopener_error_generator(401) 520 try: 521 self.wrapper.query() 522 self.fail('should have raised exception') 523 except Unauthorized as e: 524 # TODO: check exception-format 525 pass 526 except: 527 self.fail('got wrong exception') 528 529 _victim.urlopener = urlopener_error_generator(404) 530 try: 531 self.wrapper.query() 532 self.fail('should have raised exception') 533 except EndPointNotFound as e: 534 # TODO: check exception-format 535 pass 536 except: 537 self.fail('got wrong exception') 538 539 _victim.urlopener = urlopener_error_generator(414) 540 try: 541 self.wrapper.query() 542 self.fail('should have raised exception') 543 except URITooLong as e: 544 # TODO: check exception-format 545 pass 546 except: 547 self.fail('got wrong exception') 548 549 _victim.urlopener = urlopener_error_generator(500) 550 try: 551 self.wrapper.query() 552 self.fail('should have raised exception') 553 except EndPointInternalError as e: 554 # TODO: check exception-format 555 pass 556 except: 557 self.fail('got wrong exception') 558 559 _victim.urlopener = urlopener_error_generator(999) 560 try: 561 self.wrapper.query() 562 self.fail('should have raised exception') 563 except HTTPError as e: 564 # TODO: check exception-format 565 pass 566 except: 567 self.fail('got wrong exception') 568 569 def testQueryEncoding(self): 570 query = 'INSERT DATA { <urn:michel> <urn:says> "é" }' 571 572 wrapper = SPARQLWrapper('http://example.com:3030/example') 573 wrapper.setMethod(POST) 574 wrapper.setRequestMethod(URLENCODED) 575 wrapper.setQuery(query) 576 577 _victim.urlopener = urlopener_check_data_encoding 578 wrapper.query() 579 580 def testQueryAndConvert(self): 581 _oldQueryResult = _victim.QueryResult 582 583 class FakeQueryResult(object): 584 def __init__(self, result): 585 pass 586 587 def convert(self): 588 return True 589 590 try: 591 _victim.QueryResult = FakeQueryResult 592 result = self.wrapper.queryAndConvert() 593 self.assertEqual(True, result) 594 finally: 595 _victim.QueryResult = _oldQueryResult 596 597 def testComments(self): 598 # see issue #32 599 self.wrapper.setQuery(""" 600# this is a comment 601select * where { ?s ?p ?o } 602""") 603 self.assertTrue(self.wrapper.isSparqlQueryRequest()) 604 605 def testHashInPrefixes(self): 606 # see issue #77 607 self.wrapper.setQuery(""" 608PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> 609select * where { ?s ?p ?o } 610""") 611 self.assertTrue(self.wrapper.isSparqlQueryRequest()) 612 613 def testHashInPrefixComplex(self): 614 # see issue #77 615 self.wrapper.setQuery(""" 616PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 617PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> 618PREFIX weather: <http://hal.zamia.org/weather/> 619PREFIX dbo: <http://dbpedia.org/ontology/> 620PREFIX dbr: <http://dbpedia.org/resource/> 621PREFIX dbp: <http://dbpedia.org/property/> 622PREFIX xml: <http://www.w3.org/XML/1998/namespace> 623PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> 624 625SELECT DISTINCT ?location ?cityid ?timezone ?label 626WHERE { 627 ?location weather:cityid ?cityid . 628 ?location weather:timezone ?timezone . 629 ?location rdfs:label ?label . 630} 631""") 632 self.assertTrue(self.wrapper.isSparqlQueryRequest()) 633 634 def testHashWithNoComments(self): 635 # see issue #77 636 query = """ 637PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 638 639SELECT * 640WHERE { 641 ?s ?p ?o . 642} 643""" 644 parsed_query = self.wrapper._cleanComments(query) 645 self.assertEquals(query, parsed_query) 646 647 def testCommentBeginningLine(self): 648 # see issue #77 649 query = """ 650PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 651# a comment 652SELECT * 653WHERE { 654 ?s ?p ?o . 655} 656""" 657 expected_parsed_query = """ 658PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 659 660SELECT * 661WHERE { 662 ?s ?p ?o . 663} 664""" 665 parsed_query = self.wrapper._cleanComments(query) 666 self.assertEquals(expected_parsed_query, parsed_query) 667 668 def testCommentEmtpyLine(self): 669 # see issue #77 670 query = """ 671PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 672 # a comment 673SELECT * 674WHERE { 675 ?s ?p ?o . 676} 677""" 678 expected_parsed_query = """ 679PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 680 681SELECT * 682WHERE { 683 ?s ?p ?o . 684} 685""" 686 parsed_query = self.wrapper._cleanComments(query) 687 self.assertEquals(expected_parsed_query, parsed_query) 688 689 def testCommentsFirstLine(self): 690 # see issue #77 691 query = """#CONSTRUCT {?s ?p ?o} 692 SELECT ?s ?p ?o 693 WHERE {?s ?p ?o}""" 694 expected_parsed_query = """ 695 696 SELECT ?s ?p ?o 697 WHERE {?s ?p ?o}""" 698 699 parsed_query = self.wrapper._cleanComments(query) 700 self.assertEquals(expected_parsed_query, parsed_query) 701 702 @unittest.skip("issue #80") 703 def testCommentAfterStatements(self): 704 # see issue #77 705 query = """ 706PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 707 708SELECT * 709WHERE { # this is the where condition 710 ?s ?p ?o . 711} 712""" 713 expected_parsed_query = """ 714PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 715 716SELECT * 717WHERE { 718 ?s ?p ?o . 719} 720""" 721 parsed_query = self.wrapper._cleanComments(query) 722 self.assertEquals(expected_parsed_query, parsed_query) 723 724 def testSingleLineQueryLine(self): 725 # see issue #74 726 query = "prefix whatever: <http://example.org/blah#> ASK { ?s ?p ?o }" 727 parsed_query = self.wrapper._cleanComments(query) 728 self.assertEquals(query, parsed_query) 729 730 self.wrapper.setQuery(query) 731 self.assertTrue(self.wrapper.isSparqlQueryRequest()) 732 733 def testOnlyConneg(self): 734 # see issue #82 735 query = "prefix whatever: <http://example.org/blah#> ASK { ?s ?p ?o }" 736 self.wrapper.setOnlyConneg(False) 737 self.wrapper.setQuery(query) 738 request = self._get_request(self.wrapper) 739 request_params = dict(parse_qsl(urlparse(request.get_full_url()).query)) 740 for returnFormatSetting in ["format", "output", "results"]: # Obviously _returnFormatSetting is not accessible from SPARQLWrapper, so we copy&paste the possible values 741 self.assertTrue(returnFormatSetting in request_params, "URL parameter '%s' was not sent, and it was expected" %returnFormatSetting) 742 743 #ONLY Content Negotiation 744 self.wrapper.resetQuery() 745 self.wrapper.setOnlyConneg(True) 746 self.wrapper.setQuery(query) 747 request = self._get_request(self.wrapper) 748 request_params = dict(parse_qsl(urlparse(request.get_full_url()).query)) 749 for returnFormatSetting in ["format", "output", "results"]: # Obviously _returnFormatSetting is not accessible from SPARQLWrapper, so we copy&paste the possible values 750 self.assertFalse(returnFormatSetting in request_params, "URL parameter '%s' was sent, and it was not expected (only Content Negotiation)" %returnFormatSetting) 751 752 753class QueryResult_Test(unittest.TestCase): 754 755 def testConstructor(self): 756 qr = QueryResult('result') 757 self.assertEqual('result', qr.response) 758 try: 759 format = qr.requestedFormat 760 self.fail('format is not supposed to be set') 761 except: 762 pass 763 764 qr = QueryResult(('result', 'format')) 765 self.assertEqual('result', qr.response) 766 self.assertEqual('format', qr.requestedFormat) 767 768 def testProxyingToResponse(self): 769 class FakeResponse(object): 770 def __init__(self): 771 self.geturl_called = False 772 self.info_called = False 773 self.iter_called = False 774 self.next_called = False 775 776 def geturl(self): 777 self.geturl_called = True 778 779 def info(self): 780 self.info_called = True 781 return {"key": "value"} 782 783 def __iter__(self): 784 self.iter_called = True 785 786 def next(self): 787 self.next_called = True 788 789 result = FakeResponse() 790 791 qr = QueryResult(result) 792 qr.geturl() 793 qr.__iter__() 794 qr.next() 795 796 self.assertTrue(result.geturl_called) 797 self.assertTrue(result.iter_called) 798 self.assertTrue(result.next_called) 799 800 info = qr.info() 801 self.assertTrue(result.info_called) 802 self.assertEqual('value', info.__getitem__('KEY'), 'keys should be case-insensitive') 803 804 def testConvert(self): 805 class FakeResponse(object): 806 def __init__(self, content_type): 807 self.content_type = content_type 808 809 def info(self): 810 return {"Content-type": self.content_type} 811 812 def read(self, len): 813 return '' 814 815 def _mime_vs_type(mime, requested_type): 816 """ 817 :param mime: mimetype/Content-Type of the response 818 :param requested_type: requested mimetype (alias) 819 :return: number of warnings produced by combo 820 """ 821 with warnings.catch_warnings(record=True) as w: 822 qr = QueryResult((FakeResponse(mime), requested_type)) 823 824 try: 825 qr.convert() 826 except: 827 pass 828 829 return len(w) 830 831 # In the cases of "application/ld+json" and "application/rdf+xml", the 832 # RDFLib raised a warning because the manually created QueryResult has no real 833 # response value (implemented a fake read). 834 # "WARNING:rdflib.term: does not look like a valid URI, trying to serialize this will break." 835 self.assertEqual(0, _mime_vs_type("application/sparql-results+xml", XML)) 836 self.assertEqual(0, _mime_vs_type("application/sparql-results+json", JSON)) 837 self.assertEqual(0, _mime_vs_type("text/n3", N3)) 838 self.assertEqual(0, _mime_vs_type("text/turtle", TURTLE)) 839 self.assertEqual(0, _mime_vs_type("application/turtle", TURTLE)) 840 self.assertEqual(0, _mime_vs_type("application/ld+json", JSON)) # Warning 841 self.assertEqual(0, _mime_vs_type("application/ld+json", JSONLD)) # Warning 842 self.assertEqual(0, _mime_vs_type("application/rdf+xml", XML)) # Warning 843 self.assertEqual(0, _mime_vs_type("application/rdf+xml", RDF)) # Warning 844 self.assertEqual(0, _mime_vs_type("application/rdf+xml", RDFXML)) # Warning 845 self.assertEqual(0, _mime_vs_type("text/csv", CSV)) 846 self.assertEqual(0, _mime_vs_type("text/tab-separated-values", TSV)) 847 self.assertEqual(0, _mime_vs_type("application/xml", XML)) 848 849 self.assertEqual(1, _mime_vs_type("application/x-foo-bar", XML), "invalid mime") 850 851 self.assertEqual(1, _mime_vs_type("application/sparql-results+xml", N3)) 852 self.assertEqual(1, _mime_vs_type("application/sparql-results+json", XML)) 853 self.assertEqual(1, _mime_vs_type("text/n3", JSON)) 854 self.assertEqual(1, _mime_vs_type("text/turtle", XML)) 855 self.assertEqual(1, _mime_vs_type("application/ld+json", XML)) # Warning 856 self.assertEqual(1, _mime_vs_type("application/ld+json", N3)) # Warning 857 self.assertEqual(1, _mime_vs_type("application/rdf+xml", JSON)) # Warning 858 self.assertEqual(1, _mime_vs_type("application/rdf+xml", N3)) # Warning 859 860 def testPrint_results(self): 861 """ 862 print_results() is only allowed for JSON return format. 863 """ 864 class FakeResponse(object): 865 def __init__(self, content_type): 866 self.content_type = content_type 867 868 def info(self): 869 return {"Content-type": self.content_type} 870 871 def read(self, len): 872 return '' 873 874 def _print_results(mime): 875 """ 876 :param mime: mimetype/Content-Type of the response 877 :return: number of warnings produced by combo 878 """ 879 with warnings.catch_warnings(record=True) as w: 880 qr = QueryResult(FakeResponse(mime)) 881 882 try: 883 qr.print_results() 884 except: 885 pass 886 887 return len(w) 888 889 self.assertEqual(0, _print_results("application/sparql-results+json")) 890 self.assertEqual(0, _print_results("application/json")) 891 self.assertEqual(0, _print_results("text/javascript")) 892 self.assertEqual(0, _print_results("application/javascript")) 893 894 self.assertEqual(1, _print_results("application/sparql-results+xml")) 895 self.assertEqual(1, _print_results("application/xml")) 896 self.assertEqual(1, _print_results("application/rdf+xml")) 897 898 self.assertEqual(1, _print_results("application/turtle")) 899 self.assertEqual(1, _print_results("text/turtle")) 900 901 self.assertEqual(1, _print_results("text/rdf+n3")) 902 self.assertEqual(1, _print_results("application/n-triples")) 903 self.assertEqual(1, _print_results("application/n3")) 904 self.assertEqual(1, _print_results("text/n3")) 905 906 self.assertEqual(1, _print_results("text/csv")) 907 908 self.assertEqual(1, _print_results("text/tab-separated-values")) 909 910 self.assertEqual(1, _print_results("application/ld+json")) 911 self.assertEqual(1, _print_results("application/x-json+ld")) 912 913 self.assertEqual(2, _print_results("application/x-foo-bar")) 914 915 916class QueryType_Time_Test(unittest.TestCase): 917 918 def testQueries(self): 919 sparql = SPARQLWrapper("http://example.org/sparql") 920 921 queries = [] 922 923 queries.append(""" 924 PREFIX a: <http://dbpedia.org/a> 925 PREFIX b: <http://dbpedia.org/b> 926 PREFIX c: <http://dbpedia.org/c> 927 PREFIX d: <http://dbpedia.org/d> 928 PREFIX e: <http://dbpedia.org/e> 929 PREFIX f: <http://dbpedia.org/f> 930 PREFIX g: <http://dbpedia.org/g> 931 PREFIX h: <http://dbpedia.org/h> 932 FROM <http://dbpedia.org> 933 SELECT ?s ?p ?o WHERE { 934 ?s ?p ?o. 935 }""") 936 937 queries.append("""PREFIX a: <http://dbpedia.org/a> 938 PREFIX b: <http://dbpedia.org/b> 939 PREFIX c: <http://dbpedia.org/c> 940 PREFIX d: <http://dbpedia.org/d> 941 PREFIX e: <http://dbpedia.org/e> 942 PREFIX f: <http://dbpedia.org/f> 943 PREFIX g: <http://dbpedia.org/g> 944 PREFIX h: <http://dbpedia.org/h> 945 FROM <http://dbpedia.org> 946 SELECT ?s ?p ?o WHERE { 947 ?s ?p ?o. 948 }""") 949 950 queries.append("""PREFIX a: <http://dbpedia.org/a> 951PREFIX b: <http://dbpedia.org/b> 952PREFIX c: <http://dbpedia.org/c> 953PREFIX d: <http://dbpedia.org/d> 954PREFIX e: <http://dbpedia.org/e> 955PREFIX f: <http://dbpedia.org/f> 956PREFIX g: <http://dbpedia.org/g> 957PREFIX h: <http://dbpedia.org/h> 958FROM <http://dbpedia.org> 959SELECT ?s ?p ?o WHERE { 960 ?s ?p ?o. 961}""") 962 963 964 queries.append("""PREFIX a: <http://dbpedia.org/a> 965PREFIX b: <http://dbpedia.org/b> 966PREFIX c: <http://dbpedia.org/c> 967PREFIX d: <http://dbpedia.org/d> 968PREFIX e: <http://dbpedia.org/e> 969PREFIX f: <http://dbpedia.org/f> 970PREFIX g: <http://dbpedia.org/g> 971PREFIX h: <http://dbpedia.org/h> 972SELECT ?s ?p ?o WHERE { 973 ?s ?p ?o. 974}""") 975 976 977 queries.append(""" 978 PREFIX a: <http://dbpedia.org/a> 979 PREFIX b: <http://dbpedia.org/b> 980 PREFIX c: <http://dbpedia.org/c> 981 PREFIX d: <http://dbpedia.org/d> 982 PREFIX e: <http://dbpedia.org/e> 983 PREFIX f: <http://dbpedia.org/f> 984 PREFIX g: <http://dbpedia.org/g> 985 PREFIX h: <http://dbpedia.org/h> 986 SELECT ?s ?p ?o WHERE { 987 ?s ?p ?o. 988 }""") 989 990 991 queries.append(""" 992 FROM <http://dbpedia.org> 993 SELECT ?s ?p ?o WHERE { 994 ?s ?p ?o. 995 }""") 996 997 998 queries.append(""" 999 PREFIX a: <http://dbpedia.org/a> 1000 PREFIX b: <http://dbpedia.org/b> 1001 PREFIX c: <http://dbpedia.org/c> 1002 PREFIX d: <http://dbpedia.org/d> 1003 PREFIX e: <http://dbpedia.org/e> 1004 PREFIX f: <http://dbpedia.org/f> 1005 PREFIX g: <http://dbpedia.org/g> 1006 PREFIX h: <http://dbpedia.org/h> 1007 PREFIX a: <http://dbpedia.org/a> 1008 PREFIX b: <http://dbpedia.org/b> 1009 PREFIX c: <http://dbpedia.org/c> 1010 PREFIX d: <http://dbpedia.org/d> 1011 PREFIX e: <http://dbpedia.org/e> 1012 PREFIX f: <http://dbpedia.org/f> 1013 PREFIX g: <http://dbpedia.org/g> 1014 PREFIX h: <http://dbpedia.org/h> 1015 PREFIX a: <http://dbpedia.org/a> 1016 PREFIX b: <http://dbpedia.org/b> 1017 PREFIX c: <http://dbpedia.org/c> 1018 PREFIX d: <http://dbpedia.org/d> 1019 PREFIX e: <http://dbpedia.org/e> 1020 PREFIX f: <http://dbpedia.org/f> 1021 PREFIX g: <http://dbpedia.org/g> 1022 PREFIX h: <http://dbpedia.org/h> 1023 FROM <http://dbpedia.org> 1024 SELECT ?s ?p ?o WHERE { 1025 ?s ?p ?o. 1026 }""") 1027 1028 queries.append("""PREFIX a: <http://dbpedia.org/a> 1029 PREFIX b: <http://dbpedia.org/b> 1030 PREFIX c: <http://dbpedia.org/c> 1031 PREFIX d: <http://dbpedia.org/d> 1032 PREFIX e: <http://dbpedia.org/e> 1033 PREFIX f: <http://dbpedia.org/f> 1034 PREFIX g: <http://dbpedia.org/g> 1035 PREFIX h: <http://dbpedia.org/h> 1036 PREFIX a: <http://dbpedia.org/a> 1037 PREFIX b: <http://dbpedia.org/b> 1038 PREFIX c: <http://dbpedia.org/c> 1039 PREFIX d: <http://dbpedia.org/d> 1040 PREFIX e: <http://dbpedia.org/e> 1041 PREFIX f: <http://dbpedia.org/f> 1042 PREFIX g: <http://dbpedia.org/g> 1043 PREFIX h: <http://dbpedia.org/h> 1044 PREFIX a: <http://dbpedia.org/a> 1045 PREFIX b: <http://dbpedia.org/b> 1046 PREFIX c: <http://dbpedia.org/c> 1047 PREFIX d: <http://dbpedia.org/d> 1048 PREFIX e: <http://dbpedia.org/e> 1049 PREFIX f: <http://dbpedia.org/f> 1050 PREFIX g: <http://dbpedia.org/g> 1051 PREFIX h: <http://dbpedia.org/h> 1052 FROM <http://dbpedia.org> 1053 SELECT ?s ?p ?o WHERE { 1054 ?s ?p ?o. 1055 }""") 1056 1057 for query in queries: 1058 start_time = time.time() 1059 sparql.setQuery(query) 1060 self.assertTrue((time.time()-start_time)<0.001) # less than 0.001 second 1061 1062 1063if __name__ == "__main__": 1064 unittest.main() 1065