Coverage for rdflib_ocdm/reader.py: 100%

56 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-11-01 22:02 +0000

1#!/usr/bin/python 

2# -*- coding: utf-8 -*- 

3# Copyright 2023-2025 Arcangelo Massari <arcangelo.massari@unibo.it> 

4# 

5# Permission to use, copy, modify, and/or distribute this software for any purpose 

6# with or without fee is hereby granted, provided that the above copyright notice 

7# and this permission notice appear in all copies. 

8# 

9# THE SOFTWARE IS PROVIDED 'AS IS' AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 

10# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 

11# FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, 

12# OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 

13# DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 

14# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 

15# SOFTWARE. 

16from __future__ import annotations 

17 

18from typing import List, Union 

19 

20from oc_ocdm.support.reporter import Reporter 

21from rdflib import Dataset, Graph, Literal, URIRef 

22from SPARQLWrapper import JSON, POST, XML, SPARQLWrapper 

23 

24from rdflib_ocdm.ocdm_graph import OCDMDataset, OCDMGraph 

25from rdflib_ocdm.retry_utils import execute_with_retry 

26 

27 

28class Reader(object): 

29 def __init__(self, repok: Reporter = None, reperr: Reporter = None): 

30 if repok is None: 

31 self.repok: Reporter = Reporter(prefix="[Reader: INFO] ") 

32 else: 

33 self.repok: Reporter = repok 

34 

35 if reperr is None: 

36 self.reperr: Reporter = Reporter(prefix="[Reader: ERROR] ") 

37 else: 

38 self.reperr: Reporter = reperr 

39 

40 @staticmethod 

41 def import_entities_from_triplestore(ocdm_graph: Union[OCDMGraph, OCDMDataset], ts_url: str, res_list: List[URIRef], max_retries: int = 5) -> None: 

42 sparql: SPARQLWrapper = SPARQLWrapper(ts_url) 

43 

44 if isinstance(ocdm_graph, OCDMDataset): 

45 query: str = f''' 

46 SELECT ?g ?s ?p ?o (LANG(?o) AS ?lang) 

47 WHERE {{ 

48 GRAPH ?g {{ 

49 ?s ?p ?o. 

50 VALUES ?s {{<{'> <'.join(res_list)}>}} 

51 }} 

52 }} 

53 ''' 

54 sparql.setQuery(query) 

55 sparql.setMethod(POST) 

56 sparql.setReturnFormat(JSON) 

57 

58 # Use the retry utility function instead of duplicating retry logic 

59 result = execute_with_retry( 

60 sparql.queryAndConvert, 

61 max_retries=max_retries 

62 ) 

63 

64 if result and 'results' in result and 'bindings' in result['results']: 

65 temp_graph = Dataset() 

66 for binding in result['results']['bindings']: 

67 graph_uri = Graph(identifier=URIRef(binding['g']['value'])) 

68 subject = URIRef(binding['s']['value']) 

69 predicate = URIRef(binding['p']['value']) 

70 

71 obj_data = binding['o'] 

72 if obj_data['type'] == 'uri': 

73 obj = URIRef(obj_data['value']) 

74 else: 

75 value = obj_data['value'] 

76 lang = binding.get('lang', {}).get('value') 

77 datatype = obj_data.get('datatype') 

78 

79 if lang: 

80 obj = Literal(value, lang=lang) 

81 elif datatype: 

82 obj = Literal(value, datatype=URIRef(datatype)) 

83 else: 

84 obj = Literal(value) 

85 

86 temp_graph.add((subject, predicate, obj, graph_uri)) 

87 

88 for quad in temp_graph.quads(): 

89 ocdm_graph.add(quad) 

90 else: 

91 raise ValueError("No entities were found.") 

92 

93 elif isinstance(ocdm_graph, OCDMGraph): 

94 query: str = f''' 

95 CONSTRUCT {{ 

96 ?s ?p ?o 

97 }} 

98 WHERE {{ 

99 ?s ?p ?o.  

100 VALUES ?s {{<{'> <'.join(res_list)}>}} 

101 }} 

102 ''' 

103 sparql.setQuery(query) 

104 sparql.setMethod(POST) 

105 sparql.setReturnFormat(XML) 

106 

107 # Use the retry utility function instead of duplicating retry logic 

108 result: Graph = execute_with_retry( 

109 sparql.queryAndConvert, 

110 max_retries=max_retries 

111 ) 

112 

113 if result is not None and len(result) > 0: 

114 for triple in result: 

115 ocdm_graph.add(triple) 

116 else: 

117 raise ValueError("No entities were found.") 

118 

119 else: 

120 raise TypeError("ocdm_graph must be either OCDMGraph or OCDMDataset")