Skip to content

Listing of collections and databases #23

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 1 addition & 9 deletions arangoasync/collection.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
__all__ = ["Collection", "CollectionType", "StandardCollection"]
__all__ = ["Collection", "StandardCollection"]


from enum import Enum
from typing import Generic, Optional, Tuple, TypeVar

from arangoasync.errno import HTTP_NOT_FOUND, HTTP_PRECONDITION_FAILED
Expand All @@ -21,13 +20,6 @@
V = TypeVar("V")


class CollectionType(Enum):
"""Collection types."""

DOCUMENT = 2
EDGE = 3


class Collection(Generic[T, U, V]):
"""Base class for collection API wrappers.

Expand Down
170 changes: 136 additions & 34 deletions arangoasync/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
]


from typing import Optional, Sequence, TypeVar, cast
from typing import List, Optional, Sequence, TypeVar, cast

from arangoasync.collection import CollectionType, StandardCollection
from arangoasync.collection import StandardCollection
from arangoasync.connection import Connection
from arangoasync.errno import HTTP_FORBIDDEN, HTTP_NOT_FOUND
from arangoasync.exceptions import (
Expand All @@ -22,8 +22,17 @@
from arangoasync.request import Method, Request
from arangoasync.response import Response
from arangoasync.serialization import Deserializer, Serializer
from arangoasync.typings import Json, Jsons, Params, Result
from arangoasync.wrapper import KeyOptions, ServerStatusInformation, User
from arangoasync.typings import (
CollectionInfo,
CollectionType,
Json,
Jsons,
KeyOptions,
Params,
Result,
ServerStatusInformation,
UserInfo,
)

T = TypeVar("T")
U = TypeVar("U")
Expand Down Expand Up @@ -69,7 +78,10 @@ async def status(self) -> Result[ServerStatusInformation]:

Raises:
ServerSatusError: If retrieval fails.
"""

References:
- `get-server-status-information <https://docs.arangodb.com/stable/develop/http-api/administration/#get-server-status-information>`__
""" # noqa: E501
request = Request(method=Method.GET, endpoint="/_admin/status")

def response_handler(resp: Response) -> ServerStatusInformation:
Expand All @@ -79,43 +91,80 @@ def response_handler(resp: Response) -> ServerStatusInformation:

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

async def databases(self) -> Result[List[str]]:
"""Return the names of all databases.

Note:
This method can only be executed in the **_system** database.

Returns:
list: Database names.

Raises:
DatabaseListError: If retrieval fails.

References:
- `list-all-databases <https://docs.arangodb.com/stable/develop/http-api/databases/#list-all-databases>`__
""" # noqa: E501
request = Request(method=Method.GET, endpoint="/_api/database")

def response_handler(resp: Response) -> List[str]:
if resp.is_success:
body = self.deserializer.loads(resp.raw_body)
return cast(List[str], body["result"])
msg: Optional[str] = None
if resp.status_code == HTTP_FORBIDDEN:
msg = "This request can only be executed in the _system database."
raise DatabaseListError(resp, request, msg)

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

async def has_database(self, name: str) -> Result[bool]:
"""Check if a database exists.

Note:
This method can only be executed from within the **_system** database.

Args:
name (str): Database name.

Returns:
bool: `True` if the database exists, `False` otherwise.

Raises:
DatabaseListError: If failed to retrieve the list of databases.
DatabaseListError: If retrieval fails.
"""
request = Request(method=Method.GET, endpoint="/_api/database")

def response_handler(resp: Response) -> bool:
if not resp.is_success:
raise DatabaseListError(resp, request)
body = self.deserializer.loads(resp.raw_body)
return name in body["result"]
if resp.is_success:
body = self.deserializer.loads(resp.raw_body)
return name in body["result"]
msg: Optional[str] = None
if resp.status_code == HTTP_FORBIDDEN:
msg = "This request can only be executed in the _system database."
raise DatabaseListError(resp, request, msg)

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

async def create_database(
self,
name: str,
users: Optional[Sequence[Json | User]] = None,
users: Optional[Sequence[Json | UserInfo]] = None,
replication_factor: Optional[int | str] = None,
write_concern: Optional[int] = None,
sharding: Optional[bool] = None,
) -> Result[bool]:
"""Create a new database.

Note:
This method can only be executed from within the **_system** database.

Args:
name (str): Database name.
users (list | None): Optional list of users with access to the new
database, where each user is of :class:`User
<arangoasync.wrapper.User>` type, or a dictionary with fields
<arangoasync.wrapper.UserInfo>` type, or a dictionary with fields
"username", "password" and "active". If not set, the default user
**root** will be used to ensure that the new database will be
accessible after it is created.
Expand All @@ -125,12 +174,12 @@ async def create_database(
(Enterprise Edition only), and 1, which disables replication. Used
for clusters only.
write_concern (int | None): Default write concern for collections created
in this database. Determines how many copies of each shard are required
to be in sync on different DB-Servers. If there are less than these many
copies in the cluster a shard will refuse to write. Writes to shards with
enough up-to-date copies will succeed at the same time, however. Value of
this parameter can not be larger than the value of **replication_factor**.
Used for clusters only.
in this database. Determines how many copies of each shard are required
to be in sync on different DB-Servers. If there are less than these many
copies in the cluster a shard will refuse to write. Writes to shards with
enough up-to-date copies will succeed at the same time, however. Value of
this parameter can not be larger than the value of **replication_factor**.
Used for clusters only.
sharding (str | None): Sharding method used for new collections in this
database. Allowed values are: "", "flexible" and "single". The first
two are equivalent. Used for clusters only.
Expand All @@ -140,7 +189,10 @@ async def create_database(

Raises:
DatabaseCreateError: If creation fails.
"""

References:
- `create-a-database <https://docs.arangodb.com/stable/develop/http-api/databases/#create-a-database>`__
""" # noqa: E501
data: Json = {"name": name}

options: Json = {}
Expand Down Expand Up @@ -173,7 +225,10 @@ async def create_database(
def response_handler(resp: Response) -> bool:
if resp.is_success:
return True
raise DatabaseCreateError(resp, request)
msg: Optional[str] = None
if resp.status_code == HTTP_FORBIDDEN:
msg = "This request can only be executed in the _system database."
raise DatabaseCreateError(resp, request, msg)

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

Expand All @@ -182,6 +237,9 @@ async def delete_database(
) -> Result[bool]:
"""Delete a database.

Note:
This method can only be executed from within the **_system** database.

Args:
name (str): Database name.
ignore_missing (bool): Do not raise an exception on missing database.
Expand All @@ -192,21 +250,21 @@ async def delete_database(

Raises:
DatabaseDeleteError: If deletion fails.
"""

References:
- `drop-a-database <https://docs.arangodb.com/stable/develop/http-api/databases/#drop-a-database>`__
""" # noqa: E501
request = Request(method=Method.DELETE, endpoint=f"/_api/database/{name}")

def response_handler(resp: Response) -> bool:
if resp.is_success:
return True
if resp.status_code == HTTP_NOT_FOUND and ignore_missing:
return False
msg: Optional[str] = None
if resp.status_code == HTTP_FORBIDDEN:
raise DatabaseDeleteError(
resp,
request,
"This request can only be executed in the _system database.",
)
raise DatabaseDeleteError(resp, request)
msg = "This request can only be executed in the _system database."
raise DatabaseDeleteError(resp, request, msg)

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

Expand Down Expand Up @@ -241,6 +299,40 @@ def collection(
self._executor, name, serializer, deserializer
)

async def collections(
self,
exclude_system: Optional[bool] = None,
) -> Result[List[CollectionInfo]]:
"""Returns basic information for all collections in the current database,
optionally excluding system collections.

Returns:
list: Collection names.

Raises:
CollectionListError: If retrieval fails.

References:
- `list-all-collections <https://docs.arangodb.com/stable/develop/http-api/collections/#list-all-collections>`__
""" # noqa: E501
params: Params = {}
if exclude_system is not None:
params["excludeSystem"] = exclude_system

request = Request(
method=Method.GET,
endpoint="/_api/collection",
params=params,
)

def response_handler(resp: Response) -> List[CollectionInfo]:
if not resp.is_success:
raise CollectionListError(resp, request)
body = self.deserializer.loads(resp.raw_body)
return [CollectionInfo(c) for c in body["result"]]

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

async def has_collection(self, name: str) -> Result[bool]:
"""Check if a collection exists in the database.

Expand All @@ -249,14 +341,18 @@ async def has_collection(self, name: str) -> Result[bool]:

Returns:
bool: True if the collection exists, False otherwise.

Raises:
CollectionListError: If retrieval fails.
"""
request = Request(method=Method.GET, endpoint="/_api/collection")
request = Request(method=Method.GET, endpoint=f"/_api/collection/{name}")

def response_handler(resp: Response) -> bool:
if not resp.is_success:
raise CollectionListError(resp, request)
body = self.deserializer.loads(resp.raw_body)
return any(c["name"] == name for c in body["result"])
if resp.is_success:
return True
if resp.status_code == HTTP_NOT_FOUND:
return False
raise CollectionListError(resp, request)

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

Expand Down Expand Up @@ -343,7 +439,10 @@ async def create_collection(
Raises:
ValueError: If parameters are invalid.
CollectionCreateError: If the operation fails.
"""

References:
- `create-a-collection <https://docs.arangodb.com/stable/develop/http-api/collections/#create-a-collection>`__
""" # noqa: E501
data: Json = {"name": name}
if col_type is not None:
data["type"] = col_type.value
Expand Down Expand Up @@ -430,7 +529,10 @@ async def delete_collection(

Raises:
CollectionDeleteError: If the operation fails.
"""

References:
- `drop-a-collection <https://docs.arangodb.com/stable/develop/http-api/collections/#drop-a-collection>`__
""" # noqa: E501
params: Params = {}
if is_system is not None:
params["isSystem"] = is_system
Expand Down
Loading
Loading