schemathesis 3.34.0__py3-none-any.whl → 3.34.2__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/specs/openapi/checks.py +19 -52
- schemathesis/transports/__init__.py +1 -0
- {schemathesis-3.34.0.dist-info → schemathesis-3.34.2.dist-info}/METADATA +1 -1
- {schemathesis-3.34.0.dist-info → schemathesis-3.34.2.dist-info}/RECORD +7 -7
- {schemathesis-3.34.0.dist-info → schemathesis-3.34.2.dist-info}/WHEEL +0 -0
- {schemathesis-3.34.0.dist-info → schemathesis-3.34.2.dist-info}/entry_points.txt +0 -0
- {schemathesis-3.34.0.dist-info → schemathesis-3.34.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
4
|
from http.cookies import SimpleCookie
|
|
5
5
|
from typing import TYPE_CHECKING, Any, Dict, Generator, NoReturn, cast
|
|
6
|
-
from urllib.parse import parse_qs,
|
|
6
|
+
from urllib.parse import parse_qs, urlparse
|
|
7
7
|
|
|
8
8
|
from ... import failures
|
|
9
9
|
from ...exceptions import (
|
|
@@ -150,15 +150,17 @@ def response_headers_conformance(response: GenericResponse, case: Case) -> bool
|
|
|
150
150
|
for name, definition in defined_headers.items():
|
|
151
151
|
value = response.headers.get(name)
|
|
152
152
|
if value is not None:
|
|
153
|
-
parameter_definition = {"in": "header", **definition}
|
|
154
|
-
parameter: OpenAPI20Parameter | OpenAPI30Parameter
|
|
155
|
-
if isinstance(case.operation.schema, OpenApi30):
|
|
156
|
-
parameter = OpenAPI30Parameter(parameter_definition)
|
|
157
|
-
else:
|
|
158
|
-
parameter = OpenAPI20Parameter(parameter_definition)
|
|
159
|
-
schema = parameter.as_json_schema(case.operation)
|
|
160
|
-
coerced = _coerce_header_value(value, schema)
|
|
161
153
|
with case.operation.schema._validating_response(scopes) as resolver:
|
|
154
|
+
if "$ref" in definition:
|
|
155
|
+
_, definition = resolver.resolve(definition["$ref"])
|
|
156
|
+
parameter_definition = {"in": "header", **definition}
|
|
157
|
+
parameter: OpenAPI20Parameter | OpenAPI30Parameter
|
|
158
|
+
if isinstance(case.operation.schema, OpenApi30):
|
|
159
|
+
parameter = OpenAPI30Parameter(parameter_definition)
|
|
160
|
+
else:
|
|
161
|
+
parameter = OpenAPI20Parameter(parameter_definition)
|
|
162
|
+
schema = parameter.as_json_schema(case.operation)
|
|
163
|
+
coerced = _coerce_header_value(value, schema)
|
|
162
164
|
try:
|
|
163
165
|
jsonschema.validate(
|
|
164
166
|
coerced,
|
|
@@ -332,8 +334,6 @@ def ensure_resource_availability(response: GenericResponse, original: Case) -> b
|
|
|
332
334
|
|
|
333
335
|
def ignored_auth(response: GenericResponse, case: Case) -> bool | None:
|
|
334
336
|
"""Check if an operation declares authentication as a requirement but does not actually enforce it."""
|
|
335
|
-
from requests import Session
|
|
336
|
-
|
|
337
337
|
from .schemas import BaseOpenAPISchema
|
|
338
338
|
|
|
339
339
|
if not isinstance(case.operation.schema, BaseOpenAPISchema):
|
|
@@ -344,14 +344,15 @@ def ignored_auth(response: GenericResponse, case: Case) -> bool | None:
|
|
|
344
344
|
if security_parameters and 200 <= response.status_code < 300:
|
|
345
345
|
if _contains_auth(response.request, security_parameters):
|
|
346
346
|
# If there is auth in the request, then drop it and retry the call
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
new_response
|
|
350
|
-
if new_response.ok:
|
|
347
|
+
_remove_auth_from_case(case, security_parameters)
|
|
348
|
+
new_response = case.operation.schema.transport.send(case)
|
|
349
|
+
if 200 <= new_response.status_code < 300:
|
|
351
350
|
# Mutate the response object in place on the best effort basis
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
351
|
+
if hasattr(response, "__attrs__"):
|
|
352
|
+
for attribute in new_response.__attrs__:
|
|
353
|
+
setattr(response, attribute, getattr(new_response, attribute))
|
|
354
|
+
else:
|
|
355
|
+
response.__dict__.update(new_response.__dict__)
|
|
355
356
|
_raise_auth_error(new_response, case.operation.verbose_name)
|
|
356
357
|
else:
|
|
357
358
|
# Successful response when there is no auth
|
|
@@ -415,40 +416,6 @@ def _contains_auth(request: PreparedRequest, security_parameters: list[SecurityP
|
|
|
415
416
|
return False
|
|
416
417
|
|
|
417
418
|
|
|
418
|
-
def _remove_auth_from_request(
|
|
419
|
-
request: PreparedRequest, security_parameters: list[SecurityParameter]
|
|
420
|
-
) -> PreparedRequest:
|
|
421
|
-
"""Remove security parameters from a request."""
|
|
422
|
-
from requests.cookies import get_cookie_header
|
|
423
|
-
|
|
424
|
-
request = request.copy()
|
|
425
|
-
parsed = urlparse(request.url)
|
|
426
|
-
query = parse_qs(parsed.query) # type: ignore
|
|
427
|
-
should_replace_url = False
|
|
428
|
-
|
|
429
|
-
for parameter in security_parameters:
|
|
430
|
-
name = parameter["name"]
|
|
431
|
-
if parameter["in"] == "header":
|
|
432
|
-
request.headers.pop(name, None)
|
|
433
|
-
if parameter["in"] == "query":
|
|
434
|
-
query.pop(name, None)
|
|
435
|
-
should_replace_url = True
|
|
436
|
-
if parameter["in"] == "cookie":
|
|
437
|
-
del request._cookies[name] # type: ignore
|
|
438
|
-
|
|
439
|
-
if should_replace_url:
|
|
440
|
-
components = [parsed.scheme, parsed.netloc, parsed.path, parsed.params, urlencode(query), parsed.fragment]
|
|
441
|
-
url = cast(str, urlunparse(components)) # type: ignore
|
|
442
|
-
request.url = url
|
|
443
|
-
# Re-generate the `Cookie` header if needed
|
|
444
|
-
raw_cookie = request.headers.pop("Cookie", None)
|
|
445
|
-
if raw_cookie is not None:
|
|
446
|
-
new_cookie_header = get_cookie_header(request._cookies, request) # type: ignore
|
|
447
|
-
if new_cookie_header:
|
|
448
|
-
request.headers["Cookie"] = new_cookie_header
|
|
449
|
-
return request
|
|
450
|
-
|
|
451
|
-
|
|
452
419
|
def _remove_auth_from_case(case: Case, security_parameters: list[SecurityParameter]) -> None:
|
|
453
420
|
"""Remove security parameters from a generated case.
|
|
454
421
|
|
|
@@ -192,6 +192,7 @@ class RequestsTransport:
|
|
|
192
192
|
context=failures.RequestTimeout(message=message, timeout=timeout),
|
|
193
193
|
) from None
|
|
194
194
|
response.verify = verify # type: ignore[attr-defined]
|
|
195
|
+
response._session = session # type: ignore[attr-defined]
|
|
195
196
|
if close_session:
|
|
196
197
|
session.close()
|
|
197
198
|
return response
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: schemathesis
|
|
3
|
-
Version: 3.34.
|
|
3
|
+
Version: 3.34.2
|
|
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
|
|
@@ -100,7 +100,7 @@ schemathesis/specs/graphql/validation.py,sha256=uINIOt-2E7ZuQV2CxKzwez-7L9tDtqzM
|
|
|
100
100
|
schemathesis/specs/openapi/__init__.py,sha256=HDcx3bqpa6qWPpyMrxAbM3uTo0Lqpg-BUNZhDJSJKnw,279
|
|
101
101
|
schemathesis/specs/openapi/_cache.py,sha256=PAiAu4X_a2PQgD2lG5H3iisXdyg4SaHpU46bRZvfNkM,4320
|
|
102
102
|
schemathesis/specs/openapi/_hypothesis.py,sha256=XtC-rYiH-GHvWykdSSzPFVK7jHNNL7NtibjSEeIZDQw,24122
|
|
103
|
-
schemathesis/specs/openapi/checks.py,sha256=
|
|
103
|
+
schemathesis/specs/openapi/checks.py,sha256=LiwoL5W_qK40j-JFSc9hfM8IGSszMBUWe71YZJ5FBzw,19931
|
|
104
104
|
schemathesis/specs/openapi/constants.py,sha256=JqM_FHOenqS_MuUE9sxVQ8Hnw0DNM8cnKDwCwPLhID4,783
|
|
105
105
|
schemathesis/specs/openapi/converter.py,sha256=TaYgc5BBHPdkN-n0lqpbeVgLu3eL3L8Wu3y_Vo3TJaQ,2800
|
|
106
106
|
schemathesis/specs/openapi/definitions.py,sha256=Z186F0gNBSCmPg-Kk7Q-n6XxEZHIOzgUyeqixlC62XE,94058
|
|
@@ -139,13 +139,13 @@ schemathesis/stateful/sink.py,sha256=xjsqJYH5WETKh5pDGlchYyjT3HcjzHEotUjvo1p0JsE
|
|
|
139
139
|
schemathesis/stateful/state_machine.py,sha256=u7PkwCjxTZZcePC7GPiOUuu4uhqUees3UuorD_0Sx_c,12938
|
|
140
140
|
schemathesis/stateful/statistic.py,sha256=xPLiCw61ofNXQicqcK_sZyLHiqiGcgQARpwd8AiRubM,487
|
|
141
141
|
schemathesis/stateful/validation.py,sha256=JtqnRzl11ZbVR8Lcr0xBJKoOXzx8VUfRz92jOnB2Smg,3605
|
|
142
|
-
schemathesis/transports/__init__.py,sha256=
|
|
142
|
+
schemathesis/transports/__init__.py,sha256=L60_GCzJiX9jFYKVft4aeZb8EmyV6e72k8K73y2zvmE,12898
|
|
143
143
|
schemathesis/transports/auth.py,sha256=yELjkEkfx4g74hNrd0Db9aFf0xDJDRIwhg2vzKOTZGg,1138
|
|
144
144
|
schemathesis/transports/content_types.py,sha256=VrcRQvF5T_TUjrCyrZcYF2LOwKfs3IrLcMtkVSp1ImI,2189
|
|
145
145
|
schemathesis/transports/headers.py,sha256=hr_AIDOfUxsJxpHfemIZ_uNG3_vzS_ZeMEKmZjbYiBE,990
|
|
146
146
|
schemathesis/transports/responses.py,sha256=6-gvVcRK0Ho_lSydUysBNFWoJwZEiEgf6Iv-GWkQGd8,1675
|
|
147
|
-
schemathesis-3.34.
|
|
148
|
-
schemathesis-3.34.
|
|
149
|
-
schemathesis-3.34.
|
|
150
|
-
schemathesis-3.34.
|
|
151
|
-
schemathesis-3.34.
|
|
147
|
+
schemathesis-3.34.2.dist-info/METADATA,sha256=_1OPHWfBbVS9tUFtPcJJzu5L278bmaNBTfmgpafdmN0,18373
|
|
148
|
+
schemathesis-3.34.2.dist-info/WHEEL,sha256=hKi7AIIx6qfnsRbr087vpeJnrVUuDokDHZacPPMW7-Y,87
|
|
149
|
+
schemathesis-3.34.2.dist-info/entry_points.txt,sha256=VHyLcOG7co0nOeuk8WjgpRETk5P1E2iCLrn26Zkn5uk,158
|
|
150
|
+
schemathesis-3.34.2.dist-info/licenses/LICENSE,sha256=PsPYgrDhZ7g9uwihJXNG-XVb55wj2uYhkl2DD8oAzY0,1103
|
|
151
|
+
schemathesis-3.34.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|