forked from Netflix/metaflow
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
102 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
# Skip decorator is a workaround solution to implement conditional branching in metaflow. | ||
# When condition variable is_skipping is evaluated to True, | ||
# it will skip current step and execute the supplied next step. | ||
|
||
from functools import wraps | ||
from metaflow.decorators import StepDecorator | ||
|
||
|
||
class SkipDecorator(StepDecorator): | ||
""" | ||
The @skip decorator is a workaround for conditional branching. The @skip decorator checks an artifact | ||
and if it is false, skips the evaluation of the step function and jumps to the supplied next step. | ||
**The `start` and `end` steps are always expected and should not be skipped.** | ||
Usage: | ||
class SkipFlow(FlowSpec): | ||
condition = Parameter("condition", default=False) | ||
@step | ||
def start(self): | ||
print("Should skip:", self.condition) | ||
self.next(self.middle) | ||
@skip(check='condition', next='end') | ||
@step | ||
def middle(self): | ||
print("Running the middle step - not skipping") | ||
self.next(self.end) | ||
@step | ||
def end(self): | ||
pass | ||
""" | ||
|
||
name = "skip" | ||
|
||
def __init__(self, check="", next=""): | ||
super().__init__() | ||
self.check = check | ||
self.next = next | ||
|
||
def __call__(self, f): | ||
@wraps(f) | ||
def func(step): | ||
if getattr(step, self.check): | ||
step.next(getattr(step, self.next)) | ||
else: | ||
return f(step) | ||
|
||
return func |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
from metaflow import Parameter, FlowSpec, step, skip | ||
|
||
|
||
class SkipFlow(FlowSpec): | ||
|
||
condition_true = Parameter("condition-true", default=True) | ||
|
||
@step | ||
def start(self): | ||
print("Should skip:", self.condition) | ||
self.desired_step_executed = False | ||
self.condition_false = False | ||
self.next(self.skipped_step) | ||
|
||
@skip(check="condition_true", next="desired_step") | ||
@step | ||
def skipped_step(self): | ||
raise Exception( | ||
"Unexpectedly ran the skipped_step step. This step should have been skipped." | ||
) | ||
self.next(self.unreachable) | ||
|
||
def unreachable(self): | ||
raise Exception( | ||
"Unexpectedly ran the unreachable step. This step should have been skipped." | ||
) | ||
self.next(self.end) | ||
|
||
@skip(check="condition_false", next="end") | ||
@step | ||
def desired_step(self): | ||
self.desired_step_executed = True | ||
self.next(self.end) | ||
|
||
@step | ||
def end(self): | ||
assert self.desired_step_executed, "Desired step was not executed" | ||
|
||
|
||
if __name__ == "__main__": | ||
SkipFlow() |