schemathesis 4.0.2__py3-none-any.whl → 4.0.4__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.
@@ -421,6 +421,7 @@ def clear_hypothesis_notes(exc: Exception) -> None:
421
421
  def is_unrecoverable_network_error(exc: Exception) -> bool:
422
422
  from http.client import RemoteDisconnected
423
423
 
424
+ import requests
424
425
  from urllib3.exceptions import ProtocolError
425
426
 
426
427
  def has_connection_reset(inner: BaseException) -> bool:
@@ -433,6 +434,8 @@ def is_unrecoverable_network_error(exc: Exception) -> bool:
433
434
 
434
435
  return False
435
436
 
437
+ if isinstance(exc, requests.Timeout):
438
+ return True
436
439
  if isinstance(exc.__context__, ProtocolError):
437
440
  if len(exc.__context__.args) == 2 and isinstance(exc.__context__.args[1], RemoteDisconnected):
438
441
  return True
@@ -442,14 +445,16 @@ def is_unrecoverable_network_error(exc: Exception) -> bool:
442
445
  return has_connection_reset(exc)
443
446
 
444
447
 
445
- @dataclass()
448
+ @dataclass
446
449
  class UnrecoverableNetworkError:
447
- error: requests.ConnectionError | ChunkedEncodingError
450
+ error: requests.ConnectionError | ChunkedEncodingError | requests.Timeout
448
451
  code_sample: str
449
452
 
450
453
  __slots__ = ("error", "code_sample")
451
454
 
452
- def __init__(self, error: requests.ConnectionError | ChunkedEncodingError, code_sample: str) -> None:
455
+ def __init__(
456
+ self, error: requests.ConnectionError | ChunkedEncodingError | requests.Timeout, code_sample: str
457
+ ) -> None:
453
458
  self.error = error
454
459
  self.code_sample = code_sample
455
460
 
@@ -133,9 +133,9 @@ def execute_state_machine_loop(
133
133
  ctx.step_failed()
134
134
  raise
135
135
  except Exception as exc:
136
- if isinstance(exc, (requests.ConnectionError, ChunkedEncodingError)) and is_unrecoverable_network_error(
137
- exc
138
- ):
136
+ if isinstance(
137
+ exc, (requests.ConnectionError, ChunkedEncodingError, requests.Timeout)
138
+ ) and is_unrecoverable_network_error(exc):
139
139
  transport_kwargs = engine.get_transport_kwargs(operation=input.case.operation)
140
140
  if exc.request is not None:
141
141
  headers = {key: value[0] for key, value in exc.request.headers.items()}
@@ -327,9 +327,9 @@ def cached_test_func(f: Callable) -> Callable:
327
327
  except (KeyboardInterrupt, Failure):
328
328
  raise
329
329
  except Exception as exc:
330
- if isinstance(exc, (requests.ConnectionError, ChunkedEncodingError)) and is_unrecoverable_network_error(
331
- exc
332
- ):
330
+ if isinstance(
331
+ exc, (requests.ConnectionError, ChunkedEncodingError, requests.Timeout)
332
+ ) and is_unrecoverable_network_error(exc):
333
333
  # Server likely has crashed and does not accept any connections at all
334
334
  # Don't report these error - only the original crash should be reported
335
335
  if exc.request is not None:
@@ -244,19 +244,25 @@ class Case:
244
244
 
245
245
  response = Response.from_any(response)
246
246
 
247
+ config = self.operation.schema.config.checks_config_for(
248
+ operation=self.operation, phase=self.meta.phase.name.value if self.meta is not None else None
249
+ )
250
+ if not checks:
251
+ # Checks are not specified explicitly, derive from the config
252
+ checks = []
253
+ for check in CHECKS.get_all():
254
+ name = check.__name__
255
+ if config.get_by_name(name=name).enabled:
256
+ checks.append(check)
247
257
  checks = [
248
- check
249
- for check in list(checks or CHECKS.get_all()) + list(additional_checks or [])
250
- if check not in set(excluded_checks or [])
258
+ check for check in list(checks) + list(additional_checks or []) if check not in set(excluded_checks or [])
251
259
  ]
252
260
 
253
261
  ctx = CheckContext(
254
262
  override=self._override,
255
263
  auth=None,
256
264
  headers=CaseInsensitiveDict(headers) if headers else None,
257
- config=self.operation.schema.config.checks_config_for(
258
- operation=self.operation, phase=self.meta.phase.name.value if self.meta is not None else None
259
- ),
265
+ config=config,
260
266
  transport_kwargs=transport_kwargs,
261
267
  recorder=None,
262
268
  )
@@ -109,19 +109,22 @@ def cached_draw(strategy: st.SearchStrategy) -> Any:
109
109
  class CoverageContext:
110
110
  generation_modes: list[GenerationMode]
111
111
  location: str
112
+ is_required: bool
112
113
  path: list[str | int]
113
114
 
114
- __slots__ = ("location", "generation_modes", "path")
115
+ __slots__ = ("location", "generation_modes", "is_required", "path")
115
116
 
116
117
  def __init__(
117
118
  self,
118
119
  *,
119
120
  location: str,
120
121
  generation_modes: list[GenerationMode] | None = None,
122
+ is_required: bool,
121
123
  path: list[str | int] | None = None,
122
124
  ) -> None:
123
125
  self.location = location
124
126
  self.generation_modes = generation_modes if generation_modes is not None else list(GenerationMode)
127
+ self.is_required = is_required
125
128
  self.path = path or []
126
129
 
127
130
  @contextmanager
@@ -140,6 +143,7 @@ class CoverageContext:
140
143
  return CoverageContext(
141
144
  location=self.location,
142
145
  generation_modes=[GenerationMode.POSITIVE],
146
+ is_required=self.is_required,
143
147
  path=self.path,
144
148
  )
145
149
 
@@ -147,6 +151,7 @@ class CoverageContext:
147
151
  return CoverageContext(
148
152
  location=self.location,
149
153
  generation_modes=[GenerationMode.NEGATIVE],
154
+ is_required=self.is_required,
150
155
  path=self.path,
151
156
  )
152
157
 
@@ -157,6 +162,16 @@ class CoverageContext:
157
162
  return not is_invalid_path_parameter(value)
158
163
  return True
159
164
 
165
+ def leads_to_negative_test_case(self, value: Any) -> bool:
166
+ if self.location == "query":
167
+ # Some values will not be serialized into the query string
168
+ if isinstance(value, list) and not self.is_required:
169
+ # Optional parameters should be present
170
+ return any(item not in [{}, []] for item in value)
171
+ if isinstance(value, dict) and not self.is_required:
172
+ return bool(value)
173
+ return True
174
+
160
175
  def generate_from(self, strategy: st.SearchStrategy) -> Any:
161
176
  return cached_draw(strategy)
162
177
 
@@ -955,11 +970,13 @@ def _negative_items(ctx: CoverageContext, schema: dict[str, Any] | bool) -> Gene
955
970
  """Arrays not matching the schema."""
956
971
  nctx = ctx.with_negative()
957
972
  for value in cover_schema_iter(nctx, schema):
958
- yield NegativeValue(
959
- [value.value],
960
- description=f"Array with invalid items: {value.description}",
961
- location=nctx.current_path,
962
- )
973
+ items = [value.value]
974
+ if ctx.leads_to_negative_test_case(items):
975
+ yield NegativeValue(
976
+ items,
977
+ description=f"Array with invalid items: {value.description}",
978
+ location=nctx.current_path,
979
+ )
963
980
 
964
981
 
965
982
  def _not_matching_pattern(value: str, pattern: re.Pattern) -> bool:
@@ -1027,6 +1044,9 @@ def _negative_format(ctx: CoverageContext, schema: dict, format: str) -> Generat
1027
1044
  # Hypothesis-jsonschema does not canonicalise it properly right now, which leads to unsatisfiable schema
1028
1045
  without_format = {k: v for k, v in schema.items() if k != "format"}
1029
1046
  without_format.setdefault("type", "string")
1047
+ if ctx.location == "path":
1048
+ # Empty path parameters are invalid
1049
+ without_format["minLength"] = 1
1030
1050
  strategy = from_schema(without_format)
1031
1051
  if format in jsonschema.Draft202012Validator.FORMAT_CHECKER.checkers:
1032
1052
  if format == "hostname":
@@ -1060,7 +1080,7 @@ def _negative_type(
1060
1080
  strategies["number"] = FLOAT_STRATEGY.filter(_is_non_integer_float)
1061
1081
  for strategy in strategies.values():
1062
1082
  value = ctx.generate_from(strategy)
1063
- if seen.insert(value):
1083
+ if seen.insert(value) and ctx.is_valid_for_location(value):
1064
1084
  yield NegativeValue(value, description="Incorrect type", location=ctx.current_path)
1065
1085
 
1066
1086
 
@@ -474,7 +474,10 @@ def _iter_coverage_cases(
474
474
  for value in find_matching_in_responses(responses, parameter.name):
475
475
  schema.setdefault("examples", []).append(value)
476
476
  gen = coverage.cover_schema_iter(
477
- coverage.CoverageContext(location=location, generation_modes=generation_modes), schema
477
+ coverage.CoverageContext(
478
+ location=location, generation_modes=generation_modes, is_required=parameter.is_required
479
+ ),
480
+ schema,
478
481
  )
479
482
  value = next(gen, NOT_SET)
480
483
  if isinstance(value, NotSet):
@@ -492,7 +495,10 @@ def _iter_coverage_cases(
492
495
  if examples:
493
496
  schema.setdefault("examples", []).extend(examples)
494
497
  gen = coverage.cover_schema_iter(
495
- coverage.CoverageContext(location="body", generation_modes=generation_modes), schema
498
+ coverage.CoverageContext(
499
+ location="body", generation_modes=generation_modes, is_required=body.is_required
500
+ ),
501
+ schema,
496
502
  )
497
503
  value = next(gen, NOT_SET)
498
504
  if isinstance(value, NotSet):
@@ -712,11 +718,13 @@ def _iter_coverage_cases(
712
718
  }
713
719
 
714
720
  def _yield_negative(
715
- subschema: dict[str, Any], _location: str, _container_name: str
721
+ subschema: dict[str, Any], _location: str, _container_name: str, is_required: bool
716
722
  ) -> Generator[Case, None, None]:
717
723
  iterator = iter(
718
724
  coverage.cover_schema_iter(
719
- coverage.CoverageContext(location=_location, generation_modes=[GenerationMode.NEGATIVE]),
725
+ coverage.CoverageContext(
726
+ location=_location, generation_modes=[GenerationMode.NEGATIVE], is_required=is_required
727
+ ),
720
728
  subschema,
721
729
  )
722
730
  )
@@ -751,7 +759,7 @@ def _iter_coverage_cases(
751
759
  )
752
760
  if GenerationMode.NEGATIVE in generation_modes:
753
761
  subschema = _combination_schema(only_required, required, parameter_set)
754
- for case in _yield_negative(subschema, location, container_name):
762
+ for case in _yield_negative(subschema, location, container_name, is_required=bool(required)):
755
763
  kwargs = _case_to_kwargs(case)
756
764
  if not seen_negative.insert(kwargs):
757
765
  continue
@@ -778,7 +786,7 @@ def _iter_coverage_cases(
778
786
  )
779
787
  if GenerationMode.NEGATIVE in generation_modes:
780
788
  subschema = _combination_schema(combo, required, parameter_set)
781
- for case in _yield_negative(subschema, location, container_name):
789
+ for case in _yield_negative(subschema, location, container_name, is_required=bool(required)):
782
790
  assert case.meta is not None
783
791
  assert isinstance(case.meta.phase.data, CoveragePhaseData)
784
792
  # Already generated in one of the blocks above
@@ -20,6 +20,7 @@ from schemathesis.core.errors import (
20
20
  InvalidHeadersExample,
21
21
  InvalidRegexPattern,
22
22
  InvalidSchema,
23
+ SchemathesisError,
23
24
  SerializationNotPossible,
24
25
  format_exception,
25
26
  )
@@ -263,20 +264,27 @@ def pytest_pycollect_makeitem(collector: nodes.Collector, name: str, obj: Any) -
263
264
 
264
265
  @pytest.hookimpl(tryfirst=True) # type: ignore[misc]
265
266
  def pytest_exception_interact(node: Function, call: pytest.CallInfo, report: pytest.TestReport) -> None:
266
- if call.excinfo and call.excinfo.type is FailureGroup:
267
- tb_entries = list(call.excinfo.traceback)
268
- total_frames = len(tb_entries)
269
-
270
- # Keep internal Schemathesis frames + one extra one from the caller
271
- skip_frames = 0
272
- for i in range(total_frames - 1, -1, -1):
273
- entry = tb_entries[i]
274
-
275
- if not str(entry.path).endswith("schemathesis/generation/case.py"):
276
- skip_frames = i
277
- break
278
-
279
- report.longrepr = "".join(format_exception(call.excinfo.value, with_traceback=True, skip_frames=skip_frames))
267
+ if call.excinfo:
268
+ if issubclass(call.excinfo.type, SchemathesisError) and hasattr(call.excinfo.value, "__notes__"):
269
+ # Hypothesis adds quite a lot of additional debug information which is not that helpful in Schemathesis
270
+ call.excinfo.value.__notes__.clear()
271
+ report.longrepr = "".join(format_exception(call.excinfo.value))
272
+ if call.excinfo.type is FailureGroup:
273
+ tb_entries = list(call.excinfo.traceback)
274
+ total_frames = len(tb_entries)
275
+
276
+ # Keep internal Schemathesis frames + one extra one from the caller
277
+ skip_frames = 0
278
+ for i in range(total_frames - 1, -1, -1):
279
+ entry = tb_entries[i]
280
+
281
+ if not str(entry.path).endswith("schemathesis/generation/case.py"):
282
+ skip_frames = i
283
+ break
284
+
285
+ report.longrepr = "".join(
286
+ format_exception(call.excinfo.value, with_traceback=True, skip_frames=skip_frames)
287
+ )
280
288
 
281
289
 
282
290
  @hookimpl(wrapper=True)
@@ -120,7 +120,7 @@ def openapi_cases(
120
120
  for media_type in all_media_types
121
121
  ):
122
122
  # None of media types defined for this operation are not supported
123
- raise SerializationNotPossible.from_media_types(*all_media_types)
123
+ raise SerializationNotPossible.from_media_types(*all_media_types) from None
124
124
  # Other media types are possible - avoid choosing this media type in the future
125
125
  event_text = f"Can't serialize data to `{parameter.media_type}`."
126
126
  note(f"{event_text} {SERIALIZERS_SUGGESTION_MESSAGE}")
@@ -85,6 +85,12 @@ class RequestsTransport(BaseTransport["requests.Session"]):
85
85
  def send(self, case: Case, *, session: requests.Session | None = None, **kwargs: Any) -> Response:
86
86
  import requests
87
87
 
88
+ config = case.operation.schema.config
89
+
90
+ timeout = config.request_timeout_for(operation=case.operation)
91
+ verify = config.tls_verify_for(operation=case.operation)
92
+ cert = config.request_cert_for(operation=case.operation)
93
+
88
94
  if session is not None and session.headers:
89
95
  # These headers are explicitly provided via config or CLI args.
90
96
  # They have lower priority than ones provided via `kwargs`
@@ -94,6 +100,14 @@ class RequestsTransport(BaseTransport["requests.Session"]):
94
100
  kwargs["headers"] = headers
95
101
 
96
102
  data = self.serialize_case(case, **kwargs)
103
+
104
+ if verify is not None:
105
+ data.setdefault("verify", verify)
106
+ if timeout is not None:
107
+ data.setdefault("timeout", timeout)
108
+ if cert is not None:
109
+ data.setdefault("cert", cert)
110
+
97
111
  kwargs.pop("base_url", None)
98
112
  data.update({key: value for key, value in kwargs.items() if key not in data})
99
113
  data.setdefault("timeout", DEFAULT_RESPONSE_TIMEOUT)
@@ -119,7 +133,6 @@ class RequestsTransport(BaseTransport["requests.Session"]):
119
133
  verify = data.get("verify", True)
120
134
 
121
135
  try:
122
- config = case.operation.schema.config
123
136
  rate_limit = config.rate_limit_for(operation=case.operation)
124
137
  with ratelimit(rate_limit, config.base_url):
125
138
  response = session.request(**data) # type: ignore
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: schemathesis
3
- Version: 4.0.2
3
+ Version: 4.0.4
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
@@ -72,26 +72,26 @@ schemathesis/engine/__init__.py,sha256=QaFE-FinaTAaarteADo2RRMJ-Sz6hZB9TzD5KjMin
72
72
  schemathesis/engine/context.py,sha256=x-I9KX6rO6hdCvvN8FEdzIZBqIcNaxdNYHgQjcXbZhM,3931
73
73
  schemathesis/engine/control.py,sha256=FXzP8dxL47j1Giqpy2-Bsr_MdMw9YiATSK_UfpFwDtk,1348
74
74
  schemathesis/engine/core.py,sha256=5jfAqFH0XSD7NVgoSXuUPW-dooItscneAzUNq1RBh1E,5712
75
- schemathesis/engine/errors.py,sha256=cWKuwj0Kzr2BHdVCHACnniUJ8sFVJ0Nqckc3iggZS1o,18800
75
+ schemathesis/engine/errors.py,sha256=HRtFFg-TQ68VmGAM3p6VLOimTU7VaFnv6iKD9-ucjaw,18932
76
76
  schemathesis/engine/events.py,sha256=VV6epicFIJnX4c87fVNSd0ibDccX3gryDv52OUGa3FI,6370
77
77
  schemathesis/engine/recorder.py,sha256=K3HfMARrT5mPWXPnYebjjcq5CcsBRhMrtZwEL9_Lvtg,8432
78
78
  schemathesis/engine/phases/__init__.py,sha256=jUIfb_9QoUo4zmJEVU0z70PgXPYjt8CIqp4qP_HlYHg,3146
79
79
  schemathesis/engine/phases/probes.py,sha256=SEtWKPdkLfRTKV0_tbiNHTK3sJsUUPZ0jZQ9Nv4qUi8,5678
80
80
  schemathesis/engine/phases/stateful/__init__.py,sha256=Lz1rgNqCfUSIz173XqCGsiMuUI5bh4L-RIFexU1-c_Q,2461
81
- schemathesis/engine/phases/stateful/_executor.py,sha256=CV4jUuXpV4uSXVJqDI4btnLR8dpzOQVqbv2qVCgE4_s,15182
81
+ schemathesis/engine/phases/stateful/_executor.py,sha256=_303Yqflx1iFNTQI2EfjSp_2T21YvzJJgMSazhpv5JQ,15200
82
82
  schemathesis/engine/phases/stateful/context.py,sha256=A7X1SLDOWFpCvFN9IiIeNVZM0emjqatmJL_k9UsO7vM,2946
83
83
  schemathesis/engine/phases/unit/__init__.py,sha256=BvZh39LZmXg90Cy_Tn0cQY5y7eWzYvAEmJ43fGKFAt8,8715
84
- schemathesis/engine/phases/unit/_executor.py,sha256=jay_D7fmmBTjZigifmY30RiVP5Jb0OlK450fknSWZ_I,16471
84
+ schemathesis/engine/phases/unit/_executor.py,sha256=9MmZoKSBVSPk0LWwN3PZ3iaO9nzpT1Z70yzdEE48YYw,16489
85
85
  schemathesis/engine/phases/unit/_pool.py,sha256=iU0hdHDmohPnEv7_S1emcabuzbTf-Cznqwn0pGQ5wNQ,2480
86
86
  schemathesis/generation/__init__.py,sha256=tvNO2FLiY8z3fZ_kL_QJhSgzXfnT4UqwSXMHCwfLI0g,645
87
- schemathesis/generation/case.py,sha256=WbOJagE7Gjz3ZvBxzRl8vJHgm_LjW0wf2oRuPzoj6LI,11547
88
- schemathesis/generation/coverage.py,sha256=bKP0idU5-eiK4VwhH4kjxDPtCZzMg81mbN1tEDuT6EA,47913
87
+ schemathesis/generation/case.py,sha256=MuqnKsJBpGm2gaqDFdJi1yGSWgBhqJUwtYaX97kfXgo,11820
88
+ schemathesis/generation/coverage.py,sha256=SlPD8WfrRXca4A9p6P894JXBAqjdCVAto0V4qQrceOE,48825
89
89
  schemathesis/generation/meta.py,sha256=adkoMuCfzSjHJ9ZDocQn0GnVldSCkLL3eVR5A_jafwM,2552
90
90
  schemathesis/generation/metrics.py,sha256=cZU5HdeAMcLFEDnTbNE56NuNq4P0N4ew-g1NEz5-kt4,2836
91
91
  schemathesis/generation/modes.py,sha256=Q1fhjWr3zxabU5qdtLvKfpMFZJAwlW9pnxgenjeXTyU,481
92
92
  schemathesis/generation/overrides.py,sha256=OBWqDQPreiliaf2M-oyXppVKHoJkCRzxtwSJx1b6AFw,3759
93
93
  schemathesis/generation/hypothesis/__init__.py,sha256=SVwM-rx07jPZzms0idWYACgUtWAxh49HRuTnaQ__zf0,1549
94
- schemathesis/generation/hypothesis/builder.py,sha256=xc5U3LfJ1lQHKFFW_9W8n3KFutwA2mv954A4jLhB9vg,33105
94
+ schemathesis/generation/hypothesis/builder.py,sha256=JtKh9hzob2byQrAtf0IXOgKX1c17mLiMQ8f030Hae2Y,33414
95
95
  schemathesis/generation/hypothesis/examples.py,sha256=6eGaKUEC3elmKsaqfKj1sLvM8EHc-PWT4NRBq4NI0Rs,1409
96
96
  schemathesis/generation/hypothesis/given.py,sha256=sTZR1of6XaHAPWtHx2_WLlZ50M8D5Rjux0GmWkWjDq4,2337
97
97
  schemathesis/generation/hypothesis/reporting.py,sha256=uDVow6Ya8YFkqQuOqRsjbzsbyP4KKfr3jA7ZaY4FuKY,279
@@ -110,7 +110,7 @@ schemathesis/pytest/__init__.py,sha256=7W0q-Thcw03IAQfXE_Mo8JPZpUdHJzfu85fjK1Zdf
110
110
  schemathesis/pytest/control_flow.py,sha256=F8rAPsPeNv_sJiJgbZYtTpwKWjauZmqFUaKroY2GmQI,217
111
111
  schemathesis/pytest/lazy.py,sha256=u58q0orI0zisivLJKJkSo53RaQMPLSMiE0vJ1TQ9_uA,11073
112
112
  schemathesis/pytest/loaders.py,sha256=Sbv8e5F77_x4amLP50iwubfm6kpOhx7LhLFGsVXW5Ys,925
113
- schemathesis/pytest/plugin.py,sha256=m4zGLw6A537o4mBb9FvuM4jmAoxfpg0DPLWq5eCLXGc,13818
113
+ schemathesis/pytest/plugin.py,sha256=MXllorF5SqUgqjLyhHb-P0wlWokvZMg0Rm6OTRoFoas,14266
114
114
  schemathesis/python/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
115
115
  schemathesis/python/asgi.py,sha256=5PyvuTBaivvyPUEi3pwJni91K1kX5Zc0u9c6c1D8a1Q,287
116
116
  schemathesis/python/wsgi.py,sha256=uShAgo_NChbfYaV1117e6UHp0MTg7jaR0Sy_to3Jmf8,219
@@ -123,7 +123,7 @@ schemathesis/specs/graphql/schemas.py,sha256=ezkqgMwx37tMWlhy_I0ahDF1Q44emDSJkyj
123
123
  schemathesis/specs/graphql/validation.py,sha256=-W1Noc1MQmTb4RX-gNXMeU2qkgso4mzVfHxtdLkCPKM,1422
124
124
  schemathesis/specs/openapi/__init__.py,sha256=C5HOsfuDJGq_3mv8CRBvRvb0Diy1p0BFdqyEXMS-loE,238
125
125
  schemathesis/specs/openapi/_cache.py,sha256=HpglmETmZU0RCHxp3DO_sg5_B_nzi54Zuw9vGzzYCxY,4295
126
- schemathesis/specs/openapi/_hypothesis.py,sha256=005E_gH4YGhOORQyJtP6vkOOM0-FgiES06JpXRcdL5c,22601
126
+ schemathesis/specs/openapi/_hypothesis.py,sha256=NuXucpwn8jjL_O0anja1TPqEuXyuFq8quIuECIW9BLY,22611
127
127
  schemathesis/specs/openapi/checks.py,sha256=mKJ-ZkbjhbXS4eWDZiv8zslXKFDqkE3Mp4N8TVDHiI0,29801
128
128
  schemathesis/specs/openapi/constants.py,sha256=JqM_FHOenqS_MuUE9sxVQ8Hnw0DNM8cnKDwCwPLhID4,783
129
129
  schemathesis/specs/openapi/converter.py,sha256=lil8IewM5j8tvt4lpA9g_KITvIwx1M96i45DNSHNjoc,3505
@@ -154,11 +154,11 @@ schemathesis/specs/openapi/stateful/links.py,sha256=h5q40jUbcIk5DS_Tih1cvFJxS_Qx
154
154
  schemathesis/transport/__init__.py,sha256=6yg_RfV_9L0cpA6qpbH-SL9_3ggtHQji9CZrpIkbA6s,5321
155
155
  schemathesis/transport/asgi.py,sha256=qTClt6oT_xUEWnRHokACN_uqCNNUZrRPT6YG0PjbElY,926
156
156
  schemathesis/transport/prepare.py,sha256=iiB8KTAqnnuqjWzblIPiGVdkGIF7Yr1SAEz-KZzBNXw,4581
157
- schemathesis/transport/requests.py,sha256=7N0KYcCEVba7fpeL8OphoY0W8B-qNOARrgYC51cg3AE,10227
157
+ schemathesis/transport/requests.py,sha256=rziZTrZCVMAqgy6ldB8iTwhkpAsnjKSgK8hj5Sq3ThE,10656
158
158
  schemathesis/transport/serialization.py,sha256=igUXKZ_VJ9gV7P0TUc5PDQBJXl_s0kK9T3ljGWWvo6E,10339
159
159
  schemathesis/transport/wsgi.py,sha256=KoAfvu6RJtzyj24VGB8e-Iaa9smpgXJ3VsM8EgAz2tc,6152
160
- schemathesis-4.0.2.dist-info/METADATA,sha256=wqlw5M4fnuJgE7zRWt8qKu6TiP1wsPJtMiRLCMfluu8,8471
161
- schemathesis-4.0.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
162
- schemathesis-4.0.2.dist-info/entry_points.txt,sha256=hiK3un-xfgPdwj9uj16YVDtTNpO128bmk0U82SMv8ZQ,152
163
- schemathesis-4.0.2.dist-info/licenses/LICENSE,sha256=2Ve4J8v5jMQAWrT7r1nf3bI8Vflk3rZVQefiF2zpxwg,1121
164
- schemathesis-4.0.2.dist-info/RECORD,,
160
+ schemathesis-4.0.4.dist-info/METADATA,sha256=rRUbFXvyFsf72j7N6smvPu4mMvQYJLnDCvjPwf3XPOY,8471
161
+ schemathesis-4.0.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
162
+ schemathesis-4.0.4.dist-info/entry_points.txt,sha256=hiK3un-xfgPdwj9uj16YVDtTNpO128bmk0U82SMv8ZQ,152
163
+ schemathesis-4.0.4.dist-info/licenses/LICENSE,sha256=2Ve4J8v5jMQAWrT7r1nf3bI8Vflk3rZVQefiF2zpxwg,1121
164
+ schemathesis-4.0.4.dist-info/RECORD,,