apexdevkit 1.24.3__tar.gz → 1.25.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.
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/PKG-INFO +1 -1
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/fastapi/router.py +61 -55
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/formatter.py +3 -1
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/pyproject.toml +1 -1
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/LICENSE +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/README.md +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/__init__.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/annotation/__init__.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/annotation/deprecate.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/date.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/environment.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/error.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/fastapi/__init__.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/fastapi/builder.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/fastapi/dependable.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/fastapi/docs.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/fastapi/name.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/fastapi/resource.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/fastapi/response.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/fastapi/schema.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/fastapi/service.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/fluent.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/http/__init__.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/http/fake.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/http/fluent.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/http/httpx/__init__.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/http/httpx/client.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/http/httpx/hooks.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/http/json.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/http/url.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/id.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/key_fn.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/py.typed +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/query/__init__.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/query/generator.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/query/query.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/repository/__init__.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/repository/base.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/repository/connector.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/repository/database.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/repository/decorator.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/repository/in_memory.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/repository/interface.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/repository/mssql.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/repository/repository.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/repository/sql.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/repository/sqlite.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/server.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/synchronization.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/testing/__init__.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/testing/database.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/testing/fake.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/testing/rest.py +0 -0
- {apexdevkit-1.24.3 → apexdevkit-1.25.1}/apexdevkit/value.py +0 -0
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from dataclasses import dataclass, field
|
|
2
2
|
from enum import Enum
|
|
3
|
-
from functools import cached_property
|
|
4
3
|
from typing import Annotated, Any, Protocol, Self, TypeVar
|
|
5
4
|
|
|
6
5
|
from fastapi import APIRouter, Depends, Path, Query
|
|
@@ -25,16 +24,28 @@ class Dependency(Protocol): # pragma: no cover
|
|
|
25
24
|
|
|
26
25
|
@dataclass
|
|
27
26
|
class RestfulRouter:
|
|
27
|
+
name: RestfulName
|
|
28
|
+
|
|
29
|
+
parent: RestfulName | None = None
|
|
28
30
|
router: APIRouter = field(default_factory=APIRouter)
|
|
29
31
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
_schema: RestfulSchema = field(init=False)
|
|
33
|
+
_dependency: Dependency | None = field(init=False, default=None)
|
|
34
|
+
|
|
35
|
+
@classmethod
|
|
36
|
+
def named(cls, singular: str, *, plural: str | None = None) -> "RestfulRouter":
|
|
37
|
+
if plural:
|
|
38
|
+
return cls(RestfulName(singular, plural))
|
|
39
|
+
|
|
40
|
+
return cls(RestfulName(singular))
|
|
41
|
+
|
|
42
|
+
def child_of(self, singular: str, *, plural: str | None = None) -> Self:
|
|
43
|
+
self.parent = RestfulName(singular)
|
|
32
44
|
|
|
33
|
-
|
|
45
|
+
if plural:
|
|
46
|
+
self.parent = RestfulName(singular, plural)
|
|
34
47
|
|
|
35
|
-
|
|
36
|
-
def schema(self) -> RestfulSchema:
|
|
37
|
-
return RestfulSchema(name=self.name, fields=self.fields)
|
|
48
|
+
return self
|
|
38
49
|
|
|
39
50
|
@property
|
|
40
51
|
def resource(self) -> RestfulResource:
|
|
@@ -48,13 +59,8 @@ class RestfulRouter:
|
|
|
48
59
|
def item_path(self) -> str:
|
|
49
60
|
return "/{" + self.id_alias + "}"
|
|
50
61
|
|
|
51
|
-
def with_name(self, value: RestfulName) -> Self:
|
|
52
|
-
self.name = value
|
|
53
|
-
|
|
54
|
-
return self
|
|
55
|
-
|
|
56
62
|
def with_fields(self, value: SchemaFields) -> Self:
|
|
57
|
-
self.
|
|
63
|
+
self._schema = RestfulSchema(name=self.name, fields=value)
|
|
58
64
|
|
|
59
65
|
return self
|
|
60
66
|
|
|
@@ -63,12 +69,12 @@ class RestfulRouter:
|
|
|
63
69
|
|
|
64
70
|
return self
|
|
65
71
|
|
|
66
|
-
def
|
|
67
|
-
self.
|
|
72
|
+
def with_default_dependency(self, value: Dependency) -> Self:
|
|
73
|
+
self._dependency = value
|
|
68
74
|
|
|
69
75
|
return self
|
|
70
76
|
|
|
71
|
-
def
|
|
77
|
+
def with_create_one(
|
|
72
78
|
self,
|
|
73
79
|
dependency: Dependency | None = None,
|
|
74
80
|
is_documented: bool = True,
|
|
@@ -79,20 +85,20 @@ class RestfulRouter:
|
|
|
79
85
|
Service=self._resolve(dependency),
|
|
80
86
|
Item=Annotated[
|
|
81
87
|
RawItem,
|
|
82
|
-
Depends(self.
|
|
88
|
+
Depends(self._schema.for_create_one()),
|
|
83
89
|
],
|
|
84
90
|
),
|
|
85
91
|
methods=["POST"],
|
|
86
92
|
status_code=201,
|
|
87
93
|
responses={409: {}},
|
|
88
|
-
response_model=self.
|
|
94
|
+
response_model=self._schema.for_item(),
|
|
89
95
|
include_in_schema=is_documented,
|
|
90
96
|
summary="Create One",
|
|
91
97
|
)
|
|
92
98
|
|
|
93
99
|
return self
|
|
94
100
|
|
|
95
|
-
def
|
|
101
|
+
def with_create_many(
|
|
96
102
|
self,
|
|
97
103
|
dependency: Dependency | None = None,
|
|
98
104
|
is_documented: bool = True,
|
|
@@ -103,20 +109,20 @@ class RestfulRouter:
|
|
|
103
109
|
Service=self._resolve(dependency),
|
|
104
110
|
Collection=Annotated[
|
|
105
111
|
RawCollection,
|
|
106
|
-
Depends(self.
|
|
112
|
+
Depends(self._schema.for_create_many()),
|
|
107
113
|
],
|
|
108
114
|
),
|
|
109
115
|
methods=["POST"],
|
|
110
116
|
status_code=201,
|
|
111
117
|
responses={409: {}},
|
|
112
|
-
response_model=self.
|
|
118
|
+
response_model=self._schema.for_collection(),
|
|
113
119
|
include_in_schema=is_documented,
|
|
114
120
|
summary="Create Many",
|
|
115
121
|
)
|
|
116
122
|
|
|
117
123
|
return self
|
|
118
124
|
|
|
119
|
-
def
|
|
125
|
+
def with_read_one(
|
|
120
126
|
self,
|
|
121
127
|
dependency: Dependency | None = None,
|
|
122
128
|
is_documented: bool = True,
|
|
@@ -133,14 +139,14 @@ class RestfulRouter:
|
|
|
133
139
|
methods=["GET"],
|
|
134
140
|
status_code=200,
|
|
135
141
|
responses={404: {}},
|
|
136
|
-
response_model=self.
|
|
142
|
+
response_model=self._schema.for_item(),
|
|
137
143
|
include_in_schema=is_documented,
|
|
138
144
|
summary="Read One",
|
|
139
145
|
)
|
|
140
146
|
|
|
141
147
|
return self
|
|
142
148
|
|
|
143
|
-
def
|
|
149
|
+
def with_read_many(
|
|
144
150
|
self,
|
|
145
151
|
query: FluentDict[Any],
|
|
146
152
|
dependency: Dependency | None = None,
|
|
@@ -157,14 +163,14 @@ class RestfulRouter:
|
|
|
157
163
|
methods=["GET"],
|
|
158
164
|
status_code=200,
|
|
159
165
|
responses={},
|
|
160
|
-
response_model=self.
|
|
166
|
+
response_model=self._schema.for_collection(),
|
|
161
167
|
include_in_schema=is_documented,
|
|
162
168
|
summary="Read Many",
|
|
163
169
|
)
|
|
164
170
|
|
|
165
171
|
return self
|
|
166
172
|
|
|
167
|
-
def
|
|
173
|
+
def with_filter(
|
|
168
174
|
self,
|
|
169
175
|
dependency: Dependency | None = None,
|
|
170
176
|
is_documented: bool = True,
|
|
@@ -173,19 +179,19 @@ class RestfulRouter:
|
|
|
173
179
|
"/filter",
|
|
174
180
|
self.resource.filter_with(
|
|
175
181
|
Service=self._resolve(dependency),
|
|
176
|
-
QueryOptions=Annotated[RawItem, Depends(self.
|
|
182
|
+
QueryOptions=Annotated[RawItem, Depends(self._schema.for_filters())],
|
|
177
183
|
),
|
|
178
184
|
methods=["POST"],
|
|
179
185
|
status_code=200,
|
|
180
186
|
responses={},
|
|
181
|
-
response_model=self.
|
|
187
|
+
response_model=self._schema.for_collection(),
|
|
182
188
|
include_in_schema=is_documented,
|
|
183
189
|
summary="Read Filtered",
|
|
184
190
|
)
|
|
185
191
|
|
|
186
192
|
return self
|
|
187
193
|
|
|
188
|
-
def
|
|
194
|
+
def with_aggregation(
|
|
189
195
|
self,
|
|
190
196
|
dependency: Dependency | None = None,
|
|
191
197
|
is_documented: bool = True,
|
|
@@ -195,20 +201,20 @@ class RestfulRouter:
|
|
|
195
201
|
self.resource.aggregation_with(
|
|
196
202
|
Service=self._resolve(dependency),
|
|
197
203
|
FilterOptions=Annotated[
|
|
198
|
-
RawItem, Depends(self.
|
|
204
|
+
RawItem, Depends(self._schema.for_aggregation())
|
|
199
205
|
],
|
|
200
206
|
),
|
|
201
207
|
methods=["POST"],
|
|
202
208
|
status_code=200,
|
|
203
209
|
responses={},
|
|
204
|
-
response_model=self.
|
|
210
|
+
response_model=self._schema.for_aggregation_result(),
|
|
205
211
|
include_in_schema=is_documented,
|
|
206
212
|
summary="Aggregation",
|
|
207
213
|
)
|
|
208
214
|
|
|
209
215
|
return self
|
|
210
216
|
|
|
211
|
-
def
|
|
217
|
+
def with_read_all(
|
|
212
218
|
self,
|
|
213
219
|
dependency: Dependency | None = None,
|
|
214
220
|
is_documented: bool = True,
|
|
@@ -219,14 +225,14 @@ class RestfulRouter:
|
|
|
219
225
|
methods=["GET"],
|
|
220
226
|
status_code=200,
|
|
221
227
|
responses={},
|
|
222
|
-
response_model=self.
|
|
228
|
+
response_model=self._schema.for_collection(),
|
|
223
229
|
include_in_schema=is_documented,
|
|
224
230
|
summary="Read All",
|
|
225
231
|
)
|
|
226
232
|
|
|
227
233
|
return self
|
|
228
234
|
|
|
229
|
-
def
|
|
235
|
+
def with_update_one(
|
|
230
236
|
self,
|
|
231
237
|
dependency: Dependency | None = None,
|
|
232
238
|
is_documented: bool = True,
|
|
@@ -241,20 +247,20 @@ class RestfulRouter:
|
|
|
241
247
|
],
|
|
242
248
|
Updates=Annotated[
|
|
243
249
|
RawItem,
|
|
244
|
-
Depends(self.
|
|
250
|
+
Depends(self._schema.for_update_one()),
|
|
245
251
|
],
|
|
246
252
|
),
|
|
247
253
|
methods=["PATCH"],
|
|
248
254
|
status_code=200,
|
|
249
255
|
responses={404: {}},
|
|
250
|
-
response_model=self.
|
|
256
|
+
response_model=self._schema.for_no_data(),
|
|
251
257
|
include_in_schema=is_documented,
|
|
252
258
|
summary="Update One",
|
|
253
259
|
)
|
|
254
260
|
|
|
255
261
|
return self
|
|
256
262
|
|
|
257
|
-
def
|
|
263
|
+
def with_update_many(
|
|
258
264
|
self,
|
|
259
265
|
dependency: Dependency | None = None,
|
|
260
266
|
is_documented: bool = True,
|
|
@@ -265,20 +271,20 @@ class RestfulRouter:
|
|
|
265
271
|
Service=self._resolve(dependency),
|
|
266
272
|
Collection=Annotated[
|
|
267
273
|
RawCollection,
|
|
268
|
-
Depends(self.
|
|
274
|
+
Depends(self._schema.for_update_many()),
|
|
269
275
|
],
|
|
270
276
|
),
|
|
271
277
|
methods=["PATCH"],
|
|
272
278
|
status_code=200,
|
|
273
279
|
responses={},
|
|
274
|
-
response_model=self.
|
|
280
|
+
response_model=self._schema.for_no_data(),
|
|
275
281
|
include_in_schema=is_documented,
|
|
276
282
|
summary="Update Many",
|
|
277
283
|
)
|
|
278
284
|
|
|
279
285
|
return self
|
|
280
286
|
|
|
281
|
-
def
|
|
287
|
+
def with_replace_one(
|
|
282
288
|
self,
|
|
283
289
|
dependency: Dependency | None = None,
|
|
284
290
|
is_documented: bool = True,
|
|
@@ -289,20 +295,20 @@ class RestfulRouter:
|
|
|
289
295
|
Service=self._resolve(dependency),
|
|
290
296
|
Item=Annotated[
|
|
291
297
|
RawItem,
|
|
292
|
-
Depends(self.
|
|
298
|
+
Depends(self._schema.for_replace_one()),
|
|
293
299
|
],
|
|
294
300
|
),
|
|
295
301
|
methods=["PUT"],
|
|
296
302
|
status_code=200,
|
|
297
303
|
responses={404: {}},
|
|
298
|
-
response_model=self.
|
|
304
|
+
response_model=self._schema.for_no_data(),
|
|
299
305
|
include_in_schema=is_documented,
|
|
300
306
|
summary="Replace One",
|
|
301
307
|
)
|
|
302
308
|
|
|
303
309
|
return self
|
|
304
310
|
|
|
305
|
-
def
|
|
311
|
+
def with_replace_many(
|
|
306
312
|
self,
|
|
307
313
|
dependency: Dependency | None = None,
|
|
308
314
|
is_documented: bool = True,
|
|
@@ -313,20 +319,20 @@ class RestfulRouter:
|
|
|
313
319
|
Service=self._resolve(dependency),
|
|
314
320
|
Collection=Annotated[
|
|
315
321
|
RawCollection,
|
|
316
|
-
Depends(self.
|
|
322
|
+
Depends(self._schema.for_replace_many()),
|
|
317
323
|
],
|
|
318
324
|
),
|
|
319
325
|
methods=["PUT"],
|
|
320
326
|
status_code=200,
|
|
321
327
|
responses={},
|
|
322
|
-
response_model=self.
|
|
328
|
+
response_model=self._schema.for_no_data(),
|
|
323
329
|
include_in_schema=is_documented,
|
|
324
330
|
summary="Replace Many",
|
|
325
331
|
)
|
|
326
332
|
|
|
327
333
|
return self
|
|
328
334
|
|
|
329
|
-
def
|
|
335
|
+
def with_delete_one(
|
|
330
336
|
self,
|
|
331
337
|
dependency: Dependency | None = None,
|
|
332
338
|
is_documented: bool = True,
|
|
@@ -343,7 +349,7 @@ class RestfulRouter:
|
|
|
343
349
|
methods=["DELETE"],
|
|
344
350
|
status_code=200,
|
|
345
351
|
responses={404: {}},
|
|
346
|
-
response_model=self.
|
|
352
|
+
response_model=self._schema.for_no_data(),
|
|
347
353
|
include_in_schema=is_documented,
|
|
348
354
|
summary="Delete One",
|
|
349
355
|
)
|
|
@@ -358,20 +364,20 @@ class RestfulRouter:
|
|
|
358
364
|
|
|
359
365
|
def default(self) -> Self:
|
|
360
366
|
return (
|
|
361
|
-
self.
|
|
362
|
-
.
|
|
363
|
-
.
|
|
364
|
-
.
|
|
365
|
-
.
|
|
366
|
-
.
|
|
367
|
-
.
|
|
367
|
+
self.with_create_one()
|
|
368
|
+
.with_create_many()
|
|
369
|
+
.with_read_one()
|
|
370
|
+
.with_read_all()
|
|
371
|
+
.with_update_one()
|
|
372
|
+
.with_update_many()
|
|
373
|
+
.with_delete_one()
|
|
368
374
|
)
|
|
369
375
|
|
|
370
376
|
def build(self) -> APIRouter:
|
|
371
377
|
return self.router
|
|
372
378
|
|
|
373
379
|
def _resolve(self, dependency: Dependency | None) -> type[RestfulService]:
|
|
374
|
-
resolved = dependency or self.
|
|
380
|
+
resolved = dependency or self._dependency
|
|
375
381
|
assert resolved, "One of default or endpoint dependency must be specified"
|
|
376
382
|
|
|
377
383
|
return resolved.as_dependable()
|
|
@@ -87,7 +87,9 @@ class DataclassFormatter(Generic[_TargetT]):
|
|
|
87
87
|
|
|
88
88
|
def load(self, raw: Mapping[str, Any]) -> _TargetT:
|
|
89
89
|
raw = FluentDict[Any](deepcopy(raw)).select(
|
|
90
|
-
*self.resource.__annotations__.keys()
|
|
90
|
+
*self.resource.__annotations__.keys(),
|
|
91
|
+
"id",
|
|
92
|
+
"idempotency_id",
|
|
91
93
|
)
|
|
92
94
|
|
|
93
95
|
for key in fields(self.resource): # type: ignore
|
|
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
|
|
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
|