schemathesis 3.13.0__py3-none-any.whl → 4.4.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (245) hide show
  1. schemathesis/__init__.py +53 -25
  2. schemathesis/auths.py +507 -0
  3. schemathesis/checks.py +190 -25
  4. schemathesis/cli/__init__.py +27 -1016
  5. schemathesis/cli/__main__.py +4 -0
  6. schemathesis/cli/commands/__init__.py +133 -0
  7. schemathesis/cli/commands/data.py +10 -0
  8. schemathesis/cli/commands/run/__init__.py +602 -0
  9. schemathesis/cli/commands/run/context.py +228 -0
  10. schemathesis/cli/commands/run/events.py +60 -0
  11. schemathesis/cli/commands/run/executor.py +157 -0
  12. schemathesis/cli/commands/run/filters.py +53 -0
  13. schemathesis/cli/commands/run/handlers/__init__.py +46 -0
  14. schemathesis/cli/commands/run/handlers/base.py +45 -0
  15. schemathesis/cli/commands/run/handlers/cassettes.py +464 -0
  16. schemathesis/cli/commands/run/handlers/junitxml.py +60 -0
  17. schemathesis/cli/commands/run/handlers/output.py +1750 -0
  18. schemathesis/cli/commands/run/loaders.py +118 -0
  19. schemathesis/cli/commands/run/validation.py +256 -0
  20. schemathesis/cli/constants.py +5 -0
  21. schemathesis/cli/core.py +19 -0
  22. schemathesis/cli/ext/fs.py +16 -0
  23. schemathesis/cli/ext/groups.py +203 -0
  24. schemathesis/cli/ext/options.py +81 -0
  25. schemathesis/config/__init__.py +202 -0
  26. schemathesis/config/_auth.py +51 -0
  27. schemathesis/config/_checks.py +268 -0
  28. schemathesis/config/_diff_base.py +101 -0
  29. schemathesis/config/_env.py +21 -0
  30. schemathesis/config/_error.py +163 -0
  31. schemathesis/config/_generation.py +157 -0
  32. schemathesis/config/_health_check.py +24 -0
  33. schemathesis/config/_operations.py +335 -0
  34. schemathesis/config/_output.py +171 -0
  35. schemathesis/config/_parameters.py +19 -0
  36. schemathesis/config/_phases.py +253 -0
  37. schemathesis/config/_projects.py +543 -0
  38. schemathesis/config/_rate_limit.py +17 -0
  39. schemathesis/config/_report.py +120 -0
  40. schemathesis/config/_validator.py +9 -0
  41. schemathesis/config/_warnings.py +89 -0
  42. schemathesis/config/schema.json +975 -0
  43. schemathesis/core/__init__.py +72 -0
  44. schemathesis/core/adapter.py +34 -0
  45. schemathesis/core/compat.py +32 -0
  46. schemathesis/core/control.py +2 -0
  47. schemathesis/core/curl.py +100 -0
  48. schemathesis/core/deserialization.py +210 -0
  49. schemathesis/core/errors.py +588 -0
  50. schemathesis/core/failures.py +316 -0
  51. schemathesis/core/fs.py +19 -0
  52. schemathesis/core/hooks.py +20 -0
  53. schemathesis/core/jsonschema/__init__.py +13 -0
  54. schemathesis/core/jsonschema/bundler.py +183 -0
  55. schemathesis/core/jsonschema/keywords.py +40 -0
  56. schemathesis/core/jsonschema/references.py +222 -0
  57. schemathesis/core/jsonschema/types.py +41 -0
  58. schemathesis/core/lazy_import.py +15 -0
  59. schemathesis/core/loaders.py +107 -0
  60. schemathesis/core/marks.py +66 -0
  61. schemathesis/core/media_types.py +79 -0
  62. schemathesis/core/output/__init__.py +46 -0
  63. schemathesis/core/output/sanitization.py +54 -0
  64. schemathesis/core/parameters.py +45 -0
  65. schemathesis/core/rate_limit.py +60 -0
  66. schemathesis/core/registries.py +34 -0
  67. schemathesis/core/result.py +27 -0
  68. schemathesis/core/schema_analysis.py +17 -0
  69. schemathesis/core/shell.py +203 -0
  70. schemathesis/core/transforms.py +144 -0
  71. schemathesis/core/transport.py +223 -0
  72. schemathesis/core/validation.py +73 -0
  73. schemathesis/core/version.py +7 -0
  74. schemathesis/engine/__init__.py +28 -0
  75. schemathesis/engine/context.py +152 -0
  76. schemathesis/engine/control.py +44 -0
  77. schemathesis/engine/core.py +201 -0
  78. schemathesis/engine/errors.py +446 -0
  79. schemathesis/engine/events.py +284 -0
  80. schemathesis/engine/observations.py +42 -0
  81. schemathesis/engine/phases/__init__.py +108 -0
  82. schemathesis/engine/phases/analysis.py +28 -0
  83. schemathesis/engine/phases/probes.py +172 -0
  84. schemathesis/engine/phases/stateful/__init__.py +68 -0
  85. schemathesis/engine/phases/stateful/_executor.py +364 -0
  86. schemathesis/engine/phases/stateful/context.py +85 -0
  87. schemathesis/engine/phases/unit/__init__.py +220 -0
  88. schemathesis/engine/phases/unit/_executor.py +459 -0
  89. schemathesis/engine/phases/unit/_pool.py +82 -0
  90. schemathesis/engine/recorder.py +254 -0
  91. schemathesis/errors.py +47 -0
  92. schemathesis/filters.py +395 -0
  93. schemathesis/generation/__init__.py +25 -0
  94. schemathesis/generation/case.py +478 -0
  95. schemathesis/generation/coverage.py +1528 -0
  96. schemathesis/generation/hypothesis/__init__.py +121 -0
  97. schemathesis/generation/hypothesis/builder.py +992 -0
  98. schemathesis/generation/hypothesis/examples.py +56 -0
  99. schemathesis/generation/hypothesis/given.py +66 -0
  100. schemathesis/generation/hypothesis/reporting.py +285 -0
  101. schemathesis/generation/meta.py +227 -0
  102. schemathesis/generation/metrics.py +93 -0
  103. schemathesis/generation/modes.py +20 -0
  104. schemathesis/generation/overrides.py +127 -0
  105. schemathesis/generation/stateful/__init__.py +37 -0
  106. schemathesis/generation/stateful/state_machine.py +294 -0
  107. schemathesis/graphql/__init__.py +15 -0
  108. schemathesis/graphql/checks.py +109 -0
  109. schemathesis/graphql/loaders.py +285 -0
  110. schemathesis/hooks.py +270 -91
  111. schemathesis/openapi/__init__.py +13 -0
  112. schemathesis/openapi/checks.py +467 -0
  113. schemathesis/openapi/generation/__init__.py +0 -0
  114. schemathesis/openapi/generation/filters.py +72 -0
  115. schemathesis/openapi/loaders.py +315 -0
  116. schemathesis/pytest/__init__.py +5 -0
  117. schemathesis/pytest/control_flow.py +7 -0
  118. schemathesis/pytest/lazy.py +341 -0
  119. schemathesis/pytest/loaders.py +36 -0
  120. schemathesis/pytest/plugin.py +357 -0
  121. schemathesis/python/__init__.py +0 -0
  122. schemathesis/python/asgi.py +12 -0
  123. schemathesis/python/wsgi.py +12 -0
  124. schemathesis/schemas.py +683 -247
  125. schemathesis/specs/graphql/__init__.py +0 -1
  126. schemathesis/specs/graphql/nodes.py +27 -0
  127. schemathesis/specs/graphql/scalars.py +86 -0
  128. schemathesis/specs/graphql/schemas.py +395 -123
  129. schemathesis/specs/graphql/validation.py +33 -0
  130. schemathesis/specs/openapi/__init__.py +9 -1
  131. schemathesis/specs/openapi/_hypothesis.py +578 -317
  132. schemathesis/specs/openapi/adapter/__init__.py +10 -0
  133. schemathesis/specs/openapi/adapter/parameters.py +729 -0
  134. schemathesis/specs/openapi/adapter/protocol.py +59 -0
  135. schemathesis/specs/openapi/adapter/references.py +19 -0
  136. schemathesis/specs/openapi/adapter/responses.py +368 -0
  137. schemathesis/specs/openapi/adapter/security.py +144 -0
  138. schemathesis/specs/openapi/adapter/v2.py +30 -0
  139. schemathesis/specs/openapi/adapter/v3_0.py +30 -0
  140. schemathesis/specs/openapi/adapter/v3_1.py +30 -0
  141. schemathesis/specs/openapi/analysis.py +96 -0
  142. schemathesis/specs/openapi/checks.py +753 -74
  143. schemathesis/specs/openapi/converter.py +176 -37
  144. schemathesis/specs/openapi/definitions.py +599 -4
  145. schemathesis/specs/openapi/examples.py +581 -165
  146. schemathesis/specs/openapi/expressions/__init__.py +52 -5
  147. schemathesis/specs/openapi/expressions/extractors.py +25 -0
  148. schemathesis/specs/openapi/expressions/lexer.py +34 -31
  149. schemathesis/specs/openapi/expressions/nodes.py +97 -46
  150. schemathesis/specs/openapi/expressions/parser.py +35 -13
  151. schemathesis/specs/openapi/formats.py +122 -0
  152. schemathesis/specs/openapi/media_types.py +75 -0
  153. schemathesis/specs/openapi/negative/__init__.py +117 -68
  154. schemathesis/specs/openapi/negative/mutations.py +294 -104
  155. schemathesis/specs/openapi/negative/utils.py +3 -6
  156. schemathesis/specs/openapi/patterns.py +458 -0
  157. schemathesis/specs/openapi/references.py +60 -81
  158. schemathesis/specs/openapi/schemas.py +648 -650
  159. schemathesis/specs/openapi/serialization.py +53 -30
  160. schemathesis/specs/openapi/stateful/__init__.py +404 -69
  161. schemathesis/specs/openapi/stateful/control.py +87 -0
  162. schemathesis/specs/openapi/stateful/dependencies/__init__.py +232 -0
  163. schemathesis/specs/openapi/stateful/dependencies/inputs.py +428 -0
  164. schemathesis/specs/openapi/stateful/dependencies/models.py +341 -0
  165. schemathesis/specs/openapi/stateful/dependencies/naming.py +491 -0
  166. schemathesis/specs/openapi/stateful/dependencies/outputs.py +34 -0
  167. schemathesis/specs/openapi/stateful/dependencies/resources.py +339 -0
  168. schemathesis/specs/openapi/stateful/dependencies/schemas.py +447 -0
  169. schemathesis/specs/openapi/stateful/inference.py +254 -0
  170. schemathesis/specs/openapi/stateful/links.py +219 -78
  171. schemathesis/specs/openapi/types/__init__.py +3 -0
  172. schemathesis/specs/openapi/types/common.py +23 -0
  173. schemathesis/specs/openapi/types/v2.py +129 -0
  174. schemathesis/specs/openapi/types/v3.py +134 -0
  175. schemathesis/specs/openapi/utils.py +7 -6
  176. schemathesis/specs/openapi/warnings.py +75 -0
  177. schemathesis/transport/__init__.py +224 -0
  178. schemathesis/transport/asgi.py +26 -0
  179. schemathesis/transport/prepare.py +126 -0
  180. schemathesis/transport/requests.py +278 -0
  181. schemathesis/transport/serialization.py +329 -0
  182. schemathesis/transport/wsgi.py +175 -0
  183. schemathesis-4.4.2.dist-info/METADATA +213 -0
  184. schemathesis-4.4.2.dist-info/RECORD +192 -0
  185. {schemathesis-3.13.0.dist-info → schemathesis-4.4.2.dist-info}/WHEEL +1 -1
  186. schemathesis-4.4.2.dist-info/entry_points.txt +6 -0
  187. {schemathesis-3.13.0.dist-info → schemathesis-4.4.2.dist-info/licenses}/LICENSE +1 -1
  188. schemathesis/_compat.py +0 -41
  189. schemathesis/_hypothesis.py +0 -115
  190. schemathesis/cli/callbacks.py +0 -188
  191. schemathesis/cli/cassettes.py +0 -253
  192. schemathesis/cli/context.py +0 -36
  193. schemathesis/cli/debug.py +0 -21
  194. schemathesis/cli/handlers.py +0 -11
  195. schemathesis/cli/junitxml.py +0 -41
  196. schemathesis/cli/options.py +0 -51
  197. schemathesis/cli/output/__init__.py +0 -1
  198. schemathesis/cli/output/default.py +0 -508
  199. schemathesis/cli/output/short.py +0 -40
  200. schemathesis/constants.py +0 -79
  201. schemathesis/exceptions.py +0 -207
  202. schemathesis/extra/_aiohttp.py +0 -27
  203. schemathesis/extra/_flask.py +0 -10
  204. schemathesis/extra/_server.py +0 -16
  205. schemathesis/extra/pytest_plugin.py +0 -216
  206. schemathesis/failures.py +0 -131
  207. schemathesis/fixups/__init__.py +0 -29
  208. schemathesis/fixups/fast_api.py +0 -30
  209. schemathesis/lazy.py +0 -227
  210. schemathesis/models.py +0 -1041
  211. schemathesis/parameters.py +0 -88
  212. schemathesis/runner/__init__.py +0 -460
  213. schemathesis/runner/events.py +0 -240
  214. schemathesis/runner/impl/__init__.py +0 -3
  215. schemathesis/runner/impl/core.py +0 -755
  216. schemathesis/runner/impl/solo.py +0 -85
  217. schemathesis/runner/impl/threadpool.py +0 -367
  218. schemathesis/runner/serialization.py +0 -189
  219. schemathesis/serializers.py +0 -233
  220. schemathesis/service/__init__.py +0 -3
  221. schemathesis/service/client.py +0 -46
  222. schemathesis/service/constants.py +0 -12
  223. schemathesis/service/events.py +0 -39
  224. schemathesis/service/handler.py +0 -39
  225. schemathesis/service/models.py +0 -7
  226. schemathesis/service/serialization.py +0 -153
  227. schemathesis/service/worker.py +0 -40
  228. schemathesis/specs/graphql/loaders.py +0 -215
  229. schemathesis/specs/openapi/constants.py +0 -7
  230. schemathesis/specs/openapi/expressions/context.py +0 -12
  231. schemathesis/specs/openapi/expressions/pointers.py +0 -29
  232. schemathesis/specs/openapi/filters.py +0 -44
  233. schemathesis/specs/openapi/links.py +0 -302
  234. schemathesis/specs/openapi/loaders.py +0 -453
  235. schemathesis/specs/openapi/parameters.py +0 -413
  236. schemathesis/specs/openapi/security.py +0 -129
  237. schemathesis/specs/openapi/validation.py +0 -24
  238. schemathesis/stateful.py +0 -349
  239. schemathesis/targets.py +0 -32
  240. schemathesis/types.py +0 -38
  241. schemathesis/utils.py +0 -436
  242. schemathesis-3.13.0.dist-info/METADATA +0 -202
  243. schemathesis-3.13.0.dist-info/RECORD +0 -91
  244. schemathesis-3.13.0.dist-info/entry_points.txt +0 -6
  245. /schemathesis/{extra → cli/ext}/__init__.py +0 -0
@@ -1,88 +0,0 @@
1
- """API operation parameters.
2
-
3
- These are basic entities that describe what data could be sent to the API.
4
- """
5
- from typing import Any, Dict, Generator, Generic, List, TypeVar
6
-
7
- import attr
8
-
9
-
10
- @attr.s(slots=True, eq=False) # pragma: no mutate
11
- class Parameter:
12
- """A logically separate parameter bound to a location (e.g., to "query string").
13
-
14
- For example, if the API requires multiple headers to be present, each header is presented as a separate
15
- `Parameter` instance.
16
- """
17
-
18
- # The parameter definition in the language acceptable by the API
19
- definition: Any = attr.ib() # pragma: no mutate
20
-
21
- @property
22
- def location(self) -> str:
23
- """Where this parameter is located.
24
-
25
- E.g. "query" or "body"
26
- """
27
- raise NotImplementedError
28
-
29
- @property
30
- def name(self) -> str:
31
- """Parameter name."""
32
- raise NotImplementedError
33
-
34
- @property
35
- def is_required(self) -> bool:
36
- """Whether the parameter is required for a successful API call."""
37
- raise NotImplementedError
38
-
39
- @property
40
- def example(self) -> Any:
41
- """Parameter example."""
42
- raise NotImplementedError
43
-
44
- def serialize(self) -> str:
45
- """Get parameter's string representation."""
46
- raise NotImplementedError
47
-
48
-
49
- P = TypeVar("P", bound=Parameter)
50
-
51
-
52
- @attr.s # pragma: no mutate
53
- class ParameterSet(Generic[P]):
54
- """A set of parameters for the same location."""
55
-
56
- items: List[P] = attr.ib(factory=list) # pragma: no mutate
57
-
58
- def add(self, parameter: P) -> None:
59
- """Add a new parameter."""
60
- self.items.append(parameter)
61
-
62
- @property
63
- def example(self) -> Dict[str, Any]:
64
- """Composite example gathered from individual parameters."""
65
- return {item.name: item.example for item in self.items if item.example}
66
-
67
- def __bool__(self) -> bool:
68
- return bool(self.items)
69
-
70
- def __iter__(self) -> Generator[P, None, None]:
71
- yield from iter(self.items)
72
-
73
- def __len__(self) -> int:
74
- return len(self.items)
75
-
76
- def __getitem__(self, item: int) -> P:
77
- return self.items[item]
78
-
79
-
80
- class PayloadAlternatives(ParameterSet[P]):
81
- """A set of alternative payloads."""
82
-
83
- @property
84
- def example(self) -> Any:
85
- """We take only the first example."""
86
- # May be extended in the future
87
- if self.items:
88
- return self.items[0].example
@@ -1,460 +0,0 @@
1
- from typing import Any, Callable, Dict, Generator, Iterable, List, Optional, Tuple, Union
2
- from urllib.parse import urlparse
3
-
4
- import hypothesis.errors
5
- from starlette.applications import Starlette
6
-
7
- from ..checks import DEFAULT_CHECKS
8
- from ..constants import (
9
- DEFAULT_DATA_GENERATION_METHODS,
10
- DEFAULT_DEADLINE,
11
- DEFAULT_STATEFUL_RECURSION_LIMIT,
12
- DataGenerationMethod,
13
- )
14
- from ..models import CheckFunction
15
- from ..schemas import BaseSchema
16
- from ..specs.graphql import loaders as gql_loaders
17
- from ..specs.openapi import loaders as oas_loaders
18
- from ..stateful import Stateful
19
- from ..targets import DEFAULT_TARGETS, Target
20
- from ..types import Filter, NotSet, RawAuth, RequestCert
21
- from ..utils import deprecated, dict_not_none_values, dict_true_values, file_exists, get_requests_auth, import_app
22
- from . import events
23
- from .impl import (
24
- BaseRunner,
25
- SingleThreadASGIRunner,
26
- SingleThreadRunner,
27
- SingleThreadWSGIRunner,
28
- ThreadPoolASGIRunner,
29
- ThreadPoolRunner,
30
- ThreadPoolWSGIRunner,
31
- )
32
-
33
-
34
- @deprecated(removed_in="4.0", replacement="schemathesis.runner.from_schema")
35
- def prepare(
36
- schema_uri: Union[str, Dict[str, Any]],
37
- *,
38
- # Runtime behavior
39
- checks: Iterable[CheckFunction] = DEFAULT_CHECKS,
40
- data_generation_methods: Tuple[DataGenerationMethod, ...] = DEFAULT_DATA_GENERATION_METHODS,
41
- max_response_time: Optional[int] = None,
42
- targets: Iterable[Target] = DEFAULT_TARGETS,
43
- workers_num: int = 1,
44
- seed: Optional[int] = None,
45
- exit_first: bool = False,
46
- dry_run: bool = False,
47
- store_interactions: bool = False,
48
- stateful: Optional[Stateful] = None,
49
- stateful_recursion_limit: int = DEFAULT_STATEFUL_RECURSION_LIMIT,
50
- # Schema loading
51
- loader: Callable = oas_loaders.from_uri,
52
- base_url: Optional[str] = None,
53
- auth: Optional[Tuple[str, str]] = None,
54
- auth_type: Optional[str] = None,
55
- headers: Optional[Dict[str, str]] = None,
56
- request_timeout: Optional[int] = None,
57
- request_tls_verify: Union[bool, str] = True,
58
- request_cert: Optional[RequestCert] = None,
59
- endpoint: Optional[Filter] = None,
60
- method: Optional[Filter] = None,
61
- tag: Optional[Filter] = None,
62
- operation_id: Optional[Filter] = None,
63
- app: Optional[str] = None,
64
- validate_schema: bool = True,
65
- skip_deprecated_operations: bool = False,
66
- force_schema_version: Optional[str] = None,
67
- count_operations: bool = True,
68
- # Hypothesis-specific configuration
69
- hypothesis_deadline: Optional[Union[int, NotSet]] = None,
70
- hypothesis_derandomize: Optional[bool] = None,
71
- hypothesis_max_examples: Optional[int] = None,
72
- hypothesis_phases: Optional[List[hypothesis.Phase]] = None,
73
- hypothesis_report_multiple_bugs: Optional[bool] = None,
74
- hypothesis_suppress_health_check: Optional[List[hypothesis.HealthCheck]] = None,
75
- hypothesis_verbosity: Optional[hypothesis.Verbosity] = None,
76
- ) -> Generator[events.ExecutionEvent, None, None]:
77
- """Prepare a generator that will run test cases against the given API definition."""
78
- # pylint: disable=too-many-locals
79
-
80
- validate_loader(loader, schema_uri)
81
-
82
- if auth is None:
83
- # Auth type doesn't matter if auth is not passed
84
- auth_type = None # type: ignore
85
- hypothesis_settings = prepare_hypothesis_settings(
86
- deadline=hypothesis_deadline,
87
- derandomize=hypothesis_derandomize,
88
- max_examples=hypothesis_max_examples,
89
- phases=hypothesis_phases,
90
- report_multiple_bugs=hypothesis_report_multiple_bugs,
91
- suppress_health_check=hypothesis_suppress_health_check,
92
- verbosity=hypothesis_verbosity,
93
- )
94
- return execute_from_schema(
95
- schema_uri=schema_uri,
96
- loader=loader,
97
- base_url=base_url,
98
- endpoint=endpoint,
99
- method=method,
100
- tag=tag,
101
- operation_id=operation_id,
102
- app=app,
103
- validate_schema=validate_schema,
104
- skip_deprecated_operations=skip_deprecated_operations,
105
- force_schema_version=force_schema_version,
106
- checks=checks,
107
- data_generation_methods=data_generation_methods,
108
- max_response_time=max_response_time,
109
- targets=targets,
110
- hypothesis_settings=hypothesis_settings,
111
- seed=seed,
112
- workers_num=workers_num,
113
- exit_first=exit_first,
114
- dry_run=dry_run,
115
- auth=auth,
116
- auth_type=auth_type,
117
- headers=headers,
118
- request_timeout=request_timeout,
119
- request_tls_verify=request_tls_verify,
120
- request_cert=request_cert,
121
- store_interactions=store_interactions,
122
- stateful=stateful,
123
- stateful_recursion_limit=stateful_recursion_limit,
124
- count_operations=count_operations,
125
- )
126
-
127
-
128
- def validate_loader(loader: Callable, schema_uri: Union[str, Dict[str, Any]]) -> None:
129
- """Sanity checking for input schema & loader."""
130
- if loader not in (
131
- oas_loaders.from_uri,
132
- oas_loaders.from_aiohttp,
133
- oas_loaders.from_dict,
134
- oas_loaders.from_file,
135
- oas_loaders.from_path,
136
- oas_loaders.from_asgi,
137
- oas_loaders.from_wsgi,
138
- gql_loaders.from_dict,
139
- gql_loaders.from_url,
140
- gql_loaders.from_wsgi,
141
- ):
142
- # Custom loaders are not checked
143
- return
144
- if isinstance(schema_uri, dict):
145
- if loader not in (oas_loaders.from_dict, gql_loaders.from_dict):
146
- raise ValueError("Dictionary as a schema is allowed only with `from_dict` loader")
147
- elif loader in (oas_loaders.from_dict, gql_loaders.from_dict):
148
- raise ValueError("Schema should be a dictionary for `from_dict` loader")
149
-
150
-
151
- def execute_from_schema(
152
- *,
153
- schema_uri: Union[str, Dict[str, Any]],
154
- loader: Callable = oas_loaders.from_uri,
155
- base_url: Optional[str] = None,
156
- endpoint: Optional[Filter] = None,
157
- method: Optional[Filter] = None,
158
- tag: Optional[Filter] = None,
159
- operation_id: Optional[Filter] = None,
160
- app: Optional[str] = None,
161
- validate_schema: bool = True,
162
- skip_deprecated_operations: bool = False,
163
- force_schema_version: Optional[str] = None,
164
- checks: Iterable[CheckFunction],
165
- data_generation_methods: Tuple[DataGenerationMethod, ...] = DEFAULT_DATA_GENERATION_METHODS,
166
- max_response_time: Optional[int] = None,
167
- targets: Iterable[Target],
168
- workers_num: int = 1,
169
- hypothesis_settings: hypothesis.settings,
170
- auth: Optional[RawAuth] = None,
171
- auth_type: Optional[str] = None,
172
- headers: Optional[Dict[str, Any]] = None,
173
- request_timeout: Optional[int] = None,
174
- request_tls_verify: Union[bool, str] = True,
175
- request_cert: Optional[RequestCert] = None,
176
- seed: Optional[int] = None,
177
- exit_first: bool = False,
178
- dry_run: bool = False,
179
- store_interactions: bool = False,
180
- stateful: Optional[Stateful] = None,
181
- stateful_recursion_limit: int = DEFAULT_STATEFUL_RECURSION_LIMIT,
182
- count_operations: bool = True,
183
- ) -> Generator[events.ExecutionEvent, None, None]:
184
- """Execute tests for the given schema.
185
-
186
- Provides the main testing loop and preparation step.
187
- """
188
- # pylint: disable=too-many-locals
189
- try:
190
- if app is not None:
191
- app = import_app(app)
192
- schema = load_schema(
193
- schema_uri,
194
- base_url=base_url,
195
- loader=loader,
196
- app=app,
197
- validate_schema=validate_schema,
198
- skip_deprecated_operations=skip_deprecated_operations,
199
- auth=auth,
200
- auth_type=auth_type,
201
- headers=headers,
202
- endpoint=endpoint,
203
- method=method,
204
- tag=tag,
205
- operation_id=operation_id,
206
- data_generation_methods=data_generation_methods,
207
- force_schema_version=force_schema_version,
208
- request_tls_verify=request_tls_verify,
209
- request_cert=request_cert,
210
- )
211
- yield from from_schema(
212
- schema,
213
- checks=checks,
214
- max_response_time=max_response_time,
215
- targets=targets,
216
- hypothesis_settings=hypothesis_settings,
217
- auth=auth,
218
- auth_type=auth_type,
219
- headers=headers,
220
- seed=seed,
221
- workers_num=workers_num,
222
- request_timeout=request_timeout,
223
- request_tls_verify=request_tls_verify,
224
- request_cert=request_cert,
225
- exit_first=exit_first,
226
- dry_run=dry_run,
227
- store_interactions=store_interactions,
228
- stateful=stateful,
229
- stateful_recursion_limit=stateful_recursion_limit,
230
- count_operations=count_operations,
231
- ).execute()
232
- except Exception as exc:
233
- yield events.InternalError.from_exc(exc)
234
-
235
-
236
- def load_schema(
237
- schema_uri: Union[str, Dict[str, Any]],
238
- *,
239
- base_url: Optional[str] = None,
240
- loader: Callable = oas_loaders.from_uri,
241
- app: Any = None,
242
- validate_schema: bool = True,
243
- skip_deprecated_operations: bool = False,
244
- data_generation_methods: Tuple[DataGenerationMethod, ...] = DEFAULT_DATA_GENERATION_METHODS,
245
- force_schema_version: Optional[str] = None,
246
- request_tls_verify: Union[bool, str] = True,
247
- request_cert: Optional[RequestCert] = None,
248
- # Network request parameters
249
- auth: Optional[Tuple[str, str]] = None,
250
- auth_type: Optional[str] = None,
251
- headers: Optional[Dict[str, str]] = None,
252
- # Schema filters
253
- endpoint: Optional[Filter] = None,
254
- method: Optional[Filter] = None,
255
- tag: Optional[Filter] = None,
256
- operation_id: Optional[Filter] = None,
257
- ) -> BaseSchema:
258
- """Load schema via specified loader and parameters."""
259
- loader_options = dict_true_values(
260
- base_url=base_url,
261
- endpoint=endpoint,
262
- method=method,
263
- tag=tag,
264
- operation_id=operation_id,
265
- app=app,
266
- data_generation_methods=data_generation_methods,
267
- )
268
-
269
- if not isinstance(schema_uri, dict):
270
- if file_exists(schema_uri):
271
- loader = oas_loaders.from_path
272
- elif loader is not oas_loaders.from_path:
273
- if app is not None and not urlparse(schema_uri).netloc:
274
- # If `schema` is not an existing filesystem path, or a URL then it is considered as a path within
275
- # the given app
276
- loader = oas_loaders.get_loader_for_app(app)
277
- loader_options.update(dict_true_values(headers=headers))
278
- else:
279
- loader_options.update(dict_true_values(headers=headers, auth=auth, auth_type=auth_type))
280
-
281
- if loader is oas_loaders.from_uri and loader_options.get("auth"):
282
- loader_options["auth"] = get_requests_auth(loader_options["auth"], loader_options.pop("auth_type", None))
283
- if loader in (oas_loaders.from_uri, oas_loaders.from_aiohttp):
284
- loader_options["verify"] = request_tls_verify
285
- loader_options["cert"] = request_cert
286
-
287
- return loader(
288
- schema_uri,
289
- validate_schema=validate_schema,
290
- skip_deprecated_operations=skip_deprecated_operations,
291
- force_schema_version=force_schema_version,
292
- **loader_options,
293
- )
294
-
295
-
296
- def from_schema(
297
- schema: BaseSchema,
298
- *,
299
- checks: Iterable[CheckFunction] = DEFAULT_CHECKS,
300
- max_response_time: Optional[int] = None,
301
- targets: Iterable[Target] = DEFAULT_TARGETS,
302
- workers_num: int = 1,
303
- hypothesis_settings: Optional[hypothesis.settings] = None,
304
- auth: Optional[RawAuth] = None,
305
- auth_type: Optional[str] = None,
306
- headers: Optional[Dict[str, Any]] = None,
307
- request_timeout: Optional[int] = None,
308
- request_tls_verify: Union[bool, str] = True,
309
- request_cert: Optional[RequestCert] = None,
310
- seed: Optional[int] = None,
311
- exit_first: bool = False,
312
- dry_run: bool = False,
313
- store_interactions: bool = False,
314
- stateful: Optional[Stateful] = None,
315
- stateful_recursion_limit: int = DEFAULT_STATEFUL_RECURSION_LIMIT,
316
- count_operations: bool = True,
317
- ) -> BaseRunner:
318
- hypothesis_settings = hypothesis_settings or hypothesis.settings(deadline=DEFAULT_DEADLINE)
319
- if workers_num > 1:
320
- if not schema.app:
321
- return ThreadPoolRunner(
322
- schema=schema,
323
- checks=checks,
324
- max_response_time=max_response_time,
325
- targets=targets,
326
- hypothesis_settings=hypothesis_settings,
327
- auth=auth,
328
- auth_type=auth_type,
329
- headers=headers,
330
- seed=seed,
331
- workers_num=workers_num,
332
- request_timeout=request_timeout,
333
- request_tls_verify=request_tls_verify,
334
- request_cert=request_cert,
335
- exit_first=exit_first,
336
- dry_run=dry_run,
337
- store_interactions=store_interactions,
338
- stateful=stateful,
339
- stateful_recursion_limit=stateful_recursion_limit,
340
- count_operations=count_operations,
341
- )
342
- if isinstance(schema.app, Starlette):
343
- return ThreadPoolASGIRunner(
344
- schema=schema,
345
- checks=checks,
346
- max_response_time=max_response_time,
347
- targets=targets,
348
- hypothesis_settings=hypothesis_settings,
349
- auth=auth,
350
- auth_type=auth_type,
351
- headers=headers,
352
- seed=seed,
353
- exit_first=exit_first,
354
- dry_run=dry_run,
355
- store_interactions=store_interactions,
356
- stateful=stateful,
357
- stateful_recursion_limit=stateful_recursion_limit,
358
- count_operations=count_operations,
359
- )
360
- return ThreadPoolWSGIRunner(
361
- schema=schema,
362
- checks=checks,
363
- max_response_time=max_response_time,
364
- targets=targets,
365
- hypothesis_settings=hypothesis_settings,
366
- auth=auth,
367
- auth_type=auth_type,
368
- headers=headers,
369
- seed=seed,
370
- workers_num=workers_num,
371
- exit_first=exit_first,
372
- dry_run=dry_run,
373
- store_interactions=store_interactions,
374
- stateful=stateful,
375
- stateful_recursion_limit=stateful_recursion_limit,
376
- count_operations=count_operations,
377
- )
378
- if not schema.app:
379
- return SingleThreadRunner(
380
- schema=schema,
381
- checks=checks,
382
- max_response_time=max_response_time,
383
- targets=targets,
384
- hypothesis_settings=hypothesis_settings,
385
- auth=auth,
386
- auth_type=auth_type,
387
- headers=headers,
388
- seed=seed,
389
- request_timeout=request_timeout,
390
- request_tls_verify=request_tls_verify,
391
- request_cert=request_cert,
392
- exit_first=exit_first,
393
- dry_run=dry_run,
394
- store_interactions=store_interactions,
395
- stateful=stateful,
396
- stateful_recursion_limit=stateful_recursion_limit,
397
- count_operations=count_operations,
398
- )
399
- if isinstance(schema.app, Starlette):
400
- return SingleThreadASGIRunner(
401
- schema=schema,
402
- checks=checks,
403
- max_response_time=max_response_time,
404
- targets=targets,
405
- hypothesis_settings=hypothesis_settings,
406
- auth=auth,
407
- auth_type=auth_type,
408
- headers=headers,
409
- seed=seed,
410
- exit_first=exit_first,
411
- dry_run=dry_run,
412
- store_interactions=store_interactions,
413
- stateful=stateful,
414
- stateful_recursion_limit=stateful_recursion_limit,
415
- count_operations=count_operations,
416
- )
417
- return SingleThreadWSGIRunner(
418
- schema=schema,
419
- checks=checks,
420
- max_response_time=max_response_time,
421
- targets=targets,
422
- hypothesis_settings=hypothesis_settings,
423
- auth=auth,
424
- auth_type=auth_type,
425
- headers=headers,
426
- seed=seed,
427
- exit_first=exit_first,
428
- dry_run=dry_run,
429
- store_interactions=store_interactions,
430
- stateful=stateful,
431
- stateful_recursion_limit=stateful_recursion_limit,
432
- count_operations=count_operations,
433
- )
434
-
435
-
436
- def prepare_hypothesis_settings(
437
- deadline: Optional[Union[int, NotSet]] = None,
438
- derandomize: Optional[bool] = None,
439
- max_examples: Optional[int] = None,
440
- phases: Optional[List[hypothesis.Phase]] = None,
441
- report_multiple_bugs: Optional[bool] = None,
442
- suppress_health_check: Optional[List[hypothesis.HealthCheck]] = None,
443
- verbosity: Optional[hypothesis.Verbosity] = None,
444
- ) -> hypothesis.settings:
445
- kwargs = dict_not_none_values(
446
- derandomize=derandomize,
447
- max_examples=max_examples,
448
- phases=phases,
449
- report_multiple_bugs=report_multiple_bugs,
450
- suppress_health_check=suppress_health_check,
451
- verbosity=verbosity,
452
- )
453
- # `deadline` is special, since Hypothesis allows passing `None`
454
- if deadline is not None:
455
- if isinstance(deadline, NotSet):
456
- kwargs["deadline"] = None
457
- else:
458
- kwargs["deadline"] = deadline
459
- kwargs.setdefault("deadline", DEFAULT_DEADLINE)
460
- return hypothesis.settings(**kwargs)