apexdevkit 1.5.23__tar.gz → 1.5.25__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.23 → apexdevkit-1.5.25}/PKG-INFO +1 -1
  2. apexdevkit-1.5.25/apexdevkit/fastapi/resource.py +129 -0
  3. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/fastapi/router.py +49 -44
  4. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/http/httpx.py +13 -10
  5. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/testing/rest.py +87 -53
  6. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/pyproject.toml +1 -1
  7. apexdevkit-1.5.23/apexdevkit/fastapi/resource.py +0 -342
  8. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/LICENSE +0 -0
  9. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/README.md +0 -0
  10. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/__init__.py +0 -0
  11. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/annotation/__init__.py +0 -0
  12. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/annotation/deprecate.py +0 -0
  13. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/error.py +0 -0
  14. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/fastapi/__init__.py +0 -0
  15. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/fastapi/builder.py +0 -0
  16. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/fastapi/dependable.py +0 -0
  17. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/fastapi/docs.py +0 -0
  18. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/fastapi/response.py +0 -0
  19. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/fastapi/schema.py +0 -0
  20. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/fastapi/service.py +0 -0
  21. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/formatter.py +0 -0
  22. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/http/__init__.py +0 -0
  23. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/http/fake.py +0 -0
  24. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/http/fluent.py +0 -0
  25. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/http/json.py +0 -0
  26. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/http/url.py +0 -0
  27. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/py.typed +0 -0
  28. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/repository/__init__.py +0 -0
  29. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/repository/base.py +0 -0
  30. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/repository/connector.py +0 -0
  31. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/repository/database.py +0 -0
  32. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/repository/in_memory.py +0 -0
  33. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/repository/interface.py +0 -0
  34. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/testing/__init__.py +0 -0
  35. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/testing/database.py +0 -0
  36. {apexdevkit-1.5.23 → apexdevkit-1.5.25}/apexdevkit/testing/fake.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: apexdevkit
3
- Version: 1.5.23
3
+ Version: 1.5.25
4
4
  Summary: Apex Development Tools for python.
5
5
  Author: Apex Dev
6
6
  Author-email: dev@apex.ge
@@ -0,0 +1,129 @@
1
+ from dataclasses import dataclass
2
+ from functools import cached_property
3
+ from typing import Any, Callable
4
+
5
+ from starlette.responses import JSONResponse
6
+
7
+ from apexdevkit.error import DoesNotExistError, ExistsError, ForbiddenError
8
+ from apexdevkit.fastapi.response import RestfulResponse
9
+ from apexdevkit.testing import RestfulName
10
+
11
+ _Response = JSONResponse | dict[str, Any]
12
+
13
+
14
+ @dataclass
15
+ class RestfulResource:
16
+ name: RestfulName
17
+
18
+ @cached_property
19
+ def response(self) -> RestfulResponse:
20
+ return RestfulResponse(name=self.name)
21
+
22
+ def create_one(self, Service, Item) -> Callable[..., _Response]: # type: ignore
23
+ def endpoint(service: Service, item: Item) -> _Response:
24
+ try:
25
+ item = service.create_one(item)
26
+ except ExistsError as e:
27
+ return JSONResponse(self.response.exists(e), 409)
28
+ except ForbiddenError as e:
29
+ return JSONResponse(self.response.forbidden(e), 403)
30
+
31
+ return self.response.created_one(item)
32
+
33
+ return endpoint
34
+
35
+ def create_many(self, Service, Collection) -> Callable[..., _Response]: # type: ignore
36
+ def endpoint(service: Service, items: Collection) -> _Response:
37
+ try:
38
+ return self.response.created_many(service.create_many(items))
39
+ except ExistsError as e:
40
+ return JSONResponse(self.response.exists(e), 409)
41
+ except ForbiddenError as e:
42
+ return JSONResponse(self.response.forbidden(e), 403)
43
+
44
+ return endpoint
45
+
46
+ def read_one(self, Service, ItemId) -> Callable[..., _Response]: # type: ignore
47
+ def endpoint(service: Service, item_id: ItemId) -> _Response:
48
+ try:
49
+ return self.response.found_one(service.read_one(item_id))
50
+ except DoesNotExistError as e:
51
+ return JSONResponse(self.response.not_found(e), 404)
52
+ except ForbiddenError as e:
53
+ return JSONResponse(self.response.forbidden(e), 403)
54
+
55
+ return endpoint
56
+
57
+ def read_all(self, Service) -> Callable[..., _Response]: # type: ignore
58
+ def endpoint(service: Service) -> _Response:
59
+ try:
60
+ return self.response.found_many(list(service.read_all()))
61
+ except ForbiddenError as e:
62
+ return JSONResponse(self.response.forbidden(e), 403)
63
+
64
+ return endpoint
65
+
66
+ def update_one(self, Service, ItemId, Updates) -> Callable[..., _Response]: # type: ignore
67
+ def endpoint(service: Service, item_id: ItemId, updates: Updates) -> _Response:
68
+ try:
69
+ service.update_one(item_id, **updates)
70
+ except DoesNotExistError as e:
71
+ return JSONResponse(self.response.not_found(e), 404)
72
+ except ForbiddenError as e:
73
+ return JSONResponse(self.response.forbidden(e), 403)
74
+
75
+ return self.response.ok()
76
+
77
+ return endpoint
78
+
79
+ def update_many(self, Service, Collection) -> Callable[..., _Response]: # type: ignore
80
+ def endpoint(service: Service, items: Collection) -> _Response:
81
+ try:
82
+ service.update_many(items)
83
+ except DoesNotExistError as e:
84
+ return JSONResponse(self.response.not_found(e), 404)
85
+ except ForbiddenError as e:
86
+ return JSONResponse(self.response.forbidden(e), 403)
87
+
88
+ return self.response.ok()
89
+
90
+ return endpoint
91
+
92
+ def replace_one(self, Service, Item) -> Callable[..., _Response]: # type: ignore
93
+ def endpoint(service: Service, item: Item) -> _Response:
94
+ try:
95
+ service.replace_one(item)
96
+ except DoesNotExistError as e:
97
+ return JSONResponse(self.response.not_found(e), 404)
98
+ except ForbiddenError as e:
99
+ return JSONResponse(self.response.forbidden(e), 403)
100
+
101
+ return self.response.ok()
102
+
103
+ return endpoint
104
+
105
+ def replace_many(self, Service, Collection) -> Callable[..., _Response]: # type: ignore
106
+ def endpoint(service: Service, items: Collection) -> _Response:
107
+ try:
108
+ service.replace_many(items)
109
+ except DoesNotExistError as e:
110
+ return JSONResponse(self.response.not_found(e), 404)
111
+ except ForbiddenError as e:
112
+ return JSONResponse(self.response.forbidden(e), 403)
113
+
114
+ return self.response.ok()
115
+
116
+ return endpoint
117
+
118
+ def delete_one(self, Service, ItemId) -> Callable[..., _Response]: # type: ignore
119
+ def endpoint(service: Service, item_id: ItemId) -> _Response:
120
+ try:
121
+ service.delete_one(item_id)
122
+ except DoesNotExistError as e:
123
+ return JSONResponse(self.response.not_found(e), 404)
124
+ except ForbiddenError as e:
125
+ return JSONResponse(self.response.forbidden(e), 403)
126
+
127
+ return self.response.ok()
128
+
129
+ return endpoint
@@ -1,12 +1,14 @@
1
1
  from dataclasses import dataclass, field
2
2
  from functools import cached_property
3
- from typing import Annotated, Any, Callable, Self, TypeVar
3
+ from typing import Annotated, Any, Callable, Self, Type, TypeVar
4
4
 
5
- from fastapi import APIRouter, Depends, Path
5
+ from fastapi import APIRouter, Depends, HTTPException, Path
6
6
  from fastapi.responses import JSONResponse
7
7
 
8
+ from apexdevkit.error import DoesNotExistError
8
9
  from apexdevkit.fastapi.builder import RestfulServiceBuilder
9
- from apexdevkit.fastapi.resource import RestfulRootResource, RestfulSubResource
10
+ from apexdevkit.fastapi.resource import RestfulResource
11
+ from apexdevkit.fastapi.response import RestfulResponse
10
12
  from apexdevkit.fastapi.schema import RestfulSchema, SchemaFields
11
13
  from apexdevkit.fastapi.service import RawCollection, RawItem, RestfulService
12
14
  from apexdevkit.testing import RestfulName
@@ -50,16 +52,17 @@ class RestfulRouter:
50
52
  return RestfulSchema(name=self.name, fields=self.fields)
51
53
 
52
54
  @property
53
- def resource(self) -> RestfulRootResource | RestfulSubResource:
54
- if not self.parent:
55
- return RestfulRootResource(self.name, self.infra)
56
-
57
- return RestfulSubResource(self.name, self.infra, RestfulName(self.parent))
55
+ def resource(self) -> RestfulResource:
56
+ return RestfulResource(self.name)
58
57
 
59
58
  @property
60
59
  def id_alias(self) -> str:
61
60
  return self.name.singular + "_id"
62
61
 
62
+ @property
63
+ def parent_id_alias(self) -> str:
64
+ return self.parent + "_id"
65
+
63
66
  @property
64
67
  def item_path(self) -> str:
65
68
  return "/{" + self.id_alias + "}"
@@ -92,10 +95,7 @@ class RestfulRouter:
92
95
  self.router.add_api_route(
93
96
  "",
94
97
  self.resource.create_one(
95
- User=Annotated[
96
- Any,
97
- Depends(extract_user),
98
- ],
98
+ Service=self._service(extract_user),
99
99
  Item=Annotated[
100
100
  RawItem,
101
101
  Depends(self.schema.for_create_one()),
@@ -119,10 +119,7 @@ class RestfulRouter:
119
119
  self.router.add_api_route(
120
120
  "/batch",
121
121
  self.resource.create_many(
122
- User=Annotated[
123
- Any,
124
- Depends(extract_user),
125
- ],
122
+ Service=self._service(extract_user),
126
123
  Collection=Annotated[
127
124
  RawCollection,
128
125
  Depends(self.schema.for_create_many()),
@@ -146,10 +143,7 @@ class RestfulRouter:
146
143
  self.router.add_api_route(
147
144
  self.item_path,
148
145
  self.resource.read_one(
149
- User=Annotated[
150
- Any,
151
- Depends(extract_user),
152
- ],
146
+ Service=self._service(extract_user),
153
147
  ItemId=Annotated[
154
148
  str,
155
149
  Path(alias=self.id_alias),
@@ -173,10 +167,7 @@ class RestfulRouter:
173
167
  self.router.add_api_route(
174
168
  "",
175
169
  self.resource.read_all(
176
- User=Annotated[
177
- Any,
178
- Depends(extract_user),
179
- ],
170
+ Service=self._service(extract_user),
180
171
  ),
181
172
  methods=["GET"],
182
173
  status_code=200,
@@ -196,10 +187,7 @@ class RestfulRouter:
196
187
  self.router.add_api_route(
197
188
  self.item_path,
198
189
  self.resource.update_one(
199
- User=Annotated[
200
- Any,
201
- Depends(extract_user),
202
- ],
190
+ Service=self._service(extract_user),
203
191
  ItemId=Annotated[
204
192
  str,
205
193
  Path(alias=self.id_alias),
@@ -227,10 +215,7 @@ class RestfulRouter:
227
215
  self.router.add_api_route(
228
216
  "",
229
217
  self.resource.update_many(
230
- User=Annotated[
231
- Any,
232
- Depends(extract_user),
233
- ],
218
+ Service=self._service(extract_user),
234
219
  Collection=Annotated[
235
220
  RawCollection,
236
221
  Depends(self.schema.for_update_many()),
@@ -254,10 +239,7 @@ class RestfulRouter:
254
239
  self.router.add_api_route(
255
240
  "",
256
241
  self.resource.replace_one(
257
- User=Annotated[
258
- Any,
259
- Depends(extract_user),
260
- ],
242
+ Service=self._service(extract_user),
261
243
  Item=Annotated[
262
244
  RawItem,
263
245
  Depends(self.schema.for_replace_one()),
@@ -281,10 +263,7 @@ class RestfulRouter:
281
263
  self.router.add_api_route(
282
264
  "/batch",
283
265
  self.resource.replace_many(
284
- User=Annotated[
285
- Any,
286
- Depends(extract_user),
287
- ],
266
+ Service=self._service(extract_user),
288
267
  Collection=Annotated[
289
268
  RawCollection,
290
269
  Depends(self.schema.for_replace_many()),
@@ -308,10 +287,7 @@ class RestfulRouter:
308
287
  self.router.add_api_route(
309
288
  self.item_path,
310
289
  self.resource.delete_one(
311
- User=Annotated[
312
- Any,
313
- Depends(extract_user),
314
- ],
290
+ Service=self._service(extract_user),
315
291
  ItemId=Annotated[
316
292
  str,
317
293
  Path(alias=self.id_alias),
@@ -346,3 +322,32 @@ class RestfulRouter:
346
322
 
347
323
  def build(self) -> APIRouter:
348
324
  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.23"
3
+ version = "1.5.25"
4
4
  description = "Apex Development Tools for python."
5
5
  authors = ["Apex Dev <dev@apex.ge>"]
6
6
  readme = "README.md"
@@ -1,342 +0,0 @@
1
- from dataclasses import dataclass
2
- from functools import cached_property
3
- from typing import Annotated, Any, Callable
4
-
5
- from fastapi import Path
6
- from starlette.responses import JSONResponse
7
-
8
- from apexdevkit.error import DoesNotExistError, ExistsError, ForbiddenError
9
- from apexdevkit.fastapi.builder import RestfulServiceBuilder
10
- from apexdevkit.fastapi.response import RestfulResponse
11
- from apexdevkit.testing import RestfulName
12
-
13
- _Response = JSONResponse | dict[str, Any]
14
-
15
-
16
- @dataclass
17
- class RestfulSubResource:
18
- name: RestfulName
19
- infra: RestfulServiceBuilder
20
- parent: RestfulName
21
-
22
- @property
23
- def parent_id_alias(self) -> str:
24
- return self.parent.singular + "_id"
25
-
26
- @cached_property
27
- def response(self) -> RestfulResponse:
28
- return RestfulResponse(name=self.name)
29
-
30
- def create_one(self, User, Item) -> Callable[..., _Response]: # type: ignore
31
- ParentId = Annotated[str, Path(alias=self.parent_id_alias)]
32
-
33
- def endpoint(user: User, parent_id: ParentId, item: Item) -> _Response:
34
- try:
35
- service = self.infra.with_user(user).with_parent(parent_id).build()
36
- except DoesNotExistError as e:
37
- return JSONResponse(RestfulResponse(self.parent).not_found(e), 404)
38
-
39
- try:
40
- item = service.create_one(item)
41
- except ExistsError as e:
42
- return JSONResponse(self.response.exists(e), 409)
43
- except ForbiddenError as e:
44
- return JSONResponse(self.response.forbidden(e), 403)
45
-
46
- return self.response.created_one(item)
47
-
48
- return endpoint
49
-
50
- def create_many(self, User, Collection) -> Callable[..., _Response]: # type: ignore
51
- ParentId = Annotated[str, Path(alias=self.parent_id_alias)]
52
-
53
- def endpoint(user: User, parent_id: ParentId, items: Collection) -> _Response:
54
- try:
55
- service = self.infra.with_user(user).with_parent(parent_id).build()
56
- except DoesNotExistError as e:
57
- return JSONResponse(RestfulResponse(self.parent).not_found(e), 404)
58
-
59
- try:
60
- return self.response.created_many(service.create_many(items))
61
- except ExistsError as e:
62
- return JSONResponse(self.response.exists(e), 409)
63
- except ForbiddenError as e:
64
- return JSONResponse(self.response.forbidden(e), 403)
65
-
66
- return endpoint
67
-
68
- def read_one(self, User, ItemId) -> Callable[..., _Response]: # type: ignore
69
- ParentId = Annotated[str, Path(alias=self.parent_id_alias)]
70
-
71
- def endpoint(user: User, parent_id: ParentId, item_id: ItemId) -> _Response:
72
- try:
73
- service = self.infra.with_user(user).with_parent(parent_id).build()
74
- except DoesNotExistError as e:
75
- return JSONResponse(RestfulResponse(self.parent).not_found(e), 404)
76
-
77
- try:
78
- return self.response.found_one(service.read_one(item_id))
79
- except DoesNotExistError as e:
80
- return JSONResponse(self.response.not_found(e), 404)
81
- except ForbiddenError as e:
82
- return JSONResponse(self.response.forbidden(e), 403)
83
-
84
- return endpoint
85
-
86
- def read_all(self, User) -> Callable[..., _Response]: # type: ignore
87
- ParentId = Annotated[str, Path(alias=self.parent_id_alias)]
88
-
89
- def endpoint(user: User, parent_id: ParentId) -> _Response:
90
- try:
91
- service = self.infra.with_user(user).with_parent(parent_id).build()
92
- except DoesNotExistError as e:
93
- return JSONResponse(RestfulResponse(self.parent).not_found(e), 404)
94
-
95
- try:
96
- return self.response.found_many(list(service.read_all()))
97
- except ForbiddenError as e:
98
- return JSONResponse(self.response.forbidden(e), 403)
99
-
100
- return endpoint
101
-
102
- def update_one(self, User, ItemId, Updates) -> Callable[..., _Response]: # type: ignore
103
- ParentId = Annotated[str, Path(alias=self.parent_id_alias)]
104
-
105
- def endpoint(
106
- user: User,
107
- parent_id: ParentId,
108
- item_id: ItemId,
109
- updates: Updates,
110
- ) -> _Response:
111
- try:
112
- service = self.infra.with_user(user).with_parent(parent_id).build()
113
- except DoesNotExistError as e:
114
- return JSONResponse(RestfulResponse(self.parent).not_found(e), 404)
115
-
116
- try:
117
- service.update_one(item_id, **updates)
118
- except DoesNotExistError as e:
119
- return JSONResponse(self.response.not_found(e), 404)
120
- except ForbiddenError as e:
121
- return JSONResponse(self.response.forbidden(e), 403)
122
-
123
- return self.response.ok()
124
-
125
- return endpoint
126
-
127
- def update_many(self, User, Collection) -> Callable[..., _Response]: # type: ignore
128
- ParentId = Annotated[str, Path(alias=self.parent_id_alias)]
129
-
130
- def endpoint(user: User, parent_id: ParentId, items: Collection) -> _Response:
131
- try:
132
- service = self.infra.with_user(user).with_parent(parent_id).build()
133
- except DoesNotExistError as e:
134
- return JSONResponse(RestfulResponse(self.parent).not_found(e), 404)
135
-
136
- try:
137
- service.update_many(items)
138
- except DoesNotExistError as e:
139
- return JSONResponse(self.response.not_found(e), 404)
140
- except ForbiddenError as e:
141
- return JSONResponse(self.response.forbidden(e), 403)
142
-
143
- return self.response.ok()
144
-
145
- return endpoint
146
-
147
- def replace_one(self, User, Item) -> Callable[..., _Response]: # type: ignore
148
- ParentId = Annotated[str, Path(alias=self.parent_id_alias)]
149
-
150
- def endpoint(user: User, parent_id: ParentId, item: Item) -> _Response:
151
- try:
152
- service = self.infra.with_user(user).with_parent(parent_id).build()
153
- except DoesNotExistError as e:
154
- return JSONResponse(RestfulResponse(self.parent).not_found(e), 404)
155
-
156
- try:
157
- service.replace_one(item)
158
- except DoesNotExistError as e:
159
- return JSONResponse(self.response.not_found(e), 404)
160
- except ForbiddenError as e:
161
- return JSONResponse(self.response.forbidden(e), 403)
162
-
163
- return self.response.ok()
164
-
165
- return endpoint
166
-
167
- def replace_many(self, User, Collection) -> Callable[..., _Response]: # type: ignore
168
- ParentId = Annotated[str, Path(alias=self.parent_id_alias)]
169
-
170
- def endpoint(user: User, parent_id: ParentId, items: Collection) -> _Response:
171
- try:
172
- service = self.infra.with_user(user).with_parent(parent_id).build()
173
- except DoesNotExistError as e:
174
- return JSONResponse(RestfulResponse(self.parent).not_found(e), 404)
175
-
176
- try:
177
- service.replace_many(items)
178
- except DoesNotExistError as e:
179
- return JSONResponse(self.response.not_found(e), 404)
180
- except ForbiddenError as e:
181
- return JSONResponse(self.response.forbidden(e), 403)
182
-
183
- return self.response.ok()
184
-
185
- return endpoint
186
-
187
- def delete_one(self, User, ItemId) -> Callable[..., _Response]: # type: ignore
188
- ParentId = Annotated[str, Path(alias=self.parent_id_alias)]
189
-
190
- def endpoint(user: User, parent_id: ParentId, item_id: ItemId) -> _Response:
191
- try:
192
- service = self.infra.with_user(user).with_parent(parent_id).build()
193
- except DoesNotExistError as e:
194
- return JSONResponse(RestfulResponse(self.parent).not_found(e), 404)
195
-
196
- try:
197
- service.delete_one(item_id)
198
- except DoesNotExistError as e:
199
- return JSONResponse(self.response.not_found(e), 404)
200
- except ForbiddenError as e:
201
- return JSONResponse(self.response.forbidden(e), 403)
202
-
203
- return self.response.ok()
204
-
205
- return endpoint
206
-
207
-
208
- @dataclass
209
- class RestfulRootResource:
210
- name: RestfulName
211
- infra: RestfulServiceBuilder
212
-
213
- @cached_property
214
- def response(self) -> RestfulResponse:
215
- return RestfulResponse(name=self.name)
216
-
217
- def create_one(self, User, Item) -> Callable[..., _Response]: # type: ignore
218
- def endpoint(user: User, item: Item) -> _Response:
219
- service = self.infra.with_user(user).build()
220
-
221
- try:
222
- item = service.create_one(item)
223
- except ExistsError as e:
224
- return JSONResponse(self.response.exists(e), 409)
225
- except ForbiddenError as e:
226
- return JSONResponse(self.response.forbidden(e), 403)
227
-
228
- return self.response.created_one(item)
229
-
230
- return endpoint
231
-
232
- def create_many(self, User, Collection) -> Callable[..., _Response]: # type: ignore
233
- def endpoint(user: User, items: Collection) -> _Response:
234
- service = self.infra.with_user(user).build()
235
-
236
- try:
237
- return self.response.created_many(service.create_many(items))
238
- except ExistsError as e:
239
- return JSONResponse(self.response.exists(e), 409)
240
- except ForbiddenError as e:
241
- return JSONResponse(self.response.forbidden(e), 403)
242
-
243
- return endpoint
244
-
245
- def read_one(self, User, ItemId) -> Callable[..., _Response]: # type: ignore
246
- def endpoint(user: User, item_id: ItemId) -> _Response:
247
- service = self.infra.with_user(user).build()
248
-
249
- try:
250
- return self.response.found_one(service.read_one(item_id))
251
- except DoesNotExistError as e:
252
- return JSONResponse(self.response.not_found(e), 404)
253
- except ForbiddenError as e:
254
- return JSONResponse(self.response.forbidden(e), 403)
255
-
256
- return endpoint
257
-
258
- def read_all(self, User) -> Callable[..., _Response]: # type: ignore
259
- def endpoint(user: User) -> _Response:
260
- service = self.infra.with_user(user).build()
261
-
262
- try:
263
- return self.response.found_many(list(service.read_all()))
264
- except ForbiddenError as e:
265
- return JSONResponse(self.response.forbidden(e), 403)
266
-
267
- return endpoint
268
-
269
- def update_one(self, User, ItemId, Updates) -> Callable[..., _Response]: # type: ignore
270
- def endpoint(user: User, item_id: ItemId, updates: Updates) -> _Response:
271
- service = self.infra.with_user(user).build()
272
-
273
- try:
274
- service.update_one(item_id, **updates)
275
- except DoesNotExistError as e:
276
- return JSONResponse(self.response.not_found(e), 404)
277
- except ForbiddenError as e:
278
- return JSONResponse(self.response.forbidden(e), 403)
279
-
280
- return self.response.ok()
281
-
282
- return endpoint
283
-
284
- def update_many(self, User, Collection) -> Callable[..., _Response]: # type: ignore
285
- def endpoint(user: User, items: Collection) -> _Response:
286
- service = self.infra.with_user(user).build()
287
-
288
- try:
289
- service.update_many(items)
290
- except DoesNotExistError as e:
291
- return JSONResponse(self.response.not_found(e), 404)
292
- except ForbiddenError as e:
293
- return JSONResponse(self.response.forbidden(e), 403)
294
-
295
- return self.response.ok()
296
-
297
- return endpoint
298
-
299
- def replace_one(self, User, Item) -> Callable[..., _Response]: # type: ignore
300
- def endpoint(user: User, item: Item) -> _Response:
301
- service = self.infra.with_user(user).build()
302
-
303
- try:
304
- service.replace_one(item)
305
- except DoesNotExistError as e:
306
- return JSONResponse(self.response.not_found(e), 404)
307
- except ForbiddenError as e:
308
- return JSONResponse(self.response.forbidden(e), 403)
309
-
310
- return self.response.ok()
311
-
312
- return endpoint
313
-
314
- def replace_many(self, User, Collection) -> Callable[..., _Response]: # type: ignore
315
- def endpoint(user: User, items: Collection) -> _Response:
316
- service = self.infra.with_user(user).build()
317
-
318
- try:
319
- service.replace_many(items)
320
- except DoesNotExistError as e:
321
- return JSONResponse(self.response.not_found(e), 404)
322
- except ForbiddenError as e:
323
- return JSONResponse(self.response.forbidden(e), 403)
324
-
325
- return self.response.ok()
326
-
327
- return endpoint
328
-
329
- def delete_one(self, User, ItemId) -> Callable[..., _Response]: # type: ignore
330
- def endpoint(user: User, item_id: ItemId) -> _Response:
331
- service = self.infra.with_user(user).build()
332
-
333
- try:
334
- service.delete_one(item_id)
335
- except DoesNotExistError as e:
336
- return JSONResponse(self.response.not_found(e), 404)
337
- except ForbiddenError as e:
338
- return JSONResponse(self.response.forbidden(e), 403)
339
-
340
- return self.response.ok()
341
-
342
- return endpoint
File without changes
File without changes