schemathesis 4.0.1__py3-none-any.whl → 4.0.3__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/cli/commands/run/handlers/cassettes.py +23 -5
- schemathesis/cli/commands/run/handlers/junitxml.py +8 -2
- schemathesis/cli/commands/run/handlers/output.py +15 -4
- schemathesis/core/__init__.py +2 -0
- schemathesis/engine/control.py +10 -2
- schemathesis/engine/core.py +6 -0
- schemathesis/engine/phases/__init__.py +12 -2
- schemathesis/engine/phases/probes.py +25 -4
- schemathesis/generation/case.py +12 -6
- schemathesis/generation/hypothesis/builder.py +35 -6
- schemathesis/generation/meta.py +4 -0
- schemathesis/generation/overrides.py +2 -0
- schemathesis/hooks.py +2 -0
- schemathesis/pytest/lazy.py +12 -2
- schemathesis/pytest/plugin.py +22 -14
- schemathesis/schemas.py +10 -4
- schemathesis/specs/graphql/_cache.py +13 -3
- schemathesis/specs/graphql/schemas.py +2 -0
- schemathesis/specs/openapi/_hypothesis.py +1 -1
- schemathesis/specs/openapi/examples.py +4 -0
- schemathesis/specs/openapi/expressions/extractors.py +2 -0
- schemathesis/specs/openapi/expressions/lexer.py +2 -0
- schemathesis/specs/openapi/expressions/nodes.py +35 -4
- schemathesis/specs/openapi/negative/__init__.py +2 -0
- schemathesis/specs/openapi/negative/mutations.py +2 -0
- schemathesis/specs/openapi/stateful/links.py +1 -0
- schemathesis/transport/prepare.py +0 -2
- schemathesis/transport/requests.py +38 -5
- schemathesis/transport/wsgi.py +11 -1
- {schemathesis-4.0.1.dist-info → schemathesis-4.0.3.dist-info}/METADATA +2 -2
- {schemathesis-4.0.1.dist-info → schemathesis-4.0.3.dist-info}/RECORD +34 -34
- {schemathesis-4.0.1.dist-info → schemathesis-4.0.3.dist-info}/WHEEL +0 -0
- {schemathesis-4.0.1.dist-info → schemathesis-4.0.3.dist-info}/entry_points.txt +0 -0
- {schemathesis-4.0.1.dist-info → schemathesis-4.0.3.dist-info}/licenses/LICENSE +0 -0
@@ -4,7 +4,7 @@ import datetime
|
|
4
4
|
import json
|
5
5
|
import sys
|
6
6
|
import threading
|
7
|
-
from dataclasses import dataclass
|
7
|
+
from dataclasses import dataclass
|
8
8
|
from http.cookies import SimpleCookie
|
9
9
|
from pathlib import Path
|
10
10
|
from queue import Queue
|
@@ -35,10 +35,23 @@ class CassetteWriter(EventHandler):
|
|
35
35
|
format: ReportFormat
|
36
36
|
path: Path
|
37
37
|
config: ProjectConfig
|
38
|
-
queue: Queue
|
39
|
-
worker: threading.Thread
|
38
|
+
queue: Queue
|
39
|
+
worker: threading.Thread
|
40
|
+
|
41
|
+
__slots__ = ("format", "path", "config", "queue", "worker")
|
42
|
+
|
43
|
+
def __init__(
|
44
|
+
self,
|
45
|
+
format: ReportFormat,
|
46
|
+
path: Path,
|
47
|
+
config: ProjectConfig,
|
48
|
+
queue: Queue | None = None,
|
49
|
+
) -> None:
|
50
|
+
self.format = format
|
51
|
+
self.path = path
|
52
|
+
self.config = config
|
53
|
+
self.queue = queue or Queue()
|
40
54
|
|
41
|
-
def __post_init__(self) -> None:
|
42
55
|
kwargs = {
|
43
56
|
"path": self.path,
|
44
57
|
"config": self.config,
|
@@ -49,7 +62,12 @@ class CassetteWriter(EventHandler):
|
|
49
62
|
writer = har_writer
|
50
63
|
else:
|
51
64
|
writer = vcr_writer
|
52
|
-
|
65
|
+
|
66
|
+
self.worker = threading.Thread(
|
67
|
+
name="SchemathesisCassetteWriter",
|
68
|
+
target=writer,
|
69
|
+
kwargs=kwargs,
|
70
|
+
)
|
53
71
|
self.worker.start()
|
54
72
|
|
55
73
|
def start(self, ctx: ExecutionContext) -> None:
|
@@ -1,7 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import platform
|
4
|
-
from dataclasses import dataclass
|
4
|
+
from dataclasses import dataclass
|
5
5
|
from pathlib import Path
|
6
6
|
from typing import Iterable
|
7
7
|
|
@@ -16,7 +16,13 @@ from schemathesis.engine import Status, events
|
|
16
16
|
@dataclass
|
17
17
|
class JunitXMLHandler(EventHandler):
|
18
18
|
path: Path
|
19
|
-
test_cases: dict
|
19
|
+
test_cases: dict
|
20
|
+
|
21
|
+
__slots__ = ("path", "test_cases")
|
22
|
+
|
23
|
+
def __init__(self, path: Path, test_cases: dict | None = None) -> None:
|
24
|
+
self.path = path
|
25
|
+
self.test_cases = test_cases or {}
|
20
26
|
|
21
27
|
def handle_event(self, ctx: ExecutionContext, event: events.EngineEvent) -> None:
|
22
28
|
if isinstance(event, events.ScenarioFinished):
|
@@ -324,10 +324,21 @@ class ProbingProgressManager:
|
|
324
324
|
|
325
325
|
@dataclass
|
326
326
|
class WarningData:
|
327
|
-
missing_auth: dict[int, set[str]]
|
328
|
-
missing_test_data: set[str]
|
329
|
-
|
330
|
-
|
327
|
+
missing_auth: dict[int, set[str]]
|
328
|
+
missing_test_data: set[str]
|
329
|
+
validation_mismatch: set[str]
|
330
|
+
|
331
|
+
__slots__ = ("missing_auth", "missing_test_data", "validation_mismatch")
|
332
|
+
|
333
|
+
def __init__(
|
334
|
+
self,
|
335
|
+
missing_auth: dict[int, set[str]] | None = None,
|
336
|
+
missing_test_data: set[str] | None = None,
|
337
|
+
validation_mismatch: set[str] | None = None,
|
338
|
+
) -> None:
|
339
|
+
self.missing_auth = missing_auth or {}
|
340
|
+
self.missing_test_data = missing_test_data or set()
|
341
|
+
self.validation_mismatch = validation_mismatch or set()
|
331
342
|
|
332
343
|
@property
|
333
344
|
def is_empty(self) -> bool:
|
schemathesis/core/__init__.py
CHANGED
schemathesis/engine/control.py
CHANGED
@@ -12,8 +12,16 @@ class ExecutionControl:
|
|
12
12
|
|
13
13
|
stop_event: threading.Event
|
14
14
|
max_failures: int | None
|
15
|
-
_failures_counter: int
|
16
|
-
has_reached_the_failure_limit: bool
|
15
|
+
_failures_counter: int
|
16
|
+
has_reached_the_failure_limit: bool
|
17
|
+
|
18
|
+
__slots__ = ("stop_event", "max_failures", "_failures_counter", "has_reached_the_failure_limit")
|
19
|
+
|
20
|
+
def __init__(self, stop_event: threading.Event, max_failures: int | None) -> None:
|
21
|
+
self.stop_event = stop_event
|
22
|
+
self.max_failures = max_failures
|
23
|
+
self._failures_counter = 0
|
24
|
+
self.has_reached_the_failure_limit = False
|
17
25
|
|
18
26
|
@property
|
19
27
|
def is_stopped(self) -> bool:
|
schemathesis/engine/core.py
CHANGED
@@ -18,6 +18,8 @@ from .phases import Phase, PhaseName, PhaseSkipReason
|
|
18
18
|
class Engine:
|
19
19
|
schema: BaseSchema
|
20
20
|
|
21
|
+
__slots__ = ("schema",)
|
22
|
+
|
21
23
|
def execute(self) -> EventStream:
|
22
24
|
"""Execute all test phases."""
|
23
25
|
# Unregister auth if explicitly provided
|
@@ -103,6 +105,8 @@ class ExecutionPlan:
|
|
103
105
|
|
104
106
|
phases: Sequence[Phase]
|
105
107
|
|
108
|
+
__slots__ = ("phases",)
|
109
|
+
|
106
110
|
def execute(self, engine: EngineContext) -> EventGenerator:
|
107
111
|
"""Execute all phases in sequence."""
|
108
112
|
yield events.EngineStarted()
|
@@ -150,6 +154,8 @@ class EventStream:
|
|
150
154
|
generator: EventGenerator
|
151
155
|
stop_event: threading.Event
|
152
156
|
|
157
|
+
__slots__ = ("generator", "stop_event")
|
158
|
+
|
153
159
|
def __next__(self) -> events.EngineEvent:
|
154
160
|
return next(self.generator)
|
155
161
|
|
@@ -60,8 +60,18 @@ class Phase:
|
|
60
60
|
|
61
61
|
name: PhaseName
|
62
62
|
is_supported: bool
|
63
|
-
is_enabled: bool
|
64
|
-
skip_reason: PhaseSkipReason | None
|
63
|
+
is_enabled: bool
|
64
|
+
skip_reason: PhaseSkipReason | None
|
65
|
+
|
66
|
+
__slots__ = ("name", "is_supported", "is_enabled", "skip_reason")
|
67
|
+
|
68
|
+
def __init__(
|
69
|
+
self, name: PhaseName, is_supported: bool, is_enabled: bool = True, skip_reason: PhaseSkipReason | None = None
|
70
|
+
) -> None:
|
71
|
+
self.name = name
|
72
|
+
self.is_supported = is_supported
|
73
|
+
self.is_enabled = is_enabled
|
74
|
+
self.skip_reason = skip_reason
|
65
75
|
|
66
76
|
def should_execute(self, ctx: EngineContext) -> bool:
|
67
77
|
"""Determine if phase should run based on context & configuration."""
|
@@ -68,6 +68,8 @@ class Probe:
|
|
68
68
|
|
69
69
|
name: str
|
70
70
|
|
71
|
+
__slots__ = ("name",)
|
72
|
+
|
71
73
|
def prepare_request(
|
72
74
|
self, session: requests.Session, request: requests.Request, schema: BaseSchema
|
73
75
|
) -> requests.PreparedRequest:
|
@@ -92,9 +94,25 @@ class ProbeOutcome(str, enum.Enum):
|
|
92
94
|
class ProbeRun:
|
93
95
|
probe: Probe
|
94
96
|
outcome: ProbeOutcome
|
95
|
-
request: requests.PreparedRequest | None
|
96
|
-
response: requests.Response | None
|
97
|
-
error: Exception | None
|
97
|
+
request: requests.PreparedRequest | None
|
98
|
+
response: requests.Response | None
|
99
|
+
error: Exception | None
|
100
|
+
|
101
|
+
__slots__ = ("probe", "outcome", "request", "response", "error")
|
102
|
+
|
103
|
+
def __init__(
|
104
|
+
self,
|
105
|
+
probe: Probe,
|
106
|
+
outcome: ProbeOutcome,
|
107
|
+
request: requests.PreparedRequest | None = None,
|
108
|
+
response: requests.Response | None = None,
|
109
|
+
error: Exception | None = None,
|
110
|
+
) -> None:
|
111
|
+
self.probe = probe
|
112
|
+
self.outcome = outcome
|
113
|
+
self.request = request
|
114
|
+
self.response = response
|
115
|
+
self.error = error
|
98
116
|
|
99
117
|
@property
|
100
118
|
def is_failure(self) -> bool:
|
@@ -105,7 +123,10 @@ class ProbeRun:
|
|
105
123
|
class NullByteInHeader(Probe):
|
106
124
|
"""Support NULL bytes in headers."""
|
107
125
|
|
108
|
-
|
126
|
+
__slots__ = ("name",)
|
127
|
+
|
128
|
+
def __init__(self) -> None:
|
129
|
+
self.name = "Supports NULL byte in headers"
|
109
130
|
|
110
131
|
def prepare_request(
|
111
132
|
self, session: requests.Session, request: requests.Request, schema: BaseSchema
|
schemathesis/generation/case.py
CHANGED
@@ -244,19 +244,25 @@ class Case:
|
|
244
244
|
|
245
245
|
response = Response.from_any(response)
|
246
246
|
|
247
|
+
config = self.operation.schema.config.checks_config_for(
|
248
|
+
operation=self.operation, phase=self.meta.phase.name.value if self.meta is not None else None
|
249
|
+
)
|
250
|
+
if not checks:
|
251
|
+
# Checks are not specified explicitly, derive from the config
|
252
|
+
checks = []
|
253
|
+
for check in CHECKS.get_all():
|
254
|
+
name = check.__name__
|
255
|
+
if config.get_by_name(name=name).enabled:
|
256
|
+
checks.append(check)
|
247
257
|
checks = [
|
248
|
-
check
|
249
|
-
for check in list(checks or CHECKS.get_all()) + list(additional_checks or [])
|
250
|
-
if check not in set(excluded_checks or [])
|
258
|
+
check for check in list(checks) + list(additional_checks or []) if check not in set(excluded_checks or [])
|
251
259
|
]
|
252
260
|
|
253
261
|
ctx = CheckContext(
|
254
262
|
override=self._override,
|
255
263
|
auth=None,
|
256
264
|
headers=CaseInsensitiveDict(headers) if headers else None,
|
257
|
-
config=
|
258
|
-
operation=self.operation, phase=self.meta.phase.name.value if self.meta is not None else None
|
259
|
-
),
|
265
|
+
config=config,
|
260
266
|
transport_kwargs=transport_kwargs,
|
261
267
|
recorder=None,
|
262
268
|
)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import asyncio
|
4
|
-
from dataclasses import dataclass
|
4
|
+
from dataclasses import dataclass
|
5
5
|
from enum import Enum
|
6
6
|
from functools import wraps
|
7
7
|
from itertools import combinations
|
@@ -53,11 +53,39 @@ class HypothesisTestMode(str, Enum):
|
|
53
53
|
class HypothesisTestConfig:
|
54
54
|
project: ProjectConfig
|
55
55
|
modes: list[HypothesisTestMode]
|
56
|
-
settings: hypothesis.settings | None
|
57
|
-
seed: int | None
|
58
|
-
as_strategy_kwargs: dict[str, Any]
|
59
|
-
given_args: tuple[GivenInput, ...]
|
60
|
-
given_kwargs: dict[str, GivenInput]
|
56
|
+
settings: hypothesis.settings | None
|
57
|
+
seed: int | None
|
58
|
+
as_strategy_kwargs: dict[str, Any]
|
59
|
+
given_args: tuple[GivenInput, ...]
|
60
|
+
given_kwargs: dict[str, GivenInput]
|
61
|
+
|
62
|
+
__slots__ = (
|
63
|
+
"project",
|
64
|
+
"modes",
|
65
|
+
"settings",
|
66
|
+
"seed",
|
67
|
+
"as_strategy_kwargs",
|
68
|
+
"given_args",
|
69
|
+
"given_kwargs",
|
70
|
+
)
|
71
|
+
|
72
|
+
def __init__(
|
73
|
+
self,
|
74
|
+
project: ProjectConfig,
|
75
|
+
modes: list[HypothesisTestMode],
|
76
|
+
settings: hypothesis.settings | None = None,
|
77
|
+
seed: int | None = None,
|
78
|
+
as_strategy_kwargs: dict[str, Any] | None = None,
|
79
|
+
given_args: tuple[GivenInput, ...] = (),
|
80
|
+
given_kwargs: dict[str, GivenInput] | None = None,
|
81
|
+
) -> None:
|
82
|
+
self.project = project
|
83
|
+
self.modes = modes
|
84
|
+
self.settings = settings
|
85
|
+
self.seed = seed
|
86
|
+
self.as_strategy_kwargs = as_strategy_kwargs or {}
|
87
|
+
self.given_args = given_args
|
88
|
+
self.given_kwargs = given_kwargs or {}
|
61
89
|
|
62
90
|
|
63
91
|
def create_test(
|
@@ -393,6 +421,7 @@ class Template:
|
|
393
421
|
class TemplateValue:
|
394
422
|
kwargs: dict[str, Any]
|
395
423
|
components: dict[ComponentKind, ComponentInfo]
|
424
|
+
|
396
425
|
__slots__ = ("kwargs", "components")
|
397
426
|
|
398
427
|
|
schemathesis/generation/meta.py
CHANGED
@@ -37,11 +37,15 @@ class ComponentInfo:
|
|
37
37
|
class GeneratePhaseData:
|
38
38
|
"""Metadata specific to generate phase."""
|
39
39
|
|
40
|
+
__slots__ = ()
|
41
|
+
|
40
42
|
|
41
43
|
@dataclass
|
42
44
|
class ExplicitPhaseData:
|
43
45
|
"""Metadata specific to explicit phase."""
|
44
46
|
|
47
|
+
__slots__ = ()
|
48
|
+
|
45
49
|
|
46
50
|
@dataclass
|
47
51
|
class CoveragePhaseData:
|
schemathesis/hooks.py
CHANGED
schemathesis/pytest/lazy.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
from contextlib import nullcontext
|
4
|
-
from dataclasses import dataclass
|
4
|
+
from dataclasses import dataclass
|
5
5
|
from inspect import signature
|
6
6
|
from typing import TYPE_CHECKING, Any, Callable, Generator, Type
|
7
7
|
|
@@ -71,7 +71,17 @@ def get_all_tests(
|
|
71
71
|
@dataclass
|
72
72
|
class LazySchema:
|
73
73
|
fixture_name: str
|
74
|
-
filter_set: FilterSet
|
74
|
+
filter_set: FilterSet
|
75
|
+
|
76
|
+
__slots__ = ("fixture_name", "filter_set")
|
77
|
+
|
78
|
+
def __init__(
|
79
|
+
self,
|
80
|
+
fixture_name: str,
|
81
|
+
filter_set: FilterSet | None = None,
|
82
|
+
) -> None:
|
83
|
+
self.fixture_name = fixture_name
|
84
|
+
self.filter_set = filter_set or FilterSet()
|
75
85
|
|
76
86
|
def include(
|
77
87
|
self,
|
schemathesis/pytest/plugin.py
CHANGED
@@ -20,6 +20,7 @@ from schemathesis.core.errors import (
|
|
20
20
|
InvalidHeadersExample,
|
21
21
|
InvalidRegexPattern,
|
22
22
|
InvalidSchema,
|
23
|
+
SchemathesisError,
|
23
24
|
SerializationNotPossible,
|
24
25
|
format_exception,
|
25
26
|
)
|
@@ -263,20 +264,27 @@ def pytest_pycollect_makeitem(collector: nodes.Collector, name: str, obj: Any) -
|
|
263
264
|
|
264
265
|
@pytest.hookimpl(tryfirst=True) # type: ignore[misc]
|
265
266
|
def pytest_exception_interact(node: Function, call: pytest.CallInfo, report: pytest.TestReport) -> None:
|
266
|
-
if call.excinfo
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
267
|
+
if call.excinfo:
|
268
|
+
if issubclass(call.excinfo.type, SchemathesisError) and hasattr(call.excinfo.value, "__notes__"):
|
269
|
+
# Hypothesis adds quite a lot of additional debug information which is not that helpful in Schemathesis
|
270
|
+
call.excinfo.value.__notes__.clear()
|
271
|
+
report.longrepr = "".join(format_exception(call.excinfo.value))
|
272
|
+
if call.excinfo.type is FailureGroup:
|
273
|
+
tb_entries = list(call.excinfo.traceback)
|
274
|
+
total_frames = len(tb_entries)
|
275
|
+
|
276
|
+
# Keep internal Schemathesis frames + one extra one from the caller
|
277
|
+
skip_frames = 0
|
278
|
+
for i in range(total_frames - 1, -1, -1):
|
279
|
+
entry = tb_entries[i]
|
280
|
+
|
281
|
+
if not str(entry.path).endswith("schemathesis/generation/case.py"):
|
282
|
+
skip_frames = i
|
283
|
+
break
|
284
|
+
|
285
|
+
report.longrepr = "".join(
|
286
|
+
format_exception(call.excinfo.value, with_traceback=True, skip_frames=skip_frames)
|
287
|
+
)
|
280
288
|
|
281
289
|
|
282
290
|
@hookimpl(wrapper=True)
|
schemathesis/schemas.py
CHANGED
@@ -50,9 +50,6 @@ if TYPE_CHECKING:
|
|
50
50
|
from schemathesis.generation.stateful.state_machine import APIStateMachine
|
51
51
|
|
52
52
|
|
53
|
-
C = TypeVar("C", bound=Case)
|
54
|
-
|
55
|
-
|
56
53
|
@lru_cache
|
57
54
|
def get_full_path(base_path: str, path: str) -> str:
|
58
55
|
return unquote(urljoin(base_path, quote(path.lstrip("/"))))
|
@@ -483,6 +480,8 @@ class APIOperationMap(Mapping):
|
|
483
480
|
_schema: BaseSchema
|
484
481
|
_data: Mapping
|
485
482
|
|
483
|
+
__slots__ = ("_schema", "_data")
|
484
|
+
|
486
485
|
def __getitem__(self, item: str) -> APIOperation:
|
487
486
|
return self._data[item]
|
488
487
|
|
@@ -526,6 +525,8 @@ class Parameter:
|
|
526
525
|
# The parameter definition in the language acceptable by the API
|
527
526
|
definition: Any
|
528
527
|
|
528
|
+
__slots__ = ("definition",)
|
529
|
+
|
529
530
|
@property
|
530
531
|
def location(self) -> str:
|
531
532
|
"""Where this parameter is located.
|
@@ -556,7 +557,12 @@ P = TypeVar("P", bound=Parameter)
|
|
556
557
|
class ParameterSet(Generic[P]):
|
557
558
|
"""A set of parameters for the same location."""
|
558
559
|
|
559
|
-
items: list[P]
|
560
|
+
items: list[P]
|
561
|
+
|
562
|
+
__slots__ = ("items",)
|
563
|
+
|
564
|
+
def __init__(self, items: list[P] | None = None) -> None:
|
565
|
+
self.items = items or []
|
560
566
|
|
561
567
|
def _repr_pretty_(self, *args: Any, **kwargs: Any) -> None: ...
|
562
568
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
from dataclasses import dataclass
|
3
|
+
from dataclasses import dataclass
|
4
4
|
from typing import TYPE_CHECKING
|
5
5
|
|
6
6
|
if TYPE_CHECKING:
|
@@ -9,8 +9,18 @@ if TYPE_CHECKING:
|
|
9
9
|
|
10
10
|
@dataclass
|
11
11
|
class OperationCache:
|
12
|
-
_maps: dict[str, APIOperationMap]
|
13
|
-
_operations: dict[str, APIOperation]
|
12
|
+
_maps: dict[str, APIOperationMap]
|
13
|
+
_operations: dict[str, APIOperation]
|
14
|
+
|
15
|
+
__slots__ = ("_maps", "_operations")
|
16
|
+
|
17
|
+
def __init__(
|
18
|
+
self,
|
19
|
+
_maps: dict[str, APIOperationMap] | None = None,
|
20
|
+
_operations: dict[str, APIOperation] | None = None,
|
21
|
+
) -> None:
|
22
|
+
self._maps = _maps or {}
|
23
|
+
self._operations = _operations or {}
|
14
24
|
|
15
25
|
def get_map(self, key: str) -> APIOperationMap | None:
|
16
26
|
return self._maps.get(key)
|
@@ -71,6 +71,8 @@ class GraphQLOperationDefinition(OperationDefinition):
|
|
71
71
|
type_: graphql.GraphQLType
|
72
72
|
root_type: RootType
|
73
73
|
|
74
|
+
__slots__ = ("raw", "resolved", "scope", "field_name", "type_", "root_type")
|
75
|
+
|
74
76
|
def _repr_pretty_(self, *args: Any, **kwargs: Any) -> None: ...
|
75
77
|
|
76
78
|
@property
|
@@ -120,7 +120,7 @@ def openapi_cases(
|
|
120
120
|
for media_type in all_media_types
|
121
121
|
):
|
122
122
|
# None of media types defined for this operation are not supported
|
123
|
-
raise SerializationNotPossible.from_media_types(*all_media_types)
|
123
|
+
raise SerializationNotPossible.from_media_types(*all_media_types) from None
|
124
124
|
# Other media types are possible - avoid choosing this media type in the future
|
125
125
|
event_text = f"Can't serialize data to `{parameter.media_type}`."
|
126
126
|
note(f"{event_text} {SERIALIZERS_SUGGESTION_MESSAGE}")
|
@@ -35,6 +35,8 @@ class ParameterExample:
|
|
35
35
|
name: str
|
36
36
|
value: Any
|
37
37
|
|
38
|
+
__slots__ = ("container", "name", "value")
|
39
|
+
|
38
40
|
|
39
41
|
@dataclass
|
40
42
|
class BodyExample:
|
@@ -43,6 +45,8 @@ class BodyExample:
|
|
43
45
|
value: Any
|
44
46
|
media_type: str
|
45
47
|
|
48
|
+
__slots__ = ("value", "media_type")
|
49
|
+
|
46
50
|
|
47
51
|
Example = Union[ParameterExample, BodyExample]
|
48
52
|
|
@@ -39,6 +39,8 @@ class String(Node):
|
|
39
39
|
|
40
40
|
value: str
|
41
41
|
|
42
|
+
__slots__ = ("value",)
|
43
|
+
|
42
44
|
def evaluate(self, output: StepOutput) -> str | Unresolvable:
|
43
45
|
"""String tokens are passed as they are.
|
44
46
|
|
@@ -53,6 +55,8 @@ class String(Node):
|
|
53
55
|
class URL(Node):
|
54
56
|
"""A node for `$url` expression."""
|
55
57
|
|
58
|
+
__slots__ = ()
|
59
|
+
|
56
60
|
def evaluate(self, output: StepOutput) -> str | Unresolvable:
|
57
61
|
import requests
|
58
62
|
|
@@ -66,6 +70,8 @@ class URL(Node):
|
|
66
70
|
class Method(Node):
|
67
71
|
"""A node for `$method` expression."""
|
68
72
|
|
73
|
+
__slots__ = ()
|
74
|
+
|
69
75
|
def evaluate(self, output: StepOutput) -> str | Unresolvable:
|
70
76
|
return output.case.operation.method.upper()
|
71
77
|
|
@@ -74,6 +80,8 @@ class Method(Node):
|
|
74
80
|
class StatusCode(Node):
|
75
81
|
"""A node for `$statusCode` expression."""
|
76
82
|
|
83
|
+
__slots__ = ()
|
84
|
+
|
77
85
|
def evaluate(self, output: StepOutput) -> str | Unresolvable:
|
78
86
|
return str(output.response.status_code)
|
79
87
|
|
@@ -84,7 +92,14 @@ class NonBodyRequest(Node):
|
|
84
92
|
|
85
93
|
location: str
|
86
94
|
parameter: str
|
87
|
-
extractor: Extractor | None
|
95
|
+
extractor: Extractor | None
|
96
|
+
|
97
|
+
__slots__ = ("location", "parameter", "extractor")
|
98
|
+
|
99
|
+
def __init__(self, location: str, parameter: str, extractor: Extractor | None = None) -> None:
|
100
|
+
self.location = location
|
101
|
+
self.parameter = parameter
|
102
|
+
self.extractor = extractor
|
88
103
|
|
89
104
|
def evaluate(self, output: StepOutput) -> str | Unresolvable:
|
90
105
|
container = {
|
@@ -106,7 +121,12 @@ class NonBodyRequest(Node):
|
|
106
121
|
class BodyRequest(Node):
|
107
122
|
"""A node for `$request` expressions where location is `body`."""
|
108
123
|
|
109
|
-
pointer: str | None
|
124
|
+
pointer: str | None
|
125
|
+
|
126
|
+
__slots__ = ("pointer",)
|
127
|
+
|
128
|
+
def __init__(self, pointer: str | None = None) -> None:
|
129
|
+
self.pointer = pointer
|
110
130
|
|
111
131
|
def evaluate(self, output: StepOutput) -> Any | Unresolvable:
|
112
132
|
document = output.case.body
|
@@ -120,7 +140,13 @@ class HeaderResponse(Node):
|
|
120
140
|
"""A node for `$response.header` expressions."""
|
121
141
|
|
122
142
|
parameter: str
|
123
|
-
extractor: Extractor | None
|
143
|
+
extractor: Extractor | None
|
144
|
+
|
145
|
+
__slots__ = ("parameter", "extractor")
|
146
|
+
|
147
|
+
def __init__(self, parameter: str, extractor: Extractor | None = None) -> None:
|
148
|
+
self.parameter = parameter
|
149
|
+
self.extractor = extractor
|
124
150
|
|
125
151
|
def evaluate(self, output: StepOutput) -> str | Unresolvable:
|
126
152
|
value = output.response.headers.get(self.parameter.lower())
|
@@ -135,7 +161,12 @@ class HeaderResponse(Node):
|
|
135
161
|
class BodyResponse(Node):
|
136
162
|
"""A node for `$response.body` expressions."""
|
137
163
|
|
138
|
-
pointer: str | None
|
164
|
+
pointer: str | None
|
165
|
+
|
166
|
+
__slots__ = ("pointer",)
|
167
|
+
|
168
|
+
def __init__(self, pointer: str | None = None) -> None:
|
169
|
+
self.pointer = pointer
|
139
170
|
|
140
171
|
def evaluate(self, output: StepOutput) -> Any:
|
141
172
|
document = output.response.json()
|
@@ -74,6 +74,8 @@ class MutationContext:
|
|
74
74
|
# Payload media type, if available
|
75
75
|
media_type: str | None
|
76
76
|
|
77
|
+
__slots__ = ("keywords", "non_keywords", "location", "media_type")
|
78
|
+
|
77
79
|
@property
|
78
80
|
def is_header_location(self) -> bool:
|
79
81
|
return is_header_location(self.location)
|
@@ -34,8 +34,6 @@ def prepare_headers(case: Case, headers: dict[str, str] | None = None) -> CaseIn
|
|
34
34
|
default_headers.setdefault(SCHEMATHESIS_TEST_CASE_HEADER, case.id)
|
35
35
|
if headers:
|
36
36
|
default_headers.update(headers)
|
37
|
-
for header in get_exclude_headers(case):
|
38
|
-
default_headers.pop(header, None)
|
39
37
|
return default_headers
|
40
38
|
|
41
39
|
|
@@ -4,7 +4,7 @@ import binascii
|
|
4
4
|
import inspect
|
5
5
|
import os
|
6
6
|
from io import BytesIO
|
7
|
-
from typing import TYPE_CHECKING, Any
|
7
|
+
from typing import TYPE_CHECKING, Any, MutableMapping
|
8
8
|
from urllib.parse import urlparse
|
9
9
|
|
10
10
|
from schemathesis.core import NotSet
|
@@ -13,7 +13,7 @@ from schemathesis.core.transforms import deepclone, merge_at
|
|
13
13
|
from schemathesis.core.transport import DEFAULT_RESPONSE_TIMEOUT, Response
|
14
14
|
from schemathesis.generation.overrides import Override
|
15
15
|
from schemathesis.transport import BaseTransport, SerializationContext
|
16
|
-
from schemathesis.transport.prepare import prepare_body, prepare_headers, prepare_url
|
16
|
+
from schemathesis.transport.prepare import get_exclude_headers, prepare_body, prepare_headers, prepare_url
|
17
17
|
from schemathesis.transport.serialization import Binary, serialize_binary, serialize_json, serialize_xml, serialize_yaml
|
18
18
|
|
19
19
|
if TYPE_CHECKING:
|
@@ -85,23 +85,54 @@ class RequestsTransport(BaseTransport["requests.Session"]):
|
|
85
85
|
def send(self, case: Case, *, session: requests.Session | None = None, **kwargs: Any) -> Response:
|
86
86
|
import requests
|
87
87
|
|
88
|
+
config = case.operation.schema.config
|
89
|
+
|
90
|
+
timeout = config.request_timeout_for(operation=case.operation)
|
91
|
+
verify = config.tls_verify_for(operation=case.operation)
|
92
|
+
cert = config.request_cert_for(operation=case.operation)
|
93
|
+
|
94
|
+
if session is not None and session.headers:
|
95
|
+
# These headers are explicitly provided via config or CLI args.
|
96
|
+
# They have lower priority than ones provided via `kwargs`
|
97
|
+
headers = kwargs.setdefault("headers", {}) or {}
|
98
|
+
for name, value in session.headers.items():
|
99
|
+
headers.setdefault(name, value)
|
100
|
+
kwargs["headers"] = headers
|
101
|
+
|
88
102
|
data = self.serialize_case(case, **kwargs)
|
103
|
+
|
104
|
+
if verify is not None:
|
105
|
+
data.setdefault("verify", verify)
|
106
|
+
if timeout is not None:
|
107
|
+
data.setdefault("timeout", timeout)
|
108
|
+
if cert is not None:
|
109
|
+
data.setdefault("cert", cert)
|
110
|
+
|
89
111
|
kwargs.pop("base_url", None)
|
90
112
|
data.update({key: value for key, value in kwargs.items() if key not in data})
|
91
113
|
data.setdefault("timeout", DEFAULT_RESPONSE_TIMEOUT)
|
92
114
|
|
115
|
+
excluded_headers = get_exclude_headers(case)
|
116
|
+
for name in excluded_headers:
|
117
|
+
data["headers"].pop(name, None)
|
118
|
+
current_session_headers: MutableMapping[str, Any] = {}
|
119
|
+
current_session_auth = None
|
120
|
+
|
93
121
|
if session is None:
|
94
122
|
validate_vanilla_requests_kwargs(data)
|
95
123
|
session = requests.Session()
|
96
|
-
session.headers = {}
|
97
124
|
close_session = True
|
98
125
|
else:
|
126
|
+
current_session_headers = session.headers
|
127
|
+
if isinstance(session.auth, tuple) and "Authorization" in excluded_headers:
|
128
|
+
current_session_auth = session.auth
|
129
|
+
session.auth = None
|
99
130
|
close_session = False
|
131
|
+
session.headers = {}
|
100
132
|
|
101
133
|
verify = data.get("verify", True)
|
102
134
|
|
103
135
|
try:
|
104
|
-
config = case.operation.schema.config
|
105
136
|
rate_limit = config.rate_limit_for(operation=case.operation)
|
106
137
|
with ratelimit(rate_limit, config.base_url):
|
107
138
|
response = session.request(**data) # type: ignore
|
@@ -115,8 +146,10 @@ class RequestsTransport(BaseTransport["requests.Session"]):
|
|
115
146
|
path_parameters={},
|
116
147
|
),
|
117
148
|
)
|
118
|
-
|
119
149
|
finally:
|
150
|
+
session.headers = current_session_headers
|
151
|
+
if current_session_auth is not None:
|
152
|
+
session.auth = current_session_auth
|
120
153
|
if close_session:
|
121
154
|
session.close()
|
122
155
|
|
schemathesis/transport/wsgi.py
CHANGED
@@ -12,7 +12,13 @@ from schemathesis.generation.case import Case
|
|
12
12
|
from schemathesis.generation.overrides import Override
|
13
13
|
from schemathesis.python import wsgi
|
14
14
|
from schemathesis.transport import BaseTransport, SerializationContext
|
15
|
-
from schemathesis.transport.prepare import
|
15
|
+
from schemathesis.transport.prepare import (
|
16
|
+
get_exclude_headers,
|
17
|
+
normalize_base_url,
|
18
|
+
prepare_body,
|
19
|
+
prepare_headers,
|
20
|
+
prepare_path,
|
21
|
+
)
|
16
22
|
from schemathesis.transport.requests import REQUESTS_TRANSPORT
|
17
23
|
from schemathesis.transport.serialization import serialize_binary, serialize_json, serialize_xml, serialize_yaml
|
18
24
|
|
@@ -73,6 +79,10 @@ class WSGITransport(BaseTransport["werkzeug.Client"]):
|
|
73
79
|
data = self.serialize_case(case, headers=headers, params=params)
|
74
80
|
data.update({key: value for key, value in kwargs.items() if key not in data})
|
75
81
|
|
82
|
+
excluded_headers = get_exclude_headers(case)
|
83
|
+
for name in excluded_headers:
|
84
|
+
data["headers"].pop(name, None)
|
85
|
+
|
76
86
|
client = session or wsgi.get_client(application)
|
77
87
|
cookies = {**(case.cookies or {}), **(cookies or {})}
|
78
88
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: schemathesis
|
3
|
-
Version: 4.0.
|
3
|
+
Version: 4.0.3
|
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
|
@@ -170,7 +170,7 @@ def test_api(case):
|
|
170
170
|
|
171
171
|
**CI/CD:**
|
172
172
|
```yaml
|
173
|
-
- uses: schemathesis/action@
|
173
|
+
- uses: schemathesis/action@v2
|
174
174
|
with:
|
175
175
|
schema: "https://your-api.com/openapi.json"
|
176
176
|
```
|
@@ -3,9 +3,9 @@ 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
5
|
schemathesis/filters.py,sha256=OEub50Ob5sf0Tn3iTeuIaxSMtepF7KVoiEM9wtt5GGA,13433
|
6
|
-
schemathesis/hooks.py,sha256=
|
6
|
+
schemathesis/hooks.py,sha256=L1o9IQz0_mY59gs3WGHGSCnGHjF6WWEZZuwJaHcVG1o,13922
|
7
7
|
schemathesis/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
|
-
schemathesis/schemas.py,sha256=
|
8
|
+
schemathesis/schemas.py,sha256=glaIjN7JO1mdOCs5_HUFjLWQ-89z8NFBUIuc5p8cLAU,28386
|
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
|
@@ -21,9 +21,9 @@ schemathesis/cli/commands/run/loaders.py,sha256=6j0ez7wduAUYbUT28ELKxMf-dYEWr_67
|
|
21
21
|
schemathesis/cli/commands/run/validation.py,sha256=FzCzYdW1-hn3OgyzPO1p6wHEX5PG7HdewbPRvclV_vc,9002
|
22
22
|
schemathesis/cli/commands/run/handlers/__init__.py,sha256=TPZ3KdGi8m0fjlN0GjA31MAXXn1qI7uU4FtiDwroXZI,1915
|
23
23
|
schemathesis/cli/commands/run/handlers/base.py,sha256=yDsTtCiztLksfk7cRzg8JlaAVOfS-zwK3tsJMOXAFyc,530
|
24
|
-
schemathesis/cli/commands/run/handlers/cassettes.py,sha256=
|
25
|
-
schemathesis/cli/commands/run/handlers/junitxml.py,sha256=
|
26
|
-
schemathesis/cli/commands/run/handlers/output.py,sha256=
|
24
|
+
schemathesis/cli/commands/run/handlers/cassettes.py,sha256=rRD4byjp4HXCkJS-zx3jSIFOJsPq77ejPpYeyCtsEZs,19461
|
25
|
+
schemathesis/cli/commands/run/handlers/junitxml.py,sha256=Q5GxGjsPq-oKVgq5P19nv0rsi-ZWT5ghHWh-WXgpQ5k,2550
|
26
|
+
schemathesis/cli/commands/run/handlers/output.py,sha256=4sffi2lj3QcDt6JKJCsIT9wCesj1ZdHfTaP6-8dTwh8,62884
|
27
27
|
schemathesis/cli/ext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
28
28
|
schemathesis/cli/ext/fs.py,sha256=3lvoAsEDDdih75ITJJNxemd3nwxX55gGWrI7uDxm0cM,447
|
29
29
|
schemathesis/cli/ext/groups.py,sha256=kQ37t6qeArcKaY2y5VxyK3_KwAkBKCVm58IYV8gewds,2720
|
@@ -46,7 +46,7 @@ schemathesis/config/_report.py,sha256=aYLnPO74B7Wfn_qTwlEp5zY9L74U1XFuYS10yjwKKW
|
|
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=wC1qe9M_fXotfmlBOmW_FCTRw9K5YC814-PipMGKllE,18907
|
49
|
-
schemathesis/core/__init__.py,sha256=
|
49
|
+
schemathesis/core/__init__.py,sha256=j862XBH5dXhxsrDg9mE7n4cSSfol0EHdY0ru1d27tCc,1917
|
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
|
@@ -70,13 +70,13 @@ schemathesis/core/output/__init__.py,sha256=SiHqONFskXl73AtP5dV29L14nZoKo7B-IeG5
|
|
70
70
|
schemathesis/core/output/sanitization.py,sha256=Ev3tae8dVwsYd7yVb2_1VBFYs92WFsQ4Eu1fGaymItE,2013
|
71
71
|
schemathesis/engine/__init__.py,sha256=QaFE-FinaTAaarteADo2RRMJ-Sz6hZB9TzD5KjMinIA,706
|
72
72
|
schemathesis/engine/context.py,sha256=x-I9KX6rO6hdCvvN8FEdzIZBqIcNaxdNYHgQjcXbZhM,3931
|
73
|
-
schemathesis/engine/control.py,sha256=
|
74
|
-
schemathesis/engine/core.py,sha256=
|
73
|
+
schemathesis/engine/control.py,sha256=FXzP8dxL47j1Giqpy2-Bsr_MdMw9YiATSK_UfpFwDtk,1348
|
74
|
+
schemathesis/engine/core.py,sha256=5jfAqFH0XSD7NVgoSXuUPW-dooItscneAzUNq1RBh1E,5712
|
75
75
|
schemathesis/engine/errors.py,sha256=cWKuwj0Kzr2BHdVCHACnniUJ8sFVJ0Nqckc3iggZS1o,18800
|
76
76
|
schemathesis/engine/events.py,sha256=VV6epicFIJnX4c87fVNSd0ibDccX3gryDv52OUGa3FI,6370
|
77
77
|
schemathesis/engine/recorder.py,sha256=K3HfMARrT5mPWXPnYebjjcq5CcsBRhMrtZwEL9_Lvtg,8432
|
78
|
-
schemathesis/engine/phases/__init__.py,sha256=
|
79
|
-
schemathesis/engine/phases/probes.py,sha256
|
78
|
+
schemathesis/engine/phases/__init__.py,sha256=jUIfb_9QoUo4zmJEVU0z70PgXPYjt8CIqp4qP_HlYHg,3146
|
79
|
+
schemathesis/engine/phases/probes.py,sha256=SEtWKPdkLfRTKV0_tbiNHTK3sJsUUPZ0jZQ9Nv4qUi8,5678
|
80
80
|
schemathesis/engine/phases/stateful/__init__.py,sha256=Lz1rgNqCfUSIz173XqCGsiMuUI5bh4L-RIFexU1-c_Q,2461
|
81
81
|
schemathesis/engine/phases/stateful/_executor.py,sha256=CV4jUuXpV4uSXVJqDI4btnLR8dpzOQVqbv2qVCgE4_s,15182
|
82
82
|
schemathesis/engine/phases/stateful/context.py,sha256=A7X1SLDOWFpCvFN9IiIeNVZM0emjqatmJL_k9UsO7vM,2946
|
@@ -84,14 +84,14 @@ schemathesis/engine/phases/unit/__init__.py,sha256=BvZh39LZmXg90Cy_Tn0cQY5y7eWzY
|
|
84
84
|
schemathesis/engine/phases/unit/_executor.py,sha256=jay_D7fmmBTjZigifmY30RiVP5Jb0OlK450fknSWZ_I,16471
|
85
85
|
schemathesis/engine/phases/unit/_pool.py,sha256=iU0hdHDmohPnEv7_S1emcabuzbTf-Cznqwn0pGQ5wNQ,2480
|
86
86
|
schemathesis/generation/__init__.py,sha256=tvNO2FLiY8z3fZ_kL_QJhSgzXfnT4UqwSXMHCwfLI0g,645
|
87
|
-
schemathesis/generation/case.py,sha256=
|
87
|
+
schemathesis/generation/case.py,sha256=MuqnKsJBpGm2gaqDFdJi1yGSWgBhqJUwtYaX97kfXgo,11820
|
88
88
|
schemathesis/generation/coverage.py,sha256=bKP0idU5-eiK4VwhH4kjxDPtCZzMg81mbN1tEDuT6EA,47913
|
89
|
-
schemathesis/generation/meta.py,sha256=
|
89
|
+
schemathesis/generation/meta.py,sha256=adkoMuCfzSjHJ9ZDocQn0GnVldSCkLL3eVR5A_jafwM,2552
|
90
90
|
schemathesis/generation/metrics.py,sha256=cZU5HdeAMcLFEDnTbNE56NuNq4P0N4ew-g1NEz5-kt4,2836
|
91
91
|
schemathesis/generation/modes.py,sha256=Q1fhjWr3zxabU5qdtLvKfpMFZJAwlW9pnxgenjeXTyU,481
|
92
|
-
schemathesis/generation/overrides.py,sha256=
|
92
|
+
schemathesis/generation/overrides.py,sha256=OBWqDQPreiliaf2M-oyXppVKHoJkCRzxtwSJx1b6AFw,3759
|
93
93
|
schemathesis/generation/hypothesis/__init__.py,sha256=SVwM-rx07jPZzms0idWYACgUtWAxh49HRuTnaQ__zf0,1549
|
94
|
-
schemathesis/generation/hypothesis/builder.py,sha256=
|
94
|
+
schemathesis/generation/hypothesis/builder.py,sha256=xc5U3LfJ1lQHKFFW_9W8n3KFutwA2mv954A4jLhB9vg,33105
|
95
95
|
schemathesis/generation/hypothesis/examples.py,sha256=6eGaKUEC3elmKsaqfKj1sLvM8EHc-PWT4NRBq4NI0Rs,1409
|
96
96
|
schemathesis/generation/hypothesis/given.py,sha256=sTZR1of6XaHAPWtHx2_WLlZ50M8D5Rjux0GmWkWjDq4,2337
|
97
97
|
schemathesis/generation/hypothesis/reporting.py,sha256=uDVow6Ya8YFkqQuOqRsjbzsbyP4KKfr3jA7ZaY4FuKY,279
|
@@ -108,27 +108,27 @@ schemathesis/openapi/generation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm
|
|
108
108
|
schemathesis/openapi/generation/filters.py,sha256=pY9cUZdL_kQK80Z2aylTOqqa12zmaYUlYC5BfYgeQMk,2395
|
109
109
|
schemathesis/pytest/__init__.py,sha256=7W0q-Thcw03IAQfXE_Mo8JPZpUdHJzfu85fjK1ZdfQM,88
|
110
110
|
schemathesis/pytest/control_flow.py,sha256=F8rAPsPeNv_sJiJgbZYtTpwKWjauZmqFUaKroY2GmQI,217
|
111
|
-
schemathesis/pytest/lazy.py,sha256=
|
111
|
+
schemathesis/pytest/lazy.py,sha256=u58q0orI0zisivLJKJkSo53RaQMPLSMiE0vJ1TQ9_uA,11073
|
112
112
|
schemathesis/pytest/loaders.py,sha256=Sbv8e5F77_x4amLP50iwubfm6kpOhx7LhLFGsVXW5Ys,925
|
113
|
-
schemathesis/pytest/plugin.py,sha256=
|
113
|
+
schemathesis/pytest/plugin.py,sha256=MXllorF5SqUgqjLyhHb-P0wlWokvZMg0Rm6OTRoFoas,14266
|
114
114
|
schemathesis/python/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
115
115
|
schemathesis/python/asgi.py,sha256=5PyvuTBaivvyPUEi3pwJni91K1kX5Zc0u9c6c1D8a1Q,287
|
116
116
|
schemathesis/python/wsgi.py,sha256=uShAgo_NChbfYaV1117e6UHp0MTg7jaR0Sy_to3Jmf8,219
|
117
117
|
schemathesis/specs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
118
118
|
schemathesis/specs/graphql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
119
|
-
schemathesis/specs/graphql/_cache.py,sha256=
|
119
|
+
schemathesis/specs/graphql/_cache.py,sha256=mlOtzEvdE9gZ1posP7OqHUYlaZyiygL5U_Xda7wphFc,988
|
120
120
|
schemathesis/specs/graphql/nodes.py,sha256=bE3G1kNmqJ8OV4igBvIK-UORrkQA6Nofduf87O3TD9I,541
|
121
121
|
schemathesis/specs/graphql/scalars.py,sha256=6lew8mnwhrtg23leiEbG43mLGPLlRln8mClCY94XpDA,2680
|
122
|
-
schemathesis/specs/graphql/schemas.py,sha256=
|
122
|
+
schemathesis/specs/graphql/schemas.py,sha256=ezkqgMwx37tMWlhy_I0ahDF1Q44emDSJkyjduq1QGjE,14624
|
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/_cache.py,sha256=HpglmETmZU0RCHxp3DO_sg5_B_nzi54Zuw9vGzzYCxY,4295
|
126
|
-
schemathesis/specs/openapi/_hypothesis.py,sha256=
|
126
|
+
schemathesis/specs/openapi/_hypothesis.py,sha256=NuXucpwn8jjL_O0anja1TPqEuXyuFq8quIuECIW9BLY,22611
|
127
127
|
schemathesis/specs/openapi/checks.py,sha256=mKJ-ZkbjhbXS4eWDZiv8zslXKFDqkE3Mp4N8TVDHiI0,29801
|
128
128
|
schemathesis/specs/openapi/constants.py,sha256=JqM_FHOenqS_MuUE9sxVQ8Hnw0DNM8cnKDwCwPLhID4,783
|
129
129
|
schemathesis/specs/openapi/converter.py,sha256=lil8IewM5j8tvt4lpA9g_KITvIwx1M96i45DNSHNjoc,3505
|
130
130
|
schemathesis/specs/openapi/definitions.py,sha256=8htclglV3fW6JPBqs59lgM4LnA25Mm9IptXBPb_qUT0,93949
|
131
|
-
schemathesis/specs/openapi/examples.py,sha256=
|
131
|
+
schemathesis/specs/openapi/examples.py,sha256=11GMuwyTws8MizQ3CkfT3dQD4TFP22CGYBMUyESYsDM,21218
|
132
132
|
schemathesis/specs/openapi/formats.py,sha256=8AIS7Uey-Z1wm1WYRqnsVqHwG9d316PdqfKLqwUs7us,3516
|
133
133
|
schemathesis/specs/openapi/media_types.py,sha256=F5M6TKl0s6Z5X8mZpPsWDEdPBvxclKRcUOc41eEwKbo,2472
|
134
134
|
schemathesis/specs/openapi/parameters.py,sha256=BevME4DWLQ-OFvc_7fREMjj99VAbVNxVb5i8OEX6Pfs,14453
|
@@ -140,25 +140,25 @@ schemathesis/specs/openapi/serialization.py,sha256=VdDLmeHqxlWM4cxQQcCkvrU6Xuriv
|
|
140
140
|
schemathesis/specs/openapi/utils.py,sha256=ER4vJkdFVDIE7aKyxyYatuuHVRNutytezgE52pqZNE8,900
|
141
141
|
schemathesis/specs/openapi/expressions/__init__.py,sha256=hfuRtXD75tQFhzSo6QgDZ3zByyWeZRKevB8edszAVj4,2272
|
142
142
|
schemathesis/specs/openapi/expressions/errors.py,sha256=YLVhps-sYcslgVaahfcUYxUSHlIfWL-rQMeT5PZSMZ8,219
|
143
|
-
schemathesis/specs/openapi/expressions/extractors.py,sha256=
|
144
|
-
schemathesis/specs/openapi/expressions/lexer.py,sha256=
|
145
|
-
schemathesis/specs/openapi/expressions/nodes.py,sha256=
|
143
|
+
schemathesis/specs/openapi/expressions/extractors.py,sha256=IvOrgq_1IWNnirOSV_wLi0UcWOTiL-mLvBLFzLwRpVA,498
|
144
|
+
schemathesis/specs/openapi/expressions/lexer.py,sha256=ZbYPbVX-2c2Dan-6fi4NrDlFT6N55Wrz-4921TKHlZs,4030
|
145
|
+
schemathesis/specs/openapi/expressions/nodes.py,sha256=qaFpAM3seIzmlYLr9So2kRCSNrteZTa7djcRiOD_ji4,4811
|
146
146
|
schemathesis/specs/openapi/expressions/parser.py,sha256=e-ZxshrGE_5CVbgcZLYgdGSjdifgyzgKkLQp0dI0cJY,4503
|
147
|
-
schemathesis/specs/openapi/negative/__init__.py,sha256=
|
148
|
-
schemathesis/specs/openapi/negative/mutations.py,sha256=
|
147
|
+
schemathesis/specs/openapi/negative/__init__.py,sha256=1sajF22SrE4pUK7-C6PiseZ9PiR5trN33cfUqEMGIbo,3915
|
148
|
+
schemathesis/specs/openapi/negative/mutations.py,sha256=ZLiNb4n2K1Oeq3eev8tgNqvlyP7cBIPUTLe7Gc6nvDM,19318
|
149
149
|
schemathesis/specs/openapi/negative/types.py,sha256=a7buCcVxNBG6ILBM3A7oNTAX0lyDseEtZndBuej8MbI,174
|
150
150
|
schemathesis/specs/openapi/negative/utils.py,sha256=ozcOIuASufLqZSgnKUACjX-EOZrrkuNdXX0SDnLoGYA,168
|
151
151
|
schemathesis/specs/openapi/stateful/__init__.py,sha256=FSitLbJxjBYU814cqjI_QCkdyoIc-9xfT_1HQcYwsXw,15064
|
152
152
|
schemathesis/specs/openapi/stateful/control.py,sha256=QaXLSbwQWtai5lxvvVtQV3BLJ8n5ePqSKB00XFxp-MA,3695
|
153
|
-
schemathesis/specs/openapi/stateful/links.py,sha256=
|
153
|
+
schemathesis/specs/openapi/stateful/links.py,sha256=h5q40jUbcIk5DS_Tih1cvFJxS_QxxG0_9ZQnTs1A_zo,8806
|
154
154
|
schemathesis/transport/__init__.py,sha256=6yg_RfV_9L0cpA6qpbH-SL9_3ggtHQji9CZrpIkbA6s,5321
|
155
155
|
schemathesis/transport/asgi.py,sha256=qTClt6oT_xUEWnRHokACN_uqCNNUZrRPT6YG0PjbElY,926
|
156
|
-
schemathesis/transport/prepare.py,sha256=
|
157
|
-
schemathesis/transport/requests.py,sha256=
|
156
|
+
schemathesis/transport/prepare.py,sha256=iiB8KTAqnnuqjWzblIPiGVdkGIF7Yr1SAEz-KZzBNXw,4581
|
157
|
+
schemathesis/transport/requests.py,sha256=rziZTrZCVMAqgy6ldB8iTwhkpAsnjKSgK8hj5Sq3ThE,10656
|
158
158
|
schemathesis/transport/serialization.py,sha256=igUXKZ_VJ9gV7P0TUc5PDQBJXl_s0kK9T3ljGWWvo6E,10339
|
159
|
-
schemathesis/transport/wsgi.py,sha256=
|
160
|
-
schemathesis-4.0.
|
161
|
-
schemathesis-4.0.
|
162
|
-
schemathesis-4.0.
|
163
|
-
schemathesis-4.0.
|
164
|
-
schemathesis-4.0.
|
159
|
+
schemathesis/transport/wsgi.py,sha256=KoAfvu6RJtzyj24VGB8e-Iaa9smpgXJ3VsM8EgAz2tc,6152
|
160
|
+
schemathesis-4.0.3.dist-info/METADATA,sha256=hm5ioN50c0UyShRq7AN-9qzDnKGLMYSxQwXw1Lw7jTc,8471
|
161
|
+
schemathesis-4.0.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
162
|
+
schemathesis-4.0.3.dist-info/entry_points.txt,sha256=hiK3un-xfgPdwj9uj16YVDtTNpO128bmk0U82SMv8ZQ,152
|
163
|
+
schemathesis-4.0.3.dist-info/licenses/LICENSE,sha256=2Ve4J8v5jMQAWrT7r1nf3bI8Vflk3rZVQefiF2zpxwg,1121
|
164
|
+
schemathesis-4.0.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|