This is an automated email from the ASF dual-hosted git repository.

ephraimanierobi pushed a commit to branch v2-7-test
in repository https://gitbox.apache.org/repos/asf/airflow.git

commit a5df4a8b20f9467d2bf4b3ffa643e3fd150c48fc
Author: Jakub Dardzinski <kuba0...@gmail.com>
AuthorDate: Wed Oct 18 21:42:39 2023 +0200

    Fix `get_plugin_info` for class based listeners. (#35022)
    
    Signed-off-by: Jakub Dardzinski <kuba0...@gmail.com>
    (cherry picked from commit a74ec408e6fe1a2ae92df4f3669cdb089f837f0d)
---
 airflow/plugins_manager.py                 |  6 ++++--
 tests/cli/commands/test_plugins_command.py |  5 ++++-
 tests/plugins/test_plugin.py               |  3 ++-
 tests/plugins/test_plugins_manager.py      | 10 +++++++++-
 4 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/airflow/plugins_manager.py b/airflow/plugins_manager.py
index beab0f3b07..7275588d52 100644
--- a/airflow/plugins_manager.py
+++ b/airflow/plugins_manager.py
@@ -557,8 +557,10 @@ def get_plugin_info(attrs_to_dump: Iterable[str] | None = 
None) -> list[dict[str
                 elif attr in ("macros", "timetables", "hooks", "executors"):
                     info[attr] = [qualname(d) for d in getattr(plugin, attr)]
                 elif attr == "listeners":
-                    # listeners are always modules
-                    info[attr] = [d.__name__ for d in getattr(plugin, attr)]
+                    # listeners may be modules or class instances
+                    info[attr] = [
+                        d.__name__ if inspect.ismodule(d) else qualname(d) for 
d in getattr(plugin, attr)
+                    ]
                 elif attr == "appbuilder_views":
                     info[attr] = [
                         {**d, "view": qualname(d["view"].__class__) if "view" 
in d else None}
diff --git a/tests/cli/commands/test_plugins_command.py 
b/tests/cli/commands/test_plugins_command.py
index 4dcdfcdbf5..1c0e6d4d4c 100644
--- a/tests/cli/commands/test_plugins_command.py
+++ b/tests/cli/commands/test_plugins_command.py
@@ -85,7 +85,10 @@ class TestPluginsCommand:
                     "<tests.test_utils.mock_operators.CustomBaseIndexOpLink 
object>",
                 ],
                 "hooks": ["tests.plugins.test_plugin.PluginHook"],
-                "listeners": ["tests.listeners.empty_listener"],
+                "listeners": [
+                    "tests.listeners.empty_listener",
+                    "tests.listeners.class_listener.ClassBasedListener",
+                ],
                 "source": None,
                 "appbuilder_menu_items": [
                     {"name": "Google", "href": "https://www.google.com";, 
"category": "Search"},
diff --git a/tests/plugins/test_plugin.py b/tests/plugins/test_plugin.py
index 6648215f31..e207fd12da 100644
--- a/tests/plugins/test_plugin.py
+++ b/tests/plugins/test_plugin.py
@@ -32,6 +32,7 @@ from airflow.sensors.base import BaseSensorOperator
 from airflow.ti_deps.deps.base_ti_dep import BaseTIDep
 from airflow.timetables.interval import CronDataIntervalTimetable
 from tests.listeners import empty_listener
+from tests.listeners.class_listener import ClassBasedListener
 from tests.test_utils.mock_operators import (
     AirflowLink,
     AirflowLink2,
@@ -129,7 +130,7 @@ class AirflowTestPlugin(AirflowPlugin):
     ]
     operator_extra_links = [GoogleLink(), AirflowLink2(), CustomOpLink(), 
CustomBaseIndexOpLink(1)]
     timetables = [CustomCronDataIntervalTimetable]
-    listeners = [empty_listener]
+    listeners = [empty_listener, ClassBasedListener()]
     ti_deps = [CustomTestTriggerRule()]
 
 
diff --git a/tests/plugins/test_plugins_manager.py 
b/tests/plugins/test_plugins_manager.py
index bf74863407..8381c2ff64 100644
--- a/tests/plugins/test_plugins_manager.py
+++ b/tests/plugins/test_plugins_manager.py
@@ -18,6 +18,7 @@
 from __future__ import annotations
 
 import importlib
+import inspect
 import logging
 import os
 import sys
@@ -30,6 +31,7 @@ import pytest
 from airflow.hooks.base import BaseHook
 from airflow.listeners.listener import get_listener_manager
 from airflow.plugins_manager import AirflowPlugin
+from airflow.utils.module_loading import qualname
 from airflow.www import app as application
 from setup import AIRFLOW_SOURCES_ROOT
 from tests.test_utils.config import conf_vars
@@ -383,7 +385,13 @@ class TestPluginsManager:
             plugins_manager.integrate_listener_plugins(get_listener_manager())
 
             assert get_listener_manager().has_listeners
-            assert get_listener_manager().pm.get_plugins().pop().__name__ == 
"tests.listeners.empty_listener"
+            listeners = get_listener_manager().pm.get_plugins()
+            listener_names = [el.__name__ if inspect.ismodule(el) else 
qualname(el) for el in listeners]
+            # sort names as order of listeners is not guaranteed
+            assert [
+                "tests.listeners.class_listener.ClassBasedListener",
+                "tests.listeners.empty_listener",
+            ] == sorted(listener_names)
 
     def test_should_import_plugin_from_providers(self):
         from airflow import plugins_manager

Reply via email to