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

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

54 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 contextlib import contextmanager 

15from typing import Callable, Dict, Set, Tuple, TypeVar 

16 

17from hypothesis.internal.reflection import proxies 

18 

19""" 

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

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

22during the execution of our tests. 

23 

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

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

26fail in the course of testing. 

27 

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

29itself and has essentially no overhead. 

30""" 

31 

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

33pretty_file_name_cache: Dict[str, str] = {} 

34 

35 

36def pretty_file_name(f): 

37 try: 

38 return pretty_file_name_cache[f] 

39 except KeyError: 

40 pass 

41 

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

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

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

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

46 pretty_file_name_cache[f] = result 

47 return result 

48 

49 

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

51description_stack = [] 

52 

53 

54if IN_COVERAGE_TESTS: 

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

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

57 

58 written: Set[Tuple[str, bool]] = set() 

59 

60 def record_branch(name, value): 

61 key = (name, value) 

62 if key in written: 

63 return 

64 written.add(key) 

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

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

67 

68 @contextmanager 

69 def check_block(name, depth): 

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

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

72 # stack frames up. 

73 caller = sys._getframe(depth + 2) 

74 fname = pretty_file_name(caller.f_code.co_filename) 

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

76 try: 

77 description_stack.append(local_description) 

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

79 yield 

80 record_branch(description, True) 

81 except BaseException: 

82 record_branch(description, False) 

83 raise 

84 finally: 

85 description_stack.pop() 

86 

87 @contextmanager 

88 def check(name): 

89 with check_block(name, 2): 

90 yield 

91 

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

93 @proxies(f) 

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

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

96 with check_block(f.__name__, 2): 

97 return f(*args, **kwargs) 

98 

99 return accept 

100 

101else: # pragma: no cover 

102 

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

104 return f 

105 

106 @contextmanager 

107 def check(name): 

108 yield