Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/hypothesis/configuration.py: 60%

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

42 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 

11import os 

12import sys 

13import warnings 

14from pathlib import Path 

15from typing import Union 

16 

17import _hypothesis_globals 

18 

19from hypothesis.errors import HypothesisSideeffectWarning 

20 

21__hypothesis_home_directory_default = Path.cwd() / ".hypothesis" 

22__hypothesis_home_directory = None 

23 

24 

25def set_hypothesis_home_dir(directory: Union[str, Path, None]) -> None: 

26 global __hypothesis_home_directory 

27 __hypothesis_home_directory = None if directory is None else Path(directory) 

28 

29 

30def storage_directory(*names: str, intent_to_write: bool = True) -> Path: 

31 if intent_to_write: 

32 check_sideeffect_during_initialization( 

33 "accessing storage for {}", "/".join(names) 

34 ) 

35 

36 global __hypothesis_home_directory 

37 if not __hypothesis_home_directory: 

38 if where := os.getenv("HYPOTHESIS_STORAGE_DIRECTORY"): 

39 __hypothesis_home_directory = Path(where) 

40 if not __hypothesis_home_directory: 

41 __hypothesis_home_directory = __hypothesis_home_directory_default 

42 return __hypothesis_home_directory.joinpath(*names) 

43 

44 

45_first_postinit_what = None 

46 

47 

48def check_sideeffect_during_initialization( 

49 what: str, *fmt_args: object, is_restart: bool = False 

50) -> None: 

51 """Called from locations that should not be executed during initialization, for example 

52 touching disk or materializing lazy/deferred strategies from plugins. If initialization 

53 is in progress, a warning is emitted. 

54 

55 Note that computing the repr can take nontrivial time or memory, so we avoid doing so 

56 unless (and until) we're actually emitting the warning. 

57 """ 

58 global _first_postinit_what 

59 # This is not a particularly hot path, but neither is it doing productive work, so we want to 

60 # minimize the cost by returning immediately. The drawback is that we require 

61 # notice_initialization_restarted() to be called if in_initialization changes away from zero. 

62 if _first_postinit_what is not None: 

63 return 

64 elif _hypothesis_globals.in_initialization > 0: 

65 msg = what.format(*fmt_args) 

66 if is_restart: 

67 when = "between importing hypothesis and loading the hypothesis plugin" 

68 elif "_hypothesis_pytestplugin" in sys.modules or os.getenv( 

69 "HYPOTHESIS_EXTEND_INITIALIZATION" 

70 ): 

71 when = "during pytest plugin or conftest initialization" 

72 else: # pragma: no cover 

73 # This can be triggered by Hypothesis plugins, but is really annoying 

74 # to test automatically - drop st.text().example() in hypothesis.run() 

75 # to manually confirm that we get the warning. 

76 when = "at import time" 

77 # Note: -Werror is insufficient under pytest, as doesn't take effect until 

78 # test session start. 

79 text = ( 

80 f"Slow code in plugin: avoid {msg} {when}! Set PYTHONWARNINGS=error " 

81 "to get a traceback and show which plugin is responsible." 

82 ) 

83 if is_restart: 

84 text += " Additionally, set HYPOTHESIS_EXTEND_INITIALIZATION=1 to pinpoint the exact location." 

85 warnings.warn( 

86 text, 

87 HypothesisSideeffectWarning, 

88 stacklevel=3, 

89 ) 

90 else: 

91 _first_postinit_what = (what, fmt_args) 

92 

93 

94def notice_initialization_restarted(*, warn: bool = True) -> None: 

95 """Reset _first_postinit_what, so that we don't think we're in post-init. Additionally, if it 

96 was set that means that there has been a sideeffect that we haven't warned about, so do that 

97 now (the warning text will be correct, and we also hint that the stacktrace can be improved). 

98 """ 

99 global _first_postinit_what 

100 if _first_postinit_what is not None: 

101 what, *fmt_args = _first_postinit_what 

102 _first_postinit_what = None 

103 if warn: 

104 check_sideeffect_during_initialization( 

105 what, 

106 *fmt_args, 

107 is_restart=True, 

108 )