Skip to content

ENH: Add _cmd_prefix class variable to CommandLine #2379

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jan 22, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 5 additions & 8 deletions nipype/interfaces/afni/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
6 changes: 4 additions & 2 deletions nipype/interfaces/base/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import platform
import select
import subprocess as sp
import shlex
import sys
from textwrap import wrap
import simplejson as json
Expand Down Expand Up @@ -857,6 +858,7 @@ class must be instantiated with a command argument

"""
input_spec = CommandLineInputSpec
_cmd_prefix = ''
_cmd = None
_version = None
_terminal_output = 'stream'
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down
35 changes: 35 additions & 0 deletions nipype/interfaces/base/tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
5 changes: 3 additions & 2 deletions nipype/interfaces/freesurfer/preprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
6 changes: 3 additions & 3 deletions nipype/interfaces/minc/minc.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
16 changes: 12 additions & 4 deletions nipype/utils/filemanip.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down