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