schemathesis 3.26.1__py3-none-any.whl → 3.27.0__py3-none-any.whl
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.
- schemathesis/_dependency_versions.py +3 -0
- schemathesis/_rate_limiter.py +6 -0
- schemathesis/cli/__init__.py +1 -1
- schemathesis/cli/junitxml.py +79 -10
- schemathesis/cli/output/default.py +9 -47
- schemathesis/cli/reporting.py +72 -0
- schemathesis/models.py +51 -143
- schemathesis/runner/impl/core.py +10 -8
- schemathesis/runner/serialization.py +32 -10
- schemathesis/schemas.py +15 -7
- schemathesis/specs/graphql/loaders.py +2 -0
- schemathesis/specs/graphql/schemas.py +7 -40
- schemathesis/specs/openapi/_hypothesis.py +3 -1
- schemathesis/specs/openapi/loaders.py +3 -0
- schemathesis/stateful/state_machine.py +3 -13
- schemathesis/throttling.py +2 -2
- schemathesis/transports/__init__.py +306 -0
- schemathesis/transports/responses.py +2 -0
- {schemathesis-3.26.1.dist-info → schemathesis-3.27.0.dist-info}/METADATA +2 -2
- {schemathesis-3.26.1.dist-info → schemathesis-3.27.0.dist-info}/RECORD +23 -21
- {schemathesis-3.26.1.dist-info → schemathesis-3.27.0.dist-info}/WHEEL +0 -0
- {schemathesis-3.26.1.dist-info → schemathesis-3.27.0.dist-info}/entry_points.txt +0 -0
- {schemathesis-3.26.1.dist-info → schemathesis-3.27.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,5 +1,311 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import base64
|
|
4
|
+
import time
|
|
5
|
+
from contextlib import contextmanager
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from datetime import timedelta
|
|
8
|
+
from typing import TYPE_CHECKING, Any, Generator, Protocol, TypeVar, cast
|
|
9
|
+
from urllib.parse import urlparse
|
|
10
|
+
|
|
11
|
+
from .. import failures
|
|
12
|
+
from .._dependency_versions import IS_WERKZEUG_ABOVE_3
|
|
13
|
+
from ..constants import DEFAULT_RESPONSE_TIMEOUT
|
|
14
|
+
from ..exceptions import get_timeout_error
|
|
15
|
+
from ..serializers import SerializerContext
|
|
16
|
+
from ..types import Cookies, NotSet
|
|
17
|
+
|
|
18
|
+
if TYPE_CHECKING:
|
|
19
|
+
import requests
|
|
20
|
+
import werkzeug
|
|
21
|
+
from _typeshed.wsgi import WSGIApplication
|
|
22
|
+
from starlette_testclient._testclient import ASGI2App, ASGI3App
|
|
23
|
+
|
|
24
|
+
from ..models import Case
|
|
25
|
+
from .responses import WSGIResponse
|
|
2
26
|
|
|
3
27
|
|
|
4
28
|
def serialize_payload(payload: bytes) -> str:
|
|
5
29
|
return base64.b64encode(payload).decode()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def get(app: Any) -> Transport:
|
|
33
|
+
"""Get transport to send the data to the application."""
|
|
34
|
+
from starlette.applications import Starlette
|
|
35
|
+
|
|
36
|
+
if app is None:
|
|
37
|
+
return RequestsTransport()
|
|
38
|
+
if isinstance(app, Starlette):
|
|
39
|
+
return ASGITransport(app=app)
|
|
40
|
+
return WSGITransport(app=app)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
S = TypeVar("S", contravariant=True)
|
|
44
|
+
R = TypeVar("R", covariant=True)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class Transport(Protocol[S, R]):
|
|
48
|
+
def serialize_case(
|
|
49
|
+
self,
|
|
50
|
+
case: Case,
|
|
51
|
+
*,
|
|
52
|
+
base_url: str | None = None,
|
|
53
|
+
headers: dict[str, Any] | None = None,
|
|
54
|
+
params: dict[str, Any] | None = None,
|
|
55
|
+
cookies: dict[str, Any] | None = None,
|
|
56
|
+
) -> dict[str, Any]:
|
|
57
|
+
raise NotImplementedError
|
|
58
|
+
|
|
59
|
+
def send(
|
|
60
|
+
self,
|
|
61
|
+
case: Case,
|
|
62
|
+
*,
|
|
63
|
+
session: S | None = None,
|
|
64
|
+
base_url: str | None = None,
|
|
65
|
+
headers: dict[str, Any] | None = None,
|
|
66
|
+
params: dict[str, Any] | None = None,
|
|
67
|
+
cookies: dict[str, Any] | None = None,
|
|
68
|
+
**kwargs: Any,
|
|
69
|
+
) -> R:
|
|
70
|
+
raise NotImplementedError
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class RequestsTransport:
|
|
74
|
+
def serialize_case(
|
|
75
|
+
self,
|
|
76
|
+
case: Case,
|
|
77
|
+
*,
|
|
78
|
+
base_url: str | None = None,
|
|
79
|
+
headers: dict[str, Any] | None = None,
|
|
80
|
+
params: dict[str, Any] | None = None,
|
|
81
|
+
cookies: dict[str, Any] | None = None,
|
|
82
|
+
) -> dict[str, Any]:
|
|
83
|
+
final_headers = case._get_headers(headers)
|
|
84
|
+
if case.media_type and case.media_type != "multipart/form-data" and not isinstance(case.body, NotSet):
|
|
85
|
+
# `requests` will handle multipart form headers with the proper `boundary` value.
|
|
86
|
+
if "content-type" not in final_headers:
|
|
87
|
+
final_headers["Content-Type"] = case.media_type
|
|
88
|
+
url = case._get_url(base_url)
|
|
89
|
+
serializer = case._get_serializer()
|
|
90
|
+
if serializer is not None and not isinstance(case.body, NotSet):
|
|
91
|
+
context = SerializerContext(case=case)
|
|
92
|
+
extra = serializer.as_requests(context, case._get_body())
|
|
93
|
+
else:
|
|
94
|
+
extra = {}
|
|
95
|
+
if case._auth is not None:
|
|
96
|
+
extra["auth"] = case._auth
|
|
97
|
+
additional_headers = extra.pop("headers", None)
|
|
98
|
+
if additional_headers:
|
|
99
|
+
# Additional headers, needed for the serializer
|
|
100
|
+
for key, value in additional_headers.items():
|
|
101
|
+
final_headers.setdefault(key, value)
|
|
102
|
+
data = {
|
|
103
|
+
"method": case.method,
|
|
104
|
+
"url": url,
|
|
105
|
+
"cookies": case.cookies,
|
|
106
|
+
"headers": final_headers,
|
|
107
|
+
"params": case.query,
|
|
108
|
+
**extra,
|
|
109
|
+
}
|
|
110
|
+
if params is not None:
|
|
111
|
+
_merge_dict_to(data, "params", params)
|
|
112
|
+
if cookies is not None:
|
|
113
|
+
_merge_dict_to(data, "cookies", cookies)
|
|
114
|
+
return data
|
|
115
|
+
|
|
116
|
+
def send(
|
|
117
|
+
self,
|
|
118
|
+
case: Case,
|
|
119
|
+
*,
|
|
120
|
+
session: requests.Session | None = None,
|
|
121
|
+
base_url: str | None = None,
|
|
122
|
+
headers: dict[str, Any] | None = None,
|
|
123
|
+
params: dict[str, Any] | None = None,
|
|
124
|
+
cookies: dict[str, Any] | None = None,
|
|
125
|
+
**kwargs: Any,
|
|
126
|
+
) -> requests.Response:
|
|
127
|
+
import requests
|
|
128
|
+
from urllib3.exceptions import ReadTimeoutError
|
|
129
|
+
|
|
130
|
+
data = self.serialize_case(case, base_url=base_url, headers=headers, params=params, cookies=cookies)
|
|
131
|
+
data.update(kwargs)
|
|
132
|
+
data.setdefault("timeout", DEFAULT_RESPONSE_TIMEOUT / 1000)
|
|
133
|
+
if session is None:
|
|
134
|
+
validate_vanilla_requests_kwargs(data)
|
|
135
|
+
session = requests.Session()
|
|
136
|
+
close_session = True
|
|
137
|
+
else:
|
|
138
|
+
close_session = False
|
|
139
|
+
verify = data.get("verify", True)
|
|
140
|
+
try:
|
|
141
|
+
with case.operation.schema.ratelimit():
|
|
142
|
+
response = session.request(**data) # type: ignore
|
|
143
|
+
except (requests.Timeout, requests.ConnectionError) as exc:
|
|
144
|
+
if isinstance(exc, requests.ConnectionError):
|
|
145
|
+
if not isinstance(exc.args[0], ReadTimeoutError):
|
|
146
|
+
raise
|
|
147
|
+
req = requests.Request(
|
|
148
|
+
method=data["method"].upper(),
|
|
149
|
+
url=data["url"],
|
|
150
|
+
headers=data["headers"],
|
|
151
|
+
files=data.get("files"),
|
|
152
|
+
data=data.get("data") or {},
|
|
153
|
+
json=data.get("json"),
|
|
154
|
+
params=data.get("params") or {},
|
|
155
|
+
auth=data.get("auth"),
|
|
156
|
+
cookies=data["cookies"],
|
|
157
|
+
hooks=data.get("hooks"),
|
|
158
|
+
)
|
|
159
|
+
request = session.prepare_request(req)
|
|
160
|
+
else:
|
|
161
|
+
request = cast(requests.PreparedRequest, exc.request)
|
|
162
|
+
timeout = 1000 * data["timeout"] # It is defined and not empty, since the exception happened
|
|
163
|
+
code_message = case._get_code_message(case.operation.schema.code_sample_style, request, verify=verify)
|
|
164
|
+
message = f"The server failed to respond within the specified limit of {timeout:.2f}ms"
|
|
165
|
+
raise get_timeout_error(timeout)(
|
|
166
|
+
f"\n\n1. {failures.RequestTimeout.title}\n\n{message}\n\n{code_message}",
|
|
167
|
+
context=failures.RequestTimeout(message=message, timeout=timeout),
|
|
168
|
+
) from None
|
|
169
|
+
response.verify = verify # type: ignore[attr-defined]
|
|
170
|
+
if close_session:
|
|
171
|
+
session.close()
|
|
172
|
+
return response
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def _merge_dict_to(data: dict[str, Any], data_key: str, new: dict[str, Any]) -> None:
|
|
176
|
+
original = data[data_key] or {}
|
|
177
|
+
for key, value in new.items():
|
|
178
|
+
original[key] = value
|
|
179
|
+
data[data_key] = original
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def validate_vanilla_requests_kwargs(data: dict[str, Any]) -> None:
|
|
183
|
+
"""Check arguments for `requests.Session.request`.
|
|
184
|
+
|
|
185
|
+
Some arguments can be valid for cases like ASGI integration, but at the same time they won't work for the regular
|
|
186
|
+
`requests` calls. In such cases we need to avoid an obscure error message, that comes from `requests`.
|
|
187
|
+
"""
|
|
188
|
+
url = data["url"]
|
|
189
|
+
if not urlparse(url).netloc:
|
|
190
|
+
raise RuntimeError(
|
|
191
|
+
"The URL should be absolute, so Schemathesis knows where to send the data. \n"
|
|
192
|
+
f"If you use the ASGI integration, please supply your test client "
|
|
193
|
+
f"as the `session` argument to `call`.\nURL: {url}"
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
@dataclass
|
|
198
|
+
class ASGITransport(RequestsTransport):
|
|
199
|
+
app: ASGI2App | ASGI3App
|
|
200
|
+
|
|
201
|
+
def send(
|
|
202
|
+
self,
|
|
203
|
+
case: Case,
|
|
204
|
+
*,
|
|
205
|
+
session: requests.Session | None = None,
|
|
206
|
+
base_url: str | None = None,
|
|
207
|
+
headers: dict[str, Any] | None = None,
|
|
208
|
+
params: dict[str, Any] | None = None,
|
|
209
|
+
cookies: dict[str, Any] | None = None,
|
|
210
|
+
**kwargs: Any,
|
|
211
|
+
) -> requests.Response:
|
|
212
|
+
from starlette_testclient import TestClient as ASGIClient
|
|
213
|
+
|
|
214
|
+
if base_url is None:
|
|
215
|
+
base_url = case.get_full_base_url()
|
|
216
|
+
with ASGIClient(self.app) as client:
|
|
217
|
+
return super().send(
|
|
218
|
+
case, session=client, base_url=base_url, headers=headers, params=params, cookies=cookies, **kwargs
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
@dataclass
|
|
223
|
+
class WSGITransport:
|
|
224
|
+
app: WSGIApplication
|
|
225
|
+
|
|
226
|
+
def serialize_case(
|
|
227
|
+
self,
|
|
228
|
+
case: Case,
|
|
229
|
+
*,
|
|
230
|
+
base_url: str | None = None,
|
|
231
|
+
headers: dict[str, Any] | None = None,
|
|
232
|
+
params: dict[str, Any] | None = None,
|
|
233
|
+
cookies: dict[str, Any] | None = None,
|
|
234
|
+
) -> dict[str, Any]:
|
|
235
|
+
final_headers = case._get_headers(headers)
|
|
236
|
+
if case.media_type and not isinstance(case.body, NotSet):
|
|
237
|
+
# If we need to send a payload, then the Content-Type header should be set
|
|
238
|
+
final_headers["Content-Type"] = case.media_type
|
|
239
|
+
extra: dict[str, Any]
|
|
240
|
+
serializer = case._get_serializer()
|
|
241
|
+
if serializer is not None and not isinstance(case.body, NotSet):
|
|
242
|
+
context = SerializerContext(case=case)
|
|
243
|
+
extra = serializer.as_werkzeug(context, case._get_body())
|
|
244
|
+
else:
|
|
245
|
+
extra = {}
|
|
246
|
+
data = {
|
|
247
|
+
"method": case.method,
|
|
248
|
+
"path": case.operation.schema.get_full_path(case.formatted_path),
|
|
249
|
+
# Convert to a regular dictionary, as we use `CaseInsensitiveDict` which is not supported by Werkzeug
|
|
250
|
+
"headers": dict(final_headers),
|
|
251
|
+
"query_string": case.query,
|
|
252
|
+
**extra,
|
|
253
|
+
}
|
|
254
|
+
if params is not None:
|
|
255
|
+
_merge_dict_to(data, "query_string", params)
|
|
256
|
+
return data
|
|
257
|
+
|
|
258
|
+
def send(
|
|
259
|
+
self,
|
|
260
|
+
case: Case,
|
|
261
|
+
*,
|
|
262
|
+
session: Any = None,
|
|
263
|
+
base_url: str | None = None,
|
|
264
|
+
headers: dict[str, Any] | None = None,
|
|
265
|
+
params: dict[str, Any] | None = None,
|
|
266
|
+
cookies: dict[str, Any] | None = None,
|
|
267
|
+
**kwargs: Any,
|
|
268
|
+
) -> WSGIResponse:
|
|
269
|
+
import requests
|
|
270
|
+
import werkzeug
|
|
271
|
+
|
|
272
|
+
from .responses import WSGIResponse
|
|
273
|
+
|
|
274
|
+
application = kwargs.pop("app", self.app) or self.app
|
|
275
|
+
data = self.serialize_case(case, headers=headers, params=params)
|
|
276
|
+
data.update(kwargs)
|
|
277
|
+
client = werkzeug.Client(application, WSGIResponse)
|
|
278
|
+
cookies = {**(case.cookies or {}), **(cookies or {})}
|
|
279
|
+
with cookie_handler(client, cookies), case.operation.schema.ratelimit():
|
|
280
|
+
start = time.monotonic()
|
|
281
|
+
response = client.open(**data)
|
|
282
|
+
elapsed = time.monotonic() - start
|
|
283
|
+
requests_kwargs = RequestsTransport().serialize_case(
|
|
284
|
+
case,
|
|
285
|
+
base_url=case.get_full_base_url(),
|
|
286
|
+
headers=headers,
|
|
287
|
+
params=params,
|
|
288
|
+
cookies=cookies,
|
|
289
|
+
)
|
|
290
|
+
response.request = requests.Request(**requests_kwargs).prepare()
|
|
291
|
+
response.elapsed = timedelta(seconds=elapsed)
|
|
292
|
+
return response
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
@contextmanager
|
|
296
|
+
def cookie_handler(client: werkzeug.Client, cookies: Cookies | None) -> Generator[None, None, None]:
|
|
297
|
+
"""Set cookies required for a call."""
|
|
298
|
+
if not cookies:
|
|
299
|
+
yield
|
|
300
|
+
else:
|
|
301
|
+
for key, value in cookies.items():
|
|
302
|
+
if IS_WERKZEUG_ABOVE_3:
|
|
303
|
+
client.set_cookie(key=key, value=value, domain="localhost")
|
|
304
|
+
else:
|
|
305
|
+
client.set_cookie("localhost", key=key, value=value)
|
|
306
|
+
yield
|
|
307
|
+
for key in cookies:
|
|
308
|
+
if IS_WERKZEUG_ABOVE_3:
|
|
309
|
+
client.delete_cookie(key=key, domain="localhost")
|
|
310
|
+
else:
|
|
311
|
+
client.delete_cookie("localhost", key=key)
|
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import sys
|
|
4
4
|
import json
|
|
5
|
+
from datetime import timedelta
|
|
5
6
|
from typing import Union, TYPE_CHECKING, NoReturn, Any
|
|
6
7
|
from .._compat import JSONMixin
|
|
7
8
|
from werkzeug.wrappers import Response as BaseResponse
|
|
@@ -15,6 +16,7 @@ if TYPE_CHECKING:
|
|
|
15
16
|
class WSGIResponse(BaseResponse, JSONMixin):
|
|
16
17
|
# We store "requests" request to build a reproduction code
|
|
17
18
|
request: PreparedRequest
|
|
19
|
+
elapsed: timedelta
|
|
18
20
|
|
|
19
21
|
def on_json_loading_failed(self, e: json.JSONDecodeError) -> NoReturn:
|
|
20
22
|
# We don't need a werkzeug-specific exception when JSON parsing error happens
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: schemathesis
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.27.0
|
|
4
4
|
Summary: Property-based testing framework for Open API and GraphQL based apps
|
|
5
5
|
Project-URL: Documentation, https://schemathesis.readthedocs.io/en/stable/
|
|
6
6
|
Project-URL: Changelog, https://schemathesis.readthedocs.io/en/stable/changelog.html
|
|
@@ -39,7 +39,7 @@ Requires-Dist: hypothesis<7,>=6.84.3; python_version > '3.8'
|
|
|
39
39
|
Requires-Dist: hypothesis[zoneinfo]<7,>=6.84.3; python_version == '3.8'
|
|
40
40
|
Requires-Dist: jsonschema<5.0,>=4.18.0
|
|
41
41
|
Requires-Dist: junit-xml<2.0,>=1.9
|
|
42
|
-
Requires-Dist: pyrate-limiter<
|
|
42
|
+
Requires-Dist: pyrate-limiter<4.0,>=2.10
|
|
43
43
|
Requires-Dist: pytest-subtests<0.8.0,>=0.2.1
|
|
44
44
|
Requires-Dist: pytest<9,>=4.6.4
|
|
45
45
|
Requires-Dist: pyyaml<7.0,>=5.1
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
schemathesis/__init__.py,sha256=WW1NBZxmc5jRR0c24xz-ZtTkJMUQG5MOw1MGVRRGc1s,1970
|
|
2
2
|
schemathesis/_compat.py,sha256=VizWR0QAVj4l7WZautNe_zmo3AJ7WBl2zrJQOfJAQtk,1837
|
|
3
|
-
schemathesis/_dependency_versions.py,sha256=
|
|
3
|
+
schemathesis/_dependency_versions.py,sha256=InIv6MZmuRVHc_9FxAiRg7_dY-vuF0jT69FBxrBLK6U,879
|
|
4
4
|
schemathesis/_hypothesis.py,sha256=O3rfMbT0rChFONMUsYmMEGV9nPG5cHd_6v9NhWDI_IQ,10763
|
|
5
5
|
schemathesis/_lazy_import.py,sha256=LTki2tM168fCcXet1e6qDoQq8SLgInUA3xjXgi7cXJk,469
|
|
6
6
|
schemathesis/_override.py,sha256=oetGCvMGqP8plf2Suvql2E0n3P-PU9SIySKwlBjzuR4,1629
|
|
7
|
+
schemathesis/_rate_limiter.py,sha256=t0uUB4kz5lG1ogfLHwIImunOaP88jFkCf-zzzxOM3cs,212
|
|
7
8
|
schemathesis/_xml.py,sha256=5AMZuno3fS4YWPqBlrv5V-f-BmawkdwmpD3GpAsaxnA,6922
|
|
8
9
|
schemathesis/auths.py,sha256=tUuaHvXO96HJr22Gu9OmlSpL2wbAqKZr3TRbb9dVyA4,14732
|
|
9
10
|
schemathesis/checks.py,sha256=SYts1Teecg-5kSHBo32Pzhh7YQ4a1Y7DIfldd-0VTj8,2155
|
|
@@ -16,28 +17,29 @@ schemathesis/graphql.py,sha256=YkoKWY5K8lxp7H3ikAs-IsoDbiPwJvChG7O8p3DgwtI,229
|
|
|
16
17
|
schemathesis/hooks.py,sha256=cNJgCh7SyLWT1sYDKF5ncDC80ld08CinvKo2IqLMV4g,12396
|
|
17
18
|
schemathesis/lazy.py,sha256=CivWpvesh4iYLSkatXbQPTEOruWmXvuZQ29gng5p9wM,14846
|
|
18
19
|
schemathesis/loaders.py,sha256=RJnrbf-3vZ7KXmRBkmr3uqWyg0eHzOnONABuudWcTIg,4586
|
|
19
|
-
schemathesis/models.py,sha256=
|
|
20
|
+
schemathesis/models.py,sha256=KtWx7k9M8wrkaCZ82kfLMKd7jmvFxZnGyUuTE_nPhU0,42974
|
|
20
21
|
schemathesis/parameters.py,sha256=VheEffVzoSfYaSEcG7KhPlA4ypifosG8biiHifzwL8g,2257
|
|
21
22
|
schemathesis/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
23
|
schemathesis/sanitization.py,sha256=WSV_MB5YRrYkp1pQRPHrzsidqsKcqYZiq64N9grKobo,8956
|
|
23
|
-
schemathesis/schemas.py,sha256=
|
|
24
|
+
schemathesis/schemas.py,sha256=RzxAoBoJJSLsixrkTZPe2N_oWbWv8n5RL4XaYRyoSIo,18531
|
|
24
25
|
schemathesis/serializers.py,sha256=_xoebWkVrgbGbPjPgTgwuN-fN4YT004aj7kImyPComY,11619
|
|
25
26
|
schemathesis/targets.py,sha256=tzp7VZ2-7g2nZHCooRgFzTMtOVcbl0rvtNR421hQthA,1162
|
|
26
|
-
schemathesis/throttling.py,sha256=
|
|
27
|
+
schemathesis/throttling.py,sha256=uwhL4XWPWAU8HECg0NhibfCMn5dT7NElTx3fdL3Mmcc,1065
|
|
27
28
|
schemathesis/types.py,sha256=AglR5M0bce-YXeDRkweToXTP0GjNOWVjS_mIsxLobwc,919
|
|
28
29
|
schemathesis/utils.py,sha256=4HXvHysnHp-Uz2HfNgLfW5F5VjL-mtixrjjzRCEJhYo,5233
|
|
29
|
-
schemathesis/cli/__init__.py,sha256=
|
|
30
|
+
schemathesis/cli/__init__.py,sha256=oTBqweV5CP681LqRFdRXtkd0VyYoG_xUKshkKEPnqIQ,64871
|
|
30
31
|
schemathesis/cli/callbacks.py,sha256=HmD0WmSYf5x8v4xeZdOKzy_8CEk23NitUlL8JQ7LHdQ,14950
|
|
31
32
|
schemathesis/cli/cassettes.py,sha256=1ucgYyOZiNu44uOv044FdfKTzQolUyhAM2onk4m3MD0,12988
|
|
32
33
|
schemathesis/cli/constants.py,sha256=XoezT0_fHuiOY2e--cmBUhNieJsepcUoW8e48QuLSDI,1544
|
|
33
34
|
schemathesis/cli/context.py,sha256=wwfdSL_NKHEyzQnj8PcnaJdzasa_N08e2KPvy4Wl8N4,1874
|
|
34
35
|
schemathesis/cli/debug.py,sha256=PDEa-oHyz5bZ8aYjRYARwQaCv_AC6HM_L43LJfe4vUM,657
|
|
35
36
|
schemathesis/cli/handlers.py,sha256=62GPWPmgeGUz3pkDd01H4UCXcIy5a9yRtU7qaAeeR-A,389
|
|
36
|
-
schemathesis/cli/junitxml.py,sha256=
|
|
37
|
+
schemathesis/cli/junitxml.py,sha256=JMMtWz7grPQw66Ruh-tLR8YVn-58Q0o0l_MxZWQ4V3M,4586
|
|
37
38
|
schemathesis/cli/options.py,sha256=7_dXcrPT0kWqAkm60cAT1J0IsTOcvNFxT1pcHYttBuI,2558
|
|
39
|
+
schemathesis/cli/reporting.py,sha256=uTtoEJT4maJRGPsVZH184S0hohX-4SwO_dAL__i6H10,3401
|
|
38
40
|
schemathesis/cli/sanitization.py,sha256=v-9rsMCBpWhom0Bfzj_8c6InqxkVjSWK6kRoURa52Nk,727
|
|
39
41
|
schemathesis/cli/output/__init__.py,sha256=AXaUzQ1nhQ-vXhW4-X-91vE2VQtEcCOrGtQXXNN55iQ,29
|
|
40
|
-
schemathesis/cli/output/default.py,sha256=
|
|
42
|
+
schemathesis/cli/output/default.py,sha256=GjT-j9pNxVYQmU6nOu08hBqvR9uD_TMI15jZitWgI0A,36781
|
|
41
43
|
schemathesis/cli/output/short.py,sha256=MmFMOKBRqqvgq7Kmx6XJc7Vqkr9g5BrJBxRbyZ0Rh-k,2068
|
|
42
44
|
schemathesis/contrib/__init__.py,sha256=FH8NL8NXgSKBFOF8Jy_EB6T4CJEaiM-tmDhz16B2o4k,187
|
|
43
45
|
schemathesis/contrib/unique_data.py,sha256=zxrmAlQH7Bcil9YSfy2EazwLj2rxLzOvAE3O6QRRkFY,1317
|
|
@@ -66,9 +68,9 @@ schemathesis/internal/validation.py,sha256=G7i8jIMUpAeOnDsDF_eWYvRZe_yMprRswx0QA
|
|
|
66
68
|
schemathesis/runner/__init__.py,sha256=kkqjC_5G2Mrq00syLNUDHP3sXqwiId8_cusKtIlOyXM,21419
|
|
67
69
|
schemathesis/runner/events.py,sha256=eZc4TT8C8mWCMr9h4JvlijvQQ-x8wFry8LntdsYIL-A,10200
|
|
68
70
|
schemathesis/runner/probes.py,sha256=t_B38-ljy-p3Odw-dqcZUVIjYTPwBvac8KE5GaLnz4M,5546
|
|
69
|
-
schemathesis/runner/serialization.py,sha256=
|
|
71
|
+
schemathesis/runner/serialization.py,sha256=7DBve7E6JAbAHH5npzjME7lFnysKCc9dPXMmdIIYrNI,16667
|
|
70
72
|
schemathesis/runner/impl/__init__.py,sha256=1E2iME8uthYPBh9MjwVBCTFV-P3fi7AdphCCoBBspjs,199
|
|
71
|
-
schemathesis/runner/impl/core.py,sha256=
|
|
73
|
+
schemathesis/runner/impl/core.py,sha256=w0Ky7DuOQD3qpMPBP2E5Pr04d5N_eKyKNyCVZAEEZJc,39684
|
|
72
74
|
schemathesis/runner/impl/solo.py,sha256=Y_tNhVBVxcuxv65hN0FjxLlVSC41ebHMOM1xSzVrNk8,3358
|
|
73
75
|
schemathesis/runner/impl/threadpool.py,sha256=2-2Wvw7msezZtenZY5vU_x3FGLLVlH-ywvhU9hTwAAo,15073
|
|
74
76
|
schemathesis/service/__init__.py,sha256=cDVTCFD1G-vvhxZkJUwiToTAEQ-0ByIoqwXvJBCf_V8,472
|
|
@@ -86,13 +88,13 @@ schemathesis/service/serialization.py,sha256=OjWG7FfihEl4LtpOD8N-fmjOTzSPUm6A4x6
|
|
|
86
88
|
schemathesis/service/usage.py,sha256=Z-GCwFcW1pS6YdC-ziEOynikqgOttxp2Uyj_dfK5Q7A,2437
|
|
87
89
|
schemathesis/specs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
88
90
|
schemathesis/specs/graphql/__init__.py,sha256=fgyHtvWNUVWismBTOqxQtgLoTighTfvMv6v6QCD_Oyc,85
|
|
89
|
-
schemathesis/specs/graphql/loaders.py,sha256=
|
|
91
|
+
schemathesis/specs/graphql/loaders.py,sha256=5BcHD-w0XU_CRfS53SN4iuGDOfvUfjOfyiRMRGmNDVc,11461
|
|
90
92
|
schemathesis/specs/graphql/nodes.py,sha256=7F5jbk96uTZZXK9Ulr86KpCAn8z6LKMBcrLrdJHggH0,540
|
|
91
93
|
schemathesis/specs/graphql/scalars.py,sha256=W5oj6AcjiXpR-Z6eSSp1oPWl0mjH2NF-w87nRFhrHHg,1805
|
|
92
|
-
schemathesis/specs/graphql/schemas.py,sha256=
|
|
94
|
+
schemathesis/specs/graphql/schemas.py,sha256=6BlTF9iAongsDxzy4_l85YjDob2QzpB0Vt7mlbIUxaw,12637
|
|
93
95
|
schemathesis/specs/graphql/validation.py,sha256=SqQbj9uymGUQxlHXc8HkQccIq25uwP5CvLF1zReb1Xg,1636
|
|
94
96
|
schemathesis/specs/openapi/__init__.py,sha256=HDcx3bqpa6qWPpyMrxAbM3uTo0Lqpg-BUNZhDJSJKnw,279
|
|
95
|
-
schemathesis/specs/openapi/_hypothesis.py,sha256=
|
|
97
|
+
schemathesis/specs/openapi/_hypothesis.py,sha256=o1ssS7JJZ45l750ogoZ3gXoedzLmRsXqpPb1LCZXikY,22835
|
|
96
98
|
schemathesis/specs/openapi/checks.py,sha256=1WB_UGNqptfJThWLUNbds1Q-IzOGbbHCOYPIhBYk-zs,5411
|
|
97
99
|
schemathesis/specs/openapi/constants.py,sha256=JqM_FHOenqS_MuUE9sxVQ8Hnw0DNM8cnKDwCwPLhID4,783
|
|
98
100
|
schemathesis/specs/openapi/converter.py,sha256=9TKeKvNi9MVvoNMfqoPz_cODO8oNrMSTXTOwLLfjD_Q,2799
|
|
@@ -101,7 +103,7 @@ schemathesis/specs/openapi/examples.py,sha256=igLDfMpNhRMAk7mYBqi93CtVRQTZCWjCJ2
|
|
|
101
103
|
schemathesis/specs/openapi/filters.py,sha256=Ei-QTFcGCvGSIunT-GYQrtqzB-kqvUePOcUuC7B7mT8,1436
|
|
102
104
|
schemathesis/specs/openapi/formats.py,sha256=JmmkQWNAj5XreXb7Edgj4LADAf4m86YulR_Ec8evpJ4,1220
|
|
103
105
|
schemathesis/specs/openapi/links.py,sha256=FUjqEf6Sv6PeS0UX7CLL5p2VHa9vA1MGDPhx2pfYg1s,14576
|
|
104
|
-
schemathesis/specs/openapi/loaders.py,sha256=
|
|
106
|
+
schemathesis/specs/openapi/loaders.py,sha256=QoEFJ7fxJz5XcGTEWV_ZGXARiektmyyT_xmVtcHco6Q,24131
|
|
105
107
|
schemathesis/specs/openapi/media_types.py,sha256=dNTxpRQbY3SubdVjh4Cjb38R6Bc9MF9BsRQwPD87x0g,1017
|
|
106
108
|
schemathesis/specs/openapi/parameters.py,sha256=5jMZQZFsZNBFjG22Bqot-Rc65emiSA4E95rIzwImThk,13610
|
|
107
109
|
schemathesis/specs/openapi/references.py,sha256=YGunHAGubYPKbMqQtpFWZm1D4AGxB8wLuiVhE6T6cWo,8978
|
|
@@ -123,14 +125,14 @@ schemathesis/specs/openapi/negative/utils.py,sha256=ozcOIuASufLqZSgnKUACjX-EOZrr
|
|
|
123
125
|
schemathesis/specs/openapi/stateful/__init__.py,sha256=R8RhPJD3rDzqL4eA9jSnUwh9Q_Mv27ka1C5FdRuyusY,4509
|
|
124
126
|
schemathesis/specs/openapi/stateful/links.py,sha256=cSIwho2Hroty6au-gyCD-OwqnuCcIpnIIHU6FvF0SwA,3533
|
|
125
127
|
schemathesis/stateful/__init__.py,sha256=T7rvhzftfl3wumEsir33DBBzCTK2PtRp9CxBxMLdMSE,4693
|
|
126
|
-
schemathesis/stateful/state_machine.py,sha256=
|
|
127
|
-
schemathesis/transports/__init__.py,sha256=
|
|
128
|
+
schemathesis/stateful/state_machine.py,sha256=ZcKpbvEl1QGhVOYnA7Ow6zkuFHtEPDAyCjroPrj-FgU,11343
|
|
129
|
+
schemathesis/transports/__init__.py,sha256=YEbD9etlUf6uR_9H8SO01uq2nJ2WBRv30k2pxolOwtE,11203
|
|
128
130
|
schemathesis/transports/auth.py,sha256=ZKFku9gjhIG6445qNC2p_64Yt9Iz_4azbvja8AMptBk,404
|
|
129
131
|
schemathesis/transports/content_types.py,sha256=xU8RZWxz-CyWRqQTI2fGYQacB7KasoY7LL_bxPQdyPY,2144
|
|
130
132
|
schemathesis/transports/headers.py,sha256=EDxpm8su0AuhyqZUkMex-OFZMAJN_5NHah7fDT2HDZE,989
|
|
131
|
-
schemathesis/transports/responses.py,sha256=
|
|
132
|
-
schemathesis-3.
|
|
133
|
-
schemathesis-3.
|
|
134
|
-
schemathesis-3.
|
|
135
|
-
schemathesis-3.
|
|
136
|
-
schemathesis-3.
|
|
133
|
+
schemathesis/transports/responses.py,sha256=j_-udvWbmi6XtEYmpdX8WoFnlrQ6-i3PSBizfozRjQI,1673
|
|
134
|
+
schemathesis-3.27.0.dist-info/METADATA,sha256=wVeeZfcbs3AdGnpqcsHGrfx4iYX9gIV8kYgY_HW01Ps,16257
|
|
135
|
+
schemathesis-3.27.0.dist-info/WHEEL,sha256=hKi7AIIx6qfnsRbr087vpeJnrVUuDokDHZacPPMW7-Y,87
|
|
136
|
+
schemathesis-3.27.0.dist-info/entry_points.txt,sha256=VHyLcOG7co0nOeuk8WjgpRETk5P1E2iCLrn26Zkn5uk,158
|
|
137
|
+
schemathesis-3.27.0.dist-info/licenses/LICENSE,sha256=PsPYgrDhZ7g9uwihJXNG-XVb55wj2uYhkl2DD8oAzY0,1103
|
|
138
|
+
schemathesis-3.27.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|