apexdevkit 1.5.20__tar.gz → 1.5.22__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 (36) hide show
  1. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/PKG-INFO +1 -1
  2. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/apexdevkit/fastapi/builder.py +23 -0
  3. apexdevkit-1.5.22/apexdevkit/fastapi/resource.py +177 -0
  4. apexdevkit-1.5.22/apexdevkit/fastapi/response.py +130 -0
  5. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/apexdevkit/fastapi/router.py +19 -273
  6. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/pyproject.toml +1 -1
  7. apexdevkit-1.5.20/apexdevkit/fastapi/response.py +0 -64
  8. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/LICENSE +0 -0
  9. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/README.md +0 -0
  10. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/apexdevkit/__init__.py +0 -0
  11. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/apexdevkit/annotation/__init__.py +0 -0
  12. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/apexdevkit/annotation/deprecate.py +0 -0
  13. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/apexdevkit/error.py +0 -0
  14. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/apexdevkit/fastapi/__init__.py +0 -0
  15. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/apexdevkit/fastapi/dependable.py +0 -0
  16. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/apexdevkit/fastapi/docs.py +0 -0
  17. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/apexdevkit/fastapi/schema.py +0 -0
  18. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/apexdevkit/fastapi/service.py +0 -0
  19. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/apexdevkit/formatter.py +0 -0
  20. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/apexdevkit/http/__init__.py +0 -0
  21. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/apexdevkit/http/fake.py +0 -0
  22. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/apexdevkit/http/fluent.py +0 -0
  23. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/apexdevkit/http/httpx.py +0 -0
  24. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/apexdevkit/http/json.py +0 -0
  25. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/apexdevkit/http/url.py +0 -0
  26. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/apexdevkit/py.typed +0 -0
  27. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/apexdevkit/repository/__init__.py +0 -0
  28. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/apexdevkit/repository/base.py +0 -0
  29. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/apexdevkit/repository/connector.py +0 -0
  30. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/apexdevkit/repository/database.py +0 -0
  31. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/apexdevkit/repository/in_memory.py +0 -0
  32. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/apexdevkit/repository/interface.py +0 -0
  33. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/apexdevkit/testing/__init__.py +0 -0
  34. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/apexdevkit/testing/database.py +0 -0
  35. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/apexdevkit/testing/fake.py +0 -0
  36. {apexdevkit-1.5.20 → apexdevkit-1.5.22}/apexdevkit/testing/rest.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: apexdevkit
3
- Version: 1.5.20
3
+ Version: 1.5.22
4
4
  Summary: Apex Development Tools for python.
5
5
  Author: Apex Dev
6
6
  Author-email: dev@apex.ge
@@ -1,8 +1,11 @@
1
+ from abc import ABC, abstractmethod
1
2
  from dataclasses import dataclass, field
2
3
  from typing import Any, Self
3
4
 
4
5
  from fastapi import APIRouter, FastAPI
5
6
 
7
+ from apexdevkit.fastapi.service import RestfulService
8
+
6
9
 
7
10
  @dataclass
8
11
  class FastApiBuilder:
@@ -37,3 +40,23 @@ class FastApiBuilder:
37
40
  self.app.include_router(value, prefix=f"/{key}", tags=[key.title()])
38
41
 
39
42
  return self
43
+
44
+
45
+ @dataclass
46
+ class RestfulServiceBuilder(ABC):
47
+ parent_id: str = field(init=False)
48
+ user: Any = field(init=False)
49
+
50
+ def with_user(self, user: Any) -> "RestfulServiceBuilder":
51
+ self.user = user
52
+
53
+ return self
54
+
55
+ def with_parent(self, identity: str) -> "RestfulServiceBuilder":
56
+ self.parent_id = identity
57
+
58
+ return self
59
+
60
+ @abstractmethod
61
+ def build(self) -> RestfulService: # pragma: no cover
62
+ pass
@@ -0,0 +1,177 @@
1
+ from dataclasses import dataclass
2
+ from functools import cached_property
3
+ from typing import Any, Callable
4
+
5
+ from starlette.responses import JSONResponse
6
+
7
+ from apexdevkit.error import DoesNotExistError, ExistsError, ForbiddenError
8
+ from apexdevkit.fastapi.builder import RestfulServiceBuilder
9
+ from apexdevkit.fastapi.response import RestfulResponse
10
+ from apexdevkit.testing import RestfulName
11
+
12
+ _Response = JSONResponse | dict[str, Any]
13
+
14
+
15
+ @dataclass
16
+ class RestfulResource:
17
+ name: RestfulName
18
+ infra: RestfulServiceBuilder
19
+ parent: RestfulName
20
+
21
+ @cached_property
22
+ def response(self) -> RestfulResponse:
23
+ return RestfulResponse(name=self.name)
24
+
25
+ def create_one(self, User, ParentId, Item) -> Callable[..., _Response]: # type: ignore
26
+ def endpoint(user: User, parent_id: ParentId, item: Item) -> _Response:
27
+ try:
28
+ service = self.infra.with_user(user).with_parent(parent_id).build()
29
+ except DoesNotExistError as e:
30
+ return JSONResponse(RestfulResponse(self.parent).not_found(e), 404)
31
+
32
+ try:
33
+ item = service.create_one(item)
34
+ except ExistsError as e:
35
+ return JSONResponse(self.response.exists(e), 409)
36
+ except ForbiddenError as e:
37
+ return JSONResponse(self.response.forbidden(e), 403)
38
+
39
+ return self.response.created_one(item)
40
+
41
+ return endpoint
42
+
43
+ def create_many(self, User, ParentId, Collection) -> Callable[..., _Response]: # type: ignore
44
+ def endpoint(user: User, parent_id: ParentId, items: Collection) -> _Response:
45
+ try:
46
+ service = self.infra.with_user(user).with_parent(parent_id).build()
47
+ except DoesNotExistError as e:
48
+ return JSONResponse(RestfulResponse(self.parent).not_found(e), 404)
49
+
50
+ try:
51
+ return self.response.created_many(service.create_many(items))
52
+ except ExistsError as e:
53
+ return JSONResponse(self.response.exists(e), 409)
54
+ except ForbiddenError as e:
55
+ return JSONResponse(self.response.forbidden(e), 403)
56
+
57
+ return endpoint
58
+
59
+ def read_one(self, User, ParentId, ItemId) -> Callable[..., _Response]: # type: ignore
60
+ def endpoint(user: User, parent_id: ParentId, item_id: ItemId) -> _Response:
61
+ try:
62
+ service = self.infra.with_user(user).with_parent(parent_id).build()
63
+ except DoesNotExistError as e:
64
+ return JSONResponse(RestfulResponse(self.parent).not_found(e), 404)
65
+
66
+ try:
67
+ return self.response.found_one(service.read_one(item_id))
68
+ except DoesNotExistError as e:
69
+ return JSONResponse(self.response.not_found(e), 404)
70
+ except ForbiddenError as e:
71
+ return JSONResponse(self.response.forbidden(e), 403)
72
+
73
+ return endpoint
74
+
75
+ def read_all(self, User, ParentId) -> Callable[..., _Response]: # type: ignore
76
+ def endpoint(user: User, parent_id: ParentId) -> _Response:
77
+ try:
78
+ service = self.infra.with_user(user).with_parent(parent_id).build()
79
+ except DoesNotExistError as e:
80
+ return JSONResponse(RestfulResponse(self.parent).not_found(e), 404)
81
+ try:
82
+ return self.response.found_many(list(service.read_all()))
83
+ except ForbiddenError as e:
84
+ return JSONResponse(self.response.forbidden(e), 403)
85
+
86
+ return endpoint
87
+
88
+ def update_one(self, User, ParentId, ItemId, Updates) -> Callable[..., _Response]: # type: ignore
89
+ def endpoint(
90
+ user: User,
91
+ parent_id: ParentId,
92
+ item_id: ItemId,
93
+ updates: Updates,
94
+ ) -> _Response:
95
+ try:
96
+ service = self.infra.with_user(user).with_parent(parent_id).build()
97
+ except DoesNotExistError as e:
98
+ return JSONResponse(RestfulResponse(self.parent).not_found(e), 404)
99
+ try:
100
+ service.update_one(item_id, **updates)
101
+ except DoesNotExistError as e:
102
+ return JSONResponse(self.response.not_found(e), 404)
103
+ except ForbiddenError as e:
104
+ return JSONResponse(self.response.forbidden(e), 403)
105
+
106
+ return self.response.ok()
107
+
108
+ return endpoint
109
+
110
+ def update_many(self, User, ParentId, Collection) -> Callable[..., _Response]: # type: ignore
111
+ def endpoint(user: User, parent_id: ParentId, items: Collection) -> _Response:
112
+ try:
113
+ service = self.infra.with_user(user).with_parent(parent_id).build()
114
+ except DoesNotExistError as e:
115
+ return JSONResponse(RestfulResponse(self.parent).not_found(e), 404)
116
+ try:
117
+ service.update_many(items)
118
+ except DoesNotExistError as e:
119
+ return JSONResponse(self.response.not_found(e), 404)
120
+ except ForbiddenError as e:
121
+ return JSONResponse(self.response.forbidden(e), 403)
122
+
123
+ return self.response.ok()
124
+
125
+ return endpoint
126
+
127
+ def replace_one(self, User, ParentId, Item) -> Callable[..., _Response]: # type: ignore
128
+ def endpoint(user: User, parent_id: ParentId, item: Item) -> _Response:
129
+ try:
130
+ service = self.infra.with_user(user).with_parent(parent_id).build()
131
+ except DoesNotExistError as e:
132
+ return JSONResponse(RestfulResponse(self.parent).not_found(e), 404)
133
+ try:
134
+ service.replace_one(item)
135
+ except DoesNotExistError as e:
136
+ return JSONResponse(self.response.not_found(e), 404)
137
+ except ForbiddenError as e:
138
+ return JSONResponse(self.response.forbidden(e), 403)
139
+
140
+ return self.response.ok()
141
+
142
+ return endpoint
143
+
144
+ def replace_many(self, User, ParentId, Collection) -> Callable[..., _Response]: # type: ignore
145
+ def endpoint(user: User, parent_id: ParentId, items: Collection) -> _Response:
146
+ try:
147
+ service = self.infra.with_user(user).with_parent(parent_id).build()
148
+ except DoesNotExistError as e:
149
+ return JSONResponse(RestfulResponse(self.parent).not_found(e), 404)
150
+ try:
151
+ service.replace_many(items)
152
+ except DoesNotExistError as e:
153
+ return JSONResponse(self.response.not_found(e), 404)
154
+ except ForbiddenError as e:
155
+ return JSONResponse(self.response.forbidden(e), 403)
156
+
157
+ return self.response.ok()
158
+
159
+ return endpoint
160
+
161
+ def delete_one(self, User, ParentId, ItemId) -> Callable[..., _Response]: # type: ignore
162
+ def endpoint(user: User, parent_id: ParentId, item_id: ItemId) -> _Response:
163
+ try:
164
+ service = self.infra.with_user(user).with_parent(parent_id).build()
165
+ except DoesNotExistError as e:
166
+ return JSONResponse(RestfulResponse(self.parent).not_found(e), 404)
167
+
168
+ try:
169
+ service.delete_one(item_id)
170
+ except DoesNotExistError as e:
171
+ return JSONResponse(self.response.not_found(e), 404)
172
+ except ForbiddenError as e:
173
+ return JSONResponse(self.response.forbidden(e), 403)
174
+
175
+ return self.response.ok()
176
+
177
+ return endpoint
@@ -0,0 +1,130 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Any, Iterable
5
+
6
+ from fastapi import status
7
+ from fastapi.responses import JSONResponse
8
+
9
+ from apexdevkit.error import DoesNotExistError, ExistsError, ForbiddenError
10
+ from apexdevkit.testing import RestfulName
11
+
12
+
13
+ class SuccessResponse(dict[str, Any]):
14
+ def __init__(self, status_code: int, **kwargs: Any):
15
+ super().__init__(
16
+ {
17
+ "status": "success",
18
+ "code": status_code,
19
+ "data": {**kwargs},
20
+ }
21
+ )
22
+
23
+
24
+ class ResourceFound(SuccessResponse):
25
+ def __init__(self, **kwargs: Any):
26
+ super().__init__(status_code=status.HTTP_200_OK, **kwargs)
27
+
28
+
29
+ class ResourceCreated(SuccessResponse):
30
+ def __init__(self, **kwargs: Any):
31
+ super().__init__(status_code=status.HTTP_201_CREATED, **kwargs)
32
+
33
+
34
+ class ErrorResponse(JSONResponse):
35
+ def __init__(self, status_code: int, message: str, **kwargs: Any):
36
+ content = {
37
+ "status": "fail",
38
+ "code": status_code,
39
+ "error": {"message": message},
40
+ }
41
+
42
+ if kwargs:
43
+ content["data"] = {**kwargs}
44
+
45
+ super().__init__(status_code=status_code, content=content)
46
+
47
+
48
+ class BadRequest(ErrorResponse):
49
+ def __init__(self, message: str, **kwargs: Any) -> None:
50
+ super().__init__(
51
+ status_code=status.HTTP_400_BAD_REQUEST,
52
+ message=message,
53
+ **kwargs,
54
+ )
55
+
56
+
57
+ class ResourceNotFound(ErrorResponse):
58
+ def __init__(self, message: str):
59
+ super().__init__(status_code=status.HTTP_404_NOT_FOUND, message=message)
60
+
61
+
62
+ class ResourceExists(ErrorResponse):
63
+ def __init__(self, message: str, **kwargs: Any):
64
+ super().__init__(
65
+ status_code=status.HTTP_409_CONFLICT,
66
+ message=message,
67
+ **kwargs,
68
+ )
69
+
70
+
71
+ @dataclass
72
+ class RestfulResponse:
73
+ name: RestfulName
74
+
75
+ def _response(self, code: int, data: Any, error: str = "") -> dict[str, Any]:
76
+ content: dict[str, Any] = {"code": code, "status": "success"}
77
+
78
+ if error:
79
+ content["status"] = "fail"
80
+ content["error"] = {"message": error}
81
+
82
+ match data:
83
+ case None:
84
+ content["data"] = {}
85
+ case list():
86
+ content["data"] = {self.name.plural: data, "count": len(data)}
87
+ case _:
88
+ content["data"] = {self.name.singular: data}
89
+
90
+ return content
91
+
92
+ def ok(self) -> dict[str, Any]:
93
+ return self._response(200, data=None)
94
+
95
+ def not_found(self, e: DoesNotExistError) -> dict[str, Any]:
96
+ name = self.name.singular.capitalize()
97
+
98
+ return self._response(
99
+ 404,
100
+ data={"id": str(e.id)},
101
+ error=f"An item<{name}> with id<{e.id}> does not exist.",
102
+ )
103
+
104
+ def exists(self, e: ExistsError) -> dict[str, Any]:
105
+ name = self.name.singular.capitalize()
106
+
107
+ return self._response(
108
+ 409,
109
+ data={"id": str(e.id)},
110
+ error=f"An item<{name}> with the {e} already exists.",
111
+ )
112
+
113
+ def forbidden(self, e: ForbiddenError) -> dict[str, Any]:
114
+ return self._response(
115
+ 403,
116
+ data={"id": str(e.id)},
117
+ error=e.message,
118
+ )
119
+
120
+ def created_one(self, item: Any) -> dict[str, Any]:
121
+ return self._response(201, item)
122
+
123
+ def created_many(self, items: Iterable[Any]) -> dict[str, Any]:
124
+ return self._response(201, list(items))
125
+
126
+ def found_one(self, item: Any) -> dict[str, Any]:
127
+ return self._response(200, item)
128
+
129
+ def found_many(self, items: list[Any]) -> dict[str, Any]:
130
+ return self._response(200, items)
@@ -1,104 +1,21 @@
1
- from abc import ABC, abstractmethod
2
1
  from dataclasses import dataclass, field
3
2
  from functools import cached_property
4
- from typing import Annotated, Any, Callable, Iterable, Self, TypeVar
3
+ from typing import Annotated, Any, Callable, Self, TypeVar
5
4
 
6
5
  from fastapi import APIRouter, Depends, Path
7
6
  from fastapi.responses import JSONResponse
8
7
 
9
- from apexdevkit.error import DoesNotExistError, ExistsError, ForbiddenError
8
+ from apexdevkit.fastapi.builder import RestfulServiceBuilder
9
+ from apexdevkit.fastapi.resource import RestfulResource
10
10
  from apexdevkit.fastapi.schema import RestfulSchema, SchemaFields
11
11
  from apexdevkit.fastapi.service import RawCollection, RawItem, RestfulService
12
12
  from apexdevkit.testing import RestfulName
13
13
 
14
14
  _Response = JSONResponse | dict[str, Any]
15
15
 
16
-
17
- @dataclass
18
- class RestfulResponse:
19
- name: RestfulName
20
-
21
- def _response(self, code: int, data: Any, error: str = "") -> dict[str, Any]:
22
- content: dict[str, Any] = {"code": code, "status": "success"}
23
-
24
- if error:
25
- content["status"] = "fail"
26
- content["error"] = {"message": error}
27
-
28
- match data:
29
- case None:
30
- content["data"] = {}
31
- case list():
32
- content["data"] = {self.name.plural: data, "count": len(data)}
33
- case _:
34
- content["data"] = {self.name.singular: data}
35
-
36
- return content
37
-
38
- def ok(self) -> dict[str, Any]:
39
- return self._response(200, data=None)
40
-
41
- def not_found(self, e: DoesNotExistError) -> dict[str, Any]:
42
- name = self.name.singular.capitalize()
43
-
44
- return self._response(
45
- 404,
46
- data={"id": str(e.id)},
47
- error=f"An item<{name}> with id<{e.id}> does not exist.",
48
- )
49
-
50
- def exists(self, e: ExistsError) -> dict[str, Any]:
51
- name = self.name.singular.capitalize()
52
-
53
- return self._response(
54
- 409,
55
- data={"id": str(e.id)},
56
- error=f"An item<{name}> with the {e} already exists.",
57
- )
58
-
59
- def forbidden(self, e: ForbiddenError) -> dict[str, Any]:
60
- return self._response(
61
- 403,
62
- data={"id": str(e.id)},
63
- error=e.message,
64
- )
65
-
66
- def created_one(self, item: Any) -> dict[str, Any]:
67
- return self._response(201, item)
68
-
69
- def created_many(self, items: Iterable[Any]) -> dict[str, Any]:
70
- return self._response(201, list(items))
71
-
72
- def found_one(self, item: Any) -> dict[str, Any]:
73
- return self._response(200, item)
74
-
75
- def found_many(self, items: list[Any]) -> dict[str, Any]:
76
- return self._response(200, items)
77
-
78
-
79
16
  T = TypeVar("T")
80
17
 
81
18
 
82
- @dataclass
83
- class RestfulServiceBuilder(ABC):
84
- parent_id: str = field(init=False)
85
- user: Any = field(init=False)
86
-
87
- def with_user(self, user: Any) -> "RestfulServiceBuilder":
88
- self.user = user
89
-
90
- return self
91
-
92
- def with_parent(self, identity: str) -> "RestfulServiceBuilder":
93
- self.parent_id = identity
94
-
95
- return self
96
-
97
- @abstractmethod
98
- def build(self) -> RestfulService: # pragma: no cover
99
- pass
100
-
101
-
102
19
  @dataclass
103
20
  class PreBuiltRestfulService(RestfulServiceBuilder): # pragma: no cover
104
21
  service: RestfulService
@@ -119,22 +36,23 @@ class RestfulRouter:
119
36
 
120
37
  name: RestfulName = field(init=False)
121
38
  fields: SchemaFields = field(init=False)
122
- infra: RestfulServiceBuilder = field(init=False)
123
39
 
124
40
  parent: str = field(init=False, default="")
125
41
 
42
+ infra: RestfulServiceBuilder = field(init=False)
43
+
126
44
  def __post_init__(self) -> None: # pragma: no cover
127
45
  if self.service:
128
- self.infra = PreBuiltRestfulService(self.service)
129
-
130
- @cached_property
131
- def response(self) -> RestfulResponse:
132
- return RestfulResponse(name=self.name)
46
+ self.with_infra(PreBuiltRestfulService(self.service))
133
47
 
134
48
  @cached_property
135
49
  def schema(self) -> RestfulSchema:
136
50
  return RestfulSchema(name=self.name, fields=self.fields)
137
51
 
52
+ @property
53
+ def resource(self) -> RestfulResource:
54
+ return RestfulResource(self.name, self.infra, RestfulName(self.parent))
55
+
138
56
  @property
139
57
  def id_alias(self) -> str:
140
58
  return self.name.singular + "_id"
@@ -174,7 +92,7 @@ class RestfulRouter:
174
92
  ) -> Self:
175
93
  self.router.add_api_route(
176
94
  "",
177
- self.create_one(
95
+ self.resource.create_one(
178
96
  User=Annotated[
179
97
  Any,
180
98
  Depends(extract_user),
@@ -198,26 +116,6 @@ class RestfulRouter:
198
116
 
199
117
  return self
200
118
 
201
- def create_one(self, User, ParentId, Item) -> Callable[..., _Response]: # type: ignore
202
- def endpoint(user: User, parent_id: ParentId, item: Item) -> _Response:
203
- try:
204
- service = self.infra.with_user(user).with_parent(parent_id).build()
205
- except DoesNotExistError as e:
206
- return JSONResponse(
207
- RestfulResponse(RestfulName(self.parent)).not_found(e), 404
208
- )
209
-
210
- try:
211
- item = service.create_one(item)
212
- except ExistsError as e:
213
- return JSONResponse(self.response.exists(e), 409)
214
- except ForbiddenError as e:
215
- return JSONResponse(self.response.forbidden(e), 403)
216
-
217
- return self.response.created_one(item)
218
-
219
- return endpoint
220
-
221
119
  def with_create_many_endpoint(
222
120
  self,
223
121
  is_documented: bool = True,
@@ -225,7 +123,7 @@ class RestfulRouter:
225
123
  ) -> Self:
226
124
  self.router.add_api_route(
227
125
  "/batch",
228
- self.create_many(
126
+ self.resource.create_many(
229
127
  User=Annotated[
230
128
  Any,
231
129
  Depends(extract_user),
@@ -249,24 +147,6 @@ class RestfulRouter:
249
147
 
250
148
  return self
251
149
 
252
- def create_many(self, User, ParentId, Collection) -> Callable[..., _Response]: # type: ignore
253
- def endpoint(user: User, parent_id: ParentId, items: Collection) -> _Response:
254
- try:
255
- service = self.infra.with_user(user).with_parent(parent_id).build()
256
- except DoesNotExistError as e:
257
- return JSONResponse(
258
- RestfulResponse(RestfulName(self.parent)).not_found(e), 404
259
- )
260
-
261
- try:
262
- return self.response.created_many(service.create_many(items))
263
- except ExistsError as e:
264
- return JSONResponse(self.response.exists(e), 409)
265
- except ForbiddenError as e:
266
- return JSONResponse(self.response.forbidden(e), 403)
267
-
268
- return endpoint
269
-
270
150
  def with_read_one_endpoint(
271
151
  self,
272
152
  is_documented: bool = True,
@@ -274,7 +154,7 @@ class RestfulRouter:
274
154
  ) -> Self:
275
155
  self.router.add_api_route(
276
156
  self.item_path,
277
- self.read_one(
157
+ self.resource.read_one(
278
158
  User=Annotated[
279
159
  Any,
280
160
  Depends(extract_user),
@@ -298,24 +178,6 @@ class RestfulRouter:
298
178
 
299
179
  return self
300
180
 
301
- def read_one(self, User, ParentId, ItemId) -> Callable[..., _Response]: # type: ignore
302
- def endpoint(user: User, parent_id: ParentId, item_id: ItemId) -> _Response:
303
- try:
304
- service = self.infra.with_user(user).with_parent(parent_id).build()
305
- except DoesNotExistError as e:
306
- return JSONResponse(
307
- RestfulResponse(RestfulName(self.parent)).not_found(e), 404
308
- )
309
-
310
- try:
311
- return self.response.found_one(service.read_one(item_id))
312
- except DoesNotExistError as e:
313
- return JSONResponse(self.response.not_found(e), 404)
314
- except ForbiddenError as e:
315
- return JSONResponse(self.response.forbidden(e), 403)
316
-
317
- return endpoint
318
-
319
181
  def with_read_all_endpoint(
320
182
  self,
321
183
  is_documented: bool = True,
@@ -323,7 +185,7 @@ class RestfulRouter:
323
185
  ) -> Self:
324
186
  self.router.add_api_route(
325
187
  "",
326
- self.read_all(
188
+ self.resource.read_all(
327
189
  User=Annotated[
328
190
  Any,
329
191
  Depends(extract_user),
@@ -343,21 +205,6 @@ class RestfulRouter:
343
205
 
344
206
  return self
345
207
 
346
- def read_all(self, User, ParentId) -> Callable[..., _Response]: # type: ignore
347
- def endpoint(user: User, parent_id: ParentId) -> _Response:
348
- try:
349
- service = self.infra.with_user(user).with_parent(parent_id).build()
350
- except DoesNotExistError as e:
351
- return JSONResponse(
352
- RestfulResponse(RestfulName(self.parent)).not_found(e), 404
353
- )
354
- try:
355
- return self.response.found_many(list(service.read_all()))
356
- except ForbiddenError as e:
357
- return JSONResponse(self.response.forbidden(e), 403)
358
-
359
- return endpoint
360
-
361
208
  def with_update_one_endpoint(
362
209
  self,
363
210
  is_documented: bool = True,
@@ -365,7 +212,7 @@ class RestfulRouter:
365
212
  ) -> Self:
366
213
  self.router.add_api_route(
367
214
  self.item_path,
368
- self.update_one(
215
+ self.resource.update_one(
369
216
  User=Annotated[
370
217
  Any,
371
218
  Depends(extract_user),
@@ -393,30 +240,6 @@ class RestfulRouter:
393
240
 
394
241
  return self
395
242
 
396
- def update_one(self, User, ParentId, ItemId, Updates) -> Callable[..., _Response]: # type: ignore
397
- def endpoint(
398
- user: User,
399
- parent_id: ParentId,
400
- item_id: ItemId,
401
- updates: Updates,
402
- ) -> _Response:
403
- try:
404
- service = self.infra.with_user(user).with_parent(parent_id).build()
405
- except DoesNotExistError as e:
406
- return JSONResponse(
407
- RestfulResponse(RestfulName(self.parent)).not_found(e), 404
408
- )
409
- try:
410
- service.update_one(item_id, **updates)
411
- except DoesNotExistError as e:
412
- return JSONResponse(self.response.not_found(e), 404)
413
- except ForbiddenError as e:
414
- return JSONResponse(self.response.forbidden(e), 403)
415
-
416
- return self.response.ok()
417
-
418
- return endpoint
419
-
420
243
  def with_update_many_endpoint(
421
244
  self,
422
245
  is_documented: bool = True,
@@ -424,7 +247,7 @@ class RestfulRouter:
424
247
  ) -> Self:
425
248
  self.router.add_api_route(
426
249
  "",
427
- self.update_many(
250
+ self.resource.update_many(
428
251
  User=Annotated[
429
252
  Any,
430
253
  Depends(extract_user),
@@ -448,25 +271,6 @@ class RestfulRouter:
448
271
 
449
272
  return self
450
273
 
451
- def update_many(self, User, ParentId, Collection) -> Callable[..., _Response]: # type: ignore
452
- def endpoint(user: User, parent_id: ParentId, items: Collection) -> _Response:
453
- try:
454
- service = self.infra.with_user(user).with_parent(parent_id).build()
455
- except DoesNotExistError as e:
456
- return JSONResponse(
457
- RestfulResponse(RestfulName(self.parent)).not_found(e), 404
458
- )
459
- try:
460
- service.update_many(items)
461
- except DoesNotExistError as e:
462
- return JSONResponse(self.response.not_found(e), 404)
463
- except ForbiddenError as e:
464
- return JSONResponse(self.response.forbidden(e), 403)
465
-
466
- return self.response.ok()
467
-
468
- return endpoint
469
-
470
274
  def with_replace_one_endpoint(
471
275
  self,
472
276
  is_documented: bool = True,
@@ -474,7 +278,7 @@ class RestfulRouter:
474
278
  ) -> Self:
475
279
  self.router.add_api_route(
476
280
  "",
477
- self.replace_one(
281
+ self.resource.replace_one(
478
282
  User=Annotated[
479
283
  Any,
480
284
  Depends(extract_user),
@@ -498,25 +302,6 @@ class RestfulRouter:
498
302
 
499
303
  return self
500
304
 
501
- def replace_one(self, User, ParentId, Item) -> Callable[..., _Response]: # type: ignore
502
- def endpoint(user: User, parent_id: ParentId, item: Item) -> _Response:
503
- try:
504
- service = self.infra.with_user(user).with_parent(parent_id).build()
505
- except DoesNotExistError as e:
506
- return JSONResponse(
507
- RestfulResponse(RestfulName(self.parent)).not_found(e), 404
508
- )
509
- try:
510
- service.replace_one(item)
511
- except DoesNotExistError as e:
512
- return JSONResponse(self.response.not_found(e), 404)
513
- except ForbiddenError as e:
514
- return JSONResponse(self.response.forbidden(e), 403)
515
-
516
- return self.response.ok()
517
-
518
- return endpoint
519
-
520
305
  def with_replace_many_endpoint(
521
306
  self,
522
307
  is_documented: bool = True,
@@ -524,7 +309,7 @@ class RestfulRouter:
524
309
  ) -> Self:
525
310
  self.router.add_api_route(
526
311
  "/batch",
527
- self.replace_many(
312
+ self.resource.replace_many(
528
313
  User=Annotated[
529
314
  Any,
530
315
  Depends(extract_user),
@@ -548,25 +333,6 @@ class RestfulRouter:
548
333
 
549
334
  return self
550
335
 
551
- def replace_many(self, User, ParentId, Collection) -> Callable[..., _Response]: # type: ignore
552
- def endpoint(user: User, parent_id: ParentId, items: Collection) -> _Response:
553
- try:
554
- service = self.infra.with_user(user).with_parent(parent_id).build()
555
- except DoesNotExistError as e:
556
- return JSONResponse(
557
- RestfulResponse(RestfulName(self.parent)).not_found(e), 404
558
- )
559
- try:
560
- service.replace_many(items)
561
- except DoesNotExistError as e:
562
- return JSONResponse(self.response.not_found(e), 404)
563
- except ForbiddenError as e:
564
- return JSONResponse(self.response.forbidden(e), 403)
565
-
566
- return self.response.ok()
567
-
568
- return endpoint
569
-
570
336
  def with_delete_one_endpoint(
571
337
  self,
572
338
  is_documented: bool = True,
@@ -574,7 +340,7 @@ class RestfulRouter:
574
340
  ) -> Self:
575
341
  self.router.add_api_route(
576
342
  self.item_path,
577
- self.delete_one(
343
+ self.resource.delete_one(
578
344
  User=Annotated[
579
345
  Any,
580
346
  Depends(extract_user),
@@ -598,26 +364,6 @@ class RestfulRouter:
598
364
 
599
365
  return self
600
366
 
601
- def delete_one(self, User, ParentId, ItemId) -> Callable[..., _Response]: # type: ignore
602
- def endpoint(user: User, parent_id: ParentId, item_id: ItemId) -> _Response:
603
- try:
604
- service = self.infra.with_user(user).with_parent(parent_id).build()
605
- except DoesNotExistError as e:
606
- return JSONResponse(
607
- RestfulResponse(RestfulName(self.parent)).not_found(e), 404
608
- )
609
-
610
- try:
611
- service.delete_one(item_id)
612
- except DoesNotExistError as e:
613
- return JSONResponse(self.response.not_found(e), 404)
614
- except ForbiddenError as e:
615
- return JSONResponse(self.response.forbidden(e), 403)
616
-
617
- return self.response.ok()
618
-
619
- return endpoint
620
-
621
367
  def with_sub_resource(self, **names: APIRouter) -> Self:
622
368
  for name, router in names.items():
623
369
  self.router.include_router(router, prefix=f"{self.item_path}/{name}")
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "apexdevkit"
3
- version = "1.5.20"
3
+ version = "1.5.22"
4
4
  description = "Apex Development Tools for python."
5
5
  authors = ["Apex Dev <dev@apex.ge>"]
6
6
  readme = "README.md"
@@ -1,64 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import Any
4
-
5
- from fastapi import status
6
- from fastapi.responses import JSONResponse
7
-
8
-
9
- class SuccessResponse(dict[str, Any]):
10
- def __init__(self, status_code: int, **kwargs: Any):
11
- super().__init__(
12
- {
13
- "status": "success",
14
- "code": status_code,
15
- "data": {**kwargs},
16
- }
17
- )
18
-
19
-
20
- class ResourceFound(SuccessResponse):
21
- def __init__(self, **kwargs: Any):
22
- super().__init__(status_code=status.HTTP_200_OK, **kwargs)
23
-
24
-
25
- class ResourceCreated(SuccessResponse):
26
- def __init__(self, **kwargs: Any):
27
- super().__init__(status_code=status.HTTP_201_CREATED, **kwargs)
28
-
29
-
30
- class ErrorResponse(JSONResponse):
31
- def __init__(self, status_code: int, message: str, **kwargs: Any):
32
- content = {
33
- "status": "fail",
34
- "code": status_code,
35
- "error": {"message": message},
36
- }
37
-
38
- if kwargs:
39
- content["data"] = {**kwargs}
40
-
41
- super().__init__(status_code=status_code, content=content)
42
-
43
-
44
- class BadRequest(ErrorResponse):
45
- def __init__(self, message: str, **kwargs: Any) -> None:
46
- super().__init__(
47
- status_code=status.HTTP_400_BAD_REQUEST,
48
- message=message,
49
- **kwargs,
50
- )
51
-
52
-
53
- class ResourceNotFound(ErrorResponse):
54
- def __init__(self, message: str):
55
- super().__init__(status_code=status.HTTP_404_NOT_FOUND, message=message)
56
-
57
-
58
- class ResourceExists(ErrorResponse):
59
- def __init__(self, message: str, **kwargs: Any):
60
- super().__init__(
61
- status_code=status.HTTP_409_CONFLICT,
62
- message=message,
63
- **kwargs,
64
- )
File without changes
File without changes