schemathesis 4.0.0a7__py3-none-any.whl → 4.0.0a8__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/__init__.py +4 -0
- schemathesis/core/failures.py +1 -1
- schemathesis/engine/phases/__init__.py +1 -1
- schemathesis/engine/phases/unit/__init__.py +42 -37
- schemathesis/generation/coverage.py +37 -2
- schemathesis/generation/hypothesis/builder.py +26 -4
- schemathesis/hooks.py +1 -1
- schemathesis/pytest/plugin.py +6 -14
- schemathesis/schemas.py +18 -1
- schemathesis/specs/openapi/checks.py +1 -1
- schemathesis/specs/openapi/expressions/lexer.py +1 -1
- schemathesis/specs/openapi/expressions/nodes.py +1 -1
- schemathesis/specs/openapi/negative/mutations.py +1 -1
- schemathesis/specs/openapi/parameters.py +3 -0
- schemathesis/specs/openapi/references.py +4 -1
- schemathesis/specs/openapi/schemas.py +31 -20
- {schemathesis-4.0.0a7.dist-info → schemathesis-4.0.0a8.dist-info}/METADATA +1 -1
- {schemathesis-4.0.0a7.dist-info → schemathesis-4.0.0a8.dist-info}/RECORD +21 -21
- {schemathesis-4.0.0a7.dist-info → schemathesis-4.0.0a8.dist-info}/WHEEL +0 -0
- {schemathesis-4.0.0a7.dist-info → schemathesis-4.0.0a8.dist-info}/entry_points.txt +0 -0
- {schemathesis-4.0.0a7.dist-info → schemathesis-4.0.0a8.dist-info}/licenses/LICENSE +0 -0
schemathesis/__init__.py
CHANGED
@@ -8,6 +8,8 @@ from schemathesis.core.version import SCHEMATHESIS_VERSION
|
|
8
8
|
from schemathesis.generation import GenerationConfig, GenerationMode, HeaderConfig
|
9
9
|
from schemathesis.generation.case import Case
|
10
10
|
from schemathesis.generation.targets import TargetContext, TargetFunction, target
|
11
|
+
from schemathesis.hooks import HookContext
|
12
|
+
from schemathesis.schemas import BaseSchema
|
11
13
|
|
12
14
|
__version__ = SCHEMATHESIS_VERSION
|
13
15
|
|
@@ -26,6 +28,8 @@ __all__ = [
|
|
26
28
|
"Response",
|
27
29
|
"TargetContext",
|
28
30
|
"TargetFunction",
|
31
|
+
"HookContext",
|
32
|
+
"BaseSchema",
|
29
33
|
"__version__",
|
30
34
|
"auth",
|
31
35
|
"check",
|
schemathesis/core/failures.py
CHANGED
@@ -51,43 +51,48 @@ def execute(engine: EngineContext, phase: Phase) -> events.EventGenerator:
|
|
51
51
|
status = None
|
52
52
|
is_executed = False
|
53
53
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
if event
|
75
|
-
status
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
54
|
+
try:
|
55
|
+
with WorkerPool(
|
56
|
+
workers_num=workers_num,
|
57
|
+
producer=producer,
|
58
|
+
worker_factory=worker_task,
|
59
|
+
ctx=engine,
|
60
|
+
mode=mode,
|
61
|
+
phase=phase.name,
|
62
|
+
suite_id=suite_started.id,
|
63
|
+
) as pool:
|
64
|
+
try:
|
65
|
+
while True:
|
66
|
+
try:
|
67
|
+
event = pool.events_queue.get(timeout=WORKER_TIMEOUT)
|
68
|
+
is_executed = True
|
69
|
+
if engine.is_interrupted:
|
70
|
+
raise KeyboardInterrupt
|
71
|
+
yield event
|
72
|
+
if isinstance(event, events.NonFatalError):
|
73
|
+
status = Status.ERROR
|
74
|
+
if isinstance(event, events.ScenarioFinished):
|
75
|
+
if event.status != Status.SKIP and (status is None or status < event.status):
|
76
|
+
status = event.status
|
77
|
+
if event.status in (Status.ERROR, Status.FAILURE):
|
78
|
+
engine.control.count_failure()
|
79
|
+
if isinstance(event, events.Interrupted) or engine.is_interrupted:
|
80
|
+
status = Status.INTERRUPTED
|
81
|
+
engine.stop()
|
82
|
+
if engine.has_to_stop:
|
83
|
+
break # type: ignore[unreachable]
|
84
|
+
except queue.Empty:
|
85
|
+
if all(not worker.is_alive() for worker in pool.workers):
|
86
|
+
break
|
87
|
+
continue
|
88
|
+
except KeyboardInterrupt:
|
89
|
+
# Soft stop, waiting for workers to terminate
|
90
|
+
engine.stop()
|
91
|
+
status = Status.INTERRUPTED
|
92
|
+
yield events.Interrupted(phase=phase.name)
|
93
|
+
except KeyboardInterrupt:
|
94
|
+
# Hard stop, don't wait for worker threads
|
95
|
+
pass
|
91
96
|
|
92
97
|
if not is_executed:
|
93
98
|
phase.skip_reason = PhaseSkipReason.NOTHING_TO_TEST
|
@@ -150,7 +150,7 @@ class CoverageContext:
|
|
150
150
|
|
151
151
|
def is_valid_for_location(self, value: Any) -> bool:
|
152
152
|
if self.location in ("header", "cookie") and isinstance(value, str):
|
153
|
-
return is_latin_1_encodable(value) and not has_invalid_characters("", value)
|
153
|
+
return not value or (is_latin_1_encodable(value) and not has_invalid_characters("", value))
|
154
154
|
return True
|
155
155
|
|
156
156
|
def generate_from(self, strategy: st.SearchStrategy) -> Any:
|
@@ -437,6 +437,36 @@ def cover_schema_iter(
|
|
437
437
|
elif key == "required":
|
438
438
|
template = template or ctx.generate_from_schema(_get_template_schema(schema, "object"))
|
439
439
|
yield from _negative_required(ctx, template, value)
|
440
|
+
elif key == "maxItems" and isinstance(value, int) and value < BUFFER_SIZE:
|
441
|
+
try:
|
442
|
+
# Force the array to have one more item than allowed
|
443
|
+
new_schema = {**schema, "minItems": value + 1, "maxItems": value + 1, "type": "array"}
|
444
|
+
array_value = ctx.generate_from_schema(new_schema)
|
445
|
+
k = _to_hashable_key(array_value)
|
446
|
+
if k not in seen:
|
447
|
+
yield NegativeValue(
|
448
|
+
array_value,
|
449
|
+
description="Array with more items than allowed by maxItems",
|
450
|
+
location=ctx.current_path,
|
451
|
+
)
|
452
|
+
seen.add(k)
|
453
|
+
except (InvalidArgument, Unsatisfiable):
|
454
|
+
pass
|
455
|
+
elif key == "minItems" and isinstance(value, int) and value > 0:
|
456
|
+
try:
|
457
|
+
# Force the array to have one less item than the minimum
|
458
|
+
new_schema = {**schema, "minItems": value - 1, "maxItems": value - 1, "type": "array"}
|
459
|
+
array_value = ctx.generate_from_schema(new_schema)
|
460
|
+
k = _to_hashable_key(array_value)
|
461
|
+
if k not in seen:
|
462
|
+
yield NegativeValue(
|
463
|
+
array_value,
|
464
|
+
description="Array with fewer items than allowed by minItems",
|
465
|
+
location=ctx.current_path,
|
466
|
+
)
|
467
|
+
seen.add(k)
|
468
|
+
except (InvalidArgument, Unsatisfiable):
|
469
|
+
pass
|
440
470
|
elif (
|
441
471
|
key == "additionalProperties"
|
442
472
|
and not value
|
@@ -770,7 +800,12 @@ def _negative_enum(
|
|
770
800
|
_hashed = _to_hashable_key(x)
|
771
801
|
return _hashed not in seen
|
772
802
|
|
773
|
-
strategy = (
|
803
|
+
strategy = (
|
804
|
+
st.text(alphabet=st.characters(min_codepoint=65, max_codepoint=122, categories=["L"]), min_size=3)
|
805
|
+
| st.none()
|
806
|
+
| st.booleans()
|
807
|
+
| NUMERIC_STRATEGY
|
808
|
+
).filter(is_not_in_value)
|
774
809
|
value = ctx.generate_from(strategy)
|
775
810
|
yield NegativeValue(value, description="Invalid enum value", location=ctx.current_path)
|
776
811
|
hashed = _to_hashable_key(value)
|
@@ -1,9 +1,11 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
+
import asyncio
|
3
4
|
from dataclasses import dataclass, field
|
4
5
|
from enum import Enum
|
5
6
|
from functools import wraps
|
6
7
|
from itertools import combinations
|
8
|
+
import os
|
7
9
|
from time import perf_counter
|
8
10
|
from typing import Any, Callable, Generator, Mapping
|
9
11
|
|
@@ -15,7 +17,7 @@ from jsonschema.exceptions import SchemaError
|
|
15
17
|
|
16
18
|
from schemathesis import auths
|
17
19
|
from schemathesis.auths import AuthStorage, AuthStorageMark
|
18
|
-
from schemathesis.core import NOT_SET, NotSet, SpecificationFeature, media_types
|
20
|
+
from schemathesis.core import NOT_SET, NotSet, SpecificationFeature, media_types, string_to_boolean
|
19
21
|
from schemathesis.core.errors import InvalidSchema, SerializationNotPossible
|
20
22
|
from schemathesis.core.marks import Mark
|
21
23
|
from schemathesis.core.transport import prepare_urlencoded
|
@@ -38,7 +40,7 @@ from schemathesis.schemas import APIOperation, ParameterSet
|
|
38
40
|
setup()
|
39
41
|
|
40
42
|
|
41
|
-
class HypothesisTestMode(Enum):
|
43
|
+
class HypothesisTestMode(str, Enum):
|
42
44
|
EXAMPLES = "examples"
|
43
45
|
COVERAGE = "coverage"
|
44
46
|
FUZZING = "fuzzing"
|
@@ -120,8 +122,11 @@ def create_test(
|
|
120
122
|
):
|
121
123
|
hypothesis_test = add_examples(hypothesis_test, operation, hook_dispatcher=hook_dispatcher, **strategy_kwargs)
|
122
124
|
|
125
|
+
disable_coverage = string_to_boolean(os.getenv("SCHEMATHESIS_DISABLE_COVERAGE", ""))
|
126
|
+
|
123
127
|
if (
|
124
|
-
|
128
|
+
not disable_coverage
|
129
|
+
and HypothesisTestMode.COVERAGE in config.modes
|
125
130
|
and Phase.explicit in settings.phases
|
126
131
|
and specification.supports_feature(SpecificationFeature.COVERAGE)
|
127
132
|
and not config.given_args
|
@@ -158,7 +163,24 @@ def create_base_test(
|
|
158
163
|
__tracebackhide__ = True
|
159
164
|
return test_function(*args, **kwargs)
|
160
165
|
|
161
|
-
|
166
|
+
funcobj = hypothesis.given(*args, **{**kwargs, "case": strategy})(test_wrapper)
|
167
|
+
|
168
|
+
if asyncio.iscoroutinefunction(test_function):
|
169
|
+
funcobj.hypothesis.inner_test = make_async_test(test_function) # type: ignore
|
170
|
+
return funcobj
|
171
|
+
|
172
|
+
|
173
|
+
def make_async_test(test: Callable) -> Callable:
|
174
|
+
def async_run(*args: Any, **kwargs: Any) -> None:
|
175
|
+
try:
|
176
|
+
loop = asyncio.get_event_loop()
|
177
|
+
except RuntimeError:
|
178
|
+
loop = asyncio.new_event_loop()
|
179
|
+
coro = test(*args, **kwargs)
|
180
|
+
future = asyncio.ensure_future(coro, loop=loop)
|
181
|
+
loop.run_until_complete(future)
|
182
|
+
|
183
|
+
return async_run
|
162
184
|
|
163
185
|
|
164
186
|
def add_examples(
|
schemathesis/hooks.py
CHANGED
schemathesis/pytest/plugin.py
CHANGED
@@ -108,7 +108,12 @@ class SchemathesisCase(PyCollector):
|
|
108
108
|
This implementation is based on the original one in pytest, but with slight adjustments
|
109
109
|
to produce tests out of hypothesis ones.
|
110
110
|
"""
|
111
|
-
from schemathesis.generation.hypothesis.builder import
|
111
|
+
from schemathesis.generation.hypothesis.builder import (
|
112
|
+
HypothesisTestConfig,
|
113
|
+
HypothesisTestMode,
|
114
|
+
create_test,
|
115
|
+
make_async_test,
|
116
|
+
)
|
112
117
|
|
113
118
|
is_trio_test = False
|
114
119
|
for mark in getattr(self.test_function, "pytestmark", []):
|
@@ -221,19 +226,6 @@ class SchemathesisCase(PyCollector):
|
|
221
226
|
pytest.fail("Error during collection")
|
222
227
|
|
223
228
|
|
224
|
-
def make_async_test(test: Callable) -> Callable:
|
225
|
-
def async_run(*args: Any, **kwargs: Any) -> None:
|
226
|
-
try:
|
227
|
-
loop = asyncio.get_event_loop()
|
228
|
-
except RuntimeError:
|
229
|
-
loop = asyncio.new_event_loop()
|
230
|
-
coro = test(*args, **kwargs)
|
231
|
-
future = asyncio.ensure_future(coro, loop=loop)
|
232
|
-
loop.run_until_complete(future)
|
233
|
-
|
234
|
-
return async_run
|
235
|
-
|
236
|
-
|
237
229
|
@hookimpl(hookwrapper=True) # type:ignore
|
238
230
|
def pytest_pycollect_makeitem(collector: nodes.Collector, name: str, obj: Any) -> Generator[None, Any, None]:
|
239
231
|
"""Switch to a different collector if the test is parametrized marked by schemathesis."""
|
schemathesis/schemas.py
CHANGED
@@ -14,7 +14,7 @@ from typing import (
|
|
14
14
|
NoReturn,
|
15
15
|
TypeVar,
|
16
16
|
)
|
17
|
-
from urllib.parse import quote, unquote, urljoin, urlsplit, urlunsplit
|
17
|
+
from urllib.parse import quote, unquote, urljoin, urlparse, urlsplit, urlunsplit
|
18
18
|
|
19
19
|
from schemathesis import transport
|
20
20
|
from schemathesis.core import NOT_SET, NotSet
|
@@ -436,6 +436,8 @@ class BaseSchema(Mapping):
|
|
436
436
|
app: Any | NotSet = NOT_SET,
|
437
437
|
) -> Self:
|
438
438
|
if not isinstance(base_url, NotSet):
|
439
|
+
if base_url is not None:
|
440
|
+
validate_base_url(base_url)
|
439
441
|
self.base_url = base_url
|
440
442
|
if not isinstance(location, NotSet):
|
441
443
|
self.location = location
|
@@ -453,6 +455,21 @@ class BaseSchema(Mapping):
|
|
453
455
|
return self
|
454
456
|
|
455
457
|
|
458
|
+
INVALID_BASE_URL_MESSAGE = (
|
459
|
+
"The provided base URL is invalid. This URL serves as a prefix for all API endpoints you want to test. "
|
460
|
+
"Make sure it is a properly formatted URL."
|
461
|
+
)
|
462
|
+
|
463
|
+
|
464
|
+
def validate_base_url(value: str) -> None:
|
465
|
+
try:
|
466
|
+
netloc = urlparse(value).netloc
|
467
|
+
except ValueError as exc:
|
468
|
+
raise ValueError(INVALID_BASE_URL_MESSAGE) from exc
|
469
|
+
if value and not netloc:
|
470
|
+
raise ValueError(INVALID_BASE_URL_MESSAGE)
|
471
|
+
|
472
|
+
|
456
473
|
@dataclass
|
457
474
|
class APIOperationMap(Mapping):
|
458
475
|
_schema: BaseSchema
|
@@ -20,7 +20,7 @@ from .utils import can_negate
|
|
20
20
|
T = TypeVar("T")
|
21
21
|
|
22
22
|
|
23
|
-
class MutationResult(enum.Enum):
|
23
|
+
class MutationResult(int, enum.Enum):
|
24
24
|
"""The result of applying some mutation to some schema.
|
25
25
|
|
26
26
|
Failing to mutate something means that by applying some mutation, it is not possible to change
|
@@ -134,6 +134,7 @@ class OpenAPI20Parameter(OpenAPIParameter):
|
|
134
134
|
"multipleOf",
|
135
135
|
"example",
|
136
136
|
"examples",
|
137
|
+
"default",
|
137
138
|
)
|
138
139
|
|
139
140
|
|
@@ -178,6 +179,7 @@ class OpenAPI30Parameter(OpenAPIParameter):
|
|
178
179
|
"format",
|
179
180
|
"example",
|
180
181
|
"examples",
|
182
|
+
"default",
|
181
183
|
)
|
182
184
|
|
183
185
|
def from_open_api_to_json_schema(self, operation: APIOperation, open_api_schema: dict[str, Any]) -> dict[str, Any]:
|
@@ -230,6 +232,7 @@ class OpenAPI20Body(OpenAPIBody, OpenAPI20Parameter):
|
|
230
232
|
"additionalProperties",
|
231
233
|
"example",
|
232
234
|
"examples",
|
235
|
+
"default",
|
233
236
|
)
|
234
237
|
# NOTE. For Open API 2.0 bodies, we still give `x-example` precedence over the schema-level `example` field to keep
|
235
238
|
# the precedence rules consistent.
|
@@ -139,7 +139,10 @@ class ConvertingResolver(InliningResolver):
|
|
139
139
|
def resolve(self, ref: str) -> tuple[str, Any]:
|
140
140
|
url, document = super().resolve(ref)
|
141
141
|
document = to_json_schema_recursive(
|
142
|
-
document,
|
142
|
+
document,
|
143
|
+
nullable_name=self.nullable_name,
|
144
|
+
is_response_schema=self.is_response_schema,
|
145
|
+
update_quantifiers=False,
|
143
146
|
)
|
144
147
|
return url, document
|
145
148
|
|
@@ -1022,24 +1022,30 @@ class SwaggerV20(BaseOpenAPISchema):
|
|
1022
1022
|
content_types = self.get_request_payload_content_types(operation)
|
1023
1023
|
is_multipart = "multipart/form-data" in content_types
|
1024
1024
|
|
1025
|
-
|
1026
|
-
if isinstance(file_value, list):
|
1027
|
-
for item in file_value:
|
1028
|
-
files.append((name, (None, item)))
|
1029
|
-
else:
|
1030
|
-
files.append((name, file_value))
|
1025
|
+
known_fields: dict[str, dict] = {}
|
1031
1026
|
|
1032
1027
|
for parameter in operation.body:
|
1033
1028
|
if isinstance(parameter, OpenAPI20CompositeBody):
|
1034
1029
|
for form_parameter in parameter.definition:
|
1035
|
-
name = form_parameter.
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1030
|
+
known_fields[form_parameter.name] = form_parameter.definition
|
1031
|
+
|
1032
|
+
def add_file(name: str, value: Any) -> None:
|
1033
|
+
if isinstance(value, list):
|
1034
|
+
for item in value:
|
1035
|
+
files.append((name, (None, item)))
|
1036
|
+
else:
|
1037
|
+
files.append((name, value))
|
1038
|
+
|
1039
|
+
for name, value in form_data.items():
|
1040
|
+
param_def = known_fields.get(name)
|
1041
|
+
if param_def:
|
1042
|
+
if param_def.get("type") == "file" or is_multipart:
|
1043
|
+
add_file(name, value)
|
1044
|
+
else:
|
1045
|
+
data[name] = value
|
1046
|
+
else:
|
1047
|
+
# Unknown field — treat it as a file (safe default under multipart/form-data)
|
1048
|
+
add_file(name, value)
|
1043
1049
|
# `None` is the default value for `files` and `data` arguments in `requests.request`
|
1044
1050
|
return files or None, data or None
|
1045
1051
|
|
@@ -1202,14 +1208,19 @@ class OpenApi30(SwaggerV20):
|
|
1202
1208
|
break
|
1203
1209
|
else:
|
1204
1210
|
raise InternalError("No 'multipart/form-data' media type found in the schema")
|
1205
|
-
for name,
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1211
|
+
for name, value in form_data.items():
|
1212
|
+
property_schema = (schema or {}).get("properties", {}).get(name)
|
1213
|
+
if property_schema:
|
1214
|
+
if isinstance(value, list):
|
1215
|
+
files.extend([(name, item) for item in value])
|
1209
1216
|
elif property_schema.get("format") in ("binary", "base64"):
|
1210
|
-
files.append((name,
|
1217
|
+
files.append((name, value))
|
1211
1218
|
else:
|
1212
|
-
files.append((name, (None,
|
1219
|
+
files.append((name, (None, value)))
|
1220
|
+
elif isinstance(value, list):
|
1221
|
+
files.extend([(name, item) for item in value])
|
1222
|
+
else:
|
1223
|
+
files.append((name, (None, value)))
|
1213
1224
|
# `None` is the default value for `files` and `data` arguments in `requests.request`
|
1214
1225
|
return files or None, None
|
1215
1226
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: schemathesis
|
3
|
-
Version: 4.0.
|
3
|
+
Version: 4.0.0a8
|
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
|
@@ -1,11 +1,11 @@
|
|
1
|
-
schemathesis/__init__.py,sha256=
|
1
|
+
schemathesis/__init__.py,sha256=S9MD8cGyXWihyQikye9mSBpvrfUJbOItD5yr65vkx6A,1263
|
2
2
|
schemathesis/auths.py,sha256=t-YuPyoLqL7jlRUH-45JxO7Ir3pYxpe31CRmNIJh7rI,15423
|
3
3
|
schemathesis/checks.py,sha256=B5-ROnjvvwpaqgj_iQ7eCjGqvRRVT30eWNPLKmwdrM8,5084
|
4
4
|
schemathesis/errors.py,sha256=VSZ-h9Bt7QvrvywOGB-MoHCshR8OWJegYlBxfVh5Vuw,899
|
5
5
|
schemathesis/filters.py,sha256=CzVPnNSRLNgvLlU5_WssPEC0wpdQi0dMvDpHSQbAlkE,13577
|
6
|
-
schemathesis/hooks.py,sha256=
|
6
|
+
schemathesis/hooks.py,sha256=ZSGEnsLJ7UVezf4CcaJebVkjEpvwgJolJFZo5fjQNDc,13153
|
7
7
|
schemathesis/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
|
-
schemathesis/schemas.py,sha256=
|
8
|
+
schemathesis/schemas.py,sha256=A2qAs1PY9wbRWk6PFnslWyIqzchAhu5oo_MsKL7uF8w,27952
|
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=rUixnqorraUFDtOu3Nmm1x_k0qbgmW9xW96kQB_fBCQ,338
|
@@ -40,7 +40,7 @@ schemathesis/core/control.py,sha256=IzwIc8HIAEMtZWW0Q0iXI7T1niBpjvcLlbuwOSmy5O8,
|
|
40
40
|
schemathesis/core/curl.py,sha256=yuaCe_zHLGwUjEeloQi6W3tOA3cGdnHDNI17-5jia0o,1723
|
41
41
|
schemathesis/core/deserialization.py,sha256=ygIj4fNaOd0mJ2IvTsn6bsabBt_2AbSLCz-z9UqfpdQ,2406
|
42
42
|
schemathesis/core/errors.py,sha256=97Fk3udsMaS5xZrco7ZaShqe4W6g2aZ55J7d58HPRac,15881
|
43
|
-
schemathesis/core/failures.py,sha256=
|
43
|
+
schemathesis/core/failures.py,sha256=nt_KJAQnachw4Ey-rZ__P8q6nGJ_YekZiSLc6-PfFW0,8833
|
44
44
|
schemathesis/core/fs.py,sha256=ItQT0_cVwjDdJX9IiI7EnU75NI2H3_DCEyyUjzg_BgI,472
|
45
45
|
schemathesis/core/lazy_import.py,sha256=aMhWYgbU2JOltyWBb32vnWBb6kykOghucEzI_F70yVE,470
|
46
46
|
schemathesis/core/loaders.py,sha256=SQQ-8m64-D2FaOgvwKZLyTtLJuzP3RPo7Ud2BERK1c0,3404
|
@@ -63,24 +63,24 @@ schemathesis/engine/core.py,sha256=DfulRMVTivmZj-wwLekIhuSzLsFnuVPtSg7j9HyWdz0,5
|
|
63
63
|
schemathesis/engine/errors.py,sha256=8PHYsuq2qIEJHm2FDf_UnWa4IDc-DRFTPckLAr22yhE,16895
|
64
64
|
schemathesis/engine/events.py,sha256=gslRAWQKMPqBCQzLDS4wAbsKcVuONSy5SPqimJJJYT4,6250
|
65
65
|
schemathesis/engine/recorder.py,sha256=K3HfMARrT5mPWXPnYebjjcq5CcsBRhMrtZwEL9_Lvtg,8432
|
66
|
-
schemathesis/engine/phases/__init__.py,sha256=
|
66
|
+
schemathesis/engine/phases/__init__.py,sha256=CuTBMaQIsGdtWw400maiwqfIbMyVv5_vHXV-SY5A5NI,2495
|
67
67
|
schemathesis/engine/phases/probes.py,sha256=3M9g3E7CXbDDK_8inuvkRZibCCcoO2Ce5U3lnyTeWXQ,5131
|
68
68
|
schemathesis/engine/phases/stateful/__init__.py,sha256=lWo2RLrutNblHvohTzofQqL22GORwBRA8bf6jvLuGPg,2391
|
69
69
|
schemathesis/engine/phases/stateful/_executor.py,sha256=m1ZMqFUPc4Hdql10l0gF3tpP4JOImSA-XeBd4jg3Ll8,12443
|
70
70
|
schemathesis/engine/phases/stateful/context.py,sha256=SKWsok-tlWbUDagiUmP7cLNW6DsgFDc_Afv0vQfWv6c,2964
|
71
|
-
schemathesis/engine/phases/unit/__init__.py,sha256=
|
71
|
+
schemathesis/engine/phases/unit/__init__.py,sha256=QmtzIgP9KWLo-IY1kMyBqYXPMxFQz-WF2eVTWewqUfI,8174
|
72
72
|
schemathesis/engine/phases/unit/_executor.py,sha256=buMEr7e01SFSeNuEQNGMf4hoiLxX9_sp0JhH4LBAk9M,12928
|
73
73
|
schemathesis/engine/phases/unit/_pool.py,sha256=9OgmFd-ov1AAvcZGquK40PXkGLp7f2qCjZoPZuoZl4A,2529
|
74
74
|
schemathesis/experimental/__init__.py,sha256=jYY3Mq6okqTRTMudPzcaT0JVjzJW5IN_ZVJdGU0stBs,2011
|
75
75
|
schemathesis/generation/__init__.py,sha256=sWTRPTh-qDNkSfpM9rYI3v8zskH8_wFKUuPRg18fZI8,1627
|
76
76
|
schemathesis/generation/case.py,sha256=Rt5MCUtPVYVQzNyjUx8magocPJpHV1svyuqQSTwUE-I,7306
|
77
|
-
schemathesis/generation/coverage.py,sha256=
|
77
|
+
schemathesis/generation/coverage.py,sha256=vv2dbj_KAaqo8PCwMdyDWLyyAssk-YL5oTU3aCkgB1s,41185
|
78
78
|
schemathesis/generation/meta.py,sha256=36h6m4E7jzLGa8TCvl7eBl_xUWLiRul3qxzexl5cB58,2515
|
79
79
|
schemathesis/generation/modes.py,sha256=t_EvKr2aOXYMsEfdMu4lLF4KCGcX1LVVyvzTkcpJqhk,663
|
80
80
|
schemathesis/generation/overrides.py,sha256=FhqcFoliEvgW6MZyFPYemfLgzKt3Miy8Cud7OMOCb7g,3045
|
81
81
|
schemathesis/generation/targets.py,sha256=_rN2qgxTE2EfvygiN-Fy3WmDnRH0ERohdx3sKRDaYhU,2120
|
82
82
|
schemathesis/generation/hypothesis/__init__.py,sha256=Rl7QwvMBMJI7pBqTydplX6bXC420n0EGQHVm-vZgaYQ,1204
|
83
|
-
schemathesis/generation/hypothesis/builder.py,sha256=
|
83
|
+
schemathesis/generation/hypothesis/builder.py,sha256=cSgFWQG-apIHNdW-PpIBDBjLw4RorihfZ4e_Ln3j2-w,30341
|
84
84
|
schemathesis/generation/hypothesis/examples.py,sha256=6eGaKUEC3elmKsaqfKj1sLvM8EHc-PWT4NRBq4NI0Rs,1409
|
85
85
|
schemathesis/generation/hypothesis/given.py,sha256=sTZR1of6XaHAPWtHx2_WLlZ50M8D5Rjux0GmWkWjDq4,2337
|
86
86
|
schemathesis/generation/hypothesis/reporting.py,sha256=uDVow6Ya8YFkqQuOqRsjbzsbyP4KKfr3jA7ZaY4FuKY,279
|
@@ -99,7 +99,7 @@ schemathesis/pytest/__init__.py,sha256=7W0q-Thcw03IAQfXE_Mo8JPZpUdHJzfu85fjK1Zdf
|
|
99
99
|
schemathesis/pytest/control_flow.py,sha256=F8rAPsPeNv_sJiJgbZYtTpwKWjauZmqFUaKroY2GmQI,217
|
100
100
|
schemathesis/pytest/lazy.py,sha256=g7DpOeQNsjXC03FCG5e1L65iz3zE48qAyaqG81HzCZY,12028
|
101
101
|
schemathesis/pytest/loaders.py,sha256=oQJ78yyuIm3Ye9X7giVjDB1vYfaW5UY5YuhaTLm_ZFU,266
|
102
|
-
schemathesis/pytest/plugin.py,sha256=
|
102
|
+
schemathesis/pytest/plugin.py,sha256=TxbESQy9JPZBaIwUP4BHiIGFzPd2oMWwq_4VqFS_UfI,12067
|
103
103
|
schemathesis/python/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
104
104
|
schemathesis/python/asgi.py,sha256=5PyvuTBaivvyPUEi3pwJni91K1kX5Zc0u9c6c1D8a1Q,287
|
105
105
|
schemathesis/python/wsgi.py,sha256=uShAgo_NChbfYaV1117e6UHp0MTg7jaR0Sy_to3Jmf8,219
|
@@ -113,28 +113,28 @@ schemathesis/specs/graphql/validation.py,sha256=-W1Noc1MQmTb4RX-gNXMeU2qkgso4mzV
|
|
113
113
|
schemathesis/specs/openapi/__init__.py,sha256=C5HOsfuDJGq_3mv8CRBvRvb0Diy1p0BFdqyEXMS-loE,238
|
114
114
|
schemathesis/specs/openapi/_cache.py,sha256=HpglmETmZU0RCHxp3DO_sg5_B_nzi54Zuw9vGzzYCxY,4295
|
115
115
|
schemathesis/specs/openapi/_hypothesis.py,sha256=n_39iyz1rt2EdSe-Lyr-3sOIEyJIthnCVR4tGUUvH1c,21328
|
116
|
-
schemathesis/specs/openapi/checks.py,sha256=
|
116
|
+
schemathesis/specs/openapi/checks.py,sha256=i4tVVkK1wLthdmG-zu7EaQLkBxJ2T3FkuHqw0dA4qlA,27742
|
117
117
|
schemathesis/specs/openapi/constants.py,sha256=JqM_FHOenqS_MuUE9sxVQ8Hnw0DNM8cnKDwCwPLhID4,783
|
118
118
|
schemathesis/specs/openapi/converter.py,sha256=lil8IewM5j8tvt4lpA9g_KITvIwx1M96i45DNSHNjoc,3505
|
119
119
|
schemathesis/specs/openapi/definitions.py,sha256=8htclglV3fW6JPBqs59lgM4LnA25Mm9IptXBPb_qUT0,93949
|
120
120
|
schemathesis/specs/openapi/examples.py,sha256=Xvjp60QUcLaeGsJRbi2i6XM15_4uO0ceVoClIaJehiE,21062
|
121
121
|
schemathesis/specs/openapi/formats.py,sha256=ViVF3aFeFI1ctwGQbiRDXhU3so82P0BCaF2aDDbUUm8,2816
|
122
122
|
schemathesis/specs/openapi/media_types.py,sha256=ADedOaNWjbAtAekyaKmNj9fY6zBTeqcNqBEjN0EWNhI,1014
|
123
|
-
schemathesis/specs/openapi/parameters.py,sha256=
|
123
|
+
schemathesis/specs/openapi/parameters.py,sha256=tVL61gDe9A8_jwoVKZZvpXKPerMyq7vkAvwdMsi44TI,14622
|
124
124
|
schemathesis/specs/openapi/patterns.py,sha256=NLnGybcana_kYLVKVEjkEyAzdClAV0xKe4Oy4NVayMI,12834
|
125
|
-
schemathesis/specs/openapi/references.py,sha256=
|
126
|
-
schemathesis/specs/openapi/schemas.py,sha256=
|
125
|
+
schemathesis/specs/openapi/references.py,sha256=c8Ufa8hp6Dyf-gPn5lpmyqF_GtqXIBWoKkj3bk3WaPA,8871
|
126
|
+
schemathesis/specs/openapi/schemas.py,sha256=zfGPFWnaI9_W8F8E8qCTzuYQRE5yDuGx7WGW4EH-QgI,55020
|
127
127
|
schemathesis/specs/openapi/security.py,sha256=6UWYMhL-dPtkTineqqBFNKca1i4EuoTduw-EOLeE0aQ,7149
|
128
128
|
schemathesis/specs/openapi/serialization.py,sha256=VdDLmeHqxlWM4cxQQcCkvrU6XurivolwEEaT13ohelA,11972
|
129
129
|
schemathesis/specs/openapi/utils.py,sha256=ER4vJkdFVDIE7aKyxyYatuuHVRNutytezgE52pqZNE8,900
|
130
130
|
schemathesis/specs/openapi/expressions/__init__.py,sha256=hfuRtXD75tQFhzSo6QgDZ3zByyWeZRKevB8edszAVj4,2272
|
131
131
|
schemathesis/specs/openapi/expressions/errors.py,sha256=YLVhps-sYcslgVaahfcUYxUSHlIfWL-rQMeT5PZSMZ8,219
|
132
132
|
schemathesis/specs/openapi/expressions/extractors.py,sha256=Py3of3_vBACP4ljiZIcgd-xQCrWIpcMsfQFc0EtAUoA,470
|
133
|
-
schemathesis/specs/openapi/expressions/lexer.py,sha256=
|
134
|
-
schemathesis/specs/openapi/expressions/nodes.py,sha256=
|
133
|
+
schemathesis/specs/openapi/expressions/lexer.py,sha256=KFA8Z-Kh1IYUpKgwAnDtEucN9YLLpnFR1GQl8KddWlA,3987
|
134
|
+
schemathesis/specs/openapi/expressions/nodes.py,sha256=63LC4mQHy3a0_tKiGIVWaUHu9L9IWilq6R004GLpjyY,4077
|
135
135
|
schemathesis/specs/openapi/expressions/parser.py,sha256=e-ZxshrGE_5CVbgcZLYgdGSjdifgyzgKkLQp0dI0cJY,4503
|
136
136
|
schemathesis/specs/openapi/negative/__init__.py,sha256=60QqVBTXPTsAojcf7GDs7v8WbOE_k3g_VC_DBeQUqBw,3749
|
137
|
-
schemathesis/specs/openapi/negative/mutations.py,sha256=
|
137
|
+
schemathesis/specs/openapi/negative/mutations.py,sha256=MIFVSWbZHW92KhpWruJT3XLisgc-rFnvYasRtwMmExs,19253
|
138
138
|
schemathesis/specs/openapi/negative/types.py,sha256=a7buCcVxNBG6ILBM3A7oNTAX0lyDseEtZndBuej8MbI,174
|
139
139
|
schemathesis/specs/openapi/negative/utils.py,sha256=ozcOIuASufLqZSgnKUACjX-EOZrrkuNdXX0SDnLoGYA,168
|
140
140
|
schemathesis/specs/openapi/stateful/__init__.py,sha256=0pu_iGjRiKuqUDN3ewz1zUOt6f1SdvSxVtHC5uK-CYw,14750
|
@@ -146,8 +146,8 @@ schemathesis/transport/prepare.py,sha256=qQ6zXBw5NN2AIM0bzLAc5Ryc3dmMb0R6xN14lnR
|
|
146
146
|
schemathesis/transport/requests.py,sha256=j5wI1Uo_PnVuP1eV8l6ddsXosyxAPQ1mLSyWEZmTI9I,8747
|
147
147
|
schemathesis/transport/serialization.py,sha256=jIMra1LqRGav0OX3Hx7mvORt38ll4cd2DKit2D58FN0,10531
|
148
148
|
schemathesis/transport/wsgi.py,sha256=RWSuUXPrl91GxAy8a4jyNNozOWVMRBxKx_tljlWA_Lo,5697
|
149
|
-
schemathesis-4.0.
|
150
|
-
schemathesis-4.0.
|
151
|
-
schemathesis-4.0.
|
152
|
-
schemathesis-4.0.
|
153
|
-
schemathesis-4.0.
|
149
|
+
schemathesis-4.0.0a8.dist-info/METADATA,sha256=hdJd_ASqgZ75dZ1EW27p3mL6CAG179nTb-cm1zVtQqk,10427
|
150
|
+
schemathesis-4.0.0a8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
151
|
+
schemathesis-4.0.0a8.dist-info/entry_points.txt,sha256=hiK3un-xfgPdwj9uj16YVDtTNpO128bmk0U82SMv8ZQ,152
|
152
|
+
schemathesis-4.0.0a8.dist-info/licenses/LICENSE,sha256=2Ve4J8v5jMQAWrT7r1nf3bI8Vflk3rZVQefiF2zpxwg,1121
|
153
|
+
schemathesis-4.0.0a8.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|