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
« 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
18from typing import List, Union
20from oc_ocdm.support.reporter import Reporter
21from rdflib import Dataset, Graph, Literal, URIRef
22from SPARQLWrapper import JSON, POST, XML, SPARQLWrapper
24from rdflib_ocdm.ocdm_graph import OCDMDataset, OCDMGraph
25from rdflib_ocdm.retry_utils import execute_with_retry
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
35 if reperr is None:
36 self.reperr: Reporter = Reporter(prefix="[Reader: ERROR] ")
37 else:
38 self.reperr: Reporter = reperr
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)
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)
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 )
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'])
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')
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)
86 temp_graph.add((subject, predicate, obj, graph_uri))
88 for quad in temp_graph.quads():
89 ocdm_graph.add(quad)
90 else:
91 raise ValueError("No entities were found.")
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)
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 )
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.")
119 else:
120 raise TypeError("ocdm_graph must be either OCDMGraph or OCDMDataset")