Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/hypothesis/internal/coverage.py: 25%

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

57 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 json 

12import os 

13import sys 

14from collections.abc import Callable 

15from contextlib import contextmanager 

16from typing import TypeVar 

17 

18from hypothesis.internal.reflection import proxies 

19 

20""" 

21This module implements a custom coverage system that records conditions and 

22then validates that every condition has been seen to be both True and False 

23during the execution of our tests. 

24 

25The only thing we use it for at present is our argument validation functions, 

26where we assert that every validation function has been seen to both pass and 

27fail in the course of testing. 

28 

29When not running with a magic environment variable set, this module disables 

30itself and has essentially no overhead. 

31""" 

32 

33Func = TypeVar("Func", bound=Callable) 

34pretty_file_name_cache: dict[str, str] = {} 

35 

36 

37def pretty_file_name(f): 

38 try: 

39 return pretty_file_name_cache[f] 

40 except KeyError: 

41 pass 

42 

43 parts = f.split(os.path.sep) 

44 if "hypothesis" in parts: # pragma: no branch 

45 parts = parts[-parts[::-1].index("hypothesis") :] 

46 result = os.path.sep.join(parts) 

47 pretty_file_name_cache[f] = result 

48 return result 

49 

50 

51IN_COVERAGE_TESTS = os.getenv("HYPOTHESIS_INTERNAL_COVERAGE") == "true" 

52description_stack = [] 

53 

54 

55if IN_COVERAGE_TESTS: 

56 # By this point, "branch-check" should have already been deleted by the 

57 # tox config. We can't delete it here because of #1718. 

58 

59 written: set[tuple[str, bool]] = set() 

60 

61 def record_branch(name, value): 

62 key = (name, value) 

63 if key in written: 

64 return 

65 written.add(key) 

66 with open(f"branch-check-{os.getpid()}", mode="a", encoding="utf-8") as log: 

67 log.write(json.dumps({"name": name, "value": value}) + "\n") 

68 

69 @contextmanager 

70 def check_block(name, depth): 

71 # We add an extra two callers to the stack: One for the contextmanager 

72 # function, one for our actual caller, so we want to go two extra 

73 # stack frames up. 

74 caller = sys._getframe(depth + 2) 

75 fname = pretty_file_name(caller.f_code.co_filename) 

76 local_description = f"{name} at {fname}:{caller.f_lineno}" 

77 try: 

78 description_stack.append(local_description) 

79 description = " in ".join(reversed(description_stack)) + " passed" 

80 yield 

81 record_branch(description, True) 

82 except BaseException: 

83 record_branch(description, False) 

84 raise 

85 finally: 

86 description_stack.pop() 

87 

88 @contextmanager 

89 def check(name): 

90 with check_block(name, 2): 

91 yield 

92 

93 def check_function(f: Func) -> Func: 

94 @proxies(f) 

95 def accept(*args, **kwargs): 

96 # depth of 2 because of the proxy function calling us. 

97 with check_block(f.__name__, 2): 

98 return f(*args, **kwargs) 

99 

100 return accept 

101 

102else: # pragma: no cover 

103 

104 def check_function(f: Func) -> Func: 

105 return f 

106 

107 @contextmanager 

108 def check(name): 

109 yield