processor.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. """
  2. Code for tying SPARQL Engine into RDFLib
  3. These should be automatically registered with RDFLib
  4. """
  5. from __future__ import annotations
  6. from typing import Any, Mapping, Optional, Union
  7. from rdflib.graph import Graph
  8. from rdflib.plugins.sparql.algebra import translateQuery, translateUpdate
  9. from rdflib.plugins.sparql.evaluate import evalQuery
  10. from rdflib.plugins.sparql.parser import parseQuery, parseUpdate
  11. from rdflib.plugins.sparql.sparql import Query, Update
  12. from rdflib.plugins.sparql.update import evalUpdate
  13. from rdflib.query import Processor, Result, UpdateProcessor
  14. from rdflib.term import Identifier
  15. def prepareQuery(
  16. queryString: str,
  17. initNs: Optional[Mapping[str, Any]] = None,
  18. base: Optional[str] = None,
  19. ) -> Query:
  20. """
  21. Parse and translate a SPARQL Query
  22. """
  23. if initNs is None:
  24. initNs = {}
  25. ret = translateQuery(parseQuery(queryString), base, initNs)
  26. ret._original_args = (queryString, initNs, base)
  27. return ret
  28. def prepareUpdate(
  29. updateString: str,
  30. initNs: Optional[Mapping[str, Any]] = None,
  31. base: Optional[str] = None,
  32. ) -> Update:
  33. """
  34. Parse and translate a SPARQL Update
  35. """
  36. if initNs is None:
  37. initNs = {}
  38. ret = translateUpdate(parseUpdate(updateString), base, initNs)
  39. ret._original_args = (updateString, initNs, base)
  40. return ret
  41. def processUpdate(
  42. graph: Graph,
  43. updateString: str,
  44. initBindings: Optional[Mapping[str, Identifier]] = None,
  45. initNs: Optional[Mapping[str, Any]] = None,
  46. base: Optional[str] = None,
  47. ) -> None:
  48. """
  49. Process a SPARQL Update Request
  50. returns Nothing on success or raises Exceptions on error
  51. """
  52. evalUpdate(
  53. graph, translateUpdate(parseUpdate(updateString), base, initNs), initBindings
  54. )
  55. class SPARQLResult(Result):
  56. def __init__(self, res: Mapping[str, Any]):
  57. Result.__init__(self, res["type_"])
  58. self.vars = res.get("vars_")
  59. # type error: Incompatible types in assignment (expression has type "Optional[Any]", variable has type "MutableSequence[Mapping[Variable, Identifier]]")
  60. self.bindings = res.get("bindings") # type: ignore[assignment]
  61. self.askAnswer = res.get("askAnswer")
  62. self.graph = res.get("graph")
  63. class SPARQLUpdateProcessor(UpdateProcessor):
  64. def __init__(self, graph):
  65. self.graph = graph
  66. def update(
  67. self,
  68. strOrQuery: Union[str, Update],
  69. initBindings: Optional[Mapping[str, Identifier]] = None,
  70. initNs: Optional[Mapping[str, Any]] = None,
  71. ) -> None:
  72. """
  73. !!! warning "Caution"
  74. This method can access indirectly requested network endpoints, for
  75. example, query processing will attempt to access network endpoints
  76. specified in `SERVICE` directives.
  77. When processing untrusted or potentially malicious queries, measures
  78. should be taken to restrict network and file access.
  79. For information on available security measures, see the RDFLib
  80. [Security Considerations](../security_considerations.md)
  81. documentation.
  82. """
  83. if isinstance(strOrQuery, str):
  84. strOrQuery = translateUpdate(parseUpdate(strOrQuery), initNs=initNs)
  85. return evalUpdate(self.graph, strOrQuery, initBindings)
  86. class SPARQLProcessor(Processor):
  87. def __init__(self, graph):
  88. self.graph = graph
  89. # NOTE on type error: this is because the super type constructor does not
  90. # accept base argument and thie position of the DEBUG argument is
  91. # different.
  92. # type error: Signature of "query" incompatible with supertype "Processor"
  93. def query( # type: ignore[override]
  94. self,
  95. strOrQuery: Union[str, Query],
  96. initBindings: Optional[Mapping[str, Identifier]] = None,
  97. initNs: Optional[Mapping[str, Any]] = None,
  98. base: Optional[str] = None,
  99. DEBUG: bool = False,
  100. ) -> Mapping[str, Any]:
  101. """
  102. Evaluate a query with the given initial bindings, and initial
  103. namespaces. The given base is used to resolve relative URIs in
  104. the query and will be overridden by any BASE given in the query.
  105. !!! warning "Caution"
  106. This method can access indirectly requested network endpoints, for
  107. example, query processing will attempt to access network endpoints
  108. specified in `SERVICE` directives.
  109. When processing untrusted or potentially malicious queries, measures
  110. should be taken to restrict network and file access.
  111. For information on available security measures, see the RDFLib
  112. [Security Considerations](../security_considerations.md)
  113. documentation.
  114. """
  115. if isinstance(strOrQuery, str):
  116. strOrQuery = translateQuery(parseQuery(strOrQuery), base, initNs)
  117. return evalQuery(self.graph, strOrQuery, initBindings, base)