From 521aecf3fd8e51951638006b6444dad19491840f Mon Sep 17 00:00:00 2001 From: Tom Close Date: Sat, 27 Apr 2024 11:50:31 +1000 Subject: [PATCH] refactored statements into separate sub-package --- nipype2pydra/cli/pkg_gen.py | 34 ++++++- nipype2pydra/node_factory.py | 45 ++++++++- nipype2pydra/statements/__init__.py | 17 ++++ nipype2pydra/statements/assignment.py | 49 ++++++++++ nipype2pydra/{utils => statements}/imports.py | 0 nipype2pydra/statements/misc.py | 32 +++++++ .../utility.py} | 6 +- .../components.py => statements/workflow.py} | 96 ++----------------- nipype2pydra/utils/__init__.py | 3 +- nipype2pydra/utils/io.py | 2 +- nipype2pydra/utils/misc.py | 11 +++ nipype2pydra/utils/symbols.py | 2 +- .../utils/tests/test_utils_imports.py | 2 +- .../{workflow/base.py => workflow.py} | 77 +++++++-------- nipype2pydra/workflow/__init__.py | 1 - 15 files changed, 238 insertions(+), 139 deletions(-) create mode 100644 nipype2pydra/statements/__init__.py create mode 100644 nipype2pydra/statements/assignment.py rename nipype2pydra/{utils => statements}/imports.py (100%) create mode 100644 nipype2pydra/statements/misc.py rename nipype2pydra/{workflow/utility_converters.py => statements/utility.py} (92%) rename nipype2pydra/{workflow/components.py => statements/workflow.py} (79%) rename nipype2pydra/{workflow/base.py => workflow.py} (94%) delete mode 100644 nipype2pydra/workflow/__init__.py diff --git a/nipype2pydra/cli/pkg_gen.py b/nipype2pydra/cli/pkg_gen.py index 8deb2d71..793fd22f 100644 --- a/nipype2pydra/cli/pkg_gen.py +++ b/nipype2pydra/cli/pkg_gen.py @@ -23,6 +23,7 @@ from nipype2pydra.cli.base import cli from nipype2pydra.package import PackageConverter from nipype2pydra.workflow import WorkflowConverter +from nipype2pydra.node_factory import NodeFactoryConverter @cli.command( @@ -129,11 +130,18 @@ def pkg_gen( for wf_path in spec["workflows"]: parts = wf_path.split(".") wf_name = parts[-1] - mod_path = ".".join(parts[:-1]) + nipype_module_str = ".".join(parts[:-1]) + nipype_module = import_module(nipype_module_str) + try: + getattr(nipype_module, wf_name) + except AttributeError: + raise RuntimeError( + f"Did not find workflow function {wf_name} in module {nipype_module_str}" + ) with open(workflows_spec_dir / (wf_path + ".yaml"), "w") as f: f.write( WorkflowConverter.default_spec( - wf_name, mod_path, defaults=wf_defaults + wf_name, nipype_module_str, defaults=wf_defaults ) ) @@ -179,6 +187,28 @@ def pkg_gen( with open(callables_fspath, "w") as f: f.write(parsed.generate_callables(nipype_interface)) + if "node_factories" in spec: + node_factories_spec_dir = spec_dir / "node_factories" + node_factories_spec_dir.mkdir(parents=True, exist_ok=True) + for node_factory_path in spec["node_factories"]: + parts = node_factory_path.split(".") + factory_name = parts[-1] + nipype_module_str = ".".join(parts[:-1]) + nipype_module = import_module(nipype_module_str) + try: + getattr(nipype_module, factory_name) + except AttributeError: + raise RuntimeError( + f"Did not find factory function {factory_name} in module {nipype_module_str}" + ) + + with open(workflows_spec_dir / (wf_path + ".yaml"), "w") as f: + f.write( + NodeFactoryConverter.default_spec( + factory_name, nipype_module_str, defaults=wf_defaults + ) + ) + if interface_only_pkg: with open( pkg_dir diff --git a/nipype2pydra/node_factory.py b/nipype2pydra/node_factory.py index e4f3cdc2..d0f7dec9 100644 --- a/nipype2pydra/node_factory.py +++ b/nipype2pydra/node_factory.py @@ -8,15 +8,17 @@ from importlib import import_module from types import ModuleType import black.report +import yaml from .utils import ( UsedSymbols, extract_args, ImportStatement, full_address, + multiline_comment, ) -from .worflow.components import ( - CommentConverter, - DocStringConverter, +from .statements import ( + CommentStatement, + DocStringStatement, ) import nipype2pydra.package import nipype2pydra.interface @@ -27,7 +29,7 @@ @attrs.define class NodeFactoryConverter: """Specifies how the semi-automatic conversion from Nipype to Pydra should - be performed + be performed for functions that build and return Nipype nodes Parameters ---------- @@ -176,7 +178,7 @@ def _converted_code(self) -> ty.Tuple[str, ty.List[str]]: # Write out the preamble (e.g. docstring, comments, etc..) while parsed_statements and isinstance( parsed_statements[0], - (DocStringConverter, CommentConverter, ImportStatement), + (DocStringStatement, CommentStatement, ImportStatement), ): preamble += str(parsed_statements.pop(0)) + "\n" @@ -216,3 +218,36 @@ def _converted_code(self) -> ty.Tuple[str, ty.List[str]]: code_str = re.sub(find, replace, code_str, flags=re.MULTILINE | re.DOTALL) return code_str, used_configs + + @classmethod + def default_spec( + cls, name: str, nipype_module: str, defaults: ty.Dict[str, ty.Any] + ) -> str: + """Generates a spec for the workflow converter from the given function""" + conv = NodeFactoryConverter( + name=name, + nipype_name=name, + nipype_module=nipype_module, + input_nodes={"inputnode": ""}, + output_nodes={"outputnode": ""}, + **{n: eval(v) for n, v in defaults}, + ) + dct = attrs.asdict(conv) + dct["nipype_module"] = dct["nipype_module"].__name__ + del dct["package"] + del dct["nodes"] + for k in dct: + if not dct[k]: + dct[k] = None + yaml_str = yaml.dump(dct, sort_keys=False) + for k in dct: + fld = getattr(attrs.fields(NodeFactoryConverter), k) + hlp = fld.metadata.get("help") + if hlp: + yaml_str = re.sub( + r"^(" + k + r"):", + multiline_comment(hlp) + r"\1:", + yaml_str, + flags=re.MULTILINE, + ) + return yaml_str diff --git a/nipype2pydra/statements/__init__.py b/nipype2pydra/statements/__init__.py new file mode 100644 index 00000000..d2864316 --- /dev/null +++ b/nipype2pydra/statements/__init__.py @@ -0,0 +1,17 @@ +from .imports import ImportStatement, parse_imports, Imported # noqa: F401 +from .workflow import ( # noqa: F401 + AddNestedWorkflowStatement, + AddNodeStatement, + ConnectionStatement, + IterableStatement, + DynamicField, +) +from .assignment import ( # noqa: F401 + NodeAssignmentStatement, + NestedWorkflowAssignmentStatement, +) +from .misc import DocStringStatement, CommentStatement, ReturnStatement # noqa: F401 +from .utility import ( # noqa: F401 + IdentityInterfaceNodeConverter, + FunctionNodeConverter, +) diff --git a/nipype2pydra/statements/assignment.py b/nipype2pydra/statements/assignment.py new file mode 100644 index 00000000..a5e33ff5 --- /dev/null +++ b/nipype2pydra/statements/assignment.py @@ -0,0 +1,49 @@ +import attrs +import typing as ty +from .workflow import AddNodeStatement, AddNestedWorkflowStatement + + +@attrs.define +class NodeAssignmentStatement: + + nodes: ty.List[AddNodeStatement] = attrs.field() + attribute: str = attrs.field() + value: str = attrs.field() + indent: str = attrs.field() + + def __str__(self): + if not any(n.include for n in self.nodes): + return "" + node_name = self.nodes[0].name + workflow_variable = self.nodes[0].workflow_variable + assert (n.name == node_name for n in self.nodes) + assert (n.workflow_variable == workflow_variable for n in self.nodes) + return f"{self.indent}{workflow_variable}.{node_name}{self.attribute} = {self.value}" + + +@attrs.define +class NestedWorkflowAssignmentStatement: + + nodes: ty.List[AddNestedWorkflowStatement] = attrs.field() + attribute: str = attrs.field() + value: str = attrs.field() + indent: str = attrs.field() + + def __str__(self): + if not any(n.include for n in self.nodes): + return "" + node = self.nodes[0] + if not node.nested_spec: + raise NotImplementedError( + f"Need specification for nested workflow {node.workflow_name} in order to " + "assign to it" + ) + nested_wf = node.nested_spec + parts = self.attribute.split(".") + nested_node_name = parts[2] + attribute_name = parts[3] + target_in = nested_wf.input_name(nested_node_name, attribute_name) + attribute = ".".join(parts[:2] + [target_in] + parts[4:]) + workflow_variable = self.nodes[0].workflow_variable + assert (n.workflow_variable == workflow_variable for n in self.nodes) + return f"{self.indent}{workflow_variable}{attribute} = {self.value}" diff --git a/nipype2pydra/utils/imports.py b/nipype2pydra/statements/imports.py similarity index 100% rename from nipype2pydra/utils/imports.py rename to nipype2pydra/statements/imports.py diff --git a/nipype2pydra/statements/misc.py b/nipype2pydra/statements/misc.py new file mode 100644 index 00000000..4b4639cb --- /dev/null +++ b/nipype2pydra/statements/misc.py @@ -0,0 +1,32 @@ +import typing as ty +import attrs + + +@attrs.define +class ReturnStatement: + + vars: ty.List[str] = attrs.field(converter=lambda s: s.split(", ")) + indent: str = attrs.field() + + def __str__(self): + return f"{self.indent}return {', '.join(self.vars)}" + + +@attrs.define +class CommentStatement: + + comment: str = attrs.field() + indent: str = attrs.field() + + def __str__(self): + return f"{self.indent}# {self.comment}" + + +@attrs.define +class DocStringStatement: + + docstring: str = attrs.field() + indent: str = attrs.field() + + def __str__(self): + return f"{self.indent}{self.docstring}" diff --git a/nipype2pydra/workflow/utility_converters.py b/nipype2pydra/statements/utility.py similarity index 92% rename from nipype2pydra/workflow/utility_converters.py rename to nipype2pydra/statements/utility.py index ae30b5b5..040c145c 100644 --- a/nipype2pydra/workflow/utility_converters.py +++ b/nipype2pydra/statements/utility.py @@ -1,10 +1,10 @@ import re import attrs -from .components import NodeConverter +from .workflow import AddNodeStatement @attrs.define -class FunctionNodeConverter(NodeConverter): +class FunctionNodeConverter(AddNodeStatement): converted_interface = "FunctionTask" @@ -25,7 +25,7 @@ def arg_name_vals(self): @attrs.define -class IdentityInterfaceNodeConverter(NodeConverter): +class IdentityInterfaceNodeConverter(AddNodeStatement): converted_interface = "FunctionTask" diff --git a/nipype2pydra/workflow/components.py b/nipype2pydra/statements/workflow.py similarity index 79% rename from nipype2pydra/workflow/components.py rename to nipype2pydra/statements/workflow.py index a8dfd62a..c6a6a938 100644 --- a/nipype2pydra/workflow/components.py +++ b/nipype2pydra/statements/workflow.py @@ -4,7 +4,7 @@ import attrs if ty.TYPE_CHECKING: - from .base import WorkflowConverter + from ..workflow import WorkflowConverter @attrs.define @@ -60,7 +60,7 @@ def field_converter(field: str) -> ty.Union[str, VarField]: @attrs.define -class ConnectionConverter: +class ConnectionStatement: source_name: str target_name: str @@ -167,27 +167,27 @@ def __str__(self): @attrs.define -class IterableConverter: +class IterableStatement: fieldname: str = attrs.field(converter=field_converter) variable: str = attrs.field() @attrs.define -class NodeConverter: +class AddNodeStatement: name: str interface: str args: ty.List[str] - iterables: ty.List[IterableConverter] + iterables: ty.List[IterableStatement] itersource: ty.Optional[str] indent: str workflow_converter: "WorkflowConverter" = attrs.field(repr=False) splits: ty.List[str] = attrs.field( converter=attrs.converters.default_if_none(factory=list), factory=list ) - in_conns: ty.List[ConnectionConverter] = attrs.field(factory=list) - out_conns: ty.List[ConnectionConverter] = attrs.field(factory=list) + in_conns: ty.List[ConnectionStatement] = attrs.field(factory=list) + out_conns: ty.List[ConnectionStatement] = attrs.field(factory=list) include: bool = attrs.field(default=False) index: int = attrs.field() @@ -282,7 +282,7 @@ def workflow_variable(self): @attrs.define -class NestedWorkflowConverter: +class AddNestedWorkflowStatement: name: str workflow_name: str @@ -291,8 +291,8 @@ class NestedWorkflowConverter: args: ty.List[str] workflow_converter: "WorkflowConverter" = attrs.field(repr=False) include: bool = attrs.field(default=False) - in_conns: ty.List[ConnectionConverter] = attrs.field(factory=list) - out_conns: ty.List[ConnectionConverter] = attrs.field(factory=list) + in_conns: ty.List[ConnectionStatement] = attrs.field(factory=list) + out_conns: ty.List[ConnectionStatement] = attrs.field(factory=list) index: int = attrs.field() @index.default @@ -332,79 +332,3 @@ def conditional(self): @cached_property def workflow_variable(self): return self.workflow_converter.workflow_variable - - -@attrs.define -class ReturnConverter: - - vars: ty.List[str] = attrs.field(converter=lambda s: s.split(", ")) - indent: str = attrs.field() - - def __str__(self): - return f"{self.indent}return {', '.join(self.vars)}" - - -@attrs.define -class CommentConverter: - - comment: str = attrs.field() - indent: str = attrs.field() - - def __str__(self): - return f"{self.indent}# {self.comment}" - - -@attrs.define -class DocStringConverter: - - docstring: str = attrs.field() - indent: str = attrs.field() - - def __str__(self): - return f"{self.indent}{self.docstring}" - - -@attrs.define -class NodeAssignmentConverter: - - nodes: ty.List[NodeConverter] = attrs.field() - attribute: str = attrs.field() - value: str = attrs.field() - indent: str = attrs.field() - - def __str__(self): - if not any(n.include for n in self.nodes): - return "" - node_name = self.nodes[0].name - workflow_variable = self.nodes[0].workflow_variable - assert (n.name == node_name for n in self.nodes) - assert (n.workflow_variable == workflow_variable for n in self.nodes) - return f"{self.indent}{workflow_variable}.{node_name}{self.attribute} = {self.value}" - - -@attrs.define -class NestedWorkflowAssignmentConverter: - - nodes: ty.List[NestedWorkflowConverter] = attrs.field() - attribute: str = attrs.field() - value: str = attrs.field() - indent: str = attrs.field() - - def __str__(self): - if not any(n.include for n in self.nodes): - return "" - node = self.nodes[0] - if not node.nested_spec: - raise NotImplementedError( - f"Need specification for nested workflow {node.workflow_name} in order to " - "assign to it" - ) - nested_wf = node.nested_spec - parts = self.attribute.split(".") - nested_node_name = parts[2] - attribute_name = parts[3] - target_in = nested_wf.input_name(nested_node_name, attribute_name) - attribute = ".".join(parts[:2] + [target_in] + parts[4:]) - workflow_variable = self.nodes[0].workflow_variable - assert (n.workflow_variable == workflow_variable for n in self.nodes) - return f"{self.indent}{workflow_variable}{attribute} = {self.value}" diff --git a/nipype2pydra/utils/__init__.py b/nipype2pydra/utils/__init__.py index b3e714b6..163bd34f 100644 --- a/nipype2pydra/utils/__init__.py +++ b/nipype2pydra/utils/__init__.py @@ -12,9 +12,10 @@ insert_args_in_signature, # noqa: F401 get_source_code, # noqa: F401 split_source_into_statements, # noqa: F401 + multiline_comment, # noqa: F401 INBUILT_NIPYPE_TRAIT_NAMES, # noqa: F401 ) -from .imports import ImportStatement, Imported, parse_imports # noqa: F401 +from ..statements.imports import ImportStatement, Imported, parse_imports # noqa: F401 from .symbols import ( UsedSymbols, # noqa: F401 get_local_functions, # noqa: F401 diff --git a/nipype2pydra/utils/io.py b/nipype2pydra/utils/io.py index ae0117c0..7634cc70 100644 --- a/nipype2pydra/utils/io.py +++ b/nipype2pydra/utils/io.py @@ -6,7 +6,7 @@ import black.parsing import black.report from .misc import cleanup_function_body, split_source_into_statements, get_source_code -from .imports import ImportStatement, parse_imports, GENERIC_PYDRA_IMPORTS +from ..statements.imports import ImportStatement, parse_imports, GENERIC_PYDRA_IMPORTS from .symbols import UsedSymbols diff --git a/nipype2pydra/utils/misc.py b/nipype2pydra/utils/misc.py index 824ba42d..1557c6ca 100644 --- a/nipype2pydra/utils/misc.py +++ b/nipype2pydra/utils/misc.py @@ -417,3 +417,14 @@ def split_source_into_statements(source_code: str) -> ty.List[str]: else: statements.append(line) return statements + + +def multiline_comment(comment: str, line_length: int = 100) -> str: + """Convert a comment string to a multiline comment block of width `line_length`""" + multiline = "" + start_of_line = 0 + for end_of_line in range(line_length, len(comment), line_length): + multiline += "# " + comment[start_of_line:end_of_line] + "\n" + start_of_line = end_of_line + multiline += "# " + comment[start_of_line:] + "\n" + return multiline diff --git a/nipype2pydra/utils/symbols.py b/nipype2pydra/utils/symbols.py index 96436981..4a546781 100644 --- a/nipype2pydra/utils/symbols.py +++ b/nipype2pydra/utils/symbols.py @@ -12,7 +12,7 @@ from nipype.interfaces.base import BaseInterface, TraitedSpec, isdefined, Undefined from nipype.interfaces.base import traits_extension from .misc import split_source_into_statements, extract_args -from .imports import ImportStatement, parse_imports +from ..statements.imports import ImportStatement, parse_imports logger = getLogger("nipype2pydra") diff --git a/nipype2pydra/utils/tests/test_utils_imports.py b/nipype2pydra/utils/tests/test_utils_imports.py index 0ea0d757..bff548a5 100644 --- a/nipype2pydra/utils/tests/test_utils_imports.py +++ b/nipype2pydra/utils/tests/test_utils_imports.py @@ -1,4 +1,4 @@ -from nipype2pydra.utils.imports import ImportStatement, parse_imports +from nipype2pydra.statements.imports import ImportStatement, parse_imports def test_import_statement1(): diff --git a/nipype2pydra/workflow/base.py b/nipype2pydra/workflow.py similarity index 94% rename from nipype2pydra/workflow/base.py rename to nipype2pydra/workflow.py index 25eb9f78..ac8eaf78 100644 --- a/nipype2pydra/workflow/base.py +++ b/nipype2pydra/workflow.py @@ -10,7 +10,7 @@ import black.report import attrs import yaml -from ..utils import ( +from .utils import ( UsedSymbols, split_source_into_statements, extract_args, @@ -19,20 +19,21 @@ full_address, ImportStatement, parse_imports, + multiline_comment, ) -from .components import ( - NodeConverter, - ConnectionConverter, - NestedWorkflowConverter, - CommentConverter, - DocStringConverter, - ReturnConverter, - IterableConverter, +from .statements import ( + AddNodeStatement, + ConnectionStatement, + AddNestedWorkflowStatement, + CommentStatement, + DocStringStatement, + ReturnStatement, + IterableStatement, DynamicField, - NodeAssignmentConverter, - NestedWorkflowAssignmentConverter, + NodeAssignmentStatement, + NestedWorkflowAssignmentStatement, ) -from .utility_converters import UTILITY_CONVERTERS +from .statements.utility import UTILITY_CONVERTERS import nipype2pydra.package logger = logging.getLogger(__name__) @@ -155,7 +156,7 @@ class WorkflowConverter: factory=dict, ) - nodes: ty.Dict[str, ty.List[NodeConverter]] = attrs.field(factory=dict) + nodes: ty.Dict[str, ty.List[AddNodeStatement]] = attrs.field(factory=dict) def __attrs_post_init__(self): if self.workflow_variable is None: @@ -473,7 +474,7 @@ def _converted_code(self) -> ty.Tuple[str, ty.List[str]]: # Write out the preamble (e.g. docstring, comments, etc..) while parsed_statements and isinstance( parsed_statements[0], - (DocStringConverter, CommentConverter, ImportStatement), + (DocStringStatement, CommentStatement, ImportStatement), ): preamble += str(parsed_statements.pop(0)) + "\n" @@ -485,8 +486,8 @@ def _converted_code(self) -> ty.Tuple[str, ty.List[str]]: for nested_workflow in self.nested_workflows.values(): nested_configs.update(nested_workflow.used_configs) - code_str, config_sig, used_configs = self.package.find_and_replace_config_params( - code_str, nested_configs + code_str, config_sig, used_configs = ( + self.package.find_and_replace_config_params(code_str, nested_configs) ) inputs_sig = [f"{i}=attrs.NOTHING" for i in input_spec] @@ -499,7 +500,7 @@ def _converted_code(self) -> ty.Tuple[str, ty.List[str]]: signature += f" -> {return_types}" code_str = signature + ":\n\n" + preamble + code_str - if not isinstance(parsed_statements[-1], ReturnConverter): + if not isinstance(parsed_statements[-1], ReturnStatement): code_str += f"\n return {self.workflow_variable}" # Format the the code before the find and replace so it is more predictable @@ -553,13 +554,13 @@ def _parse_statements(self, func_body: str) -> ty.Tuple[ ty.Union[ str, ImportStatement, - NodeConverter, - ConnectionConverter, - NestedWorkflowConverter, - NodeAssignmentConverter, - DocStringConverter, - CommentConverter, - ReturnConverter, + AddNodeStatement, + ConnectionStatement, + AddNestedWorkflowStatement, + NodeAssignmentStatement, + DocStringStatement, + CommentStatement, + ReturnStatement, ] ], str, @@ -589,13 +590,13 @@ def _parse_statements(self, func_body: str) -> ty.Tuple[ continue if match := re.match(r"^(\s*)#\s*(.*)", statement): # comments parsed.append( - CommentConverter(comment=match.group(2), indent=match.group(1)) + CommentStatement(comment=match.group(2), indent=match.group(1)) ) elif match := re.match( r"^(\s*)(?='|\")(.*)", statement, flags=re.MULTILINE | re.DOTALL ): # docstrings parsed.append( - DocStringConverter(docstring=match.group(2), indent=match.group(1)) + DocStringStatement(docstring=match.group(2), indent=match.group(1)) ) elif ImportStatement.matches(statement): parsed.extend( @@ -619,11 +620,11 @@ def _parse_statements(self, func_body: str) -> ty.Tuple[ indent = match.group(1) varname = match.group(2) args = extract_args(statement)[1] - node_kwargs = match_kwargs(args, NodeConverter.SIGNATURE) + node_kwargs = match_kwargs(args, AddNodeStatement.SIGNATURE) intf_name, intf_args, intf_post = extract_args(node_kwargs["interface"]) if "iterables" in node_kwargs: iterables = [ - IterableConverter(*extract_args(a)[1]) + IterableStatement(*extract_args(a)[1]) for a in extract_args(node_kwargs["iterables"])[1] ] else: @@ -646,7 +647,7 @@ def _parse_statements(self, func_body: str) -> ty.Tuple[ if (i.module_name == imported_name or imported_name in i) ) except StopIteration: - converter_cls = NodeConverter + converter_cls = AddNodeStatement else: if ( import_stmt.module_name == imported_name @@ -659,7 +660,7 @@ def _parse_statements(self, func_body: str) -> ty.Tuple[ # class_name, NodeConverter # ) else: - converter_cls = NodeConverter + converter_cls = AddNodeStatement node_converter = converter_cls( name=varname, interface=intf_name, @@ -681,7 +682,7 @@ def _parse_statements(self, func_body: str) -> ty.Tuple[ flags=re.MULTILINE, ): indent, varname, wf_name = match.groups() - nested_workflow_converter = NestedWorkflowConverter( + nested_workflow_converter = AddNestedWorkflowStatement( name=varname, workflow_name=wf_name, nested_spec=self.nested_workflows.get(wf_name), @@ -719,7 +720,7 @@ def _parse_statements(self, func_body: str) -> ty.Tuple[ pre, args, post = extract_args(out) if args is not None: out = DynamicField(*args) - conn_converter = ConnectionConverter( + conn_converter = ConnectionStatement( source_name=src, target_name=tgt, source_out=out, @@ -735,7 +736,7 @@ def _parse_statements(self, func_body: str) -> ty.Tuple[ tgt_node.in_conns.append(conn_converter) elif match := re.match(r"(\s*)return (.*)", statement): parsed.append( - ReturnConverter(vars=match.group(2), indent=match.group(1)) + ReturnStatement(vars=match.group(2), indent=match.group(1)) ) elif match := ( re.match( @@ -749,11 +750,11 @@ def _parse_statements(self, func_body: str) -> ty.Tuple[ indent, node_name, attribute, value = match.groups() nodes = self.nodes[node_name] assert all(n.name == nodes[0].name for n in nodes) - if isinstance(nodes[0], NestedWorkflowConverter): - assert all(isinstance(n, NestedWorkflowConverter) for n in nodes) - klass = NestedWorkflowAssignmentConverter + if isinstance(nodes[0], AddNestedWorkflowStatement): + assert all(isinstance(n, AddNestedWorkflowStatement) for n in nodes) + klass = NestedWorkflowAssignmentStatement else: - klass = NodeAssignmentConverter + klass = NodeAssignmentStatement parsed.append( klass( nodes=nodes, @@ -832,7 +833,7 @@ def default_spec( if hlp: yaml_str = re.sub( r"^(" + k + r"):", - "# " + hlp + r"\n\1:", + multiline_comment(hlp) + r"\1:", yaml_str, flags=re.MULTILINE, ) diff --git a/nipype2pydra/workflow/__init__.py b/nipype2pydra/workflow/__init__.py deleted file mode 100644 index 792709f5..00000000 --- a/nipype2pydra/workflow/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .base import WorkflowConverter # noqa: F401