schemathesis 4.3.0__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.
@@ -579,8 +579,16 @@ def _iter_coverage_cases(
579
579
  ),
580
580
  schema,
581
581
  )
582
- value = next(gen, NOT_SET)
583
- assert not isinstance(value, NotSet), f"It should always be possible: {schema!r}"
582
+ value = next(
583
+ gen,
584
+ coverage.GeneratedValue(
585
+ "value",
586
+ generation_mode=GenerationMode.NEGATIVE,
587
+ description="Sample value for unsupported path parameter pattern",
588
+ parameter=name,
589
+ location="/",
590
+ ),
591
+ )
584
592
  template.add_parameter(location, name, value)
585
593
  continue
586
594
  continue
@@ -125,8 +125,20 @@ class JsonSchemaError(Failure):
125
125
  exc: ValidationError,
126
126
  config: OutputConfig | None = None,
127
127
  ) -> JsonSchemaError:
128
+ schema_path = list(exc.absolute_schema_path)
129
+
130
+ # Reorder schema to prioritize the failing keyword in the output
131
+ schema_to_display = exc.schema
132
+ if isinstance(schema_to_display, dict) and schema_path:
133
+ failing_keyword = schema_path[-1]
134
+ if isinstance(failing_keyword, str) and failing_keyword in schema_to_display:
135
+ # Create a new dict with the failing keyword first
136
+ schema_to_display = {
137
+ failing_keyword: schema_to_display[failing_keyword],
138
+ **{k: v for k, v in schema_to_display.items() if k != failing_keyword},
139
+ }
128
140
  schema = textwrap.indent(
129
- truncate_json(exc.schema, config=config or OutputConfig(), max_lines=20), prefix=" "
141
+ truncate_json(schema_to_display, config=config or OutputConfig(), max_lines=20), prefix=" "
130
142
  )
131
143
  value = textwrap.indent(
132
144
  truncate_json(exc.instance, config=config or OutputConfig(), max_lines=20), prefix=" "
@@ -26,12 +26,184 @@ def from_path(path: str) -> str | None:
26
26
  return to_pascal_case(singular)
27
27
 
28
28
 
29
+ IRREGULAR_TO_PLURAL = {
30
+ "echo": "echoes",
31
+ "dingo": "dingoes",
32
+ "volcano": "volcanoes",
33
+ "tornado": "tornadoes",
34
+ "torpedo": "torpedoes",
35
+ "genus": "genera",
36
+ "viscus": "viscera",
37
+ "stigma": "stigmata",
38
+ "stoma": "stomata",
39
+ "dogma": "dogmata",
40
+ "lemma": "lemmata",
41
+ "anathema": "anathemata",
42
+ "ox": "oxen",
43
+ "axe": "axes",
44
+ "die": "dice",
45
+ "yes": "yeses",
46
+ "foot": "feet",
47
+ "eave": "eaves",
48
+ "goose": "geese",
49
+ "tooth": "teeth",
50
+ "quiz": "quizzes",
51
+ "human": "humans",
52
+ "proof": "proofs",
53
+ "carve": "carves",
54
+ "valve": "valves",
55
+ "looey": "looies",
56
+ "thief": "thieves",
57
+ "groove": "grooves",
58
+ "pickaxe": "pickaxes",
59
+ "passerby": "passersby",
60
+ "canvas": "canvases",
61
+ "use": "uses",
62
+ "case": "cases",
63
+ "vase": "vases",
64
+ "house": "houses",
65
+ "mouse": "mice",
66
+ "reuse": "reuses",
67
+ "abuse": "abuses",
68
+ "excuse": "excuses",
69
+ "cause": "causes",
70
+ "pause": "pauses",
71
+ "base": "bases",
72
+ "phase": "phases",
73
+ "rose": "roses",
74
+ "dose": "doses",
75
+ "nose": "noses",
76
+ "horse": "horses",
77
+ "course": "courses",
78
+ "purpose": "purposes",
79
+ "response": "responses",
80
+ "sense": "senses",
81
+ "tense": "tenses",
82
+ "expense": "expenses",
83
+ "license": "licenses",
84
+ "defense": "defenses",
85
+ }
86
+ IRREGULAR_TO_SINGULAR = {v: k for k, v in IRREGULAR_TO_PLURAL.items()}
87
+ UNCOUNTABLE = frozenset(
88
+ [
89
+ "adulthood",
90
+ "advice",
91
+ "agenda",
92
+ "aid",
93
+ "aircraft",
94
+ "alcohol",
95
+ "ammo",
96
+ "analytics",
97
+ "anime",
98
+ "athletics",
99
+ "audio",
100
+ "bison",
101
+ "blood",
102
+ "bream",
103
+ "buffalo",
104
+ "butter",
105
+ "carp",
106
+ "cash",
107
+ "chassis",
108
+ "chess",
109
+ "clothing",
110
+ "cod",
111
+ "commerce",
112
+ "cooperation",
113
+ "corps",
114
+ "debris",
115
+ "diabetes",
116
+ "digestion",
117
+ "elk",
118
+ "energy",
119
+ "equipment",
120
+ "excretion",
121
+ "expertise",
122
+ "firmware",
123
+ "flounder",
124
+ "fun",
125
+ "gallows",
126
+ "garbage",
127
+ "graffiti",
128
+ "hardware",
129
+ "headquarters",
130
+ "health",
131
+ "herpes",
132
+ "highjinks",
133
+ "homework",
134
+ "housework",
135
+ "information",
136
+ "jeans",
137
+ "justice",
138
+ "kudos",
139
+ "labour",
140
+ "literature",
141
+ "machinery",
142
+ "mackerel",
143
+ "mail",
144
+ "media",
145
+ "mews",
146
+ "moose",
147
+ "music",
148
+ "mud",
149
+ "manga",
150
+ "news",
151
+ "only",
152
+ "personnel",
153
+ "pike",
154
+ "plankton",
155
+ "pliers",
156
+ "police",
157
+ "pollution",
158
+ "premises",
159
+ "rain",
160
+ "research",
161
+ "rice",
162
+ "salmon",
163
+ "scissors",
164
+ "series",
165
+ "sewage",
166
+ "shambles",
167
+ "shrimp",
168
+ "software",
169
+ "staff",
170
+ "swine",
171
+ "tennis",
172
+ "traffic",
173
+ "transportation",
174
+ "trout",
175
+ "tuna",
176
+ "wealth",
177
+ "welfare",
178
+ "whiting",
179
+ "wildebeest",
180
+ "wildlife",
181
+ "you",
182
+ "sheep",
183
+ "deer",
184
+ "species",
185
+ "series",
186
+ "means",
187
+ ]
188
+ )
189
+
190
+
29
191
  def to_singular(word: str) -> str:
30
- if word.endswith("ies"):
192
+ if word in UNCOUNTABLE:
193
+ return word
194
+ known = IRREGULAR_TO_SINGULAR.get(word)
195
+ if known is not None:
196
+ return known
197
+ if word.endswith("ies") and len(word) > 3 and word[-4] not in "aeiou":
31
198
  return word[:-3] + "y"
32
199
  if word.endswith("sses"):
33
200
  return word[:-2]
34
- if word.endswith(("ses", "xes", "zes", "ches", "shes")):
201
+ if word.endswith(("xes", "zes", "ches", "shes")):
202
+ return word[:-2]
203
+ # Handle "ses" ending: check if it was "se" + "s" or "s" + "es"
204
+ if word.endswith("ses") and len(word) > 3:
205
+ # "gases" has 's' at position -3, formed from "gas" + "es"
206
+ # "statuses" has 's' at position -3, formed from "status" + "es"
35
207
  return word[:-2]
36
208
  if word.endswith("s"):
37
209
  return word[:-1]
@@ -39,8 +211,13 @@ def to_singular(word: str) -> str:
39
211
 
40
212
 
41
213
  def to_plural(word: str) -> str:
42
- # party -> parties (inverse of ies -> y)
43
- if word.endswith("y"):
214
+ if word in UNCOUNTABLE:
215
+ return word
216
+ known = IRREGULAR_TO_PLURAL.get(word)
217
+ if known is not None:
218
+ return known
219
+ # Only change y -> ies after consonants (party -> parties, not day -> days)
220
+ if word.endswith("y") and len(word) > 1 and word[-2] not in "aeiou":
44
221
  return word[:-1] + "ies"
45
222
  # class -> classes
46
223
  if word.endswith("ss"):
@@ -91,6 +91,13 @@ def iter_resources_from_response(
91
91
  parent_ref = schema.get("$ref")
92
92
  _, resolved = maybe_resolve(schema, resolver, "")
93
93
 
94
+ # Sometimes data is wrapped in `data` field
95
+ pointer = None
96
+ properties = resolved.get("properties", {})
97
+ if properties and list(properties) == ["data"]:
98
+ pointer = "/data"
99
+ resolved = properties["data"]
100
+
94
101
  resolved = try_unwrap_composition(resolved, resolver)
95
102
 
96
103
  if "allOf" in resolved:
@@ -130,7 +137,12 @@ def iter_resources_from_response(
130
137
 
131
138
  if result is not None:
132
139
  resource, cardinality = result
133
- yield ExtractedResource(resource=resource, cardinality=cardinality, pointer=unwrapped.pointer)
140
+ if pointer:
141
+ if unwrapped.pointer != ROOT_POINTER:
142
+ pointer += unwrapped.pointer
143
+ else:
144
+ pointer = unwrapped.pointer
145
+ yield ExtractedResource(resource=resource, cardinality=cardinality, pointer=pointer)
134
146
 
135
147
 
136
148
  def _recover_ref_from_allof(*, branches: list[dict], pointer: str, resolver: RefResolver) -> str | None:
@@ -1,10 +1,20 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from dataclasses import dataclass
4
- from typing import TYPE_CHECKING, Any, Mapping
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
5
13
 
6
14
  from schemathesis.core.jsonschema import ALL_KEYWORDS
7
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
8
18
  from schemathesis.specs.openapi.adapter.parameters import resource_name_from_ref
9
19
  from schemathesis.specs.openapi.adapter.references import maybe_resolve
10
20
  from schemathesis.specs.openapi.stateful.dependencies import naming
@@ -13,19 +23,71 @@ if TYPE_CHECKING:
13
23
  from schemathesis.core.compat import RefResolver
14
24
 
15
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
16
79
 
17
80
 
18
81
  def canonicalize(schema: dict[str, Any], resolver: RefResolver) -> Mapping[str, Any]:
19
82
  """Transform the input schema into its canonical-ish form."""
20
- from hypothesis_jsonschema._canonicalise import canonicalish
21
- from hypothesis_jsonschema._resolve import resolve_all_refs
22
-
23
83
  # Canonicalisation in `hypothesis_jsonschema` requires all references to be resovable and non-recursive
24
84
  # On the Schemathesis side bundling solves this problem
25
85
  bundled = bundle(schema, resolver, inline_recursive=True)
26
86
  canonicalized = canonicalish(bundled)
27
87
  resolved = resolve_all_refs(canonicalized)
28
88
  resolved.pop(BUNDLE_STORAGE_KEY, None)
89
+ if "allOf" in resolved or "anyOf" in resolved or "oneOf" in resolved:
90
+ return canonicalish(resolved)
29
91
  return resolved
30
92
 
31
93
 
@@ -149,16 +211,28 @@ def unwrap_schema(
149
211
  _, resolved_resource = maybe_resolve(resource_schema, resolver, "")
150
212
 
151
213
  return UnwrappedSchema(
152
- pointer=f"/_embedded/{hal_field}", schema=resolved_resource, ref=resource_schema.get("$ref")
214
+ pointer=f"/_embedded/{encode_pointer(hal_field)}", schema=resolved_resource, ref=resource_schema.get("$ref")
153
215
  )
154
216
 
155
217
  # Pagination wrapper
156
218
  array_field = _is_pagination_wrapper(schema=schema, path=path, parent_ref=parent_ref, resolver=resolver)
157
219
  if array_field:
158
220
  array_schema = properties[array_field]
159
- _, resolved_array = maybe_resolve(array_schema, resolver, "")
160
-
161
- return UnwrappedSchema(pointer=f"/{array_field}", schema=resolved_array, ref=array_schema.get("$ref"))
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"))
162
236
 
163
237
  # External tag
164
238
  external_tag = _detect_externally_tagged_pattern(schema, path)
@@ -170,7 +244,7 @@ def unwrap_schema(
170
244
  ref = resolved.get("$ref") or resolved_tagged.get("$ref") or tagged_schema.get("$ref")
171
245
 
172
246
  _, resolved = maybe_resolve(resolved, resolver, "")
173
- return UnwrappedSchema(pointer=f"/{external_tag}", schema=resolved, ref=ref)
247
+ return UnwrappedSchema(pointer=f"/{encode_pointer(external_tag)}", schema=resolved, ref=ref)
174
248
 
175
249
  # No wrapper - single object at root
176
250
  return UnwrappedSchema(pointer="/", schema=schema, ref=schema.get("$ref"))
@@ -326,11 +400,14 @@ def _detect_externally_tagged_pattern(schema: Mapping[str, Any], path: str) -> s
326
400
  if not resource_name:
327
401
  return None
328
402
 
403
+ # For example, for `DataRequest`:
329
404
  possible_names = {
330
- # "merchant"
405
+ # `datarequest`
331
406
  resource_name.lower(),
332
- # "merchants"
407
+ # `datarequests`
333
408
  naming.to_plural(resource_name.lower()),
409
+ # `data_request`
410
+ naming.to_snake_case(resource_name),
334
411
  }
335
412
 
336
413
  for name, subschema in properties.items():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: schemathesis
3
- Version: 4.3.0
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
@@ -99,7 +99,7 @@ schemathesis/generation/metrics.py,sha256=cZU5HdeAMcLFEDnTbNE56NuNq4P0N4ew-g1NEz
99
99
  schemathesis/generation/modes.py,sha256=Q1fhjWr3zxabU5qdtLvKfpMFZJAwlW9pnxgenjeXTyU,481
100
100
  schemathesis/generation/overrides.py,sha256=xI2djHsa42fzP32xpxgxO52INixKagf5DjDAWJYswM8,3890
101
101
  schemathesis/generation/hypothesis/__init__.py,sha256=68BHULoXQC1WjFfw03ga5lvDGZ-c-J7H_fNEuUzFWRw,4976
102
- schemathesis/generation/hypothesis/builder.py,sha256=ZdY68aDGeZLLtIld288KF_O6ardFKZdFMBogwltTx2o,38362
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
@@ -167,10 +167,10 @@ schemathesis/specs/openapi/stateful/links.py,sha256=G6vqW6JFOdhF044ZjG6PsSwAHU1y
167
167
  schemathesis/specs/openapi/stateful/dependencies/__init__.py,sha256=epBYtVw7q9mkV-UtlJNbfJQgwAs9d5jkOJYkyEeUMvE,3348
168
168
  schemathesis/specs/openapi/stateful/dependencies/inputs.py,sha256=5niLSz7-wl-sP9cJdnYBItwEeLuzJr3nw4XIMT3yt98,6764
169
169
  schemathesis/specs/openapi/stateful/dependencies/models.py,sha256=4MXJzCat1bU-tmwAM7OH2dFBys_YHCJw9wTgd9Hib3c,9728
170
- schemathesis/specs/openapi/stateful/dependencies/naming.py,sha256=4cOlVf_diyHTcsYGjaGYEGbuAG4DaVkly_8z0Wwrjlo,5126
170
+ schemathesis/specs/openapi/stateful/dependencies/naming.py,sha256=1aaa8vc56tsyOAKAvD8oPk55S-qbzrCBYe1kCk3Y9VY,9052
171
171
  schemathesis/specs/openapi/stateful/dependencies/outputs.py,sha256=zvVUfQWNIuhMkKDpz5hsVGkkvkefLt1EswpJAnHajOw,1186
172
- schemathesis/specs/openapi/stateful/dependencies/resources.py,sha256=Kl-1SjbZPWbQn9-M5QQBMdEN-WIroxHKVzgbfNHyGuw,9273
173
- schemathesis/specs/openapi/stateful/dependencies/schemas.py,sha256=oL3b-DWG7wsMzVyL-z99xb-6vg8fWryRD8voh__hK0Y,10734
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
174
174
  schemathesis/specs/openapi/types/__init__.py,sha256=VPsWtLJle__Kodw_QqtQ3OuvBzBcCIKsTOrXy3eA7OU,66
175
175
  schemathesis/specs/openapi/types/v3.py,sha256=Vondr9Amk6JKCIM6i6RGcmTUjFfPgOOqzBXqerccLpo,1468
176
176
  schemathesis/transport/__init__.py,sha256=6yg_RfV_9L0cpA6qpbH-SL9_3ggtHQji9CZrpIkbA6s,5321
@@ -179,8 +179,8 @@ schemathesis/transport/prepare.py,sha256=erYXRaxpQokIDzaIuvt_csHcw72iHfCyNq8VNEz
179
179
  schemathesis/transport/requests.py,sha256=wriRI9fprTplE_qEZLEz1TerX6GwkE3pwr6ZnU2o6vQ,10648
180
180
  schemathesis/transport/serialization.py,sha256=GwO6OAVTmL1JyKw7HiZ256tjV4CbrRbhQN0ep1uaZwI,11157
181
181
  schemathesis/transport/wsgi.py,sha256=kQtasFre6pjdJWRKwLA_Qb-RyQHCFNpaey9ubzlFWKI,5907
182
- schemathesis-4.3.0.dist-info/METADATA,sha256=AIqtw5GycgCYvcZZy6hzMZNTet6ckzc_Vdtkv2A0SyU,8540
183
- schemathesis-4.3.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
184
- schemathesis-4.3.0.dist-info/entry_points.txt,sha256=hiK3un-xfgPdwj9uj16YVDtTNpO128bmk0U82SMv8ZQ,152
185
- schemathesis-4.3.0.dist-info/licenses/LICENSE,sha256=2Ve4J8v5jMQAWrT7r1nf3bI8Vflk3rZVQefiF2zpxwg,1121
186
- schemathesis-4.3.0.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,,