apexdevkit 1.9.5__tar.gz → 1.9.7__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 (39) hide show
  1. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/PKG-INFO +1 -1
  2. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/fastapi/schema.py +13 -28
  3. apexdevkit-1.9.7/apexdevkit/fluent.py +40 -0
  4. apexdevkit-1.9.7/apexdevkit/http/json.py +5 -0
  5. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/repository/mongo.py +29 -53
  6. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/testing/rest.py +2 -16
  7. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/pyproject.toml +1 -1
  8. apexdevkit-1.9.5/apexdevkit/http/json.py +0 -38
  9. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/LICENSE +0 -0
  10. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/README.md +0 -0
  11. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/__init__.py +0 -0
  12. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/annotation/__init__.py +0 -0
  13. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/annotation/deprecate.py +0 -0
  14. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/error.py +0 -0
  15. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/fastapi/__init__.py +0 -0
  16. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/fastapi/builder.py +0 -0
  17. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/fastapi/dependable.py +0 -0
  18. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/fastapi/docs.py +0 -0
  19. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/fastapi/resource.py +0 -0
  20. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/fastapi/response.py +0 -0
  21. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/fastapi/router.py +0 -0
  22. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/fastapi/service.py +0 -0
  23. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/formatter.py +0 -0
  24. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/http/__init__.py +0 -0
  25. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/http/fake.py +0 -0
  26. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/http/fluent.py +0 -0
  27. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/http/httpx.py +0 -0
  28. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/http/url.py +0 -0
  29. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/py.typed +0 -0
  30. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/repository/__init__.py +0 -0
  31. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/repository/base.py +0 -0
  32. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/repository/connector.py +0 -0
  33. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/repository/database.py +0 -0
  34. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/repository/in_memory.py +0 -0
  35. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/repository/interface.py +0 -0
  36. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/repository/sqlite.py +0 -0
  37. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/testing/__init__.py +0 -0
  38. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/testing/database.py +0 -0
  39. {apexdevkit-1.9.5 → apexdevkit-1.9.7}/apexdevkit/testing/fake.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: apexdevkit
3
- Version: 1.9.5
3
+ Version: 1.9.7
4
4
  Summary: Apex Development Tools for python.
5
5
  Author: Apex Dev
6
6
  Author-email: dev@apex.ge
@@ -5,22 +5,22 @@ from typing import Any, Callable, Iterable, List
5
5
 
6
6
  from pydantic import BaseModel, create_model
7
7
 
8
- from apexdevkit.http import JsonDict
8
+ from apexdevkit.fluent import FluentDict
9
9
  from apexdevkit.testing import RestfulName
10
10
 
11
11
 
12
12
  class SchemaFields(ABC):
13
- def id(self) -> JsonDict:
13
+ def id(self) -> FluentDict[type]:
14
14
  return self.readable().select("id")
15
15
 
16
- def writable(self) -> JsonDict:
16
+ def writable(self) -> FluentDict[type]:
17
17
  return self.readable().drop("id")
18
18
 
19
- def editable(self) -> JsonDict:
19
+ def editable(self) -> FluentDict[type]:
20
20
  return self.readable().drop("id")
21
21
 
22
22
  @abstractmethod
23
- def readable(self) -> JsonDict: # pragma: no cover
23
+ def readable(self) -> FluentDict[type]: # pragma: no cover
24
24
  pass
25
25
 
26
26
 
@@ -38,26 +38,11 @@ class RestfulSchema:
38
38
  "UpdateManyItem", self.fields.editable().merge(self.fields.id())
39
39
  )
40
40
 
41
- self._schema_for(
42
- "Item",
43
- JsonDict({self.name.singular: schema}),
44
- )
45
- self._schema_for(
46
- "Collection",
47
- JsonDict({self.name.plural: List[schema]}).with_a(count=int),
48
- )
49
-
50
- self._schema_for(
51
- "CreateMany",
52
- JsonDict({self.name.plural: List[create_schema]}),
53
- )
54
- self._schema_for(
55
- "UpdateMany",
56
- JsonDict({self.name.plural: List[update_many_item]}),
57
- )
58
- self._schema_for(
59
- "ReplaceMany", JsonDict({self.name.plural: List[replace_schema]})
60
- )
41
+ self._schema_for("Item", {self.name.singular: schema})
42
+ self._schema_for("Collection", {self.name.plural: List[schema], "count": int})
43
+ self._schema_for("CreateMany", {self.name.plural: List[create_schema]})
44
+ self._schema_for("UpdateMany", {self.name.plural: List[update_many_item]})
45
+ self._schema_for("ReplaceMany", {self.name.plural: List[replace_schema]})
61
46
 
62
47
  def _schema_for(self, action: str, fields: dict[str, Any]) -> type[BaseModel]:
63
48
  if action not in self.schemas:
@@ -81,13 +66,13 @@ class RestfulSchema:
81
66
 
82
67
  return self._schema_for(
83
68
  "NoDataResponse",
84
- JsonDict().with_a(status=str).and_a(code=int).and_a(data=NoData),
69
+ FluentDict[type]().with_a(status=str).and_a(code=int).and_a(data=NoData),
85
70
  )
86
71
 
87
72
  def for_item(self) -> type[BaseModel]:
88
73
  return self._schema_for(
89
74
  "ItemResponse",
90
- JsonDict()
75
+ FluentDict[type]()
91
76
  .with_a(status=str)
92
77
  .and_a(code=int)
93
78
  .and_a(data=self.schemas["Item"]),
@@ -96,7 +81,7 @@ class RestfulSchema:
96
81
  def for_collection(self) -> type[BaseModel]:
97
82
  return self._schema_for(
98
83
  "CollectionResponse",
99
- JsonDict()
84
+ FluentDict[type]()
100
85
  .with_a(status=str)
101
86
  .and_a(code=int)
102
87
  .and_a(data=self.schemas["Collection"]),
@@ -0,0 +1,40 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Callable, Generic, TypeVar
5
+
6
+ ItemT = TypeVar("ItemT")
7
+
8
+
9
+ class FluentDict(dict[str, ItemT]):
10
+ def value_of(self, key: str) -> FluentElement[ItemT]:
11
+ return FluentElement(self[key])
12
+
13
+ def and_a(self, **fields: ItemT) -> FluentDict[ItemT]:
14
+ return self.with_a(**fields)
15
+
16
+ def with_a(self, **fields: ItemT) -> FluentDict[ItemT]:
17
+ return self.merge(FluentDict[ItemT](fields))
18
+
19
+ def merge(self, other: FluentDict[ItemT]) -> FluentDict[ItemT]:
20
+ return FluentDict[ItemT]({**self, **other})
21
+
22
+ def drop(self, *keys: str) -> FluentDict[ItemT]:
23
+ return self.select(*set(self.keys()).difference(keys))
24
+
25
+ def select(self, *keys: str) -> FluentDict[ItemT]:
26
+ return FluentDict[ItemT]({k: v for k, v in self.items() if k in keys})
27
+
28
+
29
+ @dataclass
30
+ class FluentElement(Generic[ItemT]):
31
+ value: ItemT
32
+
33
+ def to(self, a_type: Callable[[ItemT], ConvertedT]) -> ConvertedT:
34
+ return a_type(self.value)
35
+
36
+ def __str__(self) -> str:
37
+ return str(self.value)
38
+
39
+
40
+ ConvertedT = TypeVar("ConvertedT")
@@ -0,0 +1,5 @@
1
+ from typing import Any
2
+
3
+ from apexdevkit.fluent import FluentDict
4
+
5
+ JsonDict = FluentDict[Any]
@@ -1,11 +1,10 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from dataclasses import dataclass
4
- from typing import Any, ContextManager, Dict, Generic, Iterator, Protocol, TypeVar
4
+ from typing import Any, ContextManager, Generic, Iterator, Protocol, TypeVar
5
5
 
6
6
  from pymongo import MongoClient, ReturnDocument
7
7
  from pymongo.collection import Collection
8
- from pymongo.results import DeleteResult, InsertOneResult
9
8
 
10
9
  from apexdevkit.error import DoesNotExistError, ExistsError
11
10
  from apexdevkit.formatter import Formatter
@@ -22,15 +21,22 @@ ItemT = TypeVar("ItemT", bound=_Item)
22
21
 
23
22
  @dataclass
24
23
  class MongoRepository(Generic[ItemT]):
25
- database: MongoDatabase
24
+ connector: MongoConnector
25
+ database_name: str
26
+ collection_name: str
26
27
  formatter: Formatter[dict[str, Any], ItemT]
27
28
 
29
+ def collection(self, client: MongoClient[Any]) -> Collection[Any]:
30
+ return client[self.database_name][self.collection_name]
31
+
28
32
  def __iter__(self) -> Iterator[ItemT]:
29
- for raw in self.database:
30
- yield self.formatter.load(raw)
33
+ with self.connector.connect() as client:
34
+ for raw in self.collection(client).find():
35
+ yield self.formatter.load(raw)
31
36
 
32
37
  def __len__(self) -> int:
33
- return len(self.database)
38
+ with self.connector.connect() as client:
39
+ return self.collection(client).count_documents({})
34
40
 
35
41
  def create(self, item: ItemT) -> ItemT:
36
42
  try:
@@ -39,70 +45,40 @@ class MongoRepository(Generic[ItemT]):
39
45
  lambda i: f"_Item with id<{i.id}> already exists."
40
46
  )
41
47
  except DoesNotExistError:
42
- self.database.create(self.formatter.dump(item))
43
- return item
48
+ with self.connector.connect() as client:
49
+ self.collection(client).insert_one(self.formatter.dump(item))
50
+ return item
44
51
 
45
52
  def create_many(self, items: list[ItemT]) -> list[ItemT]:
46
53
  return [self.create(item) for item in items]
47
54
 
48
55
  def read(self, item_id: str) -> ItemT:
49
- raw = self.database.read(item_id)
56
+ with self.connector.connect() as client:
57
+ raw = self.collection(client).find_one({"id": item_id})
50
58
 
51
- if not raw:
52
- raise DoesNotExistError(item_id)
59
+ if not raw:
60
+ raise DoesNotExistError(item_id)
53
61
 
54
- return self.formatter.load(raw)
62
+ return self.formatter.load(dict(raw))
55
63
 
56
64
  def update(self, item: ItemT) -> None:
57
- self.database.update(item.id, self.formatter.dump(item))
65
+ with self.connector.connect() as client:
66
+ self.collection(client).find_one_and_update(
67
+ {"id": item.id},
68
+ {"$set": self.formatter.dump(item)},
69
+ return_document=ReturnDocument.AFTER,
70
+ )
58
71
 
59
72
  def update_many(self, items: list[ItemT]) -> None:
60
73
  for item in items:
61
74
  self.update(item)
62
75
 
63
76
  def delete(self, item_id: str) -> None:
64
- result = self.database.delete(item_id)
65
- if result.deleted_count == 0:
66
- raise DoesNotExistError(item_id)
67
-
68
-
69
- @dataclass
70
- class MongoDatabase:
71
- connector: MongoConnector
72
- database_name: str
73
- collection_name: str
74
-
75
- def collection(self, client: MongoClient[Any]) -> Collection[Any]:
76
- return client[self.database_name][self.collection_name]
77
-
78
- def __iter__(self) -> Iterator[Any]:
79
77
  with self.connector.connect() as client:
80
- for raw in self.collection(client).find():
81
- yield raw
82
-
83
- def __len__(self) -> int:
84
- with self.connector.connect() as client:
85
- return self.collection(client).count_documents({})
78
+ result = self.collection(client).delete_one({"id": item_id})
86
79
 
87
- def create(self, item: Dict[str, Any]) -> InsertOneResult:
88
- with self.connector.connect() as client:
89
- return self.collection(client).insert_one(item)
90
-
91
- def read(self, item_id: str) -> Dict[str, Any] | None:
92
- with self.connector.connect() as client:
93
- return self.collection(client).find_one({"id": item_id})
94
-
95
- def update(self, item_id: str, item: Dict[str, Any]) -> Any:
96
- with self.connector.connect() as client:
97
- return self.collection(client).find_one_and_update(
98
- {"id": item_id},
99
- {"$set": item},
100
- return_document=ReturnDocument.AFTER,
101
- )
102
-
103
- def delete(self, item_id: str) -> DeleteResult:
104
- with self.connector.connect() as client:
105
- return self.collection(client).delete_one({"id": item_id})
80
+ if result.deleted_count == 0:
81
+ raise DoesNotExistError(item_id)
106
82
 
107
83
 
108
84
  class MongoConnector(Protocol): # pragma: no cover
@@ -260,27 +260,13 @@ class RestResponse:
260
260
  return self.with_item(value)
261
261
 
262
262
  def with_item(self, value: Any) -> Self:
263
- return self.with_data(
264
- **{
265
- self.resource.singular: dict(value)
266
- if isinstance(value, JsonDict)
267
- else value
268
- }
269
- )
263
+ return self.with_data(**{self.resource.singular: value})
270
264
 
271
265
  def and_collection(self, value: list[Any]) -> Self:
272
266
  return self.with_collection(value)
273
267
 
274
268
  def with_collection(self, values: list[Any]) -> Self:
275
- return self.with_data(
276
- **{
277
- self.resource.plural: [
278
- dict(value) if isinstance(value, JsonDict) else value
279
- for value in values
280
- ],
281
- },
282
- count=len(values),
283
- )
269
+ return self.with_data(**{self.resource.plural: values}, count=len(values))
284
270
 
285
271
  def and_no_data(self) -> Self:
286
272
  return self.no_data()
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "apexdevkit"
3
- version = "1.9.5"
3
+ version = "1.9.7"
4
4
  description = "Apex Development Tools for python."
5
5
  authors = ["Apex Dev <dev@apex.ge>"]
6
6
  readme = "README.md"
@@ -1,38 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from dataclasses import dataclass
4
- from typing import Any, Callable, TypeVar
5
-
6
-
7
- class JsonDict(dict[str, Any]):
8
- def value_of(self, key: str) -> FluentElement:
9
- return FluentElement(self[key])
10
-
11
- def and_a(self, **fields: Any) -> JsonDict:
12
- return self.with_a(**fields)
13
-
14
- def with_a(self, **fields: Any) -> JsonDict:
15
- return self.merge(JsonDict(fields))
16
-
17
- def merge(self, other: JsonDict) -> JsonDict:
18
- return JsonDict({**self, **other})
19
-
20
- def drop(self, *keys: str) -> JsonDict:
21
- return self.select(*set(self.keys()).difference(keys))
22
-
23
- def select(self, *keys: str) -> JsonDict:
24
- return JsonDict({k: v for k, v in self.items() if k in keys})
25
-
26
-
27
- @dataclass
28
- class FluentElement:
29
- value: Any
30
-
31
- def to(self, a_type: Callable[[Any], ConvertedT]) -> ConvertedT:
32
- return a_type(self.value)
33
-
34
- def __str__(self) -> str:
35
- return str(self.value)
36
-
37
-
38
- ConvertedT = TypeVar("ConvertedT")
File without changes
File without changes