schemathesis 3.39.7__py3-none-any.whl → 4.0.0a2__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 +27 -65
- schemathesis/auths.py +26 -68
- schemathesis/checks.py +130 -60
- schemathesis/cli/__init__.py +5 -2105
- schemathesis/cli/commands/__init__.py +37 -0
- schemathesis/cli/commands/run/__init__.py +662 -0
- schemathesis/cli/commands/run/checks.py +80 -0
- schemathesis/cli/commands/run/context.py +117 -0
- schemathesis/cli/commands/run/events.py +30 -0
- schemathesis/cli/commands/run/executor.py +141 -0
- schemathesis/cli/commands/run/filters.py +202 -0
- schemathesis/cli/commands/run/handlers/__init__.py +46 -0
- schemathesis/cli/commands/run/handlers/base.py +18 -0
- schemathesis/cli/{cassettes.py → commands/run/handlers/cassettes.py} +178 -247
- schemathesis/cli/commands/run/handlers/junitxml.py +54 -0
- schemathesis/cli/commands/run/handlers/output.py +1368 -0
- schemathesis/cli/commands/run/hypothesis.py +105 -0
- schemathesis/cli/commands/run/loaders.py +129 -0
- schemathesis/cli/{callbacks.py → commands/run/validation.py} +59 -175
- schemathesis/cli/constants.py +5 -58
- schemathesis/cli/core.py +17 -0
- schemathesis/cli/ext/fs.py +14 -0
- schemathesis/cli/ext/groups.py +55 -0
- schemathesis/cli/{options.py → ext/options.py} +37 -16
- schemathesis/cli/hooks.py +36 -0
- schemathesis/contrib/__init__.py +1 -3
- schemathesis/contrib/openapi/__init__.py +1 -3
- schemathesis/contrib/openapi/fill_missing_examples.py +3 -7
- schemathesis/core/__init__.py +58 -0
- schemathesis/core/compat.py +25 -0
- schemathesis/core/control.py +2 -0
- schemathesis/core/curl.py +58 -0
- schemathesis/core/deserialization.py +65 -0
- schemathesis/core/errors.py +370 -0
- schemathesis/core/failures.py +315 -0
- schemathesis/core/fs.py +19 -0
- schemathesis/core/loaders.py +104 -0
- schemathesis/core/marks.py +66 -0
- schemathesis/{transports/content_types.py → core/media_types.py} +14 -12
- schemathesis/{internal/output.py → core/output/__init__.py} +1 -0
- schemathesis/core/output/sanitization.py +197 -0
- schemathesis/{throttling.py → core/rate_limit.py} +16 -17
- schemathesis/core/registries.py +31 -0
- schemathesis/core/transforms.py +113 -0
- schemathesis/core/transport.py +108 -0
- schemathesis/core/validation.py +38 -0
- schemathesis/core/version.py +7 -0
- schemathesis/engine/__init__.py +30 -0
- schemathesis/engine/config.py +59 -0
- schemathesis/engine/context.py +119 -0
- schemathesis/engine/control.py +36 -0
- schemathesis/engine/core.py +157 -0
- schemathesis/engine/errors.py +394 -0
- schemathesis/engine/events.py +243 -0
- schemathesis/engine/phases/__init__.py +66 -0
- schemathesis/{runner → engine/phases}/probes.py +49 -68
- schemathesis/engine/phases/stateful/__init__.py +66 -0
- schemathesis/engine/phases/stateful/_executor.py +301 -0
- schemathesis/engine/phases/stateful/context.py +85 -0
- schemathesis/engine/phases/unit/__init__.py +175 -0
- schemathesis/engine/phases/unit/_executor.py +322 -0
- schemathesis/engine/phases/unit/_pool.py +74 -0
- schemathesis/engine/recorder.py +246 -0
- schemathesis/errors.py +31 -0
- schemathesis/experimental/__init__.py +9 -40
- schemathesis/filters.py +7 -95
- schemathesis/generation/__init__.py +3 -3
- schemathesis/generation/case.py +190 -0
- schemathesis/generation/coverage.py +22 -22
- schemathesis/{_patches.py → generation/hypothesis/__init__.py} +15 -6
- schemathesis/generation/hypothesis/builder.py +585 -0
- schemathesis/generation/{_hypothesis.py → hypothesis/examples.py} +2 -11
- schemathesis/generation/hypothesis/given.py +66 -0
- schemathesis/generation/hypothesis/reporting.py +14 -0
- schemathesis/generation/hypothesis/strategies.py +16 -0
- schemathesis/generation/meta.py +115 -0
- schemathesis/generation/modes.py +28 -0
- schemathesis/generation/overrides.py +96 -0
- schemathesis/generation/stateful/__init__.py +20 -0
- schemathesis/{stateful → generation/stateful}/state_machine.py +84 -109
- schemathesis/generation/targets.py +69 -0
- schemathesis/graphql/__init__.py +15 -0
- schemathesis/graphql/checks.py +109 -0
- schemathesis/graphql/loaders.py +131 -0
- schemathesis/hooks.py +17 -62
- schemathesis/openapi/__init__.py +13 -0
- schemathesis/openapi/checks.py +387 -0
- schemathesis/openapi/generation/__init__.py +0 -0
- schemathesis/openapi/generation/filters.py +63 -0
- schemathesis/openapi/loaders.py +178 -0
- schemathesis/pytest/__init__.py +5 -0
- schemathesis/pytest/control_flow.py +7 -0
- schemathesis/pytest/lazy.py +273 -0
- schemathesis/pytest/loaders.py +12 -0
- schemathesis/{extra/pytest_plugin.py → pytest/plugin.py} +94 -107
- schemathesis/python/__init__.py +0 -0
- schemathesis/python/asgi.py +12 -0
- schemathesis/python/wsgi.py +12 -0
- schemathesis/schemas.py +456 -228
- schemathesis/specs/graphql/__init__.py +0 -1
- schemathesis/specs/graphql/_cache.py +1 -2
- schemathesis/specs/graphql/scalars.py +5 -3
- schemathesis/specs/graphql/schemas.py +122 -123
- schemathesis/specs/graphql/validation.py +11 -17
- schemathesis/specs/openapi/__init__.py +6 -1
- schemathesis/specs/openapi/_cache.py +1 -2
- schemathesis/specs/openapi/_hypothesis.py +97 -134
- schemathesis/specs/openapi/checks.py +238 -219
- schemathesis/specs/openapi/converter.py +4 -4
- schemathesis/specs/openapi/definitions.py +1 -1
- schemathesis/specs/openapi/examples.py +22 -20
- schemathesis/specs/openapi/expressions/__init__.py +11 -15
- schemathesis/specs/openapi/expressions/extractors.py +1 -4
- schemathesis/specs/openapi/expressions/nodes.py +33 -32
- schemathesis/specs/openapi/formats.py +3 -2
- schemathesis/specs/openapi/links.py +123 -299
- schemathesis/specs/openapi/media_types.py +10 -12
- schemathesis/specs/openapi/negative/__init__.py +2 -1
- schemathesis/specs/openapi/negative/mutations.py +3 -2
- schemathesis/specs/openapi/parameters.py +8 -6
- schemathesis/specs/openapi/patterns.py +1 -1
- schemathesis/specs/openapi/references.py +11 -51
- schemathesis/specs/openapi/schemas.py +177 -191
- schemathesis/specs/openapi/security.py +1 -1
- schemathesis/specs/openapi/serialization.py +10 -6
- schemathesis/specs/openapi/stateful/__init__.py +97 -91
- schemathesis/transport/__init__.py +104 -0
- schemathesis/transport/asgi.py +26 -0
- schemathesis/transport/prepare.py +99 -0
- schemathesis/transport/requests.py +221 -0
- schemathesis/{_xml.py → transport/serialization.py} +69 -7
- schemathesis/transport/wsgi.py +165 -0
- {schemathesis-3.39.7.dist-info → schemathesis-4.0.0a2.dist-info}/METADATA +18 -14
- schemathesis-4.0.0a2.dist-info/RECORD +151 -0
- {schemathesis-3.39.7.dist-info → schemathesis-4.0.0a2.dist-info}/entry_points.txt +1 -1
- schemathesis/_compat.py +0 -74
- schemathesis/_dependency_versions.py +0 -19
- schemathesis/_hypothesis.py +0 -559
- schemathesis/_override.py +0 -50
- schemathesis/_rate_limiter.py +0 -7
- schemathesis/cli/context.py +0 -75
- schemathesis/cli/debug.py +0 -27
- schemathesis/cli/handlers.py +0 -19
- schemathesis/cli/junitxml.py +0 -124
- schemathesis/cli/output/__init__.py +0 -1
- schemathesis/cli/output/default.py +0 -936
- schemathesis/cli/output/short.py +0 -59
- schemathesis/cli/reporting.py +0 -79
- schemathesis/cli/sanitization.py +0 -26
- schemathesis/code_samples.py +0 -151
- schemathesis/constants.py +0 -56
- schemathesis/contrib/openapi/formats/__init__.py +0 -9
- schemathesis/contrib/openapi/formats/uuid.py +0 -16
- schemathesis/contrib/unique_data.py +0 -41
- schemathesis/exceptions.py +0 -571
- schemathesis/extra/_aiohttp.py +0 -28
- schemathesis/extra/_flask.py +0 -13
- schemathesis/extra/_server.py +0 -18
- schemathesis/failures.py +0 -277
- schemathesis/fixups/__init__.py +0 -37
- schemathesis/fixups/fast_api.py +0 -41
- schemathesis/fixups/utf8_bom.py +0 -28
- schemathesis/generation/_methods.py +0 -44
- schemathesis/graphql.py +0 -3
- schemathesis/internal/__init__.py +0 -7
- schemathesis/internal/checks.py +0 -84
- schemathesis/internal/copy.py +0 -32
- schemathesis/internal/datetime.py +0 -5
- schemathesis/internal/deprecation.py +0 -38
- schemathesis/internal/diff.py +0 -15
- schemathesis/internal/extensions.py +0 -27
- schemathesis/internal/jsonschema.py +0 -36
- schemathesis/internal/transformation.py +0 -26
- schemathesis/internal/validation.py +0 -34
- schemathesis/lazy.py +0 -474
- schemathesis/loaders.py +0 -122
- schemathesis/models.py +0 -1341
- schemathesis/parameters.py +0 -90
- schemathesis/runner/__init__.py +0 -605
- schemathesis/runner/events.py +0 -389
- schemathesis/runner/impl/__init__.py +0 -3
- schemathesis/runner/impl/context.py +0 -104
- schemathesis/runner/impl/core.py +0 -1246
- schemathesis/runner/impl/solo.py +0 -80
- schemathesis/runner/impl/threadpool.py +0 -391
- schemathesis/runner/serialization.py +0 -544
- schemathesis/sanitization.py +0 -252
- schemathesis/serializers.py +0 -328
- schemathesis/service/__init__.py +0 -18
- schemathesis/service/auth.py +0 -11
- schemathesis/service/ci.py +0 -202
- schemathesis/service/client.py +0 -133
- schemathesis/service/constants.py +0 -38
- schemathesis/service/events.py +0 -61
- schemathesis/service/extensions.py +0 -224
- schemathesis/service/hosts.py +0 -111
- schemathesis/service/metadata.py +0 -71
- schemathesis/service/models.py +0 -258
- schemathesis/service/report.py +0 -255
- schemathesis/service/serialization.py +0 -173
- schemathesis/service/usage.py +0 -66
- schemathesis/specs/graphql/loaders.py +0 -364
- schemathesis/specs/openapi/expressions/context.py +0 -16
- schemathesis/specs/openapi/loaders.py +0 -708
- schemathesis/specs/openapi/stateful/statistic.py +0 -198
- schemathesis/specs/openapi/stateful/types.py +0 -14
- schemathesis/specs/openapi/validation.py +0 -26
- schemathesis/stateful/__init__.py +0 -147
- schemathesis/stateful/config.py +0 -97
- schemathesis/stateful/context.py +0 -135
- schemathesis/stateful/events.py +0 -274
- schemathesis/stateful/runner.py +0 -309
- schemathesis/stateful/sink.py +0 -68
- schemathesis/stateful/statistic.py +0 -22
- schemathesis/stateful/validation.py +0 -100
- schemathesis/targets.py +0 -77
- schemathesis/transports/__init__.py +0 -359
- schemathesis/transports/asgi.py +0 -7
- schemathesis/transports/auth.py +0 -38
- schemathesis/transports/headers.py +0 -36
- schemathesis/transports/responses.py +0 -57
- schemathesis/types.py +0 -44
- schemathesis/utils.py +0 -164
- schemathesis-3.39.7.dist-info/RECORD +0 -160
- /schemathesis/{extra → cli/ext}/__init__.py +0 -0
- /schemathesis/{_lazy_import.py → core/lazy_import.py} +0 -0
- /schemathesis/{internal → core}/result.py +0 -0
- {schemathesis-3.39.7.dist-info → schemathesis-4.0.0a2.dist-info}/WHEEL +0 -0
- {schemathesis-3.39.7.dist-info → schemathesis-4.0.0a2.dist-info}/licenses/LICENSE +0 -0
schemathesis/parameters.py
DELETED
@@ -1,90 +0,0 @@
|
|
1
|
-
"""API operation parameters.
|
2
|
-
|
3
|
-
These are basic entities that describe what data could be sent to the API.
|
4
|
-
"""
|
5
|
-
|
6
|
-
from __future__ import annotations
|
7
|
-
|
8
|
-
from dataclasses import dataclass, field
|
9
|
-
from typing import TYPE_CHECKING, Any, Generator, Generic, TypeVar
|
10
|
-
|
11
|
-
if TYPE_CHECKING:
|
12
|
-
from .models import APIOperation
|
13
|
-
|
14
|
-
|
15
|
-
@dataclass(eq=False)
|
16
|
-
class Parameter:
|
17
|
-
"""A logically separate parameter bound to a location (e.g., to "query string").
|
18
|
-
|
19
|
-
For example, if the API requires multiple headers to be present, each header is presented as a separate
|
20
|
-
`Parameter` instance.
|
21
|
-
"""
|
22
|
-
|
23
|
-
# The parameter definition in the language acceptable by the API
|
24
|
-
definition: Any
|
25
|
-
|
26
|
-
@property
|
27
|
-
def location(self) -> str:
|
28
|
-
"""Where this parameter is located.
|
29
|
-
|
30
|
-
E.g. "query" or "body"
|
31
|
-
"""
|
32
|
-
raise NotImplementedError
|
33
|
-
|
34
|
-
@property
|
35
|
-
def name(self) -> str:
|
36
|
-
"""Parameter name."""
|
37
|
-
raise NotImplementedError
|
38
|
-
|
39
|
-
@property
|
40
|
-
def is_required(self) -> bool:
|
41
|
-
"""Whether the parameter is required for a successful API call."""
|
42
|
-
raise NotImplementedError
|
43
|
-
|
44
|
-
def serialize(self, operation: APIOperation) -> str:
|
45
|
-
"""Get parameter's string representation."""
|
46
|
-
raise NotImplementedError
|
47
|
-
|
48
|
-
|
49
|
-
P = TypeVar("P", bound=Parameter)
|
50
|
-
|
51
|
-
|
52
|
-
@dataclass
|
53
|
-
class ParameterSet(Generic[P]):
|
54
|
-
"""A set of parameters for the same location."""
|
55
|
-
|
56
|
-
items: list[P] = field(default_factory=list)
|
57
|
-
|
58
|
-
def _repr_pretty_(self, *args: Any, **kwargs: Any) -> None: ...
|
59
|
-
|
60
|
-
def add(self, parameter: P) -> None:
|
61
|
-
"""Add a new parameter."""
|
62
|
-
self.items.append(parameter)
|
63
|
-
|
64
|
-
def get(self, name: str) -> P | None:
|
65
|
-
for parameter in self:
|
66
|
-
if parameter.name == name:
|
67
|
-
return parameter
|
68
|
-
return None
|
69
|
-
|
70
|
-
def contains(self, name: str) -> bool:
|
71
|
-
return self.get(name) is not None
|
72
|
-
|
73
|
-
def __contains__(self, item: str) -> bool:
|
74
|
-
return self.contains(item)
|
75
|
-
|
76
|
-
def __bool__(self) -> bool:
|
77
|
-
return bool(self.items)
|
78
|
-
|
79
|
-
def __iter__(self) -> Generator[P, None, None]:
|
80
|
-
yield from iter(self.items)
|
81
|
-
|
82
|
-
def __len__(self) -> int:
|
83
|
-
return len(self.items)
|
84
|
-
|
85
|
-
def __getitem__(self, item: int) -> P:
|
86
|
-
return self.items[item]
|
87
|
-
|
88
|
-
|
89
|
-
class PayloadAlternatives(ParameterSet[P]):
|
90
|
-
"""A set of alternative payloads."""
|
schemathesis/runner/__init__.py
DELETED
@@ -1,605 +0,0 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
|
3
|
-
from random import Random
|
4
|
-
from typing import TYPE_CHECKING, Any, Callable, Generator, Iterable
|
5
|
-
from urllib.parse import urlparse
|
6
|
-
|
7
|
-
from ..constants import (
|
8
|
-
DEFAULT_DEADLINE,
|
9
|
-
DEFAULT_STATEFUL_RECURSION_LIMIT,
|
10
|
-
HYPOTHESIS_IN_MEMORY_DATABASE_IDENTIFIER,
|
11
|
-
)
|
12
|
-
from ..exceptions import SchemaError
|
13
|
-
from ..generation import DEFAULT_DATA_GENERATION_METHODS, DataGenerationMethod, GenerationConfig
|
14
|
-
from ..internal.checks import CheckConfig
|
15
|
-
from ..internal.datetime import current_datetime
|
16
|
-
from ..internal.deprecation import deprecated_function
|
17
|
-
from ..internal.validation import file_exists
|
18
|
-
from ..loaders import load_app
|
19
|
-
from ..specs.graphql import loaders as gql_loaders
|
20
|
-
from ..specs.openapi import loaders as oas_loaders
|
21
|
-
from ..targets import DEFAULT_TARGETS, Target
|
22
|
-
from ..transports import RequestConfig
|
23
|
-
from ..transports.auth import get_requests_auth
|
24
|
-
from ..types import Filter, NotSet, RawAuth, RequestCert
|
25
|
-
from . import events
|
26
|
-
from .probes import ProbeConfig
|
27
|
-
|
28
|
-
if TYPE_CHECKING:
|
29
|
-
import hypothesis
|
30
|
-
|
31
|
-
from .._override import CaseOverride
|
32
|
-
from ..models import CheckFunction
|
33
|
-
from ..schemas import BaseSchema
|
34
|
-
from ..service.client import ServiceClient
|
35
|
-
from ..stateful import Stateful
|
36
|
-
from .impl import BaseRunner
|
37
|
-
|
38
|
-
|
39
|
-
@deprecated_function(removed_in="4.0", replacement="schemathesis.runner.from_schema")
|
40
|
-
def prepare(
|
41
|
-
schema_uri: str | dict[str, Any],
|
42
|
-
*,
|
43
|
-
# Runtime behavior
|
44
|
-
checks: Iterable[CheckFunction] | None = None,
|
45
|
-
data_generation_methods: tuple[DataGenerationMethod, ...] = DEFAULT_DATA_GENERATION_METHODS,
|
46
|
-
max_response_time: int | None = None,
|
47
|
-
targets: Iterable[Target] = DEFAULT_TARGETS,
|
48
|
-
workers_num: int = 1,
|
49
|
-
seed: int | None = None,
|
50
|
-
exit_first: bool = False,
|
51
|
-
dry_run: bool = False,
|
52
|
-
store_interactions: bool = False,
|
53
|
-
stateful: Stateful | None = None,
|
54
|
-
stateful_recursion_limit: int = DEFAULT_STATEFUL_RECURSION_LIMIT,
|
55
|
-
# Schema loading
|
56
|
-
loader: Callable = oas_loaders.from_uri,
|
57
|
-
base_url: str | None = None,
|
58
|
-
auth: tuple[str, str] | None = None,
|
59
|
-
auth_type: str | None = None,
|
60
|
-
override: CaseOverride | None = None,
|
61
|
-
headers: dict[str, str] | None = None,
|
62
|
-
request_timeout: int | None = None,
|
63
|
-
request_tls_verify: bool | str = True,
|
64
|
-
request_cert: RequestCert | None = None,
|
65
|
-
endpoint: Filter | None = None,
|
66
|
-
method: Filter | None = None,
|
67
|
-
tag: Filter | None = None,
|
68
|
-
operation_id: Filter | None = None,
|
69
|
-
app: str | None = None,
|
70
|
-
validate_schema: bool = True,
|
71
|
-
skip_deprecated_operations: bool = False,
|
72
|
-
force_schema_version: str | None = None,
|
73
|
-
count_operations: bool = True,
|
74
|
-
count_links: bool = True,
|
75
|
-
# Hypothesis-specific configuration
|
76
|
-
hypothesis_deadline: int | NotSet | None = None,
|
77
|
-
hypothesis_derandomize: bool | None = None,
|
78
|
-
hypothesis_max_examples: int | None = None,
|
79
|
-
hypothesis_phases: list[hypothesis.Phase] | None = None,
|
80
|
-
hypothesis_report_multiple_bugs: bool | None = None,
|
81
|
-
hypothesis_suppress_health_check: list[hypothesis.HealthCheck] | None = None,
|
82
|
-
hypothesis_verbosity: hypothesis.Verbosity | None = None,
|
83
|
-
probe_config: ProbeConfig | None = None,
|
84
|
-
service_client: ServiceClient | None = None,
|
85
|
-
) -> Generator[events.ExecutionEvent, None, None]:
|
86
|
-
"""Prepare a generator that will run test cases against the given API definition."""
|
87
|
-
from ..checks import DEFAULT_CHECKS
|
88
|
-
|
89
|
-
checks = checks or DEFAULT_CHECKS
|
90
|
-
|
91
|
-
validate_loader(loader, schema_uri)
|
92
|
-
|
93
|
-
if auth is None:
|
94
|
-
# Auth type doesn't matter if auth is not passed
|
95
|
-
auth_type = None # type: ignore
|
96
|
-
hypothesis_settings = prepare_hypothesis_settings(
|
97
|
-
deadline=hypothesis_deadline,
|
98
|
-
derandomize=hypothesis_derandomize,
|
99
|
-
max_examples=hypothesis_max_examples,
|
100
|
-
phases=hypothesis_phases,
|
101
|
-
report_multiple_bugs=hypothesis_report_multiple_bugs,
|
102
|
-
suppress_health_check=hypothesis_suppress_health_check,
|
103
|
-
verbosity=hypothesis_verbosity,
|
104
|
-
)
|
105
|
-
return execute_from_schema(
|
106
|
-
schema_uri=schema_uri,
|
107
|
-
loader=loader,
|
108
|
-
base_url=base_url,
|
109
|
-
endpoint=endpoint,
|
110
|
-
method=method,
|
111
|
-
tag=tag,
|
112
|
-
operation_id=operation_id,
|
113
|
-
app=app,
|
114
|
-
validate_schema=validate_schema,
|
115
|
-
skip_deprecated_operations=skip_deprecated_operations,
|
116
|
-
force_schema_version=force_schema_version,
|
117
|
-
checks=checks,
|
118
|
-
data_generation_methods=data_generation_methods,
|
119
|
-
max_response_time=max_response_time,
|
120
|
-
targets=targets,
|
121
|
-
hypothesis_settings=hypothesis_settings,
|
122
|
-
seed=seed,
|
123
|
-
workers_num=workers_num,
|
124
|
-
exit_first=exit_first,
|
125
|
-
dry_run=dry_run,
|
126
|
-
auth=auth,
|
127
|
-
auth_type=auth_type,
|
128
|
-
override=override,
|
129
|
-
headers=headers,
|
130
|
-
request_timeout=request_timeout,
|
131
|
-
request_tls_verify=request_tls_verify,
|
132
|
-
request_cert=request_cert,
|
133
|
-
store_interactions=store_interactions,
|
134
|
-
stateful=stateful,
|
135
|
-
stateful_recursion_limit=stateful_recursion_limit,
|
136
|
-
count_operations=count_operations,
|
137
|
-
count_links=count_links,
|
138
|
-
probe_config=probe_config,
|
139
|
-
service_client=service_client,
|
140
|
-
)
|
141
|
-
|
142
|
-
|
143
|
-
def validate_loader(loader: Callable, schema_uri: str | dict[str, Any]) -> None:
|
144
|
-
"""Sanity checking for input schema & loader."""
|
145
|
-
if loader not in (
|
146
|
-
oas_loaders.from_uri,
|
147
|
-
oas_loaders.from_aiohttp,
|
148
|
-
oas_loaders.from_dict,
|
149
|
-
oas_loaders.from_file,
|
150
|
-
oas_loaders.from_path,
|
151
|
-
oas_loaders.from_asgi,
|
152
|
-
oas_loaders.from_wsgi,
|
153
|
-
gql_loaders.from_dict,
|
154
|
-
gql_loaders.from_url,
|
155
|
-
gql_loaders.from_wsgi,
|
156
|
-
):
|
157
|
-
# Custom loaders are not checked
|
158
|
-
return
|
159
|
-
if isinstance(schema_uri, dict):
|
160
|
-
if loader not in (oas_loaders.from_dict, gql_loaders.from_dict):
|
161
|
-
raise ValueError("Dictionary as a schema is allowed only with `from_dict` loader")
|
162
|
-
elif loader in (oas_loaders.from_dict, gql_loaders.from_dict):
|
163
|
-
raise ValueError("Schema should be a dictionary for `from_dict` loader")
|
164
|
-
|
165
|
-
|
166
|
-
def execute_from_schema(
|
167
|
-
*,
|
168
|
-
schema_uri: str | dict[str, Any],
|
169
|
-
loader: Callable = oas_loaders.from_uri,
|
170
|
-
base_url: str | None = None,
|
171
|
-
endpoint: Filter | None = None,
|
172
|
-
method: Filter | None = None,
|
173
|
-
tag: Filter | None = None,
|
174
|
-
operation_id: Filter | None = None,
|
175
|
-
app: str | None = None,
|
176
|
-
validate_schema: bool = True,
|
177
|
-
skip_deprecated_operations: bool = False,
|
178
|
-
force_schema_version: str | None = None,
|
179
|
-
checks: Iterable[CheckFunction],
|
180
|
-
data_generation_methods: tuple[DataGenerationMethod, ...] = DEFAULT_DATA_GENERATION_METHODS,
|
181
|
-
max_response_time: int | None = None,
|
182
|
-
targets: Iterable[Target],
|
183
|
-
workers_num: int = 1,
|
184
|
-
hypothesis_settings: hypothesis.settings,
|
185
|
-
auth: RawAuth | None = None,
|
186
|
-
auth_type: str | None = None,
|
187
|
-
override: CaseOverride | None = None,
|
188
|
-
headers: dict[str, Any] | None = None,
|
189
|
-
request_timeout: int | None = None,
|
190
|
-
request_tls_verify: bool | str = True,
|
191
|
-
request_cert: RequestCert | None = None,
|
192
|
-
seed: int | None = None,
|
193
|
-
exit_first: bool = False,
|
194
|
-
dry_run: bool = False,
|
195
|
-
store_interactions: bool = False,
|
196
|
-
stateful: Stateful | None = None,
|
197
|
-
stateful_recursion_limit: int = DEFAULT_STATEFUL_RECURSION_LIMIT,
|
198
|
-
count_operations: bool = True,
|
199
|
-
count_links: bool = True,
|
200
|
-
probe_config: ProbeConfig | None = None,
|
201
|
-
service_client: ServiceClient | None,
|
202
|
-
) -> Generator[events.ExecutionEvent, None, None]:
|
203
|
-
"""Execute tests for the given schema.
|
204
|
-
|
205
|
-
Provides the main testing loop and preparation step.
|
206
|
-
"""
|
207
|
-
try:
|
208
|
-
if app is not None:
|
209
|
-
app = load_app(app)
|
210
|
-
schema = load_schema(
|
211
|
-
schema_uri,
|
212
|
-
base_url=base_url,
|
213
|
-
loader=loader,
|
214
|
-
app=app,
|
215
|
-
validate_schema=validate_schema,
|
216
|
-
skip_deprecated_operations=skip_deprecated_operations,
|
217
|
-
auth=auth,
|
218
|
-
auth_type=auth_type,
|
219
|
-
headers=headers,
|
220
|
-
endpoint=endpoint,
|
221
|
-
method=method,
|
222
|
-
tag=tag,
|
223
|
-
operation_id=operation_id,
|
224
|
-
data_generation_methods=data_generation_methods,
|
225
|
-
force_schema_version=force_schema_version,
|
226
|
-
request_tls_verify=request_tls_verify,
|
227
|
-
request_cert=request_cert,
|
228
|
-
)
|
229
|
-
yield from from_schema(
|
230
|
-
schema,
|
231
|
-
checks=checks,
|
232
|
-
max_response_time=max_response_time,
|
233
|
-
targets=targets,
|
234
|
-
hypothesis_settings=hypothesis_settings,
|
235
|
-
auth=auth,
|
236
|
-
auth_type=auth_type,
|
237
|
-
override=override,
|
238
|
-
headers=headers,
|
239
|
-
seed=seed,
|
240
|
-
workers_num=workers_num,
|
241
|
-
request_timeout=request_timeout,
|
242
|
-
request_tls_verify=request_tls_verify,
|
243
|
-
request_cert=request_cert,
|
244
|
-
exit_first=exit_first,
|
245
|
-
dry_run=dry_run,
|
246
|
-
store_interactions=store_interactions,
|
247
|
-
stateful=stateful,
|
248
|
-
stateful_recursion_limit=stateful_recursion_limit,
|
249
|
-
count_operations=count_operations,
|
250
|
-
count_links=count_links,
|
251
|
-
probe_config=probe_config,
|
252
|
-
service_client=service_client,
|
253
|
-
).execute()
|
254
|
-
except SchemaError as error:
|
255
|
-
yield events.InternalError.from_schema_error(error)
|
256
|
-
except Exception as exc:
|
257
|
-
yield events.InternalError.from_exc(exc)
|
258
|
-
|
259
|
-
|
260
|
-
def load_schema(
|
261
|
-
schema_uri: str | dict[str, Any],
|
262
|
-
*,
|
263
|
-
base_url: str | None = None,
|
264
|
-
loader: Callable = oas_loaders.from_uri,
|
265
|
-
app: Any = None,
|
266
|
-
validate_schema: bool = True,
|
267
|
-
skip_deprecated_operations: bool = False,
|
268
|
-
data_generation_methods: tuple[DataGenerationMethod, ...] = DEFAULT_DATA_GENERATION_METHODS,
|
269
|
-
force_schema_version: str | None = None,
|
270
|
-
request_tls_verify: bool | str = True,
|
271
|
-
request_cert: RequestCert | None = None,
|
272
|
-
# Network request parameters
|
273
|
-
auth: tuple[str, str] | None = None,
|
274
|
-
auth_type: str | None = None,
|
275
|
-
headers: dict[str, str] | None = None,
|
276
|
-
# Schema filters
|
277
|
-
endpoint: Filter | None = None,
|
278
|
-
method: Filter | None = None,
|
279
|
-
tag: Filter | None = None,
|
280
|
-
operation_id: Filter | None = None,
|
281
|
-
) -> BaseSchema:
|
282
|
-
"""Load schema via specified loader and parameters."""
|
283
|
-
loader_options: dict[str, Any] = {
|
284
|
-
key: value
|
285
|
-
for key, value in (
|
286
|
-
("base_url", base_url),
|
287
|
-
("endpoint", endpoint),
|
288
|
-
("method", method),
|
289
|
-
("tag", tag),
|
290
|
-
("operation_id", operation_id),
|
291
|
-
("app", app),
|
292
|
-
("data_generation_methods", data_generation_methods),
|
293
|
-
)
|
294
|
-
if value
|
295
|
-
}
|
296
|
-
|
297
|
-
if not isinstance(schema_uri, dict):
|
298
|
-
if file_exists(schema_uri):
|
299
|
-
loader = oas_loaders.from_path
|
300
|
-
elif loader is not oas_loaders.from_path:
|
301
|
-
if app is not None and not urlparse(schema_uri).netloc:
|
302
|
-
# If `schema` is not an existing filesystem path, or a URL then it is considered as a path within
|
303
|
-
# the given app
|
304
|
-
loader = oas_loaders.get_loader_for_app(app)
|
305
|
-
if headers:
|
306
|
-
loader_options["headers"] = headers
|
307
|
-
else:
|
308
|
-
if headers:
|
309
|
-
loader_options["headers"] = headers
|
310
|
-
if auth:
|
311
|
-
loader_options["auth"] = auth
|
312
|
-
if auth_type:
|
313
|
-
loader_options["auth_type"] = auth_type
|
314
|
-
|
315
|
-
if loader is oas_loaders.from_uri and loader_options.get("auth"):
|
316
|
-
loader_options["auth"] = get_requests_auth(loader_options["auth"], loader_options.pop("auth_type", None))
|
317
|
-
if loader in (oas_loaders.from_uri, oas_loaders.from_aiohttp):
|
318
|
-
loader_options["verify"] = request_tls_verify
|
319
|
-
loader_options["cert"] = request_cert
|
320
|
-
|
321
|
-
return loader(
|
322
|
-
schema_uri,
|
323
|
-
validate_schema=validate_schema,
|
324
|
-
skip_deprecated_operations=skip_deprecated_operations,
|
325
|
-
force_schema_version=force_schema_version,
|
326
|
-
**loader_options,
|
327
|
-
)
|
328
|
-
|
329
|
-
|
330
|
-
def from_schema(
|
331
|
-
schema: BaseSchema,
|
332
|
-
*,
|
333
|
-
override: CaseOverride | None = None,
|
334
|
-
checks: Iterable[CheckFunction] | None = None,
|
335
|
-
max_response_time: int | None = None,
|
336
|
-
targets: Iterable[Target] = DEFAULT_TARGETS,
|
337
|
-
workers_num: int = 1,
|
338
|
-
hypothesis_settings: hypothesis.settings | None = None,
|
339
|
-
generation_config: GenerationConfig | None = None,
|
340
|
-
auth: RawAuth | None = None,
|
341
|
-
auth_type: str | None = None,
|
342
|
-
headers: dict[str, Any] | None = None,
|
343
|
-
request_timeout: int | None = None,
|
344
|
-
request_tls_verify: bool | str = True,
|
345
|
-
request_proxy: str | None = None,
|
346
|
-
request_cert: RequestCert | None = None,
|
347
|
-
seed: int | None = None,
|
348
|
-
exit_first: bool = False,
|
349
|
-
no_failfast: bool = False,
|
350
|
-
max_failures: int | None = None,
|
351
|
-
started_at: str | None = None,
|
352
|
-
unique_data: bool = False,
|
353
|
-
dry_run: bool = False,
|
354
|
-
store_interactions: bool = False,
|
355
|
-
stateful: Stateful | None = None,
|
356
|
-
stateful_recursion_limit: int = DEFAULT_STATEFUL_RECURSION_LIMIT,
|
357
|
-
count_operations: bool = True,
|
358
|
-
count_links: bool = True,
|
359
|
-
probe_config: ProbeConfig | None = None,
|
360
|
-
checks_config: CheckConfig | None = None,
|
361
|
-
service_client: ServiceClient | None = None,
|
362
|
-
) -> BaseRunner:
|
363
|
-
import hypothesis
|
364
|
-
|
365
|
-
from ..checks import DEFAULT_CHECKS
|
366
|
-
from ..transports.asgi import is_asgi_app
|
367
|
-
from .impl import (
|
368
|
-
SingleThreadASGIRunner,
|
369
|
-
SingleThreadRunner,
|
370
|
-
SingleThreadWSGIRunner,
|
371
|
-
ThreadPoolASGIRunner,
|
372
|
-
ThreadPoolRunner,
|
373
|
-
ThreadPoolWSGIRunner,
|
374
|
-
)
|
375
|
-
|
376
|
-
checks = checks or DEFAULT_CHECKS
|
377
|
-
checks_config = checks_config or CheckConfig()
|
378
|
-
probe_config = probe_config or ProbeConfig()
|
379
|
-
|
380
|
-
hypothesis_settings = hypothesis_settings or hypothesis.settings(deadline=DEFAULT_DEADLINE)
|
381
|
-
request_config = RequestConfig(
|
382
|
-
timeout=request_timeout,
|
383
|
-
tls_verify=request_tls_verify,
|
384
|
-
proxy=request_proxy,
|
385
|
-
cert=request_cert,
|
386
|
-
)
|
387
|
-
|
388
|
-
# Use the same seed for all tests unless `derandomize=True` is used
|
389
|
-
if seed is None and not hypothesis_settings.derandomize:
|
390
|
-
seed = Random().getrandbits(128)
|
391
|
-
|
392
|
-
started_at = started_at or current_datetime()
|
393
|
-
if workers_num > 1:
|
394
|
-
if not schema.app:
|
395
|
-
return ThreadPoolRunner(
|
396
|
-
schema=schema,
|
397
|
-
checks=checks,
|
398
|
-
max_response_time=max_response_time,
|
399
|
-
targets=targets,
|
400
|
-
hypothesis_settings=hypothesis_settings,
|
401
|
-
generation_config=generation_config,
|
402
|
-
auth=auth,
|
403
|
-
auth_type=auth_type,
|
404
|
-
override=override,
|
405
|
-
headers=headers,
|
406
|
-
seed=seed,
|
407
|
-
workers_num=workers_num,
|
408
|
-
request_config=request_config,
|
409
|
-
exit_first=exit_first,
|
410
|
-
no_failfast=no_failfast,
|
411
|
-
max_failures=max_failures,
|
412
|
-
started_at=started_at,
|
413
|
-
unique_data=unique_data,
|
414
|
-
dry_run=dry_run,
|
415
|
-
store_interactions=store_interactions,
|
416
|
-
stateful=stateful,
|
417
|
-
stateful_recursion_limit=stateful_recursion_limit,
|
418
|
-
count_operations=count_operations,
|
419
|
-
count_links=count_links,
|
420
|
-
probe_config=probe_config,
|
421
|
-
checks_config=checks_config,
|
422
|
-
service_client=service_client,
|
423
|
-
)
|
424
|
-
if is_asgi_app(schema.app):
|
425
|
-
return ThreadPoolASGIRunner(
|
426
|
-
schema=schema,
|
427
|
-
checks=checks,
|
428
|
-
max_response_time=max_response_time,
|
429
|
-
targets=targets,
|
430
|
-
hypothesis_settings=hypothesis_settings,
|
431
|
-
generation_config=generation_config,
|
432
|
-
auth=auth,
|
433
|
-
auth_type=auth_type,
|
434
|
-
override=override,
|
435
|
-
headers=headers,
|
436
|
-
seed=seed,
|
437
|
-
exit_first=exit_first,
|
438
|
-
no_failfast=no_failfast,
|
439
|
-
max_failures=max_failures,
|
440
|
-
started_at=started_at,
|
441
|
-
unique_data=unique_data,
|
442
|
-
dry_run=dry_run,
|
443
|
-
store_interactions=store_interactions,
|
444
|
-
stateful=stateful,
|
445
|
-
stateful_recursion_limit=stateful_recursion_limit,
|
446
|
-
count_operations=count_operations,
|
447
|
-
count_links=count_links,
|
448
|
-
probe_config=probe_config,
|
449
|
-
checks_config=checks_config,
|
450
|
-
service_client=service_client,
|
451
|
-
)
|
452
|
-
return ThreadPoolWSGIRunner(
|
453
|
-
schema=schema,
|
454
|
-
checks=checks,
|
455
|
-
max_response_time=max_response_time,
|
456
|
-
targets=targets,
|
457
|
-
hypothesis_settings=hypothesis_settings,
|
458
|
-
generation_config=generation_config,
|
459
|
-
auth=auth,
|
460
|
-
auth_type=auth_type,
|
461
|
-
override=override,
|
462
|
-
headers=headers,
|
463
|
-
seed=seed,
|
464
|
-
workers_num=workers_num,
|
465
|
-
exit_first=exit_first,
|
466
|
-
no_failfast=no_failfast,
|
467
|
-
max_failures=max_failures,
|
468
|
-
started_at=started_at,
|
469
|
-
unique_data=unique_data,
|
470
|
-
dry_run=dry_run,
|
471
|
-
store_interactions=store_interactions,
|
472
|
-
stateful=stateful,
|
473
|
-
stateful_recursion_limit=stateful_recursion_limit,
|
474
|
-
count_operations=count_operations,
|
475
|
-
count_links=count_links,
|
476
|
-
probe_config=probe_config,
|
477
|
-
checks_config=checks_config,
|
478
|
-
service_client=service_client,
|
479
|
-
)
|
480
|
-
if not schema.app:
|
481
|
-
return SingleThreadRunner(
|
482
|
-
schema=schema,
|
483
|
-
checks=checks,
|
484
|
-
max_response_time=max_response_time,
|
485
|
-
targets=targets,
|
486
|
-
hypothesis_settings=hypothesis_settings,
|
487
|
-
generation_config=generation_config,
|
488
|
-
auth=auth,
|
489
|
-
auth_type=auth_type,
|
490
|
-
override=override,
|
491
|
-
headers=headers,
|
492
|
-
seed=seed,
|
493
|
-
request_config=request_config,
|
494
|
-
exit_first=exit_first,
|
495
|
-
no_failfast=no_failfast,
|
496
|
-
max_failures=max_failures,
|
497
|
-
started_at=started_at,
|
498
|
-
unique_data=unique_data,
|
499
|
-
dry_run=dry_run,
|
500
|
-
store_interactions=store_interactions,
|
501
|
-
stateful=stateful,
|
502
|
-
stateful_recursion_limit=stateful_recursion_limit,
|
503
|
-
count_operations=count_operations,
|
504
|
-
count_links=count_links,
|
505
|
-
probe_config=probe_config,
|
506
|
-
checks_config=checks_config,
|
507
|
-
service_client=service_client,
|
508
|
-
)
|
509
|
-
if is_asgi_app(schema.app):
|
510
|
-
return SingleThreadASGIRunner(
|
511
|
-
schema=schema,
|
512
|
-
checks=checks,
|
513
|
-
max_response_time=max_response_time,
|
514
|
-
targets=targets,
|
515
|
-
hypothesis_settings=hypothesis_settings,
|
516
|
-
generation_config=generation_config,
|
517
|
-
auth=auth,
|
518
|
-
auth_type=auth_type,
|
519
|
-
override=override,
|
520
|
-
headers=headers,
|
521
|
-
seed=seed,
|
522
|
-
exit_first=exit_first,
|
523
|
-
no_failfast=no_failfast,
|
524
|
-
max_failures=max_failures,
|
525
|
-
started_at=started_at,
|
526
|
-
unique_data=unique_data,
|
527
|
-
dry_run=dry_run,
|
528
|
-
store_interactions=store_interactions,
|
529
|
-
stateful=stateful,
|
530
|
-
stateful_recursion_limit=stateful_recursion_limit,
|
531
|
-
count_operations=count_operations,
|
532
|
-
count_links=count_links,
|
533
|
-
probe_config=probe_config,
|
534
|
-
checks_config=checks_config,
|
535
|
-
service_client=service_client,
|
536
|
-
)
|
537
|
-
return SingleThreadWSGIRunner(
|
538
|
-
schema=schema,
|
539
|
-
checks=checks,
|
540
|
-
max_response_time=max_response_time,
|
541
|
-
targets=targets,
|
542
|
-
hypothesis_settings=hypothesis_settings,
|
543
|
-
generation_config=generation_config,
|
544
|
-
auth=auth,
|
545
|
-
auth_type=auth_type,
|
546
|
-
override=override,
|
547
|
-
headers=headers,
|
548
|
-
seed=seed,
|
549
|
-
exit_first=exit_first,
|
550
|
-
no_failfast=no_failfast,
|
551
|
-
max_failures=max_failures,
|
552
|
-
started_at=started_at,
|
553
|
-
unique_data=unique_data,
|
554
|
-
dry_run=dry_run,
|
555
|
-
store_interactions=store_interactions,
|
556
|
-
stateful=stateful,
|
557
|
-
stateful_recursion_limit=stateful_recursion_limit,
|
558
|
-
count_operations=count_operations,
|
559
|
-
count_links=count_links,
|
560
|
-
probe_config=probe_config,
|
561
|
-
checks_config=checks_config,
|
562
|
-
service_client=service_client,
|
563
|
-
)
|
564
|
-
|
565
|
-
|
566
|
-
def prepare_hypothesis_settings(
|
567
|
-
database: str | None = None,
|
568
|
-
deadline: int | NotSet | None = None,
|
569
|
-
derandomize: bool | None = None,
|
570
|
-
max_examples: int | None = None,
|
571
|
-
phases: list[hypothesis.Phase] | None = None,
|
572
|
-
report_multiple_bugs: bool | None = None,
|
573
|
-
suppress_health_check: list[hypothesis.HealthCheck] | None = None,
|
574
|
-
verbosity: hypothesis.Verbosity | None = None,
|
575
|
-
) -> hypothesis.settings:
|
576
|
-
import hypothesis
|
577
|
-
from hypothesis.database import DirectoryBasedExampleDatabase, InMemoryExampleDatabase
|
578
|
-
|
579
|
-
kwargs = {
|
580
|
-
key: value
|
581
|
-
for key, value in (
|
582
|
-
("derandomize", derandomize),
|
583
|
-
("max_examples", max_examples),
|
584
|
-
("phases", phases),
|
585
|
-
("report_multiple_bugs", report_multiple_bugs),
|
586
|
-
("suppress_health_check", suppress_health_check),
|
587
|
-
("verbosity", verbosity),
|
588
|
-
)
|
589
|
-
if value is not None
|
590
|
-
}
|
591
|
-
# `deadline` is special, since Hypothesis allows passing `None`
|
592
|
-
if deadline is not None:
|
593
|
-
if isinstance(deadline, NotSet):
|
594
|
-
kwargs["deadline"] = None
|
595
|
-
else:
|
596
|
-
kwargs["deadline"] = deadline
|
597
|
-
if database is not None:
|
598
|
-
if database.lower() == "none":
|
599
|
-
kwargs["database"] = None
|
600
|
-
elif database == HYPOTHESIS_IN_MEMORY_DATABASE_IDENTIFIER:
|
601
|
-
kwargs["database"] = InMemoryExampleDatabase()
|
602
|
-
else:
|
603
|
-
kwargs["database"] = DirectoryBasedExampleDatabase(database)
|
604
|
-
kwargs.setdefault("deadline", DEFAULT_DEADLINE)
|
605
|
-
return hypothesis.settings(print_blob=False, **kwargs)
|