schemathesis 4.0.0a11__py3-none-any.whl → 4.0.0b1__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 (73) hide show
  1. schemathesis/__init__.py +35 -27
  2. schemathesis/auths.py +85 -54
  3. schemathesis/checks.py +65 -36
  4. schemathesis/cli/commands/run/__init__.py +32 -27
  5. schemathesis/cli/commands/run/context.py +6 -1
  6. schemathesis/cli/commands/run/events.py +7 -1
  7. schemathesis/cli/commands/run/executor.py +12 -7
  8. schemathesis/cli/commands/run/handlers/output.py +188 -80
  9. schemathesis/cli/commands/run/validation.py +21 -6
  10. schemathesis/cli/constants.py +1 -1
  11. schemathesis/config/__init__.py +2 -1
  12. schemathesis/config/_generation.py +12 -13
  13. schemathesis/config/_operations.py +14 -0
  14. schemathesis/config/_phases.py +41 -5
  15. schemathesis/config/_projects.py +33 -1
  16. schemathesis/config/_report.py +6 -2
  17. schemathesis/config/_warnings.py +25 -0
  18. schemathesis/config/schema.json +49 -1
  19. schemathesis/core/errors.py +15 -19
  20. schemathesis/core/transport.py +117 -2
  21. schemathesis/engine/context.py +1 -0
  22. schemathesis/engine/errors.py +61 -2
  23. schemathesis/engine/events.py +10 -2
  24. schemathesis/engine/phases/probes.py +3 -0
  25. schemathesis/engine/phases/stateful/__init__.py +2 -1
  26. schemathesis/engine/phases/stateful/_executor.py +38 -5
  27. schemathesis/engine/phases/stateful/context.py +2 -2
  28. schemathesis/engine/phases/unit/_executor.py +36 -7
  29. schemathesis/generation/__init__.py +0 -3
  30. schemathesis/generation/case.py +153 -28
  31. schemathesis/generation/coverage.py +1 -1
  32. schemathesis/generation/hypothesis/builder.py +43 -19
  33. schemathesis/generation/metrics.py +93 -0
  34. schemathesis/generation/modes.py +0 -8
  35. schemathesis/generation/overrides.py +11 -27
  36. schemathesis/generation/stateful/__init__.py +17 -0
  37. schemathesis/generation/stateful/state_machine.py +32 -108
  38. schemathesis/graphql/loaders.py +152 -8
  39. schemathesis/hooks.py +63 -39
  40. schemathesis/openapi/checks.py +82 -20
  41. schemathesis/openapi/generation/filters.py +9 -2
  42. schemathesis/openapi/loaders.py +134 -8
  43. schemathesis/pytest/lazy.py +4 -31
  44. schemathesis/pytest/loaders.py +24 -0
  45. schemathesis/pytest/plugin.py +38 -6
  46. schemathesis/schemas.py +161 -94
  47. schemathesis/specs/graphql/scalars.py +37 -3
  48. schemathesis/specs/graphql/schemas.py +18 -9
  49. schemathesis/specs/openapi/_hypothesis.py +53 -34
  50. schemathesis/specs/openapi/checks.py +111 -47
  51. schemathesis/specs/openapi/expressions/nodes.py +1 -1
  52. schemathesis/specs/openapi/formats.py +30 -3
  53. schemathesis/specs/openapi/media_types.py +44 -1
  54. schemathesis/specs/openapi/negative/__init__.py +5 -3
  55. schemathesis/specs/openapi/negative/mutations.py +2 -2
  56. schemathesis/specs/openapi/parameters.py +0 -3
  57. schemathesis/specs/openapi/schemas.py +14 -93
  58. schemathesis/specs/openapi/stateful/__init__.py +2 -1
  59. schemathesis/specs/openapi/stateful/links.py +1 -63
  60. schemathesis/transport/__init__.py +54 -16
  61. schemathesis/transport/prepare.py +31 -7
  62. schemathesis/transport/requests.py +21 -9
  63. schemathesis/transport/serialization.py +0 -4
  64. schemathesis/transport/wsgi.py +15 -8
  65. {schemathesis-4.0.0a11.dist-info → schemathesis-4.0.0b1.dist-info}/METADATA +45 -87
  66. {schemathesis-4.0.0a11.dist-info → schemathesis-4.0.0b1.dist-info}/RECORD +69 -71
  67. schemathesis/contrib/__init__.py +0 -9
  68. schemathesis/contrib/openapi/__init__.py +0 -9
  69. schemathesis/contrib/openapi/fill_missing_examples.py +0 -20
  70. schemathesis/generation/targets.py +0 -69
  71. {schemathesis-4.0.0a11.dist-info → schemathesis-4.0.0b1.dist-info}/WHEEL +0 -0
  72. {schemathesis-4.0.0a11.dist-info → schemathesis-4.0.0b1.dist-info}/entry_points.txt +0 -0
  73. {schemathesis-4.0.0a11.dist-info → schemathesis-4.0.0b1.dist-info}/licenses/LICENSE +0 -0
@@ -8,6 +8,7 @@ from __future__ import annotations
8
8
 
9
9
  import enum
10
10
  import re
11
+ from dataclasses import dataclass
11
12
  from functools import cached_property
12
13
  from typing import TYPE_CHECKING, Callable, Iterator, Sequence, cast
13
14
 
@@ -24,6 +25,8 @@ from schemathesis.core.errors import (
24
25
 
25
26
  if TYPE_CHECKING:
26
27
  import hypothesis.errors
28
+ import requests
29
+ from requests.exceptions import ChunkedEncodingError
27
30
 
28
31
  __all__ = ["EngineErrorInfo", "DeadlineExceeded", "UnsupportedRecursiveReference", "UnexpectedError"]
29
32
 
@@ -61,8 +64,9 @@ class EngineErrorInfo:
61
64
  It serves as a caching wrapper around exceptions to avoid repeated computations.
62
65
  """
63
66
 
64
- def __init__(self, error: Exception) -> None:
67
+ def __init__(self, error: Exception, code_sample: str | None = None) -> None:
65
68
  self._error = error
69
+ self._code_sample = code_sample
66
70
 
67
71
  def __str__(self) -> str:
68
72
  return self._error_repr
@@ -212,6 +216,9 @@ class EngineErrorInfo:
212
216
  message.append("") # Empty line before extras
213
217
  message.extend(f"{indent}{extra}" for extra in extras)
214
218
 
219
+ if self._code_sample is not None:
220
+ message.append(f"\nReproduce with: \n\n {self._code_sample}")
221
+
215
222
  # Suggestion
216
223
  suggestion = get_runtime_error_suggestion(self._kind, bold=bold)
217
224
  if suggestion is not None:
@@ -254,7 +261,7 @@ def get_runtime_error_suggestion(error_type: RuntimeErrorKind, bold: Callable[[s
254
261
  RuntimeErrorKind.SCHEMA_INVALID_REGULAR_EXPRESSION: "Ensure your regex is compatible with Python's syntax.\n"
255
262
  "For guidance, visit: https://docs.python.org/3/library/re.html",
256
263
  RuntimeErrorKind.HYPOTHESIS_UNSUPPORTED_GRAPHQL_SCALAR: "Define a custom strategy for it.\n"
257
- "For guidance, visit: https://schemathesis.readthedocs.io/en/stable/graphql.html#custom-scalars",
264
+ "For guidance, visit: https://schemathesis.readthedocs.io/en/latest/guides/graphql-custom-scalars/",
258
265
  RuntimeErrorKind.HYPOTHESIS_HEALTH_CHECK_DATA_TOO_LARGE: _format_health_check_suggestion("data_too_large"),
259
266
  RuntimeErrorKind.HYPOTHESIS_HEALTH_CHECK_FILTER_TOO_MUCH: _format_health_check_suggestion("filter_too_much"),
260
267
  RuntimeErrorKind.HYPOTHESIS_HEALTH_CHECK_TOO_SLOW: _format_health_check_suggestion("too_slow"),
@@ -403,3 +410,55 @@ def canonicalize_error_message(error: Exception, with_traceback: bool = True) ->
403
410
  message = MEMORY_ADDRESS_RE.sub("0xbaaaaaaaaaad", message)
404
411
  # Remove URL information
405
412
  return URL_IN_ERROR_MESSAGE_RE.sub("", message)
413
+
414
+
415
+ def clear_hypothesis_notes(exc: Exception) -> None:
416
+ notes = getattr(exc, "__notes__", [])
417
+ if any("while generating" in note for note in notes):
418
+ notes.clear()
419
+
420
+
421
+ def is_unrecoverable_network_error(exc: Exception) -> bool:
422
+ from http.client import RemoteDisconnected
423
+
424
+ from urllib3.exceptions import ProtocolError
425
+
426
+ def has_connection_reset(inner: BaseException) -> bool:
427
+ exc_str = str(inner)
428
+ if any(pattern in exc_str for pattern in ["Connection reset by peer", "[Errno 104]", "ECONNRESET"]):
429
+ return True
430
+
431
+ if inner.__context__ is not None:
432
+ return has_connection_reset(inner.__context__)
433
+
434
+ return False
435
+
436
+ if isinstance(exc.__context__, ProtocolError):
437
+ if len(exc.__context__.args) == 2 and isinstance(exc.__context__.args[1], RemoteDisconnected):
438
+ return True
439
+ if len(exc.__context__.args) == 1 and exc.__context__.args[0] == "Response ended prematurely":
440
+ return True
441
+
442
+ return has_connection_reset(exc)
443
+
444
+
445
+ @dataclass()
446
+ class UnrecoverableNetworkError:
447
+ error: requests.ConnectionError | ChunkedEncodingError
448
+ code_sample: str
449
+
450
+ __slots__ = ("error", "code_sample")
451
+
452
+ def __init__(self, error: requests.ConnectionError | ChunkedEncodingError, code_sample: str) -> None:
453
+ self.error = error
454
+ self.code_sample = code_sample
455
+
456
+
457
+ @dataclass
458
+ class TestingState:
459
+ unrecoverable_network_error: UnrecoverableNetworkError | None
460
+
461
+ __slots__ = ("unrecoverable_network_error",)
462
+
463
+ def __init__(self) -> None:
464
+ self.unrecoverable_network_error = None
@@ -200,10 +200,18 @@ class NonFatalError(EngineEvent):
200
200
 
201
201
  __slots__ = ("id", "timestamp", "info", "value", "phase", "label", "related_to_operation")
202
202
 
203
- def __init__(self, *, error: Exception, phase: PhaseName, label: str, related_to_operation: bool) -> None:
203
+ def __init__(
204
+ self,
205
+ *,
206
+ error: Exception,
207
+ phase: PhaseName,
208
+ label: str,
209
+ related_to_operation: bool,
210
+ code_sample: str | None = None,
211
+ ) -> None:
204
212
  self.id = uuid.uuid4()
205
213
  self.timestamp = time.time()
206
- self.info = EngineErrorInfo(error=error)
214
+ self.info = EngineErrorInfo(error=error, code_sample=code_sample)
207
215
  self.value = error
208
216
  self.phase = phase
209
217
  self.label = label
@@ -16,6 +16,7 @@ from typing import TYPE_CHECKING
16
16
  from schemathesis.core.result import Err, Ok, Result
17
17
  from schemathesis.core.transport import USER_AGENT
18
18
  from schemathesis.engine import Status, events
19
+ from schemathesis.transport.prepare import get_default_headers
19
20
 
20
21
  if TYPE_CHECKING:
21
22
  import requests
@@ -134,6 +135,8 @@ def send(probe: Probe, ctx: EngineContext) -> ProbeRun:
134
135
  request = probe.prepare_request(session, Request(), ctx.schema)
135
136
  request.headers[HEADER_NAME] = probe.name
136
137
  request.headers["User-Agent"] = USER_AGENT
138
+ for header, value in get_default_headers().items():
139
+ request.headers.setdefault(header, value)
137
140
  with warnings.catch_warnings():
138
141
  warnings.simplefilter("ignore", InsecureRequestWarning)
139
142
  response = session.send(request, timeout=ctx.config.request_timeout or 2)
@@ -6,6 +6,7 @@ from typing import TYPE_CHECKING
6
6
 
7
7
  from schemathesis.engine import Status, events
8
8
  from schemathesis.engine.phases import Phase, PhaseName, PhaseSkipReason
9
+ from schemathesis.generation.stateful import STATEFUL_TESTS_LABEL
9
10
 
10
11
  if TYPE_CHECKING:
11
12
  from schemathesis.engine.context import EngineContext
@@ -19,7 +20,7 @@ def execute(engine: EngineContext, phase: Phase) -> events.EventGenerator:
19
20
  try:
20
21
  state_machine = engine.schema.as_state_machine()
21
22
  except Exception as exc:
22
- yield events.NonFatalError(error=exc, phase=phase.name, label="Stateful tests", related_to_operation=False)
23
+ yield events.NonFatalError(error=exc, phase=phase.name, label=STATEFUL_TESTS_LABEL, related_to_operation=False)
23
24
  yield events.PhaseFinished(phase=phase, status=Status.ERROR, payload=None)
24
25
  return
25
26
 
@@ -1,4 +1,4 @@
1
- from __future__ import annotations
1
+ from __future__ import annotations # noqa: I001
2
2
 
3
3
  import queue
4
4
  import time
@@ -8,9 +8,11 @@ from typing import Any
8
8
  from warnings import catch_warnings
9
9
 
10
10
  import hypothesis
11
+ import requests
11
12
  from hypothesis.control import current_build_context
12
13
  from hypothesis.errors import Flaky, Unsatisfiable
13
14
  from hypothesis.stateful import Rule
15
+ from requests.exceptions import ChunkedEncodingError
14
16
  from requests.structures import CaseInsensitiveDict
15
17
 
16
18
  from schemathesis.checks import CheckContext, CheckFunction, run_checks
@@ -19,19 +21,26 @@ from schemathesis.core.transport import Response
19
21
  from schemathesis.engine import Status, events
20
22
  from schemathesis.engine.context import EngineContext
21
23
  from schemathesis.engine.control import ExecutionControl
24
+ from schemathesis.engine.errors import (
25
+ TestingState,
26
+ UnrecoverableNetworkError,
27
+ clear_hypothesis_notes,
28
+ is_unrecoverable_network_error,
29
+ )
22
30
  from schemathesis.engine.phases import PhaseName
23
31
  from schemathesis.engine.phases.stateful.context import StatefulContext
24
32
  from schemathesis.engine.recorder import ScenarioRecorder
25
33
  from schemathesis.generation import overrides
26
34
  from schemathesis.generation.case import Case
27
35
  from schemathesis.generation.hypothesis.reporting import ignore_hypothesis_output
36
+ from schemathesis.generation.stateful import STATEFUL_TESTS_LABEL
28
37
  from schemathesis.generation.stateful.state_machine import (
29
38
  DEFAULT_STATE_MACHINE_SETTINGS,
30
39
  APIStateMachine,
31
40
  StepInput,
32
41
  StepOutput,
33
42
  )
34
- from schemathesis.generation.targets import TargetMetricCollector
43
+ from schemathesis.generation.metrics import MetricCollector
35
44
 
36
45
 
37
46
  def _get_hypothesis_settings_kwargs_override(settings: hypothesis.settings) -> dict[str, Any]:
@@ -72,7 +81,8 @@ def execute_state_machine_loop(
72
81
  hypothesis_settings = hypothesis.settings(configured_hypothesis_settings, **kwargs)
73
82
  generation = engine.config.generation_for(phase="stateful")
74
83
 
75
- ctx = StatefulContext(metric_collector=TargetMetricCollector(targets=generation.maximize))
84
+ ctx = StatefulContext(metric_collector=MetricCollector(metrics=generation.maximize))
85
+ state = TestingState()
76
86
 
77
87
  # Caches for validate_response to avoid repeated config lookups per operation
78
88
  _check_context_cache: dict[str, CachedCheckContextData] = {}
@@ -123,6 +133,20 @@ def execute_state_machine_loop(
123
133
  ctx.step_failed()
124
134
  raise
125
135
  except Exception as exc:
136
+ if isinstance(exc, (requests.ConnectionError, ChunkedEncodingError)) and is_unrecoverable_network_error(
137
+ exc
138
+ ):
139
+ transport_kwargs = engine.get_transport_kwargs(operation=input.case.operation)
140
+ if exc.request is not None:
141
+ headers = {key: value[0] for key, value in exc.request.headers.items()}
142
+ else:
143
+ headers = {**dict(input.case.headers or {}), **transport_kwargs.get("headers", {})}
144
+ verify = transport_kwargs.get("verify", True)
145
+ state.unrecoverable_network_error = UnrecoverableNetworkError(
146
+ error=exc,
147
+ code_sample=input.case.as_curl_command(headers=headers, verify=verify),
148
+ )
149
+
126
150
  if generation.unique_inputs:
127
151
  ctx.store_step_outcome(input.case, exc)
128
152
  ctx.step_errored()
@@ -172,7 +196,7 @@ def execute_state_machine_loop(
172
196
  case=case,
173
197
  stateful_ctx=ctx,
174
198
  check_ctx=check_ctx,
175
- checks=check_ctx.checks,
199
+ checks=check_ctx._checks,
176
200
  control=engine.control,
177
201
  recorder=self.recorder,
178
202
  additional_checks=additional_checks,
@@ -259,11 +283,20 @@ def execute_state_machine_loop(
259
283
  # Avoid infinite restarts
260
284
  break
261
285
  continue
286
+ clear_hypothesis_notes(exc)
262
287
  # Any other exception is an inner error and the test run should be stopped
263
288
  suite_status = Status.ERROR
289
+ code_sample: str | None = None
290
+ if state.unrecoverable_network_error is not None:
291
+ exc = state.unrecoverable_network_error.error
292
+ code_sample = state.unrecoverable_network_error.code_sample
264
293
  event_queue.put(
265
294
  events.NonFatalError(
266
- error=exc, phase=PhaseName.STATEFUL_TESTING, label="Stateful tests", related_to_operation=False
295
+ error=exc,
296
+ phase=PhaseName.STATEFUL_TESTING,
297
+ label=STATEFUL_TESTS_LABEL,
298
+ related_to_operation=False,
299
+ code_sample=code_sample,
267
300
  )
268
301
  )
269
302
  break
@@ -7,7 +7,7 @@ from schemathesis.core.failures import Failure
7
7
  from schemathesis.core.transport import Response
8
8
  from schemathesis.engine import Status
9
9
  from schemathesis.generation.case import Case
10
- from schemathesis.generation.targets import TargetMetricCollector
10
+ from schemathesis.generation.metrics import MetricCollector
11
11
 
12
12
 
13
13
  @dataclass
@@ -27,7 +27,7 @@ class StatefulContext:
27
27
  # The total number of completed test scenario
28
28
  completed_scenarios: int = 0
29
29
  # Metrics collector for targeted testing
30
- metric_collector: TargetMetricCollector = field(default_factory=TargetMetricCollector)
30
+ metric_collector: MetricCollector = field(default_factory=MetricCollector)
31
31
  step_outcomes: dict[int, BaseException | None] = field(default_factory=dict)
32
32
 
33
33
  @property
@@ -11,6 +11,7 @@ from hypothesis.errors import InvalidArgument
11
11
  from hypothesis_jsonschema._canonicalise import HypothesisRefResolutionError
12
12
  from jsonschema.exceptions import SchemaError as JsonSchemaError
13
13
  from jsonschema.exceptions import ValidationError
14
+ from requests.exceptions import ChunkedEncodingError
14
15
  from requests.structures import CaseInsensitiveDict
15
16
 
16
17
  from schemathesis.checks import CheckContext, run_checks
@@ -33,13 +34,17 @@ from schemathesis.engine import Status, events
33
34
  from schemathesis.engine.context import EngineContext
34
35
  from schemathesis.engine.errors import (
35
36
  DeadlineExceeded,
37
+ TestingState,
36
38
  UnexpectedError,
39
+ UnrecoverableNetworkError,
37
40
  UnsupportedRecursiveReference,
41
+ clear_hypothesis_notes,
38
42
  deduplicate_errors,
43
+ is_unrecoverable_network_error,
39
44
  )
40
45
  from schemathesis.engine.phases import PhaseName
41
46
  from schemathesis.engine.recorder import ScenarioRecorder
42
- from schemathesis.generation import overrides, targets
47
+ from schemathesis.generation import metrics, overrides
43
48
  from schemathesis.generation.case import Case
44
49
  from schemathesis.generation.hypothesis.builder import (
45
50
  InvalidHeadersExampleMark,
@@ -70,9 +75,12 @@ def run_test(
70
75
  skip_reason = None
71
76
  test_start_time = time.monotonic()
72
77
  recorder = ScenarioRecorder(label=operation.label)
78
+ state = TestingState()
73
79
 
74
- def non_fatal_error(error: Exception) -> events.NonFatalError:
75
- return events.NonFatalError(error=error, phase=phase, label=operation.label, related_to_operation=True)
80
+ def non_fatal_error(error: Exception, code_sample: str | None = None) -> events.NonFatalError:
81
+ return events.NonFatalError(
82
+ error=error, phase=phase, label=operation.label, related_to_operation=True, code_sample=code_sample
83
+ )
76
84
 
77
85
  def scenario_finished(status: Status) -> events.ScenarioFinished:
78
86
  return events.ScenarioFinished(
@@ -111,6 +119,7 @@ def run_test(
111
119
  with catch_warnings(record=True) as warnings, ignore_hypothesis_output():
112
120
  test_function(
113
121
  ctx=ctx,
122
+ state=state,
114
123
  errors=errors,
115
124
  check_ctx=check_ctx,
116
125
  recorder=recorder,
@@ -198,6 +207,7 @@ def run_test(
198
207
  yield non_fatal_error(InvalidRegexPattern.from_schema_error(exc, from_examples=False))
199
208
  except Exception as exc:
200
209
  status = Status.ERROR
210
+ clear_hypothesis_notes(exc)
201
211
  # Likely a YAML parsing issue. E.g. `00:00:00.00` (without quotes) is parsed as float `0.0`
202
212
  if str(exc) == "first argument must be string or compiled pattern":
203
213
  yield non_fatal_error(
@@ -207,7 +217,10 @@ def run_test(
207
217
  )
208
218
  )
209
219
  else:
210
- yield non_fatal_error(exc)
220
+ code_sample: str | None = None
221
+ if state.unrecoverable_network_error is not None and state.unrecoverable_network_error.error is exc:
222
+ code_sample = state.unrecoverable_network_error.code_sample
223
+ yield non_fatal_error(exc, code_sample=code_sample)
211
224
  if (
212
225
  status == Status.SUCCESS
213
226
  and continue_on_failure
@@ -270,6 +283,7 @@ def cached_test_func(f: Callable) -> Callable:
270
283
  def wrapped(
271
284
  *,
272
285
  ctx: EngineContext,
286
+ state: TestingState,
273
287
  case: Case,
274
288
  errors: list[Exception],
275
289
  check_ctx: CheckContext,
@@ -313,6 +327,21 @@ def cached_test_func(f: Callable) -> Callable:
313
327
  except (KeyboardInterrupt, Failure):
314
328
  raise
315
329
  except Exception as exc:
330
+ if isinstance(exc, (requests.ConnectionError, ChunkedEncodingError)) and is_unrecoverable_network_error(
331
+ exc
332
+ ):
333
+ # Server likely has crashed and does not accept any connections at all
334
+ # Don't report these error - only the original crash should be reported
335
+ if exc.request is not None:
336
+ headers = {key: value[0] for key, value in exc.request.headers.items()}
337
+ else:
338
+ headers = {**dict(case.headers or {}), **transport_kwargs.get("headers", {})}
339
+ verify = transport_kwargs.get("verify", True)
340
+ state.unrecoverable_network_error = UnrecoverableNetworkError(
341
+ error=exc,
342
+ code_sample=case.as_curl_command(headers=headers, verify=verify),
343
+ )
344
+ raise
316
345
  errors.append(exc)
317
346
  raise UnexpectedError from None
318
347
 
@@ -334,14 +363,14 @@ def test_func(
334
363
  recorder.record_case(parent_id=None, transition=None, case=case)
335
364
  try:
336
365
  response = case.call(**transport_kwargs)
337
- except (requests.Timeout, requests.ConnectionError) as error:
366
+ except (requests.Timeout, requests.ConnectionError, ChunkedEncodingError) as error:
338
367
  if isinstance(error.request, requests.Request):
339
368
  recorder.record_request(case_id=case.id, request=error.request.prepare())
340
369
  elif isinstance(error.request, requests.PreparedRequest):
341
370
  recorder.record_request(case_id=case.id, request=error.request)
342
371
  raise
343
372
  recorder.record_response(case_id=case.id, response=response)
344
- targets.run(generation.maximize, case=case, response=response)
373
+ metrics.maximize(generation.maximize, case=case, response=response)
345
374
  validate_response(
346
375
  case=case,
347
376
  ctx=check_ctx,
@@ -378,7 +407,7 @@ def validate_response(
378
407
  case=case,
379
408
  response=response,
380
409
  ctx=ctx,
381
- checks=ctx.checks,
410
+ checks=ctx._checks,
382
411
  on_failure=on_failure,
383
412
  on_success=on_success,
384
413
  )
@@ -10,9 +10,6 @@ __all__ = [
10
10
  ]
11
11
 
12
12
 
13
- DEFAULT_GENERATOR_MODES = [GenerationMode.default()]
14
-
15
-
16
13
  CASE_ID_ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
17
14
  BASE = len(CASE_ID_ALPHABET)
18
15
  # Separate `Random` as Hypothesis might interfere with the default one