From eadb14fc2404f78f77cf4c5d07a5f37cd249e179 Mon Sep 17 00:00:00 2001 From: Dorota Jarecka Date: Thu, 2 Aug 2018 00:19:21 -0400 Subject: [PATCH 1/7] fixing detailed graph and workflow.run().nodes() representation --- nipype/pipeline/engine/base.py | 3 +++ nipype/pipeline/engine/utils.py | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/nipype/pipeline/engine/base.py b/nipype/pipeline/engine/base.py index 9d0bc3c699..c79abe5610 100644 --- a/nipype/pipeline/engine/base.py +++ b/nipype/pipeline/engine/base.py @@ -95,6 +95,9 @@ def _check_inputs(self, parameter): def __str__(self): return self.fullname + def __repr__(self): + return self.itername + def save(self, filename=None): if filename is None: filename = 'temp.pklz' diff --git a/nipype/pipeline/engine/utils.py b/nipype/pipeline/engine/utils.py index 4ec36afe68..084bd3fc70 100644 --- a/nipype/pipeline/engine/utils.py +++ b/nipype/pipeline/engine/utils.py @@ -507,7 +507,7 @@ def _write_detailed_dot(graph, dotfilename): # write nodes edges = [] for n in nx.topological_sort(graph): - nodename = str(n) + nodename = str(n.itername) inports = [] for u, v, d in graph.in_edges(nbunch=n, data=True): for cd in d['connect']: @@ -519,8 +519,8 @@ def _write_detailed_dot(graph, dotfilename): ipstrip = 'in%s' % _replacefunk(inport) opstrip = 'out%s' % _replacefunk(outport) edges.append( - '%s:%s:e -> %s:%s:w;' % (str(u).replace('.', ''), opstrip, - str(v).replace('.', ''), ipstrip)) + '%s:%s:e -> %s:%s:w;' % (u.itername.replace('.', ''), opstrip, + v.itername.replace('.', ''), ipstrip)) if inport not in inports: inports.append(inport) inputstr = ['{IN'] + [ From 431be357d36bbf752d6d59731f9b698b40919328 Mon Sep 17 00:00:00 2001 From: Dorota Jarecka Date: Thu, 2 Aug 2018 08:56:35 -0400 Subject: [PATCH 2/7] moving itername and _id from Node to EngineBase --- nipype/pipeline/engine/base.py | 9 +++++++++ nipype/pipeline/engine/nodes.py | 9 --------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/nipype/pipeline/engine/base.py b/nipype/pipeline/engine/base.py index c79abe5610..7ee066a4a7 100644 --- a/nipype/pipeline/engine/base.py +++ b/nipype/pipeline/engine/base.py @@ -41,6 +41,7 @@ def __init__(self, name=None, base_dir=None): self.base_dir = base_dir self.config = deepcopy(config._sections) self.name = name + self._id = self.name # for compatibility with node expansion using iterables @property def name(self): @@ -66,6 +67,14 @@ def inputs(self): def outputs(self): raise NotImplementedError + @property + def itername(self): + """Name for expanded iterable""" + itername = self._id + if self._hierarchy: + itername = '%s.%s' % (self._hierarchy, self._id) + return itername + def clone(self, name): """Clone an EngineBase object diff --git a/nipype/pipeline/engine/nodes.py b/nipype/pipeline/engine/nodes.py index 5ac9e72fae..af93fd140b 100644 --- a/nipype/pipeline/engine/nodes.py +++ b/nipype/pipeline/engine/nodes.py @@ -159,7 +159,6 @@ def __init__(self, self._got_inputs = False self._originputs = None self._output_dir = None - self._id = self.name # for compatibility with node expansion using iterables self.iterables = iterables self.synchronize = synchronize @@ -249,14 +248,6 @@ def n_procs(self, value): if hasattr(self._interface.inputs, 'num_threads'): self._interface.inputs.num_threads = self._n_procs - @property - def itername(self): - """Name for expanded iterable""" - itername = self._id - if self._hierarchy: - itername = '%s.%s' % (self._hierarchy, self._id) - return itername - def output_dir(self): """Return the location of the output directory for the node""" # Output dir is cached From 7ed4ea28c770362fa490fc44f53898ffec2a9736 Mon Sep 17 00:00:00 2001 From: Dorota Jarecka Date: Thu, 2 Aug 2018 09:34:08 -0400 Subject: [PATCH 3/7] cleaning self.name in EngineBase.__init__ --- nipype/pipeline/engine/base.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/nipype/pipeline/engine/base.py b/nipype/pipeline/engine/base.py index 7ee066a4a7..6b718afd87 100644 --- a/nipype/pipeline/engine/base.py +++ b/nipype/pipeline/engine/base.py @@ -36,12 +36,11 @@ def __init__(self, name=None, base_dir=None): """ self._hierarchy = None - self._name = None + self._name = name + self._id = self.name # for compatibility with node expansion using iterables self.base_dir = base_dir self.config = deepcopy(config._sections) - self.name = name - self._id = self.name # for compatibility with node expansion using iterables @property def name(self): From f860ad69b01a03dc8a25e4dd473e597d3108ab13 Mon Sep 17 00:00:00 2001 From: Dorota Jarecka Date: Thu, 2 Aug 2018 10:06:37 -0400 Subject: [PATCH 4/7] fixing self.node in EngineBase --- nipype/pipeline/engine/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nipype/pipeline/engine/base.py b/nipype/pipeline/engine/base.py index 6b718afd87..7f7afd3928 100644 --- a/nipype/pipeline/engine/base.py +++ b/nipype/pipeline/engine/base.py @@ -36,7 +36,7 @@ def __init__(self, name=None, base_dir=None): """ self._hierarchy = None - self._name = name + self.name = name self._id = self.name # for compatibility with node expansion using iterables self.base_dir = base_dir From 052ee725858b88bf124798cbbb62c8d585cc19db Mon Sep 17 00:00:00 2001 From: Dorota Jarecka Date: Thu, 2 Aug 2018 14:33:36 -0400 Subject: [PATCH 5/7] adding tests for dot files (workflows with and without iterables) --- nipype/pipeline/engine/tests/test_engine.py | 144 +++++++++++++++++++- 1 file changed, 143 insertions(+), 1 deletion(-) diff --git a/nipype/pipeline/engine/tests/test_engine.py b/nipype/pipeline/engine/tests/test_engine.py index 151849241c..ae6dcf8efc 100644 --- a/nipype/pipeline/engine/tests/test_engine.py +++ b/nipype/pipeline/engine/tests/test_engine.py @@ -9,7 +9,7 @@ from builtins import open from copy import deepcopy from glob import glob -import os +import os, pdb import pytest @@ -441,6 +441,7 @@ def test_write_graph_runs(tmpdir): assert os.path.exists('graph.dot') or os.path.exists( 'graph_detailed.dot') + try: os.remove('graph.dot') except OSError: @@ -484,6 +485,147 @@ def test_deep_nested_write_graph_runs(tmpdir): pass +# examples of dot files used in the following test +dotfile_orig = ('strict digraph {\n' + '"mod1 (engine)";\n' + '"mod2 (engine)";\n' + '"mod1 (engine)" -> "mod2 (engine)";\n' + '}\n') + +dotfile_detailed_orig = ('digraph structs {\n' + 'node [shape=record];\n' + 'pipemod1 [label="{IN}|{ mod1 | engine | }|{OUT| output1}"];\n' + 'pipemod2 [label="{IN| input1}|{ mod2 | engine | }|{OUT}"];\n' + 'pipemod1:outoutput1:e -> pipemod2:ininput1:w;\n' + '}') + +dotfile_flat = dotfile_orig +dotfile_detailed_flat = dotfile_detailed_orig + +dotfile_exec = dotfile_orig +dotfile_detailed_exec = dotfile_detailed_orig + + +dotfile_hierarchical = ('digraph pipe{\n' + ' label="pipe";\n' + ' pipe_mod1[label="mod1 (engine)"];\n' + ' pipe_mod2[label="mod2 (engine)"];\n' + ' pipe_mod1 -> pipe_mod2;\n' + '}') + +dotfile_colored = ('digraph pipe{\n' + ' label="pipe";\n' + ' pipe_mod1[label="mod1 (engine)", style=filled, fillcolor="#FFFFC8"];\n' + ' pipe_mod2[label="mod2 (engine)", style=filled, fillcolor="#FFFFC8"];\n' + ' pipe_mod1 -> pipe_mod2;\n' + '}') + +@pytest.mark.parametrize("simple", [True, False]) +@pytest.mark.parametrize("graph_type", ['orig', 'flat', 'exec', 'hierarchical', 'colored']) +def test_write_graph_dotfile(tmpdir, graph_type, simple): + """ checking dot files for a workflow without iterables""" + tmpdir.chdir() + + pipe = pe.Workflow(name='pipe') + mod1 = pe.Node(interface=EngineTestInterface(), name='mod1') + mod2 = pe.Node(interface=EngineTestInterface(), name='mod2') + pipe.connect([(mod1, mod2, [('output1', 'input1')])]) + pipe.write_graph( + graph2use=graph_type, simple_form=simple, format='dot') + + with open("graph.dot") as f: + graph_str = f.read() + if simple: + assert graph_str == eval("dotfile_{}".format(graph_type)) + else: + # if simple=False graph.dot uses longer names + if graph_type in ["hierarchical", "colored"]: + assert graph_str == eval("dotfile_{}".format(graph_type)).replace( + "mod1 (engine)", "mod1.EngineTestInterface.engine").replace( + "mod2 (engine)", "mod2.EngineTestInterface.engine") + else: + assert graph_str == eval("dotfile_{}".format(graph_type)).replace( + "mod1 (engine)", "pipe.mod1.EngineTestInterface.engine").replace( + "mod2 (engine)", "pipe.mod2.EngineTestInterface.engine") + + # graph_detailed is not created for hierachical or colored + if graph_type not in ["hierarchical", "colored"]: + with open("graph_detailed.dot") as f: + graph_str =f.read() + assert graph_str == eval("dotfile_detailed_{}".format(graph_type)) + + +# examples of dot files used in the following test +dotfile_iter_orig = dotfile_orig +dotfile_detailed_iter_orig = dotfile_detailed_orig + +dotfile_iter_flat = dotfile_orig +dotfile_detailed_iter_flat = dotfile_detailed_orig + +dotfile_iter_exec = dotfile_orig +dotfile_detailed_iter_exec = ( + 'digraph structs {\n' + 'node [shape=record];\n' + 'pipemod1aIa1 [label="{IN}|{ a1 | engine | mod1.aI }|{OUT| output1}"];\n' + 'pipemod2a1 [label="{IN| input1}|{ a1 | engine | mod2 }|{OUT}"];\n' + 'pipemod1aIa0 [label="{IN}|{ a0 | engine | mod1.aI }|{OUT| output1}"];\n' + 'pipemod2a0 [label="{IN| input1}|{ a0 | engine | mod2 }|{OUT}"];\n' + 'pipemod1aIa0:outoutput1:e -> pipemod2a0:ininput1:w;\n' + 'pipemod1aIa1:outoutput1:e -> pipemod2a1:ininput1:w;\n' + '}') + +dotfile_iter_hierarchical = ( + 'digraph pipe{\n' + ' label="pipe";\n' + ' pipe_mod1[label="mod1 (engine)", shape=box3d,style=filled, color=black, colorscheme=greys7 fillcolor=2];\n' + ' pipe_mod2[label="mod2 (engine)"];\n' + ' pipe_mod1 -> pipe_mod2;\n' + '}') + +dotfile_iter_colored = ( + 'digraph pipe{\n' + ' label="pipe";\n' + ' pipe_mod1[label="mod1 (engine)", shape=box3d,style=filled, color=black, colorscheme=greys7 fillcolor=2];\n' + ' pipe_mod2[label="mod2 (engine)", style=filled, fillcolor="#FFFFC8"];\n' + ' pipe_mod1 -> pipe_mod2;\n' + '}') + +@pytest.mark.parametrize("simple", [True, False]) +@pytest.mark.parametrize("graph_type", ['orig', 'flat', 'exec', 'hierarchical', 'colored']) +def test_write_graph_dotfile_iterables(tmpdir, graph_type, simple): + """ checking dot files for a workflow with iterables""" + tmpdir.chdir() + + pipe = pe.Workflow(name='pipe') + mod1 = pe.Node(interface=EngineTestInterface(), name='mod1') + mod1.iterables = ('input1', [1, 2]) + mod2 = pe.Node(interface=EngineTestInterface(), name='mod2') + pipe.connect([(mod1, mod2, [('output1', 'input1')])]) + pipe.write_graph( + graph2use=graph_type, simple_form=simple, format='dot') + + with open("graph.dot") as f: + graph_str = f.read() + if simple: + assert graph_str == eval("dotfile_iter_{}".format(graph_type)) + else: + # if simple=False graph.dot uses longer names + if graph_type in ["hierarchical", "colored"]: + assert graph_str == eval("dotfile_iter_{}".format(graph_type)).replace( + "mod1 (engine)", "mod1.EngineTestInterface.engine").replace( + "mod2 (engine)", "mod2.EngineTestInterface.engine") + else: + assert graph_str == eval("dotfile_iter_{}".format(graph_type)).replace( + "mod1 (engine)", "pipe.mod1.EngineTestInterface.engine").replace( + "mod2 (engine)", "pipe.mod2.EngineTestInterface.engine") + + # graph_detailed is not created for hierachical or colored + if graph_type not in ["hierarchical", "colored"]: + with open("graph_detailed.dot") as f: + graph_str =f.read() + assert graph_str == eval("dotfile_detailed_iter_{}".format(graph_type)) + + def test_io_subclass(): """Ensure any io subclass allows dynamic traits""" from nipype.interfaces.io import IOBase From 879ea288ac24bdb3c5d17d57182946bfefad35a6 Mon Sep 17 00:00:00 2001 From: Dorota Jarecka Date: Thu, 2 Aug 2018 15:34:24 -0400 Subject: [PATCH 6/7] fixing tests for dot files - for py<3.6 the files can have lines in different order --- nipype/pipeline/engine/tests/test_engine.py | 151 ++++++++++---------- 1 file changed, 79 insertions(+), 72 deletions(-) diff --git a/nipype/pipeline/engine/tests/test_engine.py b/nipype/pipeline/engine/tests/test_engine.py index ae6dcf8efc..eee2127172 100644 --- a/nipype/pipeline/engine/tests/test_engine.py +++ b/nipype/pipeline/engine/tests/test_engine.py @@ -486,18 +486,18 @@ def test_deep_nested_write_graph_runs(tmpdir): # examples of dot files used in the following test -dotfile_orig = ('strict digraph {\n' - '"mod1 (engine)";\n' - '"mod2 (engine)";\n' - '"mod1 (engine)" -> "mod2 (engine)";\n' - '}\n') - -dotfile_detailed_orig = ('digraph structs {\n' - 'node [shape=record];\n' - 'pipemod1 [label="{IN}|{ mod1 | engine | }|{OUT| output1}"];\n' - 'pipemod2 [label="{IN| input1}|{ mod2 | engine | }|{OUT}"];\n' - 'pipemod1:outoutput1:e -> pipemod2:ininput1:w;\n' - '}') +dotfile_orig = ['strict digraph {\n', + '"mod1 (engine)";\n', + '"mod2 (engine)";\n', + '"mod1 (engine)" -> "mod2 (engine)";\n', + '}\n'] + +dotfile_detailed_orig = ['digraph structs {\n', + 'node [shape=record];\n', + 'pipemod1 [label="{IN}|{ mod1 | engine | }|{OUT| output1}"];\n', + 'pipemod2 [label="{IN| input1}|{ mod2 | engine | }|{OUT}"];\n', + 'pipemod1:outoutput1:e -> pipemod2:ininput1:w;\n', + '}'] dotfile_flat = dotfile_orig dotfile_detailed_flat = dotfile_detailed_orig @@ -506,19 +506,19 @@ def test_deep_nested_write_graph_runs(tmpdir): dotfile_detailed_exec = dotfile_detailed_orig -dotfile_hierarchical = ('digraph pipe{\n' - ' label="pipe";\n' - ' pipe_mod1[label="mod1 (engine)"];\n' - ' pipe_mod2[label="mod2 (engine)"];\n' - ' pipe_mod1 -> pipe_mod2;\n' - '}') +dotfile_hierarchical = ['digraph pipe{\n', + ' label="pipe";\n', + ' pipe_mod1[label="mod1 (engine)"];\n', + ' pipe_mod2[label="mod2 (engine)"];\n', + ' pipe_mod1 -> pipe_mod2;\n', + '}'] -dotfile_colored = ('digraph pipe{\n' - ' label="pipe";\n' - ' pipe_mod1[label="mod1 (engine)", style=filled, fillcolor="#FFFFC8"];\n' - ' pipe_mod2[label="mod2 (engine)", style=filled, fillcolor="#FFFFC8"];\n' - ' pipe_mod1 -> pipe_mod2;\n' - '}') +dotfile_colored = ['digraph pipe{\n', + ' label="pipe";\n', + ' pipe_mod1[label="mod1 (engine)", style=filled, fillcolor="#FFFFC8"];\n', + ' pipe_mod2[label="mod2 (engine)", style=filled, fillcolor="#FFFFC8"];\n', + ' pipe_mod1 -> pipe_mod2;\n', + '}'] @pytest.mark.parametrize("simple", [True, False]) @pytest.mark.parametrize("graph_type", ['orig', 'flat', 'exec', 'hierarchical', 'colored']) @@ -535,24 +535,27 @@ def test_write_graph_dotfile(tmpdir, graph_type, simple): with open("graph.dot") as f: graph_str = f.read() + if simple: - assert graph_str == eval("dotfile_{}".format(graph_type)) + for str in eval("dotfile_{}".format(graph_type)): + assert str in graph_str else: # if simple=False graph.dot uses longer names - if graph_type in ["hierarchical", "colored"]: - assert graph_str == eval("dotfile_{}".format(graph_type)).replace( - "mod1 (engine)", "mod1.EngineTestInterface.engine").replace( - "mod2 (engine)", "mod2.EngineTestInterface.engine") - else: - assert graph_str == eval("dotfile_{}".format(graph_type)).replace( - "mod1 (engine)", "pipe.mod1.EngineTestInterface.engine").replace( - "mod2 (engine)", "pipe.mod2.EngineTestInterface.engine") + for str in eval("dotfile_{}".format(graph_type)): + if graph_type in ["hierarchical", "colored"]: + assert str.replace("mod1 (engine)", "mod1.EngineTestInterface.engine").replace( + "mod2 (engine)", "mod2.EngineTestInterface.engine") in graph_str + else: + assert str.replace( + "mod1 (engine)", "pipe.mod1.EngineTestInterface.engine").replace( + "mod2 (engine)", "pipe.mod2.EngineTestInterface.engine") in graph_str # graph_detailed is not created for hierachical or colored if graph_type not in ["hierarchical", "colored"]: with open("graph_detailed.dot") as f: - graph_str =f.read() - assert graph_str == eval("dotfile_detailed_{}".format(graph_type)) + graph_str = f.read() + for str in eval("dotfile_detailed_{}".format(graph_type)): + assert str in graph_str # examples of dot files used in the following test @@ -563,32 +566,32 @@ def test_write_graph_dotfile(tmpdir, graph_type, simple): dotfile_detailed_iter_flat = dotfile_detailed_orig dotfile_iter_exec = dotfile_orig -dotfile_detailed_iter_exec = ( - 'digraph structs {\n' - 'node [shape=record];\n' - 'pipemod1aIa1 [label="{IN}|{ a1 | engine | mod1.aI }|{OUT| output1}"];\n' - 'pipemod2a1 [label="{IN| input1}|{ a1 | engine | mod2 }|{OUT}"];\n' - 'pipemod1aIa0 [label="{IN}|{ a0 | engine | mod1.aI }|{OUT| output1}"];\n' - 'pipemod2a0 [label="{IN| input1}|{ a0 | engine | mod2 }|{OUT}"];\n' - 'pipemod1aIa0:outoutput1:e -> pipemod2a0:ininput1:w;\n' - 'pipemod1aIa1:outoutput1:e -> pipemod2a1:ininput1:w;\n' - '}') - -dotfile_iter_hierarchical = ( - 'digraph pipe{\n' - ' label="pipe";\n' - ' pipe_mod1[label="mod1 (engine)", shape=box3d,style=filled, color=black, colorscheme=greys7 fillcolor=2];\n' - ' pipe_mod2[label="mod2 (engine)"];\n' - ' pipe_mod1 -> pipe_mod2;\n' - '}') - -dotfile_iter_colored = ( - 'digraph pipe{\n' - ' label="pipe";\n' - ' pipe_mod1[label="mod1 (engine)", shape=box3d,style=filled, color=black, colorscheme=greys7 fillcolor=2];\n' - ' pipe_mod2[label="mod2 (engine)", style=filled, fillcolor="#FFFFC8"];\n' - ' pipe_mod1 -> pipe_mod2;\n' - '}') +dotfile_detailed_iter_exec = [ + 'digraph structs {\n', + 'node [shape=record];\n', + 'pipemod1aIa1 [label="{IN}|{ a1 | engine | mod1.aI }|{OUT| output1}"];\n', + 'pipemod2a1 [label="{IN| input1}|{ a1 | engine | mod2 }|{OUT}"];\n', + 'pipemod1aIa0 [label="{IN}|{ a0 | engine | mod1.aI }|{OUT| output1}"];\n', + 'pipemod2a0 [label="{IN| input1}|{ a0 | engine | mod2 }|{OUT}"];\n', + 'pipemod1aIa0:outoutput1:e -> pipemod2a0:ininput1:w;\n', + 'pipemod1aIa1:outoutput1:e -> pipemod2a1:ininput1:w;\n', + '}'] + +dotfile_iter_hierarchical = [ + 'digraph pipe{\n', + ' label="pipe";\n', + ' pipe_mod1[label="mod1 (engine)", shape=box3d,style=filled, color=black, colorscheme=greys7 fillcolor=2];\n', + ' pipe_mod2[label="mod2 (engine)"];\n', + ' pipe_mod1 -> pipe_mod2;\n', + '}'] + +dotfile_iter_colored = [ + 'digraph pipe{\n', + ' label="pipe";\n', + ' pipe_mod1[label="mod1 (engine)", shape=box3d,style=filled, color=black, colorscheme=greys7 fillcolor=2];\n', + ' pipe_mod2[label="mod2 (engine)", style=filled, fillcolor="#FFFFC8"];\n', + ' pipe_mod1 -> pipe_mod2;\n', + '}'] @pytest.mark.parametrize("simple", [True, False]) @pytest.mark.parametrize("graph_type", ['orig', 'flat', 'exec', 'hierarchical', 'colored']) @@ -606,24 +609,28 @@ def test_write_graph_dotfile_iterables(tmpdir, graph_type, simple): with open("graph.dot") as f: graph_str = f.read() + if simple: - assert graph_str == eval("dotfile_iter_{}".format(graph_type)) + for str in eval("dotfile_iter_{}".format(graph_type)): + assert str in graph_str else: # if simple=False graph.dot uses longer names - if graph_type in ["hierarchical", "colored"]: - assert graph_str == eval("dotfile_iter_{}".format(graph_type)).replace( - "mod1 (engine)", "mod1.EngineTestInterface.engine").replace( - "mod2 (engine)", "mod2.EngineTestInterface.engine") - else: - assert graph_str == eval("dotfile_iter_{}".format(graph_type)).replace( - "mod1 (engine)", "pipe.mod1.EngineTestInterface.engine").replace( - "mod2 (engine)", "pipe.mod2.EngineTestInterface.engine") + for str in eval("dotfile_iter_{}".format(graph_type)): + if graph_type in ["hierarchical", "colored"]: + assert str.replace("mod1 (engine)", "mod1.EngineTestInterface.engine").replace( + "mod2 (engine)", "mod2.EngineTestInterface.engine") in graph_str + else: + assert str.replace( + "mod1 (engine)", "pipe.mod1.EngineTestInterface.engine").replace( + "mod2 (engine)", "pipe.mod2.EngineTestInterface.engine") in graph_str # graph_detailed is not created for hierachical or colored if graph_type not in ["hierarchical", "colored"]: with open("graph_detailed.dot") as f: - graph_str =f.read() - assert graph_str == eval("dotfile_detailed_iter_{}".format(graph_type)) + graph_str = f.read() + for str in eval("dotfile_detailed_iter_{}".format(graph_type)): + assert str in graph_str + def test_io_subclass(): From 670c39ea33baf9c116b0891559811ffbfd6fc3af Mon Sep 17 00:00:00 2001 From: Dorota Jarecka Date: Mon, 6 Aug 2018 11:26:05 -0400 Subject: [PATCH 7/7] small cleaning, Chris review --- nipype/pipeline/engine/tests/test_engine.py | 66 ++++++++++++--------- nipype/pipeline/engine/utils.py | 2 +- 2 files changed, 39 insertions(+), 29 deletions(-) diff --git a/nipype/pipeline/engine/tests/test_engine.py b/nipype/pipeline/engine/tests/test_engine.py index eee2127172..44afbb2e2a 100644 --- a/nipype/pipeline/engine/tests/test_engine.py +++ b/nipype/pipeline/engine/tests/test_engine.py @@ -9,7 +9,7 @@ from builtins import open from copy import deepcopy from glob import glob -import os, pdb +import os import pytest @@ -499,12 +499,6 @@ def test_deep_nested_write_graph_runs(tmpdir): 'pipemod1:outoutput1:e -> pipemod2:ininput1:w;\n', '}'] -dotfile_flat = dotfile_orig -dotfile_detailed_flat = dotfile_detailed_orig - -dotfile_exec = dotfile_orig -dotfile_detailed_exec = dotfile_detailed_orig - dotfile_hierarchical = ['digraph pipe{\n', ' label="pipe";\n', @@ -520,6 +514,14 @@ def test_deep_nested_write_graph_runs(tmpdir): ' pipe_mod1 -> pipe_mod2;\n', '}'] +dotfiles = { + "orig": dotfile_orig, + "flat": dotfile_orig, + "exec": dotfile_orig, + "hierarchical": dotfile_hierarchical, + "colored": dotfile_colored + } + @pytest.mark.parametrize("simple", [True, False]) @pytest.mark.parametrize("graph_type", ['orig', 'flat', 'exec', 'hierarchical', 'colored']) def test_write_graph_dotfile(tmpdir, graph_type, simple): @@ -537,35 +539,29 @@ def test_write_graph_dotfile(tmpdir, graph_type, simple): graph_str = f.read() if simple: - for str in eval("dotfile_{}".format(graph_type)): - assert str in graph_str + for line in dotfiles[graph_type]: + assert line in graph_str else: # if simple=False graph.dot uses longer names - for str in eval("dotfile_{}".format(graph_type)): + for line in dotfiles[graph_type]: if graph_type in ["hierarchical", "colored"]: - assert str.replace("mod1 (engine)", "mod1.EngineTestInterface.engine").replace( + assert line.replace("mod1 (engine)", "mod1.EngineTestInterface.engine").replace( "mod2 (engine)", "mod2.EngineTestInterface.engine") in graph_str else: - assert str.replace( + assert line.replace( "mod1 (engine)", "pipe.mod1.EngineTestInterface.engine").replace( "mod2 (engine)", "pipe.mod2.EngineTestInterface.engine") in graph_str + # graph_detailed is the same for orig, flat, exec (if no iterables) # graph_detailed is not created for hierachical or colored if graph_type not in ["hierarchical", "colored"]: with open("graph_detailed.dot") as f: graph_str = f.read() - for str in eval("dotfile_detailed_{}".format(graph_type)): - assert str in graph_str + for line in dotfile_detailed_orig: + assert line in graph_str # examples of dot files used in the following test -dotfile_iter_orig = dotfile_orig -dotfile_detailed_iter_orig = dotfile_detailed_orig - -dotfile_iter_flat = dotfile_orig -dotfile_detailed_iter_flat = dotfile_detailed_orig - -dotfile_iter_exec = dotfile_orig dotfile_detailed_iter_exec = [ 'digraph structs {\n', 'node [shape=record];\n', @@ -593,6 +589,20 @@ def test_write_graph_dotfile(tmpdir, graph_type, simple): ' pipe_mod1 -> pipe_mod2;\n', '}'] +dotfiles_iter = { + "orig": dotfile_orig, + "flat": dotfile_orig, + "exec": dotfile_orig, + "hierarchical": dotfile_iter_hierarchical, + "colored": dotfile_iter_colored + } + +dotfiles_detailed_iter = { + "orig": dotfile_detailed_orig, + "flat": dotfile_detailed_orig, + "exec": dotfile_detailed_iter_exec + } + @pytest.mark.parametrize("simple", [True, False]) @pytest.mark.parametrize("graph_type", ['orig', 'flat', 'exec', 'hierarchical', 'colored']) def test_write_graph_dotfile_iterables(tmpdir, graph_type, simple): @@ -611,16 +621,16 @@ def test_write_graph_dotfile_iterables(tmpdir, graph_type, simple): graph_str = f.read() if simple: - for str in eval("dotfile_iter_{}".format(graph_type)): - assert str in graph_str + for line in dotfiles_iter[graph_type]: + assert line in graph_str else: # if simple=False graph.dot uses longer names - for str in eval("dotfile_iter_{}".format(graph_type)): + for line in dotfiles_iter[graph_type]: if graph_type in ["hierarchical", "colored"]: - assert str.replace("mod1 (engine)", "mod1.EngineTestInterface.engine").replace( + assert line.replace("mod1 (engine)", "mod1.EngineTestInterface.engine").replace( "mod2 (engine)", "mod2.EngineTestInterface.engine") in graph_str else: - assert str.replace( + assert line.replace( "mod1 (engine)", "pipe.mod1.EngineTestInterface.engine").replace( "mod2 (engine)", "pipe.mod2.EngineTestInterface.engine") in graph_str @@ -628,8 +638,8 @@ def test_write_graph_dotfile_iterables(tmpdir, graph_type, simple): if graph_type not in ["hierarchical", "colored"]: with open("graph_detailed.dot") as f: graph_str = f.read() - for str in eval("dotfile_detailed_iter_{}".format(graph_type)): - assert str in graph_str + for line in dotfiles_detailed_iter[graph_type]: + assert line in graph_str diff --git a/nipype/pipeline/engine/utils.py b/nipype/pipeline/engine/utils.py index 084bd3fc70..0bb5351ad5 100644 --- a/nipype/pipeline/engine/utils.py +++ b/nipype/pipeline/engine/utils.py @@ -507,7 +507,7 @@ def _write_detailed_dot(graph, dotfilename): # write nodes edges = [] for n in nx.topological_sort(graph): - nodename = str(n.itername) + nodename = n.itername inports = [] for u, v, d in graph.in_edges(nbunch=n, data=True): for cd in d['connect']: