-
Notifications
You must be signed in to change notification settings - Fork 16.4k
[AIRFLOW-6128] Simplify plugins_manager and webserver plugin code #6696
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
Conversation
|
While working on adding more type annotations I've found more cyclic dependencies in Plugins manager. I managed to untangle them in this commit as a follow-up after the "executors" untangling. As result - we have much smaller airflow.init.py, and the dependencies are much more straightforward and not cyclic: rather than I also made most of the affected files pylint + mypy compliant. |
|
Yeh. I actually used type-hints and mypy to verify if my changes are correct (except running the airflow). It is super-helpful to be confident about your changes while commiting them. I am using pre-commit extensively to make sure I do not make mistakes. It's a big value of pylint/mypy/flake that I am using. I will split out typehint changes as the last step of review. Similarly as I do for #6596 . But this has to come as next steps. First I use mypy/pylint to get my changes verified in automated way and then I can split them out to make sure they are change/bisect friendly. |
27a8c79 to
8467268
Compare
|
@ashb-> separated out type adding to #6140. Now what we are left with is a change that internally splits-out plugins_manager and webserver initialisation to be easier to understand - includes type annotations and fix to the long-standing problem of TestView bleupring not working since 1.10.1 https://stackoverflow.com/questions/53701030/airflow-plugins-rbac-enabled-blueprint-not-working?answertab=active#tab-top |
48c1c7f to
7ef059f
Compare
2598055 to
8598720
Compare
Codecov Report
@@ Coverage Diff @@
## master #6696 +/- ##
=========================================
Coverage ? 83.93%
=========================================
Files ? 668
Lines ? 37747
Branches ? 0
=========================================
Hits ? 31683
Misses ? 6064
Partials ? 0
Continue to review full report at Codecov.
|
d400eb1 to
edd9730
Compare
edd9730 to
0eea374
Compare
While adding type annotations, it was apparent that the code for plugin manager and webserver initialisation was rather convoluted and complex. This change fixes it as follow up after untangling cyclic dependnencies. As a side effect - it turned out that the test plugin view in airflow RBAC implementation was not working since 1.10.1 - it threw "render is not an attribute" error - this has been fixed in this commit as well. The Plugins/TestView now works as expected. See https://stackoverflow.com/questions/53701030/airflow-plugins-rbac-enabled-blueprint-not-working?answertab=active#tab-top
0eea374 to
2b5839e
Compare
| if file_ext != '.py': | ||
| continue | ||
| def import_plugin(filepath: str, mod_name: str, root: str) -> None: | ||
| """Imports plugin module.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't you think a full documentation is needed here?
| log.error('Failed to import plugin %s', path) | ||
| import_errors[path] = str(e) | ||
| def try_to_import_plugin(filepath: str, root: str) -> None: | ||
| """Tries to import plugin from the file specified. Skips it if not a valid python file.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
|
|
||
| def find_airflow_plugins() -> None: | ||
| """Crawl through the plugins folder to find AirflowPlugin derivatives""" | ||
| assert settings.PLUGINS_FOLDER, "Plugins folder is not set" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought we did decide to not use assert for raising exceptions.
| def get_stat_name_handler() -> Optional[Callable[[str], str]]: | ||
| """Retrieves the single configured stats_handler (there can be only one!)""" | ||
| assert len(stat_name_handlers) in {0, 1}, \ | ||
| f'Specified more than one stat_name_handler ({stat_name_handlers}) which is not allowed.' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought we did decide to not use assert for raising exceptions.
Same here.
| 'Specified more than one stat_name_handler ({}) ' | ||
| 'is not allowed.'.format(stat_name_handlers)) | ||
| def get_stat_name_handler() -> Optional[Callable[[str], str]]: | ||
| """Retrieves the single configured stats_handler (there can be only one!)""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add the documentation for the return value, please?
|
|
||
| return app, appbuilder | ||
| def configure_app(app_name: str, config: Optional[Dict[str, Union[str, bool]]], testing: bool): | ||
| """Configure the application.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a description to the parameters.
|
|
||
| def root_app(env, resp): | ||
| def root_app(_, resp: Callable[[bytes, List[Tuple[str, str]]], None]): | ||
| """Root application function - returns 404 if the path is not found.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
| def cached_app(config: Optional[Dict[str, Union[str, bool]]] = None, | ||
| session: Optional[Session] = None, | ||
| testing: bool = False) -> Flask: | ||
| """Returns cached application if it's there. Creates it otherwise.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And here.
| global appbuilder | ||
| def cached_appbuilder(config: Optional[Dict[str, Union[str, bool]]] = None, testing=False) -> \ | ||
| AppBuilder: | ||
| """Returns cached appbuilder.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And here.
|
Thanks @feluelle ! I will come back to it soon-ish (or late-ish maybe) |
|
Same story - I think I will close that one. Ane refactoring/removals of cyclic dependencies etc. will be far easier when we move things outside of the airflow.init.py |
Make sure you have checked all steps below.
Jira
Description
While adding type annotations, it was apparent that the code for
plugin manager and webserver initialisation was rather convoluted
and complex. This change fixes it as follow up after untangling
cyclic dependnencies.
As a side effect - it turned out that the test plugin view
in airflow RBAC implementation was not working since 1.10.1 - it threw "render
is not an attribute" error - this has been fixed in this commit
as well. The Plugins/TestView now works as expected. See
https://stackoverflow.com/questions/53701030/airflow-plugins-rbac-enabled-blueprint-not-working?answertab=active#tab-top
Tests
Commits
Documentation