apexdevkit 1.9.1__tar.gz → 1.9.3__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.
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/PKG-INFO +2 -1
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/http/httpx.py +2 -2
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/repository/connector.py +13 -1
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/repository/database.py +53 -1
- apexdevkit-1.9.3/apexdevkit/repository/mongo.py +79 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/pyproject.toml +2 -1
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/LICENSE +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/README.md +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/__init__.py +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/annotation/__init__.py +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/annotation/deprecate.py +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/error.py +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/fastapi/__init__.py +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/fastapi/builder.py +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/fastapi/dependable.py +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/fastapi/docs.py +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/fastapi/resource.py +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/fastapi/response.py +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/fastapi/router.py +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/fastapi/schema.py +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/fastapi/service.py +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/formatter.py +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/http/__init__.py +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/http/fake.py +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/http/fluent.py +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/http/json.py +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/http/url.py +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/py.typed +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/repository/__init__.py +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/repository/base.py +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/repository/in_memory.py +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/repository/interface.py +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/repository/sqlite.py +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/testing/__init__.py +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/testing/database.py +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/testing/fake.py +0 -0
- {apexdevkit-1.9.1 → apexdevkit-1.9.3}/apexdevkit/testing/rest.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: apexdevkit
|
|
3
|
-
Version: 1.9.
|
|
3
|
+
Version: 1.9.3
|
|
4
4
|
Summary: Apex Development Tools for python.
|
|
5
5
|
Author: Apex Dev
|
|
6
6
|
Author-email: dev@apex.ge
|
|
@@ -10,6 +10,7 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
10
10
|
Classifier: Programming Language :: Python :: 3.12
|
|
11
11
|
Requires-Dist: fastapi
|
|
12
12
|
Requires-Dist: httpx
|
|
13
|
+
Requires-Dist: pymongo
|
|
13
14
|
Description-Content-Type: text/markdown
|
|
14
15
|
|
|
15
16
|
# apexdevkit
|
|
@@ -65,7 +65,7 @@ class HttpxConfig(Mapping[str, Any]):
|
|
|
65
65
|
endpoint: str = ""
|
|
66
66
|
headers: JsonDict = field(default_factory=JsonDict)
|
|
67
67
|
params: JsonDict = field(default_factory=JsonDict)
|
|
68
|
-
json: JsonDict =
|
|
68
|
+
json: JsonDict | None = None
|
|
69
69
|
|
|
70
70
|
def with_endpoint(self, endpoint: str) -> HttpxConfig:
|
|
71
71
|
return HttpxConfig(
|
|
@@ -104,7 +104,7 @@ class HttpxConfig(Mapping[str, Any]):
|
|
|
104
104
|
"url": self.endpoint,
|
|
105
105
|
"headers": dict(self.headers),
|
|
106
106
|
"params": dict(self.params),
|
|
107
|
-
"json": dict(self.json),
|
|
107
|
+
"json": dict(self.json) if self.json is not None else None,
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
def __len__(self) -> int:
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import sqlite3
|
|
2
2
|
from dataclasses import dataclass
|
|
3
3
|
from functools import cached_property
|
|
4
|
-
from typing import ContextManager
|
|
4
|
+
from typing import Any, ContextManager
|
|
5
|
+
|
|
6
|
+
from pymongo import MongoClient
|
|
5
7
|
|
|
6
8
|
from apexdevkit.repository import Connection
|
|
7
9
|
|
|
@@ -30,3 +32,13 @@ class SqliteInMemoryConnector:
|
|
|
30
32
|
connection.row_factory = sqlite3.Row
|
|
31
33
|
|
|
32
34
|
return connection
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass
|
|
38
|
+
class MongoDBConnector:
|
|
39
|
+
dsn: str
|
|
40
|
+
|
|
41
|
+
def connect(self) -> ContextManager[MongoClient[Any]]:
|
|
42
|
+
connection: MongoClient[Any] = MongoClient(self.dsn)
|
|
43
|
+
|
|
44
|
+
return connection
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from dataclasses import dataclass, field
|
|
4
|
-
from typing import Any, ContextManager, Iterable, Protocol, Self
|
|
4
|
+
from typing import Any, ContextManager, Dict, Iterable, Iterator, Protocol, Self
|
|
5
|
+
|
|
6
|
+
from pymongo import MongoClient
|
|
7
|
+
from pymongo.collection import Collection, ReturnDocument
|
|
8
|
+
from pymongo.results import DeleteResult, InsertOneResult
|
|
5
9
|
|
|
6
10
|
_RawData = dict[str, Any]
|
|
7
11
|
|
|
@@ -42,11 +46,59 @@ class Database:
|
|
|
42
46
|
return [dict(raw or {}) for raw in raw]
|
|
43
47
|
|
|
44
48
|
|
|
49
|
+
@dataclass
|
|
50
|
+
class MongoDatabase:
|
|
51
|
+
connector: MongoConnector
|
|
52
|
+
database_name: str
|
|
53
|
+
collection_name: str
|
|
54
|
+
|
|
55
|
+
def collection(self, client: MongoClient[Any]) -> Collection[Any]:
|
|
56
|
+
return client[self.database_name][self.collection_name]
|
|
57
|
+
|
|
58
|
+
def __iter__(self) -> Iterator[Any]:
|
|
59
|
+
with self.connector.connect() as client:
|
|
60
|
+
for raw in self.collection(client).find():
|
|
61
|
+
yield raw
|
|
62
|
+
|
|
63
|
+
def __len__(self) -> int:
|
|
64
|
+
with self.connector.connect() as client:
|
|
65
|
+
return self.collection(client).count_documents({})
|
|
66
|
+
|
|
67
|
+
def create(self, item: Dict[str, Any]) -> InsertOneResult:
|
|
68
|
+
with self.connector.connect() as client:
|
|
69
|
+
return self.collection(client).insert_one(item)
|
|
70
|
+
|
|
71
|
+
def read(self, item_id: str) -> Dict[str, Any] | None:
|
|
72
|
+
with self.connector.connect() as client:
|
|
73
|
+
return self.collection(client).find_one({"id": item_id})
|
|
74
|
+
|
|
75
|
+
def update(self, item_id: str, item: Dict[str, Any]) -> Any:
|
|
76
|
+
with self.connector.connect() as client:
|
|
77
|
+
return self.collection(client).find_one_and_update(
|
|
78
|
+
{"id": item_id},
|
|
79
|
+
{"$set": item},
|
|
80
|
+
return_document=ReturnDocument.AFTER,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
def delete(self, item_id: str) -> DeleteResult:
|
|
84
|
+
with self.connector.connect() as client:
|
|
85
|
+
return self.collection(client).delete_one({"id": item_id})
|
|
86
|
+
|
|
87
|
+
def delete_all(self) -> DeleteResult:
|
|
88
|
+
with self.connector.connect() as client:
|
|
89
|
+
return self.collection(client).delete_many({})
|
|
90
|
+
|
|
91
|
+
|
|
45
92
|
class Connector(Protocol): # pragma: no cover
|
|
46
93
|
def connect(self) -> ContextManager[Connection]:
|
|
47
94
|
pass
|
|
48
95
|
|
|
49
96
|
|
|
97
|
+
class MongoConnector(Protocol): # pragma: no cover
|
|
98
|
+
def connect(self) -> ContextManager[MongoClient[Any]]:
|
|
99
|
+
pass
|
|
100
|
+
|
|
101
|
+
|
|
50
102
|
class Connection(Protocol): # pragma: no cover
|
|
51
103
|
def cursor(self) -> Cursor:
|
|
52
104
|
pass
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any, Dict, Generic, Iterator, Protocol, TypeVar
|
|
5
|
+
|
|
6
|
+
from apexdevkit.error import DoesNotExistError, ExistsError
|
|
7
|
+
from apexdevkit.repository.database import MongoDatabase
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class _Item(Protocol): # pragma: no cover
|
|
11
|
+
@property
|
|
12
|
+
def id(self) -> Any:
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
ItemT = TypeVar("ItemT", bound=_Item)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass
|
|
20
|
+
class MongoDBRepository(Generic[ItemT]):
|
|
21
|
+
database: MongoDatabase
|
|
22
|
+
table: MongoTable[ItemT]
|
|
23
|
+
|
|
24
|
+
def __iter__(self) -> Iterator[ItemT]:
|
|
25
|
+
for raw in self.database:
|
|
26
|
+
yield self.table.load(raw)
|
|
27
|
+
|
|
28
|
+
def __len__(self) -> int:
|
|
29
|
+
return len(self.database)
|
|
30
|
+
|
|
31
|
+
def create(self, item: ItemT) -> ItemT:
|
|
32
|
+
try:
|
|
33
|
+
self.read(item.id)
|
|
34
|
+
raise ExistsError(item).with_duplicate(
|
|
35
|
+
lambda i: f"_Item with id<{i.id}> already exists."
|
|
36
|
+
)
|
|
37
|
+
except DoesNotExistError:
|
|
38
|
+
self.database.create(self.table.to_dict(item))
|
|
39
|
+
return item
|
|
40
|
+
|
|
41
|
+
def create_many(self, items: list[ItemT]) -> list[ItemT]:
|
|
42
|
+
return [self.create(item) for item in items]
|
|
43
|
+
|
|
44
|
+
def read(self, item_id: str) -> ItemT:
|
|
45
|
+
raw = self.database.read(item_id)
|
|
46
|
+
|
|
47
|
+
if not raw:
|
|
48
|
+
raise DoesNotExistError(item_id)
|
|
49
|
+
|
|
50
|
+
return self.table.load(raw)
|
|
51
|
+
|
|
52
|
+
def update(self, item: ItemT) -> None:
|
|
53
|
+
self.database.update(
|
|
54
|
+
self.table.get_id(item),
|
|
55
|
+
self.table.to_dict(item),
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
def update_many(self, items: list[ItemT]) -> None:
|
|
59
|
+
for item in items:
|
|
60
|
+
self.update(item)
|
|
61
|
+
|
|
62
|
+
def delete(self, item_id: str) -> None:
|
|
63
|
+
result = self.database.delete(item_id)
|
|
64
|
+
if result.deleted_count == 0:
|
|
65
|
+
raise DoesNotExistError(item_id)
|
|
66
|
+
|
|
67
|
+
def delete_all(self) -> None:
|
|
68
|
+
self.database.delete_all()
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class MongoTable(Generic[ItemT]):
|
|
72
|
+
def to_dict(self, item: ItemT) -> Dict[str, Any]:
|
|
73
|
+
raise NotImplementedError("Not implemented")
|
|
74
|
+
|
|
75
|
+
def load(self, data: Dict[str, Any]) -> ItemT:
|
|
76
|
+
raise NotImplementedError("Not implemented")
|
|
77
|
+
|
|
78
|
+
def get_id(self, item: ItemT) -> str:
|
|
79
|
+
raise NotImplementedError("Not implemented")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "apexdevkit"
|
|
3
|
-
version = "1.9.
|
|
3
|
+
version = "1.9.3"
|
|
4
4
|
description = "Apex Development Tools for python."
|
|
5
5
|
authors = ["Apex Dev <dev@apex.ge>"]
|
|
6
6
|
readme = "README.md"
|
|
@@ -9,6 +9,7 @@ readme = "README.md"
|
|
|
9
9
|
python = "^3.11"
|
|
10
10
|
httpx = "*"
|
|
11
11
|
fastapi = "*"
|
|
12
|
+
pymongo = "*"
|
|
12
13
|
|
|
13
14
|
[tool.poetry.group.dev.dependencies]
|
|
14
15
|
pytest = "*"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|