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.
Files changed (229) hide show
  1. schemathesis/__init__.py +27 -65
  2. schemathesis/auths.py +26 -68
  3. schemathesis/checks.py +130 -60
  4. schemathesis/cli/__init__.py +5 -2105
  5. schemathesis/cli/commands/__init__.py +37 -0
  6. schemathesis/cli/commands/run/__init__.py +662 -0
  7. schemathesis/cli/commands/run/checks.py +80 -0
  8. schemathesis/cli/commands/run/context.py +117 -0
  9. schemathesis/cli/commands/run/events.py +30 -0
  10. schemathesis/cli/commands/run/executor.py +141 -0
  11. schemathesis/cli/commands/run/filters.py +202 -0
  12. schemathesis/cli/commands/run/handlers/__init__.py +46 -0
  13. schemathesis/cli/commands/run/handlers/base.py +18 -0
  14. schemathesis/cli/{cassettes.py → commands/run/handlers/cassettes.py} +178 -247
  15. schemathesis/cli/commands/run/handlers/junitxml.py +54 -0
  16. schemathesis/cli/commands/run/handlers/output.py +1368 -0
  17. schemathesis/cli/commands/run/hypothesis.py +105 -0
  18. schemathesis/cli/commands/run/loaders.py +129 -0
  19. schemathesis/cli/{callbacks.py → commands/run/validation.py} +59 -175
  20. schemathesis/cli/constants.py +5 -58
  21. schemathesis/cli/core.py +17 -0
  22. schemathesis/cli/ext/fs.py +14 -0
  23. schemathesis/cli/ext/groups.py +55 -0
  24. schemathesis/cli/{options.py → ext/options.py} +37 -16
  25. schemathesis/cli/hooks.py +36 -0
  26. schemathesis/contrib/__init__.py +1 -3
  27. schemathesis/contrib/openapi/__init__.py +1 -3
  28. schemathesis/contrib/openapi/fill_missing_examples.py +3 -7
  29. schemathesis/core/__init__.py +58 -0
  30. schemathesis/core/compat.py +25 -0
  31. schemathesis/core/control.py +2 -0
  32. schemathesis/core/curl.py +58 -0
  33. schemathesis/core/deserialization.py +65 -0
  34. schemathesis/core/errors.py +370 -0
  35. schemathesis/core/failures.py +315 -0
  36. schemathesis/core/fs.py +19 -0
  37. schemathesis/core/loaders.py +104 -0
  38. schemathesis/core/marks.py +66 -0
  39. schemathesis/{transports/content_types.py → core/media_types.py} +14 -12
  40. schemathesis/{internal/output.py → core/output/__init__.py} +1 -0
  41. schemathesis/core/output/sanitization.py +197 -0
  42. schemathesis/{throttling.py → core/rate_limit.py} +16 -17
  43. schemathesis/core/registries.py +31 -0
  44. schemathesis/core/transforms.py +113 -0
  45. schemathesis/core/transport.py +108 -0
  46. schemathesis/core/validation.py +38 -0
  47. schemathesis/core/version.py +7 -0
  48. schemathesis/engine/__init__.py +30 -0
  49. schemathesis/engine/config.py +59 -0
  50. schemathesis/engine/context.py +119 -0
  51. schemathesis/engine/control.py +36 -0
  52. schemathesis/engine/core.py +157 -0
  53. schemathesis/engine/errors.py +394 -0
  54. schemathesis/engine/events.py +243 -0
  55. schemathesis/engine/phases/__init__.py +66 -0
  56. schemathesis/{runner → engine/phases}/probes.py +49 -68
  57. schemathesis/engine/phases/stateful/__init__.py +66 -0
  58. schemathesis/engine/phases/stateful/_executor.py +301 -0
  59. schemathesis/engine/phases/stateful/context.py +85 -0
  60. schemathesis/engine/phases/unit/__init__.py +175 -0
  61. schemathesis/engine/phases/unit/_executor.py +322 -0
  62. schemathesis/engine/phases/unit/_pool.py +74 -0
  63. schemathesis/engine/recorder.py +246 -0
  64. schemathesis/errors.py +31 -0
  65. schemathesis/experimental/__init__.py +9 -40
  66. schemathesis/filters.py +7 -95
  67. schemathesis/generation/__init__.py +3 -3
  68. schemathesis/generation/case.py +190 -0
  69. schemathesis/generation/coverage.py +22 -22
  70. schemathesis/{_patches.py → generation/hypothesis/__init__.py} +15 -6
  71. schemathesis/generation/hypothesis/builder.py +585 -0
  72. schemathesis/generation/{_hypothesis.py → hypothesis/examples.py} +2 -11
  73. schemathesis/generation/hypothesis/given.py +66 -0
  74. schemathesis/generation/hypothesis/reporting.py +14 -0
  75. schemathesis/generation/hypothesis/strategies.py +16 -0
  76. schemathesis/generation/meta.py +115 -0
  77. schemathesis/generation/modes.py +28 -0
  78. schemathesis/generation/overrides.py +96 -0
  79. schemathesis/generation/stateful/__init__.py +20 -0
  80. schemathesis/{stateful → generation/stateful}/state_machine.py +84 -109
  81. schemathesis/generation/targets.py +69 -0
  82. schemathesis/graphql/__init__.py +15 -0
  83. schemathesis/graphql/checks.py +109 -0
  84. schemathesis/graphql/loaders.py +131 -0
  85. schemathesis/hooks.py +17 -62
  86. schemathesis/openapi/__init__.py +13 -0
  87. schemathesis/openapi/checks.py +387 -0
  88. schemathesis/openapi/generation/__init__.py +0 -0
  89. schemathesis/openapi/generation/filters.py +63 -0
  90. schemathesis/openapi/loaders.py +178 -0
  91. schemathesis/pytest/__init__.py +5 -0
  92. schemathesis/pytest/control_flow.py +7 -0
  93. schemathesis/pytest/lazy.py +273 -0
  94. schemathesis/pytest/loaders.py +12 -0
  95. schemathesis/{extra/pytest_plugin.py → pytest/plugin.py} +94 -107
  96. schemathesis/python/__init__.py +0 -0
  97. schemathesis/python/asgi.py +12 -0
  98. schemathesis/python/wsgi.py +12 -0
  99. schemathesis/schemas.py +456 -228
  100. schemathesis/specs/graphql/__init__.py +0 -1
  101. schemathesis/specs/graphql/_cache.py +1 -2
  102. schemathesis/specs/graphql/scalars.py +5 -3
  103. schemathesis/specs/graphql/schemas.py +122 -123
  104. schemathesis/specs/graphql/validation.py +11 -17
  105. schemathesis/specs/openapi/__init__.py +6 -1
  106. schemathesis/specs/openapi/_cache.py +1 -2
  107. schemathesis/specs/openapi/_hypothesis.py +97 -134
  108. schemathesis/specs/openapi/checks.py +238 -219
  109. schemathesis/specs/openapi/converter.py +4 -4
  110. schemathesis/specs/openapi/definitions.py +1 -1
  111. schemathesis/specs/openapi/examples.py +22 -20
  112. schemathesis/specs/openapi/expressions/__init__.py +11 -15
  113. schemathesis/specs/openapi/expressions/extractors.py +1 -4
  114. schemathesis/specs/openapi/expressions/nodes.py +33 -32
  115. schemathesis/specs/openapi/formats.py +3 -2
  116. schemathesis/specs/openapi/links.py +123 -299
  117. schemathesis/specs/openapi/media_types.py +10 -12
  118. schemathesis/specs/openapi/negative/__init__.py +2 -1
  119. schemathesis/specs/openapi/negative/mutations.py +3 -2
  120. schemathesis/specs/openapi/parameters.py +8 -6
  121. schemathesis/specs/openapi/patterns.py +1 -1
  122. schemathesis/specs/openapi/references.py +11 -51
  123. schemathesis/specs/openapi/schemas.py +177 -191
  124. schemathesis/specs/openapi/security.py +1 -1
  125. schemathesis/specs/openapi/serialization.py +10 -6
  126. schemathesis/specs/openapi/stateful/__init__.py +97 -91
  127. schemathesis/transport/__init__.py +104 -0
  128. schemathesis/transport/asgi.py +26 -0
  129. schemathesis/transport/prepare.py +99 -0
  130. schemathesis/transport/requests.py +221 -0
  131. schemathesis/{_xml.py → transport/serialization.py} +69 -7
  132. schemathesis/transport/wsgi.py +165 -0
  133. {schemathesis-3.39.7.dist-info → schemathesis-4.0.0a2.dist-info}/METADATA +18 -14
  134. schemathesis-4.0.0a2.dist-info/RECORD +151 -0
  135. {schemathesis-3.39.7.dist-info → schemathesis-4.0.0a2.dist-info}/entry_points.txt +1 -1
  136. schemathesis/_compat.py +0 -74
  137. schemathesis/_dependency_versions.py +0 -19
  138. schemathesis/_hypothesis.py +0 -559
  139. schemathesis/_override.py +0 -50
  140. schemathesis/_rate_limiter.py +0 -7
  141. schemathesis/cli/context.py +0 -75
  142. schemathesis/cli/debug.py +0 -27
  143. schemathesis/cli/handlers.py +0 -19
  144. schemathesis/cli/junitxml.py +0 -124
  145. schemathesis/cli/output/__init__.py +0 -1
  146. schemathesis/cli/output/default.py +0 -936
  147. schemathesis/cli/output/short.py +0 -59
  148. schemathesis/cli/reporting.py +0 -79
  149. schemathesis/cli/sanitization.py +0 -26
  150. schemathesis/code_samples.py +0 -151
  151. schemathesis/constants.py +0 -56
  152. schemathesis/contrib/openapi/formats/__init__.py +0 -9
  153. schemathesis/contrib/openapi/formats/uuid.py +0 -16
  154. schemathesis/contrib/unique_data.py +0 -41
  155. schemathesis/exceptions.py +0 -571
  156. schemathesis/extra/_aiohttp.py +0 -28
  157. schemathesis/extra/_flask.py +0 -13
  158. schemathesis/extra/_server.py +0 -18
  159. schemathesis/failures.py +0 -277
  160. schemathesis/fixups/__init__.py +0 -37
  161. schemathesis/fixups/fast_api.py +0 -41
  162. schemathesis/fixups/utf8_bom.py +0 -28
  163. schemathesis/generation/_methods.py +0 -44
  164. schemathesis/graphql.py +0 -3
  165. schemathesis/internal/__init__.py +0 -7
  166. schemathesis/internal/checks.py +0 -84
  167. schemathesis/internal/copy.py +0 -32
  168. schemathesis/internal/datetime.py +0 -5
  169. schemathesis/internal/deprecation.py +0 -38
  170. schemathesis/internal/diff.py +0 -15
  171. schemathesis/internal/extensions.py +0 -27
  172. schemathesis/internal/jsonschema.py +0 -36
  173. schemathesis/internal/transformation.py +0 -26
  174. schemathesis/internal/validation.py +0 -34
  175. schemathesis/lazy.py +0 -474
  176. schemathesis/loaders.py +0 -122
  177. schemathesis/models.py +0 -1341
  178. schemathesis/parameters.py +0 -90
  179. schemathesis/runner/__init__.py +0 -605
  180. schemathesis/runner/events.py +0 -389
  181. schemathesis/runner/impl/__init__.py +0 -3
  182. schemathesis/runner/impl/context.py +0 -104
  183. schemathesis/runner/impl/core.py +0 -1246
  184. schemathesis/runner/impl/solo.py +0 -80
  185. schemathesis/runner/impl/threadpool.py +0 -391
  186. schemathesis/runner/serialization.py +0 -544
  187. schemathesis/sanitization.py +0 -252
  188. schemathesis/serializers.py +0 -328
  189. schemathesis/service/__init__.py +0 -18
  190. schemathesis/service/auth.py +0 -11
  191. schemathesis/service/ci.py +0 -202
  192. schemathesis/service/client.py +0 -133
  193. schemathesis/service/constants.py +0 -38
  194. schemathesis/service/events.py +0 -61
  195. schemathesis/service/extensions.py +0 -224
  196. schemathesis/service/hosts.py +0 -111
  197. schemathesis/service/metadata.py +0 -71
  198. schemathesis/service/models.py +0 -258
  199. schemathesis/service/report.py +0 -255
  200. schemathesis/service/serialization.py +0 -173
  201. schemathesis/service/usage.py +0 -66
  202. schemathesis/specs/graphql/loaders.py +0 -364
  203. schemathesis/specs/openapi/expressions/context.py +0 -16
  204. schemathesis/specs/openapi/loaders.py +0 -708
  205. schemathesis/specs/openapi/stateful/statistic.py +0 -198
  206. schemathesis/specs/openapi/stateful/types.py +0 -14
  207. schemathesis/specs/openapi/validation.py +0 -26
  208. schemathesis/stateful/__init__.py +0 -147
  209. schemathesis/stateful/config.py +0 -97
  210. schemathesis/stateful/context.py +0 -135
  211. schemathesis/stateful/events.py +0 -274
  212. schemathesis/stateful/runner.py +0 -309
  213. schemathesis/stateful/sink.py +0 -68
  214. schemathesis/stateful/statistic.py +0 -22
  215. schemathesis/stateful/validation.py +0 -100
  216. schemathesis/targets.py +0 -77
  217. schemathesis/transports/__init__.py +0 -359
  218. schemathesis/transports/asgi.py +0 -7
  219. schemathesis/transports/auth.py +0 -38
  220. schemathesis/transports/headers.py +0 -36
  221. schemathesis/transports/responses.py +0 -57
  222. schemathesis/types.py +0 -44
  223. schemathesis/utils.py +0 -164
  224. schemathesis-3.39.7.dist-info/RECORD +0 -160
  225. /schemathesis/{extra → cli/ext}/__init__.py +0 -0
  226. /schemathesis/{_lazy_import.py → core/lazy_import.py} +0 -0
  227. /schemathesis/{internal → core}/result.py +0 -0
  228. {schemathesis-3.39.7.dist-info → schemathesis-4.0.0a2.dist-info}/WHEEL +0 -0
  229. {schemathesis-3.39.7.dist-info → schemathesis-4.0.0a2.dist-info}/licenses/LICENSE +0 -0
@@ -1,389 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import enum
4
- import threading
5
- import time
6
- from dataclasses import asdict, dataclass, field
7
- from typing import TYPE_CHECKING, Any
8
-
9
- from ..exceptions import RuntimeErrorType, SchemaError, SchemaErrorType, format_exception
10
- from ..internal.datetime import current_datetime
11
- from ..internal.result import Err, Ok, Result
12
- from .serialization import SerializedError, SerializedTestResult
13
-
14
- if TYPE_CHECKING:
15
- from ..generation import DataGenerationMethod
16
- from ..models import APIOperation, Status, TestResult, TestResultSet
17
- from ..schemas import BaseSchema, Specification
18
- from ..service.models import AnalysisResult
19
- from ..stateful import events
20
- from . import probes
21
-
22
-
23
- @dataclass
24
- class ExecutionEvent:
25
- """Generic execution event."""
26
-
27
- # Whether this event is expected to be the last one in the event stream
28
- is_terminal = False
29
-
30
- def asdict(self, **kwargs: Any) -> dict[str, Any]:
31
- data = asdict(self, **kwargs)
32
- # An internal tag for simpler type identification
33
- data["event_type"] = self.__class__.__name__
34
- return data
35
-
36
-
37
- @dataclass
38
- class Initialized(ExecutionEvent):
39
- """Runner is initialized, settings are prepared, requests session is ready."""
40
-
41
- schema: dict[str, Any]
42
- specification: Specification
43
- # Total number of operations in the schema
44
- operations_count: int | None
45
- # Total number of links in the schema
46
- links_count: int | None
47
- # The place, where the API schema is located
48
- location: str | None
49
- seed: int | None
50
- # The base URL against which the tests are running
51
- base_url: str
52
- # The base path part of every operation
53
- base_path: str
54
- # API schema specification name
55
- specification_name: str
56
- # Monotonic clock value when the test run started. Used to properly calculate run duration, since this clock
57
- # can't go backwards.
58
- start_time: float = field(default_factory=time.monotonic)
59
- # Datetime of the test run start
60
- started_at: str = field(default_factory=current_datetime)
61
- thread_id: int = field(default_factory=threading.get_ident)
62
-
63
- @classmethod
64
- def from_schema(
65
- cls,
66
- *,
67
- schema: BaseSchema,
68
- count_operations: bool = True,
69
- count_links: bool = True,
70
- start_time: float | None = None,
71
- started_at: str | None = None,
72
- seed: int | None,
73
- ) -> Initialized:
74
- """Computes all needed data from a schema instance."""
75
- return cls(
76
- schema=schema.raw_schema,
77
- specification=schema.specification,
78
- operations_count=schema.operations_count if count_operations else None,
79
- links_count=schema.links_count if count_links else None,
80
- location=schema.location,
81
- base_url=schema.get_base_url(),
82
- base_path=schema.base_path,
83
- start_time=start_time or time.monotonic(),
84
- started_at=started_at or current_datetime(),
85
- specification_name=schema.verbose_name,
86
- seed=seed,
87
- )
88
-
89
-
90
- @dataclass
91
- class BeforeProbing(ExecutionEvent):
92
- pass
93
-
94
-
95
- @dataclass
96
- class AfterProbing(ExecutionEvent):
97
- probes: list[probes.ProbeRun] | None
98
-
99
- def asdict(self, **kwargs: Any) -> dict[str, Any]:
100
- probes = self.probes or []
101
- return {"probes": [probe.serialize() for probe in probes], "events_type": self.__class__.__name__}
102
-
103
-
104
- @dataclass
105
- class BeforeAnalysis(ExecutionEvent):
106
- pass
107
-
108
-
109
- @dataclass
110
- class AfterAnalysis(ExecutionEvent):
111
- analysis: Result[AnalysisResult, Exception] | None
112
-
113
- def _serialize(self) -> dict[str, Any]:
114
- from ..service.models import AnalysisSuccess
115
-
116
- data = {}
117
- if isinstance(self.analysis, Ok):
118
- result = self.analysis.ok()
119
- if isinstance(result, AnalysisSuccess):
120
- data["analysis_id"] = result.id
121
- else:
122
- data["error"] = result.message
123
- elif isinstance(self.analysis, Err):
124
- data["error"] = format_exception(self.analysis.err())
125
- return data
126
-
127
- def asdict(self, **kwargs: Any) -> dict[str, Any]:
128
- data = self._serialize()
129
- data["event_type"] = self.__class__.__name__
130
- return data
131
-
132
-
133
- class CurrentOperationMixin:
134
- method: str
135
- path: str
136
-
137
- @property
138
- def current_operation(self) -> str:
139
- return f"{self.method} {self.path}"
140
-
141
-
142
- @dataclass
143
- class BeforeExecution(CurrentOperationMixin, ExecutionEvent):
144
- """Happens before each tested API operation.
145
-
146
- It happens before a single hypothesis test, that may contain many examples inside.
147
- """
148
-
149
- # HTTP method
150
- method: str
151
- # Full path, including the base path
152
- path: str
153
- # Specification-specific operation name
154
- verbose_name: str
155
- # Path without the base path
156
- relative_path: str
157
- # The current level of recursion during stateful testing
158
- recursion_level: int
159
- # The way data will be generated
160
- data_generation_method: list[DataGenerationMethod]
161
- # A unique ID which connects events that happen during testing of the same API operation
162
- # It may be useful when multiple threads are involved where incoming events are not ordered
163
- correlation_id: str
164
- thread_id: int = field(default_factory=threading.get_ident)
165
-
166
- @classmethod
167
- def from_operation(
168
- cls,
169
- operation: APIOperation,
170
- recursion_level: int,
171
- data_generation_method: list[DataGenerationMethod],
172
- correlation_id: str,
173
- ) -> BeforeExecution:
174
- return cls(
175
- method=operation.method.upper(),
176
- path=operation.full_path,
177
- verbose_name=operation.verbose_name,
178
- relative_path=operation.path,
179
- recursion_level=recursion_level,
180
- data_generation_method=data_generation_method,
181
- correlation_id=correlation_id,
182
- )
183
-
184
-
185
- @dataclass
186
- class AfterExecution(CurrentOperationMixin, ExecutionEvent):
187
- """Happens after each tested API operation."""
188
-
189
- method: str
190
- path: str
191
- relative_path: str
192
- # Specification-specific operation name
193
- verbose_name: str
194
-
195
- # APIOperation test status - success / failure / error
196
- status: Status
197
- # The way data was generated
198
- data_generation_method: list[DataGenerationMethod]
199
- result: SerializedTestResult
200
- # Test running time
201
- elapsed_time: float
202
- correlation_id: str
203
- thread_id: int = field(default_factory=threading.get_ident)
204
- # Captured hypothesis stdout
205
- hypothesis_output: list[str] = field(default_factory=list)
206
-
207
- @classmethod
208
- def from_result(
209
- cls,
210
- result: TestResult,
211
- status: Status,
212
- elapsed_time: float,
213
- hypothesis_output: list[str],
214
- operation: APIOperation,
215
- data_generation_method: list[DataGenerationMethod],
216
- correlation_id: str,
217
- ) -> AfterExecution:
218
- return cls(
219
- method=operation.method.upper(),
220
- path=operation.full_path,
221
- relative_path=operation.path,
222
- verbose_name=operation.verbose_name,
223
- result=SerializedTestResult.from_test_result(result),
224
- status=status,
225
- elapsed_time=elapsed_time,
226
- hypothesis_output=hypothesis_output,
227
- data_generation_method=data_generation_method,
228
- correlation_id=correlation_id,
229
- )
230
-
231
-
232
- @dataclass
233
- class Interrupted(ExecutionEvent):
234
- """If execution was interrupted by Ctrl-C, or a received SIGTERM."""
235
-
236
- thread_id: int = field(default_factory=threading.get_ident)
237
-
238
-
239
- @enum.unique
240
- class InternalErrorType(str, enum.Enum):
241
- SCHEMA = "schema"
242
- OTHER = "other"
243
-
244
-
245
- DEFAULT_INTERNAL_ERROR_MESSAGE = "An internal error occurred during the test run"
246
-
247
-
248
- @dataclass
249
- class InternalError(ExecutionEvent):
250
- """An error that happened inside the runner."""
251
-
252
- is_terminal = True
253
-
254
- # Main error info
255
- type: InternalErrorType
256
- subtype: SchemaErrorType | None
257
- title: str
258
- message: str
259
- extras: list[str]
260
-
261
- # Exception info
262
- exception_type: str
263
- exception: str
264
- exception_with_traceback: str
265
- # Auxiliary data
266
- thread_id: int = field(default_factory=threading.get_ident)
267
-
268
- @classmethod
269
- def from_schema_error(cls, error: SchemaError) -> InternalError:
270
- return cls.with_exception(
271
- error,
272
- type_=InternalErrorType.SCHEMA,
273
- subtype=error.type,
274
- title="Schema Loading Error",
275
- message=error.message,
276
- extras=error.extras,
277
- )
278
-
279
- @classmethod
280
- def from_exc(cls, exc: Exception) -> InternalError:
281
- return cls.with_exception(
282
- exc,
283
- type_=InternalErrorType.OTHER,
284
- subtype=None,
285
- title="Test Execution Error",
286
- message=DEFAULT_INTERNAL_ERROR_MESSAGE,
287
- extras=[],
288
- )
289
-
290
- @classmethod
291
- def with_exception(
292
- cls,
293
- exc: Exception,
294
- type_: InternalErrorType,
295
- subtype: SchemaErrorType | None,
296
- title: str,
297
- message: str,
298
- extras: list[str],
299
- ) -> InternalError:
300
- exception_type = f"{exc.__class__.__module__}.{exc.__class__.__qualname__}"
301
- exception = format_exception(exc)
302
- exception_with_traceback = format_exception(exc, include_traceback=True)
303
- return cls(
304
- type=type_,
305
- subtype=subtype,
306
- title=title,
307
- message=message,
308
- extras=extras,
309
- exception_type=exception_type,
310
- exception=exception,
311
- exception_with_traceback=exception_with_traceback,
312
- )
313
-
314
-
315
- @dataclass
316
- class StatefulEvent(ExecutionEvent):
317
- """Represents an event originating from the state machine runner."""
318
-
319
- data: events.StatefulEvent
320
-
321
- __slots__ = ("data",)
322
-
323
- def asdict(self, **kwargs: Any) -> dict[str, Any]:
324
- return {"data": self.data.asdict(**kwargs), "event_type": self.__class__.__name__}
325
-
326
-
327
- @dataclass
328
- class AfterStatefulExecution(ExecutionEvent):
329
- """Happens after the stateful test run."""
330
-
331
- status: Status
332
- result: SerializedTestResult
333
- elapsed_time: float
334
- data_generation_method: list[DataGenerationMethod]
335
- thread_id: int = field(default_factory=threading.get_ident)
336
-
337
-
338
- @dataclass
339
- class Finished(ExecutionEvent):
340
- """The final event of the run.
341
-
342
- No more events after this point.
343
- """
344
-
345
- is_terminal = True
346
-
347
- passed_count: int
348
- skipped_count: int
349
- failed_count: int
350
- errored_count: int
351
-
352
- has_failures: bool
353
- has_errors: bool
354
- has_logs: bool
355
- is_empty: bool
356
- generic_errors: list[SerializedError]
357
- warnings: list[str]
358
-
359
- total: dict[str, dict[str | Status, int]]
360
-
361
- # Total test run execution time
362
- running_time: float
363
- thread_id: int = field(default_factory=threading.get_ident)
364
-
365
- @classmethod
366
- def from_results(cls, results: TestResultSet, running_time: float) -> Finished:
367
- return cls(
368
- passed_count=results.passed_count,
369
- skipped_count=results.skipped_count,
370
- failed_count=results.failed_count,
371
- errored_count=results.errored_count,
372
- has_failures=results.has_failures,
373
- has_errors=results.has_errors,
374
- has_logs=results.has_logs,
375
- is_empty=results.is_empty,
376
- total=results.total,
377
- generic_errors=[
378
- SerializedError.with_exception(
379
- type_=RuntimeErrorType.SCHEMA_GENERIC,
380
- exception=error,
381
- title=error.full_path,
382
- message=error.message,
383
- extras=[],
384
- )
385
- for error in results.generic_errors
386
- ],
387
- warnings=results.warnings,
388
- running_time=running_time,
389
- )
@@ -1,3 +0,0 @@
1
- from .core import BaseRunner
2
- from .solo import SingleThreadASGIRunner, SingleThreadRunner, SingleThreadWSGIRunner
3
- from .threadpool import ThreadPoolASGIRunner, ThreadPoolRunner, ThreadPoolWSGIRunner
@@ -1,104 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from dataclasses import dataclass
4
- from typing import TYPE_CHECKING, Any
5
-
6
- from ...constants import NOT_SET
7
- from ...internal.checks import CheckConfig
8
- from ...models import TestResult, TestResultSet
9
-
10
- if TYPE_CHECKING:
11
- import threading
12
-
13
- from ..._override import CaseOverride
14
- from ...exceptions import OperationSchemaError
15
- from ...models import Case
16
- from ...types import NotSet, RawAuth
17
-
18
-
19
- @dataclass
20
- class RunnerContext:
21
- """Holds context shared for a test run."""
22
-
23
- data: TestResultSet
24
- auth: RawAuth | None
25
- seed: int | None
26
- stop_event: threading.Event
27
- unique_data: bool
28
- outcome_cache: dict[int, BaseException | None]
29
- checks_config: CheckConfig
30
- override: CaseOverride | None
31
- no_failfast: bool
32
-
33
- __slots__ = (
34
- "data",
35
- "auth",
36
- "seed",
37
- "stop_event",
38
- "unique_data",
39
- "outcome_cache",
40
- "checks_config",
41
- "override",
42
- "no_failfast",
43
- )
44
-
45
- def __init__(
46
- self,
47
- *,
48
- seed: int | None,
49
- auth: RawAuth | None,
50
- stop_event: threading.Event,
51
- unique_data: bool,
52
- checks_config: CheckConfig,
53
- override: CaseOverride | None,
54
- no_failfast: bool,
55
- ) -> None:
56
- self.data = TestResultSet(seed=seed)
57
- self.auth = auth
58
- self.seed = seed
59
- self.stop_event = stop_event
60
- self.outcome_cache = {}
61
- self.unique_data = unique_data
62
- self.checks_config = checks_config
63
- self.override = override
64
- self.no_failfast = no_failfast
65
-
66
- def _repr_pretty_(self, *args: Any, **kwargs: Any) -> None: ...
67
-
68
- @property
69
- def is_stopped(self) -> bool:
70
- return self.stop_event.is_set()
71
-
72
- @property
73
- def has_all_not_found(self) -> bool:
74
- """Check if all responses are 404."""
75
- has_not_found = False
76
- for entry in self.data.results:
77
- for check in entry.checks:
78
- if check.response is not None:
79
- if check.response.status_code == 404:
80
- has_not_found = True
81
- else:
82
- # There are non-404 responses, no reason to check any other response
83
- return False
84
- # Only happens if all responses are 404, or there are no responses at all.
85
- # In the first case, it returns True, for the latter - False
86
- return has_not_found
87
-
88
- def add_result(self, result: TestResult) -> None:
89
- self.data.append(result)
90
-
91
- def add_generic_error(self, error: OperationSchemaError) -> None:
92
- self.data.generic_errors.append(error)
93
-
94
- def add_warning(self, message: str) -> None:
95
- self.data.add_warning(message)
96
-
97
- def cache_outcome(self, case: Case, outcome: BaseException | None) -> None:
98
- self.outcome_cache[hash(case)] = outcome
99
-
100
- def get_cached_outcome(self, case: Case) -> BaseException | None | NotSet:
101
- return self.outcome_cache.get(hash(case), NOT_SET)
102
-
103
-
104
- ALL_NOT_FOUND_WARNING_MESSAGE = "All API responses have a 404 status code. Did you specify the proper API location?"