schemathesis 4.1.0__py3-none-any.whl → 4.1.1__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/core/__init__.py +1 -0
- schemathesis/core/failures.py +2 -1
- schemathesis/engine/phases/stateful/_executor.py +9 -1
- schemathesis/engine/phases/unit/_executor.py +13 -0
- schemathesis/filters.py +4 -0
- schemathesis/generation/hypothesis/builder.py +14 -1
- schemathesis/hooks.py +24 -10
- schemathesis/pytest/plugin.py +6 -0
- schemathesis/schemas.py +9 -1
- schemathesis/specs/openapi/checks.py +4 -1
- schemathesis/specs/openapi/schemas.py +24 -2
- {schemathesis-4.1.0.dist-info → schemathesis-4.1.1.dist-info}/METADATA +1 -1
- {schemathesis-4.1.0.dist-info → schemathesis-4.1.1.dist-info}/RECORD +16 -16
- {schemathesis-4.1.0.dist-info → schemathesis-4.1.1.dist-info}/WHEEL +0 -0
- {schemathesis-4.1.0.dist-info → schemathesis-4.1.1.dist-info}/entry_points.txt +0 -0
- {schemathesis-4.1.0.dist-info → schemathesis-4.1.1.dist-info}/licenses/LICENSE +0 -0
schemathesis/core/__init__.py
CHANGED
@@ -7,6 +7,7 @@ SCHEMATHESIS_TEST_CASE_HEADER = "X-Schemathesis-TestCaseId"
|
|
7
7
|
HYPOTHESIS_IN_MEMORY_DATABASE_IDENTIFIER = ":memory:"
|
8
8
|
INTERNAL_BUFFER_SIZE = 32 * 1024
|
9
9
|
DEFAULT_STATEFUL_STEP_COUNT = 6
|
10
|
+
INJECTED_PATH_PARAMETER_KEY = "x-schemathesis-injected"
|
10
11
|
|
11
12
|
|
12
13
|
class NotSet: ...
|
schemathesis/core/failures.py
CHANGED
@@ -310,6 +310,7 @@ def format_failures(
|
|
310
310
|
output += "\n <NO RESPONSE>"
|
311
311
|
|
312
312
|
# cURL
|
313
|
-
|
313
|
+
_curl = "\n".join(f" {line}" for line in curl.splitlines())
|
314
|
+
output += "\n" + formatter(MessageBlock.CURL, f"\nReproduce with: \n\n{_curl}")
|
314
315
|
|
315
316
|
return output
|
@@ -330,10 +330,18 @@ def validate_response(
|
|
330
330
|
if stateful_ctx.is_seen_in_suite(failure) or stateful_ctx.is_seen_in_run(failure):
|
331
331
|
return
|
332
332
|
failure_data = recorder.find_failure_data(parent_id=case.id, failure=failure)
|
333
|
+
|
334
|
+
# Collect the whole chain of cURL commands
|
335
|
+
commands = []
|
336
|
+
parent = recorder.find_parent(case_id=failure_data.case.id)
|
337
|
+
while parent is not None:
|
338
|
+
commands.append(parent.as_curl_command(headers=failure_data.headers, verify=failure_data.verify))
|
339
|
+
parent = recorder.find_parent(case_id=parent.id)
|
340
|
+
commands.append(failure_data.case.as_curl_command(headers=failure_data.headers, verify=failure_data.verify))
|
333
341
|
recorder.record_check_failure(
|
334
342
|
name=name,
|
335
343
|
case_id=failure_data.case.id,
|
336
|
-
code_sample=
|
344
|
+
code_sample="\n".join(commands),
|
337
345
|
failure=failure,
|
338
346
|
)
|
339
347
|
control.count_failure()
|
@@ -49,6 +49,7 @@ from schemathesis.generation.case import Case
|
|
49
49
|
from schemathesis.generation.hypothesis.builder import (
|
50
50
|
InvalidHeadersExampleMark,
|
51
51
|
InvalidRegexMark,
|
52
|
+
MissingPathParameters,
|
52
53
|
NonSerializableMark,
|
53
54
|
UnsatisfiableExampleMark,
|
54
55
|
)
|
@@ -73,6 +74,7 @@ def run_test(
|
|
73
74
|
yield scenario_started
|
74
75
|
errors: list[Exception] = []
|
75
76
|
skip_reason = None
|
77
|
+
error: Exception
|
76
78
|
test_start_time = time.monotonic()
|
77
79
|
recorder = ScenarioRecorder(label=operation.label)
|
78
80
|
state = TestingState()
|
@@ -227,11 +229,15 @@ def run_test(
|
|
227
229
|
and any(check.status == Status.FAILURE for checks in recorder.checks.values() for check in checks)
|
228
230
|
):
|
229
231
|
status = Status.FAILURE
|
232
|
+
|
233
|
+
# Check for various errors during generation (tests may still have been generated)
|
234
|
+
|
230
235
|
if UnsatisfiableExampleMark.is_set(test_function):
|
231
236
|
status = Status.ERROR
|
232
237
|
yield non_fatal_error(
|
233
238
|
hypothesis.errors.Unsatisfiable("Failed to generate test cases from examples for this API operation")
|
234
239
|
)
|
240
|
+
|
235
241
|
non_serializable = NonSerializableMark.get(test_function)
|
236
242
|
if non_serializable is not None and status != Status.ERROR:
|
237
243
|
status = Status.ERROR
|
@@ -248,10 +254,17 @@ def run_test(
|
|
248
254
|
if invalid_regex is not None and status != Status.ERROR:
|
249
255
|
status = Status.ERROR
|
250
256
|
yield non_fatal_error(InvalidRegexPattern.from_schema_error(invalid_regex, from_examples=True))
|
257
|
+
|
251
258
|
invalid_headers = InvalidHeadersExampleMark.get(test_function)
|
252
259
|
if invalid_headers:
|
253
260
|
status = Status.ERROR
|
254
261
|
yield non_fatal_error(InvalidHeadersExample.from_headers(invalid_headers))
|
262
|
+
|
263
|
+
missing_path_parameters = MissingPathParameters.get(test_function)
|
264
|
+
if missing_path_parameters:
|
265
|
+
status = Status.ERROR
|
266
|
+
yield non_fatal_error(missing_path_parameters)
|
267
|
+
|
255
268
|
for error in deduplicate_errors(errors):
|
256
269
|
yield non_fatal_error(error)
|
257
270
|
|
schemathesis/filters.py
CHANGED
@@ -175,6 +175,10 @@ class FilterSet:
|
|
175
175
|
"""Whether the filter set does not contain any filters."""
|
176
176
|
return not self._includes and not self._excludes
|
177
177
|
|
178
|
+
def clear(self) -> None:
|
179
|
+
self._includes.clear()
|
180
|
+
self._excludes.clear()
|
181
|
+
|
178
182
|
def include(
|
179
183
|
self,
|
180
184
|
func: MatcherFunc | None = None,
|
@@ -20,7 +20,7 @@ from requests.models import CaseInsensitiveDict
|
|
20
20
|
from schemathesis import auths
|
21
21
|
from schemathesis.auths import AuthStorage, AuthStorageMark
|
22
22
|
from schemathesis.config import GenerationConfig, ProjectConfig
|
23
|
-
from schemathesis.core import NOT_SET, NotSet, SpecificationFeature, media_types
|
23
|
+
from schemathesis.core import INJECTED_PATH_PARAMETER_KEY, NOT_SET, NotSet, SpecificationFeature, media_types
|
24
24
|
from schemathesis.core.errors import InvalidSchema, SerializationNotPossible
|
25
25
|
from schemathesis.core.marks import Mark
|
26
26
|
from schemathesis.core.transforms import deepclone
|
@@ -185,6 +185,18 @@ def create_test(
|
|
185
185
|
generation_config=generation,
|
186
186
|
)
|
187
187
|
|
188
|
+
injected_path_parameter_names = [
|
189
|
+
parameter.name
|
190
|
+
for parameter in operation.path_parameters
|
191
|
+
if parameter.definition.get(INJECTED_PATH_PARAMETER_KEY)
|
192
|
+
]
|
193
|
+
if injected_path_parameter_names:
|
194
|
+
names = ", ".join(f"'{name}'" for name in injected_path_parameter_names)
|
195
|
+
plural = "s" if len(injected_path_parameter_names) > 1 else ""
|
196
|
+
verb = "are" if len(injected_path_parameter_names) > 1 else "is"
|
197
|
+
error = InvalidSchema(f"Path parameter{plural} {names} {verb} not defined")
|
198
|
+
MissingPathParameters.set(hypothesis_test, error)
|
199
|
+
|
188
200
|
setattr(hypothesis_test, SETTINGS_ATTRIBUTE_NAME, settings)
|
189
201
|
|
190
202
|
return hypothesis_test
|
@@ -902,3 +914,4 @@ UnsatisfiableExampleMark = Mark[Unsatisfiable](attr_name="unsatisfiable_example"
|
|
902
914
|
NonSerializableMark = Mark[SerializationNotPossible](attr_name="non_serializable")
|
903
915
|
InvalidRegexMark = Mark[SchemaError](attr_name="invalid_regex")
|
904
916
|
InvalidHeadersExampleMark = Mark[dict[str, str]](attr_name="invalid_example_header")
|
917
|
+
MissingPathParameters = Mark[InvalidSchema](attr_name="missing_path_parameters")
|
schemathesis/hooks.py
CHANGED
@@ -2,10 +2,11 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
import inspect
|
4
4
|
from collections import defaultdict
|
5
|
+
from contextlib import contextmanager
|
5
6
|
from dataclasses import dataclass, field
|
6
7
|
from enum import Enum, unique
|
7
8
|
from functools import lru_cache, partial
|
8
|
-
from typing import TYPE_CHECKING, Any, Callable, ClassVar, cast
|
9
|
+
from typing import TYPE_CHECKING, Any, Callable, ClassVar, Generator, cast
|
9
10
|
|
10
11
|
from schemathesis.core.marks import Mark
|
11
12
|
from schemathesis.core.transport import Response
|
@@ -54,18 +55,28 @@ def to_filterable_hook(dispatcher: HookDispatcher) -> Callable:
|
|
54
55
|
filter_used = False
|
55
56
|
filter_set = FilterSet()
|
56
57
|
|
58
|
+
@contextmanager
|
59
|
+
def _reset_on_error() -> Generator:
|
60
|
+
try:
|
61
|
+
yield
|
62
|
+
except Exception:
|
63
|
+
filter_set.clear()
|
64
|
+
raise
|
65
|
+
|
57
66
|
def register(hook: str | Callable) -> Callable:
|
58
67
|
nonlocal filter_set
|
59
68
|
|
60
69
|
if filter_used:
|
61
|
-
|
70
|
+
with _reset_on_error():
|
71
|
+
validate_filterable_hook(hook)
|
62
72
|
|
63
73
|
if isinstance(hook, str):
|
64
74
|
|
65
75
|
def decorator(func: Callable) -> Callable:
|
66
76
|
hook_name = cast(str, hook)
|
67
77
|
if filter_used:
|
68
|
-
|
78
|
+
with _reset_on_error():
|
79
|
+
validate_filterable_hook(hook)
|
69
80
|
func.filter_set = filter_set # type: ignore[attr-defined]
|
70
81
|
return dispatcher.register_hook_with_name(func, hook_name)
|
71
82
|
|
@@ -86,13 +97,15 @@ def to_filterable_hook(dispatcher: HookDispatcher) -> Callable:
|
|
86
97
|
nonlocal filter_used
|
87
98
|
|
88
99
|
filter_used = True
|
89
|
-
|
100
|
+
with _reset_on_error():
|
101
|
+
filter_set.include(*args, **kwargs)
|
90
102
|
|
91
103
|
def exclude(*args: Any, **kwargs: Any) -> None:
|
92
104
|
nonlocal filter_used
|
93
105
|
|
94
106
|
filter_used = True
|
95
|
-
|
107
|
+
with _reset_on_error():
|
108
|
+
filter_set.exclude(*args, **kwargs)
|
96
109
|
|
97
110
|
attach_filter_chain(target, "apply_to", include)
|
98
111
|
attach_filter_chain(target, "skip_for", exclude)
|
@@ -113,11 +126,9 @@ class HookDispatcher:
|
|
113
126
|
_hooks: defaultdict[str, list[Callable]] = field(default_factory=lambda: defaultdict(list))
|
114
127
|
_specs: ClassVar[dict[str, RegisteredHook]] = {}
|
115
128
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
def hook(self, hook: str | Callable) -> Callable:
|
120
|
-
raise NotImplementedError
|
129
|
+
@property
|
130
|
+
def hook(self) -> Callable:
|
131
|
+
return to_filterable_hook(self)
|
121
132
|
|
122
133
|
def apply(self, hook: Callable, *, name: str | None = None) -> Callable[[Callable], Callable]:
|
123
134
|
"""Register hook to run only on one test function.
|
@@ -201,6 +212,9 @@ class HookDispatcher:
|
|
201
212
|
"""Get a list of hooks registered for a name."""
|
202
213
|
return self._hooks.get(name, [])
|
203
214
|
|
215
|
+
def get_all(self) -> dict[str, list[Callable]]:
|
216
|
+
return self._hooks
|
217
|
+
|
204
218
|
def apply_to_container(
|
205
219
|
self, strategy: st.SearchStrategy, container: str, context: HookContext
|
206
220
|
) -> st.SearchStrategy:
|
schemathesis/pytest/plugin.py
CHANGED
@@ -298,6 +298,7 @@ def pytest_pyfunc_call(pyfuncitem): # type:ignore
|
|
298
298
|
from schemathesis.generation.hypothesis.builder import (
|
299
299
|
InvalidHeadersExampleMark,
|
300
300
|
InvalidRegexMark,
|
301
|
+
MissingPathParameters,
|
301
302
|
NonSerializableMark,
|
302
303
|
UnsatisfiableExampleMark,
|
303
304
|
)
|
@@ -333,8 +334,13 @@ def pytest_pyfunc_call(pyfuncitem): # type:ignore
|
|
333
334
|
pytest.skip(exc.args[0])
|
334
335
|
except SchemaError as exc:
|
335
336
|
raise InvalidRegexPattern.from_schema_error(exc, from_examples=False) from exc
|
337
|
+
|
336
338
|
invalid_headers = InvalidHeadersExampleMark.get(pyfuncitem.obj)
|
337
339
|
if invalid_headers is not None:
|
338
340
|
raise InvalidHeadersExample.from_headers(invalid_headers) from None
|
341
|
+
|
342
|
+
missing_path_parameters = MissingPathParameters.get(pyfuncitem.obj)
|
343
|
+
if missing_path_parameters:
|
344
|
+
raise missing_path_parameters from None
|
339
345
|
else:
|
340
346
|
yield
|
schemathesis/schemas.py
CHANGED
@@ -27,7 +27,7 @@ from schemathesis.generation.case import Case
|
|
27
27
|
from schemathesis.generation.hypothesis import strategies
|
28
28
|
from schemathesis.generation.hypothesis.given import GivenInput, given_proxy
|
29
29
|
from schemathesis.generation.meta import CaseMetadata
|
30
|
-
from schemathesis.hooks import HookDispatcherMark
|
30
|
+
from schemathesis.hooks import HookDispatcherMark, _should_skip_hook
|
31
31
|
|
32
32
|
from .auths import AuthStorage
|
33
33
|
from .filters import (
|
@@ -712,14 +712,22 @@ class APIOperation(Generic[P]):
|
|
712
712
|
def _apply_hooks(dispatcher: HookDispatcher, _strategy: SearchStrategy[Case]) -> SearchStrategy[Case]:
|
713
713
|
context = HookContext(operation=self)
|
714
714
|
for hook in dispatcher.get_all_by_name("before_generate_case"):
|
715
|
+
if _should_skip_hook(hook, context):
|
716
|
+
continue
|
715
717
|
_strategy = hook(context, _strategy)
|
716
718
|
for hook in dispatcher.get_all_by_name("filter_case"):
|
719
|
+
if _should_skip_hook(hook, context):
|
720
|
+
continue
|
717
721
|
hook = partial(hook, context)
|
718
722
|
_strategy = _strategy.filter(hook)
|
719
723
|
for hook in dispatcher.get_all_by_name("map_case"):
|
724
|
+
if _should_skip_hook(hook, context):
|
725
|
+
continue
|
720
726
|
hook = partial(hook, context)
|
721
727
|
_strategy = _strategy.map(hook)
|
722
728
|
for hook in dispatcher.get_all_by_name("flatmap_case"):
|
729
|
+
if _should_skip_hook(hook, context):
|
730
|
+
continue
|
723
731
|
hook = partial(hook, context)
|
724
732
|
_strategy = _strategy.flatmap(hook)
|
725
733
|
return _strategy
|
@@ -366,7 +366,10 @@ def use_after_free(ctx: CheckContext, response: Response, case: Case) -> bool |
|
|
366
366
|
|
367
367
|
if not isinstance(case.operation.schema, BaseOpenAPISchema) or is_unexpected_http_status_case(case):
|
368
368
|
return True
|
369
|
-
|
369
|
+
|
370
|
+
# Only check for use-after-free on successful responses (2xx) or redirects (3xx)
|
371
|
+
# Other status codes indicate request-level issues / server errors, not successful resource access
|
372
|
+
if not (200 <= response.status_code < 400):
|
370
373
|
return None
|
371
374
|
|
372
375
|
for related_case in ctx._find_related(case_id=case.id):
|
@@ -1,6 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import itertools
|
4
|
+
import string
|
4
5
|
from collections import defaultdict
|
5
6
|
from contextlib import ExitStack, contextmanager, suppress
|
6
7
|
from dataclasses import dataclass, field
|
@@ -29,7 +30,7 @@ from requests.exceptions import InvalidHeader
|
|
29
30
|
from requests.structures import CaseInsensitiveDict
|
30
31
|
from requests.utils import check_header_validity
|
31
32
|
|
32
|
-
from schemathesis.core import NOT_SET, NotSet, Specification, deserialization, media_types
|
33
|
+
from schemathesis.core import INJECTED_PATH_PARAMETER_KEY, NOT_SET, NotSet, Specification, deserialization, media_types
|
33
34
|
from schemathesis.core.compat import RefResolutionError
|
34
35
|
from schemathesis.core.errors import InternalError, InvalidSchema, LoaderError, LoaderErrorKind, OperationNotFound
|
35
36
|
from schemathesis.core.failures import Failure, FailureGroup, MalformedJson
|
@@ -89,6 +90,17 @@ def check_header(parameter: dict[str, Any]) -> None:
|
|
89
90
|
raise InvalidSchema(f"Invalid header name: {name}")
|
90
91
|
|
91
92
|
|
93
|
+
def get_template_fields(template: str) -> set[str]:
|
94
|
+
"""Extract named placeholders from a string template."""
|
95
|
+
try:
|
96
|
+
parameters = {name for _, name, _, _ in string.Formatter().parse(template) if name is not None}
|
97
|
+
# Check for malformed params to avoid injecting them - they will be checked later on in the workflow
|
98
|
+
template.format(**dict.fromkeys(parameters, ""))
|
99
|
+
return parameters
|
100
|
+
except (ValueError, IndexError):
|
101
|
+
return set()
|
102
|
+
|
103
|
+
|
92
104
|
@dataclass(eq=False, repr=False)
|
93
105
|
class BaseOpenAPISchema(BaseSchema):
|
94
106
|
nullable_name: ClassVar[str] = ""
|
@@ -100,6 +112,7 @@ class BaseOpenAPISchema(BaseSchema):
|
|
100
112
|
# excessive resolving
|
101
113
|
_inline_reference_cache_lock: RLock = field(default_factory=RLock)
|
102
114
|
component_locations: ClassVar[tuple[tuple[str, ...], ...]] = ()
|
115
|
+
_path_parameter_template: ClassVar[dict[str, Any]] = None # type: ignore
|
103
116
|
|
104
117
|
@property
|
105
118
|
def specification(self) -> Specification:
|
@@ -391,7 +404,6 @@ class BaseOpenAPISchema(BaseSchema):
|
|
391
404
|
resolved: dict[str, Any],
|
392
405
|
scope: str,
|
393
406
|
) -> APIOperation:
|
394
|
-
"""Create JSON schemas for the query, body, etc from Swagger parameters definitions."""
|
395
407
|
__tracebackhide__ = True
|
396
408
|
base_url = self.get_base_url()
|
397
409
|
operation: APIOperation[OpenAPIParameter] = APIOperation(
|
@@ -404,6 +416,14 @@ class BaseOpenAPISchema(BaseSchema):
|
|
404
416
|
)
|
405
417
|
for parameter in parameters:
|
406
418
|
operation.add_parameter(parameter)
|
419
|
+
# Inject unconstrained path parameters if any is missing
|
420
|
+
missing_parameter_names = get_template_fields(operation.path) - {
|
421
|
+
parameter.name for parameter in operation.path_parameters
|
422
|
+
}
|
423
|
+
for name in missing_parameter_names:
|
424
|
+
definition = {"name": name, INJECTED_PATH_PARAMETER_KEY: True, **deepclone(self._path_parameter_template)}
|
425
|
+
for parameter in self.collect_parameters([definition], resolved):
|
426
|
+
operation.add_parameter(parameter)
|
407
427
|
config = self.config.generation_for(operation=operation)
|
408
428
|
if config.with_security_parameters:
|
409
429
|
self.security.process_definitions(self.raw_schema, operation, self.resolver)
|
@@ -835,6 +855,7 @@ class SwaggerV20(BaseOpenAPISchema):
|
|
835
855
|
security = SwaggerSecurityProcessor()
|
836
856
|
component_locations: ClassVar[tuple[tuple[str, ...], ...]] = (("definitions",),)
|
837
857
|
links_field = "x-links"
|
858
|
+
_path_parameter_template = {"in": "path", "required": True, "type": "string"}
|
838
859
|
|
839
860
|
@property
|
840
861
|
def specification(self) -> Specification:
|
@@ -1003,6 +1024,7 @@ class OpenApi30(SwaggerV20):
|
|
1003
1024
|
security = OpenAPISecurityProcessor()
|
1004
1025
|
component_locations = (("components", "schemas"),)
|
1005
1026
|
links_field = "links"
|
1027
|
+
_path_parameter_template = {"in": "path", "required": True, "schema": {"type": "string"}}
|
1006
1028
|
|
1007
1029
|
@property
|
1008
1030
|
def specification(self) -> Specification:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: schemathesis
|
3
|
-
Version: 4.1.
|
3
|
+
Version: 4.1.1
|
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://github.com/schemathesis/schemathesis/blob/master/CHANGELOG.md
|
@@ -2,10 +2,10 @@ schemathesis/__init__.py,sha256=QqVUCBQr-RDEstgCZLsxzIa9HJslVSeijrm9gES4b_0,1423
|
|
2
2
|
schemathesis/auths.py,sha256=JdEwPRS9WKmPcxzGXYYz9pjlIUMQYCfif7ZJU0Kde-I,16400
|
3
3
|
schemathesis/checks.py,sha256=GTdejjXDooAOuq66nvCK3i-AMPBuU-_-aNeSeL9JIlc,6561
|
4
4
|
schemathesis/errors.py,sha256=T8nobEi5tQX_SkwaYb8JFoIlF9F_vOQVprZ8EVPAhjA,931
|
5
|
-
schemathesis/filters.py,sha256=
|
6
|
-
schemathesis/hooks.py,sha256=
|
5
|
+
schemathesis/filters.py,sha256=Nk1Z6_L0fJBIzFGwjUhx9oDHJiGn-kVxbAXWeN9gRcQ,13525
|
6
|
+
schemathesis/hooks.py,sha256=q2wqYNgpMCO8ImSBkbrWDSwN0BSELelqJMgAAgGvv2M,14836
|
7
7
|
schemathesis/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
|
-
schemathesis/schemas.py,sha256=
|
8
|
+
schemathesis/schemas.py,sha256=i0L6jYulGGASD1RiQsA6sOTNt1v812KHSZKIhnuX34s,28965
|
9
9
|
schemathesis/cli/__init__.py,sha256=U9gjzWWpiFhaqevPjZbwyTNjABdpvXETI4HgwdGKnvs,877
|
10
10
|
schemathesis/cli/__main__.py,sha256=MWaenjaUTZIfNPFzKmnkTiawUri7DVldtg3mirLwzU8,92
|
11
11
|
schemathesis/cli/constants.py,sha256=CVcQNHEiX-joAQmyuEVKWPOSxDHsOw_EXXZsEclzLuY,341
|
@@ -46,13 +46,13 @@ schemathesis/config/_report.py,sha256=ZECDpaCY4WWHD5UbjvgZoSjLz-rlTvfd5Ivzdgzqf2
|
|
46
46
|
schemathesis/config/_validator.py,sha256=IcE8geFZ0ZwR18rkIRs25i7pTl7Z84XbjYGUB-mqReU,258
|
47
47
|
schemathesis/config/_warnings.py,sha256=sI0VZcTj3dOnphhBwYwU_KTagxr89HGWTtQ99HcY84k,772
|
48
48
|
schemathesis/config/schema.json,sha256=3CRSBfUK2vLVl1h5PfeK_YDdEoBZSojYl8Q1kT-ITLE,19846
|
49
|
-
schemathesis/core/__init__.py,sha256=
|
49
|
+
schemathesis/core/__init__.py,sha256=h4gmDePIPvPiVuYxnjrpPKytSZPi6fZeVdTG6c822E4,1973
|
50
50
|
schemathesis/core/compat.py,sha256=9BWCrFoqN2sJIaiht_anxe8kLjYMR7t0iiOkXqLRUZ8,1058
|
51
51
|
schemathesis/core/control.py,sha256=IzwIc8HIAEMtZWW0Q0iXI7T1niBpjvcLlbuwOSmy5O8,130
|
52
52
|
schemathesis/core/curl.py,sha256=yuaCe_zHLGwUjEeloQi6W3tOA3cGdnHDNI17-5jia0o,1723
|
53
53
|
schemathesis/core/deserialization.py,sha256=qjXUPaz_mc1OSgXzTUSkC8tuVR8wgVQtb9g3CcAF6D0,2951
|
54
54
|
schemathesis/core/errors.py,sha256=pwiyGhX7tId88Toe2H4ZYsCDc_OvUJtW8Wv-xDv2UD4,16361
|
55
|
-
schemathesis/core/failures.py,sha256=
|
55
|
+
schemathesis/core/failures.py,sha256=yFpAxWdEnm0Ri8z8RqRI9H7vcLH5ztOeSIi4m4SGx5g,8996
|
56
56
|
schemathesis/core/fs.py,sha256=ItQT0_cVwjDdJX9IiI7EnU75NI2H3_DCEyyUjzg_BgI,472
|
57
57
|
schemathesis/core/hooks.py,sha256=qhbkkRSf8URJ4LKv2wmKRINKpquUOgxQzWBHKWRWo3Q,475
|
58
58
|
schemathesis/core/lazy_import.py,sha256=aMhWYgbU2JOltyWBb32vnWBb6kykOghucEzI_F70yVE,470
|
@@ -79,10 +79,10 @@ schemathesis/engine/recorder.py,sha256=K3HfMARrT5mPWXPnYebjjcq5CcsBRhMrtZwEL9_Lv
|
|
79
79
|
schemathesis/engine/phases/__init__.py,sha256=7Yp7dQbd6-K9pavIJeURg6jiNeMpW8UU-Iiikr668ts,3278
|
80
80
|
schemathesis/engine/phases/probes.py,sha256=YogjJcZJcTMS8sMdGnG4oXKmMUj_4r_J7MY-BBJtCRU,5690
|
81
81
|
schemathesis/engine/phases/stateful/__init__.py,sha256=Lz1rgNqCfUSIz173XqCGsiMuUI5bh4L-RIFexU1-c_Q,2461
|
82
|
-
schemathesis/engine/phases/stateful/_executor.py,sha256=
|
82
|
+
schemathesis/engine/phases/stateful/_executor.py,sha256=6YOgAGynP4UKKTITe7S39SCcnRp5OXQ7fCc8BJIFW3A,15592
|
83
83
|
schemathesis/engine/phases/stateful/context.py,sha256=A7X1SLDOWFpCvFN9IiIeNVZM0emjqatmJL_k9UsO7vM,2946
|
84
84
|
schemathesis/engine/phases/unit/__init__.py,sha256=9dDcxyj887pktnE9YDIPNaR-vc7iqKQWIrFr77SbUTQ,8786
|
85
|
-
schemathesis/engine/phases/unit/_executor.py,sha256=
|
85
|
+
schemathesis/engine/phases/unit/_executor.py,sha256=pqUISTWvnXb61rgrnzwlFn7PyR-ZsGis2kbRgBMH4EA,16519
|
86
86
|
schemathesis/engine/phases/unit/_pool.py,sha256=iU0hdHDmohPnEv7_S1emcabuzbTf-Cznqwn0pGQ5wNQ,2480
|
87
87
|
schemathesis/generation/__init__.py,sha256=tvNO2FLiY8z3fZ_kL_QJhSgzXfnT4UqwSXMHCwfLI0g,645
|
88
88
|
schemathesis/generation/case.py,sha256=Qc2_5JrWuUkCzAFTTgnVqNUJ2sioslmINTXiY7nHHgA,12326
|
@@ -92,7 +92,7 @@ schemathesis/generation/metrics.py,sha256=cZU5HdeAMcLFEDnTbNE56NuNq4P0N4ew-g1NEz
|
|
92
92
|
schemathesis/generation/modes.py,sha256=Q1fhjWr3zxabU5qdtLvKfpMFZJAwlW9pnxgenjeXTyU,481
|
93
93
|
schemathesis/generation/overrides.py,sha256=OBWqDQPreiliaf2M-oyXppVKHoJkCRzxtwSJx1b6AFw,3759
|
94
94
|
schemathesis/generation/hypothesis/__init__.py,sha256=jK3G4i0SdcyhqwPQg91RH_yg437lSY-smeIQ-wZLWPc,1959
|
95
|
-
schemathesis/generation/hypothesis/builder.py,sha256=
|
95
|
+
schemathesis/generation/hypothesis/builder.py,sha256=HOZLev-b-fkaFwDIxQHlpS59y7anyK9mJ-qw5IeQZqY,36777
|
96
96
|
schemathesis/generation/hypothesis/examples.py,sha256=6eGaKUEC3elmKsaqfKj1sLvM8EHc-PWT4NRBq4NI0Rs,1409
|
97
97
|
schemathesis/generation/hypothesis/given.py,sha256=sTZR1of6XaHAPWtHx2_WLlZ50M8D5Rjux0GmWkWjDq4,2337
|
98
98
|
schemathesis/generation/hypothesis/reporting.py,sha256=uDVow6Ya8YFkqQuOqRsjbzsbyP4KKfr3jA7ZaY4FuKY,279
|
@@ -111,7 +111,7 @@ schemathesis/pytest/__init__.py,sha256=7W0q-Thcw03IAQfXE_Mo8JPZpUdHJzfu85fjK1Zdf
|
|
111
111
|
schemathesis/pytest/control_flow.py,sha256=F8rAPsPeNv_sJiJgbZYtTpwKWjauZmqFUaKroY2GmQI,217
|
112
112
|
schemathesis/pytest/lazy.py,sha256=u58q0orI0zisivLJKJkSo53RaQMPLSMiE0vJ1TQ9_uA,11073
|
113
113
|
schemathesis/pytest/loaders.py,sha256=Sbv8e5F77_x4amLP50iwubfm6kpOhx7LhLFGsVXW5Ys,925
|
114
|
-
schemathesis/pytest/plugin.py,sha256
|
114
|
+
schemathesis/pytest/plugin.py,sha256=-c92Qi2aEvW45KLAzHj9EDXbY_mYq5B5ZdkRY9Ks_DY,14463
|
115
115
|
schemathesis/python/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
116
116
|
schemathesis/python/asgi.py,sha256=5PyvuTBaivvyPUEi3pwJni91K1kX5Zc0u9c6c1D8a1Q,287
|
117
117
|
schemathesis/python/wsgi.py,sha256=uShAgo_NChbfYaV1117e6UHp0MTg7jaR0Sy_to3Jmf8,219
|
@@ -123,7 +123,7 @@ schemathesis/specs/graphql/schemas.py,sha256=B6FULWIIWoN_gx9OeQOd-6qWsz9yVg5h1Xl
|
|
123
123
|
schemathesis/specs/graphql/validation.py,sha256=-W1Noc1MQmTb4RX-gNXMeU2qkgso4mzVfHxtdLkCPKM,1422
|
124
124
|
schemathesis/specs/openapi/__init__.py,sha256=C5HOsfuDJGq_3mv8CRBvRvb0Diy1p0BFdqyEXMS-loE,238
|
125
125
|
schemathesis/specs/openapi/_hypothesis.py,sha256=XK-g2284wCsqOuPhubpE-PQ5_YotUwNodAnjeHs_-R0,21712
|
126
|
-
schemathesis/specs/openapi/checks.py,sha256=
|
126
|
+
schemathesis/specs/openapi/checks.py,sha256=P4WaLJ_dqssrZI-fpRwsy4kZ8u6O93YvpQ-98JuMkIQ,30320
|
127
127
|
schemathesis/specs/openapi/constants.py,sha256=JqM_FHOenqS_MuUE9sxVQ8Hnw0DNM8cnKDwCwPLhID4,783
|
128
128
|
schemathesis/specs/openapi/converter.py,sha256=LkpCCAxZzET4Qa_3YStSNuhGlsm5G6TVwpxYu6lPO4g,4169
|
129
129
|
schemathesis/specs/openapi/definitions.py,sha256=8htclglV3fW6JPBqs59lgM4LnA25Mm9IptXBPb_qUT0,93949
|
@@ -133,7 +133,7 @@ schemathesis/specs/openapi/media_types.py,sha256=F5M6TKl0s6Z5X8mZpPsWDEdPBvxclKR
|
|
133
133
|
schemathesis/specs/openapi/parameters.py,sha256=XpuZ2sex2aYUzKDK17GXVNWFBmvamuyVtloQ1oGQhLk,14468
|
134
134
|
schemathesis/specs/openapi/patterns.py,sha256=GqPZEXMRdWENQxanWjBOalIZ2MQUjuxk21kmdiI703E,18027
|
135
135
|
schemathesis/specs/openapi/references.py,sha256=40YcDExPLR2B8EOwt-Csw-5MYFi2xj_DXf91J0Pc9d4,8855
|
136
|
-
schemathesis/specs/openapi/schemas.py,sha256=
|
136
|
+
schemathesis/specs/openapi/schemas.py,sha256=qJ0ChkZuXQafQ-nPwMzckSk3iC32H2O5W9Cbd7DN_2I,51379
|
137
137
|
schemathesis/specs/openapi/security.py,sha256=6UWYMhL-dPtkTineqqBFNKca1i4EuoTduw-EOLeE0aQ,7149
|
138
138
|
schemathesis/specs/openapi/serialization.py,sha256=VdDLmeHqxlWM4cxQQcCkvrU6XurivolwEEaT13ohelA,11972
|
139
139
|
schemathesis/specs/openapi/utils.py,sha256=ER4vJkdFVDIE7aKyxyYatuuHVRNutytezgE52pqZNE8,900
|
@@ -157,8 +157,8 @@ schemathesis/transport/prepare.py,sha256=erYXRaxpQokIDzaIuvt_csHcw72iHfCyNq8VNEz
|
|
157
157
|
schemathesis/transport/requests.py,sha256=XWiQVG4rGnFX0rOhOZAKVIPbrlknLuS7pHYwUcOiEGs,10942
|
158
158
|
schemathesis/transport/serialization.py,sha256=igUXKZ_VJ9gV7P0TUc5PDQBJXl_s0kK9T3ljGWWvo6E,10339
|
159
159
|
schemathesis/transport/wsgi.py,sha256=KoAfvu6RJtzyj24VGB8e-Iaa9smpgXJ3VsM8EgAz2tc,6152
|
160
|
-
schemathesis-4.1.
|
161
|
-
schemathesis-4.1.
|
162
|
-
schemathesis-4.1.
|
163
|
-
schemathesis-4.1.
|
164
|
-
schemathesis-4.1.
|
160
|
+
schemathesis-4.1.1.dist-info/METADATA,sha256=twjFIgwG3ZuiTWbHSwLnuRZtfy03aPhzwOwQQGb-TOo,8540
|
161
|
+
schemathesis-4.1.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
162
|
+
schemathesis-4.1.1.dist-info/entry_points.txt,sha256=hiK3un-xfgPdwj9uj16YVDtTNpO128bmk0U82SMv8ZQ,152
|
163
|
+
schemathesis-4.1.1.dist-info/licenses/LICENSE,sha256=2Ve4J8v5jMQAWrT7r1nf3bI8Vflk3rZVQefiF2zpxwg,1121
|
164
|
+
schemathesis-4.1.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|