apexdevkit 1.7.1__tar.gz → 1.8.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/PKG-INFO +1 -1
- apexdevkit-1.8.1/apexdevkit/testing/rest.py +288 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/pyproject.toml +1 -1
- apexdevkit-1.7.1/apexdevkit/testing/rest.py +0 -387
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/LICENSE +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/README.md +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/__init__.py +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/annotation/__init__.py +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/annotation/deprecate.py +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/error.py +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/fastapi/__init__.py +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/fastapi/builder.py +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/fastapi/dependable.py +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/fastapi/docs.py +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/fastapi/resource.py +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/fastapi/response.py +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/fastapi/router.py +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/fastapi/schema.py +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/fastapi/service.py +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/formatter.py +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/http/__init__.py +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/http/fake.py +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/http/fluent.py +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/http/httpx.py +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/http/json.py +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/http/url.py +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/py.typed +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/repository/__init__.py +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/repository/base.py +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/repository/connector.py +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/repository/database.py +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/repository/in_memory.py +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/repository/interface.py +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/testing/__init__.py +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/testing/database.py +0 -0
- {apexdevkit-1.7.1 → apexdevkit-1.8.1}/apexdevkit/testing/fake.py +0 -0
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from functools import cached_property
|
|
5
|
+
from typing import Any, Iterable, Self
|
|
6
|
+
|
|
7
|
+
from apexdevkit.http import Http, HttpUrl, JsonDict
|
|
8
|
+
from apexdevkit.http.fluent import HttpMethod, HttpResponse
|
|
9
|
+
from apexdevkit.http.httpx import Httpx
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class RestResource:
|
|
14
|
+
http: Http
|
|
15
|
+
name: RestfulName
|
|
16
|
+
|
|
17
|
+
def create_one(self) -> RestRequest:
|
|
18
|
+
return RestRequest(
|
|
19
|
+
self.name,
|
|
20
|
+
HttpRequest(HttpMethod.post, self.http).with_endpoint(self.name.plural),
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
def create_many(self) -> RestRequest:
|
|
24
|
+
return RestRequest(
|
|
25
|
+
self.name,
|
|
26
|
+
request=(
|
|
27
|
+
HttpRequest(HttpMethod.post, self.http)
|
|
28
|
+
.with_endpoint(self.name.plural)
|
|
29
|
+
.with_endpoint("batch")
|
|
30
|
+
),
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
def read_one(self) -> RestRequest:
|
|
34
|
+
return RestRequest(
|
|
35
|
+
self.name,
|
|
36
|
+
HttpRequest(HttpMethod.get, self.http).with_endpoint(self.name.plural),
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
def read_all(self) -> RestRequest:
|
|
40
|
+
return RestRequest(
|
|
41
|
+
self.name,
|
|
42
|
+
HttpRequest(HttpMethod.get, self.http).with_endpoint(self.name.plural),
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
def update_one(self) -> RestRequest:
|
|
46
|
+
return RestRequest(
|
|
47
|
+
self.name,
|
|
48
|
+
HttpRequest(HttpMethod.patch, self.http).with_endpoint(self.name.plural),
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
def update_many(self) -> RestRequest:
|
|
52
|
+
return RestRequest(
|
|
53
|
+
self.name,
|
|
54
|
+
HttpRequest(HttpMethod.patch, self.http).with_endpoint(self.name.plural),
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
def replace_one(self) -> RestRequest:
|
|
58
|
+
return RestRequest(
|
|
59
|
+
self.name,
|
|
60
|
+
HttpRequest(HttpMethod.put, self.http).with_endpoint(self.name.plural),
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
def replace_many(self) -> RestRequest:
|
|
64
|
+
return RestRequest(
|
|
65
|
+
self.name,
|
|
66
|
+
request=(
|
|
67
|
+
HttpRequest(HttpMethod.put, self.http)
|
|
68
|
+
.with_endpoint(self.name.plural)
|
|
69
|
+
.with_endpoint("batch")
|
|
70
|
+
),
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
def delete_one(self) -> RestRequest:
|
|
74
|
+
return RestRequest(
|
|
75
|
+
self.name,
|
|
76
|
+
HttpRequest(HttpMethod.delete, self.http).with_endpoint(self.name.plural),
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
@dataclass
|
|
81
|
+
class RestCollection(RestResource):
|
|
82
|
+
def sub_resource(self, name: str) -> RestItem:
|
|
83
|
+
assert isinstance(self.http, Httpx), "sub resource only works with Httpx"
|
|
84
|
+
|
|
85
|
+
client = self.http.client
|
|
86
|
+
client.base_url = client.base_url.join(self.name.plural)
|
|
87
|
+
|
|
88
|
+
return RestItem(self.http, RestfulName(name))
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@dataclass
|
|
92
|
+
class RestItem(RestResource):
|
|
93
|
+
def sub_resource(self, name: str) -> RestItem:
|
|
94
|
+
assert isinstance(self.http, Httpx), "sub resource only works with Httpx"
|
|
95
|
+
|
|
96
|
+
client = self.http.client
|
|
97
|
+
client.base_url = client.base_url.join(self.name.singular)
|
|
98
|
+
|
|
99
|
+
return RestItem(self.http, RestfulName(name))
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@dataclass
|
|
103
|
+
class RestfulName:
|
|
104
|
+
singular: str
|
|
105
|
+
|
|
106
|
+
plural: str = ""
|
|
107
|
+
|
|
108
|
+
def __post_init__(self) -> None:
|
|
109
|
+
self.plural = self.plural or as_plural(self.singular)
|
|
110
|
+
|
|
111
|
+
def __add__(self, other: str) -> str:
|
|
112
|
+
return HttpUrl(self.plural) + other
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def as_plural(singular: str) -> str:
|
|
116
|
+
if singular.endswith("y"):
|
|
117
|
+
return singular[:-1] + "ies"
|
|
118
|
+
|
|
119
|
+
if singular.endswith("ch") or singular.endswith("sh") or singular.endswith("ss"):
|
|
120
|
+
return singular[:-2] + "es"
|
|
121
|
+
|
|
122
|
+
if singular.endswith("s") or singular.endswith("z") or singular.endswith("x"):
|
|
123
|
+
return singular[:-1] + "es"
|
|
124
|
+
|
|
125
|
+
if singular.endswith("fe"):
|
|
126
|
+
return singular[:-2] + "ves"
|
|
127
|
+
|
|
128
|
+
if singular.endswith("f"):
|
|
129
|
+
return singular[:-1] + "ves"
|
|
130
|
+
|
|
131
|
+
return singular + "s"
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
@dataclass
|
|
135
|
+
class HttpRequest:
|
|
136
|
+
method: HttpMethod
|
|
137
|
+
http: Http
|
|
138
|
+
|
|
139
|
+
endpoint: str = ""
|
|
140
|
+
|
|
141
|
+
def with_endpoint(self, value: Any) -> HttpRequest:
|
|
142
|
+
self.endpoint = HttpUrl(self.endpoint) + str(value)
|
|
143
|
+
|
|
144
|
+
return self
|
|
145
|
+
|
|
146
|
+
def with_param(self, name: str, value: Any) -> HttpRequest:
|
|
147
|
+
self.http = self.http.with_param(name, value)
|
|
148
|
+
|
|
149
|
+
return self
|
|
150
|
+
|
|
151
|
+
def with_json(self, value: JsonDict) -> HttpRequest:
|
|
152
|
+
self.http = self.http.with_json(value)
|
|
153
|
+
|
|
154
|
+
return self
|
|
155
|
+
|
|
156
|
+
def __call__(self) -> HttpResponse:
|
|
157
|
+
return self.http.request(method=self.method, endpoint=self.endpoint)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
@dataclass
|
|
161
|
+
class RestRequest:
|
|
162
|
+
resource: RestfulName
|
|
163
|
+
request: HttpRequest
|
|
164
|
+
|
|
165
|
+
def with_id(self, value: Any) -> Self:
|
|
166
|
+
self.request = self.request.with_endpoint(value)
|
|
167
|
+
|
|
168
|
+
return self
|
|
169
|
+
|
|
170
|
+
def from_collection(self, value: list[JsonDict]) -> Self:
|
|
171
|
+
return self.with_data(
|
|
172
|
+
JsonDict({self.resource.plural: [dict(item) for item in value]})
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
def and_data(self, value: JsonDict) -> Self:
|
|
176
|
+
return self.with_data(value)
|
|
177
|
+
|
|
178
|
+
def from_data(self, value: JsonDict) -> Self:
|
|
179
|
+
return self.with_data(value)
|
|
180
|
+
|
|
181
|
+
def with_data(self, value: JsonDict) -> Self:
|
|
182
|
+
self.request = self.request.with_json(value)
|
|
183
|
+
|
|
184
|
+
return self
|
|
185
|
+
|
|
186
|
+
def and_param(self, name: str, value: Any) -> Self:
|
|
187
|
+
return self.with_param(name, value)
|
|
188
|
+
|
|
189
|
+
def with_param(self, name: str, value: Any) -> Self:
|
|
190
|
+
self.request = self.request.with_param(name, str(value))
|
|
191
|
+
|
|
192
|
+
return self
|
|
193
|
+
|
|
194
|
+
@cached_property
|
|
195
|
+
def response(self) -> HttpResponse:
|
|
196
|
+
return self.request()
|
|
197
|
+
|
|
198
|
+
def unpack(self) -> JsonDict:
|
|
199
|
+
return JsonDict(self.response.json()["data"][self.resource.singular])
|
|
200
|
+
|
|
201
|
+
def unpack_many(self) -> Iterable[JsonDict]:
|
|
202
|
+
items = self.response.json()["data"][self.resource.plural]
|
|
203
|
+
|
|
204
|
+
return [JsonDict(item) for item in items]
|
|
205
|
+
|
|
206
|
+
def ensure(self) -> RestResponse:
|
|
207
|
+
return RestResponse(
|
|
208
|
+
resource=self.resource,
|
|
209
|
+
json=JsonDict(self.response.json()),
|
|
210
|
+
http_code=self.response.code(),
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
@dataclass
|
|
215
|
+
class RestResponse:
|
|
216
|
+
resource: RestfulName
|
|
217
|
+
json: JsonDict
|
|
218
|
+
http_code: int
|
|
219
|
+
|
|
220
|
+
def fail(self) -> Self:
|
|
221
|
+
if self.http_code == 422:
|
|
222
|
+
return self
|
|
223
|
+
|
|
224
|
+
return self.with_status("fail")
|
|
225
|
+
|
|
226
|
+
def success(self) -> Self:
|
|
227
|
+
return self.with_status("success")
|
|
228
|
+
|
|
229
|
+
def with_status(self, value: str) -> Self:
|
|
230
|
+
assert self.json.value_of("status").to(str) == value
|
|
231
|
+
|
|
232
|
+
return self
|
|
233
|
+
|
|
234
|
+
def with_code(self, value: int) -> Self:
|
|
235
|
+
assert self.http_code == value
|
|
236
|
+
|
|
237
|
+
if self.http_code != 422:
|
|
238
|
+
assert self.json.value_of("code").to(int) == value
|
|
239
|
+
|
|
240
|
+
return self
|
|
241
|
+
|
|
242
|
+
def message(self, value: str) -> Self:
|
|
243
|
+
return self.with_message(value)
|
|
244
|
+
|
|
245
|
+
def and_message(self, value: str) -> Self:
|
|
246
|
+
return self.with_message(value)
|
|
247
|
+
|
|
248
|
+
def with_message(self, value: str) -> Self:
|
|
249
|
+
assert self.json.value_of("error").to(dict) == {"message": value}, self.json
|
|
250
|
+
|
|
251
|
+
return self
|
|
252
|
+
|
|
253
|
+
def and_item(self, value: Any) -> Self:
|
|
254
|
+
return self.with_item(value)
|
|
255
|
+
|
|
256
|
+
def with_item(self, value: Any) -> Self:
|
|
257
|
+
return self.with_data(
|
|
258
|
+
**{
|
|
259
|
+
self.resource.singular: dict(value)
|
|
260
|
+
if isinstance(value, JsonDict)
|
|
261
|
+
else value
|
|
262
|
+
}
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
def and_collection(self, value: list[Any]) -> Self:
|
|
266
|
+
return self.with_collection(value)
|
|
267
|
+
|
|
268
|
+
def with_collection(self, values: list[Any]) -> Self:
|
|
269
|
+
return self.with_data(
|
|
270
|
+
**{
|
|
271
|
+
self.resource.plural: [
|
|
272
|
+
dict(value) if isinstance(value, JsonDict) else value
|
|
273
|
+
for value in values
|
|
274
|
+
],
|
|
275
|
+
},
|
|
276
|
+
count=len(values),
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
def and_no_data(self) -> Self:
|
|
280
|
+
return self.no_data()
|
|
281
|
+
|
|
282
|
+
def no_data(self) -> Self:
|
|
283
|
+
return self.with_data()
|
|
284
|
+
|
|
285
|
+
def with_data(self, **kwargs: Any) -> Self:
|
|
286
|
+
assert self.json.value_of("data").to(dict) == {**kwargs}, self.json
|
|
287
|
+
|
|
288
|
+
return self
|
|
@@ -1,387 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from abc import abstractmethod
|
|
4
|
-
from dataclasses import dataclass, field
|
|
5
|
-
from functools import cached_property
|
|
6
|
-
from typing import Any, Iterable, Self
|
|
7
|
-
|
|
8
|
-
from fastapi.testclient import TestClient
|
|
9
|
-
|
|
10
|
-
from apexdevkit.http import Http, HttpUrl, JsonDict
|
|
11
|
-
from apexdevkit.http.fluent import HttpMethod, HttpResponse
|
|
12
|
-
from apexdevkit.http.httpx import Httpx
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@dataclass
|
|
16
|
-
class RestResource:
|
|
17
|
-
http: TestClient | Http
|
|
18
|
-
name: RestfulName
|
|
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
|
-
|
|
30
|
-
def create_one(self) -> CreateOne:
|
|
31
|
-
return CreateOne(self.name, self._http)
|
|
32
|
-
|
|
33
|
-
def create_many(self) -> CreateMany:
|
|
34
|
-
return CreateMany(self.name, self._http)
|
|
35
|
-
|
|
36
|
-
def read_one(self) -> ReadOne:
|
|
37
|
-
return ReadOne(self.name, self._http)
|
|
38
|
-
|
|
39
|
-
def read_all(self) -> ReadAll:
|
|
40
|
-
return ReadAll(self.name, self._http)
|
|
41
|
-
|
|
42
|
-
def update_one(self) -> UpdateOne:
|
|
43
|
-
return UpdateOne(self.name, self._http)
|
|
44
|
-
|
|
45
|
-
def update_many(self) -> UpdateMany:
|
|
46
|
-
return UpdateMany(self.name, self._http)
|
|
47
|
-
|
|
48
|
-
def replace_one(self) -> ReplaceOne:
|
|
49
|
-
return ReplaceOne(self.name, self._http)
|
|
50
|
-
|
|
51
|
-
def replace_many(self) -> ReplaceMany:
|
|
52
|
-
return ReplaceMany(self.name, self._http)
|
|
53
|
-
|
|
54
|
-
def delete_one(self) -> DeleteOne:
|
|
55
|
-
return DeleteOne(self.name, self._http)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
@dataclass
|
|
59
|
-
class RestCollection(RestResource):
|
|
60
|
-
def sub_resource(self, name: str) -> RestItem:
|
|
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))
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
@dataclass
|
|
70
|
-
class RestItem(RestResource):
|
|
71
|
-
def sub_resource(self, name: str) -> RestItem:
|
|
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.singular)
|
|
76
|
-
|
|
77
|
-
return RestItem(self.http, RestfulName(name))
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
@dataclass
|
|
81
|
-
class RestfulName:
|
|
82
|
-
singular: str
|
|
83
|
-
|
|
84
|
-
plural: str = ""
|
|
85
|
-
|
|
86
|
-
def __post_init__(self) -> None:
|
|
87
|
-
self.plural = self.plural or as_plural(self.singular)
|
|
88
|
-
|
|
89
|
-
def __add__(self, other: str) -> str:
|
|
90
|
-
return HttpUrl(self.plural) + other
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
def as_plural(singular: str) -> str:
|
|
94
|
-
if singular.endswith("y"):
|
|
95
|
-
return singular[:-1] + "ies"
|
|
96
|
-
|
|
97
|
-
if singular.endswith("ch") or singular.endswith("sh") or singular.endswith("ss"):
|
|
98
|
-
return singular[:-2] + "es"
|
|
99
|
-
|
|
100
|
-
if singular.endswith("s") or singular.endswith("z") or singular.endswith("x"):
|
|
101
|
-
return singular[:-1] + "es"
|
|
102
|
-
|
|
103
|
-
if singular.endswith("fe"):
|
|
104
|
-
return singular[:-2] + "ves"
|
|
105
|
-
|
|
106
|
-
if singular.endswith("f"):
|
|
107
|
-
return singular[:-1] + "ves"
|
|
108
|
-
|
|
109
|
-
return singular + "s"
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
@dataclass
|
|
113
|
-
class RestRequest:
|
|
114
|
-
resource: RestfulName
|
|
115
|
-
http: Http
|
|
116
|
-
|
|
117
|
-
@abstractmethod
|
|
118
|
-
@cached_property
|
|
119
|
-
def response(self) -> HttpResponse: # pragma: no cover
|
|
120
|
-
pass
|
|
121
|
-
|
|
122
|
-
def unpack(self) -> JsonDict:
|
|
123
|
-
return JsonDict(self.response.json()["data"][self.resource.singular])
|
|
124
|
-
|
|
125
|
-
def unpack_many(self) -> Iterable[JsonDict]:
|
|
126
|
-
items = self.response.json()["data"][self.resource.plural]
|
|
127
|
-
|
|
128
|
-
return [JsonDict(item) for item in items]
|
|
129
|
-
|
|
130
|
-
def ensure(self) -> RestResponse:
|
|
131
|
-
return RestResponse(
|
|
132
|
-
resource=self.resource,
|
|
133
|
-
json=JsonDict(self.response.json()),
|
|
134
|
-
http_code=self.response.code(),
|
|
135
|
-
)
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
@dataclass
|
|
139
|
-
class CreateOne(RestRequest):
|
|
140
|
-
data: JsonDict = field(init=False)
|
|
141
|
-
|
|
142
|
-
def from_data(self, value: JsonDict) -> Self:
|
|
143
|
-
self.data = value
|
|
144
|
-
|
|
145
|
-
return self
|
|
146
|
-
|
|
147
|
-
@cached_property
|
|
148
|
-
def response(self) -> HttpResponse:
|
|
149
|
-
return self.http.with_json(self.data).request(
|
|
150
|
-
method=HttpMethod.post,
|
|
151
|
-
endpoint=self.resource + "",
|
|
152
|
-
)
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
@dataclass
|
|
156
|
-
class ReadOne(RestRequest):
|
|
157
|
-
item_id: str = field(init=False)
|
|
158
|
-
|
|
159
|
-
@cached_property
|
|
160
|
-
def response(self) -> HttpResponse:
|
|
161
|
-
return self.http.request(
|
|
162
|
-
method=HttpMethod.get,
|
|
163
|
-
endpoint=self.resource + str(self.item_id),
|
|
164
|
-
)
|
|
165
|
-
|
|
166
|
-
def with_id(self, value: Any) -> Self:
|
|
167
|
-
self.item_id = str(value)
|
|
168
|
-
|
|
169
|
-
return self
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
@dataclass
|
|
173
|
-
class ReadAll(RestRequest):
|
|
174
|
-
params: dict[str, Any] = field(init=False, default_factory=dict)
|
|
175
|
-
|
|
176
|
-
@cached_property
|
|
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 + "")
|
|
183
|
-
|
|
184
|
-
def with_params(self, **kwargs: Any) -> Self:
|
|
185
|
-
self.params = {**kwargs}
|
|
186
|
-
|
|
187
|
-
return self
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
@dataclass
|
|
191
|
-
class UpdateOne(RestRequest):
|
|
192
|
-
item_id: str = field(init=False)
|
|
193
|
-
data: JsonDict = field(init=False)
|
|
194
|
-
|
|
195
|
-
@cached_property
|
|
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
|
-
)
|
|
201
|
-
|
|
202
|
-
def with_id(self, value: Any) -> Self:
|
|
203
|
-
self.item_id = str(value)
|
|
204
|
-
|
|
205
|
-
return self
|
|
206
|
-
|
|
207
|
-
def and_data(self, value: JsonDict) -> Self:
|
|
208
|
-
self.data = value
|
|
209
|
-
|
|
210
|
-
return self
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
@dataclass
|
|
214
|
-
class ReplaceOne(RestRequest):
|
|
215
|
-
data: JsonDict = field(init=False)
|
|
216
|
-
|
|
217
|
-
@cached_property
|
|
218
|
-
def response(self) -> HttpResponse:
|
|
219
|
-
return self.http.with_json(self.data).request(
|
|
220
|
-
method=HttpMethod.put,
|
|
221
|
-
endpoint=self.resource + "",
|
|
222
|
-
)
|
|
223
|
-
|
|
224
|
-
def from_data(self, value: JsonDict) -> Self:
|
|
225
|
-
self.data = value
|
|
226
|
-
|
|
227
|
-
return self
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
@dataclass
|
|
231
|
-
class CreateMany(RestRequest):
|
|
232
|
-
data: list[JsonDict] = field(default_factory=list)
|
|
233
|
-
|
|
234
|
-
@cached_property
|
|
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",
|
|
241
|
-
)
|
|
242
|
-
|
|
243
|
-
def from_data(self, value: JsonDict) -> Self:
|
|
244
|
-
self.data.append(value)
|
|
245
|
-
|
|
246
|
-
return self
|
|
247
|
-
|
|
248
|
-
def and_data(self, value: JsonDict) -> Self:
|
|
249
|
-
return self.from_data(value)
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
@dataclass
|
|
253
|
-
class UpdateMany(RestRequest):
|
|
254
|
-
data: list[JsonDict] = field(default_factory=list)
|
|
255
|
-
|
|
256
|
-
@cached_property
|
|
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 + "",
|
|
263
|
-
)
|
|
264
|
-
|
|
265
|
-
def from_data(self, value: JsonDict) -> Self:
|
|
266
|
-
self.data.append(value)
|
|
267
|
-
|
|
268
|
-
return self
|
|
269
|
-
|
|
270
|
-
def and_data(self, value: JsonDict) -> Self:
|
|
271
|
-
return self.from_data(value)
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
@dataclass
|
|
275
|
-
class ReplaceMany(RestRequest):
|
|
276
|
-
data: list[JsonDict] = field(default_factory=list)
|
|
277
|
-
|
|
278
|
-
@cached_property
|
|
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",
|
|
285
|
-
)
|
|
286
|
-
|
|
287
|
-
def from_data(self, value: JsonDict) -> Self:
|
|
288
|
-
self.data.append(value)
|
|
289
|
-
|
|
290
|
-
return self
|
|
291
|
-
|
|
292
|
-
def and_data(self, value: JsonDict) -> Self:
|
|
293
|
-
return self.from_data(value)
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
@dataclass
|
|
297
|
-
class DeleteOne(RestRequest):
|
|
298
|
-
item_id: str = field(init=False)
|
|
299
|
-
|
|
300
|
-
@cached_property
|
|
301
|
-
def response(self) -> HttpResponse:
|
|
302
|
-
return self.http.request(
|
|
303
|
-
method=HttpMethod.delete,
|
|
304
|
-
endpoint=self.resource + str(self.item_id),
|
|
305
|
-
)
|
|
306
|
-
|
|
307
|
-
def with_id(self, value: Any) -> Self:
|
|
308
|
-
self.item_id = str(value)
|
|
309
|
-
|
|
310
|
-
return self
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
@dataclass
|
|
314
|
-
class RestResponse:
|
|
315
|
-
resource: RestfulName
|
|
316
|
-
json: JsonDict
|
|
317
|
-
http_code: int
|
|
318
|
-
|
|
319
|
-
def fail(self) -> Self:
|
|
320
|
-
if self.http_code == 422:
|
|
321
|
-
return self
|
|
322
|
-
|
|
323
|
-
return self.with_status("fail")
|
|
324
|
-
|
|
325
|
-
def success(self) -> Self:
|
|
326
|
-
return self.with_status("success")
|
|
327
|
-
|
|
328
|
-
def with_status(self, value: str) -> Self:
|
|
329
|
-
assert self.json.value_of("status").to(str) == value
|
|
330
|
-
|
|
331
|
-
return self
|
|
332
|
-
|
|
333
|
-
def with_code(self, value: int) -> Self:
|
|
334
|
-
assert self.http_code == value
|
|
335
|
-
|
|
336
|
-
if self.http_code != 422:
|
|
337
|
-
assert self.json.value_of("code").to(int) == value
|
|
338
|
-
|
|
339
|
-
return self
|
|
340
|
-
|
|
341
|
-
def message(self, value: str) -> Self:
|
|
342
|
-
return self.with_message(value)
|
|
343
|
-
|
|
344
|
-
def and_message(self, value: str) -> Self:
|
|
345
|
-
return self.with_message(value)
|
|
346
|
-
|
|
347
|
-
def with_message(self, value: str) -> Self:
|
|
348
|
-
assert self.json.value_of("error").to(dict) == {"message": value}, self.json
|
|
349
|
-
|
|
350
|
-
return self
|
|
351
|
-
|
|
352
|
-
def and_item(self, value: Any) -> Self:
|
|
353
|
-
return self.with_item(value)
|
|
354
|
-
|
|
355
|
-
def with_item(self, value: Any) -> Self:
|
|
356
|
-
return self.with_data(
|
|
357
|
-
**{
|
|
358
|
-
self.resource.singular: dict(value)
|
|
359
|
-
if isinstance(value, JsonDict)
|
|
360
|
-
else value
|
|
361
|
-
}
|
|
362
|
-
)
|
|
363
|
-
|
|
364
|
-
def and_collection(self, value: list[Any]) -> Self:
|
|
365
|
-
return self.with_collection(value)
|
|
366
|
-
|
|
367
|
-
def with_collection(self, values: list[Any]) -> Self:
|
|
368
|
-
return self.with_data(
|
|
369
|
-
**{
|
|
370
|
-
self.resource.plural: [
|
|
371
|
-
dict(value) if isinstance(value, JsonDict) else value
|
|
372
|
-
for value in values
|
|
373
|
-
],
|
|
374
|
-
},
|
|
375
|
-
count=len(values),
|
|
376
|
-
)
|
|
377
|
-
|
|
378
|
-
def and_no_data(self) -> Self:
|
|
379
|
-
return self.no_data()
|
|
380
|
-
|
|
381
|
-
def no_data(self) -> Self:
|
|
382
|
-
return self.with_data()
|
|
383
|
-
|
|
384
|
-
def with_data(self, **kwargs: Any) -> Self:
|
|
385
|
-
assert self.json.value_of("data").to(dict) == {**kwargs}, self.json
|
|
386
|
-
|
|
387
|
-
return self
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|