Skip to content

Commit

Permalink
fix: dealing with nipy#2968
Browse files Browse the repository at this point in the history
  • Loading branch information
oesteban committed Jul 18, 2019
1 parent 510ef2d commit 6cf22ce
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 51 deletions.
27 changes: 19 additions & 8 deletions nipype/interfaces/base/tests/test_traits_extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class _test_spec(nib.TraitedSpec):
f = nib.traits.Dict(nib.Str, nib.File())
g = nib.traits.Either(nib.File, nib.Str)
h = nib.Str
ee = nib.OutputMultiObject(nib.Str)


def test_rebase_path_traits():
Expand All @@ -36,23 +37,28 @@ def test_rebase_path_traits():
'/some/path')
assert c == [Path('f1.txt'), Path('f2.txt'), Path('f3.txt')]

d = rebase_path_traits(
spec.trait('d'), 2.0, '/some/path')
assert d == 2.0

d = rebase_path_traits(
spec.trait('d'), '/some/path/either.txt', '/some/path')
assert '%s' % d == 'either.txt'

e = rebase_path_traits(
spec.trait('e'), ['/some/path/f1.txt', '/some/path/f2.txt', '/some/path/f3.txt'],
'/some/path')
assert e == [Path('f1.txt'), Path('f2.txt'), Path('f3.txt')]

e = rebase_path_traits(
spec.trait('e'), [['/some/path/f1.txt', '/some/path/f2.txt'], [['/some/path/f3.txt']]],
'/some/path')
assert e == [[Path('f1.txt'), Path('f2.txt')], [[Path('f3.txt')]]]

f = rebase_path_traits(
spec.trait('f'), {'1': '/some/path/f1.txt'}, '/some/path')
assert f == {'1': Path('f1.txt')}

d = rebase_path_traits(
spec.trait('d'), 2.0, '/some/path')
assert d == 2.0

d = rebase_path_traits(
spec.trait('d'), '/some/path/either.txt', '/some/path')
assert '%s' % d == 'either.txt'

g = rebase_path_traits(
spec.trait('g'), 'some/path/either.txt', '/some/path')
assert '%s' % g == 'some/path/either.txt'
Expand All @@ -69,3 +75,8 @@ def test_rebase_path_traits():

h = rebase_path_traits(spec.trait('h'), '2', '/some/path')
assert h == '2'

ee = rebase_path_traits(
spec.trait('ee'), [['/some/path/f1.txt', '/some/path/f2.txt'], [['/some/path/f3.txt']]],
'/some/path')
assert ee == [['/some/path/f1.txt', '/some/path/f2.txt'], [['/some/path/f3.txt']]]
27 changes: 17 additions & 10 deletions nipype/interfaces/base/traits_extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -504,18 +504,26 @@ def as_ctrait(self):
traits.Either = PatchedEither


def _rebase_path(value, cwd):
if isinstance(value, list):
return [_rebase_path(v, cwd) for v in value]

try:
value = Path(value)
except TypeError:
pass
else:
try:
value = Path(value).relative_to(cwd)
except ValueError:
pass
return value


def rebase_path_traits(thistrait, value, cwd):
"""Rebase a BasePath-derived trait given an interface spec."""
if thistrait.is_trait_type(BasePath):
try:
value = Path(value)
except TypeError:
pass
else:
try:
value = Path(value).relative_to(cwd)
except ValueError:
pass
value = _rebase_path(value, cwd)
elif thistrait.is_trait_type(traits.List):
innertrait, = thistrait.inner_traits
if not isinstance(value, (list, tuple)):
Expand All @@ -533,7 +541,6 @@ def rebase_path_traits(thistrait, value, cwd):
elif thistrait.alternatives:
is_str = [f.is_trait_type((traits.String, traits.BaseStr, traits.BaseBytes, Str))
for f in thistrait.alternatives]
print(is_str)
if any(is_str) and isinstance(value, (bytes, str)) and not value.startswith('/'):
return value
for subtrait in thistrait.alternatives:
Expand Down
2 changes: 1 addition & 1 deletion nipype/pipeline/engine/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,7 @@ def _run_command(self, execute, copyfiles=True):
message += ', a CommandLine Interface with command:\n{}'.format(cmd)
logger.info(message)
try:
result = self._interface.run(cwd=outdir)
result = self._interface.run(cwd=outdir, rebase_cwd=True)
except Exception as msg:
result.runtime.stderr = '%s\n\n%s'.format(
getattr(result.runtime, 'stderr', ''), msg)
Expand Down
14 changes: 9 additions & 5 deletions nipype/pipeline/engine/tests/test_nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,13 +295,17 @@ def test_inputs_removal(tmpdir):
def test_outputmultipath_collapse(tmpdir):
"""Test an OutputMultiPath whose initial value is ``[[x]]`` to ensure that
it is returned as ``[x]``, regardless of how accessed."""
select_if = niu.Select(inlist=[[1, 2, 3], [4]], index=1)
select_nd = pe.Node(niu.Select(inlist=[[1, 2, 3], [4]], index=1),
select_if = niu.Select(inlist=[[1, 2, 3], [4], [5]], index=[0, 1])
select_nd = pe.Node(niu.Select(inlist=[[1, 2, 3], [4], [5]], index=[0, 1]),
name='select_nd')

ifres = select_if.run()
ifbase = select_if.run(rebase_cwd=True) # If flattening happens could be the rebase
ndres = select_nd.run()

assert ifres.outputs.out == [4]
assert ndres.outputs.out == [4]
assert select_nd.result.outputs.out == [4]
assert ifres.outputs.out == [[1, 2, 3], [4]]
assert ifbase.outputs.out == [[1, 2, 3], [4]]
assert ndres.outputs.out == [[1, 2, 3], [4]]
assert select_nd.result.outputs.out == [[1, 2, 3], [4]]

# Inconsistent behavior of OutputMultiObject, see #2968
2 changes: 1 addition & 1 deletion nipype/pipeline/engine/tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from ....interfaces import base as nib
from ....interfaces import utility as niu
from .... import config
from ..utils import clean_working_directory, write_workflow_prov, modify_paths
from ..utils import clean_working_directory, write_workflow_prov


class InputSpec(nib.TraitedSpec):
Expand Down
40 changes: 14 additions & 26 deletions nipype/pipeline/engine/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,25 +287,23 @@ def _protect_collapses(hastraits):
def save_resultfile(result, cwd, name):
"""Save a result pklz file to ``cwd``"""
resultsfile = os.path.join(cwd, 'result_%s.pklz' % name)
if result.outputs:
try:
collapsed = _identify_collapses(result.outputs)
outputs = _uncollapse(result.outputs.trait_get(), collapsed)
# Double-protect tosave so that the original, uncollapsed trait
# is saved in the pickle file. Thus, when the loading process
# collapses, the original correct value is loaded.
tosave = _uncollapse(outputs.copy(), collapsed)
except AttributeError:
tosave = outputs = result.outputs.dictcopy() # outputs was a bunch
for k, v in list(modify_paths(tosave, relative=True, basedir=cwd).items()):
setattr(result.outputs, k, v)
# if result.outputs:
# try:
# collapsed = _identify_collapses(result.outputs)
# outputs = _uncollapse(result.outputs.trait_get(), collapsed)
# # Double-protect tosave so that the original, uncollapsed trait
# # is saved in the pickle file. Thus, when the loading process
# # collapses, the original correct value is loaded.
# tosave = _uncollapse(outputs.copy(), collapsed)
# except AttributeError:
# tosave = outputs = result.outputs.dictcopy() # outputs was a bunch

savepkl(resultsfile, result)
logger.debug('saved results in %s', resultsfile)

if result.outputs:
for k, v in list(outputs.items()):
setattr(result.outputs, k, v)
# if result.outputs:
# for k, v in list(outputs.items()):
# setattr(result.outputs, k, v)


def load_resultfile(path, name):
Expand Down Expand Up @@ -350,17 +348,7 @@ def load_resultfile(path, name):
'some file does not exist. hence trait cannot be set')
else:
if result.outputs:
try:
outputs = _protect_collapses(result.outputs)
except AttributeError:
outputs = result.outputs.dictcopy() # outputs == Bunch
try:
for k, v in list(modify_paths(outputs, relative=False,
basedir=path).items()):
setattr(result.outputs, k, v)
except FileNotFoundError:
logger.debug('conversion to full path results in '
'non existent file')
pass # TODO: resolve BasePath traits
aggregate = False
pkl_file.close()
logger.debug('Aggregate: %s', aggregate)
Expand Down

0 comments on commit 6cf22ce

Please sign in to comment.