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