diff --git a/nipype/interfaces/afni/base.py b/nipype/interfaces/afni/base.py index becfd828f7..f1a3a18429 100644 --- a/nipype/interfaces/afni/base.py +++ b/nipype/interfaces/afni/base.py @@ -294,13 +294,10 @@ class AFNIPythonCommandInputSpec(CommandLineInputSpec): class AFNIPythonCommand(AFNICommand): @property def cmd(self): - if spawn.find_executable(super(AFNIPythonCommand, - self).cmd) is not None: - return spawn.find_executable(super(AFNIPythonCommand, self).cmd) - else: - return super(AFNIPythonCommand, self).cmd + orig_cmd = super(AFNIPythonCommand, self).cmd + found = spawn.find_executable(orig_cmd) + return found if found is not None else orig_cmd @property - def cmdline(self): - return "{} {}".format(self.inputs.py27_path, - super(AFNIPythonCommand, self).cmdline) + def _cmd_prefix(self): + return "{} ".format(self.inputs.py27_path) diff --git a/nipype/interfaces/base/core.py b/nipype/interfaces/base/core.py index 34f650cde2..7ed9413d2d 100644 --- a/nipype/interfaces/base/core.py +++ b/nipype/interfaces/base/core.py @@ -26,6 +26,7 @@ import platform import select import subprocess as sp +import shlex import sys from textwrap import wrap import simplejson as json @@ -857,6 +858,7 @@ class must be instantiated with a command argument """ input_spec = CommandLineInputSpec + _cmd_prefix = '' _cmd = None _version = None _terminal_output = 'stream' @@ -915,7 +917,7 @@ def cmdline(self): """ `command` plus any arguments (args) validates arguments and generates command line""" self._check_mandatory_inputs() - allargs = [self.cmd] + self._parse_inputs() + allargs = [self._cmd_prefix + self.cmd] + self._parse_inputs() return ' '.join(allargs) @property @@ -986,7 +988,7 @@ def _run_interface(self, runtime, correct_return_codes=(0, )): runtime.environ.update(out_environ) # which $cmd - executable_name = self.cmd.split()[0] + executable_name = shlex.split(self._cmd_prefix + self.cmd)[0] cmd_path = which(executable_name, env=runtime.environ) if cmd_path is None: diff --git a/nipype/interfaces/base/tests/test_core.py b/nipype/interfaces/base/tests/test_core.py index 05a9f02b47..2c8439403a 100644 --- a/nipype/interfaces/base/tests/test_core.py +++ b/nipype/interfaces/base/tests/test_core.py @@ -480,3 +480,38 @@ def test_global_CommandLine_output(tmpdir): # Check default affects derived interfaces ci = BET() assert ci.terminal_output == 'file' + + +def test_CommandLine_prefix(tmpdir): + tmpdir.chdir() + oop = 'out/of/path' + os.makedirs(oop) + + script_name = 'test_script.sh' + script_path = os.path.join(oop, script_name) + with open(script_path, 'w') as script_f: + script_f.write('#!/usr/bin/env bash\necho Success!') + os.chmod(script_path, 0o755) + + ci = nib.CommandLine(command=script_name) + with pytest.raises(IOError): + ci.run() + + class OOPCLI(nib.CommandLine): + _cmd_prefix = oop + '/' + + ci = OOPCLI(command=script_name) + ci.run() + + class OOPShell(nib.CommandLine): + _cmd_prefix = 'bash {}/'.format(oop) + + ci = OOPShell(command=script_name) + ci.run() + + class OOPBadShell(nib.CommandLine): + _cmd_prefix = 'shell_dne {}/'.format(oop) + + ci = OOPBadShell(command=script_name) + with pytest.raises(IOError): + ci.run() diff --git a/nipype/interfaces/freesurfer/preprocess.py b/nipype/interfaces/freesurfer/preprocess.py index 3e70200ad3..b2d6173099 100644 --- a/nipype/interfaces/freesurfer/preprocess.py +++ b/nipype/interfaces/freesurfer/preprocess.py @@ -655,8 +655,9 @@ def cmdline(self): files = self._get_filelist(outdir) for infile, outfile in files: if not os.path.exists(outfile): - single_cmd = '%s %s %s' % (self.cmd, infile, - os.path.join(outdir, outfile)) + single_cmd = '%s%s %s %s' % (self._cmd_prefix, self.cmd, + infile, os.path.join(outdir, + outfile)) cmd.extend([single_cmd]) return '; '.join(cmd) diff --git a/nipype/interfaces/minc/minc.py b/nipype/interfaces/minc/minc.py index a520768bde..4c35248132 100644 --- a/nipype/interfaces/minc/minc.py +++ b/nipype/interfaces/minc/minc.py @@ -1742,15 +1742,15 @@ def _list_outputs(self): @property def cmdline(self): output_file_base = self.inputs.output_file_base + orig_cmdline = super(Blur, self).cmdline if isdefined(output_file_base): - return super(Blur, self).cmdline + return orig_cmdline else: # FIXME this seems like a bit of a hack. Can we force output_file # to show up in cmdline by default, even if it isn't specified in # the instantiation of Pik? - return '%s %s' % (super(Blur, self).cmdline, - self._gen_output_base()) + return '%s %s' % (orig_cmdline, self._gen_output_base()) class MathInputSpec(CommandLineInputSpec): diff --git a/nipype/utils/filemanip.py b/nipype/utils/filemanip.py index b88bcbd257..24820bfbd8 100644 --- a/nipype/utils/filemanip.py +++ b/nipype/utils/filemanip.py @@ -774,12 +774,20 @@ def which(cmd, env=None, pathext=None): return filename return None + def isexec(path): + return os.path.isfile(path) and os.access(path, os.X_OK) + for ext in pathext: extcmd = cmd + ext - for directory in path.split(os.pathsep): - filename = op.join(directory, extcmd) - if op.exists(filename): - return filename + fpath, fname = os.path.split(extcmd) + if fpath: + if isexec(extcmd): + return extcmd + else: + for directory in path.split(os.pathsep): + filename = op.join(directory, extcmd) + if isexec(filename): + return filename return None