schemathesis 4.2.2__py3-none-any.whl → 4.3.1__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 (28) hide show
  1. schemathesis/config/__init__.py +8 -1
  2. schemathesis/config/_phases.py +14 -3
  3. schemathesis/config/schema.json +2 -1
  4. schemathesis/core/jsonschema/bundler.py +3 -2
  5. schemathesis/core/transforms.py +14 -6
  6. schemathesis/engine/context.py +35 -2
  7. schemathesis/generation/hypothesis/__init__.py +3 -1
  8. schemathesis/generation/hypothesis/builder.py +10 -2
  9. schemathesis/openapi/checks.py +13 -1
  10. schemathesis/specs/openapi/adapter/parameters.py +3 -3
  11. schemathesis/specs/openapi/adapter/protocol.py +2 -0
  12. schemathesis/specs/openapi/adapter/responses.py +29 -7
  13. schemathesis/specs/openapi/adapter/v2.py +2 -0
  14. schemathesis/specs/openapi/adapter/v3_0.py +2 -0
  15. schemathesis/specs/openapi/adapter/v3_1.py +2 -0
  16. schemathesis/specs/openapi/stateful/dependencies/__init__.py +88 -0
  17. schemathesis/specs/openapi/stateful/dependencies/inputs.py +182 -0
  18. schemathesis/specs/openapi/stateful/dependencies/models.py +270 -0
  19. schemathesis/specs/openapi/stateful/dependencies/naming.py +345 -0
  20. schemathesis/specs/openapi/stateful/dependencies/outputs.py +34 -0
  21. schemathesis/specs/openapi/stateful/dependencies/resources.py +282 -0
  22. schemathesis/specs/openapi/stateful/dependencies/schemas.py +420 -0
  23. schemathesis/specs/openapi/stateful/inference.py +2 -1
  24. {schemathesis-4.2.2.dist-info → schemathesis-4.3.1.dist-info}/METADATA +1 -1
  25. {schemathesis-4.2.2.dist-info → schemathesis-4.3.1.dist-info}/RECORD +28 -21
  26. {schemathesis-4.2.2.dist-info → schemathesis-4.3.1.dist-info}/WHEEL +0 -0
  27. {schemathesis-4.2.2.dist-info → schemathesis-4.3.1.dist-info}/entry_points.txt +0 -0
  28. {schemathesis-4.2.2.dist-info → schemathesis-4.3.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,420 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from typing import TYPE_CHECKING, Any, Callable, Mapping
5
+
6
+ from hypothesis_jsonschema._canonicalise import (
7
+ SCHEMA_KEYS as SCHEMA_KEYS_TUPLE,
8
+ )
9
+ from hypothesis_jsonschema._canonicalise import (
10
+ SCHEMA_OBJECT_KEYS as SCHEMA_OBJECT_KEYS_TUPLE,
11
+ )
12
+ from hypothesis_jsonschema._canonicalise import canonicalish, merged
13
+
14
+ from schemathesis.core.jsonschema import ALL_KEYWORDS
15
+ from schemathesis.core.jsonschema.bundler import BUNDLE_STORAGE_KEY, bundle
16
+ from schemathesis.core.jsonschema.types import JsonSchema, JsonSchemaObject
17
+ from schemathesis.core.transforms import encode_pointer
18
+ from schemathesis.specs.openapi.adapter.parameters import resource_name_from_ref
19
+ from schemathesis.specs.openapi.adapter.references import maybe_resolve
20
+ from schemathesis.specs.openapi.stateful.dependencies import naming
21
+
22
+ if TYPE_CHECKING:
23
+ from schemathesis.core.compat import RefResolver
24
+
25
+ ROOT_POINTER = "/"
26
+ SCHEMA_KEYS = frozenset(SCHEMA_KEYS_TUPLE)
27
+ SCHEMA_OBJECT_KEYS = frozenset(SCHEMA_OBJECT_KEYS_TUPLE)
28
+
29
+
30
+ def resolve_all_refs(schema: JsonSchemaObject) -> dict[str, Any]:
31
+ if not schema:
32
+ return schema
33
+ bundled = schema.get(BUNDLE_STORAGE_KEY, {})
34
+
35
+ resolved_cache: dict[str, dict[str, Any]] = {}
36
+
37
+ def resolve(ref: str) -> dict[str, Any]:
38
+ # All references here are bundled, therefore it is safe to avoid full reference resolving
39
+ if ref in resolved_cache:
40
+ return resolved_cache[ref]
41
+ key = ref.split("/")[-1]
42
+ # No clone needed, as it will be cloned inside `merged`
43
+ result = resolve_all_refs_inner(bundled[key], resolve=resolve)
44
+ resolved_cache[ref] = result
45
+ return result
46
+
47
+ return resolve_all_refs_inner(schema, resolve=resolve)
48
+
49
+
50
+ def resolve_all_refs_inner(schema: JsonSchema, *, resolve: Callable[[str], dict[str, Any]]) -> dict[str, Any]:
51
+ if schema is True:
52
+ return {}
53
+ if schema is False:
54
+ return {"not": {}}
55
+ if not schema:
56
+ return schema
57
+
58
+ reference = schema.get("$ref")
59
+ if reference is not None:
60
+ resolved = resolve(reference)
61
+ if len(schema) == 1 or (len(schema) == 2 and BUNDLE_STORAGE_KEY in schema):
62
+ return resolved
63
+ del schema["$ref"]
64
+ schema.pop(BUNDLE_STORAGE_KEY, None)
65
+ schema.pop("example", None)
66
+ return merged([resolve_all_refs_inner(schema, resolve=resolve), resolved]) # type: ignore
67
+
68
+ for key, value in schema.items():
69
+ if key in SCHEMA_KEYS:
70
+ if isinstance(value, list):
71
+ schema[key] = [resolve_all_refs_inner(v, resolve=resolve) if isinstance(v, dict) else v for v in value]
72
+ elif isinstance(value, dict):
73
+ schema[key] = resolve_all_refs_inner(value, resolve=resolve)
74
+ if key in SCHEMA_OBJECT_KEYS:
75
+ schema[key] = {
76
+ k: resolve_all_refs_inner(v, resolve=resolve) if isinstance(v, dict) else v for k, v in value.items()
77
+ }
78
+ return schema
79
+
80
+
81
+ def canonicalize(schema: dict[str, Any], resolver: RefResolver) -> Mapping[str, Any]:
82
+ """Transform the input schema into its canonical-ish form."""
83
+ # Canonicalisation in `hypothesis_jsonschema` requires all references to be resovable and non-recursive
84
+ # On the Schemathesis side bundling solves this problem
85
+ bundled = bundle(schema, resolver, inline_recursive=True)
86
+ canonicalized = canonicalish(bundled)
87
+ resolved = resolve_all_refs(canonicalized)
88
+ resolved.pop(BUNDLE_STORAGE_KEY, None)
89
+ if "allOf" in resolved or "anyOf" in resolved or "oneOf" in resolved:
90
+ return canonicalish(resolved)
91
+ return resolved
92
+
93
+
94
+ def try_unwrap_composition(schema: Mapping[str, Any], resolver: RefResolver) -> Mapping[str, Any]:
95
+ """Unwrap oneOf/anyOf if we can safely extract a single schema."""
96
+ keys = ("anyOf", "oneOf")
97
+ composition_key = None
98
+ for key in keys:
99
+ if key in schema:
100
+ composition_key = key
101
+ break
102
+
103
+ if composition_key is None:
104
+ return schema
105
+
106
+ alternatives = schema[composition_key]
107
+
108
+ if not isinstance(alternatives, list):
109
+ return schema
110
+
111
+ # Filter to interesting alternatives
112
+ interesting = _filter_composition_alternatives(alternatives, resolver)
113
+
114
+ # If no interesting alternatives, return original
115
+ if not interesting:
116
+ return schema
117
+
118
+ # If exactly one interesting alternative, unwrap it
119
+ if len(interesting) == 1:
120
+ return interesting[0]
121
+
122
+ # Pick the first one
123
+ # TODO: Support multiple alternatives
124
+ return interesting[0]
125
+
126
+
127
+ def try_unwrap_all_of(schema: Mapping[str, Any]) -> Mapping[str, Any]:
128
+ alternatives = schema.get("allOf")
129
+ if not isinstance(alternatives, list):
130
+ return schema
131
+
132
+ interesting = []
133
+
134
+ for subschema in alternatives:
135
+ if isinstance(subschema, dict) and _is_interesting_schema(subschema):
136
+ interesting.append(subschema)
137
+
138
+ if len(interesting) == 1:
139
+ return interesting[0]
140
+ return schema
141
+
142
+
143
+ def _filter_composition_alternatives(alternatives: list[dict], resolver: RefResolver) -> list[dict]:
144
+ """Filter oneOf/anyOf alternatives to keep only interesting schemas."""
145
+ interesting = []
146
+
147
+ for alt_schema in alternatives:
148
+ _, resolved = maybe_resolve(alt_schema, resolver, "")
149
+
150
+ if _is_interesting_schema(resolved):
151
+ # Keep original (with $ref)
152
+ interesting.append(alt_schema)
153
+
154
+ return interesting
155
+
156
+
157
+ def _is_interesting_schema(schema: Mapping[str, Any]) -> bool:
158
+ """Check if a schema represents interesting structured data."""
159
+ # Has $ref - definitely interesting (references a named schema)
160
+ if "$ref" in schema:
161
+ return True
162
+
163
+ ty = schema.get("type")
164
+
165
+ # Primitives are not interesting
166
+ if ty in {"string", "number", "integer", "boolean", "null"}:
167
+ return False
168
+
169
+ # Arrays - check items
170
+ if ty == "array":
171
+ items = schema.get("items")
172
+ if not isinstance(items, dict):
173
+ return False
174
+ # Recursively check if items are interesting
175
+ return _is_interesting_schema(items)
176
+
177
+ # allOf/anyOf/oneOf - interesting (composition)
178
+ if any(key in schema for key in ["allOf", "anyOf", "oneOf"]):
179
+ return True
180
+
181
+ # Objects (or untyped) - check if they have any keywords
182
+ return bool(set(schema).intersection(ALL_KEYWORDS))
183
+
184
+
185
+ @dataclass
186
+ class UnwrappedSchema:
187
+ """Result of wrapper pattern detection."""
188
+
189
+ pointer: str
190
+ schema: Mapping[str, Any]
191
+ ref: str | None
192
+
193
+ __slots__ = ("pointer", "schema", "ref")
194
+
195
+
196
+ def unwrap_schema(
197
+ schema: Mapping[str, Any], path: str, parent_ref: str | None, resolver: RefResolver
198
+ ) -> UnwrappedSchema:
199
+ # Array at root
200
+ if schema.get("type") == "array":
201
+ return UnwrappedSchema(pointer="/", schema=schema, ref=None)
202
+
203
+ properties = schema.get("properties", {})
204
+
205
+ # HAL _embedded (Spring-specific)
206
+ hal_field = _detect_hal_embedded(schema)
207
+ if hal_field:
208
+ embedded_schema = properties["_embedded"]
209
+ _, resolved_embedded = maybe_resolve(embedded_schema, resolver, "")
210
+ resource_schema = resolved_embedded.get("properties", {}).get(hal_field, {})
211
+ _, resolved_resource = maybe_resolve(resource_schema, resolver, "")
212
+
213
+ return UnwrappedSchema(
214
+ pointer=f"/_embedded/{encode_pointer(hal_field)}", schema=resolved_resource, ref=resource_schema.get("$ref")
215
+ )
216
+
217
+ # Pagination wrapper
218
+ array_field = _is_pagination_wrapper(schema=schema, path=path, parent_ref=parent_ref, resolver=resolver)
219
+ if array_field:
220
+ array_schema = properties[array_field]
221
+ _, resolved = maybe_resolve(array_schema, resolver, "")
222
+ pointer = f"/{encode_pointer(array_field)}"
223
+
224
+ # Try to unwrap one more time
225
+ if resolved.get("type") == "array" or "items" in resolved:
226
+ nested_items = resolved.get("items")
227
+ if isinstance(nested_items, dict):
228
+ _, resolved_items = maybe_resolve(nested_items, resolver, "")
229
+ external_tag = _detect_externally_tagged_pattern(resolved_items, path)
230
+ if external_tag:
231
+ nested_properties = resolved_items["properties"][external_tag]
232
+ _, resolved = maybe_resolve(nested_properties, resolver, "")
233
+ pointer += f"/{encode_pointer(external_tag)}"
234
+
235
+ return UnwrappedSchema(pointer=pointer, schema=resolved, ref=array_schema.get("$ref"))
236
+
237
+ # External tag
238
+ external_tag = _detect_externally_tagged_pattern(schema, path)
239
+ if external_tag:
240
+ tagged_schema = properties[external_tag]
241
+ _, resolved_tagged = maybe_resolve(tagged_schema, resolver, "")
242
+
243
+ resolved = try_unwrap_all_of(resolved_tagged)
244
+ ref = resolved.get("$ref") or resolved_tagged.get("$ref") or tagged_schema.get("$ref")
245
+
246
+ _, resolved = maybe_resolve(resolved, resolver, "")
247
+ return UnwrappedSchema(pointer=f"/{encode_pointer(external_tag)}", schema=resolved, ref=ref)
248
+
249
+ # No wrapper - single object at root
250
+ return UnwrappedSchema(pointer="/", schema=schema, ref=schema.get("$ref"))
251
+
252
+
253
+ def _detect_hal_embedded(schema: Mapping[str, Any]) -> str | None:
254
+ """Detect HAL _embedded pattern.
255
+
256
+ Spring Data REST uses: {_embedded: {users: [...]}}
257
+ """
258
+ properties = schema.get("properties", {})
259
+ embedded = properties.get("_embedded")
260
+
261
+ if not isinstance(embedded, dict):
262
+ return None
263
+
264
+ embedded_properties = embedded.get("properties", {})
265
+
266
+ # Find array properties in _embedded
267
+ for name, subschema in embedded_properties.items():
268
+ if isinstance(subschema, dict) and subschema.get("type") == "array":
269
+ # Found array in _embedded
270
+ return name
271
+
272
+ return None
273
+
274
+
275
+ def _is_pagination_wrapper(
276
+ schema: Mapping[str, Any], path: str, parent_ref: str | None, resolver: RefResolver
277
+ ) -> str | None:
278
+ """Detect if schema is a pagination wrapper."""
279
+ properties = schema.get("properties", {})
280
+
281
+ if not properties:
282
+ return None
283
+
284
+ metadata_fields = frozenset(["links", "errors"])
285
+
286
+ # Find array properties
287
+ arrays = []
288
+ for name, subschema in properties.items():
289
+ if name in metadata_fields:
290
+ continue
291
+ if isinstance(subschema, dict):
292
+ _, subschema = maybe_resolve(subschema, resolver, "")
293
+ if subschema.get("type") == "array":
294
+ arrays.append(name)
295
+
296
+ # Must have exactly one array property
297
+ if len(arrays) != 1:
298
+ return None
299
+
300
+ array_field = arrays[0]
301
+
302
+ # Check if array field name matches common patterns
303
+ common_data_fields = {"data", "items", "results", "value", "content", "elements", "records", "list"}
304
+
305
+ if parent_ref:
306
+ resource_name = resource_name_from_ref(parent_ref)
307
+ resource_name = naming.strip_affixes(resource_name, ["get", "create", "list", "delete"], ["response"])
308
+ common_data_fields.add(resource_name.lower())
309
+
310
+ if array_field.lower() not in common_data_fields:
311
+ # Check if field name matches resource-specific pattern
312
+ # Example: path="/items/runner-groups" -> resource="RunnerGroup" -> "runner_groups"
313
+ resource_name_from_path = naming.from_path(path)
314
+ if resource_name_from_path is None:
315
+ return None
316
+
317
+ candidate = naming.to_plural(naming.to_snake_case(resource_name_from_path))
318
+ if array_field.lower() != candidate:
319
+ # Field name doesn't match resource pattern
320
+ return None
321
+
322
+ # Check for pagination metadata indicators
323
+ others = [p for p in properties if p != array_field]
324
+
325
+ pagination_indicators = {
326
+ "count",
327
+ "total",
328
+ "totalcount",
329
+ "total_count",
330
+ "totalelements",
331
+ "total_elements",
332
+ "page",
333
+ "pagenumber",
334
+ "page_number",
335
+ "currentpage",
336
+ "current_page",
337
+ "next",
338
+ "previous",
339
+ "prev",
340
+ "nextpage",
341
+ "prevpage",
342
+ "nextpageurl",
343
+ "prevpageurl",
344
+ "next_page_url",
345
+ "prev_page_url",
346
+ "next_page_token",
347
+ "nextpagetoken",
348
+ "cursor",
349
+ "nextcursor",
350
+ "next_cursor",
351
+ "nextlink",
352
+ "next_link",
353
+ "endcursor",
354
+ "hasmore",
355
+ "has_more",
356
+ "hasnextpage",
357
+ "haspreviouspage",
358
+ "pagesize",
359
+ "page_size",
360
+ "perpage",
361
+ "per_page",
362
+ "limit",
363
+ "size",
364
+ "pageinfo",
365
+ "page_info",
366
+ "pagination",
367
+ "links",
368
+ "meta",
369
+ }
370
+
371
+ # Check if any other property looks like pagination metadata
372
+ has_pagination_metadata = any(
373
+ prop.lower().replace("_", "").replace("-", "") in pagination_indicators for prop in others
374
+ )
375
+
376
+ # Either there is pagination metadata or the wrapper has just items + some other field which is likely an unrecognized metadata
377
+ if has_pagination_metadata or len(properties) <= 2:
378
+ return array_field
379
+
380
+ return None
381
+
382
+
383
+ def _detect_externally_tagged_pattern(schema: Mapping[str, Any], path: str) -> str | None:
384
+ """Detect externally tagged resource pattern.
385
+
386
+ Pattern: {ResourceName: [...]} or {resourceName: [...]}
387
+
388
+ Examples:
389
+ - GET /merchants -> {"Merchants": [...]}
390
+ - GET /users -> {"Users": [...]} or {"users": [...]}
391
+
392
+ """
393
+ properties = schema.get("properties", {})
394
+
395
+ if not properties:
396
+ return None
397
+
398
+ resource_name = naming.from_path(path)
399
+
400
+ if not resource_name:
401
+ return None
402
+
403
+ # For example, for `DataRequest`:
404
+ possible_names = {
405
+ # `datarequest`
406
+ resource_name.lower(),
407
+ # `datarequests`
408
+ naming.to_plural(resource_name.lower()),
409
+ # `data_request`
410
+ naming.to_snake_case(resource_name),
411
+ }
412
+
413
+ for name, subschema in properties.items():
414
+ if name.lower() not in possible_names:
415
+ continue
416
+
417
+ if isinstance(subschema, dict):
418
+ return name
419
+
420
+ return None
@@ -21,6 +21,7 @@ from werkzeug.exceptions import MethodNotAllowed, NotFound
21
21
  from werkzeug.routing import Map, MapAdapter, Rule
22
22
 
23
23
  from schemathesis.core.adapter import ResponsesContainer
24
+ from schemathesis.core.transforms import encode_pointer
24
25
 
25
26
  if TYPE_CHECKING:
26
27
  from schemathesis.engine.observations import LocationHeaderEntry
@@ -95,7 +96,7 @@ class LinkInferencer:
95
96
  if operation_id:
96
97
  operation = OperationById(operation_id, method=method, path=path)
97
98
  else:
98
- encoded_path = path.replace("~", "~0").replace("/", "~1")
99
+ encoded_path = encode_pointer(path)
99
100
  operation = OperationByRef(f"#/paths/{encoded_path}/{method}", method=method, path=path)
100
101
 
101
102
  operations.append(operation)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: schemathesis
3
- Version: 4.2.2
3
+ Version: 4.3.1
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://github.com/schemathesis/schemathesis/blob/master/CHANGELOG.md
@@ -28,7 +28,7 @@ schemathesis/cli/ext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hS
28
28
  schemathesis/cli/ext/fs.py,sha256=dHQYBjQozQmuSSfXVp-2KWFK0ESOb_w-lV2SptfMfco,461
29
29
  schemathesis/cli/ext/groups.py,sha256=kQ37t6qeArcKaY2y5VxyK3_KwAkBKCVm58IYV8gewds,2720
30
30
  schemathesis/cli/ext/options.py,sha256=6yYwZNJL__FCEEL7kI3r5MbVmbp3ZeQjm7DrZ6J_h7s,3347
31
- schemathesis/config/__init__.py,sha256=Ff-mcdwCatFIS_WpJNpSe-gl7ez0-m_s4F2_4Teg2eM,6240
31
+ schemathesis/config/__init__.py,sha256=fXE_NxvAxhyGag0_gC3xJwUrUkxZz4OKANQ1nYuGFQk,6311
32
32
  schemathesis/config/_auth.py,sha256=83RLVPm97W2thbn-yi01Rt94YwOxLG_a5VoxhEfjUjs,1528
33
33
  schemathesis/config/_checks.py,sha256=F0r16eSSiICvoiTUkNNOE2PH73EGd8bikoeZdME_3Yw,10763
34
34
  schemathesis/config/_diff_base.py,sha256=U7wuE4480EjP3K16mfC528TP5q7Q5IwAZwZLqRIrS1E,4300
@@ -39,13 +39,13 @@ schemathesis/config/_health_check.py,sha256=zC9inla5ibMBlEy5WyM4_TME7ju_KH3Bwfo2
39
39
  schemathesis/config/_operations.py,sha256=JvfMkieYBkbEmZRb4cTvQLfvHQLhmsxa3GXzgjOtmFc,12383
40
40
  schemathesis/config/_output.py,sha256=3G9SOi-4oNcQPHeNRG3HggFCwvcKOW1kF28a9m0H-pU,4434
41
41
  schemathesis/config/_parameters.py,sha256=i76Hwaf834fBAMmtKfKTl1SFCicJ-Y-5tZt5QNGW2fA,618
42
- schemathesis/config/_phases.py,sha256=JgDyh579iR301OpD93L3WBeEpYUrNxD7R59WZE1X2MA,8390
42
+ schemathesis/config/_phases.py,sha256=0D6eTo_jOVOyMevlpYAo-hcdgi4ocPpibsDpleMzSJ8,8741
43
43
  schemathesis/config/_projects.py,sha256=MpXFBIkNAWAzE_NWQISI9R8dlbCVId2eXGdIqZBgK98,20468
44
44
  schemathesis/config/_rate_limit.py,sha256=ekEW-jP_Ichk_O6hYpj-h2TTTKfp7Fm0nyFUbvlWcbA,456
45
45
  schemathesis/config/_report.py,sha256=ZECDpaCY4WWHD5UbjvgZoSjLz-rlTvfd5Ivzdgzqf2I,3891
46
46
  schemathesis/config/_validator.py,sha256=IcE8geFZ0ZwR18rkIRs25i7pTl7Z84XbjYGUB-mqReU,258
47
47
  schemathesis/config/_warnings.py,sha256=sI0VZcTj3dOnphhBwYwU_KTagxr89HGWTtQ99HcY84k,772
48
- schemathesis/config/schema.json,sha256=3CRSBfUK2vLVl1h5PfeK_YDdEoBZSojYl8Q1kT-ITLE,19846
48
+ schemathesis/config/schema.json,sha256=MWWV2W9ozqBBGtzrtTiYQkdyCdTFSx_fDlYLKrXRs0Q,19887
49
49
  schemathesis/core/__init__.py,sha256=h4gmDePIPvPiVuYxnjrpPKytSZPi6fZeVdTG6c822E4,1973
50
50
  schemathesis/core/adapter.py,sha256=zwJ0vNhalrF9sYXN8_0pMSkJ71GPDnUBKqBCVsnuVIY,951
51
51
  schemathesis/core/compat.py,sha256=9BWCrFoqN2sJIaiht_anxe8kLjYMR7t0iiOkXqLRUZ8,1058
@@ -64,19 +64,19 @@ schemathesis/core/parameters.py,sha256=20pd4DLW1uXs61YuESKG1Fx9QJJQN3JY7CKnOJMgD
64
64
  schemathesis/core/rate_limit.py,sha256=7tg9Znk11erTfw8-ANutjEmu7hbfUHZx_iEdkoaP174,1757
65
65
  schemathesis/core/registries.py,sha256=T4jZB4y3zBHdeSgQc0pRbgSeMblvO-6z4I3zmzIfTi0,811
66
66
  schemathesis/core/result.py,sha256=d449YvyONjqjDs-A5DAPgtAI96iT753K8sU6_1HLo2Q,461
67
- schemathesis/core/transforms.py,sha256=rgr22JdVjFj0di9Oeo94Leo1JmdLJdCjnA-eGpfszV8,4095
67
+ schemathesis/core/transforms.py,sha256=n_inn8Vb-CFiDUd9Z8E7JIp2kn2eAnxO8DD3OSwOTiM,4310
68
68
  schemathesis/core/transport.py,sha256=LQcamAkFqJ0HuXQzepevAq2MCJW-uq5Nm-HE9yc7HMI,7503
69
69
  schemathesis/core/validation.py,sha256=b0USkKzkWvdz3jOW1JXYc_TfYshfKZeP7xAUnMqcNoc,2303
70
70
  schemathesis/core/version.py,sha256=dOBUWrY3-uA2NQXJp9z7EtZgkR6jYeLg8sMhQCL1mcI,205
71
71
  schemathesis/core/jsonschema/__init__.py,sha256=gBZGsXIpK2EFfcp8x0b69dqzWAm2OeZHepKImkkLvoE,320
72
- schemathesis/core/jsonschema/bundler.py,sha256=IWZqKb0PqYSKtFW5ncItqHg5o1uVM0yS7vgbBg6pD0c,7724
72
+ schemathesis/core/jsonschema/bundler.py,sha256=7Cc-1ccBNEdyMMypPyqTEbwcXmnkkjFPDxTZidgzIpU,7804
73
73
  schemathesis/core/jsonschema/keywords.py,sha256=pjseXTfH9OItNs_Qq6ubkhNWQOrxTnwHmrP_jxrHeJU,631
74
74
  schemathesis/core/jsonschema/references.py,sha256=c2Q4IKWUbwENNtkbFaqf8r3LLZu6GFE5YLnYQlg5tPg,6069
75
75
  schemathesis/core/jsonschema/types.py,sha256=C7f9g8yKFuoxC5_0YNIh8QAyGU0-tj8pzTMfMDjjjVM,1248
76
76
  schemathesis/core/output/__init__.py,sha256=SiHqONFskXl73AtP5dV29L14nZoKo7B-IeG52KZB32M,1446
77
77
  schemathesis/core/output/sanitization.py,sha256=Ev3tae8dVwsYd7yVb2_1VBFYs92WFsQ4Eu1fGaymItE,2013
78
78
  schemathesis/engine/__init__.py,sha256=QaFE-FinaTAaarteADo2RRMJ-Sz6hZB9TzD5KjMinIA,706
79
- schemathesis/engine/context.py,sha256=40L4rEu34Y6a4jrag5O7N7sYh3qG5asE2ErF8w9-ktA,5362
79
+ schemathesis/engine/context.py,sha256=iMyyum60AmZlX1reghxzCW6A_dDA43RA3NXJZqruHv8,6821
80
80
  schemathesis/engine/control.py,sha256=FXzP8dxL47j1Giqpy2-Bsr_MdMw9YiATSK_UfpFwDtk,1348
81
81
  schemathesis/engine/core.py,sha256=qlPHnZVq2RrUe93fOciXd1hC3E1gVyF2BIWMPMeLIj8,6655
82
82
  schemathesis/engine/errors.py,sha256=FlpEk44WRLzRkdK9m37z93EQuY3kbeMIQRGwU5e3Qm4,19005
@@ -98,8 +98,8 @@ schemathesis/generation/meta.py,sha256=tXhUZBEdpQMn68uMx1SW8Vv59Uf6Wl6yzs-VB9lu_
98
98
  schemathesis/generation/metrics.py,sha256=cZU5HdeAMcLFEDnTbNE56NuNq4P0N4ew-g1NEz5-kt4,2836
99
99
  schemathesis/generation/modes.py,sha256=Q1fhjWr3zxabU5qdtLvKfpMFZJAwlW9pnxgenjeXTyU,481
100
100
  schemathesis/generation/overrides.py,sha256=xI2djHsa42fzP32xpxgxO52INixKagf5DjDAWJYswM8,3890
101
- schemathesis/generation/hypothesis/__init__.py,sha256=Dfdz6_Wa7ez6GxrMBxnWQnLaNjPUweTxfi01jiFqso4,4900
102
- schemathesis/generation/hypothesis/builder.py,sha256=ZdY68aDGeZLLtIld288KF_O6ardFKZdFMBogwltTx2o,38362
101
+ schemathesis/generation/hypothesis/__init__.py,sha256=68BHULoXQC1WjFfw03ga5lvDGZ-c-J7H_fNEuUzFWRw,4976
102
+ schemathesis/generation/hypothesis/builder.py,sha256=tnDN_0MNT48mAO421JmcI3E0U2zeeTX-mjF3KXmpc7A,38629
103
103
  schemathesis/generation/hypothesis/examples.py,sha256=6eGaKUEC3elmKsaqfKj1sLvM8EHc-PWT4NRBq4NI0Rs,1409
104
104
  schemathesis/generation/hypothesis/given.py,sha256=sTZR1of6XaHAPWtHx2_WLlZ50M8D5Rjux0GmWkWjDq4,2337
105
105
  schemathesis/generation/hypothesis/reporting.py,sha256=uDVow6Ya8YFkqQuOqRsjbzsbyP4KKfr3jA7ZaY4FuKY,279
@@ -110,7 +110,7 @@ schemathesis/graphql/__init__.py,sha256=_eO6MAPHGgiADVGRntnwtPxmuvk666sAh-FAU4cG
110
110
  schemathesis/graphql/checks.py,sha256=IADbxiZjgkBWrC5yzHDtohRABX6zKXk5w_zpWNwdzYo,3186
111
111
  schemathesis/graphql/loaders.py,sha256=2tgG4HIvFmjHLr_KexVXnT8hSBM-dKG_fuXTZgE97So,9445
112
112
  schemathesis/openapi/__init__.py,sha256=-KcsSAM19uOM0N5J4s-yTnQ1BFsptYhW1E51cEf6kVM,311
113
- schemathesis/openapi/checks.py,sha256=VaQRxko6KwZL6saIzc4uUgJa_fj086O7Y6QFK8Zg-7A,12419
113
+ schemathesis/openapi/checks.py,sha256=nrkkagRqg-HOsDCAMbJqCnHyBZEA2PpRV_AB8lI_I9c,13080
114
114
  schemathesis/openapi/loaders.py,sha256=-DSFWcvD_PmekTyy0qZrJ1YYODh9C1KuAJJIytEnS1s,10733
115
115
  schemathesis/openapi/generation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
116
116
  schemathesis/openapi/generation/filters.py,sha256=pY9cUZdL_kQK80Z2aylTOqqa12zmaYUlYC5BfYgeQMk,2395
@@ -142,14 +142,14 @@ schemathesis/specs/openapi/schemas.py,sha256=vwBgw7kznPlQJIufgJ48oRxCzDFkUWKfb4u
142
142
  schemathesis/specs/openapi/serialization.py,sha256=RPNdadne5wdhsGmjSvgKLRF58wpzpRx3wura8PsHM3o,12152
143
143
  schemathesis/specs/openapi/utils.py,sha256=XkOJT8qD-6uhq-Tmwxk_xYku1Gy5F9pKL3ldNg_DRZw,522
144
144
  schemathesis/specs/openapi/adapter/__init__.py,sha256=YEovBgLjnXd3WGPMJXq0KbSGHezkRlEv4dNRO7_evfk,249
145
- schemathesis/specs/openapi/adapter/parameters.py,sha256=jX6tQuJ8k0Ml9w4jAquncGv2ZbJzsG2fUwLu6Grmlq8,18614
146
- schemathesis/specs/openapi/adapter/protocol.py,sha256=6Ioe563EL_ZAyRe8Kj8AE6l6grpFbIVn4C3GDuqizTA,2567
145
+ schemathesis/specs/openapi/adapter/parameters.py,sha256=MYEQUxhtv23e1uhoDq5bDHMUT3Q64bW7aZloJuz13QY,18626
146
+ schemathesis/specs/openapi/adapter/protocol.py,sha256=VDF6COcilHEUnmw76YBVur8bFiTFQHsNvaO9pR_i_KM,2709
147
147
  schemathesis/specs/openapi/adapter/references.py,sha256=6M59pJy_U_sLh3Xzgu6-izWXtz3bjXnqJYSD65wRHtk,549
148
- schemathesis/specs/openapi/adapter/responses.py,sha256=bti5FhqZaq_8g95kdpYx5lD2_1cUZEq56yIjlASji8I,12455
148
+ schemathesis/specs/openapi/adapter/responses.py,sha256=Zv9uNgyr591-ZUcBCYMGot9ZccJgrxEOd9KI8wDfDTY,13253
149
149
  schemathesis/specs/openapi/adapter/security.py,sha256=W3cqlbs80NxF9SAavOi7BhtNGzdxHO476lYxiWN0D08,4945
150
- schemathesis/specs/openapi/adapter/v2.py,sha256=tWbq3EuJnSomWylPw_BT6TfEw8sIJQEFnVKpxCiq5XE,1153
151
- schemathesis/specs/openapi/adapter/v3_0.py,sha256=Q6b1Rfajx2tiO5W6uEwLosxQcdFqVgT5TS4r2jYFwg4,1145
152
- schemathesis/specs/openapi/adapter/v3_1.py,sha256=lvLvoxMC_AEwm8c_d3RGHk0BptaOFCdDcV8RrH-uOGw,1155
150
+ schemathesis/specs/openapi/adapter/v2.py,sha256=2Rd1cTv7_I5QrBPLVfa2yD80NAErxV3tdeACjtEfXAA,1280
151
+ schemathesis/specs/openapi/adapter/v3_0.py,sha256=8bOE9WUDrvPivGs0w-S1PP2TXgWuaoTzMdg2_WWbi-E,1272
152
+ schemathesis/specs/openapi/adapter/v3_1.py,sha256=Hi4iMQdLDAeqSVYjafXbRb5yolWuqMz9A954tE2SCQY,1282
153
153
  schemathesis/specs/openapi/expressions/__init__.py,sha256=hfuRtXD75tQFhzSo6QgDZ3zByyWeZRKevB8edszAVj4,2272
154
154
  schemathesis/specs/openapi/expressions/errors.py,sha256=YLVhps-sYcslgVaahfcUYxUSHlIfWL-rQMeT5PZSMZ8,219
155
155
  schemathesis/specs/openapi/expressions/extractors.py,sha256=IvOrgq_1IWNnirOSV_wLi0UcWOTiL-mLvBLFzLwRpVA,498
@@ -162,8 +162,15 @@ schemathesis/specs/openapi/negative/types.py,sha256=a7buCcVxNBG6ILBM3A7oNTAX0lyD
162
162
  schemathesis/specs/openapi/negative/utils.py,sha256=ozcOIuASufLqZSgnKUACjX-EOZrrkuNdXX0SDnLoGYA,168
163
163
  schemathesis/specs/openapi/stateful/__init__.py,sha256=nD5f9pP2Rx2DKIeXtbc_KqUukC4Nf2834cHeOp52byM,16247
164
164
  schemathesis/specs/openapi/stateful/control.py,sha256=QaXLSbwQWtai5lxvvVtQV3BLJ8n5ePqSKB00XFxp-MA,3695
165
- schemathesis/specs/openapi/stateful/inference.py,sha256=TCgEnDdTg2syk8KM8YCM96eE6-hMRNMW4OvVCxuyZkc,9603
165
+ schemathesis/specs/openapi/stateful/inference.py,sha256=9o9V-UUpphW7u_Kqz5MCp1_JXS2H_rcAZwz0bwJnmbI,9637
166
166
  schemathesis/specs/openapi/stateful/links.py,sha256=G6vqW6JFOdhF044ZjG6PsSwAHU1yP4E3FolcNFE55NM,7918
167
+ schemathesis/specs/openapi/stateful/dependencies/__init__.py,sha256=epBYtVw7q9mkV-UtlJNbfJQgwAs9d5jkOJYkyEeUMvE,3348
168
+ schemathesis/specs/openapi/stateful/dependencies/inputs.py,sha256=5niLSz7-wl-sP9cJdnYBItwEeLuzJr3nw4XIMT3yt98,6764
169
+ schemathesis/specs/openapi/stateful/dependencies/models.py,sha256=4MXJzCat1bU-tmwAM7OH2dFBys_YHCJw9wTgd9Hib3c,9728
170
+ schemathesis/specs/openapi/stateful/dependencies/naming.py,sha256=1aaa8vc56tsyOAKAvD8oPk55S-qbzrCBYe1kCk3Y9VY,9052
171
+ schemathesis/specs/openapi/stateful/dependencies/outputs.py,sha256=zvVUfQWNIuhMkKDpz5hsVGkkvkefLt1EswpJAnHajOw,1186
172
+ schemathesis/specs/openapi/stateful/dependencies/resources.py,sha256=7E2Z6LvomSRrp_0vCD_adzoux0wBLEjKi_EiSqiN43U,9664
173
+ schemathesis/specs/openapi/stateful/dependencies/schemas.py,sha256=pNV2GibNW8042KrdfUQBdJEkGj_dd84bTHbqunba48k,13976
167
174
  schemathesis/specs/openapi/types/__init__.py,sha256=VPsWtLJle__Kodw_QqtQ3OuvBzBcCIKsTOrXy3eA7OU,66
168
175
  schemathesis/specs/openapi/types/v3.py,sha256=Vondr9Amk6JKCIM6i6RGcmTUjFfPgOOqzBXqerccLpo,1468
169
176
  schemathesis/transport/__init__.py,sha256=6yg_RfV_9L0cpA6qpbH-SL9_3ggtHQji9CZrpIkbA6s,5321
@@ -172,8 +179,8 @@ schemathesis/transport/prepare.py,sha256=erYXRaxpQokIDzaIuvt_csHcw72iHfCyNq8VNEz
172
179
  schemathesis/transport/requests.py,sha256=wriRI9fprTplE_qEZLEz1TerX6GwkE3pwr6ZnU2o6vQ,10648
173
180
  schemathesis/transport/serialization.py,sha256=GwO6OAVTmL1JyKw7HiZ256tjV4CbrRbhQN0ep1uaZwI,11157
174
181
  schemathesis/transport/wsgi.py,sha256=kQtasFre6pjdJWRKwLA_Qb-RyQHCFNpaey9ubzlFWKI,5907
175
- schemathesis-4.2.2.dist-info/METADATA,sha256=x3D71YX9YO81-h_n1Emw98R4jxq6NoL33XbYe3ntWNc,8540
176
- schemathesis-4.2.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
177
- schemathesis-4.2.2.dist-info/entry_points.txt,sha256=hiK3un-xfgPdwj9uj16YVDtTNpO128bmk0U82SMv8ZQ,152
178
- schemathesis-4.2.2.dist-info/licenses/LICENSE,sha256=2Ve4J8v5jMQAWrT7r1nf3bI8Vflk3rZVQefiF2zpxwg,1121
179
- schemathesis-4.2.2.dist-info/RECORD,,
182
+ schemathesis-4.3.1.dist-info/METADATA,sha256=cJcbDVPtmrVZIVWanF1tJxF1Vbhel76KAhpzJLj_KHs,8540
183
+ schemathesis-4.3.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
184
+ schemathesis-4.3.1.dist-info/entry_points.txt,sha256=hiK3un-xfgPdwj9uj16YVDtTNpO128bmk0U82SMv8ZQ,152
185
+ schemathesis-4.3.1.dist-info/licenses/LICENSE,sha256=2Ve4J8v5jMQAWrT7r1nf3bI8Vflk3rZVQefiF2zpxwg,1121
186
+ schemathesis-4.3.1.dist-info/RECORD,,