Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/hypothesis/_settings.py: 71%
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/.
11"""The settings module configures runtime options for Hypothesis.
13Either an explicit settings object can be used or the default object on
14this module can be modified.
15"""
17import contextlib
18import datetime
19import inspect
20import os
21import warnings
22from collections.abc import Collection, Generator, Sequence
23from enum import Enum, EnumMeta, unique
24from functools import total_ordering
25from typing import (
26 TYPE_CHECKING,
27 Any,
28 ClassVar,
29 Optional,
30 TypeVar,
31)
33from hypothesis.errors import (
34 HypothesisDeprecationWarning,
35 InvalidArgument,
36)
37from hypothesis.internal.conjecture.providers import AVAILABLE_PROVIDERS
38from hypothesis.internal.reflection import get_pretty_function_description
39from hypothesis.internal.validation import check_type, try_convert
40from hypothesis.utils.conventions import not_set
41from hypothesis.utils.dynamicvariables import DynamicVariable
43if TYPE_CHECKING:
44 from hypothesis.database import ExampleDatabase
46__all__ = ["settings"]
48T = TypeVar("T")
49all_settings: list[str] = [
50 "max_examples",
51 "derandomize",
52 "database",
53 "verbosity",
54 "phases",
55 "stateful_step_count",
56 "report_multiple_bugs",
57 "suppress_health_check",
58 "deadline",
59 "print_blob",
60 "backend",
61]
64@unique
65@total_ordering
66class Verbosity(Enum):
67 """Options for the |settings.verbosity| argument to |@settings|."""
69 quiet = "quiet"
70 """
71 Hypothesis will not print any output, not even the final falsifying example.
72 """
74 normal = "normal"
75 """
76 Standard verbosity. Hypothesis will print the falsifying example, alongside
77 any notes made with |note| (only for the falsfying example).
78 """
80 verbose = "verbose"
81 """
82 Increased verbosity. In addition to everything in |Verbosity.normal|, Hypothesis
83 will:
85 * Print each test case as it tries it
86 * Print any notes made with |note| for each test case
87 * Print each shrinking attempt
88 * Print all explicit failing examples when using |@example|, instead of only
89 the simplest one
90 """
92 debug = "debug"
93 """
94 Even more verbosity. Useful for debugging Hypothesis internals. You probably
95 don't want this.
96 """
98 @classmethod
99 def _missing_(cls, value):
100 # deprecation pathway for integer values. Can be removed in Hypothesis 7.
101 if isinstance(value, int) and not isinstance(value, bool):
102 int_to_name = {0: "quiet", 1: "normal", 2: "verbose", 3: "debug"}
103 if value in int_to_name:
104 note_deprecation(
105 f"Passing Verbosity({value}) as an integer is deprecated. "
106 "Hypothesis now treats Verbosity values as strings, not integers. "
107 f"Use Verbosity.{int_to_name[value]} instead.",
108 since="2025-11-05",
109 has_codemod=False,
110 stacklevel=2,
111 )
112 return cls(int_to_name[value])
113 return None
115 def __repr__(self) -> str:
116 return f"Verbosity.{self.name}"
118 @staticmethod
119 def _int_value(value: "Verbosity") -> int:
120 # we would just map Verbosity keys, except it's not hashable
121 mapping = {
122 Verbosity.quiet.name: 0,
123 Verbosity.normal.name: 1,
124 Verbosity.verbose.name: 2,
125 Verbosity.debug.name: 3,
126 }
127 # make sure we don't forget any new verbosity members
128 assert list(mapping.keys()) == [verbosity.name for verbosity in Verbosity]
129 return mapping[value.name]
131 def __eq__(self, other: Any) -> bool:
132 if isinstance(other, Verbosity):
133 return super().__eq__(other)
134 return Verbosity._int_value(self) == other
136 def __gt__(self, other: Any) -> bool:
137 value1 = Verbosity._int_value(self)
138 value2 = Verbosity._int_value(other) if isinstance(other, Verbosity) else other
139 return value1 > value2
142@unique
143class Phase(Enum):
144 """Options for the |settings.phases| argument to |@settings|."""
146 explicit = "explicit"
147 """
148 Controls whether explicit examples are run.
149 """
151 reuse = "reuse"
152 """
153 Controls whether previous examples will be reused.
154 """
156 generate = "generate"
157 """
158 Controls whether new examples will be generated.
159 """
161 target = "target"
162 """
163 Controls whether examples will be mutated for targeting.
164 """
166 shrink = "shrink"
167 """
168 Controls whether examples will be shrunk.
169 """
171 explain = "explain"
172 """
173 Controls whether Hypothesis attempts to explain test failures.
175 The explain phase has two parts, each of which is best-effort - if Hypothesis
176 can't find a useful explanation, we'll just print the minimal failing example.
177 """
179 @classmethod
180 def _missing_(cls, value):
181 # deprecation pathway for integer values. Can be removed in Hypothesis 7.
182 if isinstance(value, int) and not isinstance(value, bool):
183 int_to_name = {
184 0: "explicit",
185 1: "reuse",
186 2: "generate",
187 3: "target",
188 4: "shrink",
189 5: "explain",
190 }
191 if value in int_to_name:
192 note_deprecation(
193 f"Passing Phase({value}) as an integer is deprecated. "
194 "Hypothesis now treats Phase values as strings, not integers. "
195 f"Use Phase.{int_to_name[value]} instead.",
196 since="2025-11-05",
197 has_codemod=False,
198 stacklevel=2,
199 )
200 return cls(int_to_name[value])
201 return None
203 def __repr__(self) -> str:
204 return f"Phase.{self.name}"
207class HealthCheckMeta(EnumMeta):
208 def __iter__(self):
209 deprecated = (HealthCheck.return_value, HealthCheck.not_a_test_method)
210 return iter(x for x in super().__iter__() if x not in deprecated)
213@unique
214class HealthCheck(Enum, metaclass=HealthCheckMeta):
215 """
216 A |HealthCheck| is proactively raised by Hypothesis when Hypothesis detects
217 that your test has performance problems, which may result in less rigorous
218 testing than you expect. For example, if your test takes a long time to generate
219 inputs, or filters away too many inputs using |assume| or |filter|, Hypothesis
220 will raise a corresponding health check.
222 A health check is a proactive warning, not an error. We encourage suppressing
223 health checks where you have evaluated they will not pose a problem, or where
224 you have evaluated that fixing the underlying issue is not worthwhile.
226 With the exception of |HealthCheck.function_scoped_fixture| and
227 |HealthCheck.differing_executors|, all health checks warn about performance
228 problems, not correctness errors.
230 Disabling health checks
231 -----------------------
233 Health checks can be disabled by |settings.suppress_health_check|. To suppress
234 all health checks, you can pass ``suppress_health_check=list(HealthCheck)``.
236 .. seealso::
238 See also the :doc:`/how-to/suppress-healthchecks` how-to.
240 Correctness health checks
241 -------------------------
243 Some health checks report potential correctness errors, rather than performance
244 problems.
246 * |HealthCheck.function_scoped_fixture| indicates that a function-scoped
247 pytest fixture is used by an |@given| test. Many Hypothesis users expect
248 function-scoped fixtures to reset once per input, but they actually reset once
249 per test. We proactively raise |HealthCheck.function_scoped_fixture| to
250 ensure you have considered this case.
251 * |HealthCheck.differing_executors| indicates that the same |@given| test has
252 been executed multiple times with multiple distinct executors.
254 We recommend treating these particular health checks with more care, as
255 suppressing them may result in an unsound test.
256 """
258 @classmethod
259 def _missing_(cls, value):
260 # deprecation pathway for integer values. Can be removed in Hypothesis 7.
261 if isinstance(value, int) and not isinstance(value, bool):
262 int_to_name = {
263 1: "data_too_large",
264 2: "filter_too_much",
265 3: "too_slow",
266 5: "return_value",
267 7: "large_base_example",
268 8: "not_a_test_method",
269 9: "function_scoped_fixture",
270 10: "differing_executors",
271 11: "nested_given",
272 }
273 if value in int_to_name:
274 note_deprecation(
275 f"Passing HealthCheck({value}) as an integer is deprecated. "
276 "Hypothesis now treats HealthCheck values as strings, not integers. "
277 f"Use HealthCheck.{int_to_name[value]} instead.",
278 since="2025-11-05",
279 has_codemod=False,
280 stacklevel=2,
281 )
282 return cls(int_to_name[value])
283 return None
285 def __repr__(self) -> str:
286 return f"{self.__class__.__name__}.{self.name}"
288 @classmethod
289 def all(cls) -> list["HealthCheck"]:
290 # Skipping of deprecated attributes is handled in HealthCheckMeta.__iter__
291 note_deprecation(
292 "`HealthCheck.all()` is deprecated; use `list(HealthCheck)` instead.",
293 since="2023-04-16",
294 has_codemod=True,
295 stacklevel=1,
296 )
297 return list(HealthCheck)
299 data_too_large = "data_too_large"
300 """Checks if too many examples are aborted for being too large.
302 This is measured by the number of random choices that Hypothesis makes
303 in order to generate something, not the size of the generated object.
304 For example, choosing a 100MB object from a predefined list would take
305 only a few bits, while generating 10KB of JSON from scratch might trigger
306 this health check.
307 """
309 filter_too_much = "filter_too_much"
310 """Check for when the test is filtering out too many examples, either
311 through use of |assume| or |.filter|, or occasionally for Hypothesis
312 internal reasons."""
314 too_slow = "too_slow"
315 """
316 Check for when input generation is very slow. Since Hypothesis generates 100
317 (by default) inputs per test execution, a slowdown in generating each input
318 can result in very slow tests overall.
319 """
321 return_value = "return_value"
322 """Deprecated; we always error if a test returns a non-None value."""
324 large_base_example = "large_base_example"
325 """
326 Checks if the smallest natural input to your test is very large. This makes
327 it difficult for Hypothesis to generate good inputs, especially when trying to
328 shrink failing inputs.
329 """
331 not_a_test_method = "not_a_test_method"
332 """Deprecated; we always error if |@given| is applied
333 to a method defined by :class:`python:unittest.TestCase` (i.e. not a test)."""
335 function_scoped_fixture = "function_scoped_fixture"
336 """Checks if |@given| has been applied to a test
337 with a pytest function-scoped fixture. Function-scoped fixtures run once
338 for the whole function, not once per example, and this is usually not what
339 you want.
341 Because of this limitation, tests that need to set up or reset
342 state for every example need to do so manually within the test itself,
343 typically using an appropriate context manager.
345 Suppress this health check only in the rare case that you are using a
346 function-scoped fixture that does not need to be reset between individual
347 examples, but for some reason you cannot use a wider fixture scope
348 (e.g. session scope, module scope, class scope).
350 This check requires the :ref:`Hypothesis pytest plugin<pytest-plugin>`,
351 which is enabled by default when running Hypothesis inside pytest."""
353 differing_executors = "differing_executors"
354 """Checks if |@given| has been applied to a test
355 which is executed by different :ref:`executors<custom-function-execution>`.
356 If your test function is defined as a method on a class, that class will be
357 your executor, and subclasses executing an inherited test is a common way
358 for things to go wrong.
360 The correct fix is often to bring the executor instance under the control
361 of hypothesis by explicit parametrization over, or sampling from,
362 subclasses, or to refactor so that |@given| is
363 specified on leaf subclasses."""
365 nested_given = "nested_given"
366 """Checks if |@given| is used inside another
367 |@given|. This results in quadratic generation and
368 shrinking behavior, and can usually be expressed more cleanly by using
369 :func:`~hypothesis.strategies.data` to replace the inner
370 |@given|.
372 Nesting @given can be appropriate if you set appropriate limits for the
373 quadratic behavior and cannot easily reexpress the inner function with
374 :func:`~hypothesis.strategies.data`. To suppress this health check, set
375 ``suppress_health_check=[HealthCheck.nested_given]`` on the outer
376 |@given|. Setting it on the inner
377 |@given| has no effect. If you have more than one
378 level of nesting, add a suppression for this health check to every
379 |@given| except the innermost one.
380 """
383class duration(datetime.timedelta):
384 """A timedelta specifically measured in milliseconds."""
386 def __repr__(self) -> str:
387 ms = self.total_seconds() * 1000
388 return f"timedelta(milliseconds={int(ms) if ms == int(ms) else ms!r})"
391# see https://adamj.eu/tech/2020/03/09/detect-if-your-tests-are-running-on-ci
392# initially from https://github.com/tox-dev/tox/blob/e911788a/src/tox/util/ci.py
393_CI_VARS = {
394 "CI": None, # various, including GitHub Actions, Travis CI, and AppVeyor
395 # see https://github.com/tox-dev/tox/issues/3442
396 "__TOX_ENVIRONMENT_VARIABLE_ORIGINAL_CI": None,
397 "TF_BUILD": "true", # Azure Pipelines
398 "bamboo.buildKey": None, # Bamboo
399 "BUILDKITE": "true", # Buildkite
400 "CIRCLECI": "true", # Circle CI
401 "CIRRUS_CI": "true", # Cirrus CI
402 "CODEBUILD_BUILD_ID": None, # CodeBuild
403 "GITHUB_ACTIONS": "true", # GitHub Actions
404 "GITLAB_CI": None, # GitLab CI
405 "HEROKU_TEST_RUN_ID": None, # Heroku CI
406 "TEAMCITY_VERSION": None, # TeamCity
407}
410def is_in_ci() -> bool:
411 return any(
412 key in os.environ and (value is None or os.environ[key] == value)
413 for key, value in _CI_VARS.items()
414 )
417default_variable = DynamicVariable[Optional["settings"]](None)
420def _validate_choices(name: str, value: T, *, choices: Sequence[object]) -> T:
421 if value not in choices:
422 msg = f"Invalid {name}, {value!r}. Valid choices: {choices!r}"
423 raise InvalidArgument(msg)
424 return value
427def _validate_enum_value(cls: Any, value: object, *, name: str) -> Any:
428 try:
429 return cls(value)
430 except ValueError:
431 raise InvalidArgument(
432 f"{name}={value} is not a valid value. The options "
433 f"are: {', '.join(repr(m.name) for m in cls)}"
434 ) from None
437def _validate_max_examples(max_examples: int) -> int:
438 check_type(int, max_examples, name="max_examples")
439 if max_examples < 1:
440 raise InvalidArgument(
441 f"max_examples={max_examples!r} must be at least one. If you want "
442 "to disable generation entirely, use phases=[Phase.explicit] instead."
443 )
444 return max_examples
447def _validate_database(
448 database: Optional["ExampleDatabase"],
449) -> Optional["ExampleDatabase"]:
450 from hypothesis.database import ExampleDatabase
452 if database is None or isinstance(database, ExampleDatabase):
453 return database
454 raise InvalidArgument(
455 "Arguments to the database setting must be None or an instance of "
456 "ExampleDatabase. Use one of the database classes in "
457 "hypothesis.database"
458 )
461def _validate_phases(phases: Collection[Phase]) -> Sequence[Phase]:
462 phases = try_convert(tuple, phases, "phases")
463 phases = tuple(
464 _validate_enum_value(Phase, phase, name="phases") for phase in phases
465 )
466 # sort by definition order
467 return tuple(phase for phase in list(Phase) if phase in phases)
470def _validate_stateful_step_count(stateful_step_count: int) -> int:
471 check_type(int, stateful_step_count, name="stateful_step_count")
472 if stateful_step_count < 1:
473 raise InvalidArgument(
474 f"stateful_step_count={stateful_step_count!r} must be at least one."
475 )
476 return stateful_step_count
479def _validate_suppress_health_check(suppressions: object) -> tuple[HealthCheck, ...]:
480 suppressions = try_convert(tuple, suppressions, "suppress_health_check")
481 for health_check in suppressions:
482 if health_check in (HealthCheck.return_value, HealthCheck.not_a_test_method):
483 note_deprecation(
484 f"The {health_check.name} health check is deprecated, because this is always an error.",
485 since="2023-03-15",
486 has_codemod=False,
487 stacklevel=2,
488 )
489 return tuple(
490 _validate_enum_value(HealthCheck, health_check, name="suppress_health_check")
491 for health_check in suppressions
492 )
495def _validate_deadline(
496 deadline: int | float | datetime.timedelta | None,
497) -> duration | None:
498 if deadline is None:
499 return deadline
500 invalid_deadline_error = InvalidArgument(
501 f"deadline={deadline!r} (type {type(deadline).__name__}) must be a timedelta object, "
502 "an integer or float number of milliseconds, or None to disable the "
503 "per-test-case deadline."
504 )
505 if isinstance(deadline, (int, float)):
506 if isinstance(deadline, bool):
507 raise invalid_deadline_error
508 try:
509 deadline = duration(milliseconds=deadline)
510 except OverflowError:
511 raise InvalidArgument(
512 f"deadline={deadline!r} is invalid, because it is too large to represent "
513 "as a timedelta. Use deadline=None to disable deadlines."
514 ) from None
515 if isinstance(deadline, datetime.timedelta):
516 if deadline <= datetime.timedelta(0):
517 raise InvalidArgument(
518 f"deadline={deadline!r} is invalid, because it is impossible to meet a "
519 "deadline <= 0. Use deadline=None to disable deadlines."
520 )
521 return duration(seconds=deadline.total_seconds())
522 raise invalid_deadline_error
525def _validate_backend(backend: str) -> str:
526 if backend not in AVAILABLE_PROVIDERS:
527 if backend == "crosshair": # pragma: no cover
528 install = '`pip install "hypothesis[crosshair]"` and try again.'
529 raise InvalidArgument(f"backend={backend!r} is not available. {install}")
530 raise InvalidArgument(
531 f"backend={backend!r} is not available - maybe you need to install a plugin?"
532 f"\n Installed backends: {sorted(AVAILABLE_PROVIDERS)!r}"
533 )
534 return backend
537class settingsMeta(type):
538 def __init__(cls, *args, **kwargs):
539 super().__init__(*args, **kwargs)
541 @property
542 def default(cls) -> Optional["settings"]:
543 v = default_variable.value
544 if v is not None:
545 return v
546 if getattr(settings, "_current_profile", None) is not None:
547 assert settings._current_profile is not None
548 settings.load_profile(settings._current_profile)
549 assert default_variable.value is not None
550 return default_variable.value
552 def __setattr__(cls, name: str, value: object) -> None:
553 if name == "default":
554 raise AttributeError(
555 "Cannot assign to the property settings.default - "
556 "consider using settings.load_profile instead."
557 )
558 elif not name.startswith("_"):
559 raise AttributeError(
560 f"Cannot assign hypothesis.settings.{name}={value!r} - the settings "
561 "class is immutable. You can change the global default "
562 "settings with settings.load_profile, or use @settings(...) "
563 "to decorate your test instead."
564 )
565 super().__setattr__(name, value)
567 def __repr__(cls):
568 return "hypothesis.settings"
571class settings(metaclass=settingsMeta):
572 """
573 A settings object controls the following aspects of test behavior:
574 |~settings.max_examples|, |~settings.derandomize|, |~settings.database|,
575 |~settings.verbosity|, |~settings.phases|, |~settings.stateful_step_count|,
576 |~settings.report_multiple_bugs|, |~settings.suppress_health_check|,
577 |~settings.deadline|, |~settings.print_blob|, and |~settings.backend|.
579 A settings object can be applied as a decorator to a test function, in which
580 case that test function will use those settings. A test may only have one
581 settings object applied to it. A settings object can also be passed to
582 |settings.register_profile| or as a parent to another |settings|.
584 Attribute inheritance
585 ---------------------
587 Settings objects are immutable once created. When a settings object is created,
588 it uses the value specified for each attribute. Any attribute which is
589 not specified will inherit from its value in the ``parent`` settings object.
590 If ``parent`` is not passed, any attributes which are not specified will inherit
591 from the current settings profile instead.
593 For instance, ``settings(max_examples=10)`` will have a ``max_examples`` of ``10``,
594 and the value of all other attributes will be equal to its value in the
595 current settings profile.
597 Changes made from activating a new settings profile with |settings.load_profile|
598 will be reflected in settings objects created after the profile was loaded,
599 but not in existing settings objects.
601 .. _builtin-profiles:
603 Built-in profiles
604 -----------------
606 While you can register additional profiles with |settings.register_profile|,
607 Hypothesis comes with two built-in profiles: ``default`` and ``ci``.
609 By default, the ``default`` profile is active. If the ``CI`` environment
610 variable is set to any value, the ``ci`` profile is active by default. Hypothesis
611 also automatically detects various vendor-specific CI environment variables.
613 The attributes of the currently active settings profile can be retrieved with
614 ``settings()`` (so ``settings().max_examples`` is the currently active default
615 for |settings.max_examples|).
617 The settings attributes for the built-in profiles are as follows:
619 .. code-block:: python
621 default = settings.register_profile(
622 "default",
623 max_examples=100,
624 derandomize=False,
625 database=not_set, # see settings.database for the default database
626 verbosity=Verbosity.normal,
627 phases=tuple(Phase),
628 stateful_step_count=50,
629 report_multiple_bugs=True,
630 suppress_health_check=(),
631 deadline=duration(milliseconds=200),
632 print_blob=False,
633 backend="hypothesis",
634 )
636 ci = settings.register_profile(
637 "ci",
638 parent=default,
639 derandomize=True,
640 deadline=None,
641 database=None,
642 print_blob=True,
643 suppress_health_check=[HealthCheck.too_slow],
644 )
646 You can replace either of the built-in profiles with |settings.register_profile|:
648 .. code-block:: python
650 # run more examples in CI
651 settings.register_profile(
652 "ci",
653 settings.get_profile("ci"),
654 max_examples=1000,
655 )
656 """
658 _profiles: ClassVar[dict[str, "settings"]] = {}
659 _current_profile: ClassVar[str | None] = None
661 def __init__(
662 self,
663 parent: Optional["settings"] = None,
664 *,
665 # This looks pretty strange, but there's good reason: we want Mypy to detect
666 # bad calls downstream, but not to freak out about the `= not_set` part even
667 # though it's not semantically valid to pass that as an argument value.
668 # The intended use is "like **kwargs, but more tractable for tooling".
669 max_examples: int = not_set, # type: ignore
670 derandomize: bool = not_set, # type: ignore
671 database: Optional["ExampleDatabase"] = not_set, # type: ignore
672 verbosity: "Verbosity" = not_set, # type: ignore
673 phases: Collection["Phase"] = not_set, # type: ignore
674 stateful_step_count: int = not_set, # type: ignore
675 report_multiple_bugs: bool = not_set, # type: ignore
676 suppress_health_check: Collection["HealthCheck"] = not_set, # type: ignore
677 deadline: int | float | datetime.timedelta | None = not_set, # type: ignore
678 print_blob: bool = not_set, # type: ignore
679 backend: str = not_set, # type: ignore
680 ) -> None:
681 self._in_definition = True
683 if parent is not None:
684 check_type(settings, parent, "parent")
685 if derandomize not in (not_set, False):
686 if database not in (not_set, None): # type: ignore
687 raise InvalidArgument(
688 "derandomize=True implies database=None, so passing "
689 f"{database=} too is invalid."
690 )
691 database = None
693 # fallback is None if we're creating the default settings object, and
694 # the parent (or default settings object) otherwise
695 self._fallback = parent or settings.default
696 self._max_examples = (
697 self._fallback.max_examples # type: ignore
698 if max_examples is not_set # type: ignore
699 else _validate_max_examples(max_examples)
700 )
701 self._derandomize = (
702 self._fallback.derandomize # type: ignore
703 if derandomize is not_set # type: ignore
704 else _validate_choices("derandomize", derandomize, choices=[True, False])
705 )
706 if database is not not_set: # type: ignore
707 database = _validate_database(database)
708 self._database = database
709 self._cached_database = None
710 self._verbosity = (
711 self._fallback.verbosity # type: ignore
712 if verbosity is not_set # type: ignore
713 else _validate_enum_value(Verbosity, verbosity, name="verbosity")
714 )
715 self._phases = (
716 self._fallback.phases # type: ignore
717 if phases is not_set # type: ignore
718 else _validate_phases(phases)
719 )
720 self._stateful_step_count = (
721 self._fallback.stateful_step_count # type: ignore
722 if stateful_step_count is not_set # type: ignore
723 else _validate_stateful_step_count(stateful_step_count)
724 )
725 self._report_multiple_bugs = (
726 self._fallback.report_multiple_bugs # type: ignore
727 if report_multiple_bugs is not_set # type: ignore
728 else _validate_choices(
729 "report_multiple_bugs", report_multiple_bugs, choices=[True, False]
730 )
731 )
732 self._suppress_health_check = (
733 self._fallback.suppress_health_check # type: ignore
734 if suppress_health_check is not_set # type: ignore
735 else _validate_suppress_health_check(suppress_health_check)
736 )
737 self._deadline = (
738 self._fallback.deadline # type: ignore
739 if deadline is not_set # type: ignore
740 else _validate_deadline(deadline)
741 )
742 self._print_blob = (
743 self._fallback.print_blob # type: ignore
744 if print_blob is not_set # type: ignore
745 else _validate_choices("print_blob", print_blob, choices=[True, False])
746 )
747 self._backend = (
748 self._fallback.backend # type: ignore
749 if backend is not_set # type: ignore
750 else _validate_backend(backend)
751 )
753 self._in_definition = False
755 @property
756 def max_examples(self):
757 """
758 Once this many satisfying examples have been considered without finding any
759 counter-example, Hypothesis will stop looking.
761 Note that we might call your test function fewer times if we find a bug early
762 or can tell that we've exhausted the search space; or more if we discard some
763 examples due to use of .filter(), assume(), or a few other things that can
764 prevent the test case from completing successfully.
766 The default value is chosen to suit a workflow where the test will be part of
767 a suite that is regularly executed locally or on a CI server, balancing total
768 running time against the chance of missing a bug.
770 If you are writing one-off tests, running tens of thousands of examples is
771 quite reasonable as Hypothesis may miss uncommon bugs with default settings.
772 For very complex code, we have observed Hypothesis finding novel bugs after
773 *several million* examples while testing :pypi:`SymPy <sympy>`.
774 If you are running more than 100k examples for a test, consider using our
775 :ref:`integration for coverage-guided fuzzing <fuzz_one_input>` - it really
776 shines when given minutes or hours to run.
778 The default max examples is ``100``.
779 """
780 return self._max_examples
782 @property
783 def derandomize(self):
784 """
785 If True, seed Hypothesis' random number generator using a hash of the test
786 function, so that every run will test the same set of examples until you
787 update Hypothesis, Python, or the test function.
789 This allows you to `check for regressions and look for bugs
790 <https://blog.nelhage.com/post/two-kinds-of-testing/>`__ using separate
791 settings profiles - for example running
792 quick deterministic tests on every commit, and a longer non-deterministic
793 nightly testing run.
795 The default is ``False``. If running on CI, the default is ``True`` instead.
796 """
797 return self._derandomize
799 @property
800 def database(self):
801 """
802 An instance of |ExampleDatabase| that will be used to save examples to
803 and load previous examples from.
805 If not set, a |DirectoryBasedExampleDatabase| is created in the current
806 working directory under ``.hypothesis/examples``. If this location is
807 unusable, e.g. due to the lack of read or write permissions, Hypothesis
808 will emit a warning and fall back to an |InMemoryExampleDatabase|.
810 If ``None``, no storage will be used.
812 See the :ref:`database documentation <database>` for a list of database
813 classes, and how to define custom database classes.
814 """
815 from hypothesis.database import _db_for_path
817 # settings.database has two conflicting requirements:
818 # * The default settings should respect changes to set_hypothesis_home_dir
819 # in-between accesses
820 # * `s.database is s.database` should be true, except for the default settings
821 #
822 # We therefore cache s.database for everything except the default settings,
823 # which always recomputes dynamically.
824 if self._fallback is None:
825 # if self._fallback is None, we are the default settings, at which point
826 # we should recompute the database dynamically
827 assert self._database is not_set
828 return _db_for_path(not_set)
830 # otherwise, we cache the database
831 if self._cached_database is None:
832 self._cached_database = (
833 self._fallback.database if self._database is not_set else self._database
834 )
835 return self._cached_database
837 @property
838 def verbosity(self):
839 """
840 Control the verbosity level of Hypothesis messages.
842 To see what's going on while Hypothesis runs your tests, you can turn
843 up the verbosity setting.
845 .. code-block:: pycon
847 >>> from hypothesis import settings, Verbosity
848 >>> from hypothesis.strategies import lists, integers
849 >>> @given(lists(integers()))
850 ... @settings(verbosity=Verbosity.verbose)
851 ... def f(x):
852 ... assert not any(x)
853 ... f()
854 Trying example: []
855 Falsifying example: [-1198601713, -67, 116, -29578]
856 Shrunk example to [-1198601713]
857 Shrunk example to [-128]
858 Shrunk example to [32]
859 Shrunk example to [1]
860 [1]
862 The four levels are |Verbosity.quiet|, |Verbosity.normal|,
863 |Verbosity.verbose|, and |Verbosity.debug|. |Verbosity.normal| is the
864 default. For |Verbosity.quiet|, Hypothesis will not print anything out,
865 not even the final falsifying example. |Verbosity.debug| is basically
866 |Verbosity.verbose| but a bit more so. You probably don't want it.
868 Verbosity can be passed either as a |Verbosity| enum value, or as the
869 corresponding string value, or as the corresponding integer value. For
870 example:
872 .. code-block:: python
874 # these three are equivalent
875 settings(verbosity=Verbosity.verbose)
876 settings(verbosity="verbose")
878 If you are using :pypi:`pytest`, you may also need to :doc:`disable
879 output capturing for passing tests <pytest:how-to/capture-stdout-stderr>`
880 to see verbose output as tests run.
881 """
882 return self._verbosity
884 @property
885 def phases(self):
886 """
887 Control which phases should be run.
889 Hypothesis divides tests into logically distinct phases.
891 - |Phase.explicit|: Running explicit examples from |@example|.
892 - |Phase.reuse|: Running examples from the database which previously failed.
893 - |Phase.generate|: Generating new random examples.
894 - |Phase.target|: Mutating examples for :ref:`targeted property-based
895 testing <targeted>`. Requires |Phase.generate|.
896 - |Phase.shrink|: Shrinking failing examples.
897 - |Phase.explain|: Attempting to explain why a failure occurred.
898 Requires |Phase.shrink|.
900 The phases argument accepts a collection with any subset of these. E.g.
901 ``settings(phases=[Phase.generate, Phase.shrink])`` will generate new examples
902 and shrink them, but will not run explicit examples or reuse previous failures,
903 while ``settings(phases=[Phase.explicit])`` will only run explicit examples
904 from |@example|.
906 Phases can be passed either as a |Phase| enum value, or as the corresponding
907 string value. For example:
909 .. code-block:: python
911 # these two are equivalent
912 settings(phases=[Phase.explicit])
913 settings(phases=["explicit"])
915 Following the first failure, Hypothesis will (usually, depending on
916 which |Phase| is enabled) track which lines of code are always run on
917 failing but never on passing inputs. On 3.12+, this uses
918 :mod:`sys.monitoring`, while 3.11 and earlier uses :func:`python:sys.settrace`.
919 For python 3.11 and earlier, we therefore automatically disable the explain
920 phase on PyPy, or if you are using :pypi:`coverage` or a debugger. If
921 there are no clearly suspicious lines of code, :pep:`we refuse the
922 temptation to guess <20>`.
924 After shrinking to a minimal failing example, Hypothesis will try to find
925 parts of the example -- e.g. separate args to |@given|
926 -- which can vary freely without changing the result
927 of that minimal failing example. If the automated experiments run without
928 finding a passing variation, we leave a comment in the final report:
930 .. code-block:: python
932 test_x_divided_by_y(
933 x=0, # or any other generated value
934 y=0,
935 )
937 Just remember that the *lack* of an explanation sometimes just means that
938 Hypothesis couldn't efficiently find one, not that no explanation (or
939 simpler failing example) exists.
940 """
942 return self._phases
944 @property
945 def stateful_step_count(self):
946 """
947 The maximum number of times to call an additional |@rule| method in
948 :ref:`stateful testing <stateful>` before we give up on finding a bug.
950 Note that this setting is effectively multiplicative with max_examples,
951 as each example will run for a maximum of ``stateful_step_count`` steps.
953 The default stateful step count is ``50``.
954 """
955 return self._stateful_step_count
957 @property
958 def report_multiple_bugs(self):
959 """
960 Because Hypothesis runs the test many times, it can sometimes find multiple
961 bugs in a single run. Reporting all of them at once is usually very useful,
962 but replacing the exceptions can occasionally clash with debuggers.
963 If disabled, only the exception with the smallest minimal example is raised.
965 The default value is ``True``.
966 """
967 return self._report_multiple_bugs
969 @property
970 def suppress_health_check(self):
971 """
972 Suppress the given |HealthCheck| exceptions. Those health checks will not
973 be raised by Hypothesis. To suppress all health checks, you can pass
974 ``suppress_health_check=list(HealthCheck)``.
976 Health checks can be passed either as a |HealthCheck| enum value, or as
977 the corresponding string value. For example:
979 .. code-block:: python
981 # these two are equivalent
982 settings(suppress_health_check=[HealthCheck.filter_too_much])
983 settings(suppress_health_check=["filter_too_much"])
985 Health checks are proactive warnings, not correctness errors, so we
986 encourage suppressing health checks where you have evaluated they will
987 not pose a problem, or where you have evaluated that fixing the underlying
988 issue is not worthwhile.
990 .. seealso::
992 See also the :doc:`/how-to/suppress-healthchecks` how-to.
993 """
994 return self._suppress_health_check
996 @property
997 def deadline(self):
998 """
999 The maximum allowed duration of an individual test case, in milliseconds.
1000 You can pass an integer, float, or timedelta. If ``None``, the deadline
1001 is disabled entirely.
1003 We treat the deadline as a soft limit in some cases, where that would
1004 avoid flakiness due to timing variability.
1006 The default deadline is 200 milliseconds. If running on CI, the default is
1007 ``None`` instead.
1008 """
1009 return self._deadline
1011 @property
1012 def print_blob(self):
1013 """
1014 If set to ``True``, Hypothesis will print code for failing examples that
1015 can be used with |@reproduce_failure| to reproduce the failing example.
1017 The default value is ``False``. If running on CI, the default is ``True`` instead.
1018 """
1019 return self._print_blob
1021 @property
1022 def backend(self):
1023 """
1024 .. warning::
1026 EXPERIMENTAL AND UNSTABLE - see :ref:`alternative-backends`.
1028 The importable name of a backend which Hypothesis should use to generate
1029 primitive types. We support heuristic-random, solver-based, and fuzzing-based
1030 backends.
1031 """
1032 return self._backend
1034 def __call__(self, test: T) -> T:
1035 """Make the settings object (self) an attribute of the test.
1037 The settings are later discovered by looking them up on the test itself.
1038 """
1039 # Aliasing as Any avoids mypy errors (attr-defined) when accessing and
1040 # setting custom attributes on the decorated function or class.
1041 _test: Any = test
1043 # Using the alias here avoids a mypy error (return-value) later when
1044 # ``test`` is returned, because this check results in type refinement.
1045 if not callable(_test):
1046 raise InvalidArgument(
1047 "settings objects can be called as a decorator with @given, "
1048 f"but decorated {test=} is not callable."
1049 )
1050 if inspect.isclass(test):
1051 from hypothesis.stateful import RuleBasedStateMachine
1053 if issubclass(_test, RuleBasedStateMachine):
1054 attr_name = "_hypothesis_internal_settings_applied"
1055 if getattr(test, attr_name, False):
1056 raise InvalidArgument(
1057 "Applying the @settings decorator twice would "
1058 "overwrite the first version; merge their arguments "
1059 "instead."
1060 )
1061 setattr(test, attr_name, True)
1062 _test.TestCase.settings = self
1063 return test
1064 else:
1065 raise InvalidArgument(
1066 "@settings(...) can only be used as a decorator on "
1067 "functions, or on subclasses of RuleBasedStateMachine."
1068 )
1069 if hasattr(_test, "_hypothesis_internal_settings_applied"):
1070 # Can't use _hypothesis_internal_use_settings as an indicator that
1071 # @settings was applied, because @given also assigns that attribute.
1072 descr = get_pretty_function_description(test)
1073 raise InvalidArgument(
1074 f"{descr} has already been decorated with a settings object.\n"
1075 f" Previous: {_test._hypothesis_internal_use_settings!r}\n"
1076 f" This: {self!r}"
1077 )
1079 _test._hypothesis_internal_use_settings = self
1080 _test._hypothesis_internal_settings_applied = True
1081 return test
1083 def __setattr__(self, name: str, value: object) -> None:
1084 if not name.startswith("_") and not self._in_definition:
1085 raise AttributeError("settings objects are immutable")
1086 return super().__setattr__(name, value)
1088 def __repr__(self) -> str:
1089 bits = sorted(
1090 f"{name}={getattr(self, name)!r}"
1091 for name in all_settings
1092 if (name != "backend" or len(AVAILABLE_PROVIDERS) > 1) # experimental
1093 )
1094 return "settings({})".format(", ".join(bits))
1096 def show_changed(self) -> str:
1097 bits = []
1098 for name in all_settings:
1099 value = getattr(self, name)
1100 if value != getattr(default, name):
1101 bits.append(f"{name}={value!r}")
1102 return ", ".join(sorted(bits, key=len))
1104 @staticmethod
1105 def register_profile(
1106 name: str,
1107 parent: Optional["settings"] = None,
1108 **kwargs: Any,
1109 ) -> None:
1110 """
1111 Register a settings object as a settings profile, under the name ``name``.
1112 The ``parent`` and ``kwargs`` arguments to this method are as for
1113 |settings|.
1115 If a settings profile already exists under ``name``, it will be overwritten.
1116 Registering a profile with the same name as the currently active profile
1117 will cause those changes to take effect in the active profile immediately,
1118 and do not require reloading the profile.
1120 Registered settings profiles can be retrieved later by name with
1121 |settings.get_profile|.
1122 """
1123 check_type(str, name, "name")
1125 if (
1126 default_variable.value
1127 and settings._current_profile
1128 and default_variable.value != settings._profiles[settings._current_profile]
1129 ):
1130 note_deprecation(
1131 "Cannot register a settings profile when the current settings differ "
1132 "from the current profile (usually due to an @settings decorator). "
1133 "Register profiles at module level instead.",
1134 since="2025-11-15",
1135 has_codemod=False,
1136 )
1138 # if we just pass the parent and no kwargs, like
1139 # settings.register_profile(settings(max_examples=10))
1140 # then optimize out the pointless intermediate settings object which
1141 # would just forward everything to the parent.
1142 settings._profiles[name] = (
1143 parent
1144 if parent is not None and not kwargs
1145 else settings(parent=parent, **kwargs)
1146 )
1147 if settings._current_profile == name:
1148 settings.load_profile(name)
1150 @staticmethod
1151 def get_profile(name: str) -> "settings":
1152 """
1153 Returns the settings profile registered under ``name``. If no settings
1154 profile is registered under ``name``, raises |InvalidArgument|.
1155 """
1156 check_type(str, name, "name")
1157 try:
1158 return settings._profiles[name]
1159 except KeyError:
1160 raise InvalidArgument(f"Profile {name!r} is not registered") from None
1162 @staticmethod
1163 def load_profile(name: str) -> None:
1164 """
1165 Makes the settings profile registered under ``name`` the active profile.
1167 If no settings profile is registered under ``name``, raises |InvalidArgument|.
1168 """
1169 check_type(str, name, "name")
1170 settings._current_profile = name
1171 default_variable.value = settings.get_profile(name)
1173 @staticmethod
1174 def get_current_profile_name() -> str:
1175 """
1176 The name of the current settings profile. For example:
1178 .. code-block:: python
1180 >>> settings.load_profile("myprofile")
1181 >>> settings.get_current_profile_name()
1182 'myprofile'
1183 """
1184 assert settings._current_profile is not None
1185 return settings._current_profile
1188@contextlib.contextmanager
1189def local_settings(s: settings) -> Generator[settings, None, None]:
1190 with default_variable.with_value(s):
1191 yield s
1194def note_deprecation(
1195 message: str, *, since: str, has_codemod: bool, stacklevel: int = 0
1196) -> None:
1197 if since != "RELEASEDAY":
1198 date = datetime.date.fromisoformat(since)
1199 assert datetime.date(2021, 1, 1) <= date
1200 if has_codemod:
1201 message += (
1202 "\n The `hypothesis codemod` command-line tool can automatically "
1203 "refactor your code to fix this warning."
1204 )
1205 warnings.warn(HypothesisDeprecationWarning(message), stacklevel=2 + stacklevel)
1208default = settings(
1209 max_examples=100,
1210 derandomize=False,
1211 database=not_set, # type: ignore
1212 verbosity=Verbosity.normal,
1213 phases=tuple(Phase),
1214 stateful_step_count=50,
1215 report_multiple_bugs=True,
1216 suppress_health_check=(),
1217 deadline=duration(milliseconds=200),
1218 print_blob=False,
1219 backend="hypothesis",
1220)
1221settings.register_profile("default", default)
1222settings.load_profile("default")
1224assert settings.default is not None
1226CI = settings(
1227 derandomize=True,
1228 deadline=None,
1229 database=None,
1230 print_blob=True,
1231 suppress_health_check=[HealthCheck.too_slow],
1232)
1234settings.register_profile("ci", CI)
1237if is_in_ci(): # pragma: no cover # covered in ci, but not locally
1238 settings.load_profile("ci")
1240assert settings.default is not None
1243# Check that the kwonly args to settings.__init__ is the same as the set of
1244# defined settings - in case we've added or remove something from one but
1245# not the other.
1246assert set(all_settings) == {
1247 p.name
1248 for p in inspect.signature(settings.__init__).parameters.values()
1249 if p.kind == inspect.Parameter.KEYWORD_ONLY
1250}