rdf4j-python 0.1.1a0__tar.gz → 0.1.2__tar.gz

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.
Files changed (43) hide show
  1. {rdf4j_python-0.1.1a0 → rdf4j_python-0.1.2}/PKG-INFO +12 -12
  2. {rdf4j_python-0.1.1a0 → rdf4j_python-0.1.2}/README.md +10 -11
  3. {rdf4j_python-0.1.1a0 → rdf4j_python-0.1.2}/pyproject.toml +7 -1
  4. rdf4j_python-0.1.2/rdf4j_python/__init__.py +14 -0
  5. rdf4j_python-0.1.2/rdf4j_python/_client/_client.py +253 -0
  6. {rdf4j_python-0.1.1a0 → rdf4j_python-0.1.2}/rdf4j_python/_driver/__init__.py +2 -0
  7. rdf4j_python-0.1.2/rdf4j_python/_driver/_async_named_graph.py +75 -0
  8. {rdf4j_python-0.1.1a0 → rdf4j_python-0.1.2}/rdf4j_python/_driver/_async_rdf4j_db.py +55 -29
  9. rdf4j_python-0.1.2/rdf4j_python/_driver/_async_repository.py +382 -0
  10. rdf4j_python-0.1.2/rdf4j_python/exception/__init__.py +5 -0
  11. rdf4j_python-0.1.2/rdf4j_python/exception/repo_exception.py +34 -0
  12. rdf4j_python-0.1.2/rdf4j_python/model/__init__.py +13 -0
  13. rdf4j_python-0.1.2/rdf4j_python/model/_base_model.py +48 -0
  14. rdf4j_python-0.1.2/rdf4j_python/model/_dataset.py +38 -0
  15. rdf4j_python-0.1.2/rdf4j_python/model/_namespace.py +134 -0
  16. {rdf4j_python-0.1.1a0 → rdf4j_python-0.1.2}/rdf4j_python/model/_repository_info.py +12 -1
  17. rdf4j_python-0.1.1a0/rdf4j_python/model/_repository_config.py → rdf4j_python-0.1.2/rdf4j_python/model/repository_config.py +565 -17
  18. rdf4j_python-0.1.2/rdf4j_python/model/term.py +14 -0
  19. rdf4j_python-0.1.2/rdf4j_python/model/vocabulary.py +6 -0
  20. rdf4j_python-0.1.2/rdf4j_python/utils/__init__.py +3 -0
  21. {rdf4j_python-0.1.1a0 → rdf4j_python-0.1.2}/rdf4j_python/utils/const.py +4 -4
  22. rdf4j_python-0.1.2/rdf4j_python/utils/helpers.py +22 -0
  23. {rdf4j_python-0.1.1a0 → rdf4j_python-0.1.2}/rdf4j_python.egg-info/PKG-INFO +12 -12
  24. {rdf4j_python-0.1.1a0 → rdf4j_python-0.1.2}/rdf4j_python.egg-info/SOURCES.txt +9 -2
  25. rdf4j_python-0.1.2/tests/test_async_named_graph.py +83 -0
  26. rdf4j_python-0.1.2/tests/test_client.py +78 -0
  27. rdf4j_python-0.1.2/tests/test_rdf4j_repository.py +241 -0
  28. rdf4j_python-0.1.1a0/rdf4j_python/__init__.py +0 -9
  29. rdf4j_python-0.1.1a0/rdf4j_python/_client/_client.py +0 -102
  30. rdf4j_python-0.1.1a0/rdf4j_python/_driver/_async_repository.py +0 -109
  31. rdf4j_python-0.1.1a0/rdf4j_python/exception/repo_exception.py +0 -13
  32. rdf4j_python-0.1.1a0/rdf4j_python/model/__init__.py +0 -16
  33. rdf4j_python-0.1.1a0/rdf4j_python/model/_base_model.py +0 -26
  34. rdf4j_python-0.1.1a0/rdf4j_python/model/_namespace.py +0 -56
  35. rdf4j_python-0.1.1a0/rdf4j_python/utils/__init__.py +0 -0
  36. rdf4j_python-0.1.1a0/tests/test_client.py +0 -88
  37. rdf4j_python-0.1.1a0/tests/test_rdf4j_repo.py +0 -124
  38. {rdf4j_python-0.1.1a0 → rdf4j_python-0.1.2}/LICENSE +0 -0
  39. {rdf4j_python-0.1.1a0 → rdf4j_python-0.1.2}/rdf4j_python/_client/__init__.py +0 -0
  40. {rdf4j_python-0.1.1a0 → rdf4j_python-0.1.2}/rdf4j_python.egg-info/dependency_links.txt +0 -0
  41. {rdf4j_python-0.1.1a0 → rdf4j_python-0.1.2}/rdf4j_python.egg-info/requires.txt +0 -0
  42. {rdf4j_python-0.1.1a0 → rdf4j_python-0.1.2}/rdf4j_python.egg-info/top_level.txt +0 -0
  43. {rdf4j_python-0.1.1a0 → rdf4j_python-0.1.2}/setup.cfg +0 -0
@@ -1,7 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rdf4j-python
3
- Version: 0.1.1a0
3
+ Version: 0.1.2
4
4
  Summary: The Python client for RDF4J
5
+ Author-email: Chengxu Bian <cbian564@gmail.com>
5
6
  Requires-Python: >=3.10
6
7
  Description-Content-Type: text/markdown
7
8
  License-File: LICENSE
@@ -42,24 +43,23 @@ pip install rdf4j-python
42
43
  Here's a basic example of how to use `rdf4j-python` to create an in-memory sail repository
43
44
 
44
45
  ```python
45
- from rdf4j_python import AsyncRdf4j
46
- from rdf4j_python.model import MemoryStoreConfig, RepositoryConfig
47
- from rdf4j_python.utils.const import Rdf4jContentType
48
-
49
46
  async with AsyncRdf4j("http://localhost:19780/rdf4j-server") as db:
50
47
  repo_config = (
51
- RepositoryConfig.builder_with_sail_repository(
52
- MemoryStoreConfig.Builder().persist(False).build(),
53
- )
48
+ RepositoryConfig.Builder()
54
49
  .repo_id("example-repo")
55
50
  .title("Example Repository")
51
+ .sail_repository_impl(
52
+ MemoryStoreConfig.Builder().persist(False).build(),
53
+ )
56
54
  .build()
57
55
  )
58
- await db.create_repository(
59
- repository_id=repo_config.repo_id,
60
- rdf_config_data=repo_config.to_turtle(),
61
- content_type=Rdf4jContentType.TURTLE,
56
+ repo = await db.create_repository(config=repo_config)
57
+ await repo.add_statement(
58
+ IRI("http://example.com/subject"),
59
+ IRI("http://example.com/predicate"),
60
+ Literal("test_object"),
62
61
  )
62
+ await repo.get_statements(subject=IRI("http://example.com/subject"))
63
63
  ```
64
64
 
65
65
  For more detailed examples, refer to the [examples](https://github.com/odysa/rdf4j-python/tree/main/examples) directory.
@@ -31,24 +31,23 @@ pip install rdf4j-python
31
31
  Here's a basic example of how to use `rdf4j-python` to create an in-memory sail repository
32
32
 
33
33
  ```python
34
- from rdf4j_python import AsyncRdf4j
35
- from rdf4j_python.model import MemoryStoreConfig, RepositoryConfig
36
- from rdf4j_python.utils.const import Rdf4jContentType
37
-
38
34
  async with AsyncRdf4j("http://localhost:19780/rdf4j-server") as db:
39
35
  repo_config = (
40
- RepositoryConfig.builder_with_sail_repository(
41
- MemoryStoreConfig.Builder().persist(False).build(),
42
- )
36
+ RepositoryConfig.Builder()
43
37
  .repo_id("example-repo")
44
38
  .title("Example Repository")
39
+ .sail_repository_impl(
40
+ MemoryStoreConfig.Builder().persist(False).build(),
41
+ )
45
42
  .build()
46
43
  )
47
- await db.create_repository(
48
- repository_id=repo_config.repo_id,
49
- rdf_config_data=repo_config.to_turtle(),
50
- content_type=Rdf4jContentType.TURTLE,
44
+ repo = await db.create_repository(config=repo_config)
45
+ await repo.add_statement(
46
+ IRI("http://example.com/subject"),
47
+ IRI("http://example.com/predicate"),
48
+ Literal("test_object"),
51
49
  )
50
+ await repo.get_statements(subject=IRI("http://example.com/subject"))
52
51
  ```
53
52
 
54
53
  For more detailed examples, refer to the [examples](https://github.com/odysa/rdf4j-python/tree/main/examples) directory.
@@ -1,6 +1,7 @@
1
1
  [project]
2
2
  name = "rdf4j-python"
3
- version = "0.1.1a"
3
+ authors = [{ name = "Chengxu Bian", email = "cbian564@gmail.com" }]
4
+ version = "0.1.2"
4
5
  description = "The Python client for RDF4J"
5
6
  readme = "README.md"
6
7
  requires-python = ">=3.10"
@@ -13,6 +14,11 @@ dev = [
13
14
  "pytest-docker>=3.2.1",
14
15
  "ruff>=0.11.8",
15
16
  ]
17
+ docs = [
18
+ "furo>=2024.8.6",
19
+ "sphinx>=8",
20
+ ]
21
+
16
22
 
17
23
  [tool.pytest.ini_options]
18
24
  log_cli = true
@@ -0,0 +1,14 @@
1
+ """
2
+ RDF4J Python is a Python library for interacting with RDF4J repositories.
3
+ """
4
+
5
+ from ._driver import AsyncNamedGraph, AsyncRdf4j, AsyncRdf4JRepository
6
+ from .exception import * # noqa: F403
7
+ from .model import * # noqa: F403
8
+ from .utils import * # noqa: F403
9
+
10
+ __all__ = [
11
+ "AsyncRdf4j",
12
+ "AsyncRdf4JRepository",
13
+ "AsyncNamedGraph",
14
+ ]
@@ -0,0 +1,253 @@
1
+ from typing import Any, Dict, Optional
2
+
3
+ import httpx
4
+
5
+
6
+ class BaseClient:
7
+ """Base HTTP client that provides shared URL building functionality."""
8
+
9
+ def __init__(self, base_url: str, timeout: int = 10):
10
+ """
11
+ Initializes a BaseClient.
12
+
13
+ Args:
14
+ base_url (str): The base URL for the API endpoints.
15
+ timeout (int, optional): Request timeout in seconds. Defaults to 10.
16
+ """
17
+ self.base_url = base_url.rstrip("/")
18
+ self.timeout = timeout
19
+
20
+ def _build_url(self, path: str) -> str:
21
+ """
22
+ Builds a full URL by combining the base URL and the given path.
23
+
24
+ Args:
25
+ path (str): The path to append to the base URL.
26
+
27
+ Returns:
28
+ str: The full URL.
29
+ """
30
+ return f"{self.base_url}/{path.lstrip('/')}"
31
+
32
+ def get_base_url(self) -> str:
33
+ """
34
+ Returns the base URL.
35
+
36
+ Returns:
37
+ str: The base URL.
38
+ """
39
+ return self.base_url
40
+
41
+
42
+ class SyncApiClient(BaseClient):
43
+ """Synchronous API client using httpx.Client."""
44
+
45
+ def __enter__(self):
46
+ """
47
+ Enters the context and initializes the HTTP client.
48
+
49
+ Returns:
50
+ SyncApiClient: The instance of the client.
51
+ """
52
+ self.client = httpx.Client(timeout=self.timeout).__enter__()
53
+ return self
54
+
55
+ def __exit__(self, exc_type, exc_value, traceback):
56
+ """
57
+ Exits the context and closes the HTTP client.
58
+ """
59
+ self.client.__exit__(exc_type, exc_value, traceback)
60
+
61
+ def get(
62
+ self,
63
+ path: str,
64
+ params: Optional[Dict[str, Any]] = None,
65
+ headers: Optional[Dict[str, str]] = None,
66
+ ) -> httpx.Response:
67
+ """
68
+ Sends a GET request.
69
+
70
+ Args:
71
+ path (str): API endpoint path.
72
+ params (Optional[Dict[str, Any]]): Query parameters.
73
+ headers (Optional[Dict[str, str]]): Request headers.
74
+
75
+ Returns:
76
+ httpx.Response: The HTTP response.
77
+ """
78
+ return self.client.get(self._build_url(path), params=params, headers=headers)
79
+
80
+ def post(
81
+ self,
82
+ path: str,
83
+ data: Optional[Dict[str, Any]] = None,
84
+ json: Optional[Any] = None,
85
+ headers: Optional[Dict[str, str]] = None,
86
+ ) -> httpx.Response:
87
+ """
88
+ Sends a POST request.
89
+
90
+ Args:
91
+ path (str): API endpoint path.
92
+ data (Optional[Dict[str, Any]]): Form-encoded body data.
93
+ json (Optional[Any]): JSON-encoded body data.
94
+ headers (Optional[Dict[str, str]]): Request headers.
95
+
96
+ Returns:
97
+ httpx.Response: The HTTP response.
98
+ """
99
+ return self.client.post(
100
+ self._build_url(path), data=data, json=json, headers=headers
101
+ )
102
+
103
+ def put(
104
+ self,
105
+ path: str,
106
+ data: Optional[Dict[str, Any]] = None,
107
+ json: Optional[Any] = None,
108
+ headers: Optional[Dict[str, str]] = None,
109
+ ) -> httpx.Response:
110
+ """
111
+ Sends a PUT request.
112
+
113
+ Args:
114
+ path (str): API endpoint path.
115
+ data (Optional[Dict[str, Any]]): Form-encoded body data.
116
+ json (Optional[Any]): JSON-encoded body data.
117
+ headers (Optional[Dict[str, str]]): Request headers.
118
+
119
+ Returns:
120
+ httpx.Response: The HTTP response.
121
+ """
122
+ return self.client.put(
123
+ self._build_url(path), data=data, json=json, headers=headers
124
+ )
125
+
126
+ def delete(
127
+ self, path: str, headers: Optional[Dict[str, str]] = None
128
+ ) -> httpx.Response:
129
+ """
130
+ Sends a DELETE request.
131
+
132
+ Args:
133
+ path (str): API endpoint path.
134
+ headers (Optional[Dict[str, str]]): Request headers.
135
+
136
+ Returns:
137
+ httpx.Response: The HTTP response.
138
+ """
139
+ return self.client.delete(self._build_url(path), headers=headers)
140
+
141
+
142
+ class AsyncApiClient(BaseClient):
143
+ """Asynchronous API client using httpx.AsyncClient."""
144
+
145
+ async def __aenter__(self):
146
+ """
147
+ Enters the async context and initializes the HTTP client.
148
+
149
+ Returns:
150
+ AsyncApiClient: The instance of the client.
151
+ """
152
+ self.client = await httpx.AsyncClient(timeout=self.timeout).__aenter__()
153
+ return self
154
+
155
+ async def __aexit__(self, exc_type, exc_value, traceback):
156
+ """
157
+ Exits the async context and closes the HTTP client.
158
+ """
159
+ await self.client.__aexit__(exc_type, exc_value, traceback)
160
+
161
+ async def get(
162
+ self,
163
+ path: str,
164
+ params: Optional[Dict[str, Any]] = None,
165
+ headers: Optional[Dict[str, str]] = None,
166
+ ) -> httpx.Response:
167
+ """
168
+ Sends an asynchronous GET request.
169
+
170
+ Args:
171
+ path (str): API endpoint path.
172
+ params (Optional[Dict[str, Any]]): Query parameters.
173
+ headers (Optional[Dict[str, str]]): Request headers.
174
+
175
+ Returns:
176
+ httpx.Response: The HTTP response.
177
+ """
178
+ return await self.client.get(
179
+ self._build_url(path), params=params, headers=headers
180
+ )
181
+
182
+ async def post(
183
+ self,
184
+ path: str,
185
+ content: Optional[str] = None,
186
+ json: Optional[Any] = None,
187
+ headers: Optional[Dict[str, str]] = None,
188
+ ) -> httpx.Response:
189
+ """
190
+ Sends an asynchronous POST request.
191
+
192
+ Args:
193
+ path (str): API endpoint path.
194
+ content (Optional[str]): Raw string content to include in the request body.
195
+ json (Optional[Any]): JSON-encoded body data.
196
+ headers (Optional[Dict[str, str]]): Request headers.
197
+
198
+ Returns:
199
+ httpx.Response: The HTTP response.
200
+ """
201
+ return await self.client.post(
202
+ self._build_url(path), content=content, json=json, headers=headers
203
+ )
204
+
205
+ async def put(
206
+ self,
207
+ path: str,
208
+ content: Optional[bytes] = None,
209
+ params: Optional[Dict[str, Any]] = None,
210
+ json: Optional[Any] = None,
211
+ headers: Optional[Dict[str, str]] = None,
212
+ ) -> httpx.Response:
213
+ """
214
+ Sends an asynchronous PUT request.
215
+
216
+ Args:
217
+ path (str): API endpoint path.
218
+ content (Optional[bytes]): Raw bytes to include in the request body.
219
+ params (Optional[Dict[str, Any]]): Query parameters.
220
+ json (Optional[Any]): JSON-encoded body data.
221
+ headers (Optional[Dict[str, str]]): Request headers.
222
+
223
+ Returns:
224
+ httpx.Response: The HTTP response.
225
+ """
226
+ return await self.client.put(
227
+ self._build_url(path),
228
+ content=content,
229
+ json=json,
230
+ headers=headers,
231
+ params=params,
232
+ )
233
+
234
+ async def delete(
235
+ self,
236
+ path: str,
237
+ params: Optional[Dict[str, Any]] = None,
238
+ headers: Optional[Dict[str, str]] = None,
239
+ ) -> httpx.Response:
240
+ """
241
+ Sends an asynchronous DELETE request.
242
+
243
+ Args:
244
+ path (str): API endpoint path.
245
+ params (Optional[Dict[str, Any]]): Query parameters.
246
+ headers (Optional[Dict[str, str]]): Request headers.
247
+
248
+ Returns:
249
+ httpx.Response: The HTTP response.
250
+ """
251
+ return await self.client.delete(
252
+ self._build_url(path), params=params, headers=headers
253
+ )
@@ -1,7 +1,9 @@
1
+ from ._async_named_graph import AsyncNamedGraph
1
2
  from ._async_rdf4j_db import AsyncRdf4j
2
3
  from ._async_repository import AsyncRdf4JRepository
3
4
 
4
5
  __all__ = [
5
6
  "AsyncRdf4j",
6
7
  "AsyncRdf4JRepository",
8
+ "AsyncNamedGraph",
7
9
  ]
@@ -0,0 +1,75 @@
1
+ from typing import Iterable
2
+
3
+ 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.utils.const import Rdf4jContentType
7
+ from rdf4j_python.utils.helpers import serialize_statements
8
+
9
+
10
+ class AsyncNamedGraph:
11
+ """Asynchronous interface for operations on a specific RDF4J named graph."""
12
+
13
+ def __init__(self, client: AsyncApiClient, repository_id: str, graph_uri: str):
14
+ """Initializes the AsyncNamedGraph.
15
+
16
+ Args:
17
+ client (AsyncApiClient): The RDF4J HTTP client.
18
+ repository_id (str): The ID of the RDF4J repository.
19
+ graph_uri (str): The URI identifying the named graph.
20
+ """
21
+ self._client = client
22
+ self._repository_id = repository_id
23
+ self._graph_uri = graph_uri
24
+
25
+ async def get(self) -> RDF4JDataSet:
26
+ """Fetches all RDF statements from this named graph.
27
+
28
+ Returns:
29
+ str: RDF data serialized in the requested format.
30
+
31
+ Raises:
32
+ httpx.HTTPStatusError: If the request fails.
33
+ """
34
+ path = f"/repositories/{self._repository_id}/rdf-graphs/{self._graph_uri}"
35
+ headers = {"Accept": Rdf4jContentType.NQUADS}
36
+ response = await self._client.get(path, headers=headers)
37
+ response.raise_for_status()
38
+ return RDF4JDataSet.from_raw_text(response.text)
39
+
40
+ async def add(self, statements: Iterable[RDFStatement]):
41
+ """Adds RDF statements to this named graph.
42
+
43
+ Args:
44
+ statements (Iterable[RDFStatement]): RDF statements to add.
45
+
46
+ Raises:
47
+ httpx.HTTPStatusError: If the request fails.
48
+ """
49
+ path = f"/repositories/{self._repository_id}/rdf-graphs/{self._graph_uri}"
50
+ headers = {"Content-Type": Rdf4jContentType.NQUADS}
51
+ response = await self._client.post(
52
+ path, content=serialize_statements(statements), headers=headers
53
+ )
54
+ response.raise_for_status()
55
+
56
+ async def clear(self):
57
+ """Deletes all statements from this named graph.
58
+
59
+ Raises:
60
+ httpx.HTTPStatusError: If the request fails.
61
+ """
62
+ path = f"/repositories/{self._repository_id}/rdf-graphs/{self._graph_uri}"
63
+ response = await self._client.delete(path)
64
+ response.raise_for_status()
65
+
66
+ @property
67
+ def iri(self) -> IRI:
68
+ """Returns the IRI of the named graph.
69
+
70
+ Returns:
71
+ str: The graph IRI.
72
+ """
73
+ return IRI(
74
+ f"{self._client.get_base_url()}/repositories/{self._repository_id}/rdf-graphs/{self._graph_uri}"
75
+ )
@@ -1,43 +1,66 @@
1
- from typing import Union
2
-
3
1
  import httpx
4
2
  import rdflib
5
3
 
6
- from rdf4j_python import AsyncApiClient
4
+ from rdf4j_python._client import AsyncApiClient
7
5
  from rdf4j_python.exception.repo_exception import (
8
6
  RepositoryCreationException,
9
7
  RepositoryDeletionException,
10
8
  )
11
9
  from rdf4j_python.model._repository_info import RepositoryMetadata
10
+ from rdf4j_python.model.repository_config import RepositoryConfig
12
11
  from rdf4j_python.utils.const import Rdf4jContentType
13
12
 
14
13
  from ._async_repository import AsyncRdf4JRepository
15
14
 
16
15
 
17
16
  class AsyncRdf4j:
17
+ """Asynchronous entry point for interacting with an RDF4J server."""
18
+
18
19
  _client: AsyncApiClient
19
20
  _base_url: str
20
21
 
21
22
  def __init__(self, base_url: str):
23
+ """Initializes the RDF4J API client.
24
+
25
+ Args:
26
+ base_url (str): Base URL of the RDF4J server.
27
+ """
22
28
  self._base_url = base_url.rstrip("/")
23
29
 
24
30
  async def __aenter__(self):
31
+ """Enters the async context and initializes the HTTP client.
32
+
33
+ Returns:
34
+ AsyncRdf4j: The initialized RDF4J interface.
35
+ """
25
36
  self._client = await AsyncApiClient(base_url=self._base_url).__aenter__()
26
37
  return self
27
38
 
28
39
  async def __aexit__(self, exc_type, exc_value, traceback):
40
+ """Closes the HTTP client when exiting the async context."""
29
41
  await self._client.__aexit__(exc_type, exc_value, traceback)
30
42
 
31
43
  async def get_protocol_version(self) -> str:
44
+ """Fetches the RDF4J protocol version.
45
+
46
+ Returns:
47
+ str: The protocol version string.
48
+
49
+ Raises:
50
+ httpx.HTTPStatusError: If the request fails.
51
+ """
32
52
  response = await self._client.get("/protocol")
33
53
  response.raise_for_status()
34
54
  return response.text
35
55
 
36
56
  async def list_repositories(self) -> list[RepositoryMetadata]:
37
- """
38
- List all RDF4J repositories.
57
+ """Lists all available RDF4J repositories.
58
+
59
+ Returns:
60
+ list[RepositoryMetadata]: A list of repository metadata objects.
39
61
 
40
- :return: List of repository information.
62
+ Raises:
63
+ httpx.HTTPStatusError: If the request fails.
41
64
  """
42
65
  response = await self._client.get(
43
66
  "/repositories",
@@ -46,54 +69,57 @@ class AsyncRdf4j:
46
69
  result = rdflib.query.Result.parse(
47
70
  response, format=Rdf4jContentType.SPARQL_RESULTS_JSON
48
71
  )
49
-
50
72
  return [
51
73
  RepositoryMetadata.from_rdflib_binding(binding)
52
74
  for binding in result.bindings
53
75
  ]
54
76
 
55
77
  async def get_repository(self, repository_id: str) -> AsyncRdf4JRepository:
56
- """
57
- Get an AsyncRepository instance for the specified repository ID.
78
+ """Gets an interface to a specific RDF4J repository.
79
+
80
+ Args:
81
+ repository_id (str): The ID of the repository.
58
82
 
59
- :param repository_id: The ID of the repository.
60
- :return: An instance of AsyncRepository.
83
+ Returns:
84
+ AsyncRdf4JRepository: An async interface for the repository.
61
85
  """
62
86
  return AsyncRdf4JRepository(self._client, repository_id)
63
87
 
64
88
  async def create_repository(
65
89
  self,
66
- repository_id: str,
67
- rdf_config_data: str,
68
- content_type: Union[Rdf4jContentType, str] = Rdf4jContentType.TURTLE,
90
+ config: RepositoryConfig,
69
91
  ) -> AsyncRdf4JRepository:
70
- """
71
- Create a new RDF4J repository.
92
+ """Creates a new RDF4J repository using RDF configuration.
72
93
 
73
- :param repository_id: Repository ID to create.
74
- :param rdf_config_data: RDF config in Turtle, RDF/XML, etc.
75
- :param content_type: MIME type of RDF config.
76
- """
77
- path = f"/repositories/{repository_id}"
94
+ Args:
95
+ repository_id (str): The repository ID to create.
96
+ config (RepositoryConfig): RDF configuration.
78
97
 
79
- if isinstance(content_type, Rdf4jContentType):
80
- content_type = content_type.value
81
- headers = {"Content-Type": content_type}
98
+ Returns:
99
+ AsyncRdf4JRepository: An async interface to the newly created repository.
82
100
 
101
+ Raises:
102
+ RepositoryCreationException: If repository creation fails.
103
+ """
104
+ path = f"/repositories/{config.repo_id}"
105
+ headers = {"Content-Type": Rdf4jContentType.TURTLE}
83
106
  response: httpx.Response = await self._client.put(
84
- path, content=rdf_config_data, headers=headers
107
+ path, content=config.to_turtle(), headers=headers
85
108
  )
86
109
  if response.status_code != httpx.codes.NO_CONTENT:
87
110
  raise RepositoryCreationException(
88
111
  f"Repository creation failed: {response.status_code} - {response.text}"
89
112
  )
90
- return AsyncRdf4JRepository(self._client, repository_id)
113
+ return AsyncRdf4JRepository(self._client, config.repo_id)
91
114
 
92
115
  async def delete_repository(self, repository_id: str):
93
- """
94
- Delete an RDF4J repository and its data/config.
116
+ """Deletes a repository and all its data and configuration.
117
+
118
+ Args:
119
+ repository_id (str): The ID of the repository to delete.
95
120
 
96
- :param repository_id: The repository ID to delete.
121
+ Raises:
122
+ RepositoryDeletionException: If the deletion fails.
97
123
  """
98
124
  path = f"/repositories/{repository_id}"
99
125
  response = await self._client.delete(path)