Skip to content

Commit 526b135

Browse files
committed
Vertex collection management
1 parent 6ea9259 commit 526b135

File tree

4 files changed

+144
-7
lines changed

4 files changed

+144
-7
lines changed

arangoasync/exceptions.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,10 @@ class GraphListError(ArangoServerError):
295295
"""Failed to retrieve graphs."""
296296

297297

298+
class GraphPropertiesError(ArangoServerError):
299+
"""Failed to retrieve graph properties."""
300+
301+
298302
class IndexCreateError(ArangoServerError):
299303
"""Failed to create collection index."""
300304

arangoasync/graph.py

Lines changed: 84 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
__all__ = ["Graph"]
22

33

4-
from typing import Generic, Optional, Sequence, TypeVar
4+
from typing import Generic, List, Optional, Sequence, TypeVar
55

66
from arangoasync.collection import EdgeCollection, VertexCollection
77
from arangoasync.exceptions import (
88
EdgeDefinitionCreateError,
9-
GraphListError,
9+
GraphPropertiesError,
1010
VertexCollectionCreateError,
11+
VertexCollectionDeleteError,
12+
VertexCollectionListError,
1113
)
1214
from arangoasync.executor import ApiExecutor
1315
from arangoasync.request import Method, Request
@@ -74,7 +76,7 @@ async def properties(self) -> Result[GraphProperties]:
7476
GraphProperties: Properties of the graph.
7577
7678
Raises:
77-
GraphListError: If the operation fails.
79+
GraphProperties: If the operation fails.
7880
7981
References:
8082
- `get-a-graph <https://docs.arangodb.com/stable/develop/http-api/graphs/named-graphs/#get-a-graph>`__
@@ -83,7 +85,7 @@ async def properties(self) -> Result[GraphProperties]:
8385

8486
def response_handler(resp: Response) -> GraphProperties:
8587
if not resp.is_success:
86-
raise GraphListError(resp, request)
88+
raise GraphPropertiesError(resp, request)
8789
body = self.deserializer.loads(resp.raw_body)
8890
return GraphProperties(body["graph"])
8991

@@ -106,6 +108,56 @@ def vertex_collection(self, name: str) -> VertexCollection[T, U, V]:
106108
doc_deserializer=self._doc_deserializer,
107109
)
108110

111+
async def vertex_collections(self) -> Result[List[str]]:
112+
"""Get the names of all vertex collections in the graph.
113+
114+
Returns:
115+
list: List of vertex collection names.
116+
117+
Raises:
118+
VertexCollectionListError: If the operation fails.
119+
120+
References:
121+
- `list-vertex-collections <https://docs.arangodb.com/stable/develop/http-api/graphs/named-graphs/#list-vertex-collections>`__
122+
""" # noqa: E501
123+
request = Request(
124+
method=Method.GET,
125+
endpoint=f"/_api/gharial/{self._name}/vertex",
126+
)
127+
128+
def response_handler(resp: Response) -> List[str]:
129+
if not resp.is_success:
130+
raise VertexCollectionListError(resp, request)
131+
body = self.deserializer.loads(resp.raw_body)
132+
return list(sorted(set(body["collections"])))
133+
134+
return await self._executor.execute(request, response_handler)
135+
136+
async def has_vertex_collection(self, name: str) -> Result[bool]:
137+
"""Check if the graph has the given vertex collection.
138+
139+
Args:
140+
name (str): Vertex collection mame.
141+
142+
Returns:
143+
bool: `True` if the graph has the vertex collection, `False` otherwise.
144+
145+
Raises:
146+
VertexCollectionListError: If the operation fails.
147+
"""
148+
request = Request(
149+
method=Method.GET,
150+
endpoint=f"/_api/gharial/{self._name}/vertex",
151+
)
152+
153+
def response_handler(resp: Response) -> bool:
154+
if not resp.is_success:
155+
raise VertexCollectionListError(resp, request)
156+
body = self.deserializer.loads(resp.raw_body)
157+
return name in body["collections"]
158+
159+
return await self._executor.execute(request, response_handler)
160+
109161
async def create_vertex_collection(
110162
self,
111163
name: str,
@@ -148,6 +200,34 @@ def response_handler(resp: Response) -> VertexCollection[T, U, V]:
148200

149201
return await self._executor.execute(request, response_handler)
150202

203+
async def delete_vertex_collection(self, name: str, purge: bool = False) -> None:
204+
"""Remove a vertex collection from the graph.
205+
206+
Args:
207+
name (str): Vertex collection name.
208+
purge (bool): If set to `True`, the vertex collection is not just deleted
209+
from the graph but also from the database completely. Note that you
210+
cannot remove vertex collections that are used in one of the edge
211+
definitions of the graph.
212+
213+
Raises:
214+
VertexCollectionDeleteError: If the operation fails.
215+
216+
References:
217+
- `remove-a-vertex-collection <https://docs.arangodb.com/stable/develop/http-api/graphs/named-graphs/#remove-a-vertex-collection>`__
218+
""" # noqa: E501
219+
request = Request(
220+
method=Method.DELETE,
221+
endpoint=f"/_api/gharial/{self._name}/vertex/{name}",
222+
params={"dropCollection": purge},
223+
)
224+
225+
def response_handler(resp: Response) -> None:
226+
if not resp.is_success:
227+
raise VertexCollectionDeleteError(resp, request)
228+
229+
await self._executor.execute(request, response_handler)
230+
151231
def edge_collection(self, name: str) -> EdgeCollection[T, U, V]:
152232
"""Returns the edge collection API wrapper.
153233

tests/conftest.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@
88
from arangoasync.auth import Auth, JwtToken
99
from arangoasync.client import ArangoClient
1010
from arangoasync.typings import UserInfo
11-
from tests.helpers import generate_col_name, generate_db_name, generate_username
11+
from tests.helpers import (
12+
generate_col_name,
13+
generate_db_name,
14+
generate_graph_name,
15+
generate_username,
16+
)
1217

1318

1419
@dataclass
@@ -19,6 +24,7 @@ class GlobalData:
1924
secret: str = None
2025
token: JwtToken = None
2126
sys_db_name: str = "_system"
27+
graph_name: str = "test_graph"
2228
username: str = generate_username()
2329
cluster: bool = False
2430
enterprise: bool = False
@@ -64,6 +70,7 @@ def pytest_configure(config):
6470
global_data.token = JwtToken.generate_token(global_data.secret)
6571
global_data.cluster = config.getoption("cluster")
6672
global_data.enterprise = config.getoption("enterprise")
73+
global_data.graph_name = generate_graph_name()
6774

6875
async def get_db_version():
6976
async with ArangoClient(hosts=global_data.url) as client:
@@ -215,6 +222,11 @@ async def bad_db(arango_client):
215222
)
216223

217224

225+
@pytest_asyncio.fixture
226+
def bad_graph(bad_db):
227+
return bad_db.graph(global_data.graph_name)
228+
229+
218230
@pytest_asyncio.fixture
219231
async def doc_col(db):
220232
col_name = generate_col_name()

tests/test_graph.py

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
import pytest
22

3-
from arangoasync.exceptions import GraphCreateError, GraphDeleteError, GraphListError
3+
from arangoasync.exceptions import (
4+
GraphCreateError,
5+
GraphDeleteError,
6+
GraphListError,
7+
GraphPropertiesError,
8+
VertexCollectionCreateError,
9+
VertexCollectionDeleteError,
10+
VertexCollectionListError,
11+
)
412
from arangoasync.typings import GraphOptions
513
from tests.helpers import generate_col_name, generate_graph_name
614

@@ -41,13 +49,16 @@ async def test_graph_basic(db, bad_db):
4149
await bad_db.delete_graph(graph1_name)
4250

4351

44-
async def test_graph_properties(db, cluster, enterprise):
52+
async def test_graph_properties(db, bad_graph, cluster, enterprise):
4553
# Create a graph
4654
name = generate_graph_name()
4755
is_smart = cluster and enterprise
4856
options = GraphOptions(number_of_shards=3)
4957
graph = await db.create_graph(name, is_smart=is_smart, options=options)
5058

59+
with pytest.raises(GraphPropertiesError):
60+
await bad_graph.properties()
61+
5162
# Create first vertex collection
5263
vcol_name = generate_col_name()
5364
vcol = await graph.create_vertex_collection(vcol_name)
@@ -85,3 +96,33 @@ async def test_graph_properties(db, cluster, enterprise):
8596
assert properties.edge_definitions[0]["from"][0] == vcol_name
8697
assert len(properties.edge_definitions[0]["to"]) == 1
8798
assert properties.edge_definitions[0]["to"][0] == vcol2_name
99+
100+
101+
async def test_vertex_collections(db, bad_graph):
102+
# Test errors
103+
with pytest.raises(VertexCollectionCreateError):
104+
await bad_graph.create_vertex_collection("bad_col")
105+
with pytest.raises(VertexCollectionListError):
106+
await bad_graph.vertex_collections()
107+
with pytest.raises(VertexCollectionListError):
108+
await bad_graph.has_vertex_collection("bad_col")
109+
with pytest.raises(VertexCollectionDeleteError):
110+
await bad_graph.delete_vertex_collection("bad_col")
111+
112+
# Create graph
113+
graph = await db.create_graph(generate_graph_name())
114+
115+
# Create vertex collections
116+
names = [generate_col_name() for _ in range(3)]
117+
cols = [await graph.create_vertex_collection(name) for name in names]
118+
119+
# List vertex collection
120+
col_list = await graph.vertex_collections()
121+
assert len(col_list) == 3
122+
for c in cols:
123+
assert c.name in col_list
124+
assert await graph.has_vertex_collection(c.name)
125+
126+
# Delete collections
127+
await graph.delete_vertex_collection(names[0])
128+
assert await graph.has_vertex_collection(names[0]) is False

0 commit comments

Comments
 (0)