apexdevkit 1.3.15__tar.gz → 1.4.2__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.3.15 → apexdevkit-1.4.2}/PKG-INFO +1 -1
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/apexdevkit/fastapi/router.py +103 -30
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/pyproject.toml +1 -1
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/LICENSE +0 -0
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/README.md +0 -0
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/apexdevkit/__init__.py +0 -0
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/apexdevkit/annotation/__init__.py +0 -0
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/apexdevkit/annotation/deprecate.py +0 -0
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/apexdevkit/error.py +0 -0
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/apexdevkit/fastapi/__init__.py +0 -0
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/apexdevkit/fastapi/builder.py +0 -0
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/apexdevkit/fastapi/dependable.py +0 -0
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/apexdevkit/fastapi/docs.py +0 -0
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/apexdevkit/fastapi/response.py +0 -0
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/apexdevkit/fastapi/schema.py +0 -0
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/apexdevkit/fastapi/service.py +0 -0
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/apexdevkit/http/__init__.py +0 -0
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/apexdevkit/http/fake.py +0 -0
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/apexdevkit/http/fluent.py +0 -0
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/apexdevkit/http/httpx.py +0 -0
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/apexdevkit/http/json.py +0 -0
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/apexdevkit/http/url.py +0 -0
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/apexdevkit/py.typed +0 -0
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/apexdevkit/repository/__init__.py +0 -0
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/apexdevkit/repository/connector.py +0 -0
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/apexdevkit/repository/database.py +0 -0
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/apexdevkit/repository/in_memory.py +0 -0
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/apexdevkit/repository/interface.py +0 -0
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/apexdevkit/testing/__init__.py +0 -0
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/apexdevkit/testing/database.py +0 -0
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/apexdevkit/testing/fake.py +0 -0
- {apexdevkit-1.3.15 → apexdevkit-1.4.2}/apexdevkit/testing/rest.py +0 -0
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
1
2
|
from dataclasses import dataclass, field
|
|
2
3
|
from functools import cached_property
|
|
3
|
-
from typing import Annotated, Any,
|
|
4
|
+
from typing import Annotated, Any, Callable, Iterable, Self, TypeVar
|
|
4
5
|
|
|
5
6
|
from fastapi import APIRouter, Depends, Path
|
|
7
|
+
from fastapi.requests import Request
|
|
6
8
|
from fastapi.responses import JSONResponse
|
|
7
9
|
|
|
8
10
|
from apexdevkit.error import DoesNotExistError, ExistsError, ForbiddenError
|
|
@@ -78,19 +80,38 @@ class RestfulResponse:
|
|
|
78
80
|
T = TypeVar("T")
|
|
79
81
|
|
|
80
82
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
+
@dataclass
|
|
84
|
+
class RestfulServiceBuilder(ABC):
|
|
85
|
+
parent_id: str = field(init=False)
|
|
86
|
+
user: Any = field(init=False)
|
|
87
|
+
|
|
88
|
+
def with_user(self, user: Any) -> "RestfulServiceBuilder":
|
|
89
|
+
self.user = user
|
|
90
|
+
|
|
91
|
+
return self
|
|
92
|
+
|
|
93
|
+
def with_parent(self, identity: str) -> "RestfulServiceBuilder":
|
|
94
|
+
self.parent_id = identity
|
|
95
|
+
|
|
96
|
+
return self
|
|
97
|
+
|
|
98
|
+
@abstractmethod
|
|
99
|
+
def build(self) -> RestfulService:
|
|
83
100
|
pass
|
|
84
101
|
|
|
85
102
|
|
|
86
|
-
@dataclass
|
|
87
|
-
class
|
|
103
|
+
@dataclass
|
|
104
|
+
class PreBuiltRestfulService(RestfulServiceBuilder):
|
|
88
105
|
service: RestfulService
|
|
89
106
|
|
|
90
|
-
def
|
|
107
|
+
def build(self) -> RestfulService:
|
|
91
108
|
return self.service
|
|
92
109
|
|
|
93
110
|
|
|
111
|
+
def no_user(request: Request) -> None:
|
|
112
|
+
pass
|
|
113
|
+
|
|
114
|
+
|
|
94
115
|
@dataclass
|
|
95
116
|
class RestfulRouter:
|
|
96
117
|
service: RestfulService | None = None
|
|
@@ -99,13 +120,13 @@ class RestfulRouter:
|
|
|
99
120
|
|
|
100
121
|
name: RestfulName = field(init=False)
|
|
101
122
|
fields: SchemaFields = field(init=False)
|
|
102
|
-
infra:
|
|
123
|
+
infra: RestfulServiceBuilder = field(init=False)
|
|
103
124
|
|
|
104
125
|
parent: str = field(init=False, default="")
|
|
105
126
|
|
|
106
127
|
def __post_init__(self) -> None:
|
|
107
128
|
if self.service:
|
|
108
|
-
self.infra =
|
|
129
|
+
self.infra = PreBuiltRestfulService(self.service)
|
|
109
130
|
|
|
110
131
|
@cached_property
|
|
111
132
|
def response(self) -> RestfulResponse:
|
|
@@ -148,16 +169,20 @@ class RestfulRouter:
|
|
|
148
169
|
return self
|
|
149
170
|
|
|
150
171
|
def with_service(self, value: RestfulService) -> Self:
|
|
151
|
-
self.infra =
|
|
172
|
+
self.infra = PreBuiltRestfulService(value)
|
|
152
173
|
|
|
153
174
|
return self
|
|
154
175
|
|
|
155
|
-
def with_infra(self, value:
|
|
176
|
+
def with_infra(self, value: RestfulServiceBuilder) -> Self:
|
|
156
177
|
self.infra = value
|
|
157
178
|
|
|
158
179
|
return self
|
|
159
180
|
|
|
160
|
-
def with_create_one_endpoint(
|
|
181
|
+
def with_create_one_endpoint(
|
|
182
|
+
self,
|
|
183
|
+
is_documented: bool = True,
|
|
184
|
+
extract_user: Callable[[Request], Any] = no_user,
|
|
185
|
+
) -> Self:
|
|
161
186
|
parent_id_type = Annotated[
|
|
162
187
|
str,
|
|
163
188
|
Path(alias=self.parent_id_alias, default_factory=str),
|
|
@@ -175,9 +200,13 @@ class RestfulRouter:
|
|
|
175
200
|
response_model=self.schema.for_item(),
|
|
176
201
|
include_in_schema=is_documented,
|
|
177
202
|
)
|
|
178
|
-
def create_one(
|
|
203
|
+
def create_one(
|
|
204
|
+
user: Annotated[Any, Depends(extract_user)],
|
|
205
|
+
parent_id: parent_id_type,
|
|
206
|
+
item: item_type,
|
|
207
|
+
) -> _Response:
|
|
179
208
|
try:
|
|
180
|
-
service = self.infra.
|
|
209
|
+
service = self.infra.with_user(user).with_parent(parent_id).build()
|
|
181
210
|
except DoesNotExistError as e:
|
|
182
211
|
return JSONResponse(
|
|
183
212
|
RestfulResponse(RestfulName(self.parent)).not_found(e), 404
|
|
@@ -192,7 +221,11 @@ class RestfulRouter:
|
|
|
192
221
|
|
|
193
222
|
return self
|
|
194
223
|
|
|
195
|
-
def with_create_many_endpoint(
|
|
224
|
+
def with_create_many_endpoint(
|
|
225
|
+
self,
|
|
226
|
+
is_documented: bool = True,
|
|
227
|
+
extract_user: Callable[[Request], Any] = no_user,
|
|
228
|
+
) -> Self:
|
|
196
229
|
parent_id_type = Annotated[
|
|
197
230
|
str,
|
|
198
231
|
Path(alias=self.parent_id_alias, default_factory=str),
|
|
@@ -210,9 +243,13 @@ class RestfulRouter:
|
|
|
210
243
|
response_model=self.schema.for_collection(),
|
|
211
244
|
include_in_schema=is_documented,
|
|
212
245
|
)
|
|
213
|
-
def create_many(
|
|
246
|
+
def create_many(
|
|
247
|
+
user: Annotated[Any, Depends(extract_user)],
|
|
248
|
+
parent_id: parent_id_type,
|
|
249
|
+
items: collection_type,
|
|
250
|
+
) -> _Response:
|
|
214
251
|
try:
|
|
215
|
-
service = self.infra.
|
|
252
|
+
service = self.infra.with_user(user).with_parent(parent_id).build()
|
|
216
253
|
except DoesNotExistError as e:
|
|
217
254
|
return JSONResponse(
|
|
218
255
|
RestfulResponse(RestfulName(self.parent)).not_found(e), 404
|
|
@@ -225,7 +262,11 @@ class RestfulRouter:
|
|
|
225
262
|
|
|
226
263
|
return self
|
|
227
264
|
|
|
228
|
-
def with_read_one_endpoint(
|
|
265
|
+
def with_read_one_endpoint(
|
|
266
|
+
self,
|
|
267
|
+
is_documented: bool = True,
|
|
268
|
+
extract_user: Callable[[Request], Any] = no_user,
|
|
269
|
+
) -> Self:
|
|
229
270
|
id_type = Annotated[str, Path(alias=self.id_alias)]
|
|
230
271
|
parent_id_type = Annotated[
|
|
231
272
|
str,
|
|
@@ -239,8 +280,12 @@ class RestfulRouter:
|
|
|
239
280
|
response_model=self.schema.for_item(),
|
|
240
281
|
include_in_schema=is_documented,
|
|
241
282
|
)
|
|
242
|
-
def read_one(
|
|
243
|
-
|
|
283
|
+
def read_one(
|
|
284
|
+
user: Annotated[Any, Depends(extract_user)],
|
|
285
|
+
parent_id: parent_id_type,
|
|
286
|
+
item_id: id_type,
|
|
287
|
+
) -> _Response:
|
|
288
|
+
service = self.infra.with_user(user).with_parent(parent_id).build()
|
|
244
289
|
|
|
245
290
|
try:
|
|
246
291
|
return self.response.found_one(service.read_one(item_id))
|
|
@@ -249,7 +294,11 @@ class RestfulRouter:
|
|
|
249
294
|
|
|
250
295
|
return self
|
|
251
296
|
|
|
252
|
-
def with_read_all_endpoint(
|
|
297
|
+
def with_read_all_endpoint(
|
|
298
|
+
self,
|
|
299
|
+
is_documented: bool = True,
|
|
300
|
+
extract_user: Callable[[Request], Any] = no_user,
|
|
301
|
+
) -> Self:
|
|
253
302
|
parent_id_type = Annotated[
|
|
254
303
|
str,
|
|
255
304
|
Path(alias=self.parent_id_alias, default_factory=str),
|
|
@@ -262,14 +311,21 @@ class RestfulRouter:
|
|
|
262
311
|
response_model=self.schema.for_collection(),
|
|
263
312
|
include_in_schema=is_documented,
|
|
264
313
|
)
|
|
265
|
-
def read_all(
|
|
266
|
-
|
|
314
|
+
def read_all(
|
|
315
|
+
user: Annotated[Any, Depends(extract_user)],
|
|
316
|
+
parent_id: parent_id_type,
|
|
317
|
+
) -> _Response:
|
|
318
|
+
service = self.infra.with_user(user).with_parent(parent_id).build()
|
|
267
319
|
|
|
268
320
|
return self.response.found_many(list(service.read_all()))
|
|
269
321
|
|
|
270
322
|
return self
|
|
271
323
|
|
|
272
|
-
def with_update_one_endpoint(
|
|
324
|
+
def with_update_one_endpoint(
|
|
325
|
+
self,
|
|
326
|
+
is_documented: bool = True,
|
|
327
|
+
extract_user: Callable[[Request], Any] = no_user,
|
|
328
|
+
) -> Self:
|
|
273
329
|
parent_id_type = Annotated[
|
|
274
330
|
str,
|
|
275
331
|
Path(alias=self.parent_id_alias, default_factory=str),
|
|
@@ -288,11 +344,12 @@ class RestfulRouter:
|
|
|
288
344
|
include_in_schema=is_documented,
|
|
289
345
|
)
|
|
290
346
|
def update_one(
|
|
347
|
+
user: Annotated[Any, Depends(extract_user)],
|
|
291
348
|
parent_id: parent_id_type,
|
|
292
349
|
item_id: id_type,
|
|
293
350
|
updates: update_type,
|
|
294
351
|
) -> _Response:
|
|
295
|
-
service = self.infra.
|
|
352
|
+
service = self.infra.with_user(user).with_parent(parent_id).build()
|
|
296
353
|
|
|
297
354
|
try:
|
|
298
355
|
service.update_one(item_id, **updates)
|
|
@@ -305,7 +362,11 @@ class RestfulRouter:
|
|
|
305
362
|
|
|
306
363
|
return self
|
|
307
364
|
|
|
308
|
-
def with_update_many_endpoint(
|
|
365
|
+
def with_update_many_endpoint(
|
|
366
|
+
self,
|
|
367
|
+
is_documented: bool = True,
|
|
368
|
+
extract_user: Callable[[Request], Any] = no_user,
|
|
369
|
+
) -> Self:
|
|
309
370
|
parent_id_type = Annotated[
|
|
310
371
|
str,
|
|
311
372
|
Path(alias=self.parent_id_alias, default_factory=str),
|
|
@@ -322,8 +383,12 @@ class RestfulRouter:
|
|
|
322
383
|
response_model=self.schema.for_no_data(),
|
|
323
384
|
include_in_schema=is_documented,
|
|
324
385
|
)
|
|
325
|
-
def update_many(
|
|
326
|
-
|
|
386
|
+
def update_many(
|
|
387
|
+
user: Annotated[Any, Depends(extract_user)],
|
|
388
|
+
parent_id: parent_id_type,
|
|
389
|
+
items: collection_type,
|
|
390
|
+
) -> _Response:
|
|
391
|
+
service = self.infra.with_user(user).with_parent(parent_id).build()
|
|
327
392
|
|
|
328
393
|
service.update_many(items)
|
|
329
394
|
|
|
@@ -331,7 +396,11 @@ class RestfulRouter:
|
|
|
331
396
|
|
|
332
397
|
return self
|
|
333
398
|
|
|
334
|
-
def with_delete_one_endpoint(
|
|
399
|
+
def with_delete_one_endpoint(
|
|
400
|
+
self,
|
|
401
|
+
is_documented: bool = True,
|
|
402
|
+
extract_user: Callable[[Request], Any] = no_user,
|
|
403
|
+
) -> Self:
|
|
335
404
|
parent_id_type = Annotated[
|
|
336
405
|
str,
|
|
337
406
|
Path(alias=self.parent_id_alias, default_factory=str),
|
|
@@ -345,8 +414,12 @@ class RestfulRouter:
|
|
|
345
414
|
response_model=self.schema.for_no_data(),
|
|
346
415
|
include_in_schema=is_documented,
|
|
347
416
|
)
|
|
348
|
-
def delete_one(
|
|
349
|
-
|
|
417
|
+
def delete_one(
|
|
418
|
+
user: Annotated[Any, Depends(extract_user)],
|
|
419
|
+
parent_id: parent_id_type,
|
|
420
|
+
item_id: id_type,
|
|
421
|
+
) -> _Response:
|
|
422
|
+
service = self.infra.with_user(user).with_parent(parent_id).build()
|
|
350
423
|
|
|
351
424
|
try:
|
|
352
425
|
service.delete_one(item_id)
|
|
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
|