12
12
import os
13
13
import struct
14
14
import sys
15
- import types
15
+
16
+ from importlib .machinery import ModuleSpec
17
+ from types import CodeType , ModuleType
18
+ from typing import Any , List , Optional , Tuple
16
19
17
20
from coverage import env
18
21
from coverage .exceptions import CoverageException , _ExceptionDuringRun , NoCode , NoSource
@@ -30,11 +33,13 @@ class DummyLoader:
30
33
31
34
Currently only implements the .fullname attribute
32
35
"""
33
- def __init__ (self , fullname , * _args ) :
36
+ def __init__ (self , fullname : str , * _args : Any ) -> None :
34
37
self .fullname = fullname
35
38
36
39
37
- def find_module (modulename ):
40
+ def find_module (
41
+ modulename : str ,
42
+ ) -> Tuple [Optional [str ], str , ModuleSpec ]:
38
43
"""Find the module named `modulename`.
39
44
40
45
Returns the file path of the module, the name of the enclosing
@@ -68,18 +73,23 @@ class PyRunner:
68
73
This is meant to emulate real Python execution as closely as possible.
69
74
70
75
"""
71
- def __init__ (self , args , as_module = False ):
76
+ def __init__ (self , args : List [ str ] , as_module : bool = False ) -> None :
72
77
self .args = args
73
78
self .as_module = as_module
74
79
75
80
self .arg0 = args [0 ]
76
- self .package = self .modulename = self .pathname = self .loader = self .spec = None
81
+ self .package : Optional [str ] = None
82
+ self .modulename : Optional [str ] = None
83
+ self .pathname : Optional [str ] = None
84
+ self .loader : Optional [DummyLoader ] = None
85
+ self .spec : Optional [ModuleSpec ] = None
77
86
78
- def prepare (self ):
87
+ def prepare (self ) -> None :
79
88
"""Set sys.path properly.
80
89
81
90
This needs to happen before any importing, and without importing anything.
82
91
"""
92
+ path0 : Optional [str ]
83
93
if self .as_module :
84
94
path0 = os .getcwd ()
85
95
elif os .path .isdir (self .arg0 ):
@@ -113,7 +123,7 @@ def prepare(self):
113
123
if path0 is not None :
114
124
sys .path [0 ] = python_reported_file (path0 )
115
125
116
- def _prepare2 (self ):
126
+ def _prepare2 (self ) -> None :
117
127
"""Do more preparation to run Python code.
118
128
119
129
Includes finding the module to run and adjusting sys.argv[0].
@@ -126,6 +136,7 @@ def _prepare2(self):
126
136
if self .spec is not None :
127
137
self .modulename = self .spec .name
128
138
self .loader = DummyLoader (self .modulename )
139
+ assert pathname is not None
129
140
self .pathname = os .path .abspath (pathname )
130
141
self .args [0 ] = self .arg0 = self .pathname
131
142
elif os .path .isdir (self .arg0 ):
@@ -155,25 +166,25 @@ def _prepare2(self):
155
166
156
167
self .arg0 = python_reported_file (self .arg0 )
157
168
158
- def run (self ):
169
+ def run (self ) -> None :
159
170
"""Run the Python code!"""
160
171
161
172
self ._prepare2 ()
162
173
163
174
# Create a module to serve as __main__
164
- main_mod = types . ModuleType ('__main__' )
175
+ main_mod = ModuleType ('__main__' )
165
176
166
177
from_pyc = self .arg0 .endswith ((".pyc" , ".pyo" ))
167
178
main_mod .__file__ = self .arg0
168
179
if from_pyc :
169
180
main_mod .__file__ = main_mod .__file__ [:- 1 ]
170
181
if self .package is not None :
171
182
main_mod .__package__ = self .package
172
- main_mod .__loader__ = self .loader
183
+ main_mod .__loader__ = self .loader # type: ignore[assignment]
173
184
if self .spec is not None :
174
185
main_mod .__spec__ = self .spec
175
186
176
- main_mod .__builtins__ = sys .modules ['builtins' ]
187
+ main_mod .__builtins__ = sys .modules ['builtins' ] # type: ignore[attr-defined]
177
188
178
189
sys .modules ['__main__' ] = main_mod
179
190
@@ -209,6 +220,9 @@ def run(self):
209
220
# so that the coverage.py code doesn't appear in the final printed
210
221
# traceback.
211
222
typ , err , tb = sys .exc_info ()
223
+ assert typ is not None
224
+ assert err is not None
225
+ assert tb is not None
212
226
213
227
# PyPy3 weirdness. If I don't access __context__, then somehow it
214
228
# is non-None when the exception is reported at the upper layer,
@@ -218,6 +232,7 @@ def run(self):
218
232
219
233
# Call the excepthook.
220
234
try :
235
+ assert err .__traceback__ is not None
221
236
err .__traceback__ = err .__traceback__ .tb_next
222
237
sys .excepthook (typ , err , tb .tb_next )
223
238
except SystemExit : # pylint: disable=try-except-raise
@@ -227,7 +242,11 @@ def run(self):
227
242
# shenanigans is kind of involved.
228
243
sys .stderr .write ("Error in sys.excepthook:\n " )
229
244
typ2 , err2 , tb2 = sys .exc_info ()
245
+ assert typ2 is not None
246
+ assert err2 is not None
247
+ assert tb2 is not None
230
248
err2 .__suppress_context__ = True
249
+ assert err2 .__traceback__ is not None
231
250
err2 .__traceback__ = err2 .__traceback__ .tb_next
232
251
sys .__excepthook__ (typ2 , err2 , tb2 .tb_next )
233
252
sys .stderr .write ("\n Original exception was:\n " )
@@ -238,7 +257,7 @@ def run(self):
238
257
os .chdir (cwd )
239
258
240
259
241
- def run_python_module (args ) :
260
+ def run_python_module (args : List [ str ]) -> None :
242
261
"""Run a Python module, as though with ``python -m name args...``.
243
262
244
263
`args` is the argument array to present as sys.argv, including the first
@@ -252,7 +271,7 @@ def run_python_module(args):
252
271
runner .run ()
253
272
254
273
255
- def run_python_file (args ) :
274
+ def run_python_file (args : List [ str ]) -> None :
256
275
"""Run a Python file as if it were the main program on the command line.
257
276
258
277
`args` is the argument array to present as sys.argv, including the first
@@ -267,18 +286,18 @@ def run_python_file(args):
267
286
runner .run ()
268
287
269
288
270
- def make_code_from_py (filename ) :
289
+ def make_code_from_py (filename : str ) -> CodeType :
271
290
"""Get source from `filename` and make a code object of it."""
272
291
# Open the source file.
273
292
try :
274
293
source = get_python_source (filename )
275
294
except (OSError , NoSource ) as exc :
276
295
raise NoSource (f"No file to run: '{ filename } '" ) from exc
277
296
278
- return compile (source , filename , "exec" , dont_inherit = True )
297
+ return compile (source , filename , "exec" , dont_inherit = True ) # type: ignore[no-any-return]
279
298
280
299
281
- def make_code_from_pyc (filename ) :
300
+ def make_code_from_pyc (filename : str ) -> CodeType :
282
301
"""Get a code object from a .pyc file."""
283
302
try :
284
303
fpyc = open (filename , "rb" )
@@ -303,5 +322,6 @@ def make_code_from_pyc(filename):
303
322
304
323
# The rest of the file is the code object we want.
305
324
code = marshal .load (fpyc )
325
+ assert isinstance (code , CodeType )
306
326
307
327
return code
0 commit comments