apexdevkit 2.1.4__tar.gz → 2.2.1__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 (52) hide show
  1. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/PKG-INFO +1 -1
  2. apexdevkit-2.2.1/apexdevkit/fastapi/resource.py +103 -0
  3. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/fastapi/router.py +14 -11
  4. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/fastapi/schema.py +0 -3
  5. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/fastapi/service.py +1 -53
  6. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/pyproject.toml +2 -1
  7. apexdevkit-2.1.4/apexdevkit/fastapi/docs.py +0 -15
  8. apexdevkit-2.1.4/apexdevkit/fastapi/resource.py +0 -319
  9. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/LICENSE +0 -0
  10. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/README.md +0 -0
  11. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/__init__.py +0 -0
  12. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/annotation/__init__.py +0 -0
  13. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/annotation/deprecate.py +0 -0
  14. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/date.py +0 -0
  15. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/error.py +0 -0
  16. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/fastapi/__init__.py +0 -0
  17. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/fastapi/builder.py +0 -0
  18. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/fastapi/dependable.py +0 -0
  19. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/fastapi/name.py +0 -0
  20. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/fastapi/response.py +0 -0
  21. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/formatter.py +0 -0
  22. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/key_fn.py +0 -0
  23. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/py.typed +0 -0
  24. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/query/__init__.py +0 -0
  25. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/query/generator.py +0 -0
  26. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/query/query.py +0 -0
  27. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/repository/__init__.py +0 -0
  28. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/repository/core/__init__.py +0 -0
  29. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/repository/core/database.py +0 -0
  30. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/repository/core/decorator.py +0 -0
  31. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/repository/core/interface.py +0 -0
  32. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/repository/core/mixin.py +0 -0
  33. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/repository/in_memory/__init__.py +0 -0
  34. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/repository/in_memory/mixin.py +0 -0
  35. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/repository/in_memory/repository.py +0 -0
  36. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/repository/in_memory/store.py +0 -0
  37. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/repository/sql/__init__.py +0 -0
  38. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/repository/sql/connector.py +0 -0
  39. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/repository/sql/field.py +0 -0
  40. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/repository/sql/mssql/__init__.py +0 -0
  41. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/repository/sql/mssql/repository.py +0 -0
  42. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/repository/sql/mssql/table.py +0 -0
  43. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/repository/sql/sqlite/__init__.py +0 -0
  44. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/repository/sql/sqlite/repository.py +0 -0
  45. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/repository/sql/sqlite/table.py +0 -0
  46. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/server.py +0 -0
  47. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/sync/__init__.py +0 -0
  48. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/sync/observer.py +0 -0
  49. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/sync/source.py +0 -0
  50. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/sync/sync.py +0 -0
  51. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/sync/target.py +0 -0
  52. {apexdevkit-2.1.4 → apexdevkit-2.2.1}/apexdevkit/testing.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: apexdevkit
3
- Version: 2.1.4
3
+ Version: 2.2.1
4
4
  Summary: Apex Development Tools for python.
5
5
  License-File: LICENSE
6
6
  Author: Apex Dev
@@ -0,0 +1,103 @@
1
+ from collections.abc import Callable
2
+ from dataclasses import dataclass
3
+ from typing import Any
4
+
5
+ from fastapi.responses import JSONResponse
6
+
7
+ from apexdevkit.error import DoesNotExistError, ExistsError, ForbiddenError
8
+ from apexdevkit.fastapi.response import RestfulResponse
9
+
10
+ _Response = JSONResponse | dict[str, Any]
11
+ _Endpoint = Callable[..., _Response]
12
+
13
+
14
+ @dataclass(frozen=True)
15
+ class RestfulResource:
16
+ response: RestfulResponse
17
+
18
+ def create_one_endpoint(self, Service, Item) -> _Endpoint:
19
+ def endpoint(service: Service, item: Item) -> _Response:
20
+ try:
21
+ result = service.create_one(item)
22
+ except ExistsError as e:
23
+ return JSONResponse(self.response.exists(e), 409)
24
+ except ForbiddenError as e:
25
+ return JSONResponse(self.response.forbidden(e), 403)
26
+
27
+ return self.response.created_one(result)
28
+
29
+ return endpoint
30
+
31
+ def read_one_endpoint(self, Service, ItemId) -> _Endpoint:
32
+ def endpoint(service: Service, item_id: ItemId) -> _Response:
33
+ try:
34
+ result = service.read_one(item_id)
35
+ except DoesNotExistError as e:
36
+ return JSONResponse(self.response.not_found(e), 404)
37
+ except ForbiddenError as e:
38
+ return JSONResponse(self.response.forbidden(e), 403)
39
+
40
+ return self.response.found_one(result)
41
+
42
+ return endpoint
43
+
44
+ def read_many_endpoint(self, Service, QueryParams) -> _Endpoint:
45
+ def endpoint(service: Service, params: QueryParams) -> _Response:
46
+ try:
47
+ result = list(service.read_many(**dict(params)))
48
+ except ForbiddenError as e:
49
+ return JSONResponse(self.response.forbidden(e), 403)
50
+
51
+ return self.response.found_many(result)
52
+
53
+ return endpoint
54
+
55
+ def read_all_endpoint(self, Service) -> _Endpoint:
56
+ def endpoint(service: Service) -> _Response:
57
+ try:
58
+ result = list(service.read_all())
59
+ except ForbiddenError as e:
60
+ return JSONResponse(self.response.forbidden(e), 403)
61
+
62
+ return self.response.found_many(result)
63
+
64
+ return endpoint
65
+
66
+ def update_one_endpoint(self, Service, ItemId, Updates) -> _Endpoint:
67
+ def endpoint(service: Service, item_id: ItemId, updates: Updates) -> _Response:
68
+ try:
69
+ service.update_one(item_id, **updates)
70
+ except DoesNotExistError as e:
71
+ return JSONResponse(self.response.not_found(e), 404)
72
+ except ForbiddenError as e:
73
+ return JSONResponse(self.response.forbidden(e), 403)
74
+
75
+ return self.response.ok()
76
+
77
+ return endpoint
78
+
79
+ def replace_one_endpoint(self, Service, Item) -> _Endpoint:
80
+ def endpoint(service: Service, item: Item) -> _Response:
81
+ try:
82
+ service.replace_one(item)
83
+ except DoesNotExistError as e:
84
+ return JSONResponse(self.response.not_found(e), 404)
85
+ except ForbiddenError as e:
86
+ return JSONResponse(self.response.forbidden(e), 403)
87
+
88
+ return self.response.ok()
89
+
90
+ return endpoint
91
+
92
+ def delete_one_endpoint(self, Service, ItemId) -> _Endpoint:
93
+ def endpoint(service: Service, item_id: ItemId) -> _Response:
94
+ try:
95
+ service.delete_one(item_id)
96
+ except DoesNotExistError as e:
97
+ return JSONResponse(self.response.not_found(e), 404)
98
+ except ForbiddenError as e:
99
+ return JSONResponse(self.response.forbidden(e), 403)
100
+
101
+ return self.response.ok()
102
+
103
+ return endpoint
@@ -1,7 +1,7 @@
1
1
  from collections.abc import Callable
2
2
  from dataclasses import dataclass, field
3
3
  from enum import Enum
4
- from typing import Annotated, Any, Protocol, Self, TypeVar
4
+ from typing import Annotated, Any, Protocol, Self
5
5
 
6
6
  from fastapi import APIRouter, Depends, Path, Query
7
7
  from fastapi.responses import JSONResponse
@@ -47,8 +47,6 @@ class RouterWithHiddenUnderscoreRoutes(APIRouter):
47
47
 
48
48
  _Response = JSONResponse | dict[str, Any]
49
49
 
50
- T = TypeVar("T")
51
-
52
50
 
53
51
  class Dependency(Protocol): # pragma: no cover
54
52
  def as_dependable(self) -> type[RestfulService]:
@@ -128,7 +126,7 @@ class RestfulRouter:
128
126
  ) -> Self:
129
127
  self.router.add_api_route(
130
128
  "",
131
- self.resource.create_one(
129
+ self.resource.create_one_endpoint(
132
130
  Service=self._resolve(dependency),
133
131
  Item=Annotated[
134
132
  RawItem,
@@ -153,7 +151,7 @@ class RestfulRouter:
153
151
  ) -> Self:
154
152
  self.router.add_api_route(
155
153
  self.item_path,
156
- self.resource.read_one(
154
+ self.resource.read_one_endpoint(
157
155
  Service=self._resolve(dependency),
158
156
  ItemId=Annotated[
159
157
  str,
@@ -179,10 +177,13 @@ class RestfulRouter:
179
177
  ) -> Self:
180
178
  self.router.add_api_route(
181
179
  "",
182
- self.resource.read_many(
180
+ self.resource.read_many_endpoint(
183
181
  Service=self._resolve(dependency),
184
182
  QueryParams=Annotated[
185
- Schema(self.name.singular).optional_schema_for("ReadMany", query),
183
+ Schema(self.name.singular).optional_schema_for(
184
+ action="ReadMany",
185
+ fields=query,
186
+ ),
186
187
  Query(),
187
188
  ],
188
189
  ),
@@ -204,7 +205,9 @@ class RestfulRouter:
204
205
  ) -> Self:
205
206
  self.router.add_api_route(
206
207
  "",
207
- self.resource.read_all(Service=self._resolve(dependency)),
208
+ self.resource.read_all_endpoint(
209
+ Service=self._resolve(dependency),
210
+ ),
208
211
  methods=["GET"],
209
212
  status_code=200,
210
213
  responses={},
@@ -223,7 +226,7 @@ class RestfulRouter:
223
226
  ) -> Self:
224
227
  self.router.add_api_route(
225
228
  self.item_path,
226
- self.resource.update_one(
229
+ self.resource.update_one_endpoint(
227
230
  Service=self._resolve(dependency),
228
231
  ItemId=Annotated[
229
232
  str,
@@ -252,7 +255,7 @@ class RestfulRouter:
252
255
  ) -> Self:
253
256
  self.router.add_api_route(
254
257
  "",
255
- self.resource.replace_one(
258
+ self.resource.replace_one_endpoint(
256
259
  Service=self._resolve(dependency),
257
260
  Item=Annotated[
258
261
  RawItem,
@@ -277,7 +280,7 @@ class RestfulRouter:
277
280
  ) -> Self:
278
281
  self.router.add_api_route(
279
282
  self.item_path,
280
- self.resource.delete_one(
283
+ self.resource.delete_one_endpoint(
281
284
  Service=self._resolve(dependency),
282
285
  ItemId=Annotated[
283
286
  str,
@@ -11,9 +11,6 @@ from apexdevkit.fastapi.name import RestfulName
11
11
 
12
12
 
13
13
  class SchemaFields(ABC):
14
- def id(self) -> FluentDict[type]:
15
- return self.readable().select("id")
16
-
17
14
  def writable(self) -> FluentDict[type]:
18
15
  return self.readable().drop("id")
19
16
 
@@ -2,61 +2,36 @@ from __future__ import annotations
2
2
 
3
3
  from collections.abc import Iterable, Mapping
4
4
  from dataclasses import dataclass
5
- from functools import cached_property
6
5
  from typing import TYPE_CHECKING, Any
7
6
 
8
- from apexdevkit.repository import BruteForceBatch, Entity, Repository
7
+ from apexdevkit.repository import Entity, Repository
9
8
 
10
9
  if TYPE_CHECKING:
11
10
  from apexdevkit.formatter import Formatter
12
- from apexdevkit.repository.core.interface import BatchRepository
13
11
 
14
12
  RawItem = Mapping[str, Any]
15
13
  RawCollection = Iterable[RawItem]
16
14
 
17
15
 
18
- class _RawItemWithId(dict[str, Any]):
19
- def __post_init__(self) -> None:
20
- assert "id" in self
21
-
22
-
23
- RawCollectionWithId = Iterable[_RawItemWithId]
24
-
25
-
26
16
  class RestfulService: # pragma: no cover
27
17
  def create_one(self, item: RawItem) -> RawItem:
28
18
  raise NotImplementedError(self.create_one.__name__)
29
19
 
30
- def create_many(self, items: RawCollection) -> RawCollection:
31
- raise NotImplementedError(self.create_many.__name__)
32
-
33
20
  def read_one(self, item_id: str) -> RawItem:
34
21
  raise NotImplementedError(self.read_one.__name__)
35
22
 
36
23
  def read_many(self, **params: Any) -> RawCollection:
37
24
  raise NotImplementedError(self.read_many.__name__)
38
25
 
39
- def filter_with(self, options: RawItem) -> RawCollection:
40
- raise NotImplementedError(self.filter_with.__name__)
41
-
42
- def aggregation_with(self, options: RawItem) -> RawItem:
43
- raise NotImplementedError(self.filter_with.__name__)
44
-
45
26
  def read_all(self) -> RawCollection:
46
27
  raise NotImplementedError(self.read_all.__name__)
47
28
 
48
29
  def update_one(self, item_id: str, **with_fields: Any) -> RawItem:
49
30
  raise NotImplementedError(self.update_one.__name__)
50
31
 
51
- def update_many(self, items: RawCollectionWithId) -> RawCollection:
52
- raise NotImplementedError(self.update_many.__name__)
53
-
54
32
  def replace_one(self, item: RawItem) -> RawItem:
55
33
  raise NotImplementedError(self.replace_one.__name__)
56
34
 
57
- def replace_many(self, items: RawCollection) -> RawCollection:
58
- raise NotImplementedError(self.replace_many.__name__)
59
-
60
35
  def delete_one(self, item_id: str) -> None:
61
36
  raise NotImplementedError(self.delete_one.__name__)
62
37
 
@@ -67,21 +42,9 @@ class RestfulRepository[ItemT: Entity](RestfulService):
67
42
 
68
43
  formatter: Formatter[Mapping[str, Any], ItemT]
69
44
 
70
- @cached_property
71
- def _batch(self) -> BatchRepository[ItemT]:
72
- return BruteForceBatch(inner=self.repository)
73
-
74
45
  def create_one(self, item: RawItem) -> RawItem:
75
46
  return self.formatter.dump(self.repository.create(self.formatter.load(item)))
76
47
 
77
- def create_many(self, items: RawCollection) -> RawCollection:
78
- return [
79
- self.formatter.dump(item)
80
- for item in self._batch.load(
81
- [self.formatter.load(fields) for fields in items]
82
- )
83
- ]
84
-
85
48
  def read_one(self, item_id: str) -> RawItem:
86
49
  return self.formatter.dump(self.repository.read(item_id))
87
50
 
@@ -96,25 +59,10 @@ class RestfulRepository[ItemT: Entity](RestfulService):
96
59
 
97
60
  return data
98
61
 
99
- def update_many(self, items: RawCollectionWithId) -> RawCollection:
100
- updates = []
101
- for fields in items:
102
- data = dict(self.formatter.dump(self.repository.read(fields["id"])))
103
- data.update(**fields)
104
-
105
- updates.append(self.formatter.load(data))
106
-
107
- return [self.formatter.dump(item) for item in self._batch.renew(updates)]
108
-
109
62
  def replace_one(self, item: RawItem) -> RawItem:
110
63
  self.repository.update(self.formatter.load(item))
111
64
 
112
65
  return item
113
66
 
114
- def replace_many(self, items: RawCollection) -> RawCollection:
115
- updated = self._batch.renew([self.formatter.load(item) for item in items])
116
-
117
- return [self.formatter.dump(item) for item in updated]
118
-
119
67
  def delete_one(self, item_id: str) -> None:
120
68
  self.repository.delete(item_id)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "apexdevkit"
3
- version = "2.1.4"
3
+ version = "2.2.1"
4
4
  description = "Apex Development Tools for python."
5
5
  readme = "README.md"
6
6
  authors = [
@@ -80,6 +80,7 @@ ignore = [
80
80
  [tool.mypy]
81
81
  exclude = [
82
82
  "apexdevkit/fastapi/dependable.py",
83
+ "apexdevkit/fastapi/resource.py",
83
84
  "apexdevkit/fastapi/schema.py",
84
85
  ]
85
86
  ignore_missing_imports = true
@@ -1,15 +0,0 @@
1
- from typing import TypeVar
2
-
3
- from pydantic import BaseModel
4
-
5
- PayloadT = TypeVar("PayloadT")
6
-
7
-
8
- class Response[PayloadT](BaseModel):
9
- status: str
10
- code: int
11
- data: PayloadT
12
-
13
-
14
- class NoData(BaseModel):
15
- pass
@@ -1,319 +0,0 @@
1
- import re
2
- from collections.abc import Callable
3
- from dataclasses import dataclass
4
- from typing import Any, Union
5
-
6
- from fastapi.responses import JSONResponse
7
- from pydantic import BaseModel
8
-
9
- from apexdevkit.error import DoesNotExistError, ExistsError, ForbiddenError
10
- from apexdevkit.fastapi.response import RestfulResponse
11
- from apexdevkit.query.query import (
12
- Aggregation,
13
- AggregationOption,
14
- DateValue,
15
- Filter,
16
- FooterOptions,
17
- Leaf,
18
- ListValue,
19
- NullValue,
20
- NumericValue,
21
- Operation,
22
- Operator,
23
- Page,
24
- QueryOptions,
25
- Sort,
26
- StringValue,
27
- )
28
-
29
- _Response = JSONResponse | dict[str, Any]
30
- _Endpoint = Callable[..., _Response]
31
-
32
-
33
- @dataclass(frozen=True)
34
- class RestfulResource:
35
- response: RestfulResponse
36
-
37
- def create_one(self, Service, Item) -> _Endpoint: # type: ignore
38
- def endpoint(service: Service, item: Item) -> _Response:
39
- try:
40
- item = service.create_one(item)
41
- except ExistsError as e:
42
- return JSONResponse(self.response.exists(e), 409)
43
- except ForbiddenError as e:
44
- return JSONResponse(self.response.forbidden(e), 403)
45
-
46
- return self.response.created_one(item)
47
-
48
- return endpoint
49
-
50
- def create_many(self, Service, Collection) -> _Endpoint: # type: ignore
51
- def endpoint(service: Service, items: Collection) -> _Response:
52
- try:
53
- return self.response.created_many(service.create_many(items))
54
- except ExistsError as e:
55
- return JSONResponse(self.response.exists(e), 409)
56
- except ForbiddenError as e:
57
- return JSONResponse(self.response.forbidden(e), 403)
58
-
59
- return endpoint
60
-
61
- def read_one(self, Service, ItemId) -> _Endpoint: # type: ignore
62
- def endpoint(service: Service, item_id: ItemId) -> _Response:
63
- try:
64
- return self.response.found_one(service.read_one(item_id))
65
- except DoesNotExistError as e:
66
- return JSONResponse(self.response.not_found(e), 404)
67
- except ForbiddenError as e:
68
- return JSONResponse(self.response.forbidden(e), 403)
69
-
70
- return endpoint
71
-
72
- def read_many(self, Service, QueryParams) -> _Endpoint: # type: ignore
73
- def endpoint(service: Service, params: QueryParams) -> _Response:
74
- try:
75
- return self.response.found_many(list(service.read_many(**dict(params))))
76
- except ForbiddenError as e:
77
- return JSONResponse(self.response.forbidden(e), 403)
78
-
79
- return endpoint
80
-
81
- def filter_with(self, Service, QueryOptions) -> _Endpoint: # type: ignore
82
- def endpoint(service: Service, options: QueryOptions) -> _Response:
83
- try:
84
- return self.response.found_many(list(service.filter_with(options)))
85
- except ForbiddenError as e:
86
- return JSONResponse(self.response.forbidden(e), 403)
87
-
88
- return endpoint
89
-
90
- def aggregation_with(self, Service, FilterOptions) -> _Endpoint: # type: ignore
91
- def endpoint(service: Service, options: FilterOptions) -> _Response:
92
- try:
93
- return {
94
- "status": "success",
95
- "code": 200,
96
- "aggregations": service.aggregation_with(options),
97
- }
98
- except ForbiddenError as e:
99
- return JSONResponse(self.response.forbidden(e), 403)
100
-
101
- return endpoint
102
-
103
- def read_all(self, Service) -> _Endpoint: # type: ignore
104
- def endpoint(service: Service) -> _Response:
105
- try:
106
- return self.response.found_many(list(service.read_all()))
107
- except ForbiddenError as e:
108
- return JSONResponse(self.response.forbidden(e), 403)
109
-
110
- return endpoint
111
-
112
- def update_one(self, Service, ItemId, Updates) -> _Endpoint: # type: ignore
113
- def endpoint(service: Service, item_id: ItemId, updates: Updates) -> _Response:
114
- try:
115
- service.update_one(item_id, **updates)
116
- except DoesNotExistError as e:
117
- return JSONResponse(self.response.not_found(e), 404)
118
- except ForbiddenError as e:
119
- return JSONResponse(self.response.forbidden(e), 403)
120
-
121
- return self.response.ok()
122
-
123
- return endpoint
124
-
125
- def update_many(self, Service, Collection) -> _Endpoint: # type: ignore
126
- def endpoint(service: Service, items: Collection) -> _Response:
127
- try:
128
- service.update_many(items)
129
- except DoesNotExistError as e:
130
- return JSONResponse(self.response.not_found(e), 404)
131
- except ForbiddenError as e:
132
- return JSONResponse(self.response.forbidden(e), 403)
133
-
134
- return self.response.ok()
135
-
136
- return endpoint
137
-
138
- def replace_one(self, Service, Item) -> _Endpoint: # type: ignore
139
- def endpoint(service: Service, item: Item) -> _Response:
140
- try:
141
- service.replace_one(item)
142
- except DoesNotExistError as e:
143
- return JSONResponse(self.response.not_found(e), 404)
144
- except ForbiddenError as e:
145
- return JSONResponse(self.response.forbidden(e), 403)
146
-
147
- return self.response.ok()
148
-
149
- return endpoint
150
-
151
- def replace_many(self, Service, Collection) -> _Endpoint: # type: ignore
152
- def endpoint(service: Service, items: Collection) -> _Response:
153
- try:
154
- service.replace_many(items)
155
- except DoesNotExistError as e:
156
- return JSONResponse(self.response.not_found(e), 404)
157
- except ForbiddenError as e:
158
- return JSONResponse(self.response.forbidden(e), 403)
159
-
160
- return self.response.ok()
161
-
162
- return endpoint
163
-
164
- def delete_one(self, Service, ItemId) -> _Endpoint: # type: ignore
165
- def endpoint(service: Service, item_id: ItemId) -> _Response:
166
- try:
167
- service.delete_one(item_id)
168
- except DoesNotExistError as e:
169
- return JSONResponse(self.response.not_found(e), 404)
170
- except ForbiddenError as e:
171
- return JSONResponse(self.response.forbidden(e), 403)
172
-
173
- return self.response.ok()
174
-
175
- return endpoint
176
-
177
-
178
- @dataclass
179
- class _ColumnName:
180
- raw: str
181
-
182
- def __str__(self) -> str:
183
- return re.sub(r"(?<!^)(?=[A-Z])", "_", self.raw).lower()
184
-
185
-
186
- class _NumericItem(BaseModel):
187
- value: int
188
- exponent: int
189
-
190
- def to_value(self) -> NumericValue:
191
- return NumericValue(self.value, self.exponent)
192
-
193
-
194
- class _StringItem(BaseModel):
195
- value: str
196
-
197
- def to_value(self) -> StringValue:
198
- return StringValue(self.value)
199
-
200
-
201
- class _DateItem(BaseModel):
202
- date: str
203
-
204
- def to_value(self) -> DateValue:
205
- return DateValue(self.date)
206
-
207
-
208
- class _ListItem(BaseModel):
209
- values: list[_NumericItem | _StringItem | _DateItem]
210
-
211
- def to_value(self) -> ListValue:
212
- return ListValue([item.to_value() for item in self.values])
213
-
214
-
215
- class _LeafItem(BaseModel):
216
- name: str
217
- values: list[_NumericItem | _StringItem | _DateItem]
218
-
219
- def to_value(self) -> Leaf:
220
- return Leaf(
221
- name=str(_ColumnName(self.name)),
222
- values=[item.to_value() for item in self.values],
223
- )
224
-
225
-
226
- class _OperatorItem(BaseModel):
227
- operation: Operation
228
- operands: list[Union["_LeafItem", "_OperatorItem"]]
229
-
230
- def to_value(self) -> Operator:
231
- return Operator(self.operation, [item.to_value() for item in self.operands])
232
-
233
-
234
- class _SortItem(BaseModel):
235
- name: str
236
- is_descending: bool
237
-
238
- def to_value(self) -> Sort:
239
- return Sort(str(_ColumnName(self.name)), self.is_descending)
240
-
241
-
242
- class _PageItem(BaseModel):
243
- page: int | None
244
- length: int | None
245
- offset: int | None
246
-
247
- def to_value(self) -> Page:
248
- return Page(self.page, self.length, self.offset)
249
-
250
-
251
- class _FilterItem(BaseModel):
252
- args: list[_NumericItem | _StringItem | _DateItem | _ListItem | None]
253
-
254
- def to_value(self) -> Filter:
255
- return Filter(
256
- [arg.to_value() if arg is not None else None for arg in self.args]
257
- )
258
-
259
-
260
- class _AggregationOptionItem(BaseModel):
261
- name: str | None
262
- aggregation: Aggregation
263
-
264
- def to_value(self) -> AggregationOption:
265
- return AggregationOption(
266
- str(_ColumnName(self.name)) if self.name else None,
267
- self.aggregation,
268
- )
269
-
270
-
271
- class _FooterOptions(BaseModel):
272
- filter: _FilterItem | None
273
- condition: _OperatorItem | None
274
- aggregations: list[_AggregationOptionItem]
275
-
276
- def to_footer_options(self) -> FooterOptions:
277
- return FooterOptions(
278
- filter=self.filter.to_value() if self.filter else None,
279
- condition=self.condition.to_value() if self.condition else None,
280
- aggregations=[item.to_value() for item in self.aggregations],
281
- )
282
-
283
-
284
- class _QueryOptions(BaseModel):
285
- filter: _FilterItem | None
286
- condition: _OperatorItem | None
287
- ordering: list[_SortItem]
288
- paging: _PageItem
289
-
290
- def to_query_options(self) -> QueryOptions:
291
- return QueryOptions(
292
- filter=self.filter.to_value() if self.filter else None,
293
- condition=self.condition.to_value() if self.condition else None,
294
- ordering=[item.to_value() for item in self.ordering],
295
- paging=self.paging.to_value(),
296
- )
297
-
298
-
299
- class _SummaryItem(BaseModel):
300
- name: str | None
301
- aggregation: Aggregation
302
- result: NumericValue | StringValue | DateValue | NullValue
303
-
304
-
305
- class _SummaryListEnvelope(BaseModel):
306
- count: int
307
- summaries: list[_SummaryItem]
308
-
309
-
310
- class SummaryResponse(BaseModel):
311
- status: str
312
- code: int
313
- data: _SummaryListEnvelope
314
-
315
-
316
- class SumResponse(BaseModel):
317
- status: str
318
- code: int
319
- count: int
File without changes
File without changes