rdf4j-python 0.1.3__py3-none-any.whl → 0.1.4__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_rdf4j_db.py +1 -0
- rdf4j_python/_driver/_async_repository.py +43 -12
- rdf4j_python/model/repository_config.py +5 -5
- {rdf4j_python-0.1.3.dist-info → rdf4j_python-0.1.4.dist-info}/METADATA +4 -1
- {rdf4j_python-0.1.3.dist-info → rdf4j_python-0.1.4.dist-info}/RECORD +8 -8
- {rdf4j_python-0.1.3.dist-info → rdf4j_python-0.1.4.dist-info}/WHEEL +1 -1
- {rdf4j_python-0.1.3.dist-info → rdf4j_python-0.1.4.dist-info}/licenses/LICENSE +0 -0
- {rdf4j_python-0.1.3.dist-info → rdf4j_python-0.1.4.dist-info}/top_level.txt +0 -0
|
@@ -69,6 +69,7 @@ class AsyncRdf4j:
|
|
|
69
69
|
query_solutions = og.parse_query_results(
|
|
70
70
|
response.text, format=og.QueryResultsFormat.JSON
|
|
71
71
|
)
|
|
72
|
+
assert isinstance(query_solutions, og.QuerySolutions)
|
|
72
73
|
return [
|
|
73
74
|
RepositoryMetadata.from_sparql_query_solution(query_solution)
|
|
74
75
|
for query_solution in query_solutions
|
|
@@ -25,10 +25,21 @@ from rdf4j_python.model.term import (
|
|
|
25
25
|
from rdf4j_python.utils.const import Rdf4jContentType
|
|
26
26
|
from rdf4j_python.utils.helpers import serialize_statements
|
|
27
27
|
|
|
28
|
+
try:
|
|
29
|
+
from SPARQLWrapper import SPARQLWrapper
|
|
30
|
+
|
|
31
|
+
_has_sparql_wrapper = True
|
|
32
|
+
except ImportError:
|
|
33
|
+
_has_sparql_wrapper = False
|
|
34
|
+
|
|
28
35
|
|
|
29
36
|
class AsyncRdf4JRepository:
|
|
30
37
|
"""Asynchronous interface for interacting with an RDF4J repository."""
|
|
31
38
|
|
|
39
|
+
_client: AsyncApiClient
|
|
40
|
+
_repository_id: str
|
|
41
|
+
_sparql_wrapper: Optional["SPARQLWrapper"] = None
|
|
42
|
+
|
|
32
43
|
def __init__(self, client: AsyncApiClient, repository_id: str):
|
|
33
44
|
"""Initializes the repository interface.
|
|
34
45
|
|
|
@@ -39,32 +50,47 @@ class AsyncRdf4JRepository:
|
|
|
39
50
|
self._client = client
|
|
40
51
|
self._repository_id = repository_id
|
|
41
52
|
|
|
53
|
+
async def get_sparql_wrapper(self) -> "SPARQLWrapper":
|
|
54
|
+
"""Returns the SPARQLWrapper for the repository.
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
SPARQLWrapper: The SPARQLWrapper for the repository.
|
|
58
|
+
"""
|
|
59
|
+
if not _has_sparql_wrapper:
|
|
60
|
+
raise ImportError(
|
|
61
|
+
"SPARQLWrapper is not installed. Please install it with `pip install rdf4j-python[sparqlwrapper]`"
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
if self._sparql_wrapper is None:
|
|
65
|
+
self._sparql_wrapper = SPARQLWrapper(
|
|
66
|
+
f"{self._client.get_base_url()}/repositories/{self._repository_id}"
|
|
67
|
+
)
|
|
68
|
+
return self._sparql_wrapper
|
|
69
|
+
|
|
42
70
|
async def query(
|
|
43
71
|
self,
|
|
44
72
|
sparql_query: str,
|
|
45
73
|
infer: bool = True,
|
|
46
|
-
|
|
47
|
-
):
|
|
74
|
+
) -> og.QuerySolutions | og.QueryBoolean:
|
|
48
75
|
"""Executes a SPARQL SELECT query.
|
|
49
76
|
|
|
50
77
|
Args:
|
|
51
78
|
sparql_query (str): The SPARQL query string.
|
|
52
79
|
infer (bool): Whether to include inferred statements. Defaults to True.
|
|
53
|
-
accept (Rdf4jContentType): The expected response format.
|
|
54
80
|
|
|
55
81
|
Returns:
|
|
56
|
-
|
|
82
|
+
og.QuerySolutions | og.QueryBoolean: Parsed query results.
|
|
57
83
|
"""
|
|
58
84
|
path = f"/repositories/{self._repository_id}"
|
|
59
85
|
params = {"query": sparql_query, "infer": str(infer).lower()}
|
|
60
|
-
headers = {"Accept":
|
|
86
|
+
headers = {"Accept": Rdf4jContentType.SPARQL_RESULTS_JSON}
|
|
61
87
|
response = await self._client.get(path, params=params, headers=headers)
|
|
62
88
|
self._handle_repo_not_found_exception(response)
|
|
63
|
-
|
|
64
|
-
return response.json()
|
|
65
|
-
return response.text
|
|
89
|
+
return og.parse_query_results(response.text, format=og.QueryResultsFormat.JSON)
|
|
66
90
|
|
|
67
|
-
async def update(
|
|
91
|
+
async def update(
|
|
92
|
+
self, sparql_update_query: str, content_type: Rdf4jContentType
|
|
93
|
+
) -> None:
|
|
68
94
|
"""Executes a SPARQL UPDATE command.
|
|
69
95
|
|
|
70
96
|
Args:
|
|
@@ -74,11 +100,15 @@ class AsyncRdf4JRepository:
|
|
|
74
100
|
RepositoryNotFoundException: If the repository doesn't exist.
|
|
75
101
|
httpx.HTTPStatusError: If the update fails.
|
|
76
102
|
"""
|
|
103
|
+
# TODO: handle update results
|
|
77
104
|
path = f"/repositories/{self._repository_id}/statements"
|
|
78
|
-
headers = {"Content-Type":
|
|
79
|
-
response = await self._client.post(
|
|
105
|
+
headers = {"Content-Type": content_type}
|
|
106
|
+
response = await self._client.post(
|
|
107
|
+
path, content=sparql_update_query, headers=headers
|
|
108
|
+
)
|
|
80
109
|
self._handle_repo_not_found_exception(response)
|
|
81
|
-
response.
|
|
110
|
+
if response.status_code != httpx.codes.NO_CONTENT:
|
|
111
|
+
raise RepositoryUpdateException(f"Failed to update: {response.text}")
|
|
82
112
|
|
|
83
113
|
async def get_namespaces(self):
|
|
84
114
|
"""Retrieves all namespaces in the repository.
|
|
@@ -97,6 +127,7 @@ class AsyncRdf4JRepository:
|
|
|
97
127
|
query_solutions = og.parse_query_results(
|
|
98
128
|
response.text, format=og.QueryResultsFormat.JSON
|
|
99
129
|
)
|
|
130
|
+
assert isinstance(query_solutions, og.QuerySolutions)
|
|
100
131
|
return [
|
|
101
132
|
Namespace.from_sparql_query_solution(query_solution)
|
|
102
133
|
for query_solution in query_solutions
|
|
@@ -59,12 +59,12 @@ class RepositoryConfig:
|
|
|
59
59
|
"""
|
|
60
60
|
return self._title
|
|
61
61
|
|
|
62
|
-
def to_turtle(self) ->
|
|
62
|
+
def to_turtle(self) -> bytes | None:
|
|
63
63
|
"""
|
|
64
64
|
Serializes the Repository configuration to Turtle syntax using .
|
|
65
65
|
|
|
66
66
|
Returns:
|
|
67
|
-
|
|
67
|
+
bytes | None: A UTF-8 encoded Turtle string representing the RDF4J repository configuration.
|
|
68
68
|
The serialization includes the repository ID, optional human-readable title,
|
|
69
69
|
and nested repository implementation configuration if available.
|
|
70
70
|
|
|
@@ -909,7 +909,7 @@ class SchemaCachingRDFSInferencerConfig(SailConfig):
|
|
|
909
909
|
"""
|
|
910
910
|
sail_node = super().add_to_graph(graph)
|
|
911
911
|
delegate_node = self.config_params["delegate"].to_rdf(graph)
|
|
912
|
-
graph.add((sail_node, CONFIG.delegate, delegate_node))
|
|
912
|
+
graph.add(Quad(sail_node, CONFIG.delegate, delegate_node, None))
|
|
913
913
|
return sail_node
|
|
914
914
|
|
|
915
915
|
class Builder:
|
|
@@ -1002,7 +1002,7 @@ class DirectTypeHierarchyInferencerConfig(SailConfig):
|
|
|
1002
1002
|
"""
|
|
1003
1003
|
sail_node = super().add_to_graph(graph)
|
|
1004
1004
|
delegate_node = self.config_params["delegate"].to_rdf(graph)
|
|
1005
|
-
graph.add((sail_node, CONFIG["delegate"], delegate_node))
|
|
1005
|
+
graph.add(Quad(sail_node, CONFIG["delegate"], delegate_node, None))
|
|
1006
1006
|
return sail_node
|
|
1007
1007
|
|
|
1008
1008
|
class Builder:
|
|
@@ -1175,7 +1175,7 @@ class SHACLSailConfig(SailConfig):
|
|
|
1175
1175
|
"""
|
|
1176
1176
|
sail_node = super().add_to_graph(graph) # Get the basic node
|
|
1177
1177
|
delegate_node = self.config_params["delegate"].to_rdf(graph)
|
|
1178
|
-
graph.add((sail_node, CONFIG.delegate, delegate_node))
|
|
1178
|
+
graph.add(Quad(sail_node, CONFIG.delegate, delegate_node, None))
|
|
1179
1179
|
|
|
1180
1180
|
# Add SHACL-specific parameters
|
|
1181
1181
|
for key, value in self.config_params.items():
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rdf4j-python
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: The Python client for RDF4J
|
|
5
5
|
Author-email: Chengxu Bian <cbian564@gmail.com>
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -8,6 +8,8 @@ Description-Content-Type: text/markdown
|
|
|
8
8
|
License-File: LICENSE
|
|
9
9
|
Requires-Dist: httpx>=0.28.1
|
|
10
10
|
Requires-Dist: pyoxigraph>=0.4.10
|
|
11
|
+
Provides-Extra: sparqlwrapper
|
|
12
|
+
Requires-Dist: sparqlwrapper>=2.0.0; extra == "sparqlwrapper"
|
|
11
13
|
Dynamic: license-file
|
|
12
14
|
|
|
13
15
|
# 🐍 rdf4j-python
|
|
@@ -60,6 +62,7 @@ async with AsyncRdf4j("http://localhost:19780/rdf4j-server") as db:
|
|
|
60
62
|
Literal("test_object"),
|
|
61
63
|
)
|
|
62
64
|
await repo.get_statements(subject=IRI("http://example.com/subject"))
|
|
65
|
+
results = await repo.query("SELECT * WHERE { ?s ?p ?o }")
|
|
63
66
|
```
|
|
64
67
|
|
|
65
68
|
For more detailed examples, refer to the [examples](https://github.com/odysa/rdf4j-python/tree/main/examples) directory.
|
|
@@ -3,21 +3,21 @@ rdf4j_python/_client/__init__.py,sha256=L5q5RTHXCNyHp2WNP4xTemGXNntUW4RF_QJPoCWc
|
|
|
3
3
|
rdf4j_python/_client/_client.py,sha256=JfHFudRDVkzmb_jWx1u2meqqFONImBQHuaoYkb4mWPc,7390
|
|
4
4
|
rdf4j_python/_driver/__init__.py,sha256=au0r15mQBVaJkqBknw9CoVswe7_rPPFs1wFWI_ttdy4,224
|
|
5
5
|
rdf4j_python/_driver/_async_named_graph.py,sha256=BqJRpN-JzGpvlSnWY2RrM5TrnIHg6W4PortZ0y-4mgw,2685
|
|
6
|
-
rdf4j_python/_driver/_async_rdf4j_db.py,sha256=
|
|
7
|
-
rdf4j_python/_driver/_async_repository.py,sha256=
|
|
6
|
+
rdf4j_python/_driver/_async_rdf4j_db.py,sha256=POJ2-5EiyFOjX6ykjxbm0RH7yjtU6mXCY2PlVYidLDI,4497
|
|
7
|
+
rdf4j_python/_driver/_async_repository.py,sha256=sW52MvZfbPeqJciFk4bgTHcDpxlZpXSikEsYflAmYHQ,15251
|
|
8
8
|
rdf4j_python/exception/__init__.py,sha256=PFdUyIMsHIL5e2P2z33Qr2pwlUAJVI0G5T8114W4-1A,83
|
|
9
9
|
rdf4j_python/exception/repo_exception.py,sha256=WXlfIYzOYfNU8LpwtOct9fAZADR-P3cZx4jAX9v_HaA,704
|
|
10
10
|
rdf4j_python/model/__init__.py,sha256=wHboqZX2bN3AubXvWRwKOWwnrefpeiiB_nnry2Ba_a4,176
|
|
11
11
|
rdf4j_python/model/_namespace.py,sha256=6iOvPc2Z6XFY44wmVucQCrjZbFuxdBtoTfDq_bSHJS0,3854
|
|
12
12
|
rdf4j_python/model/_repository_info.py,sha256=fdKwjoQz6_D95Q8uZEuEYhXEUeqElsdBkHRCRRNxjzM,2010
|
|
13
|
-
rdf4j_python/model/repository_config.py,sha256=
|
|
13
|
+
rdf4j_python/model/repository_config.py,sha256=6s-b0NPVILOLbmhAdTYR2xia7ErACvWvCUrAYcvZZng,56702
|
|
14
14
|
rdf4j_python/model/term.py,sha256=JBxndQESR2KEY6y9s6TqoELUQaegKcIUO0ctR818QaA,508
|
|
15
15
|
rdf4j_python/model/vocabulary.py,sha256=Yam0F_YNlO-7wDi2fc0DkAqIKB4ZqCpqq56wKRrFAcw,307
|
|
16
16
|
rdf4j_python/utils/__init__.py,sha256=LAyzkmO5QOIjJogQE1m4Eszwb2cCU8ytKRfhjAGoraw,34
|
|
17
17
|
rdf4j_python/utils/const.py,sha256=HKH9ZGe7m_dvMx1RwT6zhu2HUkvwOX2Y4e8vQFs3uE8,849
|
|
18
18
|
rdf4j_python/utils/helpers.py,sha256=4ubvrx3OV_0Y2_YECNIJhkJUB-JthdCJA8d6Hz_G_kE,506
|
|
19
|
-
rdf4j_python-0.1.
|
|
20
|
-
rdf4j_python-0.1.
|
|
21
|
-
rdf4j_python-0.1.
|
|
22
|
-
rdf4j_python-0.1.
|
|
23
|
-
rdf4j_python-0.1.
|
|
19
|
+
rdf4j_python-0.1.4.dist-info/licenses/LICENSE,sha256=sGjA7CzoCG1LVlkh0ZB76ZdgWHVpUFegLU41YYDkGIA,1499
|
|
20
|
+
rdf4j_python-0.1.4.dist-info/METADATA,sha256=wdaugJ9Oxn4-fgfwifMaIlK3bplUxHJan54ciVAtZKo,3011
|
|
21
|
+
rdf4j_python-0.1.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
22
|
+
rdf4j_python-0.1.4.dist-info/top_level.txt,sha256=Lf2K8d8WcEkmvo5giLGuZ3gl20rNEwMssyAFBeVzbCs,13
|
|
23
|
+
rdf4j_python-0.1.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|