@@ -173,12 +173,26 @@ def check_output(cmd, **popen_args):
173173 return output .decode ('utf-8' )
174174
175175
176- def try_to_run (cmd ):
176+ def try_to_run (cmd , shell = True ):
177177 try :
178- return check_output (cmd , shell = True )
178+ return check_output (cmd , shell = shell )
179179 except subprocess .CalledProcessError as e :
180180 write (' Error running `%s`: %s' % (cmd , str (getattr (e , 'output' , str (e )))))
181181
182+ def run_python_coverage (args ):
183+ """Run the Python coverage tool
184+
185+ If it's importable in this Python, launch it using 'python -m'.
186+ Otherwise, look it up on PATH like any other command.
187+ """
188+ try :
189+ import coverage
190+ except ImportError :
191+ # Coverage is not installed on this Python. Hope it's on PATH.
192+ try_to_run (['coverage' ] + args , shell = False )
193+ else :
194+ # Coverage is installed on this Python. Run it as a module.
195+ try_to_run ([sys .executable , '-m' , 'coverage' ] + args , shell = False )
182196
183197def remove_non_ascii (data ):
184198 try :
@@ -666,12 +680,12 @@ def main(*argv, **kwargs):
666680 # The `-a` option is mandatory here. If we
667681 # have a `.coverage` in the current directory, calling
668682 # without the option would delete the previous data
669- try_to_run ( 'coverage combine -a' )
683+ run_python_coverage ([ ' combine' , ' -a'] )
670684
671685 if os .path .exists (opj (os .getcwd (), '.coverage' )) and not os .path .exists (opj (os .getcwd (), 'coverage.xml' )):
672686 write (' Generating coverage xml reports for Python' )
673687 # using `-i` to ignore "No source for code" error
674- try_to_run ( 'coverage xml -i' )
688+ run_python_coverage ([ ' xml' , ' -i'] )
675689 reports .append (read (opj (os .getcwd (), 'coverage.xml' )))
676690
677691 reports = list (filter (bool , reports ))
0 commit comments