rdf4j-python 0.1.2__py3-none-any.whl → 0.1.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rdf4j_python/_driver/_async_named_graph.py +8 -7
- rdf4j_python/_driver/_async_rdf4j_db.py +5 -5
- rdf4j_python/_driver/_async_repository.py +48 -39
- rdf4j_python/model/__init__.py +0 -2
- rdf4j_python/model/_namespace.py +38 -15
- rdf4j_python/model/_repository_info.py +25 -15
- rdf4j_python/model/repository_config.py +106 -53
- rdf4j_python/model/term.py +15 -9
- rdf4j_python/model/vocabulary.py +1 -0
- rdf4j_python/utils/helpers.py +10 -12
- {rdf4j_python-0.1.2.dist-info → rdf4j_python-0.1.3.dist-info}/METADATA +2 -2
- rdf4j_python-0.1.3.dist-info/RECORD +23 -0
- rdf4j_python/model/_base_model.py +0 -48
- rdf4j_python/model/_dataset.py +0 -38
- rdf4j_python-0.1.2.dist-info/RECORD +0 -25
- {rdf4j_python-0.1.2.dist-info → rdf4j_python-0.1.3.dist-info}/WHEEL +0 -0
- {rdf4j_python-0.1.2.dist-info → rdf4j_python-0.1.3.dist-info}/licenses/LICENSE +0 -0
- {rdf4j_python-0.1.2.dist-info → rdf4j_python-0.1.3.dist-info}/top_level.txt +0 -0
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
from typing import Iterable
|
|
2
2
|
|
|
3
|
+
import pyoxigraph as og
|
|
4
|
+
|
|
3
5
|
from rdf4j_python._client import AsyncApiClient
|
|
4
|
-
from rdf4j_python.model import
|
|
5
|
-
from rdf4j_python.model.term import IRI, RDFStatement
|
|
6
|
+
from rdf4j_python.model.term import IRI, Quad, QuadResultSet, Triple
|
|
6
7
|
from rdf4j_python.utils.const import Rdf4jContentType
|
|
7
8
|
from rdf4j_python.utils.helpers import serialize_statements
|
|
8
9
|
|
|
@@ -22,11 +23,11 @@ class AsyncNamedGraph:
|
|
|
22
23
|
self._repository_id = repository_id
|
|
23
24
|
self._graph_uri = graph_uri
|
|
24
25
|
|
|
25
|
-
async def get(self) ->
|
|
26
|
+
async def get(self) -> QuadResultSet:
|
|
26
27
|
"""Fetches all RDF statements from this named graph.
|
|
27
28
|
|
|
28
29
|
Returns:
|
|
29
|
-
|
|
30
|
+
QuadResultSet: RDF data serialized in the requested format.
|
|
30
31
|
|
|
31
32
|
Raises:
|
|
32
33
|
httpx.HTTPStatusError: If the request fails.
|
|
@@ -35,13 +36,13 @@ class AsyncNamedGraph:
|
|
|
35
36
|
headers = {"Accept": Rdf4jContentType.NQUADS}
|
|
36
37
|
response = await self._client.get(path, headers=headers)
|
|
37
38
|
response.raise_for_status()
|
|
38
|
-
return
|
|
39
|
+
return og.parse(response.content, format=og.RdfFormat.N_QUADS)
|
|
39
40
|
|
|
40
|
-
async def add(self, statements: Iterable[
|
|
41
|
+
async def add(self, statements: Iterable[Quad] | Iterable[Triple]):
|
|
41
42
|
"""Adds RDF statements to this named graph.
|
|
42
43
|
|
|
43
44
|
Args:
|
|
44
|
-
statements (Iterable[
|
|
45
|
+
statements (Iterable[Quad] | Iterable[Triple]): RDF statements to add.
|
|
45
46
|
|
|
46
47
|
Raises:
|
|
47
48
|
httpx.HTTPStatusError: If the request fails.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import httpx
|
|
2
|
-
import
|
|
2
|
+
import pyoxigraph as og
|
|
3
3
|
|
|
4
4
|
from rdf4j_python._client import AsyncApiClient
|
|
5
5
|
from rdf4j_python.exception.repo_exception import (
|
|
@@ -66,12 +66,12 @@ class AsyncRdf4j:
|
|
|
66
66
|
"/repositories",
|
|
67
67
|
headers={"Accept": Rdf4jContentType.SPARQL_RESULTS_JSON},
|
|
68
68
|
)
|
|
69
|
-
|
|
70
|
-
response, format=
|
|
69
|
+
query_solutions = og.parse_query_results(
|
|
70
|
+
response.text, format=og.QueryResultsFormat.JSON
|
|
71
71
|
)
|
|
72
72
|
return [
|
|
73
|
-
RepositoryMetadata.
|
|
74
|
-
for
|
|
73
|
+
RepositoryMetadata.from_sparql_query_solution(query_solution)
|
|
74
|
+
for query_solution in query_solutions
|
|
75
75
|
]
|
|
76
76
|
|
|
77
77
|
async def get_repository(self, repository_id: str) -> AsyncRdf4JRepository:
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
from typing import Iterable, Optional
|
|
2
2
|
|
|
3
3
|
import httpx
|
|
4
|
-
import
|
|
5
|
-
import rdflib.resource
|
|
6
|
-
import rdflib.serializer
|
|
7
|
-
import rdflib.store
|
|
4
|
+
import pyoxigraph as og
|
|
8
5
|
|
|
9
6
|
from rdf4j_python._client import AsyncApiClient
|
|
10
7
|
from rdf4j_python._driver._async_named_graph import AsyncNamedGraph
|
|
@@ -14,13 +11,16 @@ from rdf4j_python.exception.repo_exception import (
|
|
|
14
11
|
RepositoryNotFoundException,
|
|
15
12
|
RepositoryUpdateException,
|
|
16
13
|
)
|
|
17
|
-
from rdf4j_python.model import Namespace
|
|
14
|
+
from rdf4j_python.model import Namespace
|
|
18
15
|
from rdf4j_python.model.term import (
|
|
16
|
+
IRI,
|
|
19
17
|
Context,
|
|
20
18
|
Object,
|
|
21
19
|
Predicate,
|
|
22
|
-
|
|
20
|
+
Quad,
|
|
21
|
+
QuadResultSet,
|
|
23
22
|
Subject,
|
|
23
|
+
Triple,
|
|
24
24
|
)
|
|
25
25
|
from rdf4j_python.utils.const import Rdf4jContentType
|
|
26
26
|
from rdf4j_python.utils.helpers import serialize_statements
|
|
@@ -57,7 +57,7 @@ class AsyncRdf4JRepository:
|
|
|
57
57
|
"""
|
|
58
58
|
path = f"/repositories/{self._repository_id}"
|
|
59
59
|
params = {"query": sparql_query, "infer": str(infer).lower()}
|
|
60
|
-
headers = {"Accept": accept
|
|
60
|
+
headers = {"Accept": accept}
|
|
61
61
|
response = await self._client.get(path, params=params, headers=headers)
|
|
62
62
|
self._handle_repo_not_found_exception(response)
|
|
63
63
|
if "json" in response.headers.get("Content-Type", ""):
|
|
@@ -92,26 +92,32 @@ class AsyncRdf4JRepository:
|
|
|
92
92
|
path = f"/repositories/{self._repository_id}/namespaces"
|
|
93
93
|
headers = {"Accept": Rdf4jContentType.SPARQL_RESULTS_JSON}
|
|
94
94
|
response = await self._client.get(path, headers=headers)
|
|
95
|
-
result = rdflib.query.Result.parse(
|
|
96
|
-
response, format=Rdf4jContentType.SPARQL_RESULTS_JSON
|
|
97
|
-
)
|
|
98
95
|
self._handle_repo_not_found_exception(response)
|
|
99
|
-
return [Namespace.from_rdflib_binding(binding) for binding in result.bindings]
|
|
100
96
|
|
|
101
|
-
|
|
97
|
+
query_solutions = og.parse_query_results(
|
|
98
|
+
response.text, format=og.QueryResultsFormat.JSON
|
|
99
|
+
)
|
|
100
|
+
return [
|
|
101
|
+
Namespace.from_sparql_query_solution(query_solution)
|
|
102
|
+
for query_solution in query_solutions
|
|
103
|
+
]
|
|
104
|
+
|
|
105
|
+
async def set_namespace(self, prefix: str, namespace: IRI):
|
|
102
106
|
"""Sets a namespace prefix.
|
|
103
107
|
|
|
104
108
|
Args:
|
|
105
109
|
prefix (str): The namespace prefix.
|
|
106
|
-
namespace (
|
|
110
|
+
namespace (IRI): The namespace URI.
|
|
107
111
|
|
|
108
112
|
Raises:
|
|
109
113
|
RepositoryNotFoundException: If the repository doesn't exist.
|
|
110
114
|
NamespaceException: If the request fails.
|
|
111
115
|
"""
|
|
112
116
|
path = f"/repositories/{self._repository_id}/namespaces/{prefix}"
|
|
113
|
-
headers = {"Content-Type": Rdf4jContentType.NTRIPLES
|
|
114
|
-
response = await self._client.put(
|
|
117
|
+
headers = {"Content-Type": Rdf4jContentType.NTRIPLES}
|
|
118
|
+
response = await self._client.put(
|
|
119
|
+
path, content=namespace.value, headers=headers
|
|
120
|
+
)
|
|
115
121
|
self._handle_repo_not_found_exception(response)
|
|
116
122
|
if response.status_code != httpx.codes.NO_CONTENT:
|
|
117
123
|
raise NamespaceException(f"Failed to set namespace: {response.text}")
|
|
@@ -130,7 +136,7 @@ class AsyncRdf4JRepository:
|
|
|
130
136
|
NamespaceException: If retrieval fails.
|
|
131
137
|
"""
|
|
132
138
|
path = f"/repositories/{self._repository_id}/namespaces/{prefix}"
|
|
133
|
-
headers = {"Accept": Rdf4jContentType.NTRIPLES
|
|
139
|
+
headers = {"Accept": Rdf4jContentType.NTRIPLES}
|
|
134
140
|
response = await self._client.get(path, headers=headers)
|
|
135
141
|
self._handle_repo_not_found_exception(response)
|
|
136
142
|
|
|
@@ -192,7 +198,7 @@ class AsyncRdf4JRepository:
|
|
|
192
198
|
object_: Optional[Object] = None,
|
|
193
199
|
contexts: Optional[list[Context]] = None,
|
|
194
200
|
infer: bool = True,
|
|
195
|
-
) ->
|
|
201
|
+
) -> QuadResultSet:
|
|
196
202
|
"""Retrieves statements matching the given pattern.
|
|
197
203
|
|
|
198
204
|
Args:
|
|
@@ -202,7 +208,7 @@ class AsyncRdf4JRepository:
|
|
|
202
208
|
contexts (Optional[list[Context]]): Filter by context (named graph).
|
|
203
209
|
|
|
204
210
|
Returns:
|
|
205
|
-
|
|
211
|
+
QuadResultSet: QuadResultSet of matching RDF statements.
|
|
206
212
|
|
|
207
213
|
Raises:
|
|
208
214
|
RepositoryNotFoundException: If the repository doesn't exist.
|
|
@@ -211,20 +217,18 @@ class AsyncRdf4JRepository:
|
|
|
211
217
|
params = {}
|
|
212
218
|
|
|
213
219
|
if subject:
|
|
214
|
-
params["subj"] = subject
|
|
220
|
+
params["subj"] = str(subject)
|
|
215
221
|
if predicate:
|
|
216
|
-
params["pred"] = predicate
|
|
222
|
+
params["pred"] = str(predicate)
|
|
217
223
|
if object_:
|
|
218
|
-
params["obj"] = object_
|
|
224
|
+
params["obj"] = str(object_)
|
|
219
225
|
if contexts:
|
|
220
|
-
params["context"] = [ctx
|
|
226
|
+
params["context"] = [str(ctx) for ctx in contexts]
|
|
221
227
|
params["infer"] = str(infer).lower()
|
|
222
228
|
|
|
223
229
|
headers = {"Accept": Rdf4jContentType.NQUADS}
|
|
224
230
|
response = await self._client.get(path, params=params, headers=headers)
|
|
225
|
-
|
|
226
|
-
dataset.parse(data=response.text, format="nquads")
|
|
227
|
-
return dataset
|
|
231
|
+
return og.parse(response.content, format=og.RdfFormat.N_QUADS)
|
|
228
232
|
|
|
229
233
|
async def delete_statements(
|
|
230
234
|
self,
|
|
@@ -250,13 +254,13 @@ class AsyncRdf4JRepository:
|
|
|
250
254
|
params = {}
|
|
251
255
|
|
|
252
256
|
if subject:
|
|
253
|
-
params["subj"] = subject
|
|
257
|
+
params["subj"] = str(subject)
|
|
254
258
|
if predicate:
|
|
255
|
-
params["pred"] = predicate
|
|
259
|
+
params["pred"] = str(predicate)
|
|
256
260
|
if object_:
|
|
257
|
-
params["obj"] = object_
|
|
261
|
+
params["obj"] = str(object_)
|
|
258
262
|
if contexts:
|
|
259
|
-
params["context"] = [ctx
|
|
263
|
+
params["context"] = [str(ctx) for ctx in contexts]
|
|
260
264
|
|
|
261
265
|
response = await self._client.delete(path, params=params)
|
|
262
266
|
self._handle_repo_not_found_exception(response)
|
|
@@ -286,21 +290,26 @@ class AsyncRdf4JRepository:
|
|
|
286
290
|
httpx.HTTPStatusError: If addition fails.
|
|
287
291
|
"""
|
|
288
292
|
path = f"/repositories/{self._repository_id}/statements"
|
|
293
|
+
statement: Triple | Quad
|
|
294
|
+
if context is None:
|
|
295
|
+
statement = Triple(subject, predicate, object)
|
|
296
|
+
else:
|
|
297
|
+
statement = Quad(subject, predicate, object, context)
|
|
298
|
+
|
|
289
299
|
response = await self._client.post(
|
|
290
300
|
path,
|
|
291
|
-
content=serialize_statements([
|
|
301
|
+
content=serialize_statements([statement]),
|
|
292
302
|
headers={"Content-Type": Rdf4jContentType.NQUADS},
|
|
293
303
|
)
|
|
294
304
|
self._handle_repo_not_found_exception(response)
|
|
295
305
|
if response.status_code != httpx.codes.NO_CONTENT:
|
|
296
306
|
raise RepositoryUpdateException(f"Failed to add statement: {response.text}")
|
|
297
307
|
|
|
298
|
-
async def add_statements(self, statements: Iterable[
|
|
308
|
+
async def add_statements(self, statements: Iterable[Quad] | Iterable[Triple]):
|
|
299
309
|
"""Adds a list of RDF statements to the repository.
|
|
300
310
|
|
|
301
311
|
Args:
|
|
302
|
-
statements (Iterable[
|
|
303
|
-
RDFStatement: A tuple of subject, predicate, object, and context.
|
|
312
|
+
statements (Iterable[Quad] | Iterable[Triple]): A list of RDF statements.
|
|
304
313
|
|
|
305
314
|
Raises:
|
|
306
315
|
RepositoryNotFoundException: If the repository doesn't exist.
|
|
@@ -320,26 +329,26 @@ class AsyncRdf4JRepository:
|
|
|
320
329
|
|
|
321
330
|
async def replace_statements(
|
|
322
331
|
self,
|
|
323
|
-
statements: Iterable[
|
|
324
|
-
contexts: Optional[
|
|
332
|
+
statements: Iterable[Quad] | Iterable[Triple],
|
|
333
|
+
contexts: Optional[Iterable[Context]] = None,
|
|
325
334
|
base_uri: Optional[str] = None,
|
|
326
335
|
):
|
|
327
336
|
"""Replaces all repository statements with the given RDF data.
|
|
328
337
|
|
|
329
338
|
Args:
|
|
330
|
-
statements (Iterable[
|
|
331
|
-
contexts (Optional[
|
|
339
|
+
statements (Iterable[Quad] | Iterable[Triple]): RDF statements to load.
|
|
340
|
+
contexts (Optional[Iterable[Context]]): One or more specific contexts to restrict deletion to.
|
|
332
341
|
|
|
333
342
|
Raises:
|
|
334
343
|
RepositoryNotFoundException: If the repository doesn't exist.
|
|
335
344
|
httpx.HTTPStatusError: If the operation fails.
|
|
336
345
|
"""
|
|
337
346
|
path = f"/repositories/{self._repository_id}/statements"
|
|
338
|
-
headers = {"Content-Type": Rdf4jContentType.NQUADS
|
|
347
|
+
headers = {"Content-Type": Rdf4jContentType.NQUADS}
|
|
339
348
|
|
|
340
349
|
params = {}
|
|
341
350
|
if contexts:
|
|
342
|
-
params["context"] = [ctx
|
|
351
|
+
params["context"] = [str(ctx) for ctx in contexts]
|
|
343
352
|
if base_uri:
|
|
344
353
|
params["baseUri"] = base_uri
|
|
345
354
|
|
rdf4j_python/model/__init__.py
CHANGED
rdf4j_python/model/_namespace.py
CHANGED
|
@@ -1,11 +1,32 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
from rdflib.namespace import Namespace as RdflibNamespace
|
|
4
|
-
from rdflib.term import Identifier, Variable
|
|
1
|
+
import pyoxigraph as og
|
|
5
2
|
|
|
6
3
|
from rdf4j_python.model.term import IRI
|
|
7
4
|
|
|
8
|
-
|
|
5
|
+
|
|
6
|
+
class _Namespace(str):
|
|
7
|
+
def __new__(cls, value: str | bytes) -> "Namespace":
|
|
8
|
+
try:
|
|
9
|
+
rt = str.__new__(cls, value)
|
|
10
|
+
except UnicodeDecodeError:
|
|
11
|
+
rt = str.__new__(cls, value, "utf-8")
|
|
12
|
+
return rt
|
|
13
|
+
|
|
14
|
+
def term(self, name: str) -> IRI:
|
|
15
|
+
return IRI(self + (name if isinstance(name, str) else ""))
|
|
16
|
+
|
|
17
|
+
def __getitem__(self, key: str) -> IRI:
|
|
18
|
+
return self.term(key)
|
|
19
|
+
|
|
20
|
+
def __getattr__(self, name: str) -> IRI:
|
|
21
|
+
if name.startswith("__"):
|
|
22
|
+
raise AttributeError
|
|
23
|
+
return self.term(name)
|
|
24
|
+
|
|
25
|
+
def __repr__(self) -> str:
|
|
26
|
+
return f"Namespace({super().__repr__()})"
|
|
27
|
+
|
|
28
|
+
def __contains__(self, ref: str) -> bool:
|
|
29
|
+
return ref.startswith(self)
|
|
9
30
|
|
|
10
31
|
|
|
11
32
|
class Namespace:
|
|
@@ -14,7 +35,7 @@ class Namespace:
|
|
|
14
35
|
"""
|
|
15
36
|
|
|
16
37
|
_prefix: str
|
|
17
|
-
_namespace:
|
|
38
|
+
_namespace: _Namespace
|
|
18
39
|
|
|
19
40
|
def __init__(self, prefix: str, namespace: str):
|
|
20
41
|
"""
|
|
@@ -25,24 +46,26 @@ class Namespace:
|
|
|
25
46
|
namespace (str): The namespace URI.
|
|
26
47
|
"""
|
|
27
48
|
self._prefix = prefix
|
|
28
|
-
self._namespace =
|
|
49
|
+
self._namespace = _Namespace(namespace)
|
|
29
50
|
|
|
30
51
|
@classmethod
|
|
31
|
-
def
|
|
52
|
+
def from_sparql_query_solution(
|
|
53
|
+
cls, query_solution: og.QuerySolution
|
|
54
|
+
) -> "Namespace":
|
|
32
55
|
"""
|
|
33
|
-
Creates a Namespace from a
|
|
56
|
+
Creates a Namespace from a binding.
|
|
34
57
|
|
|
35
58
|
Args:
|
|
36
|
-
binding (Mapping[Variable, Identifier]): The
|
|
59
|
+
binding (Mapping[Variable, Identifier]): The binding.
|
|
37
60
|
|
|
38
61
|
Returns:
|
|
39
62
|
Namespace: The created Namespace.
|
|
40
63
|
"""
|
|
41
|
-
prefix =
|
|
42
|
-
namespace =
|
|
64
|
+
prefix: og.Literal = query_solution[og.Variable("prefix")]
|
|
65
|
+
namespace: og.NamedNode = query_solution[og.Variable("namespace")]
|
|
43
66
|
return cls(
|
|
44
|
-
prefix=prefix,
|
|
45
|
-
namespace=namespace,
|
|
67
|
+
prefix=prefix.value,
|
|
68
|
+
namespace=namespace.value,
|
|
46
69
|
)
|
|
47
70
|
|
|
48
71
|
def __str__(self):
|
|
@@ -85,7 +108,7 @@ class Namespace:
|
|
|
85
108
|
Returns:
|
|
86
109
|
IRI: The IRI for the term.
|
|
87
110
|
"""
|
|
88
|
-
return
|
|
111
|
+
return self._namespace.term(name)
|
|
89
112
|
|
|
90
113
|
def __getitem__(self, item: str) -> IRI:
|
|
91
114
|
"""
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
|
-
from typing import Mapping
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
from ._base_model import _BaseModel
|
|
3
|
+
import pyoxigraph as og
|
|
7
4
|
|
|
8
5
|
|
|
9
6
|
@dataclass
|
|
10
|
-
class RepositoryMetadata
|
|
7
|
+
class RepositoryMetadata:
|
|
11
8
|
"""
|
|
12
9
|
Represents a repository metadata RDF4J.
|
|
13
10
|
"""
|
|
@@ -28,25 +25,38 @@ class RepositoryMetadata(_BaseModel):
|
|
|
28
25
|
return f"Repository(id={self.id}, title={self.title}, uri={self.uri})"
|
|
29
26
|
|
|
30
27
|
@classmethod
|
|
31
|
-
def
|
|
32
|
-
cls,
|
|
28
|
+
def from_sparql_query_solution(
|
|
29
|
+
cls, query_solution: og.QuerySolution
|
|
33
30
|
) -> "RepositoryMetadata":
|
|
34
31
|
"""
|
|
35
|
-
Create a
|
|
36
|
-
represented as a Mapping from rdflib Variables to Identifiers.
|
|
32
|
+
Create a RepositoryMetadata instance from a SPARQL query result.
|
|
37
33
|
|
|
38
34
|
Args:
|
|
39
|
-
|
|
35
|
+
query_solution (og.QuerySolution): The SPARQL query result.
|
|
40
36
|
|
|
41
37
|
Returns:
|
|
42
38
|
RepositoryMetadata: The RepositoryMetadata instance.
|
|
39
|
+
|
|
40
|
+
Raises:
|
|
41
|
+
ValueError: If the query solution is missing required fields.
|
|
43
42
|
"""
|
|
44
43
|
|
|
45
44
|
# Construct and return the Repository object
|
|
45
|
+
if query_solution["id"] is None:
|
|
46
|
+
raise ValueError("id is required")
|
|
47
|
+
if query_solution["uri"] is None:
|
|
48
|
+
raise ValueError("uri is required")
|
|
49
|
+
if query_solution["title"] is None:
|
|
50
|
+
raise ValueError("title is required")
|
|
51
|
+
if query_solution["readable"] is None:
|
|
52
|
+
raise ValueError("readable is required")
|
|
53
|
+
if query_solution["writable"] is None:
|
|
54
|
+
raise ValueError("writable is required")
|
|
55
|
+
|
|
46
56
|
return cls(
|
|
47
|
-
id=
|
|
48
|
-
uri=
|
|
49
|
-
title=
|
|
50
|
-
readable=
|
|
51
|
-
writable=
|
|
57
|
+
id=query_solution["id"].value,
|
|
58
|
+
uri=query_solution["uri"].value,
|
|
59
|
+
title=query_solution["title"].value,
|
|
60
|
+
readable=bool(query_solution["readable"].value),
|
|
61
|
+
writable=bool(query_solution["writable"].value),
|
|
52
62
|
)
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
from typing import Any, Dict, Optional
|
|
2
2
|
|
|
3
|
-
from
|
|
4
|
-
|
|
3
|
+
from pyoxigraph import Dataset, Quad, RdfFormat, serialize
|
|
4
|
+
|
|
5
|
+
from rdf4j_python.model import Namespace
|
|
6
|
+
from rdf4j_python.model.term import IRI as URIRef
|
|
7
|
+
from rdf4j_python.model.term import BlankNode as BNode
|
|
8
|
+
from rdf4j_python.model.term import Literal
|
|
9
|
+
from rdf4j_python.model.vocabulary import RDF, RDFS, XSD
|
|
5
10
|
|
|
6
11
|
# Define the RDF4J configuration namespace
|
|
7
|
-
CONFIG = Namespace("tag:rdf4j.org,2023:config/")
|
|
12
|
+
CONFIG = Namespace("config", "tag:rdf4j.org,2023:config/")
|
|
8
13
|
|
|
9
14
|
|
|
10
15
|
class RepositoryConfig:
|
|
@@ -56,7 +61,7 @@ class RepositoryConfig:
|
|
|
56
61
|
|
|
57
62
|
def to_turtle(self) -> str:
|
|
58
63
|
"""
|
|
59
|
-
Serializes the Repository configuration to Turtle syntax using
|
|
64
|
+
Serializes the Repository configuration to Turtle syntax using .
|
|
60
65
|
|
|
61
66
|
Returns:
|
|
62
67
|
str: A UTF-8 encoded Turtle string representing the RDF4J repository configuration.
|
|
@@ -66,23 +71,20 @@ class RepositoryConfig:
|
|
|
66
71
|
Raises:
|
|
67
72
|
ValueError: If any of the configuration values are of unsupported types during serialization.
|
|
68
73
|
"""
|
|
69
|
-
graph =
|
|
70
|
-
graph.bind("rdfs", RDFS)
|
|
71
|
-
graph.bind("config", CONFIG)
|
|
72
|
-
graph.bind("xsd", XSD)
|
|
74
|
+
graph = Dataset()
|
|
73
75
|
repo_node = BNode()
|
|
74
|
-
graph.add((repo_node, RDF["type"], CONFIG["Repository"]))
|
|
76
|
+
graph.add(Quad(repo_node, RDF["type"], CONFIG["Repository"], None))
|
|
75
77
|
|
|
76
|
-
graph.add((repo_node, CONFIG["rep.id"], Literal(self._repo_id)))
|
|
78
|
+
graph.add(Quad(repo_node, CONFIG["rep.id"], Literal(self._repo_id), None))
|
|
77
79
|
|
|
78
80
|
if self._title:
|
|
79
|
-
graph.add((repo_node, RDFS["label"], Literal(self._title)))
|
|
81
|
+
graph.add(Quad(repo_node, RDFS["label"], Literal(self._title), None))
|
|
80
82
|
|
|
81
83
|
if self._impl:
|
|
82
84
|
impl_node = self._impl.add_to_graph(graph)
|
|
83
|
-
graph.add((repo_node, CONFIG["rep.impl"], impl_node))
|
|
85
|
+
graph.add(Quad(repo_node, CONFIG["rep.impl"], impl_node, None))
|
|
84
86
|
|
|
85
|
-
return
|
|
87
|
+
return serialize(graph, format=RdfFormat.TURTLE)
|
|
86
88
|
|
|
87
89
|
class Builder:
|
|
88
90
|
"""
|
|
@@ -168,14 +170,14 @@ class RepositoryConfig:
|
|
|
168
170
|
|
|
169
171
|
class RepositoryImplConfig:
|
|
170
172
|
"""
|
|
171
|
-
Base class for repository implementation configurations using
|
|
173
|
+
Base class for repository implementation configurations using .
|
|
172
174
|
"""
|
|
173
175
|
|
|
174
176
|
def __init__(self, rep_type: str):
|
|
175
177
|
self.rep_type = rep_type
|
|
176
178
|
self.config_params: Dict[str, Any] = {}
|
|
177
179
|
|
|
178
|
-
def add_to_graph(self, graph:
|
|
180
|
+
def add_to_graph(self, graph: Dataset) -> URIRef:
|
|
179
181
|
"""
|
|
180
182
|
Adds the repository implementation configuration to the RDF graph.
|
|
181
183
|
|
|
@@ -183,28 +185,45 @@ class RepositoryImplConfig:
|
|
|
183
185
|
The RDF node representing this configuration.
|
|
184
186
|
"""
|
|
185
187
|
sail_node = BNode()
|
|
186
|
-
graph.add((sail_node, CONFIG["rep.type"], Literal(self.rep_type)))
|
|
188
|
+
graph.add(Quad(sail_node, CONFIG["rep.type"], Literal(self.rep_type), None))
|
|
187
189
|
for key, value in self.config_params.items():
|
|
188
190
|
if isinstance(value, str):
|
|
189
|
-
graph.add((sail_node, CONFIG[key], Literal(value)))
|
|
190
|
-
elif isinstance(value, int):
|
|
191
|
+
graph.add(Quad(sail_node, CONFIG[key], Literal(value), None))
|
|
192
|
+
elif isinstance(value, int) and not isinstance(value, bool):
|
|
191
193
|
graph.add(
|
|
192
|
-
(
|
|
194
|
+
Quad(
|
|
195
|
+
sail_node,
|
|
196
|
+
CONFIG[key],
|
|
197
|
+
Literal(value, datatype=XSD["integer"]),
|
|
198
|
+
None,
|
|
199
|
+
)
|
|
193
200
|
)
|
|
194
201
|
elif isinstance(value, float):
|
|
195
|
-
graph.add(
|
|
202
|
+
graph.add(
|
|
203
|
+
Quad(
|
|
204
|
+
sail_node,
|
|
205
|
+
CONFIG[key],
|
|
206
|
+
Literal(value, datatype=XSD["double"]),
|
|
207
|
+
None,
|
|
208
|
+
)
|
|
209
|
+
)
|
|
196
210
|
elif isinstance(value, bool):
|
|
197
211
|
graph.add(
|
|
198
|
-
(
|
|
212
|
+
Quad(
|
|
213
|
+
sail_node,
|
|
214
|
+
CONFIG[key],
|
|
215
|
+
Literal(str(value).lower(), datatype=XSD["boolean"]),
|
|
216
|
+
None,
|
|
217
|
+
)
|
|
199
218
|
)
|
|
200
219
|
elif isinstance(value, list):
|
|
201
220
|
for item in value:
|
|
202
|
-
graph.add((sail_node, CONFIG[key], URIRef(item)))
|
|
221
|
+
graph.add(Quad(sail_node, CONFIG[key], URIRef(item), None))
|
|
203
222
|
elif isinstance(value, RepositoryImplConfig) or isinstance(
|
|
204
223
|
value, SailConfig
|
|
205
224
|
):
|
|
206
225
|
nested_node = value.add_to_graph(graph)
|
|
207
|
-
graph.add((sail_node, CONFIG[key], nested_node))
|
|
226
|
+
graph.add(Quad(sail_node, CONFIG[key], nested_node, None))
|
|
208
227
|
else:
|
|
209
228
|
raise ValueError(f"Unsupported configuration value type: {type(value)}")
|
|
210
229
|
return sail_node
|
|
@@ -212,7 +231,7 @@ class RepositoryImplConfig:
|
|
|
212
231
|
|
|
213
232
|
class SPARQLRepositoryConfig(RepositoryImplConfig):
|
|
214
233
|
"""
|
|
215
|
-
Configuration for a SPARQLRepository
|
|
234
|
+
Configuration for a SPARQLRepository.
|
|
216
235
|
"""
|
|
217
236
|
|
|
218
237
|
TYPE = "openrdf:SPARQLRepository"
|
|
@@ -265,7 +284,7 @@ class SPARQLRepositoryConfig(RepositoryImplConfig):
|
|
|
265
284
|
|
|
266
285
|
class HTTPRepositoryConfig(RepositoryImplConfig):
|
|
267
286
|
"""
|
|
268
|
-
Configuration for an HTTPRepository
|
|
287
|
+
Configuration for an HTTPRepository.
|
|
269
288
|
"""
|
|
270
289
|
|
|
271
290
|
TYPE = "openrdf:HTTPRepository"
|
|
@@ -320,7 +339,7 @@ class HTTPRepositoryConfig(RepositoryImplConfig):
|
|
|
320
339
|
|
|
321
340
|
class SailRepositoryConfig(RepositoryImplConfig):
|
|
322
341
|
"""
|
|
323
|
-
Configuration for a SailRepository
|
|
342
|
+
Configuration for a SailRepository.
|
|
324
343
|
"""
|
|
325
344
|
|
|
326
345
|
TYPE = "openrdf:SailRepository"
|
|
@@ -329,7 +348,7 @@ class SailRepositoryConfig(RepositoryImplConfig):
|
|
|
329
348
|
super().__init__(rep_type=SailRepositoryConfig.TYPE)
|
|
330
349
|
self.config_params["sail.impl"] = sail_impl
|
|
331
350
|
|
|
332
|
-
def add_to_graph(self, graph:
|
|
351
|
+
def add_to_graph(self, graph: Dataset) -> URIRef:
|
|
333
352
|
"""
|
|
334
353
|
Adds the SailRepository configuration to the RDF graph.
|
|
335
354
|
"""
|
|
@@ -364,7 +383,7 @@ class SailRepositoryConfig(RepositoryImplConfig):
|
|
|
364
383
|
|
|
365
384
|
class DatasetRepositoryConfig(RepositoryImplConfig):
|
|
366
385
|
"""
|
|
367
|
-
Configuration for a DatasetRepository using
|
|
386
|
+
Configuration for a DatasetRepository using .
|
|
368
387
|
"""
|
|
369
388
|
|
|
370
389
|
TYPE = "openrdf:DatasetRepository"
|
|
@@ -373,7 +392,7 @@ class DatasetRepositoryConfig(RepositoryImplConfig):
|
|
|
373
392
|
super().__init__(rep_type=DatasetRepositoryConfig.TYPE)
|
|
374
393
|
self.config_params["delegate"] = delegate
|
|
375
394
|
|
|
376
|
-
def add_to_graph(self, graph:
|
|
395
|
+
def add_to_graph(self, graph: Dataset) -> URIRef:
|
|
377
396
|
"""
|
|
378
397
|
Adds the DatasetRepository configuration to the RDF Graph
|
|
379
398
|
"""
|
|
@@ -390,7 +409,7 @@ class DatasetRepositoryConfig(RepositoryImplConfig):
|
|
|
390
409
|
|
|
391
410
|
class SailConfig:
|
|
392
411
|
"""
|
|
393
|
-
Base class for SAIL configurations using
|
|
412
|
+
Base class for SAIL configurations using .
|
|
394
413
|
"""
|
|
395
414
|
|
|
396
415
|
def __init__(
|
|
@@ -410,7 +429,7 @@ class SailConfig:
|
|
|
410
429
|
default_query_evaluation_mode
|
|
411
430
|
)
|
|
412
431
|
|
|
413
|
-
def add_to_graph(self, graph:
|
|
432
|
+
def add_to_graph(self, graph: Dataset) -> URIRef:
|
|
414
433
|
"""
|
|
415
434
|
Adds the SAIL configuration to the RDF graph.
|
|
416
435
|
|
|
@@ -418,28 +437,45 @@ class SailConfig:
|
|
|
418
437
|
The RDF node representing this configuration.
|
|
419
438
|
"""
|
|
420
439
|
sail_node = BNode()
|
|
421
|
-
graph.add((sail_node, CONFIG["sail.type"], Literal(self.sail_type)))
|
|
440
|
+
graph.add(Quad(sail_node, CONFIG["sail.type"], Literal(self.sail_type), None))
|
|
422
441
|
for key, value in self.config_params.items():
|
|
423
442
|
if isinstance(value, str):
|
|
424
|
-
graph.add((sail_node, CONFIG[key], Literal(value)))
|
|
425
|
-
elif isinstance(value,
|
|
443
|
+
graph.add(Quad(sail_node, CONFIG[key], Literal(value), None))
|
|
444
|
+
elif isinstance(value, bool):
|
|
426
445
|
graph.add(
|
|
427
|
-
(
|
|
446
|
+
Quad(
|
|
447
|
+
sail_node,
|
|
448
|
+
CONFIG[key],
|
|
449
|
+
Literal(str(value).lower(), datatype=XSD["boolean"]),
|
|
450
|
+
None,
|
|
451
|
+
)
|
|
452
|
+
)
|
|
453
|
+
elif isinstance(value, int) and not isinstance(value, bool):
|
|
454
|
+
graph.add(
|
|
455
|
+
Quad(
|
|
456
|
+
sail_node,
|
|
457
|
+
CONFIG[key],
|
|
458
|
+
Literal(str(value), datatype=XSD["integer"]),
|
|
459
|
+
None,
|
|
460
|
+
)
|
|
428
461
|
)
|
|
429
462
|
elif isinstance(value, float):
|
|
430
|
-
graph.add((sail_node, CONFIG[key], Literal(value, datatype=XSD.double)))
|
|
431
|
-
elif isinstance(value, bool):
|
|
432
463
|
graph.add(
|
|
433
|
-
(
|
|
464
|
+
Quad(
|
|
465
|
+
sail_node,
|
|
466
|
+
CONFIG[key],
|
|
467
|
+
Literal(str(value), datatype=XSD["double"]),
|
|
468
|
+
None,
|
|
469
|
+
)
|
|
434
470
|
)
|
|
435
471
|
elif isinstance(value, list):
|
|
436
472
|
for item in value:
|
|
437
|
-
graph.add((sail_node, CONFIG[key], URIRef(item)))
|
|
473
|
+
graph.add(Quad(sail_node, CONFIG[key], URIRef(item), None))
|
|
438
474
|
elif isinstance(value, SailConfig) or isinstance(
|
|
439
475
|
value, RepositoryImplConfig
|
|
440
476
|
):
|
|
441
477
|
nested_node = value.add_to_graph(graph)
|
|
442
|
-
graph.add((sail_node, CONFIG[key], nested_node))
|
|
478
|
+
graph.add(Quad(sail_node, CONFIG[key], nested_node, None))
|
|
443
479
|
else:
|
|
444
480
|
raise ValueError(f"Unsupported configuration value type: {type(value)}")
|
|
445
481
|
return sail_node
|
|
@@ -447,7 +483,7 @@ class SailConfig:
|
|
|
447
483
|
|
|
448
484
|
class MemoryStoreConfig(SailConfig):
|
|
449
485
|
"""
|
|
450
|
-
Configuration for a MemoryStore using
|
|
486
|
+
Configuration for a MemoryStore using .
|
|
451
487
|
"""
|
|
452
488
|
|
|
453
489
|
TYPE = "openrdf:MemoryStore"
|
|
@@ -543,7 +579,7 @@ class MemoryStoreConfig(SailConfig):
|
|
|
543
579
|
|
|
544
580
|
class NativeStoreConfig(SailConfig):
|
|
545
581
|
"""
|
|
546
|
-
Configuration for a NativeStore using
|
|
582
|
+
Configuration for a NativeStore using .
|
|
547
583
|
"""
|
|
548
584
|
|
|
549
585
|
TYPE = "openrdf:NativeStore"
|
|
@@ -711,7 +747,7 @@ class NativeStoreConfig(SailConfig):
|
|
|
711
747
|
|
|
712
748
|
class ElasticsearchStoreConfig(SailConfig):
|
|
713
749
|
"""
|
|
714
|
-
Configuration for an ElasticsearchStore using
|
|
750
|
+
Configuration for an ElasticsearchStore using .
|
|
715
751
|
"""
|
|
716
752
|
|
|
717
753
|
TYPE = "rdf4j:ElasticsearchStore"
|
|
@@ -835,7 +871,7 @@ class ElasticsearchStoreConfig(SailConfig):
|
|
|
835
871
|
|
|
836
872
|
class SchemaCachingRDFSInferencerConfig(SailConfig):
|
|
837
873
|
"""
|
|
838
|
-
Configuration for the RDF Schema inferencer using
|
|
874
|
+
Configuration for the RDF Schema inferencer using .
|
|
839
875
|
"""
|
|
840
876
|
|
|
841
877
|
TYPE = "rdf4j:SchemaCachingRDFSInferencer"
|
|
@@ -861,7 +897,7 @@ class SchemaCachingRDFSInferencerConfig(SailConfig):
|
|
|
861
897
|
)
|
|
862
898
|
self.config_params["delegate"] = delegate
|
|
863
899
|
|
|
864
|
-
def add_to_graph(self, graph:
|
|
900
|
+
def add_to_graph(self, graph: Dataset) -> URIRef:
|
|
865
901
|
"""
|
|
866
902
|
Adds the SchemaCachingRDFSInferencer configuration to the RDF graph.
|
|
867
903
|
|
|
@@ -928,7 +964,7 @@ class SchemaCachingRDFSInferencerConfig(SailConfig):
|
|
|
928
964
|
|
|
929
965
|
class DirectTypeHierarchyInferencerConfig(SailConfig):
|
|
930
966
|
"""
|
|
931
|
-
Configuration for the Direct Type inferencer using
|
|
967
|
+
Configuration for the Direct Type inferencer using .
|
|
932
968
|
"""
|
|
933
969
|
|
|
934
970
|
TYPE = "openrdf:DirectTypeHierarchyInferencer"
|
|
@@ -954,7 +990,7 @@ class DirectTypeHierarchyInferencerConfig(SailConfig):
|
|
|
954
990
|
)
|
|
955
991
|
self.config_params["delegate"] = delegate
|
|
956
992
|
|
|
957
|
-
def add_to_graph(self, graph:
|
|
993
|
+
def add_to_graph(self, graph: Dataset) -> URIRef:
|
|
958
994
|
"""
|
|
959
995
|
Adds the DirectTypeHierarchyInferencerConfig to the graph
|
|
960
996
|
|
|
@@ -1027,7 +1063,7 @@ class DirectTypeHierarchyInferencerConfig(SailConfig):
|
|
|
1027
1063
|
|
|
1028
1064
|
class SHACLSailConfig(SailConfig):
|
|
1029
1065
|
"""
|
|
1030
|
-
Configuration for the SHACL Sail using
|
|
1066
|
+
Configuration for the SHACL Sail using .
|
|
1031
1067
|
"""
|
|
1032
1068
|
|
|
1033
1069
|
TYPE = "rdf4j:ShaclSail"
|
|
@@ -1127,7 +1163,7 @@ class SHACLSailConfig(SailConfig):
|
|
|
1127
1163
|
validation_results_limit_per_constraint
|
|
1128
1164
|
)
|
|
1129
1165
|
|
|
1130
|
-
def add_to_graph(self, graph:
|
|
1166
|
+
def add_to_graph(self, graph: Dataset) -> URIRef:
|
|
1131
1167
|
"""
|
|
1132
1168
|
Adds the SHACLSailConfig to the RDF graph.
|
|
1133
1169
|
|
|
@@ -1146,14 +1182,31 @@ class SHACLSailConfig(SailConfig):
|
|
|
1146
1182
|
if key != "delegate": # Delegate is already handled
|
|
1147
1183
|
if isinstance(value, bool):
|
|
1148
1184
|
graph.add(
|
|
1149
|
-
(
|
|
1185
|
+
Quad(
|
|
1186
|
+
sail_node,
|
|
1187
|
+
CONFIG[key],
|
|
1188
|
+
Literal(str(value).lower(), datatype=XSD["boolean"]),
|
|
1189
|
+
None,
|
|
1190
|
+
)
|
|
1150
1191
|
)
|
|
1151
|
-
elif isinstance(value, int):
|
|
1192
|
+
elif isinstance(value, int) and not isinstance(value, bool):
|
|
1152
1193
|
graph.add(
|
|
1153
|
-
(
|
|
1194
|
+
Quad(
|
|
1195
|
+
sail_node,
|
|
1196
|
+
CONFIG[key],
|
|
1197
|
+
Literal(str(value), datatype=XSD["integer"]),
|
|
1198
|
+
None,
|
|
1199
|
+
)
|
|
1154
1200
|
)
|
|
1155
1201
|
else:
|
|
1156
|
-
graph.add(
|
|
1202
|
+
graph.add(
|
|
1203
|
+
Quad(
|
|
1204
|
+
sail_node,
|
|
1205
|
+
CONFIG[key],
|
|
1206
|
+
Literal(value),
|
|
1207
|
+
None,
|
|
1208
|
+
)
|
|
1209
|
+
)
|
|
1157
1210
|
return sail_node
|
|
1158
1211
|
|
|
1159
1212
|
class Builder:
|
rdf4j_python/model/term.py
CHANGED
|
@@ -1,14 +1,20 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import TypeAlias
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
from rdflib.term import IdentifiedNode, Node
|
|
3
|
+
import pyoxigraph as og
|
|
5
4
|
|
|
6
|
-
IRI: TypeAlias =
|
|
5
|
+
IRI: TypeAlias = og.NamedNode
|
|
6
|
+
BlankNode: TypeAlias = og.BlankNode
|
|
7
|
+
Literal: TypeAlias = og.Literal
|
|
8
|
+
DefaultGraph: TypeAlias = og.DefaultGraph
|
|
9
|
+
Variable: TypeAlias = og.Variable
|
|
7
10
|
|
|
11
|
+
Quad: TypeAlias = og.Quad
|
|
12
|
+
Triple: TypeAlias = og.Triple
|
|
8
13
|
|
|
9
|
-
Subject: TypeAlias =
|
|
10
|
-
Predicate: TypeAlias =
|
|
11
|
-
Object: TypeAlias =
|
|
12
|
-
Context: TypeAlias =
|
|
14
|
+
Subject: TypeAlias = IRI | BlankNode | Triple
|
|
15
|
+
Predicate: TypeAlias = IRI
|
|
16
|
+
Object: TypeAlias = IRI | BlankNode | Literal
|
|
17
|
+
Context: TypeAlias = IRI | BlankNode | DefaultGraph | None
|
|
13
18
|
|
|
14
|
-
|
|
19
|
+
|
|
20
|
+
QuadResultSet: TypeAlias = og.QuadParser
|
rdf4j_python/model/vocabulary.py
CHANGED
|
@@ -4,3 +4,4 @@ from rdf4j_python.model import Namespace
|
|
|
4
4
|
RDF = Namespace("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#")
|
|
5
5
|
RDFS = Namespace("rdfs", "http://www.w3.org/2000/01/rdf-schema#")
|
|
6
6
|
EXAMPLE = Namespace("ex", "http://example.org/")
|
|
7
|
+
XSD = Namespace("xsd", "http://www.w3.org/2001/XMLSchema#")
|
rdf4j_python/utils/helpers.py
CHANGED
|
@@ -1,22 +1,20 @@
|
|
|
1
|
+
from io import BytesIO
|
|
1
2
|
from typing import Iterable
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
import pyoxigraph as og
|
|
4
5
|
|
|
6
|
+
from rdf4j_python.model.term import Quad, Triple
|
|
5
7
|
|
|
6
|
-
|
|
8
|
+
|
|
9
|
+
def serialize_statements(statements: Iterable[Quad] | Iterable[Triple]) -> bytes:
|
|
7
10
|
"""Serializes statements to RDF data.
|
|
8
11
|
|
|
9
12
|
Args:
|
|
10
|
-
statements (Iterable[
|
|
13
|
+
statements (Iterable[Quad] | Iterable[Triple]): RDF statements.
|
|
11
14
|
|
|
12
15
|
Returns:
|
|
13
|
-
|
|
16
|
+
bytes: Serialized RDF data.
|
|
14
17
|
"""
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if ctx:
|
|
19
|
-
parts.append(ctx.n3())
|
|
20
|
-
parts.append(".")
|
|
21
|
-
lines.append(" ".join(parts))
|
|
22
|
-
return "\n".join(lines) + "\n"
|
|
18
|
+
io = BytesIO()
|
|
19
|
+
og.serialize(statements, output=io, format=og.RdfFormat.N_QUADS)
|
|
20
|
+
return io.getvalue()
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rdf4j-python
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: The Python client for RDF4J
|
|
5
5
|
Author-email: Chengxu Bian <cbian564@gmail.com>
|
|
6
6
|
Requires-Python: >=3.10
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
8
8
|
License-File: LICENSE
|
|
9
9
|
Requires-Dist: httpx>=0.28.1
|
|
10
|
-
Requires-Dist:
|
|
10
|
+
Requires-Dist: pyoxigraph>=0.4.10
|
|
11
11
|
Dynamic: license-file
|
|
12
12
|
|
|
13
13
|
# 🐍 rdf4j-python
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
rdf4j_python/__init__.py,sha256=E8gojaWuLHo2AfNn5HBc5cF7K8_dK2jOBcZaH_qoZs4,347
|
|
2
|
+
rdf4j_python/_client/__init__.py,sha256=L5q5RTHXCNyHp2WNP4xTemGXNntUW4RF_QJPoCWciUQ,98
|
|
3
|
+
rdf4j_python/_client/_client.py,sha256=JfHFudRDVkzmb_jWx1u2meqqFONImBQHuaoYkb4mWPc,7390
|
|
4
|
+
rdf4j_python/_driver/__init__.py,sha256=au0r15mQBVaJkqBknw9CoVswe7_rPPFs1wFWI_ttdy4,224
|
|
5
|
+
rdf4j_python/_driver/_async_named_graph.py,sha256=BqJRpN-JzGpvlSnWY2RrM5TrnIHg6W4PortZ0y-4mgw,2685
|
|
6
|
+
rdf4j_python/_driver/_async_rdf4j_db.py,sha256=LkeLwLhp_lSYhrJVY98LHv9V4jkxF0U5RWQiZmVI9zw,4435
|
|
7
|
+
rdf4j_python/_driver/_async_repository.py,sha256=E6DfW05LFh5KY2X081tW9gg1ksr7DyiM90_j29v71VQ,14212
|
|
8
|
+
rdf4j_python/exception/__init__.py,sha256=PFdUyIMsHIL5e2P2z33Qr2pwlUAJVI0G5T8114W4-1A,83
|
|
9
|
+
rdf4j_python/exception/repo_exception.py,sha256=WXlfIYzOYfNU8LpwtOct9fAZADR-P3cZx4jAX9v_HaA,704
|
|
10
|
+
rdf4j_python/model/__init__.py,sha256=wHboqZX2bN3AubXvWRwKOWwnrefpeiiB_nnry2Ba_a4,176
|
|
11
|
+
rdf4j_python/model/_namespace.py,sha256=6iOvPc2Z6XFY44wmVucQCrjZbFuxdBtoTfDq_bSHJS0,3854
|
|
12
|
+
rdf4j_python/model/_repository_info.py,sha256=fdKwjoQz6_D95Q8uZEuEYhXEUeqElsdBkHRCRRNxjzM,2010
|
|
13
|
+
rdf4j_python/model/repository_config.py,sha256=Uawni9kTjUpH3gCXQxh026NJaGVaJxDd5M-A5U9Ho_4,56654
|
|
14
|
+
rdf4j_python/model/term.py,sha256=JBxndQESR2KEY6y9s6TqoELUQaegKcIUO0ctR818QaA,508
|
|
15
|
+
rdf4j_python/model/vocabulary.py,sha256=Yam0F_YNlO-7wDi2fc0DkAqIKB4ZqCpqq56wKRrFAcw,307
|
|
16
|
+
rdf4j_python/utils/__init__.py,sha256=LAyzkmO5QOIjJogQE1m4Eszwb2cCU8ytKRfhjAGoraw,34
|
|
17
|
+
rdf4j_python/utils/const.py,sha256=HKH9ZGe7m_dvMx1RwT6zhu2HUkvwOX2Y4e8vQFs3uE8,849
|
|
18
|
+
rdf4j_python/utils/helpers.py,sha256=4ubvrx3OV_0Y2_YECNIJhkJUB-JthdCJA8d6Hz_G_kE,506
|
|
19
|
+
rdf4j_python-0.1.3.dist-info/licenses/LICENSE,sha256=sGjA7CzoCG1LVlkh0ZB76ZdgWHVpUFegLU41YYDkGIA,1499
|
|
20
|
+
rdf4j_python-0.1.3.dist-info/METADATA,sha256=Qo5X3u9Mw5r3ABzTmHzlUEEfO01DEsFm_BL2tyfWmAU,2857
|
|
21
|
+
rdf4j_python-0.1.3.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
|
|
22
|
+
rdf4j_python-0.1.3.dist-info/top_level.txt,sha256=Lf2K8d8WcEkmvo5giLGuZ3gl20rNEwMssyAFBeVzbCs,13
|
|
23
|
+
rdf4j_python-0.1.3.dist-info/RECORD,,
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
from abc import ABC
|
|
2
|
-
from typing import Mapping, Optional
|
|
3
|
-
|
|
4
|
-
from rdflib.term import Identifier, Literal, URIRef, Variable
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class _BaseModel(ABC):
|
|
8
|
-
"""Abstract base class providing utility methods for parsing RDF query results."""
|
|
9
|
-
|
|
10
|
-
@staticmethod
|
|
11
|
-
def get_literal(
|
|
12
|
-
result: Mapping[Variable, Identifier],
|
|
13
|
-
var_name: str,
|
|
14
|
-
default: Optional[str] = None,
|
|
15
|
-
) -> Optional[str]:
|
|
16
|
-
"""
|
|
17
|
-
Extracts a literal value from a SPARQL query result.
|
|
18
|
-
|
|
19
|
-
Args:
|
|
20
|
-
result (Mapping[Variable, Identifier]): A mapping of variable bindings from a query result.
|
|
21
|
-
var_name (str): The variable name to extract.
|
|
22
|
-
default (Optional[str], optional): The value to return if the variable is not found or is not a Literal. Defaults to None.
|
|
23
|
-
|
|
24
|
-
Returns:
|
|
25
|
-
Optional[str]: The Python representation of the literal, or the default value.
|
|
26
|
-
"""
|
|
27
|
-
val = result.get(Variable(var_name))
|
|
28
|
-
return val.toPython() if isinstance(val, Literal) else default
|
|
29
|
-
|
|
30
|
-
@staticmethod
|
|
31
|
-
def get_uri(
|
|
32
|
-
result: Mapping[Variable, Identifier],
|
|
33
|
-
var_name: str,
|
|
34
|
-
default: Optional[str] = None,
|
|
35
|
-
) -> Optional[str]:
|
|
36
|
-
"""
|
|
37
|
-
Extracts a URI value from a SPARQL query result.
|
|
38
|
-
|
|
39
|
-
Args:
|
|
40
|
-
result (Mapping[Variable, Identifier]): A mapping of variable bindings from a query result.
|
|
41
|
-
var_name (str): The variable name to extract.
|
|
42
|
-
default (Optional[str], optional): The value to return if the variable is not found or is not a URIRef. Defaults to None.
|
|
43
|
-
|
|
44
|
-
Returns:
|
|
45
|
-
Optional[str]: The URI string, or the default value.
|
|
46
|
-
"""
|
|
47
|
-
val = result.get(Variable(var_name))
|
|
48
|
-
return str(val) if isinstance(val, URIRef) else default
|
rdf4j_python/model/_dataset.py
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
from rdflib import Dataset as _Dataset
|
|
2
|
-
|
|
3
|
-
from rdf4j_python.model.term import IRI
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class RDF4JDataSet(_Dataset):
|
|
7
|
-
"""
|
|
8
|
-
An RDFLib Dataset subclass with RDF4J-specific utility methods.
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
def as_list(self) -> list[tuple]:
|
|
12
|
-
"""
|
|
13
|
-
Converts all quads in the dataset to a list of 4-tuples.
|
|
14
|
-
|
|
15
|
-
Replaces the RDF4J default context IRI ("urn:x-rdflib:default") with None.
|
|
16
|
-
|
|
17
|
-
Returns:
|
|
18
|
-
list[tuple]: A list of (subject, predicate, object, context) quads.
|
|
19
|
-
"""
|
|
20
|
-
return [
|
|
21
|
-
(s, p, o, ctx if ctx != IRI("urn:x-rdflib:default") else None)
|
|
22
|
-
for s, p, o, ctx in self.quads((None, None, None, None))
|
|
23
|
-
]
|
|
24
|
-
|
|
25
|
-
@staticmethod
|
|
26
|
-
def from_raw_text(text: str) -> "RDF4JDataSet":
|
|
27
|
-
"""
|
|
28
|
-
Parses a string of N-Quads RDF data into an RDF4JDataSet.
|
|
29
|
-
|
|
30
|
-
Args:
|
|
31
|
-
text (str): The RDF data in N-Quads format.
|
|
32
|
-
|
|
33
|
-
Returns:
|
|
34
|
-
RDF4JDataSet: A populated dataset.
|
|
35
|
-
"""
|
|
36
|
-
ds = RDF4JDataSet()
|
|
37
|
-
ds.parse(data=text, format="nquads")
|
|
38
|
-
return ds
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
rdf4j_python/__init__.py,sha256=E8gojaWuLHo2AfNn5HBc5cF7K8_dK2jOBcZaH_qoZs4,347
|
|
2
|
-
rdf4j_python/_client/__init__.py,sha256=L5q5RTHXCNyHp2WNP4xTemGXNntUW4RF_QJPoCWciUQ,98
|
|
3
|
-
rdf4j_python/_client/_client.py,sha256=JfHFudRDVkzmb_jWx1u2meqqFONImBQHuaoYkb4mWPc,7390
|
|
4
|
-
rdf4j_python/_driver/__init__.py,sha256=au0r15mQBVaJkqBknw9CoVswe7_rPPFs1wFWI_ttdy4,224
|
|
5
|
-
rdf4j_python/_driver/_async_named_graph.py,sha256=zpYr6x_9aI2wHH0Pj71LlCKkHFFanz7G77Tz5azXlg4,2642
|
|
6
|
-
rdf4j_python/_driver/_async_rdf4j_db.py,sha256=u6r4A4_CTp4JMEswl0I5rMjsuWnMkQV_TJrvF6u9R94,4403
|
|
7
|
-
rdf4j_python/_driver/_async_repository.py,sha256=NKM9IFLTNMepVCx_UeWc7h0BTxHMKfDnUcThz97pVCs,14075
|
|
8
|
-
rdf4j_python/exception/__init__.py,sha256=PFdUyIMsHIL5e2P2z33Qr2pwlUAJVI0G5T8114W4-1A,83
|
|
9
|
-
rdf4j_python/exception/repo_exception.py,sha256=WXlfIYzOYfNU8LpwtOct9fAZADR-P3cZx4jAX9v_HaA,704
|
|
10
|
-
rdf4j_python/model/__init__.py,sha256=eUvfFEPgDsbq37eIpd_dlvjpQPGuRwkKWNfqa0c2QwM,231
|
|
11
|
-
rdf4j_python/model/_base_model.py,sha256=PyhvLhaseKaFuRU70xord8EgIfO88-UVcllkuRobE14,1780
|
|
12
|
-
rdf4j_python/model/_dataset.py,sha256=-nYTm8Fz1CGsLL2ykmtGEJ9Jv4u8FC2Dgl_31LeoGhM,1065
|
|
13
|
-
rdf4j_python/model/_namespace.py,sha256=yaH-MjMFsUfCFadlo25MgHf9zaRbk-wkn_BgtmemVo4,3259
|
|
14
|
-
rdf4j_python/model/_repository_info.py,sha256=zSL3o_QWL06xYbnpFtXIg-PqFiRbwDFPb1aiy2JufYQ,1668
|
|
15
|
-
rdf4j_python/model/repository_config.py,sha256=WPXJAbZ2pM594Uh_r3zI6N1fqObSsk74ArVZTTdqPks,55012
|
|
16
|
-
rdf4j_python/model/term.py,sha256=FkK8-HG6h79dAYO_qiTYTxvu8t-d5zVY5FtgJrW997o,352
|
|
17
|
-
rdf4j_python/model/vocabulary.py,sha256=R9k9dzDPwRBEgwjIF6sNZh3hL41R7GZ1eSJKb8w7IaY,247
|
|
18
|
-
rdf4j_python/utils/__init__.py,sha256=LAyzkmO5QOIjJogQE1m4Eszwb2cCU8ytKRfhjAGoraw,34
|
|
19
|
-
rdf4j_python/utils/const.py,sha256=HKH9ZGe7m_dvMx1RwT6zhu2HUkvwOX2Y4e8vQFs3uE8,849
|
|
20
|
-
rdf4j_python/utils/helpers.py,sha256=xnMB_imsybGQ2GiHvXK4wEpcs4ADiqZ4ez0yop_ko8E,577
|
|
21
|
-
rdf4j_python-0.1.2.dist-info/licenses/LICENSE,sha256=sGjA7CzoCG1LVlkh0ZB76ZdgWHVpUFegLU41YYDkGIA,1499
|
|
22
|
-
rdf4j_python-0.1.2.dist-info/METADATA,sha256=7V13OG7A4fxFPLcwbIUjsqUCVDwC1dlqXE5YSHw7PbU,2852
|
|
23
|
-
rdf4j_python-0.1.2.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
|
|
24
|
-
rdf4j_python-0.1.2.dist-info/top_level.txt,sha256=Lf2K8d8WcEkmvo5giLGuZ3gl20rNEwMssyAFBeVzbCs,13
|
|
25
|
-
rdf4j_python-0.1.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|