Skip to content

Commit a85bb14

Browse files
authored
Merge pull request #632 from ghisvail/fix/specs/staticmethod-as-callable
FIX: Allow staticmethod be passed to callable metadata in ouput spec
2 parents 72f5022 + 46a6e9a commit a85bb14

File tree

2 files changed

+36
-2
lines changed

2 files changed

+36
-2
lines changed

pydra/engine/specs.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,12 @@ def _field_metadata(
602602
return attr.NOTHING
603603
return val
604604
elif "callable" in fld.metadata:
605-
call_args = inspect.getfullargspec(fld.metadata["callable"])
605+
callable_ = fld.metadata["callable"]
606+
if isinstance(callable_, staticmethod):
607+
# In case callable is defined as a static method,
608+
# retrieve the function wrapped in the descriptor.
609+
callable_ = callable_.__func__
610+
call_args = inspect.getfullargspec(callable_)
606611
call_args_val = {}
607612
for argnm in call_args.args:
608613
if argnm == "field":
@@ -624,7 +629,7 @@ def _field_metadata(
624629
f"has to be in inputs or be field or output_dir, "
625630
f"but {argnm} is used"
626631
)
627-
return fld.metadata["callable"](**call_args_val)
632+
return callable_(**call_args_val)
628633
else:
629634
raise Exception("(_field_metadata) is not a current valid metadata key.")
630635

pydra/engine/tests/test_shelltask.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2928,6 +2928,35 @@ def gather_output(executable, output_dir, ble):
29282928
shelly()
29292929

29302930

2931+
@pytest.mark.parametrize("results_function", [result_no_submitter, result_submitter])
2932+
def test_shell_cmd_outputspec_5c(plugin, results_function):
2933+
"""
2934+
Customised output spec defined as a class,
2935+
using a static function to collect output files.
2936+
"""
2937+
2938+
@attr.s(kw_only=True)
2939+
class MyOutputSpec(ShellOutSpec):
2940+
@staticmethod
2941+
def gather_output(executable, output_dir):
2942+
files = executable[1:]
2943+
return [Path(output_dir) / file for file in files]
2944+
2945+
newfile: MultiOutputFile = attr.ib(metadata={"callable": gather_output})
2946+
2947+
shelly = ShellCommandTask(
2948+
name="shelly",
2949+
executable=["touch", "newfile_tmp1.txt", "newfile_tmp2.txt"],
2950+
output_spec=SpecInfo(name="Output", bases=(MyOutputSpec,)),
2951+
)
2952+
2953+
res = results_function(shelly, plugin)
2954+
assert res.output.stdout == ""
2955+
# newfile is a list
2956+
assert len(res.output.newfile) == 2
2957+
assert all([file.exists for file in res.output.newfile])
2958+
2959+
29312960
@pytest.mark.parametrize("results_function", [result_no_submitter, result_submitter])
29322961
def test_shell_cmd_outputspec_6(plugin, results_function, tmpdir):
29332962
"""

0 commit comments

Comments
 (0)