apexdevkit 1.3.11__tar.gz → 1.3.12__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 (32) hide show
  1. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/PKG-INFO +1 -1
  2. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/apexdevkit/fastapi/router.py +104 -16
  3. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/pyproject.toml +1 -1
  4. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/LICENSE +0 -0
  5. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/README.md +0 -0
  6. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/apexdevkit/__init__.py +0 -0
  7. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/apexdevkit/annotation/__init__.py +0 -0
  8. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/apexdevkit/annotation/deprecate.py +0 -0
  9. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/apexdevkit/error.py +0 -0
  10. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/apexdevkit/fastapi/__init__.py +0 -0
  11. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/apexdevkit/fastapi/builder.py +0 -0
  12. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/apexdevkit/fastapi/dependable.py +0 -0
  13. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/apexdevkit/fastapi/docs.py +0 -0
  14. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/apexdevkit/fastapi/response.py +0 -0
  15. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/apexdevkit/fastapi/schema.py +0 -0
  16. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/apexdevkit/fastapi/service.py +0 -0
  17. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/apexdevkit/http/__init__.py +0 -0
  18. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/apexdevkit/http/fake.py +0 -0
  19. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/apexdevkit/http/fluent.py +0 -0
  20. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/apexdevkit/http/httpx.py +0 -0
  21. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/apexdevkit/http/json.py +0 -0
  22. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/apexdevkit/http/url.py +0 -0
  23. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/apexdevkit/py.typed +0 -0
  24. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/apexdevkit/repository/__init__.py +0 -0
  25. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/apexdevkit/repository/connector.py +0 -0
  26. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/apexdevkit/repository/database.py +0 -0
  27. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/apexdevkit/repository/in_memory.py +0 -0
  28. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/apexdevkit/repository/interface.py +0 -0
  29. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/apexdevkit/testing/__init__.py +0 -0
  30. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/apexdevkit/testing/database.py +0 -0
  31. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/apexdevkit/testing/fake.py +0 -0
  32. {apexdevkit-1.3.11 → apexdevkit-1.3.12}/apexdevkit/testing/rest.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: apexdevkit
3
- Version: 1.3.11
3
+ Version: 1.3.12
4
4
  Summary: Apex Development Tools for python.
5
5
  Author: Apex Dev
6
6
  Author-email: dev@apex.ge
@@ -1,6 +1,6 @@
1
1
  from dataclasses import dataclass, field
2
2
  from functools import cached_property
3
- from typing import Annotated, Any, Iterable, Self, TypeVar
3
+ from typing import Annotated, Any, Iterable, Protocol, Self, TypeVar
4
4
 
5
5
  from fastapi import APIRouter, Depends, Path
6
6
  from fastapi.responses import JSONResponse
@@ -78,14 +78,34 @@ class RestfulResponse:
78
78
  T = TypeVar("T")
79
79
 
80
80
 
81
+ class RestfulServiceInfra(Protocol):
82
+ def service_for(self, parent_id: str) -> RestfulService:
83
+ pass
84
+
85
+
86
+ @dataclass(frozen=True)
87
+ class SingleRestfulServiceInfra:
88
+ service: RestfulService
89
+
90
+ def service_for(self, parent_id: str) -> RestfulService:
91
+ return self.service
92
+
93
+
81
94
  @dataclass
82
95
  class RestfulRouter:
83
- service: RestfulService
96
+ service: RestfulService | None = None
84
97
 
85
98
  router: APIRouter = field(default_factory=APIRouter)
86
99
 
87
100
  name: RestfulName = field(init=False)
88
101
  fields: SchemaFields = field(init=False)
102
+ infra: RestfulServiceInfra = field(init=False)
103
+
104
+ parent: str = field(init=False, default="")
105
+
106
+ def __post_init__(self) -> None:
107
+ if self.service:
108
+ self.infra = SingleRestfulServiceInfra(self.service)
89
109
 
90
110
  @cached_property
91
111
  def response(self) -> RestfulResponse:
@@ -99,6 +119,10 @@ class RestfulRouter:
99
119
  def id_alias(self) -> str:
100
120
  return self.name.singular + "_id"
101
121
 
122
+ @property
123
+ def parent_id_alias(self) -> str:
124
+ return self.parent + "_id"
125
+
102
126
  @property
103
127
  def item_path(self) -> str:
104
128
  return "/{" + self.id_alias + "}"
@@ -118,7 +142,27 @@ class RestfulRouter:
118
142
 
119
143
  return self
120
144
 
145
+ def with_parent(self, name: str) -> Self:
146
+ self.parent = name
147
+
148
+ return self
149
+
150
+ def with_service(self, value: RestfulService) -> Self:
151
+ self.infra = SingleRestfulServiceInfra(value)
152
+
153
+ return self
154
+
155
+ def with_infra(self, value: RestfulServiceInfra) -> Self:
156
+ self.infra = value
157
+
158
+ return self
159
+
121
160
  def with_create_one_endpoint(self, is_documented: bool = True) -> Self:
161
+ parent_id_type = Annotated[
162
+ str,
163
+ Path(alias=self.parent_id_alias, default_factory=str),
164
+ ]
165
+
122
166
  item_type = Annotated[
123
167
  RawItem,
124
168
  Depends(self.schema.for_create_one()),
@@ -131,9 +175,11 @@ class RestfulRouter:
131
175
  response_model=self.schema.for_item(),
132
176
  include_in_schema=is_documented,
133
177
  )
134
- def create_one(item: item_type) -> _Response:
178
+ def create_one(parent_id: parent_id_type, item: item_type) -> _Response:
179
+ service = self.infra.service_for(parent_id)
180
+
135
181
  try:
136
- item = self.service.create_one(item)
182
+ item = service.create_one(item)
137
183
  except ExistsError as e:
138
184
  return JSONResponse(self.response.exists(e), 409)
139
185
 
@@ -142,6 +188,11 @@ class RestfulRouter:
142
188
  return self
143
189
 
144
190
  def with_create_many_endpoint(self, is_documented: bool = True) -> Self:
191
+ parent_id_type = Annotated[
192
+ str,
193
+ Path(alias=self.parent_id_alias, default_factory=str),
194
+ ]
195
+
145
196
  collection_type = Annotated[
146
197
  RawCollection,
147
198
  Depends(self.schema.for_create_many()),
@@ -154,9 +205,11 @@ class RestfulRouter:
154
205
  response_model=self.schema.for_collection(),
155
206
  include_in_schema=is_documented,
156
207
  )
157
- def create_many(items: collection_type) -> _Response:
208
+ def create_many(parent_id: parent_id_type, items: collection_type) -> _Response:
209
+ service = self.infra.service_for(parent_id)
210
+
158
211
  try:
159
- return self.response.created_many(self.service.create_many(items))
212
+ return self.response.created_many(service.create_many(items))
160
213
  except ExistsError as e:
161
214
  return JSONResponse(self.response.exists(e), 409)
162
215
 
@@ -164,6 +217,10 @@ class RestfulRouter:
164
217
 
165
218
  def with_read_one_endpoint(self, is_documented: bool = True) -> Self:
166
219
  id_type = Annotated[str, Path(alias=self.id_alias)]
220
+ parent_id_type = Annotated[
221
+ str,
222
+ Path(alias=self.parent_id_alias, default_factory=str),
223
+ ]
167
224
 
168
225
  @self.router.get(
169
226
  self.item_path,
@@ -172,15 +229,22 @@ class RestfulRouter:
172
229
  response_model=self.schema.for_item(),
173
230
  include_in_schema=is_documented,
174
231
  )
175
- def read_one(item_id: id_type) -> _Response:
232
+ def read_one(parent_id: parent_id_type, item_id: id_type) -> _Response:
233
+ service = self.infra.service_for(parent_id)
234
+
176
235
  try:
177
- return self.response.found_one(self.service.read_one(item_id))
236
+ return self.response.found_one(service.read_one(item_id))
178
237
  except DoesNotExistError as e:
179
238
  return JSONResponse(self.response.not_found(e), 404)
180
239
 
181
240
  return self
182
241
 
183
242
  def with_read_all_endpoint(self, is_documented: bool = True) -> Self:
243
+ parent_id_type = Annotated[
244
+ str,
245
+ Path(alias=self.parent_id_alias, default_factory=str),
246
+ ]
247
+
184
248
  @self.router.get(
185
249
  "",
186
250
  status_code=200,
@@ -188,12 +252,18 @@ class RestfulRouter:
188
252
  response_model=self.schema.for_collection(),
189
253
  include_in_schema=is_documented,
190
254
  )
191
- def read_all() -> _Response:
192
- return self.response.found_many(list(self.service.read_all()))
255
+ def read_all(parent_id: parent_id_type) -> _Response:
256
+ service = self.infra.service_for(parent_id)
257
+
258
+ return self.response.found_many(list(service.read_all()))
193
259
 
194
260
  return self
195
261
 
196
262
  def with_update_one_endpoint(self, is_documented: bool = True) -> Self:
263
+ parent_id_type = Annotated[
264
+ str,
265
+ Path(alias=self.parent_id_alias, default_factory=str),
266
+ ]
197
267
  id_type = Annotated[str, Path(alias=self.id_alias)]
198
268
  update_type = Annotated[
199
269
  RawItem,
@@ -207,9 +277,15 @@ class RestfulRouter:
207
277
  response_model=self.schema.for_no_data(),
208
278
  include_in_schema=is_documented,
209
279
  )
210
- def update_one(item_id: id_type, updates: update_type) -> _Response:
280
+ def update_one(
281
+ parent_id: parent_id_type,
282
+ item_id: id_type,
283
+ updates: update_type,
284
+ ) -> _Response:
285
+ service = self.infra.service_for(parent_id)
286
+
211
287
  try:
212
- self.service.update_one(item_id, **updates)
288
+ service.update_one(item_id, **updates)
213
289
  except DoesNotExistError as e:
214
290
  return JSONResponse(self.response.not_found(e), 404)
215
291
  except ForbiddenError as e:
@@ -220,6 +296,10 @@ class RestfulRouter:
220
296
  return self
221
297
 
222
298
  def with_update_many_endpoint(self, is_documented: bool = True) -> Self:
299
+ parent_id_type = Annotated[
300
+ str,
301
+ Path(alias=self.parent_id_alias, default_factory=str),
302
+ ]
223
303
  collection_type = Annotated[
224
304
  RawCollection,
225
305
  Depends(self.schema.for_update_many()),
@@ -232,14 +312,20 @@ class RestfulRouter:
232
312
  response_model=self.schema.for_no_data(),
233
313
  include_in_schema=is_documented,
234
314
  )
235
- def update_many(items: collection_type) -> _Response:
236
- self.service.update_many(items)
315
+ def update_many(parent_id: parent_id_type, items: collection_type) -> _Response:
316
+ service = self.infra.service_for(parent_id)
317
+
318
+ service.update_many(items)
237
319
 
238
320
  return self.response.ok()
239
321
 
240
322
  return self
241
323
 
242
324
  def with_delete_one_endpoint(self, is_documented: bool = True) -> Self:
325
+ parent_id_type = Annotated[
326
+ str,
327
+ Path(alias=self.parent_id_alias, default_factory=str),
328
+ ]
243
329
  id_type = Annotated[str, Path(alias=self.id_alias)]
244
330
 
245
331
  @self.router.delete(
@@ -249,9 +335,11 @@ class RestfulRouter:
249
335
  response_model=self.schema.for_no_data(),
250
336
  include_in_schema=is_documented,
251
337
  )
252
- def delete_one(item_id: id_type) -> _Response:
338
+ def delete_one(parent_id: parent_id_type, item_id: id_type) -> _Response:
339
+ service = self.infra.service_for(parent_id)
340
+
253
341
  try:
254
- self.service.delete_one(item_id)
342
+ service.delete_one(item_id)
255
343
  except DoesNotExistError as e:
256
344
  return JSONResponse(self.response.not_found(e), 404)
257
345
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "apexdevkit"
3
- version = "1.3.11"
3
+ version = "1.3.12"
4
4
  description = "Apex Development Tools for python."
5
5
  authors = ["Apex Dev <dev@apex.ge>"]
6
6
  readme = "README.md"
File without changes
File without changes