plugin.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  1. """Plugin support for rdf.
  2. There are a number of plugin points for rdf: parser, serializer,
  3. store, query processor, and query result. Plugins can be registered
  4. either through setuptools entry_points or by calling
  5. rdf.plugin.register directly.
  6. If you have a package that uses a setuptools based `setup.py` you can add the
  7. following to your setup:
  8. ```python
  9. entry_points = {
  10. 'rdf.plugins.parser': [
  11. 'nt = rdf.plugins.parsers.ntriples:NTParser',
  12. ],
  13. 'rdf.plugins.serializer': [
  14. 'nt = rdf.plugins.serializers.NTSerializer:NTSerializer',
  15. ],
  16. }
  17. ```
  18. See the [setuptools dynamic discovery of services and plugins](http://peak.telecommunity.com/DevCenter/setuptools#dynamic-discovery-of-services-and-plugins)
  19. for moreinformation.
  20. """
  21. from __future__ import annotations
  22. from importlib.metadata import EntryPoint, entry_points
  23. from typing import (
  24. TYPE_CHECKING,
  25. Any,
  26. Dict,
  27. Generic,
  28. Iterator,
  29. Optional,
  30. Tuple,
  31. Type,
  32. TypeVar,
  33. overload,
  34. )
  35. import rdflib.plugins.stores.berkeleydb
  36. from rdflib.exceptions import Error
  37. from rdflib.parser import Parser
  38. from rdflib.query import (
  39. Processor,
  40. Result,
  41. ResultParser,
  42. ResultSerializer,
  43. UpdateProcessor,
  44. )
  45. from rdflib.serializer import Serializer
  46. from rdflib.store import Store
  47. __all__ = [
  48. "register",
  49. "get",
  50. "plugins",
  51. "PluginException",
  52. "Plugin",
  53. "PluginT",
  54. "PKGPlugin",
  55. ]
  56. rdflib_entry_points = {
  57. "rdf.plugins.store": Store,
  58. "rdf.plugins.serializer": Serializer,
  59. "rdf.plugins.parser": Parser,
  60. "rdf.plugins.resultparser": ResultParser,
  61. "rdf.plugins.resultserializer": ResultSerializer,
  62. "rdf.plugins.queryprocessor": Processor,
  63. "rdf.plugins.queryresult": Result,
  64. "rdf.plugins.updateprocessor": UpdateProcessor,
  65. }
  66. _plugins: Dict[Tuple[str, Type[Any]], Plugin] = {}
  67. class PluginException(Error): # noqa: N818
  68. pass
  69. #: A generic type variable for plugins
  70. PluginT = TypeVar("PluginT")
  71. class Plugin(Generic[PluginT]):
  72. def __init__(
  73. self, name: str, kind: Type[PluginT], module_path: str, class_name: str
  74. ):
  75. self.name = name
  76. self.kind = kind
  77. self.module_path = module_path
  78. self.class_name = class_name
  79. self._class: Optional[Type[PluginT]] = None
  80. def getClass(self) -> Type[PluginT]: # noqa: N802
  81. if self._class is None:
  82. module = __import__(self.module_path, globals(), locals(), [""])
  83. self._class = getattr(module, self.class_name)
  84. return self._class
  85. class PKGPlugin(Plugin[PluginT]):
  86. def __init__(self, name: str, kind: Type[PluginT], ep: EntryPoint):
  87. self.name = name
  88. self.kind = kind
  89. self.ep = ep
  90. self._class: Optional[Type[PluginT]] = None
  91. def getClass(self) -> Type[PluginT]: # noqa: N802
  92. if self._class is None:
  93. self._class = self.ep.load()
  94. return self._class
  95. def register(name: str, kind: Type[Any], module_path, class_name):
  96. """
  97. Register the plugin for (name, kind). The module_path and
  98. class_name should be the path to a plugin class.
  99. """
  100. p = Plugin(name, kind, module_path, class_name)
  101. _plugins[(name, kind)] = p
  102. def get(name: str, kind: Type[PluginT]) -> Type[PluginT]:
  103. """
  104. Return the class for the specified (name, kind). Raises a
  105. PluginException if unable to do so.
  106. """
  107. try:
  108. p: Plugin[PluginT] = _plugins[(name, kind)]
  109. except KeyError:
  110. raise PluginException("No plugin registered for (%s, %s)" % (name, kind))
  111. return p.getClass()
  112. all_entry_points = entry_points()
  113. if hasattr(all_entry_points, "select"):
  114. for entry_point, kind in rdflib_entry_points.items():
  115. for ep in all_entry_points.select(group=entry_point):
  116. _plugins[(ep.name, kind)] = PKGPlugin(ep.name, kind, ep)
  117. else:
  118. # Prior to Python 3.10, this returns a dict instead of the selection interface, which is slightly slower
  119. if TYPE_CHECKING:
  120. assert isinstance(all_entry_points, dict)
  121. for entry_point, kind in rdflib_entry_points.items():
  122. for ep in all_entry_points.get(entry_point, []):
  123. _plugins[(ep.name, kind)] = PKGPlugin(ep.name, kind, ep)
  124. @overload
  125. def plugins(
  126. name: Optional[str] = ..., kind: Type[PluginT] = ...
  127. ) -> Iterator[Plugin[PluginT]]: ...
  128. @overload
  129. def plugins(name: Optional[str] = ..., kind: None = ...) -> Iterator[Plugin]: ...
  130. def plugins(
  131. name: Optional[str] = None, kind: Optional[Type[PluginT]] = None
  132. ) -> Iterator[Plugin[PluginT]]:
  133. """
  134. A generator of the plugins.
  135. Pass in name and kind to filter... else leave None to match all.
  136. """
  137. for p in _plugins.values():
  138. if (name is None or name == p.name) and (kind is None or kind == p.kind):
  139. yield p
  140. # Register Stores
  141. if rdflib.plugins.stores.berkeleydb.has_bsddb:
  142. # Checks for BerkeleyDB before registering it
  143. register(
  144. "BerkeleyDB",
  145. Store,
  146. "rdflib.plugins.stores.berkeleydb",
  147. "BerkeleyDB",
  148. )
  149. register(
  150. "default",
  151. Store,
  152. "rdflib.plugins.stores.memory",
  153. "Memory",
  154. )
  155. register(
  156. "Memory",
  157. Store,
  158. "rdflib.plugins.stores.memory",
  159. "Memory",
  160. )
  161. register(
  162. "SimpleMemory",
  163. Store,
  164. "rdflib.plugins.stores.memory",
  165. "SimpleMemory",
  166. )
  167. register(
  168. "Auditable",
  169. Store,
  170. "rdflib.plugins.stores.auditable",
  171. "AuditableStore",
  172. )
  173. register(
  174. "Concurrent",
  175. Store,
  176. "rdflib.plugins.stores.concurrent",
  177. "ConcurrentStore",
  178. )
  179. register(
  180. "SPARQLStore",
  181. Store,
  182. "rdflib.plugins.stores.sparqlstore",
  183. "SPARQLStore",
  184. )
  185. register(
  186. "SPARQLUpdateStore",
  187. Store,
  188. "rdflib.plugins.stores.sparqlstore",
  189. "SPARQLUpdateStore",
  190. )
  191. # Register Triple Serializers
  192. register(
  193. "application/rdf+xml",
  194. Serializer,
  195. "rdflib.plugins.serializers.rdfxml",
  196. "XMLSerializer",
  197. )
  198. register(
  199. "xml",
  200. Serializer,
  201. "rdflib.plugins.serializers.rdfxml",
  202. "XMLSerializer",
  203. )
  204. register(
  205. "pretty-xml",
  206. Serializer,
  207. "rdflib.plugins.serializers.rdfxml",
  208. "PrettyXMLSerializer",
  209. )
  210. register(
  211. "text/n3",
  212. Serializer,
  213. "rdflib.plugins.serializers.n3",
  214. "N3Serializer",
  215. )
  216. register(
  217. "n3",
  218. Serializer,
  219. "rdflib.plugins.serializers.n3",
  220. "N3Serializer",
  221. )
  222. register(
  223. "text/turtle",
  224. Serializer,
  225. "rdflib.plugins.serializers.turtle",
  226. "TurtleSerializer",
  227. )
  228. register(
  229. "turtle",
  230. Serializer,
  231. "rdflib.plugins.serializers.turtle",
  232. "TurtleSerializer",
  233. )
  234. register(
  235. "ttl",
  236. Serializer,
  237. "rdflib.plugins.serializers.turtle",
  238. "TurtleSerializer",
  239. )
  240. register(
  241. "longturtle",
  242. Serializer,
  243. "rdflib.plugins.serializers.longturtle",
  244. "LongTurtleSerializer",
  245. )
  246. register(
  247. "application/n-triples",
  248. Serializer,
  249. "rdflib.plugins.serializers.nt",
  250. "NTSerializer",
  251. )
  252. register(
  253. "ntriples",
  254. Serializer,
  255. "rdflib.plugins.serializers.nt",
  256. "NTSerializer",
  257. )
  258. register(
  259. "nt",
  260. Serializer,
  261. "rdflib.plugins.serializers.nt",
  262. "NTSerializer",
  263. )
  264. register(
  265. "nt11",
  266. Serializer,
  267. "rdflib.plugins.serializers.nt",
  268. "NT11Serializer",
  269. )
  270. register(
  271. "json-ld",
  272. Serializer,
  273. "rdflib.plugins.serializers.jsonld",
  274. "JsonLDSerializer",
  275. )
  276. register(
  277. "application/ld+json",
  278. Serializer,
  279. "rdflib.plugins.serializers.jsonld",
  280. "JsonLDSerializer",
  281. )
  282. # Register Quad Serializers
  283. register(
  284. "application/n-quads",
  285. Serializer,
  286. "rdflib.plugins.serializers.nquads",
  287. "NQuadsSerializer",
  288. )
  289. register(
  290. "nquads",
  291. Serializer,
  292. "rdflib.plugins.serializers.nquads",
  293. "NQuadsSerializer",
  294. )
  295. register(
  296. "application/trix",
  297. Serializer,
  298. "rdflib.plugins.serializers.trix",
  299. "TriXSerializer",
  300. )
  301. register(
  302. "trix",
  303. Serializer,
  304. "rdflib.plugins.serializers.trix",
  305. "TriXSerializer",
  306. )
  307. register(
  308. "application/trig",
  309. Serializer,
  310. "rdflib.plugins.serializers.trig",
  311. "TrigSerializer",
  312. )
  313. register(
  314. "trig",
  315. Serializer,
  316. "rdflib.plugins.serializers.trig",
  317. "TrigSerializer",
  318. )
  319. register(
  320. "hext",
  321. Serializer,
  322. "rdflib.plugins.serializers.hext",
  323. "HextuplesSerializer",
  324. )
  325. register(
  326. "patch",
  327. Serializer,
  328. "rdflib.plugins.serializers.patch",
  329. "PatchSerializer",
  330. )
  331. # Register Triple Parsers
  332. register(
  333. "application/rdf+xml",
  334. Parser,
  335. "rdflib.plugins.parsers.rdfxml",
  336. "RDFXMLParser",
  337. )
  338. register(
  339. "xml",
  340. Parser,
  341. "rdflib.plugins.parsers.rdfxml",
  342. "RDFXMLParser",
  343. )
  344. register(
  345. "text/n3",
  346. Parser,
  347. "rdflib.plugins.parsers.notation3",
  348. "N3Parser",
  349. )
  350. register(
  351. "n3",
  352. Parser,
  353. "rdflib.plugins.parsers.notation3",
  354. "N3Parser",
  355. )
  356. register(
  357. "text/turtle",
  358. Parser,
  359. "rdflib.plugins.parsers.notation3",
  360. "TurtleParser",
  361. )
  362. register(
  363. "turtle",
  364. Parser,
  365. "rdflib.plugins.parsers.notation3",
  366. "TurtleParser",
  367. )
  368. register(
  369. "ttl",
  370. Parser,
  371. "rdflib.plugins.parsers.notation3",
  372. "TurtleParser",
  373. )
  374. register(
  375. "application/n-triples",
  376. Parser,
  377. "rdflib.plugins.parsers.ntriples",
  378. "NTParser",
  379. )
  380. register(
  381. "ntriples",
  382. Parser,
  383. "rdflib.plugins.parsers.ntriples",
  384. "NTParser",
  385. )
  386. register(
  387. "nt",
  388. Parser,
  389. "rdflib.plugins.parsers.ntriples",
  390. "NTParser",
  391. )
  392. register(
  393. "nt11",
  394. Parser,
  395. "rdflib.plugins.parsers.ntriples",
  396. "NTParser",
  397. )
  398. register(
  399. "application/ld+json",
  400. Parser,
  401. "rdflib.plugins.parsers.jsonld",
  402. "JsonLDParser",
  403. )
  404. register(
  405. "json-ld",
  406. Parser,
  407. "rdflib.plugins.parsers.jsonld",
  408. "JsonLDParser",
  409. )
  410. # Register Quad Parsers
  411. register(
  412. "application/n-quads",
  413. Parser,
  414. "rdflib.plugins.parsers.nquads",
  415. "NQuadsParser",
  416. )
  417. register(
  418. "nquads",
  419. Parser,
  420. "rdflib.plugins.parsers.nquads",
  421. "NQuadsParser",
  422. )
  423. register(
  424. "application/trix",
  425. Parser,
  426. "rdflib.plugins.parsers.trix",
  427. "TriXParser",
  428. )
  429. register(
  430. "trix",
  431. Parser,
  432. "rdflib.plugins.parsers.trix",
  433. "TriXParser",
  434. )
  435. register(
  436. "application/trig",
  437. Parser,
  438. "rdflib.plugins.parsers.trig",
  439. "TrigParser",
  440. )
  441. register(
  442. "trig",
  443. Parser,
  444. "rdflib.plugins.parsers.trig",
  445. "TrigParser",
  446. )
  447. register(
  448. "hext",
  449. Parser,
  450. "rdflib.plugins.parsers.hext",
  451. "HextuplesParser",
  452. )
  453. # Register RDF Patch Parsers
  454. register(
  455. "patch",
  456. Parser,
  457. "rdflib.plugins.parsers.patch",
  458. "RDFPatchParser",
  459. )
  460. # Register SPARQL Processors
  461. register(
  462. "sparql",
  463. Result,
  464. "rdflib.plugins.sparql.processor",
  465. "SPARQLResult",
  466. )
  467. register(
  468. "sparql",
  469. Processor,
  470. "rdflib.plugins.sparql.processor",
  471. "SPARQLProcessor",
  472. )
  473. register(
  474. "sparql",
  475. UpdateProcessor,
  476. "rdflib.plugins.sparql.processor",
  477. "SPARQLUpdateProcessor",
  478. )
  479. # Register SPARQL Result Serializers
  480. register(
  481. "xml",
  482. ResultSerializer,
  483. "rdflib.plugins.sparql.results.xmlresults",
  484. "XMLResultSerializer",
  485. )
  486. register(
  487. "application/sparql-results+xml",
  488. ResultSerializer,
  489. "rdflib.plugins.sparql.results.xmlresults",
  490. "XMLResultSerializer",
  491. )
  492. register(
  493. "txt",
  494. ResultSerializer,
  495. "rdflib.plugins.sparql.results.txtresults",
  496. "TXTResultSerializer",
  497. )
  498. register(
  499. "json",
  500. ResultSerializer,
  501. "rdflib.plugins.sparql.results.jsonresults",
  502. "JSONResultSerializer",
  503. )
  504. register(
  505. "application/sparql-results+json",
  506. ResultSerializer,
  507. "rdflib.plugins.sparql.results.jsonresults",
  508. "JSONResultSerializer",
  509. )
  510. register(
  511. "csv",
  512. ResultSerializer,
  513. "rdflib.plugins.sparql.results.csvresults",
  514. "CSVResultSerializer",
  515. )
  516. register(
  517. "text/csv",
  518. ResultSerializer,
  519. "rdflib.plugins.sparql.results.csvresults",
  520. "CSVResultSerializer",
  521. )
  522. # Register SPARQL Result Parsers
  523. register(
  524. "xml",
  525. ResultParser,
  526. "rdflib.plugins.sparql.results.xmlresults",
  527. "XMLResultParser",
  528. )
  529. register(
  530. "application/sparql-results+xml",
  531. ResultParser,
  532. "rdflib.plugins.sparql.results.xmlresults",
  533. "XMLResultParser",
  534. )
  535. register(
  536. "json",
  537. ResultParser,
  538. "rdflib.plugins.sparql.results.jsonresults",
  539. "JSONResultParser",
  540. )
  541. register(
  542. "application/sparql-results+json",
  543. ResultParser,
  544. "rdflib.plugins.sparql.results.jsonresults",
  545. "JSONResultParser",
  546. )
  547. register(
  548. "csv",
  549. ResultParser,
  550. "rdflib.plugins.sparql.results.csvresults",
  551. "CSVResultParser",
  552. )
  553. register(
  554. "text/csv",
  555. ResultParser,
  556. "rdflib.plugins.sparql.results.csvresults",
  557. "CSVResultParser",
  558. )
  559. register(
  560. "tsv",
  561. ResultParser,
  562. "rdflib.plugins.sparql.results.tsvresults",
  563. "TSVResultParser",
  564. )
  565. register(
  566. "text/tab-separated-values",
  567. ResultParser,
  568. "rdflib.plugins.sparql.results.tsvresults",
  569. "TSVResultParser",
  570. )
  571. graph_parsers = {parser.name for parser in plugins(kind=Parser)}
  572. result_parsers = {parser.name for parser in plugins(kind=ResultParser)}
  573. graph_result_parsers = graph_parsers - result_parsers
  574. for parser_name in graph_result_parsers:
  575. register(
  576. parser_name,
  577. ResultParser,
  578. "rdflib.plugins.sparql.results.graph",
  579. "GraphResultParser",
  580. )