@@ -26,6 +26,7 @@ class TaskConverter:
26
26
doctest : dict = attrs .field (factory = dict )
27
27
tests_inputs : list = attrs .field (factory = list )
28
28
tests_outputs : list = attrs .field (factory = list )
29
+ output_module : str = attrs .field (default = None )
29
30
callables_module : ModuleType = attrs .field (
30
31
converter = import_module_from_path , default = None
31
32
)
@@ -35,6 +36,18 @@ def output_callables_validator(self, _, output_callables: dict):
35
36
if not output_callables .keys ().isdisjoint (self .output_templates .keys ()):
36
37
raise Exception ("output_callables and output_templates have the same keys" )
37
38
39
+ def __attrs_post_init__ (self ):
40
+ if self .output_module is None :
41
+ if self .nipype_module .__name__ .startswith ("nipype.interfaces." ):
42
+ self .output_module = self .nipype_module .__name__ [len ("nipype.interfaces." ):]
43
+ else :
44
+ raise RuntimeError (
45
+ "Output-module needs to be explicitly provided to task converter "
46
+ "when converting Nipype interefaces in non standard locations such "
47
+ f"as { self .nipype_module .__name__ } .{ self .task_name } (i.e. not in "
48
+ "nipype.interfaces)"
49
+ )
50
+
38
51
@property
39
52
def nipype_interface (self ) -> nipype .interfaces .base .BaseInterface :
40
53
return getattr (self .nipype_module , self .task_name )
@@ -47,20 +60,21 @@ def nipype_input_spec(self) -> nipype.interfaces.base.BaseInterfaceInputSpec:
47
60
def nipype_output_spec (self ) -> nipype .interfaces .base .BaseTraitedSpec :
48
61
return self .nipype_interface .output_spec ()
49
62
50
- def generate (self , output_file : Path ):
63
+ def generate (self , package_root : Path ):
51
64
"""creating pydra input/output spec from nipype specs
52
65
if write is True, a pydra Task class will be written to the file together with tests
53
66
"""
54
67
input_fields , inp_templates = self .convert_input_fields ()
55
68
output_fields = self .convert_output_spec (fields_from_template = inp_templates )
56
69
57
- testdir = output_file .parent / "tests"
58
- testdir .mkdir ()
59
- filename_test = testdir / f"test_spec_{ output_file .name } "
60
- filename_test_run = testdir / f"test_run_{ output_file .name } "
61
-
70
+ module_path = (Path (package_root ) / "pydra" / "tasks" ).joinpath (self .output_module .split ("." ))
71
+ output_file = (module_path / self .task_name .lower ()).with_suffix (".py" )
62
72
self .write_task (output_file , input_fields , output_fields )
63
73
74
+ testdir = module_path / "tests"
75
+ testdir .mkdir ()
76
+ filename_test = testdir / f"test_spec_{ self .task_name .lower ()} "
77
+ filename_test_run = testdir / f"test_run_{ self .task_name .lower ()} "
64
78
self .write_test (filename_test = filename_test )
65
79
self .write_test (filename_test = filename_test_run , run = True )
66
80
@@ -131,7 +145,7 @@ def pydra_fld_input(self, field, nm):
131
145
tp_pdr = str
132
146
elif nm not in self .output_callables :
133
147
raise Exception (
134
- f"the filed { nm } has genfile=True, but no output template or callables provided"
148
+ f"the filed { nm } has genfile=True, but no output template or callables_module provided"
135
149
)
136
150
137
151
metadata_pdr .update (metadata_extra_spec )
@@ -346,12 +360,12 @@ def write_test(self, filename_test, run=False):
346
360
347
361
spec_str = "import os, pytest \n from pathlib import Path\n "
348
362
spec_str += (
349
- f"from . .{ self .task_name .lower ()} import { self .task_name } \n \n "
363
+ f"from pydra.tasks. { self . output_module } .{ self .task_name .lower ()} import { self .task_name } \n \n "
350
364
)
351
365
if run :
352
366
pass
353
367
spec_str += f"@pytest.mark.parametrize('inputs, outputs', { tests_inp_outp } )\n "
354
- spec_str += f"def test_{ self .task_name } (test_data, inputs, outputs):\n "
368
+ spec_str += f"def test_{ self .task_name . lower () } (test_data, inputs, outputs):\n "
355
369
spec_str += " in_file = Path(test_data) / 'test.nii.gz'\n "
356
370
spec_str += " if inputs is None: inputs = {{}}\n "
357
371
spec_str += " for key, val in inputs.items():\n "
0 commit comments