Skip to content

Commit 414fa39

Browse files
satraeffigies
authored andcommitted
fix: mapnode to generate result file when crashes in single node mode
1 parent f122323 commit 414fa39

File tree

3 files changed

+65
-7
lines changed

3 files changed

+65
-7
lines changed

nipype/info.py

+9-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,15 @@ def get_nipype_gitversion():
155155
# https://github.com/nipy/nipype/pull/2961#issuecomment-512035484
156156
REQUIRES += ["neurdflib"]
157157

158-
TESTS_REQUIRES = ["codecov", "coverage<5", "mock", "pytest", "pytest-cov", "pytest-env"]
158+
TESTS_REQUIRES = [
159+
"codecov",
160+
"coverage<5",
161+
"mock",
162+
"pytest",
163+
"pytest-cov",
164+
"pytest-env",
165+
"pytest-timeout",
166+
]
159167

160168
EXTRA_REQUIRES = {
161169
"data": ["datalad"],

nipype/pipeline/engine/nodes.py

+32-6
Original file line numberDiff line numberDiff line change
@@ -1366,13 +1366,39 @@ def _run_interface(self, execute=True, updatehash=False):
13661366
nodenames = [nnametpl.format(i) for i in range(nitems)]
13671367

13681368
# Run mapnode
1369-
result = self._collate_results(
1370-
_node_runner(
1371-
self._make_nodes(cwd),
1372-
updatehash=updatehash,
1373-
stop_first=str2bool(self.config["execution"]["stop_on_first_crash"]),
1374-
)
1369+
outdir = self.output_dir()
1370+
result = InterfaceResult(
1371+
interface=self._interface.__class__,
1372+
runtime=Bunch(
1373+
cwd=outdir,
1374+
returncode=1,
1375+
environ=dict(os.environ),
1376+
hostname=socket.gethostname(),
1377+
),
1378+
inputs=self._interface.inputs.get_traitsfree(),
13751379
)
1380+
try:
1381+
result = self._collate_results(
1382+
_node_runner(
1383+
self._make_nodes(cwd),
1384+
updatehash=updatehash,
1385+
stop_first=str2bool(
1386+
self.config["execution"]["stop_on_first_crash"]
1387+
),
1388+
)
1389+
)
1390+
except Exception as msg:
1391+
result.runtime.stderr = "%s\n\n%s".format(
1392+
getattr(result.runtime, "stderr", ""), msg
1393+
)
1394+
_save_resultfile(
1395+
result,
1396+
outdir,
1397+
self.name,
1398+
rebase=str2bool(self.config["execution"]["use_relative_paths"]),
1399+
)
1400+
raise
1401+
13761402
# And store results
13771403
_save_resultfile(result, cwd, self.name, rebase=False)
13781404
# remove any node directories no longer required

nipype/pipeline/engine/tests/test_nodes.py

+24
Original file line numberDiff line numberDiff line change
@@ -314,3 +314,27 @@ def test_outputmultipath_collapse(tmpdir):
314314
assert ifres.outputs.out == [4]
315315
assert ndres.outputs.out == [4]
316316
assert select_nd.result.outputs.out == [4]
317+
318+
319+
@pytest.mark.timeout(30)
320+
def test_mapnode_single(tmpdir):
321+
tmpdir.chdir()
322+
323+
def _producer(num=1, output_file=None, deadly_num=7):
324+
if num == deadly_num:
325+
raise RuntimeError("Got the deadly num (%d)." % num)
326+
if output_file is None:
327+
output_file = "producer_output_%05d" % num
328+
with open(output_file, "w") as ofile:
329+
ofile.write("%d" % num)
330+
return output_file
331+
332+
pnode = pe.MapNode(
333+
niu.Function(function=_producer), name="ProducerNode", iterfield=["num"]
334+
)
335+
pnode.inputs.num = [7]
336+
wf = pe.Workflow(name="PC_Workflow")
337+
wf.add_nodes([pnode])
338+
wf.base_dir = os.path.abspath("./test_output")
339+
with pytest.raises(RuntimeError):
340+
wf.run(plugin="MultiProc")

0 commit comments

Comments
 (0)