Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sanitize decorators and callable parameters on entrypoint load #15932

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

soamicharan
Copy link
Contributor

@soamicharan soamicharan commented Nov 6, 2024

During prefect deploy command execution, if python environment is not setup prefect load entrypoint using code parsing by ast module.
Now this is done by _sanitize_and_load_flow function which tries to sanitize code definition and try to load the flow.
Now in flow decorator, if it used any other decorator or uses callback hooks on_completion, on_running etc. then it will throw ScriptError.
So in this PR, try to sanitize the decorators and keywords used in flow decorator to try to load flow.

Checklist

  • This pull request references any related issue by including "closes <link to issue>"
  • If this pull request adds new functionality, it includes unit tests that cover the changes
  • If this pull request removes docs files, it includes redirect settings in mint.json.
  • If this pull request adds functions or classes, it includes helpful docstrings.

Copy link

codspeed-hq bot commented Nov 6, 2024

CodSpeed Performance Report

Merging #15932 will not alter performance

Comparing soamicharan:enchance-safe-entrypoint-load (8fc7d81) with main (575a1f6)

Summary

✅ 3 untouched benchmarks

@desertaxle
Copy link
Member

Thanks for the PR @soamicharan! Could you please open an GitHub issue with an MRE describing the bug you're fixing here? That will be very helpful for me to understand the issue and help me make sure that the solution fits in well with the surrounding code.

@soamicharan
Copy link
Contributor Author

Thanks for suggestion
#15942
@desertaxle linked the Issue

@soamicharan
Copy link
Contributor Author

@desertaxle @zzstoatzz Please review and merge the MR

@zzstoatzz
Copy link
Collaborator

zzstoatzz commented Nov 18, 2024

@desertaxle @zzstoatzz Please review and merge the MR

hi @soamicharan - there are still tests failing here which we'll need to fix

@github-actions github-actions bot added the bug Something isn't working label Nov 19, 2024
Copy link
Member

@desertaxle desertaxle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a couple of comments in addition to the test failures that @zzstoatzz pointed out. Let us know if you have any questions!

Comment on lines +2119 to +2159
# Remove flow decorator callback hooks

def get_decorator_function_name(func_decorator):
"""Retrieve decorator function name."""
func_decorator = (
func_decorator.func
if isinstance(func_decorator, ast.Call)
else func_decorator
)
return (
func_decorator.attr
if isinstance(func_decorator, ast.Attribute)
else func_decorator.id
)

if func_def.decorator_list:
# Keep only prefect flow decorator only
func_def.decorator_list = [
func_decorator
for func_decorator in func_def.decorator_list
if get_decorator_function_name(func_decorator) == "flow"
]
exclude_keyword_args = (
"on_failure",
"on_completion",
"on_cancellation",
"on_crashed",
"on_running",
)

# Exclude callable type keyword arguments from flow decorator
for func_decorator in func_def.decorator_list:
if not hasattr(func_decorator, "keywords"):
continue

func_decorator.keywords = list(
filter(
lambda keyword_arg: keyword_arg.arg not in exclude_keyword_args,
func_decorator.keywords,
)
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer if this code were encapsulated in a function for readability. Also, the decorator_list is looped over twice, and the code could be condensed to a single loop instead of filtering out all non-flow decorators first.

entrypoint = f"{tmp_path.joinpath('flow.py')}:flow_function"

result = safe_load_flow_from_entrypoint(entrypoint)
assert result is not None
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add an additional check validating the flow was loaded as expected? You should be able to call the flow and check the return value is (None, None) since the defaults are removed when loading.

Copy link
Contributor

github-actions bot commented Dec 3, 2024

This pull request is stale because it has been open 14 days with no activity. To keep this pull request open remove stale label or comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working status:stale
Projects
None yet
Development

Successfully merging this pull request may close these issues.

prefect deploy script loading with complex callback hooks raising ScriptErrors
3 participants