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.
@@ -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 RDF4JDataSet
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) -> RDF4JDataSet:
26
+ async def get(self) -> QuadResultSet:
26
27
  """Fetches all RDF statements from this named graph.
27
28
 
28
29
  Returns:
29
- str: RDF data serialized in the requested format.
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 RDF4JDataSet.from_raw_text(response.text)
39
+ return og.parse(response.content, format=og.RdfFormat.N_QUADS)
39
40
 
40
- async def add(self, statements: Iterable[RDFStatement]):
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[RDFStatement]): RDF statements to add.
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 rdflib
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
- result = rdflib.query.Result.parse(
70
- response, format=Rdf4jContentType.SPARQL_RESULTS_JSON
69
+ query_solutions = og.parse_query_results(
70
+ response.text, format=og.QueryResultsFormat.JSON
71
71
  )
72
72
  return [
73
- RepositoryMetadata.from_rdflib_binding(binding)
74
- for binding in result.bindings
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 rdflib
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, RDF4JDataSet
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
- RDFStatement,
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.value}
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
- async def set_namespace(self, prefix: str, namespace: str):
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 (str): The namespace URI.
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.value}
114
- response = await self._client.put(path, content=namespace, headers=headers)
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.value}
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
- ) -> RDF4JDataSet:
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
- DataSet: Dataset of matching RDF statements.
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.n3()
220
+ params["subj"] = str(subject)
215
221
  if predicate:
216
- params["pred"] = predicate.n3()
222
+ params["pred"] = str(predicate)
217
223
  if object_:
218
- params["obj"] = object_.n3()
224
+ params["obj"] = str(object_)
219
225
  if contexts:
220
- params["context"] = [ctx.n3() for ctx in contexts]
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
- dataset = RDF4JDataSet()
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.n3()
257
+ params["subj"] = str(subject)
254
258
  if predicate:
255
- params["pred"] = predicate.n3()
259
+ params["pred"] = str(predicate)
256
260
  if object_:
257
- params["obj"] = object_.n3()
261
+ params["obj"] = str(object_)
258
262
  if contexts:
259
- params["context"] = [ctx.n3() for ctx in contexts]
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([(subject, predicate, object, context)]),
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[RDFStatement]):
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[RDFStatement]): A list of RDF statements.
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[RDFStatement],
324
- contexts: Optional[list[Context]] = None,
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[RDFStatement]): RDF statements to load.
331
- contexts (Optional[list[Context]]): One or more specific contexts to restrict deletion to.
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.value}
347
+ headers = {"Content-Type": Rdf4jContentType.NQUADS}
339
348
 
340
349
  params = {}
341
350
  if contexts:
342
- params["context"] = [ctx.n3() for ctx in contexts]
351
+ params["context"] = [str(ctx) for ctx in contexts]
343
352
  if base_uri:
344
353
  params["baseUri"] = base_uri
345
354
 
@@ -2,12 +2,10 @@
2
2
  RDF4J Python Model Module
3
3
  """
4
4
 
5
- from ._dataset import RDF4JDataSet
6
5
  from ._namespace import Namespace
7
6
  from ._repository_info import RepositoryMetadata
8
7
 
9
8
  __all__ = [
10
9
  "Namespace",
11
10
  "RepositoryMetadata",
12
- "RDF4JDataSet",
13
11
  ]
@@ -1,11 +1,32 @@
1
- from typing import Mapping
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
- from ._base_model import _BaseModel
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: RdflibNamespace
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 = RdflibNamespace(namespace)
49
+ self._namespace = _Namespace(namespace)
29
50
 
30
51
  @classmethod
31
- def from_rdflib_binding(cls, binding: Mapping[Variable, Identifier]) -> "Namespace":
52
+ def from_sparql_query_solution(
53
+ cls, query_solution: og.QuerySolution
54
+ ) -> "Namespace":
32
55
  """
33
- Creates a Namespace from a RDFlib binding.
56
+ Creates a Namespace from a binding.
34
57
 
35
58
  Args:
36
- binding (Mapping[Variable, Identifier]): The RDFlib binding.
59
+ binding (Mapping[Variable, Identifier]): The binding.
37
60
 
38
61
  Returns:
39
62
  Namespace: The created Namespace.
40
63
  """
41
- prefix = _BaseModel.get_literal(binding, "prefix", "")
42
- namespace = _BaseModel.get_literal(binding, "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 IRI(self._namespace.term(name))
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
- from rdflib.term import Identifier, Variable
5
-
6
- from ._base_model import _BaseModel
3
+ import pyoxigraph as og
7
4
 
8
5
 
9
6
  @dataclass
10
- class RepositoryMetadata(_BaseModel):
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 from_rdflib_binding(
32
- cls, result: Mapping[Variable, Identifier]
28
+ def from_sparql_query_solution(
29
+ cls, query_solution: og.QuerySolution
33
30
  ) -> "RepositoryMetadata":
34
31
  """
35
- Create a Repository instance from a SPARQL query result
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
- result (Mapping[Variable, Identifier]): The SPARQL query result.
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=_BaseModel.get_literal(result, "id", ""),
48
- uri=_BaseModel.get_uri(result, "uri", ""),
49
- title=_BaseModel.get_literal(result, "title", ""),
50
- readable=_BaseModel.get_literal(result, "readable", False),
51
- writable=_BaseModel.get_literal(result, "writable", False),
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 rdflib import BNode, Graph, Literal, Namespace, URIRef
4
- from rdflib.namespace import RDF, RDFS, XSD
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 RDFlib.
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 = 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 graph.serialize(format="turtle").encode("utf-8")
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 RDFlib.
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: Graph) -> URIRef:
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
- (sail_node, CONFIG[key], Literal(value, datatype=XSD.integer))
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((sail_node, CONFIG[key], Literal(value, datatype=XSD.double)))
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
- (sail_node, CONFIG[key], Literal(value, datatype=XSD.boolean))
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))) # Assuming IRIs
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 using RDFlib.
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 using RDFlib.
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 using RDFlib.
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: Graph) -> URIRef:
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 RDFlib.
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: Graph) -> URIRef:
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 RDFlib.
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: Graph) -> URIRef:
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, int):
443
+ graph.add(Quad(sail_node, CONFIG[key], Literal(value), None))
444
+ elif isinstance(value, bool):
426
445
  graph.add(
427
- (sail_node, CONFIG[key], Literal(value, datatype=XSD.integer))
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
- (sail_node, CONFIG[key], Literal(value, datatype=XSD.boolean))
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 RDFlib.
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 RDFlib.
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 RDFlib.
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 RDFlib.
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: Graph) -> URIRef:
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 RDFlib.
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: Graph) -> URIRef:
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 RDFlib.
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: Graph) -> URIRef:
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
- (sail_node, CONFIG[key], Literal(value, datatype=XSD.boolean))
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
- (sail_node, CONFIG[key], Literal(value, datatype=XSD.integer))
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((sail_node, CONFIG[key], Literal(value)))
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:
@@ -1,14 +1,20 @@
1
- from typing import Optional, Tuple, TypeAlias
1
+ from typing import TypeAlias
2
2
 
3
- from rdflib import URIRef as _URIRef
4
- from rdflib.term import IdentifiedNode, Node
3
+ import pyoxigraph as og
5
4
 
6
- IRI: TypeAlias = _URIRef
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 = Node
10
- Predicate: TypeAlias = Node
11
- Object: TypeAlias = Node
12
- Context: TypeAlias = Optional[IdentifiedNode]
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
- RDFStatement: TypeAlias = Tuple[Subject, Predicate, Object, Context]
19
+
20
+ QuadResultSet: TypeAlias = og.QuadParser
@@ -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#")
@@ -1,22 +1,20 @@
1
+ from io import BytesIO
1
2
  from typing import Iterable
2
3
 
3
- from rdf4j_python.model.term import RDFStatement
4
+ import pyoxigraph as og
4
5
 
6
+ from rdf4j_python.model.term import Quad, Triple
5
7
 
6
- def serialize_statements(statements: Iterable[RDFStatement]) -> str:
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[RDFStatement]): RDF statements.
13
+ statements (Iterable[Quad] | Iterable[Triple]): RDF statements.
11
14
 
12
15
  Returns:
13
- str: Serialized RDF data.
16
+ bytes: Serialized RDF data.
14
17
  """
15
- lines = []
16
- for subj, pred, obj, ctx in statements:
17
- parts = [subj.n3(), pred.n3(), obj.n3()]
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.2
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: rdflib>=7.1.4
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
@@ -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,,