Coverage for coverage / execfile.py: 98.655%

181 statements  

« prev     ^ index     » next       coverage.py v7.12.1a0.dev1, created at 2025-11-30 17:57 +0000

1# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 

2# For details: https://github.com/coveragepy/coveragepy/blob/main/NOTICE.txt 

3 

4"""Execute files of Python code.""" 

5 

6from __future__ import annotations 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

7 

8import importlib.machinery 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

9import importlib.util 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

10import inspect 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

11import marshal 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

12import os 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

13import struct 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

14import sys 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

15from importlib.machinery import ModuleSpec 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

16from types import CodeType, ModuleType 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

17from typing import Any 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

18 

19from coverage.exceptions import CoverageException, NoCode, NoSource, _ExceptionDuringRun 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

20from coverage.files import canonical_filename, python_reported_file 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

21from coverage.misc import isolate_module 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

22from coverage.python import get_python_source 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

23 

24os = isolate_module(os) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

25 

26 

27PYC_MAGIC_NUMBER = importlib.util.MAGIC_NUMBER 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

28 

29 

30class DummyLoader: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

31 """A shim for the pep302 __loader__, emulating pkgutil.ImpLoader. 

32 

33 Currently only implements the .fullname attribute 

34 """ 

35 

36 def __init__(self, fullname: str, *_args: Any) -> None: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

37 self.fullname = fullname 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

38 

39 

40def find_module( 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

41 modulename: str, 

42) -> tuple[str | None, str, ModuleSpec]: 

43 """Find the module named `modulename`. 

44 

45 Returns the file path of the module, the name of the enclosing 

46 package, and the spec. 

47 """ 

48 try: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

49 spec = importlib.util.find_spec(modulename) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

50 except ImportError as err: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

51 raise NoSource(str(err)) from err 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

52 if not spec: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

53 raise NoSource(f"No module named {modulename!r}") 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

54 pathname = spec.origin 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

55 packagename = spec.name 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

56 if spec.submodule_search_locations: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

57 mod_main = modulename + ".__main__" 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

58 spec = importlib.util.find_spec(mod_main) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

59 if not spec: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

60 raise NoSource( 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

61 f"No module named {mod_main}; " 

62 + f"{modulename!r} is a package and cannot be directly executed", 

63 ) 

64 pathname = spec.origin 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

65 packagename = spec.name 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

66 packagename = packagename.rpartition(".")[0] 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

67 return pathname, packagename, spec 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

68 

69 

70class PyRunner: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

71 """Multi-stage execution of Python code. 

72 

73 This is meant to emulate real Python execution as closely as possible. 

74 

75 """ 

76 

77 def __init__(self, args: list[str], as_module: bool = False) -> None: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

78 self.args = args 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

79 self.as_module = as_module 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

80 

81 self.arg0 = args[0] 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

82 self.package: str | None = None 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

83 self.modulename: str | None = None 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

84 self.pathname: str | None = None 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

85 self.loader: DummyLoader | None = None 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

86 self.spec: ModuleSpec | None = None 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

87 

88 def prepare(self) -> None: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

89 """Set sys.path properly. 

90 

91 This needs to happen before any importing, and without importing anything. 

92 """ 

93 path0: str | None 

94 if getattr(sys.flags, "safe_path", False): 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

95 # See https://docs.python.org/3/using/cmdline.html#cmdoption-P 

96 path0 = None 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789

97 elif self.as_module: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

98 path0 = os.getcwd() 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

99 elif os.path.isdir(self.arg0): 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

100 # Running a directory means running the __main__.py file in that 

101 # directory. 

102 path0 = self.arg0 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

103 else: 

104 path0 = os.path.abspath(os.path.dirname(self.arg0)) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

105 

106 if os.path.isdir(sys.path[0]): 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

107 # sys.path fakery. If we are being run as a command, then sys.path[0] 

108 # is the directory of the "coverage" script. If this is so, replace 

109 # sys.path[0] with the directory of the file we're running, or the 

110 # current directory when running modules. If it isn't so, then we 

111 # don't know what's going on, and just leave it alone. 

112 top_file = inspect.stack()[-1][0].f_code.co_filename 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

113 sys_path_0_abs = os.path.abspath(sys.path[0]) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

114 top_file_dir_abs = os.path.abspath(os.path.dirname(top_file)) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

115 sys_path_0_abs = canonical_filename(sys_path_0_abs) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

116 top_file_dir_abs = canonical_filename(top_file_dir_abs) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

117 if sys_path_0_abs != top_file_dir_abs: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

118 path0 = None 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

119 

120 else: 

121 # sys.path[0] is a file. Is the next entry the directory containing 

122 # that file? 

123 if sys.path[1] == os.path.dirname(sys.path[0]): 123 ↛ 125line 123 didn't jump to line 125 because the condition on line 123 was never true1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

124 # Can it be right to always remove that? 

125 del sys.path[1] 

126 

127 if path0 is not None: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

128 sys.path[0] = python_reported_file(path0) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

129 

130 def _prepare2(self) -> None: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

131 """Do more preparation to run Python code. 

132 

133 Includes finding the module to run and adjusting sys.argv[0]. 

134 This method is allowed to import code. 

135 

136 """ 

137 if self.as_module: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

138 self.modulename = self.arg0 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

139 pathname, self.package, self.spec = find_module(self.modulename) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

140 if self.spec is not None: 140 ↛ 142line 140 didn't jump to line 142 because the condition on line 140 was always true1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

141 self.modulename = self.spec.name 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

142 self.loader = DummyLoader(self.modulename) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

143 assert pathname is not None 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

144 self.pathname = os.path.abspath(pathname) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

145 self.args[0] = self.arg0 = self.pathname 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

146 elif os.path.isdir(self.arg0): 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

147 # Running a directory means running the __main__.py file in that 

148 # directory. 

149 for ext in [".py", ".pyc", ".pyo"]: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

150 try_filename = os.path.join(self.arg0, f"__main__{ext}") 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

151 # 3.8.10 changed how files are reported when running a 

152 # directory. 

153 try_filename = os.path.abspath(try_filename) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

154 if os.path.exists(try_filename): 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

155 self.arg0 = try_filename 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

156 break 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

157 else: 

158 raise NoSource(f"Can't find '__main__' module in '{self.arg0}'") 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

159 

160 # Make a spec. I don't know if this is the right way to do it. 

161 try_filename = python_reported_file(try_filename) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

162 self.spec = importlib.machinery.ModuleSpec("__main__", None, origin=try_filename) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

163 self.spec.has_location = True 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

164 self.package = "" 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

165 self.loader = DummyLoader("__main__") 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

166 else: 

167 self.loader = DummyLoader("__main__") 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

168 

169 self.arg0 = python_reported_file(self.arg0) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

170 

171 def run(self) -> None: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

172 """Run the Python code!""" 

173 

174 self._prepare2() 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

175 

176 # Create a module to serve as __main__ 

177 main_mod = ModuleType("__main__") 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

178 

179 from_pyc = self.arg0.endswith((".pyc", ".pyo")) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

180 main_mod.__file__ = self.arg0 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

181 if from_pyc: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

182 main_mod.__file__ = main_mod.__file__[:-1] 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

183 if self.package is not None: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

184 main_mod.__package__ = self.package 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

185 main_mod.__loader__ = self.loader # type: ignore[assignment] 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

186 if self.spec is not None: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

187 main_mod.__spec__ = self.spec 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

188 

189 main_mod.__builtins__ = sys.modules["builtins"] # type: ignore[attr-defined] 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

190 

191 sys.modules["__main__"] = main_mod 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

192 

193 # Set sys.argv properly. 

194 sys.argv = self.args 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

195 

196 try: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

197 # Make a code object somehow. 

198 if from_pyc: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

199 code = make_code_from_pyc(self.arg0) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

200 else: 

201 code = make_code_from_py(self.arg0) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

202 except CoverageException: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

203 raise 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

204 except Exception as exc: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

205 msg = f"Couldn't run '{self.arg0}' as Python code: {exc.__class__.__name__}: {exc}" 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

206 raise CoverageException(msg) from exc 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

207 

208 # Execute the code object. 

209 # Return to the original directory in case the test code exits in 

210 # a non-existent directory. 

211 cwd = os.getcwd() 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

212 try: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

213 exec(code, main_mod.__dict__) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

214 except SystemExit: # pylint: disable=try-except-raise 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

215 # The user called sys.exit(). Just pass it along to the upper 

216 # layers, where it will be handled. 

217 raise 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

218 except Exception: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

219 # Something went wrong while executing the user code. 

220 # Get the exc_info, and pack them into an exception that we can 

221 # throw up to the outer loop. We peel one layer off the traceback 

222 # so that the coverage.py code doesn't appear in the final printed 

223 # traceback. 

224 typ, err, tb = sys.exc_info() 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

225 assert typ is not None 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

226 assert err is not None 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

227 assert tb is not None 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

228 

229 # PyPy3 weirdness. If I don't access __context__, then somehow it 

230 # is non-None when the exception is reported at the upper layer, 

231 # and a nested exception is shown to the user. This getattr fixes 

232 # it somehow? https://bitbucket.org/pypy/pypy/issue/1903 

233 getattr(err, "__context__", None) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

234 

235 # Call the excepthook. 

236 try: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

237 assert err.__traceback__ is not None 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

238 err.__traceback__ = err.__traceback__.tb_next 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

239 sys.excepthook(typ, err, tb.tb_next) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

240 except SystemExit: # pylint: disable=try-except-raise 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

241 raise 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

242 except Exception as exc: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

243 # Getting the output right in the case of excepthook 

244 # shenanigans is kind of involved. 

245 sys.stderr.write("Error in sys.excepthook:\n") 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

246 typ2, err2, tb2 = sys.exc_info() 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

247 assert typ2 is not None 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

248 assert err2 is not None 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

249 assert tb2 is not None 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

250 err2.__suppress_context__ = True 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

251 assert err2.__traceback__ is not None 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

252 err2.__traceback__ = err2.__traceback__.tb_next 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

253 sys.__excepthook__(typ2, err2, tb2.tb_next) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

254 sys.stderr.write("\nOriginal exception was:\n") 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

255 raise _ExceptionDuringRun(typ, err, tb.tb_next) from exc 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

256 else: 

257 sys.exit(1) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

258 finally: 

259 os.chdir(cwd) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

260 

261 

262def run_python_module(args: list[str]) -> None: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

263 """Run a Python module, as though with ``python -m name args...``. 

264 

265 `args` is the argument array to present as sys.argv, including the first 

266 element naming the module being executed. 

267 

268 This is a helper for tests, to encapsulate how to use PyRunner. 

269 

270 """ 

271 runner = PyRunner(args, as_module=True) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

272 runner.prepare() 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

273 runner.run() 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

274 

275 

276def run_python_file(args: list[str]) -> None: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

277 """Run a Python file as if it were the main program on the command line. 

278 

279 `args` is the argument array to present as sys.argv, including the first 

280 element naming the file being executed. `package` is the name of the 

281 enclosing package, if any. 

282 

283 This is a helper for tests, to encapsulate how to use PyRunner. 

284 

285 """ 

286 runner = PyRunner(args, as_module=False) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

287 runner.prepare() 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

288 runner.run() 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

289 

290 

291def make_code_from_py(filename: str) -> CodeType: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

292 """Get source from `filename` and make a code object of it.""" 

293 try: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

294 source = get_python_source(filename) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

295 except (OSError, NoSource) as exc: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

296 raise NoSource(f"No file to run: '{filename}'") from exc 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

297 

298 code = compile(source, filename, mode="exec", dont_inherit=True) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

299 return code 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

300 

301 

302def make_code_from_pyc(filename: str) -> CodeType: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

303 """Get a code object from a .pyc file.""" 

304 try: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

305 fpyc = open(filename, "rb") 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

306 except OSError as exc: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

307 raise NoCode(f"No file to run: '{filename}'") from exc 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

308 

309 with fpyc: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

310 # First four bytes are a version-specific magic number. It has to 

311 # match or we won't run the file. 

312 magic = fpyc.read(4) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

313 if magic != PYC_MAGIC_NUMBER: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

314 raise NoCode(f"Bad magic number in .pyc file: {magic!r} != {PYC_MAGIC_NUMBER!r}") 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

315 

316 flags = struct.unpack("<L", fpyc.read(4))[0] 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

317 hash_based = flags & 0x01 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

318 if hash_based: 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

319 fpyc.read(8) # Skip the hash. 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

320 else: 

321 # Skip the junk in the header that we don't need. 

322 fpyc.read(4) # Skip the moddate. 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

323 fpyc.read(4) # Skip the size. 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

324 

325 # The rest of the file is the code object we want. 

326 code = marshal.load(fpyc) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

327 assert isinstance(code, CodeType) 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89

328 

329 return code 1!#$%'(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567)89