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

More friendly output of the airflow plugins command + add timetables #19298

Merged
merged 1 commit into from Oct 30, 2021

Conversation

mik-laj
Copy link
Member

@mik-laj mik-laj commented Oct 29, 2021

I suggest introducing a few improvements to this command, as this command does not always do the job:

  • The flask blueprints field contains information about the name and the imported name to distinguish between different objects.
  • Full import paths for classes are shown to easily identify the class. In particular, I want the executor field to show the full name so that it can be easily set in the configuration file.
  • The method output is deterministic, so it's easier to use. Users don't care about object memory addresses.

Before:

$ AIRFLOW__CORE__PLUGINS_FOLDER=$PWD/tests/plugins airflow plugins --output=json | jq .
[
  {
    "name": "test_plugin",
    "appbuilder_views": [
      {
        "name": "Test View",
        "category": "Test Plugin",
        "view": "<test_plugin.PluginTestAppBuilderBaseView object at 0x7fe21ed57860>"
      }
    ],
    "flask_blueprints": [
      "<flask.blueprints.Blueprint object at 0x7fe21ed57898>"
    ],
    "appbuilder_menu_items": [
      {
        "name": "Google",
        "href": "https://www.google.com",
        "category": "Search"
      },
      {
        "name": "apache",
        "href": "https://www.apache.org/",
        "label": "The Apache Software Foundation"
      }
    ],
    "executors": [
      "PluginExecutor"
    ],
    "hooks": [
      "PluginHook"
    ],
    "macros": [
      "<function plugin_macro at 0x7fe248a88400>"
    ],
    "operator_extra_links": [
      "GoogleLink()",
      "AirflowLink2()",
      "CustomOpLink()",
      "CustomBaseIndexOpLink(index=1)"
    ],
    "source": "$PLUGINS_FOLDER/test_plugin.py",
    "global_operator_extra_links": [
      "AirflowLink()",
      "GithubLink()"
    ]
  },
  {
    "name": "plugin-a",
    "appbuilder_views": [],
    "flask_blueprints": [],
    "appbuilder_menu_items": [],
    "executors": [],
    "hooks": [],
    "macros": [],
    "operator_extra_links": [],
    "source": "$PLUGINS_FOLDER/test_plugin.py",
    "global_operator_extra_links": []
  },
  {
    "name": "plugin-b",
    "appbuilder_views": [],
    "flask_blueprints": [],
    "appbuilder_menu_items": [],
    "executors": [],
    "hooks": [],
    "macros": [],
    "operator_extra_links": [],
    "source": "$PLUGINS_FOLDER/test_plugin.py",
    "global_operator_extra_links": []
  },
  {
    "name": "plugin-c",
    "appbuilder_views": [],
    "flask_blueprints": [],
    "appbuilder_menu_items": [],
    "executors": [],
    "hooks": [],
    "macros": [],
    "operator_extra_links": [],
    "source": "$PLUGINS_FOLDER/test_plugin.py",
    "global_operator_extra_links": []
  },
  {
    "name": "postload",
    "appbuilder_views": [],
    "flask_blueprints": [],
    "appbuilder_menu_items": [],
    "executors": [],
    "hooks": [],
    "macros": [],
    "operator_extra_links": [],
    "source": "$PLUGINS_FOLDER/test_plugin.py",
    "global_operator_extra_links": []
  }
]

After:

$ AIRFLOW__CORE__PLUGINS_FOLDER=$PWD/tests/plugins airflow plugins --output=json | jq .
[
  {
    "name": "test_plugin",
    "source": "$PLUGINS_FOLDER/test_plugin.py",
    "flask_blueprints": [
      "<flask.blueprints.Blueprint: name='test_plugin' import_name='test_plugin'>"
    ],
    "appbuilder_menu_items": [
      {
        "name": "Google",
        "href": "https://www.google.com",
        "category": "Search"
      },
      {
        "name": "apache",
        "href": "https://www.apache.org/",
        "label": "The Apache Software Foundation"
      }
    ],
    "operator_extra_links": [
      "<tests.test_utils.mock_operators.GoogleLink>",
      "<tests.test_utils.mock_operators.AirflowLink2>",
      "<tests.test_utils.mock_operators.CustomOpLink>",
      "<tests.test_utils.mock_operators.CustomBaseIndexOpLink>"
    ],
    "macros": [
      "test_plugin.plugin_macro"
    ],
    "hooks": [
      "test_plugin.PluginHook"
    ],
    "global_operator_extra_links": [
      "<tests.test_utils.mock_operators.AirflowLink>",
      "<tests.test_utils.mock_operators.GithubLink>"
    ],
    "appbuilder_views": [
      {
        "name": "Test View",
        "category": "Test Plugin",
        "view": "test_plugin.PluginTestAppBuilderBaseView"
      }
    ],
    "executors": [
      "test_plugin.PluginExecutor"
    ],
    "timetables": [
      "test_plugin.CustomCronDataIntervalTimetable"
    ]
  },
  {
    "name": "plugin-a",
    "source": "$PLUGINS_FOLDER/test_plugin.py",
    "flask_blueprints": [],
    "appbuilder_menu_items": [],
    "operator_extra_links": [],
    "macros": [],
    "hooks": [],
    "global_operator_extra_links": [],
    "appbuilder_views": [],
    "executors": [],
    "timetables": []
  },
  {
    "name": "plugin-b",
    "source": "$PLUGINS_FOLDER/test_plugin.py",
    "flask_blueprints": [],
    "appbuilder_menu_items": [],
    "operator_extra_links": [],
    "macros": [],
    "hooks": [],
    "global_operator_extra_links": [],
    "appbuilder_views": [],
    "executors": [],
    "timetables": []
  },
  {
    "name": "plugin-c",
    "source": "$PLUGINS_FOLDER/test_plugin.py",
    "flask_blueprints": [],
    "appbuilder_menu_items": [],
    "operator_extra_links": [],
    "macros": [],
    "hooks": [],
    "global_operator_extra_links": [],
    "appbuilder_views": [],
    "executors": [],
    "timetables": []
  },
  {
    "name": "postload",
    "source": "$PLUGINS_FOLDER/test_plugin.py",
    "flask_blueprints": [],
    "appbuilder_menu_items": [],
    "operator_extra_links": [],
    "macros": [],
    "hooks": [],
    "global_operator_extra_links": [],
    "appbuilder_views": [],
    "executors": [],
    "timetables": []
  }
]

^ Add meaningful description above

Read the Pull Request Guidelines for more information.
In case of fundamental code change, Airflow Improvement Proposal (AIP) is needed.
In case of a new dependency, check compliance with the ASF 3rd Party License Policy.
In case of backwards incompatible changes please leave a note in UPDATING.md.

@uranusjr
Copy link
Member

Very nice! What's significant about the angle brackets?

@mik-laj
Copy link
Member Author

mik-laj commented Oct 29, 2021

@uranusjr This is an object, not a class. I tried to follow the official Python convention: https://docs.python.org/3/reference/datamodel.html?highlight=__repr__#object.__repr__ .

@uranusjr
Copy link
Member

Ah OK, thanks for the explaination. Maybe it'd be clearer to say something like

<tests.test_utils.mock_operators.GithubLink object>

instead? This would be closer to the built-in repr format as well

>>> class Foo:
...  pass
...
>>> Foo()
<__main__.Foo object at 0x7f2dc444efa0>

@mik-laj
Copy link
Member Author

mik-laj commented Oct 29, 2021

@uranusjr Done

@github-actions github-actions bot added the full tests needed We need to run full set of tests for this PR to merge label Oct 29, 2021
@github-actions
Copy link

The PR most likely needs to run full matrix of tests because it modifies parts of the core of Airflow. However, committers might decide to merge it quickly and take the risk. If they don't merge it quickly - please rebase it to the latest main at your convenience, or amend the last commit of the PR, and push it with --force-with-lease.

@mik-laj mik-laj merged commit b8131d5 into apache:main Oct 30, 2021
@ephraimbuddy ephraimbuddy added the type:improvement Changelog: Improvements label Apr 11, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:CLI area:plugins full tests needed We need to run full set of tests for this PR to merge type:improvement Changelog: Improvements
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants