Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/hypothesis/errors.py: 65%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# This file is part of Hypothesis, which may be found at
2# https://github.com/HypothesisWorks/hypothesis/
3#
4# Copyright the Hypothesis Authors.
5# Individual contributors are listed in AUTHORS.rst and the git log.
6#
7# This Source Code Form is subject to the terms of the Mozilla Public License,
8# v. 2.0. If a copy of the MPL was not distributed with this file, You can
9# obtain one at https://mozilla.org/MPL/2.0/.
11from collections.abc import Mapping
12from datetime import timedelta
13from typing import TYPE_CHECKING, Any, Literal
15from hypothesis.internal.compat import ExceptionGroup
17if TYPE_CHECKING:
18 from hypothesis.internal.conjecture.choice import ChoiceConstraintsT
19else:
20 ChoiceConstraintsT = Mapping
23class HypothesisException(Exception):
24 """Generic parent class for exceptions thrown by Hypothesis."""
27class _Trimmable(HypothesisException):
28 """Hypothesis can trim these tracebacks even if they're raised internally."""
31class UnsatisfiedAssumption(HypothesisException):
32 """An internal error raised by assume.
34 If you're seeing this error something has gone wrong.
35 """
37 def __init__(self, reason: str | None = None) -> None:
38 self.reason = reason
41class NoSuchExample(HypothesisException):
42 """The condition we have been asked to satisfy appears to be always false.
44 This does not guarantee that no example exists, only that we were
45 unable to find one.
46 """
48 def __init__(self, condition_string: str, extra: str = "") -> None:
49 super().__init__(f"No examples found of condition {condition_string}{extra}")
52class Unsatisfiable(_Trimmable):
53 """We ran out of test cases before we could find enough which satisfy the
54 assumptions of this hypothesis.
56 This could be because the function is using |assume| in a way that is
57 too hard to satisfy. If so, try writing a custom strategy or using a
58 better starting point (e.g if you are requiring a list has unique
59 values you could instead filter out all duplicate values from the list)
60 """
63class ChoiceTooLarge(HypothesisException):
64 """An internal error raised by choice_from_index."""
67class Flaky(_Trimmable):
68 """
69 Base class for indeterministic failures. Usually one of the more
70 specific subclasses (|FlakyFailure| or |FlakyStrategyDefinition|) is raised.
72 .. seealso::
74 See also the :doc:`flaky failures tutorial </tutorial/flaky>`.
75 """
78class FlakyReplay(Flaky):
79 """Internal error raised by the conjecture engine if flaky failures are
80 detected during replay.
82 Carries information allowing the runner to reconstruct the flakiness as
83 a FlakyFailure exception group for final presentation.
84 """
86 def __init__(self, reason, interesting_origins=None):
87 super().__init__(reason)
88 self.reason = reason
89 self._interesting_origins = interesting_origins
92def _render_constraints(show: Mapping[str, object], other: Mapping[str, object]) -> str:
93 assert show.keys() == other.keys()
94 return ", ".join(
95 f"{k}={'...' if v == other[k] else repr(v)}" for k, v in show.items()
96 )
99class FlakyStrategyDefinition(Flaky):
100 """
101 This function appears to cause inconsistent data generation.
103 Common causes for this problem are:
104 1. The strategy depends on external state. e.g. it uses an external
105 random number generator. Try to make a version that passes all the
106 relevant state in from Hypothesis.
108 .. seealso::
110 See also the :doc:`flaky failures tutorial </tutorial/flaky>`.
111 """
113 _BASE_MESSAGE = (
114 "Inconsistent data generation! Data generation behaved differently "
115 "between test cases. Is your data generation depending on external "
116 "state?"
117 )
119 @classmethod
120 def with_detail(cls, detail: str) -> "FlakyStrategyDefinition":
121 return cls(f"{cls._BASE_MESSAGE}\n\n{detail}")
123 @classmethod
124 def from_mismatch(
125 cls,
126 expected_type: str,
127 expected_constraints: ChoiceConstraintsT,
128 actual_type: str,
129 actual_constraints: ChoiceConstraintsT,
130 ) -> "FlakyStrategyDefinition":
131 if actual_type != expected_type:
132 detail = (
133 "The second test case drew a different type of value than the first.\n"
134 f" first: {expected_type}\n"
135 f" second: {actual_type}\n"
136 )
137 else:
138 detail = (
139 f"The second test case drew type {actual_type} with different constraints "
140 "than the first.\n"
141 f" first: {_render_constraints(expected_constraints, actual_constraints)}\n"
142 f" second: {_render_constraints(actual_constraints, expected_constraints)}\n"
143 )
144 return cls.with_detail(detail)
147class _WrappedBaseException(Exception):
148 """Used internally for wrapping BaseExceptions as components of FlakyFailure."""
151class FlakyFailure(ExceptionGroup, Flaky):
152 """
153 This function appears to fail non-deterministically: We have seen it
154 fail when passed this value at least once, but a subsequent invocation
155 did not fail, or caused a distinct error.
157 Common causes for this problem are:
158 1. The function depends on external state. e.g. it uses an external
159 random number generator. Try to make a version that passes all the
160 relevant state in from Hypothesis.
161 2. The function is suffering from too much recursion and its failure
162 depends sensitively on where it's been called from.
163 3. The function is timing sensitive and can fail or pass depending on
164 how long it takes. Try breaking it up into smaller functions which
165 don't do that and testing those instead.
167 .. seealso::
169 See also the :doc:`flaky failures tutorial </tutorial/flaky>`.
170 """
172 def __new__(cls, msg, group):
173 # The Exception mixin forces this an ExceptionGroup (only accepting
174 # Exceptions, not BaseException). Usually BaseException is raised
175 # directly and will hence not be part of a FlakyFailure, but I'm not
176 # sure this assumption holds everywhere. So wrap any BaseExceptions.
177 group = list(group)
178 for i, exc in enumerate(group):
179 if not isinstance(exc, Exception):
180 err = _WrappedBaseException()
181 err.__cause__ = err.__context__ = exc
182 group[i] = err
183 return ExceptionGroup.__new__(cls, msg, group)
185 # defining `derive` is required for `split` to return an instance of FlakyFailure
186 # instead of ExceptionGroup. See https://github.com/python/cpython/issues/119287
187 # and https://docs.python.org/3/library/exceptions.html#BaseExceptionGroup.derive
188 def derive(self, excs):
189 return type(self)(self.message, excs)
192class FlakyBackendFailure(FlakyFailure):
193 """
194 A failure was reported by an |alternative backend|,
195 but this failure did not reproduce when replayed under the Hypothesis backend.
197 When an alternative backend reports a failure, Hypothesis first replays it
198 under the standard Hypothesis backend to check for flakiness. If the failure
199 does not reproduce, Hypothesis raises this exception.
200 """
203class InvalidArgument(_Trimmable, TypeError):
204 """Used to indicate that the arguments to a Hypothesis function were in
205 some manner incorrect."""
208class ResolutionFailed(InvalidArgument):
209 """Hypothesis had to resolve a type to a strategy, but this failed.
211 Type inference is best-effort, so this only happens when an
212 annotation exists but could not be resolved for a required argument
213 to the target of ``builds()``, or where the user passed ``...``.
214 """
217class InvalidState(HypothesisException):
218 """The system is not in a state where you were allowed to do that."""
221class InvalidDefinition(_Trimmable, TypeError):
222 """Used to indicate that a class definition was not well put together and
223 has something wrong with it."""
226class HypothesisWarning(HypothesisException, Warning):
227 """A generic warning issued by Hypothesis."""
230class FailedHealthCheck(_Trimmable):
231 """Raised when a test fails a health check. See |HealthCheck|."""
234class NonInteractiveExampleWarning(HypothesisWarning):
235 """
236 Emitted when |.example| is used outside of interactive use.
238 |.example| is intended for exploratory and interactive work, not to be run as
239 part of a test suite.
240 """
243class HypothesisDeprecationWarning(HypothesisWarning, FutureWarning):
244 """A deprecation warning issued by Hypothesis.
246 Actually inherits from FutureWarning, because DeprecationWarning is
247 hidden by the default warnings filter.
249 You can configure the :mod:`python:warnings` module to handle these
250 warnings differently to others, either turning them into errors or
251 suppressing them entirely. Obviously we would prefer the former!
252 """
255class HypothesisSideeffectWarning(HypothesisWarning):
256 """A warning issued by Hypothesis when it sees actions that are
257 discouraged at import or initialization time because they are
258 slow or have user-visible side effects.
259 """
262class Frozen(HypothesisException):
263 """Raised when a mutation method has been called on a ConjectureData object
264 after freeze() has been called."""
267def __getattr__(name: str) -> Any:
268 if name == "MultipleFailures":
269 from hypothesis.internal.compat import BaseExceptionGroup
270 from hypothesis.utils.deprecation import note_deprecation
272 note_deprecation(
273 "MultipleFailures is deprecated; use the builtin `BaseExceptionGroup` type "
274 "instead, or `exceptiongroup.BaseExceptionGroup` before Python 3.11",
275 since="2022-08-02",
276 has_codemod=False, # This would be a great PR though!
277 stacklevel=1,
278 )
279 return BaseExceptionGroup
281 raise AttributeError(f"Module 'hypothesis.errors' has no attribute {name}")
284class DeadlineExceeded(_Trimmable):
285 """
286 Raised when an input takes too long to run, relative to the |settings.deadline|
287 setting.
288 """
290 def __init__(self, runtime: timedelta, deadline: timedelta) -> None:
291 super().__init__(
292 f"Test took {runtime.total_seconds() * 1000:.2f}ms, which exceeds "
293 f"the deadline of {deadline.total_seconds() * 1000:.2f}ms. If you "
294 "expect test cases to take this long, you can use @settings(deadline=...) "
295 "to either set a higher deadline, or to disable it with deadline=None."
296 )
297 self.runtime = runtime
298 self.deadline = deadline
300 def __reduce__(
301 self,
302 ) -> tuple[type["DeadlineExceeded"], tuple[timedelta, timedelta]]:
303 return (type(self), (self.runtime, self.deadline))
306class StopTest(BaseException):
307 """Raised when a test should stop running and return control to
308 the Hypothesis engine, which should then continue normally.
309 """
311 def __init__(self, testcounter: int) -> None:
312 super().__init__(repr(testcounter))
313 self.testcounter = testcounter
316class DidNotReproduce(HypothesisException):
317 pass
320class Found(HypothesisException):
321 """Signal that the example matches condition. Internal use only."""
324class RewindRecursive(Exception):
325 """Signal that the type inference should be rewound due to recursive types. Internal use only."""
327 def __init__(self, target: object) -> None:
328 self.target = target
331class SmallSearchSpaceWarning(HypothesisWarning):
332 """Indicates that an inferred strategy does not span the search space
333 in a meaningful way, for example by only creating default instances."""
336CannotProceedScopeT = Literal["verified", "exhausted", "discard_test_case", "other"]
337_valid_cannot_proceed_scopes = CannotProceedScopeT.__args__ # type: ignore
340class BackendCannotProceed(HypothesisException):
341 """
342 Raised by alternative backends when a |PrimitiveProvider| cannot proceed.
343 This is expected to occur inside one of the ``.draw_*()`` methods, or for
344 symbolic execution perhaps in |PrimitiveProvider.realize|.
346 The optional ``scope`` argument can enable smarter integration:
348 verified:
349 Do not request further |test cases| from this backend. We *may*
350 generate more test cases with other backends; if one fails then
351 Hypothesis will report unsound verification in the backend too.
353 exhausted:
354 Do not request further test cases from this backend; finish testing
355 with test cases generated with the default backend. Common if e.g.
356 native code blocks symbolic reasoning very early.
358 discard_test_case:
359 This particular test case could not be converted to concrete values;
360 skip any further processing and continue with another test case from
361 this backend.
362 """
364 def __init__(self, scope: CannotProceedScopeT = "other", /) -> None:
365 if scope not in _valid_cannot_proceed_scopes:
366 raise InvalidArgument(
367 f"Got scope={scope}, but expected one of "
368 f"{_valid_cannot_proceed_scopes!r}"
369 )
370 self.scope = scope