/usr/lib/python2.7/dist-packages/dipy/tests/scriptrunner.py is in python-dipy 0.10.1-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | """ Module to help tests check script output
Provides class to be instantiated in tests that check scripts. Usually works
something like this in a test module::
from .scriptrunner import ScriptRunner
runner = ScriptRunner()
Then, in the tests, something like::
code, stdout, stderr = runner.run_command(['my-script', my_arg])
assert_equal(code, 0)
assert_equal(stdout, b'This script ran OK')
"""
import sys
import os
from os.path import (dirname, join as pjoin, isfile, isdir, realpath, pathsep)
from subprocess import Popen, PIPE
try: # Python 2
string_types = basestring,
except NameError: # Python 3
string_types = str,
def _get_package():
""" Workaround for missing ``__package__`` in Python 3.2
"""
if '__package__' in globals() and not __package__ is None:
return __package__
return __name__.split('.', 1)[0]
# Same as __package__ for Python 2.6, 2.7 and >= 3.3
MY_PACKAGE=_get_package()
def local_script_dir(script_sdir):
""" Get local script directory if running in development dir, else None
"""
# Check for presence of scripts in development directory. ``realpath``
# allows for the situation where the development directory has been linked
# into the path.
package_path = dirname(__import__(MY_PACKAGE).__file__)
above_us = realpath(pjoin(package_path, '..'))
devel_script_dir = pjoin(above_us, script_sdir)
if isfile(pjoin(above_us, 'setup.py')) and isdir(devel_script_dir):
return devel_script_dir
return None
def local_module_dir(module_name):
""" Get local module directory if running in development dir, else None
"""
mod = __import__(module_name)
containing_path = dirname(dirname(realpath(mod.__file__)))
if containing_path == realpath(os.getcwd()):
return containing_path
return None
class ScriptRunner(object):
""" Class to run scripts and return output
Finds local scripts and local modules if running in the development
directory, otherwise finds system scripts and modules.
"""
def __init__(self,
script_sdir = 'scripts',
module_sdir = MY_PACKAGE,
debug_print_var = None,
output_processor = lambda x : x
):
""" Init ScriptRunner instance
Parameters
----------
script_sdir : str, optional
Name of subdirectory in top-level directory (directory containing
setup.py), to find scripts in development tree. Typically
'scripts', but might be 'bin'.
module_sdir : str, optional
Name of subdirectory in top-level directory (directory containing
setup.py), to find main package directory.
debug_print_vsr : str, optional
Name of environment variable that indicates whether to do debug
printing or no.
output_processor : callable
Callable to run on the stdout, stderr outputs before returning
them. Use this to convert bytes to unicode, strip whitespace, etc.
"""
self.local_script_dir = local_script_dir(script_sdir)
self.local_module_dir = local_module_dir(module_sdir)
if debug_print_var is None:
debug_print_var = '{0}_DEBUG_PRINT'.format(module_sdir.upper())
self.debug_print = os.environ.get(debug_print_var, False)
self.output_processor = output_processor
def run_command(self, cmd, check_code=True):
""" Run command sequence `cmd` returning exit code, stdout, stderr
Parameters
----------
cmd : str or sequence
string with command name or sequence of strings defining command
check_code : {True, False}, optional
If True, raise error for non-zero return code
Returns
-------
returncode : int
return code from execution of `cmd`
stdout : bytes (python 3) or str (python 2)
stdout from `cmd`
stderr : bytes (python 3) or str (python 2)
stderr from `cmd`
"""
if isinstance(cmd, string_types):
cmd = [cmd]
else:
cmd = list(cmd)
if not self.local_script_dir is None:
# Windows can't run script files without extensions natively so we need
# to run local scripts (no extensions) via the Python interpreter. On
# Unix, we might have the wrong incantation for the Python interpreter
# in the hash bang first line in the source file. So, either way, run
# the script through the Python interpreter
cmd = [sys.executable,
pjoin(self.local_script_dir, cmd[0])] + cmd[1:]
elif os.name == 'nt':
# Need .bat file extension for windows
cmd[0] += '.bat'
if os.name == 'nt':
# Quote any arguments with spaces. The quotes delimit the arguments
# on Windows, and the arguments might be files paths with spaces.
# On Unix the list elements are each separate arguments.
cmd = ['"{0}"'.format(c) if ' ' in c else c for c in cmd]
if self.debug_print:
print("Running command '%s'" % cmd)
env = os.environ
if not self.local_module_dir is None:
# module likely comes from the current working directory. We might need
# that directory on the path if we're running the scripts from a
# temporary directory
env = env.copy()
pypath = env.get('PYTHONPATH', None)
if pypath is None:
env['PYTHONPATH'] = self.local_module_dir
else:
env['PYTHONPATH'] = self.local_module_dir + pathsep + pypath
proc = Popen(cmd, stdout=PIPE, stderr=PIPE, env=env)
stdout, stderr = proc.communicate()
if proc.poll() == None:
proc.terminate()
if check_code and proc.returncode != 0:
raise RuntimeError(
"""Command "{0}" failed with
stdout
------
{1}
stderr
------
{2}
""".format(cmd, stdout, stderr))
opp = self.output_processor
return proc.returncode, opp(stdout), opp(stderr)
|