Skip to content

Support staticmethod and classmethod flow entrypoints #17892

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

Closed
vyagubov opened this issue Apr 23, 2025 · 5 comments · Fixed by #17976
Closed

Support staticmethod and classmethod flow entrypoints #17892

vyagubov opened this issue Apr 23, 2025 · 5 comments · Fixed by #17976
Labels
enhancement An improvement of an existing feature

Comments

@vyagubov
Copy link
Contributor

Bug summary

I'm using Prefect with static methods defined inside classes and deploying with source code from GitLab using an explicit entrypoint.

My flow is defined like this:

class ClassName:

    @staticmethod
    @flow
    def run() -> None:
        ...

I try to use:

entrypoint = "path/flow.py:ClassName.run"

However, Prefect raises an error saying it couldn't find the flow.

Expected Behavior:

Since @flow supports @staticmethod based on the source code here:

if isinstance(fn, staticmethod):

I expect that specifying ClassName.run in the entrypoint should work.

Root Cause:
In the same file, later in the Flow class, the entrypoint is hardcoded as:

self._entrypoint = f"{module}:{fn.__name__}"

This ignores the class context (ClassName) and causes the flow to be inaccessible via the expected entrypoint path.

Current Workaround:
To make this work, I need to add a top-level alias:

class ClassName:

    @staticmethod
    @flow
    def run() -> None:
        ...

run = ClassName.run  # workaround for entrypoint to resolve

# entrypoint = "path/flow.py:run"

Suggested Fix:

Respect the class context in the entrypoint, or allow users to specify ClassName.run explicitly and resolve it correctly during loading.

Version info

the last version of Prefect which is available in github.

Additional context

No response

@vyagubov vyagubov added the bug Something isn't working label Apr 23, 2025
@desertaxle desertaxle added enhancement An improvement of an existing feature and removed bug Something isn't working labels Apr 24, 2025
@desertaxle desertaxle changed the title Staticmethod flow entrypoints from class not supported(classmethod too) Support staticmethod and classmethod flow entrypoints Apr 24, 2025
@desertaxle
Copy link
Member

Thanks for opening this, @vyagubov! Adding support for @staticmethod and @classmethod flow entrypoints seems doable. The bulk of the changes should be in load_flow_from_entrypoint and safe_load_flow_from_entrypoint in src/prefect/flows.py.

Are you up for giving it a shot? I'm happy to help if you run into any issues.

@vyagubov
Copy link
Contributor Author

I will give it a try. Expect PR on Tuesday (on Monday I am on vacation).

@vyagubov
Copy link
Contributor Author

For load_flow_from_entrypoint it was straightforward — I only needed to adjust import_object, and it already works in my Orchestrator project:
vyagubov@0e74a48 (I will also add some tests later).

However, for safe_load_flow_from_entrypoint it's more complicated.
I had to extend _entrypoint_definition_and_source to support ast.ClassDef.
In the case of a class, I also need to pass ClassName.method_name, not just ClassName, back to the caller.
Currently, I'm doing it via func_def.name = object_path, but it feels like a hack:
vyagubov@7e84285

I see a few options:

  • Do not change safe_load_flow_from_entrypoint for now, since it is just a fallback inside load_flow_from_entrypoint.
  • Keep the workaround with func_def.name = object_path.
  • Refactor _entrypoint_definition_and_source to return an additional value like Tuple[Union[ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef], str, List[str]], and update is_entrypoint_async and load_flow_arguments_from_entrypoint accordingly.

@desertaxle
What would you suggest?
Personally, I lean toward the third option (adding a separate return value) — it feels cleaner and would avoid hacks inside AST nodes. However, it would require a broader refactor (affecting safe_load_flow_from_entrypoint, is_entrypoint_async, and load_flow_arguments_from_entrypoint), and initially I planned to avoid large refactoring here.

@desertaxle
Copy link
Member

Cool! I think you're approach in 3 sounds good and it wouldn't be too big of a change since we have some unused functions. load_from_arguments_from_entrypoint and is_entrypoint_async aren't used anywhere except in load_placeholder_flow, which isn't used at all, so I don't think they need to be updated.

@vyagubov
Copy link
Contributor Author

vyagubov commented May 4, 2025

Hi @desertaxle! This is ready for review — any feedback is welcome and much appreciated.

⚠️ Note: The CI job failed due to a 403 Not authenticated error when trying to access Prefect Cloud. I believe this is because secrets like PREFECT_API_KEY aren’t available in GitHub Actions when run from forks. Just flagging in case this needs a manual rerun or adjustment in CI config.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement An improvement of an existing feature
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants