Skip to content

Commit 53e8b9a

Browse files
Merge branch 'main' of github.com:fair-workflows/fairworkflows into fix-bug-is-fairworkflows-decorator
Conflicts: fairworkflows/fairworkflow.py
2 parents abec9a6 + 068f755 commit 53e8b9a

2 files changed

Lines changed: 41 additions & 3 deletions

File tree

fairworkflows/fairworkflow.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -541,10 +541,8 @@ def _modify_function(func):
541541
num_params = len(inspect.signature(func).parameters)
542542
empty_args = ([inspect.Parameter.empty()] * num_params)
543543
workflow_level_promise = scheduled_workflow(*empty_args)
544+
_validate_decorated_function(func, empty_args)
544545
step_level_promise = func(*empty_args)
545-
if not isinstance(step_level_promise, PromisedObject):
546-
raise TypeError("The workflow does not return a 'promise'. Did you use the "
547-
"is_fairstep decorator on all the steps?")
548546

549547
# Description of workflow is the raw function code
550548
description = inspect.getsource(func)
@@ -553,3 +551,22 @@ def _modify_function(func):
553551
is_pplan_plan=is_pplan_plan, derived_from=None)
554552
return workflow_level_promise
555553
return _modify_function
554+
555+
556+
def _validate_decorated_function(func, empty_args):
557+
"""
558+
Validate that a function decorated with is_fairworkflow actually consists of steps that are
559+
decorated with is_fairstep. Call the function using empty arguments to test. NB: This won't
560+
catch all edgecases of users misusing the is_fairworkflow decorator, but at least will
561+
provide more useful error messages in frequently occurring cases.
562+
"""
563+
try:
564+
result = func(*empty_args)
565+
except TypeError as e:
566+
raise TypeError("Marking the function as workflow with `is_fairworkflow` decorator "
567+
"failed. "
568+
"Did you use the is_fairstep decorator on all the steps? "
569+
f"Detailed error message: {e}")
570+
if not isinstance(result, PromisedObject):
571+
raise TypeError("The workflow does not return a 'promise'. Did you use the "
572+
"is_fairstep decorator on all the steps?")

tests/test_fairworkflow.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,3 +396,24 @@ def my_workflow(in1):
396396
"""
397397
return return_value(in1)
398398
assert "The workflow does not return a 'promise'" in str(e.value)
399+
400+
def test_workflow_mixed_decorated_steps(self):
401+
def add(a: float, b: float) -> float:
402+
"""Adding up numbers. NB: no is_fairstep decorator!"""
403+
return a + b
404+
405+
@is_fairstep(label='Subtraction')
406+
def sub(a: float, b: float) -> float:
407+
"""Subtracting numbers."""
408+
return a - b
409+
410+
with pytest.raises(TypeError) as e:
411+
@is_fairworkflow(label='My Workflow')
412+
def my_workflow(in1, in2):
413+
"""
414+
A simple addition, subtraction workflow
415+
"""
416+
return add(in1, sub(in2, in2))
417+
assert ("Marking the function as workflow with `is_fairworkflow` decorator failed. "
418+
in str(e.value))
419+
assert "unsupported operand type(s)" in str(e.value)

0 commit comments

Comments
 (0)