schemathesis 4.0.0a4__py3-none-any.whl → 4.0.0a6__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 (29) hide show
  1. schemathesis/cli/commands/run/__init__.py +15 -45
  2. schemathesis/cli/commands/run/checks.py +2 -3
  3. schemathesis/cli/commands/run/context.py +30 -17
  4. schemathesis/cli/commands/run/executor.py +1 -0
  5. schemathesis/cli/commands/run/handlers/output.py +168 -88
  6. schemathesis/cli/commands/run/hypothesis.py +7 -45
  7. schemathesis/core/__init__.py +7 -1
  8. schemathesis/engine/config.py +2 -2
  9. schemathesis/engine/core.py +11 -1
  10. schemathesis/engine/events.py +7 -0
  11. schemathesis/engine/phases/__init__.py +16 -4
  12. schemathesis/engine/phases/unit/__init__.py +77 -52
  13. schemathesis/engine/phases/unit/_executor.py +14 -12
  14. schemathesis/engine/phases/unit/_pool.py +8 -0
  15. schemathesis/experimental/__init__.py +0 -6
  16. schemathesis/generation/hypothesis/builder.py +222 -97
  17. schemathesis/openapi/checks.py +3 -1
  18. schemathesis/pytest/lazy.py +41 -2
  19. schemathesis/pytest/plugin.py +2 -1
  20. schemathesis/specs/openapi/checks.py +1 -1
  21. schemathesis/specs/openapi/examples.py +39 -25
  22. schemathesis/specs/openapi/patterns.py +39 -7
  23. schemathesis/specs/openapi/serialization.py +14 -0
  24. schemathesis/transport/requests.py +10 -1
  25. {schemathesis-4.0.0a4.dist-info → schemathesis-4.0.0a6.dist-info}/METADATA +47 -91
  26. {schemathesis-4.0.0a4.dist-info → schemathesis-4.0.0a6.dist-info}/RECORD +29 -29
  27. {schemathesis-4.0.0a4.dist-info → schemathesis-4.0.0a6.dist-info}/licenses/LICENSE +1 -1
  28. {schemathesis-4.0.0a4.dist-info → schemathesis-4.0.0a6.dist-info}/WHEEL +0 -0
  29. {schemathesis-4.0.0a4.dist-info → schemathesis-4.0.0a6.dist-info}/entry_points.txt +0 -0
@@ -16,6 +16,7 @@ from schemathesis.generation.case import Case
16
16
  from schemathesis.generation.hypothesis import examples
17
17
  from schemathesis.generation.meta import TestPhase
18
18
  from schemathesis.schemas import APIOperation
19
+ from schemathesis.specs.openapi.serialization import get_serializers_for_operation
19
20
 
20
21
  from ._hypothesis import get_default_format_strategies, openapi_cases
21
22
  from .constants import LOCATION_TO_CONTAINER
@@ -50,11 +51,7 @@ def get_strategies_from_examples(
50
51
  operation: APIOperation[OpenAPIParameter], **kwargs: Any
51
52
  ) -> list[SearchStrategy[Case]]:
52
53
  """Build a set of strategies that generate test cases based on explicit examples in the schema."""
53
- maps = {}
54
- for location, container in LOCATION_TO_CONTAINER.items():
55
- serializer = operation.get_parameter_serializer(location)
56
- if serializer is not None:
57
- maps[container] = serializer
54
+ maps = get_serializers_for_operation(operation)
58
55
 
59
56
  def serialize_components(case: Case) -> Case:
60
57
  """Applies special serialization rules for case components.
@@ -402,45 +399,62 @@ def find_matching_in_responses(examples: dict[str, list], param: str) -> Iterato
402
399
  if not isinstance(example, dict):
403
400
  continue
404
401
  # Unwrapping example from `{"item": [{...}]}`
405
- if isinstance(example, dict) and len(example) == 1 and list(example)[0].lower() == schema_name.lower():
406
- inner = list(example.values())[0]
407
- if isinstance(inner, list):
408
- for sub_example in inner:
409
- found = _find_matching_in_responses(sub_example, schema_name, param, normalized, is_id_param)
410
- if found is not NOT_FOUND:
411
- yield found
412
- continue
413
- if isinstance(inner, dict):
414
- example = inner
415
- found = _find_matching_in_responses(example, schema_name, param, normalized, is_id_param)
416
- if found is not NOT_FOUND:
417
- yield found
402
+ if isinstance(example, dict):
403
+ inner = next((value for key, value in example.items() if key.lower() == schema_name.lower()), None)
404
+ if inner is not None:
405
+ if isinstance(inner, list):
406
+ for sub_example in inner:
407
+ if isinstance(sub_example, dict):
408
+ for found in _find_matching_in_responses(
409
+ sub_example, schema_name, param, normalized, is_id_param
410
+ ):
411
+ if found is not NOT_FOUND:
412
+ yield found
413
+ continue
414
+ if isinstance(inner, dict):
415
+ example = inner
416
+ for found in _find_matching_in_responses(example, schema_name, param, normalized, is_id_param):
417
+ if found is not NOT_FOUND:
418
+ yield found
418
419
 
419
420
 
420
421
  def _find_matching_in_responses(
421
422
  example: dict[str, Any], schema_name: str, param: str, normalized: str, is_id_param: bool
422
- ) -> Any:
423
+ ) -> Iterator[Any]:
423
424
  # Check for exact match
424
425
  if param in example:
425
- return example[param]
426
+ yield example[param]
427
+ return
426
428
  if is_id_param and param[:-2] in example:
427
- return example[param[:-2]]
429
+ value = example[param[:-2]]
430
+ if isinstance(value, list):
431
+ for sub_example in value:
432
+ for found in _find_matching_in_responses(sub_example, schema_name, param, normalized, is_id_param):
433
+ if found is not NOT_FOUND:
434
+ yield found
435
+ return
436
+ else:
437
+ yield value
438
+ return
428
439
 
429
440
  # Check for case-insensitive match
430
441
  for key in example:
431
442
  if key.lower() == normalized:
432
- return example[key]
443
+ yield example[key]
444
+ return
433
445
  else:
434
446
  # If no match found and it's an ID parameter, try additional checks
435
447
  if is_id_param:
436
448
  # Check for 'id' if parameter is '{something}Id'
437
449
  if "id" in example:
438
- return example["id"]
450
+ yield example["id"]
451
+ return
439
452
  # Check for '{schemaName}Id' or '{schemaName}_id'
440
453
  if normalized == "id" or normalized.startswith(schema_name.lower()):
441
454
  for key in (schema_name, schema_name.lower()):
442
455
  for suffix in ("_id", "Id"):
443
456
  with_suffix = f"{key}{suffix}"
444
457
  if with_suffix in example:
445
- return example[with_suffix]
446
- return NOT_FOUND
458
+ yield example[with_suffix]
459
+ return
460
+ yield NOT_FOUND
@@ -3,6 +3,8 @@ from __future__ import annotations
3
3
  import re
4
4
  from functools import lru_cache
5
5
 
6
+ from schemathesis.core.errors import InternalError
7
+
6
8
  try: # pragma: no cover
7
9
  import re._constants as sre
8
10
  import re._parser as sre_parse
@@ -29,7 +31,15 @@ def update_quantifier(pattern: str, min_length: int | None, max_length: int | No
29
31
 
30
32
  try:
31
33
  parsed = sre_parse.parse(pattern)
32
- return _handle_parsed_pattern(parsed, pattern, min_length, max_length)
34
+ updated = _handle_parsed_pattern(parsed, pattern, min_length, max_length)
35
+ try:
36
+ re.compile(updated)
37
+ except re.error as exc:
38
+ raise InternalError(
39
+ f"The combination of min_length={min_length} and max_length={max_length} applied to the original pattern '{pattern}' resulted in an invalid regex: '{updated}'. "
40
+ "This indicates a bug in the regex quantifier merging logic"
41
+ ) from exc
42
+ return updated
33
43
  except re.error:
34
44
  # Invalid pattern
35
45
  return pattern
@@ -114,6 +124,21 @@ def _handle_anchored_pattern(parsed: list, pattern: str, min_length: int | None,
114
124
 
115
125
  for op, value in pattern_parts:
116
126
  if op == LITERAL:
127
+ # Check if the literal comes from a bracketed expression,
128
+ # e.g. Python regex parses "[+]" as a single LITERAL token.
129
+ if pattern[current_position] == "[":
130
+ # Find the matching closing bracket.
131
+ end_idx = current_position + 1
132
+ while end_idx < len(pattern):
133
+ # Check for an unescaped closing bracket.
134
+ if pattern[end_idx] == "]" and (end_idx == current_position + 1 or pattern[end_idx - 1] != "\\"):
135
+ end_idx += 1
136
+ break
137
+ end_idx += 1
138
+ # Append the entire character set.
139
+ result += pattern[current_position:end_idx]
140
+ current_position = end_idx
141
+ continue
117
142
  if pattern[current_position] == "\\":
118
143
  # Escaped value
119
144
  current_position += 2
@@ -261,13 +286,18 @@ def _handle_repeat_quantifier(
261
286
  min_length, max_length = _build_size(min_repeat, max_repeat, min_length, max_length)
262
287
  if min_length > max_length:
263
288
  return pattern
264
- return f"({_strip_quantifier(pattern).strip(')(')})" + _build_quantifier(min_length, max_length)
289
+ inner = _strip_quantifier(pattern)
290
+ if inner.startswith("(") and inner.endswith(")"):
291
+ inner = inner[1:-1]
292
+ return f"({inner})" + _build_quantifier(min_length, max_length)
265
293
 
266
294
 
267
295
  def _handle_literal_or_in_quantifier(pattern: str, min_length: int | None, max_length: int | None) -> str:
268
296
  """Handle literal or character class quantifiers."""
269
297
  min_length = 1 if min_length is None else max(min_length, 1)
270
- return f"({pattern.strip(')(')})" + _build_quantifier(min_length, max_length)
298
+ if pattern.startswith("(") and pattern.endswith(")"):
299
+ pattern = pattern[1:-1]
300
+ return f"({pattern})" + _build_quantifier(min_length, max_length)
271
301
 
272
302
 
273
303
  def _build_quantifier(minimum: int | None, maximum: int | None) -> str:
@@ -294,10 +324,12 @@ def _build_size(min_repeat: int, max_repeat: int, min_length: int | None, max_le
294
324
  def _strip_quantifier(pattern: str) -> str:
295
325
  """Remove quantifier from the pattern."""
296
326
  # Lazy & posessive quantifiers
297
- if pattern.endswith(("*?", "+?", "??", "*+", "?+", "++")):
298
- return pattern[:-2]
299
- if pattern.endswith(("?", "*", "+")):
300
- pattern = pattern[:-1]
327
+ for marker in ("*?", "+?", "??", "*+", "?+", "++"):
328
+ if pattern.endswith(marker) and not pattern.endswith(rf"\{marker}"):
329
+ return pattern[:-2]
330
+ for marker in ("?", "*", "+"):
331
+ if pattern.endswith(marker) and not pattern.endswith(rf"\{marker}"):
332
+ pattern = pattern[:-1]
301
333
  if pattern.endswith("}") and "{" in pattern:
302
334
  # Find the start of the exact quantifier and drop everything since that index
303
335
  idx = pattern.rfind("{")
@@ -3,12 +3,24 @@ from __future__ import annotations
3
3
  import json
4
4
  from typing import Any, Callable, Dict, Generator, List
5
5
 
6
+ from schemathesis.schemas import APIOperation
7
+ from schemathesis.specs.openapi.constants import LOCATION_TO_CONTAINER
8
+
6
9
  Generated = Dict[str, Any]
7
10
  Definition = Dict[str, Any]
8
11
  DefinitionList = List[Definition]
9
12
  MapFunction = Callable[[Generated], Generated]
10
13
 
11
14
 
15
+ def get_serializers_for_operation(operation: APIOperation) -> dict[str, Callable]:
16
+ serializers = {}
17
+ for location, container in LOCATION_TO_CONTAINER.items():
18
+ serializer = operation.get_parameter_serializer(location)
19
+ if serializer is not None:
20
+ serializers[container] = serializer
21
+ return serializers
22
+
23
+
12
24
  def make_serializer(
13
25
  func: Callable[[DefinitionList], Generator[Callable | None, None, None]],
14
26
  ) -> Callable[[DefinitionList], Callable | None]:
@@ -16,6 +28,8 @@ def make_serializer(
16
28
 
17
29
  def _wrapper(definitions: DefinitionList) -> Callable | None:
18
30
  functions = list(func(definitions))
31
+ if not functions:
32
+ return None
19
33
 
20
34
  def composed(x: Any) -> Any:
21
35
  result = x
@@ -56,12 +56,21 @@ class RequestsTransport(BaseTransport["Case", Response, "requests.Session"]):
56
56
  for key, value in additional_headers.items():
57
57
  final_headers.setdefault(key, value)
58
58
 
59
+ params = case.query
60
+
61
+ # Replace empty dictionaries with empty strings, so the parameters actually present in the query string
62
+ if any(value == {} for value in (params or {}).values()):
63
+ params = deepclone(params)
64
+ for key, value in params.items():
65
+ if value == {}:
66
+ params[key] = ""
67
+
59
68
  data = {
60
69
  "method": case.method,
61
70
  "url": url,
62
71
  "cookies": case.cookies,
63
72
  "headers": final_headers,
64
- "params": case.query,
73
+ "params": params,
65
74
  **extra,
66
75
  }
67
76
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: schemathesis
3
- Version: 4.0.0a4
3
+ Version: 4.0.0a6
4
4
  Summary: Property-based testing framework for Open API and GraphQL based apps
5
5
  Project-URL: Documentation, https://schemathesis.readthedocs.io/en/stable/
6
6
  Project-URL: Changelog, https://schemathesis.readthedocs.io/en/stable/changelog.html
@@ -117,81 +117,47 @@ Description-Content-Type: text/markdown
117
117
 
118
118
  ## Schemathesis
119
119
 
120
- > ⚠️ You are viewing the Schemathesis V4 README (Work in Progress) ⚠️
121
-
122
- > This branch is under active development, with substantial changes expected before stabilization. While V4 is fully functional and passing tests, some features are missing, and the documentation may be outdated.
123
-
124
- > For the stable release, see the [V3 branch](https://github.com/schemathesis/schemathesis/tree/v3).
125
-
126
- > 💡 Have feedback? Share your thoughts in [this discussion](https://github.com/schemathesis/schemathesis/discussions/2677)!
127
-
128
- Schemathesis is an API testing tool that automatically finds crashes and validates spec compliance.
120
+ Schemathesis automatically generates and runs API tests from your OpenAPI or GraphQL schema to find bugs and spec violations.
129
121
 
130
122
  <p align="center">
131
- <img src="https://raw.githubusercontent.com/schemathesis/schemathesis/master/img/demo.gif" alt="Schemathesis Demo"/>
123
+ <img src="https://raw.githubusercontent.com/schemathesis/schemathesis/master/img/demo.gif" alt="Schemathesis automatically finding a server error"/>
124
+ <br>
125
+ <i>Automatically finding specification violations and server errors</i>
132
126
  </p>
133
127
 
134
- <p align="center">
135
- <i>Finding server crashes in the Demo API.</i>
136
- </p>
137
-
138
- ### Highlights
139
-
140
- 🎯 **Catches Hard-to-Find Bugs**
141
-
142
- - Uncover hidden crashes and edge cases that manual testing might miss
143
- - Identify spec violations and ensure your API adheres to its contract
144
-
145
- ⚡ **Accelerates Testing Cycles**
146
-
147
- - Automatically generate a wide range of test cases based on your API schema
148
- - Save time by reducing the need for manual test case creation
128
+ > **Note:** This is the V4 branch under active development. While fully functional and passing tests, some features may be missing, and documentation is being updated. For the stable release, see the [V3 branch](https://github.com/schemathesis/schemathesis/tree/v3).
149
129
 
150
- 🧩 **Integrates Seamlessly**
130
+ ## Why Schemathesis?
151
131
 
152
- - Works with popular API formats such as OpenAPI, GraphQL.
153
- - Easily integrate into your existing CI/CD workflows.
154
-
155
- 🔧 **Customizable and Extendable**
156
-
157
- - Tune the testing process using Python extensions.
158
- - Adjust the testing flow to suit your needs with rich configuration options.
159
-
160
- 🐞 **Simplifies Debugging**
161
-
162
- - Get detailed reports to identify and fix issues quickly.
163
- - Reproduce failing test cases with cURL commands.
164
-
165
- 🔬 **Proven by Research**
166
-
167
- - Validated through academic studies on API testing automation
168
- - Featured in [ICSE 2022 paper](https://ieeexplore.ieee.org/document/9793781) on semantics-aware fuzzing
169
- - Recognized in [ACM survey](https://dl.acm.org/doi/10.1145/3617175) as state-of-the-art RESTful API testing tool
132
+ - 📑 **Schema-Based Testing** - Transform API documentation into a comprehensive test suite
133
+ - 🚀 **Zero Configuration** - Begin testing immediately with a valid OpenAPI or GraphQL schema
134
+ - ⚙️ **CI-Ready** - Integrate API testing into existing pipelines without complex configuration
135
+ - 🛡️ **Effective Coverage** - Find edge cases no manual testing could uncover
136
+ - 🔬 **Research-Backed**: [Recognized](https://dl.acm.org/doi/10.1145/3617175) in [academic research](https://ieeexplore.ieee.org/document/9793781) as a state-of-the-art API testing tool
170
137
 
171
138
  ## Installation
172
139
 
173
- Use Schemathesis via Docker, or install it from [PyPI](https://pypi.org/project/schemathesis/)
174
-
175
140
  ```console
176
- # Via Docker.
177
- $ docker pull schemathesis/schemathesis:stable
141
+ # Using uv (recommended)
142
+ $ uv pip install schemathesis
178
143
 
179
- # With pip.
144
+ # Using pip
180
145
  $ pip install schemathesis
146
+
147
+ # Using Docker
148
+ $ docker pull schemathesis/schemathesis:stable
181
149
  ```
182
150
 
183
- ## Getting Started
151
+ ## Usage
184
152
 
185
- Schemathesis works as a standalone CLI:
153
+ ### Command Line
186
154
 
187
155
  ```console
188
- docker run schemathesis/schemathesis:stable
189
- run --checks all https://example.schemathesis.io/openapi.json
190
- # Or when installed with pip
191
- schemathesis run --checks all https://example.schemathesis.io/openapi.json
156
+ # Run tests against a schema URL
157
+ $ st run https://example.schemathesis.io/openapi.json
192
158
  ```
193
159
 
194
- Or a Python library:
160
+ ### Python Library
195
161
 
196
162
  ```python
197
163
  import schemathesis
@@ -204,36 +170,35 @@ def test_api(case):
204
170
  case.call_and_validate()
205
171
  ```
206
172
 
207
- See a complete working example project in the [/example](https://github.com/schemathesis/schemathesis/tree/master/example) directory.
208
-
209
- Schemathesis can be easily integrated into your CI/CD pipeline using GitHub Actions. Add this block to your GitHub Actions to run Schemathesis against your API:
173
+ ### CI/CD Integration
210
174
 
211
175
  ```yaml
212
- api-tests:
213
- runs-on: ubuntu-latest
214
- steps:
215
- - uses: schemathesis/action@v1
216
- with:
217
- schema: "https://example.schemathesis.io/openapi.json"
176
+ # GitHub Actions example
177
+ steps:
178
+ - uses: schemathesis/action@v1
179
+ with:
180
+ schema: "https://example.schemathesis.io/openapi.json"
218
181
  ```
219
182
 
220
- For more details, check out our [GitHub Action](https://github.com/schemathesis/action) repository or see our [GitHub Tutorial](https://docs.schemathesis.io/tutorials/github).
183
+ ## Documentation
184
+
185
+ 📚 **[Read the full documentation](https://schemathesis.readthedocs.io/)** for guides, examples, and reference material.
221
186
 
222
187
  ## Who's Using Schemathesis?
223
188
 
224
- Schemathesis is used by a number of projects and companies, including direct usage or integration into other tools:
189
+ Schemathesis is used by companies and open-source projects including:
225
190
 
226
- - Abstract Machines ([Magistrala](https://github.com/absmach/magistrala))
227
- - Bundesstelle für Open Data ([smard-api](https://github.com/bundesAPI/smard-api))
228
- - [CheckMK](https://github.com/Checkmk/checkmk)
229
- - Chronosphere.io ([Calyptia](https://github.com/chronosphereio/calyptia-api))
230
- - HXSecurity ([DongTai](https://github.com/HXSecurity/DongTai))
231
191
  - Netflix ([Dispatch](https://github.com/Netflix/dispatch))
232
- - [Pixie](https://github.com/pixie-io/pixie)
233
- - [Qdrant](https://github.com/qdrant/qdrant)
234
192
  - Spotify ([Backstage](https://github.com/backstage/backstage))
235
- - [Weechat](https://github.com/weechat/weechat)
236
193
  - WordPress ([OpenVerse](https://github.com/WordPress/openverse))
194
+ - Chronosphere.io ([Calyptia](https://github.com/chronosphereio/calyptia-api))
195
+ - [Qdrant](https://github.com/qdrant/qdrant)
196
+ - [Pixie](https://github.com/pixie-io/pixie)
197
+ - [CheckMK](https://github.com/Checkmk/checkmk)
198
+ - [Weechat](https://github.com/weechat/weechat)
199
+ - HXSecurity ([DongTai](https://github.com/HXSecurity/DongTai))
200
+ - Abstract Machines ([Magistrala](https://github.com/absmach/magistrala))
201
+ - Bundesstelle für Open Data ([smard-api](https://github.com/bundesAPI/smard-api))
237
202
 
238
203
  ## Testimonials
239
204
 
@@ -249,7 +214,7 @@ Schemathesis is used by a number of projects and companies, including direct usa
249
214
 
250
215
  ---
251
216
 
252
- "_The tool is absolutely amazing as it can do the negative scenario testing instead of me and much faster! Before I was doing the same tests in Postman client. But it's much slower and brings maintenance burden._"
217
+ "_The tool is amazing as it can test negative scenarios instead of me and much faster!_"
253
218
 
254
219
  <div>Luděk Nový - <strong>JetBrains</strong></div>
255
220
 
@@ -269,24 +234,15 @@ Schemathesis is used by a number of projects and companies, including direct usa
269
234
 
270
235
  ## Contributing
271
236
 
272
- We welcome contributions in code and are especially interested in learning about your use cases. Your input is essential for improving Schemathesis and directly influences future updates.
273
-
274
- ### How to Contribute
275
-
276
- 1. Discuss ideas and questions through [GitHub issues](https://github.com/schemathesis/schemathesis/issues) or on our [Discord channel](https://discord.gg/R9ASRAmHnA).
277
- 2. For code contributions, see our [contributing guidelines](https://github.com/schemathesis/schemathesis/blob/master/CONTRIBUTING.rst).
278
- 3. Share your experience and thoughts using [this feedback form](https://forms.gle/kJ4hSxc1Yp6Ga96t5).
279
-
280
- ### Why Your Input Matters
281
-
282
- - Enables us to develop useful features and fix bugs faster
283
- - Improves our test suite and documentation
237
+ We welcome contributions! Your input directly influences Schemathesis development.
284
238
 
285
- Thank you for contributing to making Schemathesis better! 👍
239
+ - Discuss ideas in [GitHub issues](https://github.com/schemathesis/schemathesis/issues) or our [Discord server](https://discord.gg/R9ASRAmHnA)
240
+ - See our [contributing guidelines](https://github.com/schemathesis/schemathesis/blob/master/CONTRIBUTING.rst) for code contributions
241
+ - Share your experience using [this feedback form](https://forms.gle/kJ4hSxc1Yp6Ga96t5)
286
242
 
287
243
  ## Get in Touch
288
244
 
289
- If you need assistance with integrating Schemathesis into your workflows or have specific questions, feel free to reach out at <a href="mailto:support@schemathesis.io">support@schemathesis.io</a>.
245
+ Need assistance with integration or have specific questions? Contact us at <a href="mailto:support@schemathesis.io">support@schemathesis.io</a>.
290
246
 
291
247
  ## Acknowledgements
292
248
 
@@ -12,13 +12,13 @@ schemathesis/cli/constants.py,sha256=rUixnqorraUFDtOu3Nmm1x_k0qbgmW9xW96kQB_fBCQ
12
12
  schemathesis/cli/core.py,sha256=Qm5xvpIIMwJDTeR3N3TjKhMCHV5d5Rp0UstVS2GjWgw,459
13
13
  schemathesis/cli/hooks.py,sha256=vTrA8EN99whRns5K5AnExViQ6WL9cak5RGsC-ZBEiJM,1458
14
14
  schemathesis/cli/commands/__init__.py,sha256=FFalEss3D7mnCRO0udtYb65onXSjQCCOv8sOSjqvTTM,1059
15
- schemathesis/cli/commands/run/__init__.py,sha256=5hxw_Xxn8cleTFF6eUBxeQBBW1Ztlmi3BLPCsAA_fqg,23871
16
- schemathesis/cli/commands/run/checks.py,sha256=-p6bzuc98kNR1VhkTI2s4xaJx-b5zYSMwdlhONwUhRM,3337
17
- schemathesis/cli/commands/run/context.py,sha256=fXt7kMZc-O1cddknb_NCs23SP7JZ05eVhEn00TxXass,7187
15
+ schemathesis/cli/commands/run/__init__.py,sha256=pLuXYxgO0z1CLZH_2P_uW8xeGOy1S2VtxLnNqKXanHk,23138
16
+ schemathesis/cli/commands/run/checks.py,sha256=lLtBCt6NhhQisrWo8aC6i0M3dSXlbjGWTTlOyjzatks,3278
17
+ schemathesis/cli/commands/run/context.py,sha256=pUwSlS7UwW2cq1nJXfKZFEaWDipsQAElCO4tdv1qYJA,7739
18
18
  schemathesis/cli/commands/run/events.py,sha256=Dj-xvIr-Hkms8kvh4whNwKSk1Q2Hx4NIENi_4A8nQO8,1224
19
- schemathesis/cli/commands/run/executor.py,sha256=AbLqlTBsbIFNoTlUZZTcChAmCeA-1iony-XgQU8g6Gw,5405
19
+ schemathesis/cli/commands/run/executor.py,sha256=lKQZswH7vLsKCUNdDL8IOwJYsUicyPxRJ3vXOi1pwAk,5446
20
20
  schemathesis/cli/commands/run/filters.py,sha256=MdymOZtzOolvXCNBIdfHbBbWEXVF7Se0mmDpy3sVWu4,7411
21
- schemathesis/cli/commands/run/hypothesis.py,sha256=kUPm8W5JB2Njt9ZvrWsrskwx33n3qYh6Xqkp0YBGY_0,4000
21
+ schemathesis/cli/commands/run/hypothesis.py,sha256=hdEHim_Hc2HwCGxAiRTf4t2OfQf0IeCUhyjNT_btB1o,2553
22
22
  schemathesis/cli/commands/run/loaders.py,sha256=VedoeIE1tgFBqVokWxOoUReAjBl-Zhx87RjCEBtCVfs,4840
23
23
  schemathesis/cli/commands/run/reports.py,sha256=OjyakiV0lpNDBZb1xsb_2HmLtcqhTThPYMpJGXyNNO8,2147
24
24
  schemathesis/cli/commands/run/validation.py,sha256=7fvLeDREQ9FTV8ZMJRnCdycD858j21k7j56ow4_iIcY,12789
@@ -26,7 +26,7 @@ schemathesis/cli/commands/run/handlers/__init__.py,sha256=TPZ3KdGi8m0fjlN0GjA31M
26
26
  schemathesis/cli/commands/run/handlers/base.py,sha256=yDsTtCiztLksfk7cRzg8JlaAVOfS-zwK3tsJMOXAFyc,530
27
27
  schemathesis/cli/commands/run/handlers/cassettes.py,sha256=SVk13xPhsQduCpgvvBwzEMDNTju-SHQCW90xTQ6iL1U,18525
28
28
  schemathesis/cli/commands/run/handlers/junitxml.py,sha256=c24UiwXqRCnv2eWQWEaNXLOghMI9JtGoZ9RTJY4ao6M,2350
29
- schemathesis/cli/commands/run/handlers/output.py,sha256=O95Ap8_HtnNtNPf9kaV-rNa7mGG6_A06ySlMUhgNwVg,54505
29
+ schemathesis/cli/commands/run/handlers/output.py,sha256=n25QDGvYMXPKRPHBDckkDVwkkieY3Gq4HHSG0h3paTA,58800
30
30
  schemathesis/cli/ext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
31
  schemathesis/cli/ext/fs.py,sha256=OA3mRzra4rq3NyDTcBvlRh0WJrh4ByN-QQ8loI04m88,408
32
32
  schemathesis/cli/ext/groups.py,sha256=kQ37t6qeArcKaY2y5VxyK3_KwAkBKCVm58IYV8gewds,2720
@@ -34,7 +34,7 @@ schemathesis/cli/ext/options.py,sha256=gBjfYPoiSoxCymWq41x0oKcQ2frv1fQnweETVpYiI
34
34
  schemathesis/contrib/__init__.py,sha256=wxpX86xrEGRAS3f7eugQfKVbnqV6ZfOqFBS_DmWxOok,120
35
35
  schemathesis/contrib/openapi/__init__.py,sha256=-7mBZ9RQj0EGzzmC-HKiT5ZslwHcoWFqCVpRG0GHO_o,162
36
36
  schemathesis/contrib/openapi/fill_missing_examples.py,sha256=BfBpuy3vCKbE_uILqPXnm7kxEDopAr5tNQwP5E9xX8A,585
37
- schemathesis/core/__init__.py,sha256=Lag-8jUqWpcRdiTUtKS3v9HJZgwRy_JS854ZA7wh0W4,1573
37
+ schemathesis/core/__init__.py,sha256=4SLVPpUZgZYABL6QPVRtanMemibKxTQEYcp4LFu4Jco,1761
38
38
  schemathesis/core/compat.py,sha256=Lflo6z-nQ6S4uKZINc4Fr90pd3LTN6cIG9HJJmmaHeY,754
39
39
  schemathesis/core/control.py,sha256=IzwIc8HIAEMtZWW0Q0iXI7T1niBpjvcLlbuwOSmy5O8,130
40
40
  schemathesis/core/curl.py,sha256=yuaCe_zHLGwUjEeloQi6W3tOA3cGdnHDNI17-5jia0o,1723
@@ -56,22 +56,22 @@ schemathesis/core/version.py,sha256=O-6yFbNocbD4RDwiBZLborxTp54htyKxBWTqpZDnPvg,
56
56
  schemathesis/core/output/__init__.py,sha256=lhVc4OzzxCsmvEPPvg1k8x19iPf_HF-9YonTaqsxvx8,2015
57
57
  schemathesis/core/output/sanitization.py,sha256=EODHJMHD8gqlIA0Yqs1OnElZ2JyNxjvQ0WWErZV1K3s,6210
58
58
  schemathesis/engine/__init__.py,sha256=xncZMXY8S-v4mrfnW4CK6-RQ0S0bigfLDJScpQysblE,831
59
- schemathesis/engine/config.py,sha256=vWwtaWuSLvE-w0S9n4_MlJADjN58zlgSp84ZQS2z0ls,1919
59
+ schemathesis/engine/config.py,sha256=92Ud_aSTj-xi4Mwf8gej_gcvzjemH_ISjHQiXGGKskA,1885
60
60
  schemathesis/engine/context.py,sha256=HeLX-0aqSAbXJe_ZlkqVfg3QlhmbCrazbb9-ZPbi0h0,3723
61
61
  schemathesis/engine/control.py,sha256=QKUOs5VMphe7EcAIro_DDo9ZqdOU6ZVwTU1gMNndHWw,1006
62
- schemathesis/engine/core.py,sha256=_Z89tc_aWQ0kHajVXmoTaEbIRYeERvb1s0rD82XpYxg,5085
62
+ schemathesis/engine/core.py,sha256=DfulRMVTivmZj-wwLekIhuSzLsFnuVPtSg7j9HyWdz0,5536
63
63
  schemathesis/engine/errors.py,sha256=8PHYsuq2qIEJHm2FDf_UnWa4IDc-DRFTPckLAr22yhE,16895
64
- schemathesis/engine/events.py,sha256=7tpxCxptKx_WvcFgv9_6v0E-5wiQfDs1O5bsOH46xb8,5989
64
+ schemathesis/engine/events.py,sha256=gslRAWQKMPqBCQzLDS4wAbsKcVuONSy5SPqimJJJYT4,6250
65
65
  schemathesis/engine/recorder.py,sha256=K3HfMARrT5mPWXPnYebjjcq5CcsBRhMrtZwEL9_Lvtg,8432
66
- schemathesis/engine/phases/__init__.py,sha256=HZmlOjGvtDkfTwAw2rJFcfsJ2qg2h973l4zDy3AzsQg,2034
66
+ schemathesis/engine/phases/__init__.py,sha256=3p_T3JYBFOtrwtgmMM7J-6a41QJgk83dUtm7NKcVl3o,2490
67
67
  schemathesis/engine/phases/probes.py,sha256=3M9g3E7CXbDDK_8inuvkRZibCCcoO2Ce5U3lnyTeWXQ,5131
68
68
  schemathesis/engine/phases/stateful/__init__.py,sha256=lWo2RLrutNblHvohTzofQqL22GORwBRA8bf6jvLuGPg,2391
69
69
  schemathesis/engine/phases/stateful/_executor.py,sha256=m1ZMqFUPc4Hdql10l0gF3tpP4JOImSA-XeBd4jg3Ll8,12443
70
70
  schemathesis/engine/phases/stateful/context.py,sha256=SKWsok-tlWbUDagiUmP7cLNW6DsgFDc_Afv0vQfWv6c,2964
71
- schemathesis/engine/phases/unit/__init__.py,sha256=R6ZLed54p_kXUE_tVF60ucj8J6V04--Tf6smm4qavFg,7468
72
- schemathesis/engine/phases/unit/_executor.py,sha256=LjdR6pcvtqCV3nXszU_IOBtR-lnRGKg0aLGDwz9PRVM,13016
73
- schemathesis/engine/phases/unit/_pool.py,sha256=01xRGJnmfLqGBH-f3nQEDv7vOufmen5ZCiXwNLpkxOw,2210
74
- schemathesis/experimental/__init__.py,sha256=36H1vLQhrw4SMD_jx76Wt07PHneELRDY1jfBSh7VxU0,2257
71
+ schemathesis/engine/phases/unit/__init__.py,sha256=LcBQpGNPeEFB9XPGpcHBcH-C7nF-e8bZNPop9PIfiKA,7861
72
+ schemathesis/engine/phases/unit/_executor.py,sha256=buMEr7e01SFSeNuEQNGMf4hoiLxX9_sp0JhH4LBAk9M,12928
73
+ schemathesis/engine/phases/unit/_pool.py,sha256=9OgmFd-ov1AAvcZGquK40PXkGLp7f2qCjZoPZuoZl4A,2529
74
+ schemathesis/experimental/__init__.py,sha256=jYY3Mq6okqTRTMudPzcaT0JVjzJW5IN_ZVJdGU0stBs,2011
75
75
  schemathesis/generation/__init__.py,sha256=2htA0TlQee6AvQmLl1VNxEptRDqvPjksXKJLMVLAJng,1580
76
76
  schemathesis/generation/case.py,sha256=Rt5MCUtPVYVQzNyjUx8magocPJpHV1svyuqQSTwUE-I,7306
77
77
  schemathesis/generation/coverage.py,sha256=hyDb465tBoCWE7nI-ZJjhTUzk7f2WDufaadWdSAkdr0,39276
@@ -80,7 +80,7 @@ schemathesis/generation/modes.py,sha256=t_EvKr2aOXYMsEfdMu4lLF4KCGcX1LVVyvzTkcpJ
80
80
  schemathesis/generation/overrides.py,sha256=FhqcFoliEvgW6MZyFPYemfLgzKt3Miy8Cud7OMOCb7g,3045
81
81
  schemathesis/generation/targets.py,sha256=_rN2qgxTE2EfvygiN-Fy3WmDnRH0ERohdx3sKRDaYhU,2120
82
82
  schemathesis/generation/hypothesis/__init__.py,sha256=Rl7QwvMBMJI7pBqTydplX6bXC420n0EGQHVm-vZgaYQ,1204
83
- schemathesis/generation/hypothesis/builder.py,sha256=K8pA5hFkx7sXSFIR8zX7ltYCwJHx3CFcq4Rm12ou1wk,24650
83
+ schemathesis/generation/hypothesis/builder.py,sha256=lAxBePbfqGsp6iPjjXeDL-X8RnOgUhsgpYQpeKc1VKg,29292
84
84
  schemathesis/generation/hypothesis/examples.py,sha256=6eGaKUEC3elmKsaqfKj1sLvM8EHc-PWT4NRBq4NI0Rs,1409
85
85
  schemathesis/generation/hypothesis/given.py,sha256=sTZR1of6XaHAPWtHx2_WLlZ50M8D5Rjux0GmWkWjDq4,2337
86
86
  schemathesis/generation/hypothesis/reporting.py,sha256=uDVow6Ya8YFkqQuOqRsjbzsbyP4KKfr3jA7ZaY4FuKY,279
@@ -91,15 +91,15 @@ schemathesis/graphql/__init__.py,sha256=_eO6MAPHGgiADVGRntnwtPxmuvk666sAh-FAU4cG
91
91
  schemathesis/graphql/checks.py,sha256=IADbxiZjgkBWrC5yzHDtohRABX6zKXk5w_zpWNwdzYo,3186
92
92
  schemathesis/graphql/loaders.py,sha256=96R_On1jFvsNuLwqXnO3_TTpsYhdCv0LAmR5jWRXXnY,4756
93
93
  schemathesis/openapi/__init__.py,sha256=-KcsSAM19uOM0N5J4s-yTnQ1BFsptYhW1E51cEf6kVM,311
94
- schemathesis/openapi/checks.py,sha256=Rt6uX0yEVIG30YJdQeQKLu-9XZ1Bx-In1LCautTcghg,10760
94
+ schemathesis/openapi/checks.py,sha256=i26qtVqsNUb46Aqu191qWK5lVC51KK6ezbhm1rSSyr4,10781
95
95
  schemathesis/openapi/loaders.py,sha256=jskoCnMgpjg_cpn17FRI4oDUpMdsMYjxfXdRPHYnPqs,6472
96
96
  schemathesis/openapi/generation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
97
97
  schemathesis/openapi/generation/filters.py,sha256=MB2t_k6OVc2Rt6qXUrV-u-3sDg5wX6c0Mli9WgfMUF4,2001
98
98
  schemathesis/pytest/__init__.py,sha256=7W0q-Thcw03IAQfXE_Mo8JPZpUdHJzfu85fjK1ZdfQM,88
99
99
  schemathesis/pytest/control_flow.py,sha256=F8rAPsPeNv_sJiJgbZYtTpwKWjauZmqFUaKroY2GmQI,217
100
- schemathesis/pytest/lazy.py,sha256=tPW8_VfMWy4vqk-XgzswqvL9jCYxhIyYieq1HFf4UTw,10480
100
+ schemathesis/pytest/lazy.py,sha256=g7DpOeQNsjXC03FCG5e1L65iz3zE48qAyaqG81HzCZY,12028
101
101
  schemathesis/pytest/loaders.py,sha256=oQJ78yyuIm3Ye9X7giVjDB1vYfaW5UY5YuhaTLm_ZFU,266
102
- schemathesis/pytest/plugin.py,sha256=kon8stIVLCySkeyTTk0gBunEs5sUkXwQY8Nviwb-dxA,12303
102
+ schemathesis/pytest/plugin.py,sha256=RDOuT25Uotese7W-SD3Pu-nb7zdnaPbyPOoJSkJKSoQ,12379
103
103
  schemathesis/python/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
104
104
  schemathesis/python/asgi.py,sha256=5PyvuTBaivvyPUEi3pwJni91K1kX5Zc0u9c6c1D8a1Q,287
105
105
  schemathesis/python/wsgi.py,sha256=uShAgo_NChbfYaV1117e6UHp0MTg7jaR0Sy_to3Jmf8,219
@@ -113,19 +113,19 @@ schemathesis/specs/graphql/validation.py,sha256=-W1Noc1MQmTb4RX-gNXMeU2qkgso4mzV
113
113
  schemathesis/specs/openapi/__init__.py,sha256=C5HOsfuDJGq_3mv8CRBvRvb0Diy1p0BFdqyEXMS-loE,238
114
114
  schemathesis/specs/openapi/_cache.py,sha256=HpglmETmZU0RCHxp3DO_sg5_B_nzi54Zuw9vGzzYCxY,4295
115
115
  schemathesis/specs/openapi/_hypothesis.py,sha256=n_39iyz1rt2EdSe-Lyr-3sOIEyJIthnCVR4tGUUvH1c,21328
116
- schemathesis/specs/openapi/checks.py,sha256=Fk2_2MdKjhMuHGkWtm_lu_8c8DenF9ttZfDGN9nPnj0,27697
116
+ schemathesis/specs/openapi/checks.py,sha256=m3n5N3_iZcS7inJojW47FF6dfbUQzrBH-bXwsCAOyhM,27737
117
117
  schemathesis/specs/openapi/constants.py,sha256=JqM_FHOenqS_MuUE9sxVQ8Hnw0DNM8cnKDwCwPLhID4,783
118
118
  schemathesis/specs/openapi/converter.py,sha256=lil8IewM5j8tvt4lpA9g_KITvIwx1M96i45DNSHNjoc,3505
119
119
  schemathesis/specs/openapi/definitions.py,sha256=8htclglV3fW6JPBqs59lgM4LnA25Mm9IptXBPb_qUT0,93949
120
- schemathesis/specs/openapi/examples.py,sha256=Uy6naFBq-m1vo_18j4KuZBUYc9qKrBk19jBCWT7tnRg,20464
120
+ schemathesis/specs/openapi/examples.py,sha256=Xvjp60QUcLaeGsJRbi2i6XM15_4uO0ceVoClIaJehiE,21062
121
121
  schemathesis/specs/openapi/formats.py,sha256=ViVF3aFeFI1ctwGQbiRDXhU3so82P0BCaF2aDDbUUm8,2816
122
122
  schemathesis/specs/openapi/media_types.py,sha256=ADedOaNWjbAtAekyaKmNj9fY6zBTeqcNqBEjN0EWNhI,1014
123
123
  schemathesis/specs/openapi/parameters.py,sha256=hv1reNpSjVuzFbtMpSTwWZ75zcWTOy5ZE0ah6AVEqAo,14565
124
- schemathesis/specs/openapi/patterns.py,sha256=6qNZRYQkHtJ98_JMjwhqIGpeR4aR7rlxcCmr1nOHMzk,11258
124
+ schemathesis/specs/openapi/patterns.py,sha256=NLnGybcana_kYLVKVEjkEyAzdClAV0xKe4Oy4NVayMI,12834
125
125
  schemathesis/specs/openapi/references.py,sha256=YjD1xMlaYS7xLt6PrrVS20R72ZWHuFZFTa8Llzf54Rg,8808
126
126
  schemathesis/specs/openapi/schemas.py,sha256=VSeacEAVJJ6EKJ-llwOaX4aalzUTXyWP8s4wbxTqtWc,54720
127
127
  schemathesis/specs/openapi/security.py,sha256=6UWYMhL-dPtkTineqqBFNKca1i4EuoTduw-EOLeE0aQ,7149
128
- schemathesis/specs/openapi/serialization.py,sha256=JFxMqCr8YWwPT4BVrbvVytcAmkzGXyL1_Q1xR1JKBPs,11464
128
+ schemathesis/specs/openapi/serialization.py,sha256=VdDLmeHqxlWM4cxQQcCkvrU6XurivolwEEaT13ohelA,11972
129
129
  schemathesis/specs/openapi/utils.py,sha256=ER4vJkdFVDIE7aKyxyYatuuHVRNutytezgE52pqZNE8,900
130
130
  schemathesis/specs/openapi/expressions/__init__.py,sha256=hfuRtXD75tQFhzSo6QgDZ3zByyWeZRKevB8edszAVj4,2272
131
131
  schemathesis/specs/openapi/expressions/errors.py,sha256=YLVhps-sYcslgVaahfcUYxUSHlIfWL-rQMeT5PZSMZ8,219
@@ -143,11 +143,11 @@ schemathesis/specs/openapi/stateful/links.py,sha256=8oHpmb-yBa3kZKoCv9ytndpOp80d
143
143
  schemathesis/transport/__init__.py,sha256=z-mRNSOlMBKwQyaEIhpmYv0plWTmK5dJqc9UmQOry80,3949
144
144
  schemathesis/transport/asgi.py,sha256=qTClt6oT_xUEWnRHokACN_uqCNNUZrRPT6YG0PjbElY,926
145
145
  schemathesis/transport/prepare.py,sha256=qQ6zXBw5NN2AIM0bzLAc5Ryc3dmMb0R6xN14lnR49pU,3826
146
- schemathesis/transport/requests.py,sha256=OObRvcTL72-BZ7AfuDUrZZU9nZtfBqr22oF8nkzaOLE,8389
146
+ schemathesis/transport/requests.py,sha256=j5wI1Uo_PnVuP1eV8l6ddsXosyxAPQ1mLSyWEZmTI9I,8747
147
147
  schemathesis/transport/serialization.py,sha256=jIMra1LqRGav0OX3Hx7mvORt38ll4cd2DKit2D58FN0,10531
148
148
  schemathesis/transport/wsgi.py,sha256=RWSuUXPrl91GxAy8a4jyNNozOWVMRBxKx_tljlWA_Lo,5697
149
- schemathesis-4.0.0a4.dist-info/METADATA,sha256=dCVDX4dbQi5yTEg-CRNkZBEuWl3s0lDOKs6w-BNakzI,12292
150
- schemathesis-4.0.0a4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
151
- schemathesis-4.0.0a4.dist-info/entry_points.txt,sha256=hiK3un-xfgPdwj9uj16YVDtTNpO128bmk0U82SMv8ZQ,152
152
- schemathesis-4.0.0a4.dist-info/licenses/LICENSE,sha256=PsPYgrDhZ7g9uwihJXNG-XVb55wj2uYhkl2DD8oAzY0,1103
153
- schemathesis-4.0.0a4.dist-info/RECORD,,
149
+ schemathesis-4.0.0a6.dist-info/METADATA,sha256=W8GlnQVnH1VOEqPqS-ElR_yk0RvdB9TOXTxHy_p3zTU,10427
150
+ schemathesis-4.0.0a6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
151
+ schemathesis-4.0.0a6.dist-info/entry_points.txt,sha256=hiK3un-xfgPdwj9uj16YVDtTNpO128bmk0U82SMv8ZQ,152
152
+ schemathesis-4.0.0a6.dist-info/licenses/LICENSE,sha256=2Ve4J8v5jMQAWrT7r1nf3bI8Vflk3rZVQefiF2zpxwg,1121
153
+ schemathesis-4.0.0a6.dist-info/RECORD,,
@@ -1,7 +1,7 @@
1
1
  MIT License
2
2
 
3
3
  Copyright (c) 2019 Kiwi.com
4
- Copyright (c) 2020-2022 Dmitry Dygalo
4
+ Copyright (c) 2020-2025 Dmitry Dygalo & Schemathesis.io
5
5
 
6
6
  Permission is hereby granted, free of charge, to any person obtaining a copy
7
7
  of this software and associated documentation files (the "Software"), to deal