Skip to content

Commit dbbb6c9

Browse files
authored
Merge pull request #1 from moevm/dev
merge dev into main
2 parents 1177999 + 0bb91a9 commit dbbb6c9

File tree

6 files changed

+359
-0
lines changed

6 files changed

+359
-0
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.env
2+
.idea
3+
.github
4+
.venv
5+
__pycache__

docker-compose.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
version: '3.8'
2+
3+
services:
4+
arangodb:
5+
image: arangodb:latest
6+
environment:
7+
- ARANGO_ROOT_PASSWORD=${ARANGO_PASS}
8+
ports:
9+
- "${ARANGO_PORT}:8529"
10+
volumes:
11+
- arango_data:/var/lib/arangodb3
12+
- arango_apps:/var/lib/arangodb3-apps
13+
14+
volumes:
15+
arango_data:
16+
arango_apps:

hello_world/arangodb_client.py

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
import os
2+
import sys
3+
4+
from dotenv import load_dotenv
5+
6+
from aioarango import ArangoClient
7+
import aioarango.exceptions
8+
from aioarango.database import StandardDatabase
9+
10+
from typing import Optional, Any
11+
from aioarango.typings import Json, Jsons
12+
13+
14+
dotenv_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '.env')
15+
if os.path.exists(dotenv_path):
16+
load_dotenv(dotenv_path)
17+
18+
ARANGO_HOST = os.getenv("ARANGO_HOST")
19+
ARANGO_PORT = os.getenv("ARANGO_PORT")
20+
ARANGO_DB = os.getenv("ARANGO_DB")
21+
ARANGO_USER = os.getenv("ARANGO_USER")
22+
ARANGO_PASS = os.getenv("ARANGO_PASS")
23+
24+
class ArangoDatabaseClient:
25+
def __init__(self):
26+
self.client = ArangoClient(hosts=f"http://{ARANGO_HOST}:{ARANGO_PORT}")
27+
self.db: StandardDatabase = None
28+
29+
async def connect(self) -> None:
30+
try:
31+
system_db = await self.client.db("_system", username=ARANGO_USER, password=ARANGO_PASS)
32+
except aioarango.exceptions.ServerConnectionError as e:
33+
sys.exit(1)
34+
35+
# Создаем базу, если её нет
36+
if not await system_db.has_database(ARANGO_DB):
37+
await system_db.create_database(ARANGO_DB)
38+
print(f"База '{ARANGO_DB}' успешно создана.")
39+
else:
40+
print(f"База '{ARANGO_DB}' уже существует.")
41+
42+
# Подключаемся к базе
43+
try:
44+
self.db = await self.client.db(ARANGO_DB, username=ARANGO_USER, password=ARANGO_PASS, verify=True)
45+
except aioarango.exceptions.ServerConnectionError as e:
46+
sys.exit(1)
47+
48+
print(f"Подключение к базе '{ARANGO_DB}' прошло успешно.")
49+
50+
async def close(self):
51+
await self.client.close()
52+
print("Подключение к базе данных закрыто.")
53+
54+
async def has_collection(self, collection_name: str) -> bool:
55+
return await self.db.has_collection(collection_name)
56+
57+
async def create_collection(self, collection_name: str) -> bool:
58+
if await self.db.has_collection(collection_name):
59+
print(f"Коллекция '{collection_name}' уже существует.")
60+
return False
61+
62+
await self.db.create_collection(collection_name)
63+
print(f"Коллекция '{collection_name}' успешна создана.")
64+
return True
65+
66+
async def delete_collection(self, collection_name: str) -> bool:
67+
if not await self.db.has_collection(collection_name):
68+
print(f"Коллекции '{collection_name}' не существует.")
69+
return False
70+
71+
await self.db.delete_collection(collection_name)
72+
print(f"Коллекция '{collection_name}' успешна удалена.")
73+
return True
74+
75+
async def get_all_documents_from_collection(self, collection_name: str) -> Optional[Jsons]:
76+
if not await self.has_collection(collection_name):
77+
print(f"Коллекции {collection_name} не существует.")
78+
return None
79+
80+
collection = self.db.collection(collection_name)
81+
82+
cursor = await collection.all()
83+
84+
documents = [document async for document in cursor]
85+
86+
return documents
87+
88+
async def insert_documents_to_collection(self, collection_name: str, documents: Jsons) -> bool:
89+
if not await self.has_collection(collection_name):
90+
print(f"Коллекции {collection_name} не существует.")
91+
return False
92+
93+
collection = self.db.collection(collection_name)
94+
95+
try:
96+
await collection.insert_many(documents, overwrite=True, silent=True)
97+
except aioarango.exceptions.DocumentInsertError as e:
98+
print(f"Не удалось провести вставку в коллекцию {collection_name}:\n{e}")
99+
return False
100+
101+
print(f"Запись в {collection_name} прошла успешно.")
102+
return True
103+
104+
async def get_document_by_key(self, collection_name: str, document_key: str) -> Optional[Json]:
105+
if not await self.has_collection(collection_name):
106+
print(f"Коллекции {collection_name} не существует.")
107+
return None
108+
109+
collection = self.db.collection(collection_name)
110+
111+
return await collection.get(document_key)
112+
113+
async def update_document_by_key(self, collection_name: str, document_key: str, new_document: Json) -> bool:
114+
if not await self.has_collection(collection_name):
115+
print(f"Коллекции {collection_name} не существует.")
116+
return False
117+
118+
collection = self.db.collection(collection_name)
119+
120+
new_document.update({"_key": document_key})
121+
122+
try:
123+
await collection.update(new_document, silent=True)
124+
except aioarango.exceptions.DocumentUpdateError as e:
125+
print(f"Не удалось провести обновление документа {document_key} в коллекции {collection_name}:\n{e}")
126+
return False
127+
128+
print(f"Обновление документа {document_key} в {collection_name} прошло успешно.")
129+
return True
130+
131+
async def delete_document_by_key(self, collection_name: str, document_key: str) -> bool:
132+
if not await self.has_collection(collection_name):
133+
print(f"Коллекции {collection_name} не существует.")
134+
return False
135+
136+
collection = self.db.collection(collection_name)
137+
138+
try:
139+
await collection.delete(document_key, silent=True)
140+
except aioarango.exceptions.DocumentDeleteError as e:
141+
print(f"Не удалось провести удаление документа {document_key} из коллекции {collection_name}:\n{e}")
142+
return False
143+
144+
print(f"Удаление документа {document_key} из {collection_name} прошло успешно.")
145+
return True
146+
147+
async def find_documents_by_fields(self, collection_name: str, filter: dict[str, Any]) -> Optional[Jsons]:
148+
if not await self.has_collection(collection_name):
149+
print(f"Коллекции {collection_name} не существует.")
150+
return None
151+
152+
collection = self.db.collection(collection_name)
153+
154+
cursor = await collection.find(filter)
155+
156+
return [document async for document in cursor]
157+
158+
async def find_documents_keys_by_fields(self, collection_name: str, filter: dict) -> Optional[list[str]]:
159+
documents = await self.find_documents_by_fields(collection_name, filter)
160+
161+
if documents is None:
162+
return None
163+
164+
return [document["_key"] for document in documents]

hello_world/requirements.txt

1.21 KB
Binary file not shown.
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
import os
2+
from dotenv import load_dotenv
3+
4+
import pytest_asyncio
5+
import pytest
6+
7+
dotenv_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '.env')
8+
if os.path.exists(dotenv_path):
9+
load_dotenv(dotenv_path)
10+
11+
from arangodb_client import ArangoDatabaseClient
12+
13+
@pytest_asyncio.fixture(scope="function")
14+
async def db_client():
15+
client = ArangoDatabaseClient()
16+
await client.connect()
17+
yield client
18+
await client.close()
19+
20+
collection_name = "test_collection"
21+
22+
@pytest.mark.asyncio
23+
async def test_create_non_existing_collection(db_client):
24+
if await db_client.has_collection(collection_name):
25+
await db_client.delete_collection(collection_name)
26+
27+
assert await db_client.has_collection(collection_name) is False
28+
29+
creation_result = await db_client.create_collection(collection_name)
30+
assert creation_result is True
31+
32+
assert await db_client.has_collection(collection_name) is True
33+
34+
@pytest.mark.asyncio
35+
async def test_create_existing_collection(db_client):
36+
if not await db_client.has_collection(collection_name):
37+
await db_client.create_collection(collection_name)
38+
39+
assert await db_client.has_collection(collection_name) is True
40+
41+
creation_result = await db_client.create_collection(collection_name)
42+
assert creation_result is False
43+
44+
@pytest.mark.asyncio
45+
async def test_insert_documents_to_existing_collection(db_client):
46+
if not await db_client.has_collection(collection_name):
47+
await db_client.create_collection(collection_name)
48+
49+
assert await db_client.has_collection(collection_name) is True
50+
51+
documents = [{"_key": "1", "name": "Andrew", "age": 30},
52+
{"_key": "2", "name": "Anton", "age": 20},
53+
{"_key": "3", "name": "Egor", "age": 21}]
54+
55+
insertion_result = await db_client.insert_documents_to_collection(collection_name, documents)
56+
assert insertion_result is True
57+
58+
result_documents = await db_client.get_all_documents_from_collection(collection_name)
59+
for i, result_document in enumerate(result_documents):
60+
assert (result_document["_key"] == documents[i]["_key"]
61+
and result_document["name"] == documents[i]["name"]
62+
and result_document["age"] == documents[i]["age"])
63+
64+
@pytest.mark.asyncio
65+
async def test_insert_documents_to_non_existing_collection(db_client):
66+
non_existing_collection_name = "non_existing_collection"
67+
68+
if await db_client.has_collection(non_existing_collection_name):
69+
await db_client.delete_collection(non_existing_collection_name)
70+
71+
assert await db_client.has_collection(non_existing_collection_name) is False
72+
73+
documents = [{"_key": "7", "name": "Gleb", "age": 15},
74+
{"_key": "8", "name": "Max", "age": 44},
75+
{"_key": "9", "name": "Ilya", "age": 19}]
76+
77+
insertion_result = await db_client.insert_documents_to_collection(non_existing_collection_name, documents)
78+
assert insertion_result is False
79+
80+
result_documents = await db_client.get_all_documents_from_collection(non_existing_collection_name)
81+
assert result_documents is None
82+
83+
@pytest.mark.asyncio
84+
async def test_update_document_with_known_key(db_client):
85+
if not await db_client.has_collection(collection_name):
86+
await db_client.create_collection(collection_name)
87+
88+
assert await db_client.has_collection(collection_name) is True
89+
90+
document = {"_key": "123", "name": "Aleksandr", "age": 20}
91+
92+
updated_data = {"name": "Kirill"}
93+
94+
insertion_result = await db_client.insert_documents_to_collection(collection_name, [document])
95+
assert insertion_result is True
96+
97+
update_result = await db_client.update_document_by_key(collection_name, "123", updated_data)
98+
assert update_result is True
99+
100+
result_document = await db_client.get_document_by_key(collection_name, "123")
101+
assert result_document["name"] == "Kirill"
102+
103+
@pytest.mark.asyncio
104+
async def test_delete_existing_document(db_client):
105+
if not await db_client.has_collection(collection_name):
106+
await db_client.create_collection(collection_name)
107+
108+
assert await db_client.has_collection(collection_name) is True
109+
110+
document = {"_key": "123", "name": "Aleksandr", "age": 20}
111+
112+
insertion_result = await db_client.insert_documents_to_collection(collection_name, [document])
113+
assert insertion_result is True
114+
115+
assert await db_client.get_document_by_key(collection_name, "123") is not None
116+
117+
deletion_result = await db_client.delete_document_by_key(collection_name, "123")
118+
assert deletion_result is True
119+
120+
result_document = await db_client.get_document_by_key(collection_name, "123")
121+
assert result_document is None
122+
123+
@pytest.mark.asyncio
124+
async def test_delete_non_existing_document(db_client):
125+
if not await db_client.has_collection(collection_name):
126+
await db_client.create_collection(collection_name)
127+
128+
assert await db_client.has_collection(collection_name) is True
129+
130+
if await db_client.get_document_by_key(collection_name, "doc_key") is not None:
131+
await db_client.delete_document_by_key(collection_name, "doc_key")
132+
133+
assert await db_client.get_document_by_key(collection_name, "doc_key") is None
134+
135+
deletion_result = await db_client.delete_document_by_key(collection_name, "doc_key")
136+
assert deletion_result is False
137+
138+
@pytest.mark.asyncio
139+
async def test_find_existing_document(db_client):
140+
if not await db_client.has_collection(collection_name):
141+
await db_client.create_collection(collection_name)
142+
143+
assert await db_client.has_collection(collection_name) is True
144+
145+
document = {"_key": "111", "name": "Andrew", "age": 30}
146+
document_key = "111"
147+
148+
if await db_client.get_document_by_key(collection_name, document_key) is None:
149+
await db_client.insert_documents_to_collection(collection_name, [document])
150+
151+
assert await db_client.get_document_by_key(collection_name, document_key) is not None
152+
153+
search_result = await db_client.find_documents_by_fields(collection_name, {"name": "Andrew", "age": 30})
154+
assert search_result is not None and len(search_result) > 0
155+
156+
@pytest.mark.asyncio
157+
async def test_find_non_existing_document(db_client):
158+
if not await db_client.has_collection(collection_name):
159+
await db_client.create_collection(collection_name)
160+
161+
assert await db_client.has_collection(collection_name) is True
162+
163+
document = { "_key": "cghgvjb", "name": "Aleksey", "age": 30 }
164+
document_key = "cghgvjb"
165+
166+
if await db_client.get_document_by_key(collection_name, document_key) is not None:
167+
await db_client.delete_document_by_key(collection_name, document_key)
168+
169+
assert await db_client.get_document_by_key(collection_name, document_key) is None
170+
171+
search_result = await db_client.find_documents_by_fields(collection_name, {"name": "Aleksey", "age": 30})
172+
assert search_result is not None and len(search_result) == 0

pytest.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[pytest]
2+
async_mode = auto

0 commit comments

Comments
 (0)