apexdevkit 1.5.24__tar.gz → 1.6.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.
Files changed (36) hide show
  1. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/PKG-INFO +1 -1
  2. apexdevkit-1.6.1/apexdevkit/fastapi/dependable.py +100 -0
  3. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/fastapi/router.py +33 -103
  4. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/http/httpx.py +13 -10
  5. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/testing/rest.py +87 -53
  6. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/pyproject.toml +2 -2
  7. apexdevkit-1.5.24/apexdevkit/fastapi/dependable.py +0 -11
  8. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/LICENSE +0 -0
  9. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/README.md +0 -0
  10. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/__init__.py +0 -0
  11. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/annotation/__init__.py +0 -0
  12. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/annotation/deprecate.py +0 -0
  13. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/error.py +0 -0
  14. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/fastapi/__init__.py +0 -0
  15. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/fastapi/builder.py +0 -0
  16. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/fastapi/docs.py +0 -0
  17. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/fastapi/resource.py +0 -0
  18. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/fastapi/response.py +0 -0
  19. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/fastapi/schema.py +0 -0
  20. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/fastapi/service.py +0 -0
  21. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/formatter.py +0 -0
  22. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/http/__init__.py +0 -0
  23. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/http/fake.py +0 -0
  24. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/http/fluent.py +0 -0
  25. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/http/json.py +0 -0
  26. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/http/url.py +0 -0
  27. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/py.typed +0 -0
  28. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/repository/__init__.py +0 -0
  29. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/repository/base.py +0 -0
  30. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/repository/connector.py +0 -0
  31. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/repository/database.py +0 -0
  32. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/repository/in_memory.py +0 -0
  33. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/repository/interface.py +0 -0
  34. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/testing/__init__.py +0 -0
  35. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/testing/database.py +0 -0
  36. {apexdevkit-1.5.24 → apexdevkit-1.6.1}/apexdevkit/testing/fake.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: apexdevkit
3
- Version: 1.5.24
3
+ Version: 1.6.1
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
@@ -4,34 +4,37 @@ from dataclasses import dataclass, field
4
4
  from typing import Any, Iterator, Mapping, Self
5
5
 
6
6
  import httpx
7
+ from httpx import Client
7
8
 
8
9
  from apexdevkit.http.fluent import HttpMethod, HttpResponse
9
10
  from apexdevkit.http.json import JsonDict
10
- from apexdevkit.http.url import HttpUrl
11
+
12
+
13
+ def default_config() -> HttpxConfig:
14
+ return HttpxConfig()
11
15
 
12
16
 
13
17
  @dataclass(frozen=True)
14
18
  class Httpx:
15
- url: HttpUrl
16
- config: HttpxConfig
19
+ client: httpx.Client
20
+
21
+ config: HttpxConfig = field(default_factory=default_config)
17
22
 
18
23
  @classmethod
19
24
  def create_for(cls, url: str) -> Self:
20
- return cls(HttpUrl(url), HttpxConfig())
25
+ return cls(Client(base_url=url), HttpxConfig())
21
26
 
22
27
  def with_header(self, key: str, value: str) -> Httpx:
23
- return Httpx(self.url, self.config.with_header(key, value))
28
+ return Httpx(self.client, self.config.with_header(key, value))
24
29
 
25
30
  def with_param(self, key: str, value: str) -> Httpx:
26
- return Httpx(self.url, self.config.with_param(key, value))
31
+ return Httpx(self.client, self.config.with_param(key, value))
27
32
 
28
33
  def with_json(self, value: JsonDict) -> Httpx:
29
- return Httpx(self.url, self.config.with_json(value))
34
+ return Httpx(self.client, self.config.with_json(value))
30
35
 
31
36
  def request(self, method: HttpMethod, endpoint: str) -> HttpResponse:
32
- return _HttpxResponse(
33
- httpx.request(method.name, self.url + endpoint, **self.config)
34
- )
37
+ return _HttpxResponse(self.client.request(method.name, endpoint, **self.config))
35
38
 
36
39
 
37
40
  @dataclass
@@ -5,67 +5,76 @@ from dataclasses import dataclass, field
5
5
  from functools import cached_property
6
6
  from typing import Any, Iterable, Self
7
7
 
8
- import httpx
9
8
  from fastapi.testclient import TestClient
10
9
 
11
- from apexdevkit.http import HttpUrl, JsonDict
10
+ from apexdevkit.http import Http, HttpUrl, JsonDict
11
+ from apexdevkit.http.fluent import HttpMethod, HttpResponse
12
+ from apexdevkit.http.httpx import Httpx
12
13
 
13
14
 
14
15
  @dataclass
15
16
  class RestResource:
16
- http: TestClient
17
+ http: TestClient | Http
17
18
  name: RestfulName
18
19
 
20
+ def __post_init__(self) -> None:
21
+ if isinstance(self.http, TestClient):
22
+ self.http = Httpx(self.http)
23
+
24
+ @property
25
+ def _http(self) -> Http:
26
+ assert not isinstance(self.http, TestClient)
27
+
28
+ return self.http
29
+
19
30
  def create_one(self) -> CreateOne:
20
- return CreateOne(self.name, self.http)
31
+ return CreateOne(self.name, self._http)
21
32
 
22
33
  def create_many(self) -> CreateMany:
23
- return CreateMany(self.name, self.http)
34
+ return CreateMany(self.name, self._http)
24
35
 
25
36
  def read_one(self) -> ReadOne:
26
- return ReadOne(self.name, self.http)
37
+ return ReadOne(self.name, self._http)
27
38
 
28
39
  def read_all(self) -> ReadAll:
29
- return ReadAll(self.name, self.http)
40
+ return ReadAll(self.name, self._http)
30
41
 
31
42
  def update_one(self) -> UpdateOne:
32
- return UpdateOne(self.name, self.http)
43
+ return UpdateOne(self.name, self._http)
33
44
 
34
45
  def update_many(self) -> UpdateMany:
35
- return UpdateMany(self.name, self.http)
46
+ return UpdateMany(self.name, self._http)
36
47
 
37
48
  def replace_one(self) -> ReplaceOne:
38
- return ReplaceOne(self.name, self.http)
49
+ return ReplaceOne(self.name, self._http)
39
50
 
40
51
  def replace_many(self) -> ReplaceMany:
41
- return ReplaceMany(self.name, self.http)
52
+ return ReplaceMany(self.name, self._http)
42
53
 
43
54
  def delete_one(self) -> DeleteOne:
44
- return DeleteOne(self.name, self.http)
55
+ return DeleteOne(self.name, self._http)
45
56
 
46
57
 
47
58
  @dataclass
48
59
  class RestCollection(RestResource):
49
60
  def sub_resource(self, name: str) -> RestItem:
50
- return RestItem(
51
- TestClient(
52
- self.http.app,
53
- base_url=HttpUrl(str(self.http.base_url)) + self.name.plural,
54
- ),
55
- RestfulName(name),
56
- )
61
+ assert isinstance(self.http, Httpx), "sub resource only works with Httpx"
62
+
63
+ client = self.http.client
64
+ client.base_url = client.base_url.join(self.name.plural)
65
+
66
+ return RestItem(self.http, RestfulName(name))
57
67
 
58
68
 
59
69
  @dataclass
60
70
  class RestItem(RestResource):
61
71
  def sub_resource(self, name: str) -> RestItem:
62
- return RestItem(
63
- TestClient(
64
- self.http.app,
65
- base_url=HttpUrl(str(self.http.base_url)) + self.name.singular,
66
- ),
67
- RestfulName(name),
68
- )
72
+ assert isinstance(self.http, Httpx), "sub resource only works with Httpx"
73
+
74
+ client = self.http.client
75
+ client.base_url = client.base_url.join(self.name.plural)
76
+
77
+ return RestItem(self.http, RestfulName(name))
69
78
 
70
79
 
71
80
  @dataclass
@@ -103,11 +112,11 @@ def as_plural(singular: str) -> str:
103
112
  @dataclass
104
113
  class RestRequest:
105
114
  resource: RestfulName
106
- http: TestClient
115
+ http: Http
107
116
 
108
117
  @abstractmethod
109
118
  @cached_property
110
- def response(self) -> httpx.Response: # pragma: no cover
119
+ def response(self) -> HttpResponse: # pragma: no cover
111
120
  pass
112
121
 
113
122
  def unpack(self) -> JsonDict:
@@ -122,7 +131,7 @@ class RestRequest:
122
131
  return RestResponse(
123
132
  resource=self.resource,
124
133
  json=JsonDict(self.response.json()),
125
- http_code=self.response.status_code,
134
+ http_code=self.response.code(),
126
135
  )
127
136
 
128
137
 
@@ -136,8 +145,11 @@ class CreateOne(RestRequest):
136
145
  return self
137
146
 
138
147
  @cached_property
139
- def response(self) -> httpx.Response:
140
- return self.http.post(self.resource + "", json=dict(self.data))
148
+ def response(self) -> HttpResponse:
149
+ return self.http.with_json(self.data).request(
150
+ method=HttpMethod.post,
151
+ endpoint=self.resource + "",
152
+ )
141
153
 
142
154
 
143
155
  @dataclass
@@ -145,8 +157,11 @@ class ReadOne(RestRequest):
145
157
  item_id: str = field(init=False)
146
158
 
147
159
  @cached_property
148
- def response(self) -> httpx.Response:
149
- return self.http.get(self.resource + str(self.item_id))
160
+ def response(self) -> HttpResponse:
161
+ return self.http.request(
162
+ method=HttpMethod.get,
163
+ endpoint=self.resource + str(self.item_id),
164
+ )
150
165
 
151
166
  def with_id(self, value: Any) -> Self:
152
167
  self.item_id = str(value)
@@ -159,8 +174,12 @@ class ReadAll(RestRequest):
159
174
  params: dict[str, Any] = field(init=False, default_factory=dict)
160
175
 
161
176
  @cached_property
162
- def response(self) -> httpx.Response:
163
- return self.http.get(self.resource + "", params=self.params)
177
+ def response(self) -> HttpResponse:
178
+ http = self.http
179
+ for param, value in self.params.items():
180
+ http = http.with_param(param, value)
181
+
182
+ return http.request(method=HttpMethod.get, endpoint=self.resource + "")
164
183
 
165
184
  def with_params(self, **kwargs: Any) -> Self:
166
185
  self.params = {**kwargs}
@@ -174,8 +193,11 @@ class UpdateOne(RestRequest):
174
193
  data: JsonDict = field(init=False)
175
194
 
176
195
  @cached_property
177
- def response(self) -> httpx.Response:
178
- return self.http.patch(self.resource + str(self.item_id), json=dict(self.data))
196
+ def response(self) -> HttpResponse:
197
+ return self.http.with_json(self.data).request(
198
+ method=HttpMethod.patch,
199
+ endpoint=self.resource + str(self.item_id),
200
+ )
179
201
 
180
202
  def with_id(self, value: Any) -> Self:
181
203
  self.item_id = str(value)
@@ -193,8 +215,11 @@ class ReplaceOne(RestRequest):
193
215
  data: JsonDict = field(init=False)
194
216
 
195
217
  @cached_property
196
- def response(self) -> httpx.Response:
197
- return self.http.put(self.resource + "", json=dict(self.data))
218
+ def response(self) -> HttpResponse:
219
+ return self.http.with_json(self.data).request(
220
+ method=HttpMethod.put,
221
+ endpoint=self.resource + "",
222
+ )
198
223
 
199
224
  def from_data(self, value: JsonDict) -> Self:
200
225
  self.data = value
@@ -207,10 +232,12 @@ class CreateMany(RestRequest):
207
232
  data: list[JsonDict] = field(default_factory=list)
208
233
 
209
234
  @cached_property
210
- def response(self) -> httpx.Response:
211
- return self.http.post(
212
- self.resource + "batch",
213
- json={self.resource.plural: [dict(data) for data in self.data]},
235
+ def response(self) -> HttpResponse:
236
+ json = JsonDict({self.resource.plural: [dict(data) for data in self.data]})
237
+
238
+ return self.http.with_json(json).request(
239
+ method=HttpMethod.post,
240
+ endpoint=self.resource + "batch",
214
241
  )
215
242
 
216
243
  def from_data(self, value: JsonDict) -> Self:
@@ -227,10 +254,12 @@ class UpdateMany(RestRequest):
227
254
  data: list[JsonDict] = field(default_factory=list)
228
255
 
229
256
  @cached_property
230
- def response(self) -> httpx.Response:
231
- return self.http.patch(
232
- self.resource + "",
233
- json={self.resource.plural: [dict(data) for data in self.data]},
257
+ def response(self) -> HttpResponse:
258
+ json = JsonDict({self.resource.plural: [dict(data) for data in self.data]})
259
+
260
+ return self.http.with_json(json).request(
261
+ method=HttpMethod.patch,
262
+ endpoint=self.resource + "",
234
263
  )
235
264
 
236
265
  def from_data(self, value: JsonDict) -> Self:
@@ -247,10 +276,12 @@ class ReplaceMany(RestRequest):
247
276
  data: list[JsonDict] = field(default_factory=list)
248
277
 
249
278
  @cached_property
250
- def response(self) -> httpx.Response:
251
- return self.http.put(
252
- self.resource + "batch",
253
- json={self.resource.plural: [dict(data) for data in self.data]},
279
+ def response(self) -> HttpResponse:
280
+ json = JsonDict({self.resource.plural: [dict(data) for data in self.data]})
281
+
282
+ return self.http.with_json(json).request(
283
+ method=HttpMethod.put,
284
+ endpoint=self.resource + "batch",
254
285
  )
255
286
 
256
287
  def from_data(self, value: JsonDict) -> Self:
@@ -267,8 +298,11 @@ class DeleteOne(RestRequest):
267
298
  item_id: str = field(init=False)
268
299
 
269
300
  @cached_property
270
- def response(self) -> httpx.Response:
271
- return self.http.delete(self.resource + str(self.item_id))
301
+ def response(self) -> HttpResponse:
302
+ return self.http.request(
303
+ method=HttpMethod.delete,
304
+ endpoint=self.resource + str(self.item_id),
305
+ )
272
306
 
273
307
  def with_id(self, value: Any) -> Self:
274
308
  self.item_id = str(value)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "apexdevkit"
3
- version = "1.5.24"
3
+ version = "1.6.1"
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