apexdevkit 1.5.25__tar.gz → 1.6.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.
Files changed (36) hide show
  1. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/PKG-INFO +1 -1
  2. apexdevkit-1.6.2/apexdevkit/fastapi/dependable.py +100 -0
  3. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/fastapi/router.py +33 -103
  4. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/http/url.py +1 -1
  5. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/pyproject.toml +2 -2
  6. apexdevkit-1.5.25/apexdevkit/fastapi/dependable.py +0 -11
  7. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/LICENSE +0 -0
  8. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/README.md +0 -0
  9. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/__init__.py +0 -0
  10. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/annotation/__init__.py +0 -0
  11. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/annotation/deprecate.py +0 -0
  12. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/error.py +0 -0
  13. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/fastapi/__init__.py +0 -0
  14. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/fastapi/builder.py +0 -0
  15. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/fastapi/docs.py +0 -0
  16. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/fastapi/resource.py +0 -0
  17. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/fastapi/response.py +0 -0
  18. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/fastapi/schema.py +0 -0
  19. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/fastapi/service.py +0 -0
  20. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/formatter.py +0 -0
  21. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/http/__init__.py +0 -0
  22. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/http/fake.py +0 -0
  23. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/http/fluent.py +0 -0
  24. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/http/httpx.py +0 -0
  25. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/http/json.py +0 -0
  26. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/py.typed +0 -0
  27. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/repository/__init__.py +0 -0
  28. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/repository/base.py +0 -0
  29. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/repository/connector.py +0 -0
  30. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/repository/database.py +0 -0
  31. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/repository/in_memory.py +0 -0
  32. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/repository/interface.py +0 -0
  33. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/testing/__init__.py +0 -0
  34. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/testing/database.py +0 -0
  35. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/testing/fake.py +0 -0
  36. {apexdevkit-1.5.25 → apexdevkit-1.6.2}/apexdevkit/testing/rest.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: apexdevkit
3
- Version: 1.5.25
3
+ Version: 1.6.2
4
4
  Summary: Apex Development Tools for python.
5
5
  Author: Apex Dev
6
6
  Author-email: dev@apex.ge
@@ -0,0 +1,100 @@
1
+ from dataclasses import dataclass, field
2
+ from typing import Annotated, Any, Callable, Protocol, Self
3
+
4
+ from fastapi import Depends, Path
5
+ from fastapi.requests import Request
6
+
7
+ from apexdevkit.fastapi import RestfulServiceBuilder
8
+ from apexdevkit.fastapi.service import RestfulService
9
+ from apexdevkit.testing import RestfulName
10
+
11
+
12
+ def inject(dependency: str) -> Any: # pragma: no cover
13
+ def get(request: Request) -> Any:
14
+ return getattr(request.app.state, dependency)
15
+
16
+ return Depends(get)
17
+
18
+
19
+ class _Dependency(Protocol):
20
+ def as_dependable(self) -> type[RestfulServiceBuilder]:
21
+ pass
22
+
23
+
24
+ @dataclass
25
+ class ServiceDependency:
26
+ dependency: _Dependency
27
+
28
+ def as_dependable(self) -> type[RestfulService]:
29
+ Builder = self.dependency.as_dependable()
30
+
31
+ def _(builder: Builder) -> RestfulService:
32
+ return builder.build()
33
+
34
+ return Annotated[RestfulService, Depends(_)]
35
+
36
+
37
+ @dataclass
38
+ class ParentDependency:
39
+ parent: RestfulName
40
+ dependency: _Dependency
41
+
42
+ def as_dependable(self) -> type[RestfulServiceBuilder]:
43
+ Builder = self.dependency.as_dependable()
44
+ ParentId = Annotated[str, Path(alias=self.parent.singular + "_id")]
45
+
46
+ def _(builder: Builder, parent_id: ParentId) -> RestfulServiceBuilder:
47
+ return builder.with_parent(parent_id)
48
+
49
+ return Annotated[RestfulServiceBuilder, Depends(_)]
50
+
51
+
52
+ @dataclass
53
+ class UserDependency:
54
+ extract_user: Callable[..., Any]
55
+ dependency: _Dependency
56
+
57
+ def as_dependable(self) -> type[RestfulServiceBuilder]:
58
+ Builder = self.dependency.as_dependable()
59
+ User = Annotated[Any, Depends(self.extract_user)]
60
+
61
+ def _(builder: Builder, user: User) -> RestfulServiceBuilder:
62
+ return builder.with_user(user)
63
+
64
+ return Annotated[RestfulServiceBuilder, Depends(_)]
65
+
66
+
67
+ @dataclass
68
+ class InfraDependency:
69
+ infra: RestfulServiceBuilder
70
+
71
+ def as_dependable(self) -> type[RestfulServiceBuilder]:
72
+ def _() -> RestfulServiceBuilder:
73
+ return self.infra
74
+
75
+ return Annotated[RestfulServiceBuilder, Depends(_)]
76
+
77
+
78
+ @dataclass
79
+ class DependableBuilder:
80
+ dependency: _Dependency = field(init=False)
81
+
82
+ def from_infra(self, value: RestfulServiceBuilder) -> Self:
83
+ self.dependency = InfraDependency(value)
84
+
85
+ return self
86
+
87
+ def with_parent(self, value: RestfulName) -> Self:
88
+ dependable = DependableBuilder()
89
+ dependable.dependency = ParentDependency(value, self.dependency)
90
+
91
+ return dependable
92
+
93
+ def with_user(self, extract_user: Callable[..., Any]) -> Self:
94
+ dependable = DependableBuilder()
95
+ dependable.dependency = UserDependency(extract_user, self.dependency)
96
+
97
+ return dependable
98
+
99
+ def as_dependable(self) -> type[RestfulService]:
100
+ return ServiceDependency(self.dependency).as_dependable()
@@ -1,14 +1,12 @@
1
1
  from dataclasses import dataclass, field
2
2
  from functools import cached_property
3
- from typing import Annotated, Any, Callable, Self, Type, TypeVar
3
+ from typing import Annotated, Any, Protocol, Self, TypeVar
4
4
 
5
- from fastapi import APIRouter, Depends, HTTPException, Path
5
+ from fastapi import APIRouter, Depends, Path
6
6
  from fastapi.responses import JSONResponse
7
7
 
8
- from apexdevkit.error import DoesNotExistError
9
8
  from apexdevkit.fastapi.builder import RestfulServiceBuilder
10
9
  from apexdevkit.fastapi.resource import RestfulResource
11
- from apexdevkit.fastapi.response import RestfulResponse
12
10
  from apexdevkit.fastapi.schema import RestfulSchema, SchemaFields
13
11
  from apexdevkit.fastapi.service import RawCollection, RawItem, RestfulService
14
12
  from apexdevkit.testing import RestfulName
@@ -18,6 +16,11 @@ _Response = JSONResponse | dict[str, Any]
18
16
  T = TypeVar("T")
19
17
 
20
18
 
19
+ class Dependable(Protocol):
20
+ def as_dependable(self) -> type[RestfulService]:
21
+ pass
22
+
23
+
21
24
  @dataclass
22
25
  class PreBuiltRestfulService(RestfulServiceBuilder): # pragma: no cover
23
26
  service: RestfulService
@@ -26,27 +29,13 @@ class PreBuiltRestfulService(RestfulServiceBuilder): # pragma: no cover
26
29
  return self.service
27
30
 
28
31
 
29
- def no_user() -> None:
30
- pass
31
-
32
-
33
32
  @dataclass
34
33
  class RestfulRouter:
35
- service: RestfulService | None = None
36
-
37
34
  router: APIRouter = field(default_factory=APIRouter)
38
35
 
39
36
  name: RestfulName = field(init=False)
40
37
  fields: SchemaFields = field(init=False)
41
38
 
42
- parent: str = field(init=False, default="")
43
-
44
- infra: RestfulServiceBuilder = field(init=False)
45
-
46
- def __post_init__(self) -> None: # pragma: no cover
47
- if self.service:
48
- self.with_infra(PreBuiltRestfulService(self.service))
49
-
50
39
  @cached_property
51
40
  def schema(self) -> RestfulSchema:
52
41
  return RestfulSchema(name=self.name, fields=self.fields)
@@ -59,10 +48,6 @@ class RestfulRouter:
59
48
  def id_alias(self) -> str:
60
49
  return self.name.singular + "_id"
61
50
 
62
- @property
63
- def parent_id_alias(self) -> str:
64
- return self.parent + "_id"
65
-
66
51
  @property
67
52
  def item_path(self) -> str:
68
53
  return "/{" + self.id_alias + "}"
@@ -77,25 +62,15 @@ class RestfulRouter:
77
62
 
78
63
  return self
79
64
 
80
- def with_parent(self, name: str) -> Self:
81
- self.parent = name
82
-
83
- return self
84
-
85
- def with_infra(self, value: RestfulServiceBuilder) -> Self:
86
- self.infra = value
87
-
88
- return self
89
-
90
65
  def with_create_one_endpoint(
91
66
  self,
67
+ dependable: Dependable,
92
68
  is_documented: bool = True,
93
- extract_user: Callable[..., Any] = no_user,
94
69
  ) -> Self:
95
70
  self.router.add_api_route(
96
71
  "",
97
72
  self.resource.create_one(
98
- Service=self._service(extract_user),
73
+ Service=dependable.as_dependable(),
99
74
  Item=Annotated[
100
75
  RawItem,
101
76
  Depends(self.schema.for_create_one()),
@@ -112,14 +87,12 @@ class RestfulRouter:
112
87
  return self
113
88
 
114
89
  def with_create_many_endpoint(
115
- self,
116
- is_documented: bool = True,
117
- extract_user: Callable[..., Any] = no_user,
90
+ self, dependable: Dependable, is_documented: bool = True
118
91
  ) -> Self:
119
92
  self.router.add_api_route(
120
93
  "/batch",
121
94
  self.resource.create_many(
122
- Service=self._service(extract_user),
95
+ Service=dependable.as_dependable(),
123
96
  Collection=Annotated[
124
97
  RawCollection,
125
98
  Depends(self.schema.for_create_many()),
@@ -136,14 +109,12 @@ class RestfulRouter:
136
109
  return self
137
110
 
138
111
  def with_read_one_endpoint(
139
- self,
140
- is_documented: bool = True,
141
- extract_user: Callable[..., Any] = no_user,
112
+ self, dependable: Dependable, is_documented: bool = True
142
113
  ) -> Self:
143
114
  self.router.add_api_route(
144
115
  self.item_path,
145
116
  self.resource.read_one(
146
- Service=self._service(extract_user),
117
+ Service=dependable.as_dependable(),
147
118
  ItemId=Annotated[
148
119
  str,
149
120
  Path(alias=self.id_alias),
@@ -160,14 +131,12 @@ class RestfulRouter:
160
131
  return self
161
132
 
162
133
  def with_read_all_endpoint(
163
- self,
164
- is_documented: bool = True,
165
- extract_user: Callable[..., Any] = no_user,
134
+ self, dependable: Dependable, is_documented: bool = True
166
135
  ) -> Self:
167
136
  self.router.add_api_route(
168
137
  "",
169
138
  self.resource.read_all(
170
- Service=self._service(extract_user),
139
+ Service=dependable.as_dependable(),
171
140
  ),
172
141
  methods=["GET"],
173
142
  status_code=200,
@@ -180,14 +149,12 @@ class RestfulRouter:
180
149
  return self
181
150
 
182
151
  def with_update_one_endpoint(
183
- self,
184
- is_documented: bool = True,
185
- extract_user: Callable[..., Any] = no_user,
152
+ self, dependable: Dependable, is_documented: bool = True
186
153
  ) -> Self:
187
154
  self.router.add_api_route(
188
155
  self.item_path,
189
156
  self.resource.update_one(
190
- Service=self._service(extract_user),
157
+ Service=dependable.as_dependable(),
191
158
  ItemId=Annotated[
192
159
  str,
193
160
  Path(alias=self.id_alias),
@@ -208,14 +175,12 @@ class RestfulRouter:
208
175
  return self
209
176
 
210
177
  def with_update_many_endpoint(
211
- self,
212
- is_documented: bool = True,
213
- extract_user: Callable[..., Any] = no_user,
178
+ self, dependable: Dependable, is_documented: bool = True
214
179
  ) -> Self:
215
180
  self.router.add_api_route(
216
181
  "",
217
182
  self.resource.update_many(
218
- Service=self._service(extract_user),
183
+ Service=dependable.as_dependable(),
219
184
  Collection=Annotated[
220
185
  RawCollection,
221
186
  Depends(self.schema.for_update_many()),
@@ -232,14 +197,12 @@ class RestfulRouter:
232
197
  return self
233
198
 
234
199
  def with_replace_one_endpoint(
235
- self,
236
- is_documented: bool = True,
237
- extract_user: Callable[..., Any] = no_user,
200
+ self, dependable: Dependable, is_documented: bool = True
238
201
  ) -> Self:
239
202
  self.router.add_api_route(
240
203
  "",
241
204
  self.resource.replace_one(
242
- Service=self._service(extract_user),
205
+ Service=dependable.as_dependable(),
243
206
  Item=Annotated[
244
207
  RawItem,
245
208
  Depends(self.schema.for_replace_one()),
@@ -256,14 +219,12 @@ class RestfulRouter:
256
219
  return self
257
220
 
258
221
  def with_replace_many_endpoint(
259
- self,
260
- is_documented: bool = True,
261
- extract_user: Callable[..., Any] = no_user,
222
+ self, dependable: Dependable, is_documented: bool = True
262
223
  ) -> Self:
263
224
  self.router.add_api_route(
264
225
  "/batch",
265
226
  self.resource.replace_many(
266
- Service=self._service(extract_user),
227
+ Service=dependable.as_dependable(),
267
228
  Collection=Annotated[
268
229
  RawCollection,
269
230
  Depends(self.schema.for_replace_many()),
@@ -280,14 +241,12 @@ class RestfulRouter:
280
241
  return self
281
242
 
282
243
  def with_delete_one_endpoint(
283
- self,
284
- is_documented: bool = True,
285
- extract_user: Callable[..., Any] = no_user,
244
+ self, dependable: Dependable, is_documented: bool = True
286
245
  ) -> Self:
287
246
  self.router.add_api_route(
288
247
  self.item_path,
289
248
  self.resource.delete_one(
290
- Service=self._service(extract_user),
249
+ Service=dependable.as_dependable(),
291
250
  ItemId=Annotated[
292
251
  str,
293
252
  Path(alias=self.id_alias),
@@ -309,45 +268,16 @@ class RestfulRouter:
309
268
 
310
269
  return self
311
270
 
312
- def default(self) -> Self:
271
+ def default(self, dependable: Dependable) -> Self:
313
272
  return (
314
- self.with_create_one_endpoint()
315
- .with_create_many_endpoint()
316
- .with_read_one_endpoint()
317
- .with_read_all_endpoint()
318
- .with_update_one_endpoint()
319
- .with_update_many_endpoint()
320
- .with_delete_one_endpoint()
273
+ self.with_create_one_endpoint(dependable)
274
+ .with_create_many_endpoint(dependable)
275
+ .with_read_one_endpoint(dependable)
276
+ .with_read_all_endpoint(dependable)
277
+ .with_update_one_endpoint(dependable)
278
+ .with_update_many_endpoint(dependable)
279
+ .with_delete_one_endpoint(dependable)
321
280
  )
322
281
 
323
282
  def build(self) -> APIRouter:
324
283
  return self.router
325
-
326
- def _service(
327
- self, extract_user: Callable[..., Any] = no_user
328
- ) -> Type[RestfulService]:
329
- User = Annotated[Any, Depends(extract_user)]
330
- ParentId = Annotated[str, Path(alias=self.parent_id_alias)]
331
-
332
- def srv_child(user: User, parent_id: ParentId) -> RestfulService:
333
- try:
334
- return self.infra.with_user(user).with_parent(parent_id).build()
335
- except DoesNotExistError as e:
336
- raise HTTPException(
337
- status_code=404,
338
- detail=RestfulResponse(RestfulName(self.parent)).not_found(e),
339
- )
340
-
341
- def srv_root(user: User) -> RestfulService:
342
- try:
343
- return self.infra.with_user(user).build()
344
- except DoesNotExistError as e:
345
- raise HTTPException(
346
- status_code=404,
347
- detail=RestfulResponse(RestfulName(self.parent)).not_found(e),
348
- )
349
-
350
- if self.parent:
351
- return Annotated[RestfulService, Depends(srv_child)] # type: ignore
352
- else:
353
- return Annotated[RestfulService, Depends(srv_root)] # type: ignore
@@ -6,4 +6,4 @@ class HttpUrl:
6
6
  value: str
7
7
 
8
8
  def __add__(self, endpoint: str) -> str:
9
- return self.value.strip("/") + "/" + endpoint.strip("/")
9
+ return (self.value.strip("/") + "/" + endpoint.strip("/")).strip("/")
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "apexdevkit"
3
- version = "1.5.25"
3
+ version = "1.6.2"
4
4
  description = "Apex Development Tools for python."
5
5
  authors = ["Apex Dev <dev@apex.ge>"]
6
6
  readme = "README.md"
@@ -25,7 +25,7 @@ ruff = "*"
25
25
  python_version = "3.11"
26
26
  ignore_missing_imports = true
27
27
  strict = true
28
- exclude = ["apexdevkit/fastapi/schema.py"]
28
+ exclude = ["apexdevkit/fastapi/schema.py", "apexdevkit/fastapi/dependable.py"]
29
29
 
30
30
  [tool.ruff]
31
31
  target-version = "py311"
@@ -1,11 +0,0 @@
1
- from typing import Any
2
-
3
- from fastapi import Depends
4
- from fastapi.requests import Request
5
-
6
-
7
- def inject(dependency: str) -> Any: # pragma: no cover
8
- def get(request: Request) -> Any:
9
- return getattr(request.app.state, dependency)
10
-
11
- return Depends(get)
File without changes
File without changes