Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/hypothesis/_settings.py: 63%

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

281 statements  

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/. 

10 

11"""The settings module configures runtime options for Hypothesis. 

12 

13Either an explicit settings object can be used or the default object on 

14this module can be modified. 

15""" 

16 

17import contextlib 

18import datetime 

19import inspect 

20import os 

21import warnings 

22from enum import Enum, EnumMeta, IntEnum, unique 

23from typing import ( 

24 TYPE_CHECKING, 

25 Any, 

26 ClassVar, 

27 Collection, 

28 Dict, 

29 List, 

30 Optional, 

31 TypeVar, 

32 Union, 

33) 

34 

35import attr 

36 

37from hypothesis.errors import ( 

38 HypothesisDeprecationWarning, 

39 InvalidArgument, 

40 InvalidState, 

41) 

42from hypothesis.internal.reflection import get_pretty_function_description 

43from hypothesis.internal.validation import check_type, try_convert 

44from hypothesis.utils.conventions import not_set 

45from hypothesis.utils.dynamicvariables import DynamicVariable 

46 

47if TYPE_CHECKING: 

48 from hypothesis.database import ExampleDatabase 

49 

50__all__ = ["settings"] 

51 

52all_settings: Dict[str, "Setting"] = {} 

53 

54T = TypeVar("T") 

55 

56 

57class settingsProperty: 

58 def __init__(self, name, show_default): 

59 self.name = name 

60 self.show_default = show_default 

61 

62 def __get__(self, obj, type=None): 

63 if obj is None: 

64 return self 

65 else: 

66 try: 

67 result = obj.__dict__[self.name] 

68 # This is a gross hack, but it preserves the old behaviour that 

69 # you can change the storage directory and it will be reflected 

70 # in the default database. 

71 if self.name == "database" and result is not_set: 

72 from hypothesis.database import ExampleDatabase 

73 

74 result = ExampleDatabase(not_set) 

75 return result 

76 except KeyError: 

77 raise AttributeError(self.name) from None 

78 

79 def __set__(self, obj, value): 

80 obj.__dict__[self.name] = value 

81 

82 def __delete__(self, obj): 

83 raise AttributeError(f"Cannot delete attribute {self.name}") 

84 

85 @property 

86 def __doc__(self): 

87 description = all_settings[self.name].description 

88 default = ( 

89 repr(getattr(settings.default, self.name)) 

90 if self.show_default 

91 else "(dynamically calculated)" 

92 ) 

93 return f"{description}\n\ndefault value: ``{default}``" 

94 

95 

96default_variable = DynamicVariable(None) 

97 

98 

99class settingsMeta(type): 

100 def __init__(cls, *args, **kwargs): 

101 super().__init__(*args, **kwargs) 

102 

103 @property 

104 def default(cls): 

105 v = default_variable.value 

106 if v is not None: 

107 return v 

108 if hasattr(settings, "_current_profile"): 

109 settings.load_profile(settings._current_profile) 

110 assert default_variable.value is not None 

111 return default_variable.value 

112 

113 def _assign_default_internal(cls, value): 

114 default_variable.value = value 

115 

116 def __setattr__(cls, name, value): 

117 if name == "default": 

118 raise AttributeError( 

119 "Cannot assign to the property settings.default - " 

120 "consider using settings.load_profile instead." 

121 ) 

122 elif not (isinstance(value, settingsProperty) or name.startswith("_")): 

123 raise AttributeError( 

124 f"Cannot assign hypothesis.settings.{name}={value!r} - the settings " 

125 "class is immutable. You can change the global default " 

126 "settings with settings.load_profile, or use @settings(...) " 

127 "to decorate your test instead." 

128 ) 

129 return super().__setattr__(name, value) 

130 

131 

132class settings(metaclass=settingsMeta): 

133 """A settings object configures options including verbosity, runtime controls, 

134 persistence, determinism, and more. 

135 

136 Default values are picked up from the settings.default object and 

137 changes made there will be picked up in newly created settings. 

138 """ 

139 

140 __definitions_are_locked = False 

141 _profiles: ClassVar[Dict[str, "settings"]] = {} 

142 __module__ = "hypothesis" 

143 

144 def __getattr__(self, name): 

145 if name in all_settings: 

146 return all_settings[name].default 

147 else: 

148 raise AttributeError(f"settings has no attribute {name}") 

149 

150 def __init__( 

151 self, 

152 parent: Optional["settings"] = None, 

153 *, 

154 # This looks pretty strange, but there's good reason: we want Mypy to detect 

155 # bad calls downstream, but not to freak out about the `= not_set` part even 

156 # though it's not semantically valid to pass that as an argument value. 

157 # The intended use is "like **kwargs, but more tractable for tooling". 

158 max_examples: int = not_set, # type: ignore 

159 derandomize: bool = not_set, # type: ignore 

160 database: Optional["ExampleDatabase"] = not_set, # type: ignore 

161 verbosity: "Verbosity" = not_set, # type: ignore 

162 phases: Collection["Phase"] = not_set, # type: ignore 

163 stateful_step_count: int = not_set, # type: ignore 

164 report_multiple_bugs: bool = not_set, # type: ignore 

165 suppress_health_check: Collection["HealthCheck"] = not_set, # type: ignore 

166 deadline: Union[int, float, datetime.timedelta, None] = not_set, # type: ignore 

167 print_blob: bool = not_set, # type: ignore 

168 backend: str = not_set, # type: ignore 

169 ) -> None: 

170 if parent is not None: 

171 check_type(settings, parent, "parent") 

172 if derandomize not in (not_set, False): 

173 if database not in (not_set, None): # type: ignore 

174 raise InvalidArgument( 

175 "derandomize=True implies database=None, so passing " 

176 f"{database=} too is invalid." 

177 ) 

178 database = None 

179 

180 defaults = parent or settings.default 

181 if defaults is not None: 

182 for setting in all_settings.values(): 

183 value = locals()[setting.name] 

184 if value is not_set: 

185 object.__setattr__( 

186 self, setting.name, getattr(defaults, setting.name) 

187 ) 

188 else: 

189 object.__setattr__(self, setting.name, setting.validator(value)) 

190 

191 def __call__(self, test: T) -> T: 

192 """Make the settings object (self) an attribute of the test. 

193 

194 The settings are later discovered by looking them up on the test itself. 

195 """ 

196 # Aliasing as Any avoids mypy errors (attr-defined) when accessing and 

197 # setting custom attributes on the decorated function or class. 

198 _test: Any = test 

199 

200 # Using the alias here avoids a mypy error (return-value) later when 

201 # ``test`` is returned, because this check results in type refinement. 

202 if not callable(_test): 

203 raise InvalidArgument( 

204 "settings objects can be called as a decorator with @given, " 

205 f"but decorated {test=} is not callable." 

206 ) 

207 if inspect.isclass(test): 

208 from hypothesis.stateful import RuleBasedStateMachine 

209 

210 if issubclass(_test, RuleBasedStateMachine): 

211 attr_name = "_hypothesis_internal_settings_applied" 

212 if getattr(test, attr_name, False): 

213 raise InvalidArgument( 

214 "Applying the @settings decorator twice would " 

215 "overwrite the first version; merge their arguments " 

216 "instead." 

217 ) 

218 setattr(test, attr_name, True) 

219 _test.TestCase.settings = self 

220 return test # type: ignore 

221 else: 

222 raise InvalidArgument( 

223 "@settings(...) can only be used as a decorator on " 

224 "functions, or on subclasses of RuleBasedStateMachine." 

225 ) 

226 if hasattr(_test, "_hypothesis_internal_settings_applied"): 

227 # Can't use _hypothesis_internal_use_settings as an indicator that 

228 # @settings was applied, because @given also assigns that attribute. 

229 descr = get_pretty_function_description(test) 

230 raise InvalidArgument( 

231 f"{descr} has already been decorated with a settings object.\n" 

232 f" Previous: {_test._hypothesis_internal_use_settings!r}\n" 

233 f" This: {self!r}" 

234 ) 

235 

236 _test._hypothesis_internal_use_settings = self 

237 _test._hypothesis_internal_settings_applied = True 

238 return test 

239 

240 @classmethod 

241 def _define_setting( 

242 cls, 

243 name, 

244 description, 

245 *, 

246 default, 

247 options=None, 

248 validator=None, 

249 show_default=True, 

250 ): 

251 """Add a new setting. 

252 

253 - name is the name of the property that will be used to access the 

254 setting. This must be a valid python identifier. 

255 - description will appear in the property's docstring 

256 - default is the default value. This may be a zero argument 

257 function in which case it is evaluated and its result is stored 

258 the first time it is accessed on any given settings object. 

259 """ 

260 if settings.__definitions_are_locked: 

261 raise InvalidState( 

262 "settings have been locked and may no longer be defined." 

263 ) 

264 if options is not None: 

265 options = tuple(options) 

266 assert default in options 

267 

268 def validator(value): 

269 if value not in options: 

270 msg = f"Invalid {name}, {value!r}. Valid options: {options!r}" 

271 raise InvalidArgument(msg) 

272 return value 

273 

274 else: 

275 assert validator is not None 

276 

277 all_settings[name] = Setting( 

278 name=name, 

279 description=description.strip(), 

280 default=default, 

281 validator=validator, 

282 ) 

283 setattr(settings, name, settingsProperty(name, show_default)) 

284 

285 @classmethod 

286 def lock_further_definitions(cls): 

287 settings.__definitions_are_locked = True 

288 

289 def __setattr__(self, name, value): 

290 raise AttributeError("settings objects are immutable") 

291 

292 def __repr__(self): 

293 from hypothesis.internal.conjecture.data import AVAILABLE_PROVIDERS 

294 

295 bits = sorted( 

296 f"{name}={getattr(self, name)!r}" 

297 for name in all_settings 

298 if (name != "backend" or len(AVAILABLE_PROVIDERS) > 1) # experimental 

299 ) 

300 return "settings({})".format(", ".join(bits)) 

301 

302 def show_changed(self): 

303 bits = [] 

304 for name, setting in all_settings.items(): 

305 value = getattr(self, name) 

306 if value != setting.default: 

307 bits.append(f"{name}={value!r}") 

308 return ", ".join(sorted(bits, key=len)) 

309 

310 @staticmethod 

311 def register_profile( 

312 name: str, 

313 parent: Optional["settings"] = None, 

314 **kwargs: Any, 

315 ) -> None: 

316 """Registers a collection of values to be used as a settings profile. 

317 

318 Settings profiles can be loaded by name - for example, you might 

319 create a 'fast' profile which runs fewer examples, keep the 'default' 

320 profile, and create a 'ci' profile that increases the number of 

321 examples and uses a different database to store failures. 

322 

323 The arguments to this method are exactly as for 

324 :class:`~hypothesis.settings`: optional ``parent`` settings, and 

325 keyword arguments for each setting that will be set differently to 

326 parent (or settings.default, if parent is None). 

327 """ 

328 check_type(str, name, "name") 

329 settings._profiles[name] = settings(parent=parent, **kwargs) 

330 

331 @staticmethod 

332 def get_profile(name: str) -> "settings": 

333 """Return the profile with the given name.""" 

334 check_type(str, name, "name") 

335 try: 

336 return settings._profiles[name] 

337 except KeyError: 

338 raise InvalidArgument(f"Profile {name!r} is not registered") from None 

339 

340 @staticmethod 

341 def load_profile(name: str) -> None: 

342 """Loads in the settings defined in the profile provided. 

343 

344 If the profile does not exist, InvalidArgument will be raised. 

345 Any setting not defined in the profile will be the library 

346 defined default for that setting. 

347 """ 

348 check_type(str, name, "name") 

349 settings._current_profile = name 

350 settings._assign_default_internal(settings.get_profile(name)) 

351 

352 

353@contextlib.contextmanager 

354def local_settings(s): 

355 with default_variable.with_value(s): 

356 yield s 

357 

358 

359@attr.s() 

360class Setting: 

361 name = attr.ib() 

362 description = attr.ib() 

363 default = attr.ib() 

364 validator = attr.ib() 

365 

366 

367def _max_examples_validator(x): 

368 check_type(int, x, name="max_examples") 

369 if x < 1: 

370 raise InvalidArgument( 

371 f"max_examples={x!r} should be at least one. You can disable " 

372 "example generation with the `phases` setting instead." 

373 ) 

374 return x 

375 

376 

377settings._define_setting( 

378 "max_examples", 

379 default=100, 

380 validator=_max_examples_validator, 

381 description=""" 

382Once this many satisfying examples have been considered without finding any 

383counter-example, Hypothesis will stop looking. 

384 

385Note that we might call your test function fewer times if we find a bug early 

386or can tell that we've exhausted the search space; or more if we discard some 

387examples due to use of .filter(), assume(), or a few other things that can 

388prevent the test case from completing successfully. 

389 

390The default value is chosen to suit a workflow where the test will be part of 

391a suite that is regularly executed locally or on a CI server, balancing total 

392running time against the chance of missing a bug. 

393 

394If you are writing one-off tests, running tens of thousands of examples is 

395quite reasonable as Hypothesis may miss uncommon bugs with default settings. 

396For very complex code, we have observed Hypothesis finding novel bugs after 

397*several million* examples while testing :pypi:`SymPy`. 

398If you are running more than 100k examples for a test, consider using our 

399:ref:`integration for coverage-guided fuzzing <fuzz_one_input>` - it really 

400shines when given minutes or hours to run. 

401""", 

402) 

403 

404 

405settings._define_setting( 

406 "derandomize", 

407 default=False, 

408 options=(True, False), 

409 description=""" 

410If True, seed Hypothesis' random number generator using a hash of the test 

411function, so that every run will test the same set of examples until you 

412update Hypothesis, Python, or the test function. 

413 

414This allows you to `check for regressions and look for bugs 

415<https://blog.nelhage.com/post/two-kinds-of-testing/>`__ using 

416:ref:`separate settings profiles <settings_profiles>` - for example running 

417quick deterministic tests on every commit, and a longer non-deterministic 

418nightly testing run. 

419""", 

420) 

421 

422 

423def _validate_database(db): 

424 from hypothesis.database import ExampleDatabase 

425 

426 if db is None or isinstance(db, ExampleDatabase): 

427 return db 

428 raise InvalidArgument( 

429 "Arguments to the database setting must be None or an instance of " 

430 f"ExampleDatabase. Try passing database=ExampleDatabase({db!r}), or " 

431 "construct and use one of the specific subclasses in " 

432 "hypothesis.database" 

433 ) 

434 

435 

436settings._define_setting( 

437 "database", 

438 default=not_set, 

439 show_default=False, 

440 description=""" 

441An instance of :class:`~hypothesis.database.ExampleDatabase` that will be 

442used to save examples to and load previous examples from. May be ``None`` 

443in which case no storage will be used. 

444 

445See the :doc:`example database documentation <database>` for a list of built-in 

446example database implementations, and how to define custom implementations. 

447""", 

448 validator=_validate_database, 

449) 

450 

451 

452@unique 

453class Phase(IntEnum): 

454 explicit = 0 #: controls whether explicit examples are run. 

455 reuse = 1 #: controls whether previous examples will be reused. 

456 generate = 2 #: controls whether new examples will be generated. 

457 target = 3 #: controls whether examples will be mutated for targeting. 

458 shrink = 4 #: controls whether examples will be shrunk. 

459 explain = 5 #: controls whether Hypothesis attempts to explain test failures. 

460 

461 def __repr__(self): 

462 return f"Phase.{self.name}" 

463 

464 

465class HealthCheckMeta(EnumMeta): 

466 def __iter__(self): 

467 deprecated = (HealthCheck.return_value, HealthCheck.not_a_test_method) 

468 return iter(x for x in super().__iter__() if x not in deprecated) 

469 

470 

471@unique 

472class HealthCheck(Enum, metaclass=HealthCheckMeta): 

473 """Arguments for :attr:`~hypothesis.settings.suppress_health_check`. 

474 

475 Each member of this enum is a type of health check to suppress. 

476 """ 

477 

478 def __repr__(self): 

479 return f"{self.__class__.__name__}.{self.name}" 

480 

481 @classmethod 

482 def all(cls) -> List["HealthCheck"]: 

483 # Skipping of deprecated attributes is handled in HealthCheckMeta.__iter__ 

484 note_deprecation( 

485 "`Healthcheck.all()` is deprecated; use `list(HealthCheck)` instead.", 

486 since="2023-04-16", 

487 has_codemod=True, 

488 stacklevel=1, 

489 ) 

490 return list(HealthCheck) 

491 

492 data_too_large = 1 

493 """Checks if too many examples are aborted for being too large. 

494 

495 This is measured by the number of random choices that Hypothesis makes 

496 in order to generate something, not the size of the generated object. 

497 For example, choosing a 100MB object from a predefined list would take 

498 only a few bits, while generating 10KB of JSON from scratch might trigger 

499 this health check. 

500 """ 

501 

502 filter_too_much = 2 

503 """Check for when the test is filtering out too many examples, either 

504 through use of :func:`~hypothesis.assume()` or :ref:`filter() <filtering>`, 

505 or occasionally for Hypothesis internal reasons.""" 

506 

507 too_slow = 3 

508 """Check for when your data generation is extremely slow and likely to hurt 

509 testing.""" 

510 

511 return_value = 5 

512 """Deprecated; we always error if a test returns a non-None value.""" 

513 

514 large_base_example = 7 

515 """Checks if the natural example to shrink towards is very large.""" 

516 

517 not_a_test_method = 8 

518 """Deprecated; we always error if :func:`@given <hypothesis.given>` is applied 

519 to a method defined by :class:`python:unittest.TestCase` (i.e. not a test).""" 

520 

521 function_scoped_fixture = 9 

522 """Checks if :func:`@given <hypothesis.given>` has been applied to a test 

523 with a pytest function-scoped fixture. Function-scoped fixtures run once 

524 for the whole function, not once per example, and this is usually not what 

525 you want. 

526 

527 Because of this limitation, tests that need to set up or reset 

528 state for every example need to do so manually within the test itself, 

529 typically using an appropriate context manager. 

530 

531 Suppress this health check only in the rare case that you are using a 

532 function-scoped fixture that does not need to be reset between individual 

533 examples, but for some reason you cannot use a wider fixture scope 

534 (e.g. session scope, module scope, class scope). 

535 

536 This check requires the :ref:`Hypothesis pytest plugin<pytest-plugin>`, 

537 which is enabled by default when running Hypothesis inside pytest.""" 

538 

539 differing_executors = 10 

540 """Checks if :func:`@given <hypothesis.given>` has been applied to a test 

541 which is executed by different :ref:`executors<custom-function-execution>`. 

542 If your test function is defined as a method on a class, that class will be 

543 your executor, and subclasses executing an inherited test is a common way 

544 for things to go wrong. 

545 

546 The correct fix is often to bring the executor instance under the control 

547 of hypothesis by explicit parametrization over, or sampling from, 

548 subclasses, or to refactor so that :func:`@given <hypothesis.given>` is 

549 specified on leaf subclasses.""" 

550 

551 

552@unique 

553class Verbosity(IntEnum): 

554 quiet = 0 

555 normal = 1 

556 verbose = 2 

557 debug = 3 

558 

559 def __repr__(self): 

560 return f"Verbosity.{self.name}" 

561 

562 

563settings._define_setting( 

564 "verbosity", 

565 options=tuple(Verbosity), 

566 default=Verbosity.normal, 

567 description="Control the verbosity level of Hypothesis messages", 

568) 

569 

570 

571def _validate_phases(phases): 

572 phases = tuple(phases) 

573 for a in phases: 

574 if not isinstance(a, Phase): 

575 raise InvalidArgument(f"{a!r} is not a valid phase") 

576 return tuple(p for p in list(Phase) if p in phases) 

577 

578 

579settings._define_setting( 

580 "phases", 

581 default=tuple(Phase), 

582 description=( 

583 "Control which phases should be run. " 

584 "See :ref:`the full documentation for more details <phases>`" 

585 ), 

586 validator=_validate_phases, 

587) 

588 

589 

590def _validate_stateful_step_count(x): 

591 check_type(int, x, name="stateful_step_count") 

592 if x < 1: 

593 raise InvalidArgument(f"stateful_step_count={x!r} must be at least one.") 

594 return x 

595 

596 

597settings._define_setting( 

598 name="stateful_step_count", 

599 default=50, 

600 validator=_validate_stateful_step_count, 

601 description=""" 

602Number of steps to run a stateful program for before giving up on it breaking. 

603""", 

604) 

605 

606settings._define_setting( 

607 name="report_multiple_bugs", 

608 default=True, 

609 options=(True, False), 

610 description=""" 

611Because Hypothesis runs the test many times, it can sometimes find multiple 

612bugs in a single run. Reporting all of them at once is usually very useful, 

613but replacing the exceptions can occasionally clash with debuggers. 

614If disabled, only the exception with the smallest minimal example is raised. 

615""", 

616) 

617 

618 

619def validate_health_check_suppressions(suppressions): 

620 suppressions = try_convert(list, suppressions, "suppress_health_check") 

621 for s in suppressions: 

622 if not isinstance(s, HealthCheck): 

623 raise InvalidArgument( 

624 f"Non-HealthCheck value {s!r} of type {type(s).__name__} " 

625 "is invalid in suppress_health_check." 

626 ) 

627 if s in (HealthCheck.return_value, HealthCheck.not_a_test_method): 

628 note_deprecation( 

629 f"The {s.name} health check is deprecated, because this is always an error.", 

630 since="2023-03-15", 

631 has_codemod=False, 

632 stacklevel=2, 

633 ) 

634 return suppressions 

635 

636 

637settings._define_setting( 

638 "suppress_health_check", 

639 default=(), 

640 description="""A list of :class:`~hypothesis.HealthCheck` items to disable.""", 

641 validator=validate_health_check_suppressions, 

642) 

643 

644 

645class duration(datetime.timedelta): 

646 """A timedelta specifically measured in milliseconds.""" 

647 

648 def __repr__(self): 

649 ms = self.total_seconds() * 1000 

650 return f"timedelta(milliseconds={int(ms) if ms == int(ms) else ms!r})" 

651 

652 

653def _validate_deadline(x): 

654 if x is None: 

655 return x 

656 invalid_deadline_error = InvalidArgument( 

657 f"deadline={x!r} (type {type(x).__name__}) must be a timedelta object, " 

658 "an integer or float number of milliseconds, or None to disable the " 

659 "per-test-case deadline." 

660 ) 

661 if isinstance(x, (int, float)): 

662 if isinstance(x, bool): 

663 raise invalid_deadline_error 

664 try: 

665 x = duration(milliseconds=x) 

666 except OverflowError: 

667 raise InvalidArgument( 

668 f"deadline={x!r} is invalid, because it is too large to represent " 

669 "as a timedelta. Use deadline=None to disable deadlines." 

670 ) from None 

671 if isinstance(x, datetime.timedelta): 

672 if x <= datetime.timedelta(0): 

673 raise InvalidArgument( 

674 f"deadline={x!r} is invalid, because it is impossible to meet a " 

675 "deadline <= 0. Use deadline=None to disable deadlines." 

676 ) 

677 return duration(seconds=x.total_seconds()) 

678 raise invalid_deadline_error 

679 

680 

681settings._define_setting( 

682 "deadline", 

683 default=duration(milliseconds=200), 

684 validator=_validate_deadline, 

685 description=""" 

686If set, a duration (as timedelta, or integer or float number of milliseconds) 

687that each individual example (i.e. each time your test 

688function is called, not the whole decorated test) within a test is not 

689allowed to exceed. Tests which take longer than that may be converted into 

690errors (but will not necessarily be if close to the deadline, to allow some 

691variability in test run time). 

692 

693Set this to ``None`` to disable this behaviour entirely. 

694""", 

695) 

696 

697 

698def is_in_ci() -> bool: 

699 # GitHub Actions, Travis CI and AppVeyor have "CI" 

700 # Azure Pipelines has "TF_BUILD" 

701 return "CI" in os.environ or "TF_BUILD" in os.environ 

702 

703 

704settings._define_setting( 

705 "print_blob", 

706 default=is_in_ci(), 

707 show_default=False, 

708 options=(True, False), 

709 description=""" 

710If set to ``True``, Hypothesis will print code for failing examples that can be used with 

711:func:`@reproduce_failure <hypothesis.reproduce_failure>` to reproduce the failing example. 

712The default is ``True`` if the ``CI`` or ``TF_BUILD`` env vars are set, ``False`` otherwise. 

713""", 

714) 

715 

716 

717def _backend_validator(value): 

718 from hypothesis.internal.conjecture.data import AVAILABLE_PROVIDERS 

719 

720 if value not in AVAILABLE_PROVIDERS: 

721 if value == "crosshair": # pragma: no cover 

722 install = '`pip install "hypothesis[crosshair]"` and try again.' 

723 raise InvalidArgument(f"backend={value!r} is not available. {install}") 

724 raise InvalidArgument( 

725 f"backend={value!r} is not available - maybe you need to install a plugin?" 

726 f"\n Installed backends: {sorted(AVAILABLE_PROVIDERS)!r}" 

727 ) 

728 return value 

729 

730 

731settings._define_setting( 

732 "backend", 

733 default="hypothesis", 

734 show_default=False, 

735 validator=_backend_validator, 

736 description=""" 

737EXPERIMENTAL AND UNSTABLE - see :ref:`alternative-backends`. 

738The importable name of a backend which Hypothesis should use to generate primitive 

739types. We aim to support heuristic-random, solver-based, and fuzzing-based backends. 

740""", 

741) 

742 

743settings.lock_further_definitions() 

744 

745 

746def note_deprecation( 

747 message: str, *, since: str, has_codemod: bool, stacklevel: int = 0 

748) -> None: 

749 if since != "RELEASEDAY": 

750 date = datetime.date.fromisoformat(since) 

751 assert datetime.date(2021, 1, 1) <= date 

752 if has_codemod: 

753 message += ( 

754 "\n The `hypothesis codemod` command-line tool can automatically " 

755 "refactor your code to fix this warning." 

756 ) 

757 warnings.warn(HypothesisDeprecationWarning(message), stacklevel=2 + stacklevel) 

758 

759 

760settings.register_profile("default", settings()) 

761settings.load_profile("default") 

762assert settings.default is not None 

763 

764 

765# Check that the kwonly args to settings.__init__ is the same as the set of 

766# defined settings - in case we've added or remove something from one but 

767# not the other. 

768assert set(all_settings) == { 

769 p.name 

770 for p in inspect.signature(settings.__init__).parameters.values() 

771 if p.kind == inspect.Parameter.KEYWORD_ONLY 

772}