sparql.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. import json
  2. import requests
  3. from dokk import settings
  4. from pyld import jsonld
  5. def escape_literal(literal=''):
  6. """
  7. Escape a string literal to insert in a SPARQL query
  8. https://www.w3.org/TR/turtle/#sec-escapes
  9. """
  10. return literal.translate(str.maketrans({
  11. '\t': r'\t',
  12. '\b': r'\b',
  13. '\n': r'\n',
  14. '\r': r'\r',
  15. '\f': r'\f',
  16. '"': r'\"',
  17. "'": r'\'',
  18. '\\': r'\\',
  19. '\x00': r'\x00', # NULL
  20. '\x1a': r'\x1a' # Ctrl+Z
  21. }))
  22. def escape_term(term=''):
  23. """
  24. Escape the local name of a term to insert in a SPARQL query.
  25. It's the part after the prefix, eg. "schema:name".
  26. https://www.w3.org/TR/turtle/#sec-escapes
  27. """
  28. return term.translate(str.maketrans({
  29. '~': r'\~',
  30. '.': r'\.',
  31. '-': r'\-',
  32. '!': r'\!',
  33. '$': r'\$',
  34. '&': r'\&',
  35. "'": r'\'',
  36. '(': r'\(',
  37. ')': r'\)',
  38. '*': r'\*',
  39. '+': r'\+',
  40. ',': r'\,',
  41. ';': r'\;',
  42. '=': r'\=',
  43. '/': r'\/',
  44. '?': r'\?',
  45. '#': r'\#',
  46. '@': r'\@',
  47. '%': r'\%',
  48. '_': r'\_'
  49. }))
  50. def query(query_string, endpoint, timeout=60, data={}):
  51. """
  52. Query a SPARQL endpoint.
  53. :param query_string: The SPARQL query.
  54. :param endpoint: The URL to be queries. Must be a SPARQL endpoint.
  55. :param timeout: How long to wait for a reply before giving up.
  56. :param data: Additional parameters to be sent along with the request.
  57. """
  58. response = requests.post(
  59. endpoint,
  60. timeout = timeout,
  61. data = { 'format': 'json',
  62. 'query': query_string,
  63. **data })
  64. return response.json()
  65. def update(query_string, endpoint, timeout=60):
  66. """
  67. Update a SPARQL endpoint.
  68. """
  69. response = requests.post(
  70. endpoint,
  71. timeout = timeout,
  72. data = { 'update': query_string })
  73. return response.status_code == 200
  74. def query_instance(query_string):
  75. return query(query_string, settings['sparql.instance_query'])
  76. def query_graph(query_string):
  77. return query(query_string, settings['sparql.graph_query'])
  78. def query_public(query_string):
  79. # ?default-graph-uri=urn:x-arq:UnionGraph is a Fuseki special graph name
  80. # that instructs the server to consider the default graph as the union
  81. # of all named graphs. We use this because the public endpoint is composed
  82. # of the DOKK instance graph plus other imported graphs. See the Fuseki
  83. # configuration file for the list of named graphs.
  84. return query(query_string, settings['sparql.public_query'],
  85. data={'default-graph-uri': 'urn:x-arq:UnionGraph'})
  86. def update_instance(query_string):
  87. return update(query_string, settings['sparql.instance_update'])
  88. def update_graph(query_string):
  89. return update(query_string, settings['sparql.graph_update'])
  90. def frame(json_data, new_frame):
  91. """
  92. Apply a new frame to a JSON-LD document.
  93. https://w3c.github.io/json-ld-syntax/#framed-document-form
  94. """
  95. return jsonld.frame(json_data, new_frame)
  96. def expand(json_data):
  97. """
  98. Expand a JSON-LD document.
  99. https://w3c.github.io/json-ld-syntax/#expanded-document-form
  100. """
  101. return jsonld.expand(json_data)