Skip to content

Commit c9e7b09

Browse files
committed
added new tests, updated documentation
1 parent ebb46cd commit c9e7b09

File tree

3 files changed

+62
-4
lines changed

3 files changed

+62
-4
lines changed

doc/devel/interface_specs.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,9 @@ CommandLine
358358
``name_source``
359359
Indicates the list of input fields from which the value of the current File
360360
output variable will be drawn. This input field must be the name of a File.
361+
Chaining is allowed, meaning that an input field can point to another as
362+
``name_source``, which also points as ``name_source`` to a third field.
363+
In this situation, the templates for substitutions are also accumulated.
361364

362365
``name_template``
363366
By default a ``%s_generated`` template is used to create the output

nipype/interfaces/base.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@
4747

4848
__docformat__ = 'restructuredtext'
4949

50+
class NipypeInterfaceError(Exception):
51+
def __init__(self, value):
52+
self.value = value
53+
def __str__(self):
54+
return repr(self.value)
55+
5056
def _lock_files():
5157
tmpdir = '/tmp'
5258
pattern = '.X*-lock'
@@ -1510,7 +1516,10 @@ def _format_arg(self, name, trait_spec, value):
15101516
# Append options using format string.
15111517
return argstr % value
15121518

1513-
def _filename_from_source(self, name):
1519+
def _filename_from_source(self, name, chain=None):
1520+
if chain is None:
1521+
chain = []
1522+
15141523
trait_spec = self.inputs.trait(name)
15151524
retval = getattr(self.inputs, name)
15161525

@@ -1546,8 +1555,13 @@ def _filename_from_source(self, name):
15461555
except AttributeError:
15471556
base = source
15481557
else:
1549-
base = self._filename_from_source(ns)
1558+
if name in chain:
1559+
raise NipypeInterfaceError('Mutually pointing name_sources')
1560+
1561+
chain.append(name)
1562+
base = self._filename_from_source(ns, chain)
15501563

1564+
chain = None
15511565
retval = name_template % base
15521566
_, _, ext = split_filename(retval)
15531567
if trait_spec.keep_extension and ext:

nipype/interfaces/tests/test_base.py

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,49 @@ class TestName(nib.CommandLine):
218218

219219
testobj = TestName()
220220
testobj.inputs.doo = tmp_infile
221-
yield assert_true, '%s_mootpl' % nme in testobj.cmdline
222-
yield assert_true, '%s_mootpl_generated' % nme in testobj.cmdline
221+
res = testobj.cmdline
222+
yield assert_true, '%s' % tmp_infile in res
223+
yield assert_true, '%s_mootpl ' % nme in res
224+
yield assert_true, '%s_mootpl_generated' % nme in res
225+
226+
os.chdir(pwd)
227+
teardown_file(tmpd)
228+
229+
230+
def test_cycle_namesource():
231+
tmp_infile = setup_file()
232+
tmpd, nme, ext = split_filename(tmp_infile)
233+
pwd = os.getcwd()
234+
os.chdir(tmpd)
235+
236+
from unittest import TestCase
237+
238+
class spec3(nib.CommandLineInputSpec):
239+
moo = nib.File(name_source=['doo'], hash_files=False, argstr="%s",
240+
position=1, name_template='%s_mootpl')
241+
poo = nib.File(name_source=['moo'], hash_files=False,
242+
argstr="%s", position=2)
243+
doo = nib.File(name_source=['poo'], hash_files=False,
244+
argstr="%s", position=3)
245+
246+
class TestCycle(nib.CommandLine):
247+
_cmd = "mycommand"
248+
input_spec = spec3
249+
250+
def get_cmd(self):
251+
return self.cmdline
252+
253+
# Check that an exception is raised
254+
to0 = TestCycle()
255+
yield assert_raises, nib.NipypeInterfaceError, to0.get_cmd
256+
257+
# Check that loop can be broken by setting one of the inputs
258+
to1 = TestCycle()
259+
to1.inputs.poo = tmp_infile
260+
res = to1.cmdline
261+
yield assert_true, '%s' % tmp_infile in res
262+
yield assert_true, '%s_generated ' % nme in res
263+
yield assert_true, '%s_generated_mootpl' % nme in res
223264

224265
os.chdir(pwd)
225266
teardown_file(tmpd)

0 commit comments

Comments
 (0)