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

potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 2605912870 add CLI notification commands to providers (#33116)
2605912870 is described below

commit 260591287052a9d6fe37e323e4a3cdb7be818e76
Author: Albert Olweny <[email protected]>
AuthorDate: Sun Aug 6 18:01:56 2023 +0300

    add CLI notification commands to providers (#33116)
    
    
    
    ---------
    
    Co-authored-by: res <okirialbert>
---
 airflow/cli/cli_config.py                |  6 ++++++
 airflow/cli/commands/provider_command.py | 12 ++++++++++++
 airflow/providers_manager.py             | 28 ++++++++++++++++++++++++++++
 scripts/in_container/verify_providers.py | 15 +++++++++++++++
 tests/always/test_providers_manager.py   |  5 +++++
 5 files changed, 66 insertions(+)

diff --git a/airflow/cli/cli_config.py b/airflow/cli/cli_config.py
index 52ed700db7..7569e2ff58 100644
--- a/airflow/cli/cli_config.py
+++ b/airflow/cli/cli_config.py
@@ -1800,6 +1800,12 @@ PROVIDERS_COMMANDS = (
         
func=lazy_load_command("airflow.cli.commands.provider_command.executors_list"),
         args=(ARG_OUTPUT, ARG_VERBOSE),
     ),
+    ActionCommand(
+        name="notifications",
+        help="Get information about notifications provided",
+        
func=lazy_load_command("airflow.cli.commands.provider_command.notifications_list"),
+        args=(ARG_OUTPUT, ARG_VERBOSE),
+    ),
     ActionCommand(
         name="configs",
         help="Get information about provider configuration",
diff --git a/airflow/cli/commands/provider_command.py 
b/airflow/cli/commands/provider_command.py
index a55032d9f2..e3a57af781 100644
--- a/airflow/cli/commands/provider_command.py
+++ b/airflow/cli/commands/provider_command.py
@@ -101,6 +101,18 @@ def triggers_list(args):
     )
 
 
+@suppress_logs_and_warning
+@providers_configuration_loaded
+def notifications_list(args):
+    AirflowConsole().print_as(
+        data=ProvidersManager().notification,
+        output=args.output,
+        mapper=lambda x: {
+            "notification_class_name": x,
+        },
+    )
+
+
 @suppress_logs_and_warning
 @providers_configuration_loaded
 def connection_form_widget_list(args):
diff --git a/airflow/providers_manager.py b/airflow/providers_manager.py
index bba64e316e..0aa8ff170e 100644
--- a/airflow/providers_manager.py
+++ b/airflow/providers_manager.py
@@ -218,6 +218,13 @@ class TriggerInfo(NamedTuple):
     integration_name: str
 
 
+class NotificationInfo(NamedTuple):
+    """Notification class and provider it comes from."""
+
+    notification_class_name: str
+    package_name: str
+
+
 class PluginInfo(NamedTuple):
     """Plugin class, name and provider it comes from."""
 
@@ -426,6 +433,7 @@ class ProvidersManager(LoggingMixin, metaclass=Singleton):
         self._provider_configs: dict[str, dict[str, Any]] = {}
         self._api_auth_backend_module_names: set[str] = set()
         self._trigger_info_set: set[TriggerInfo] = set()
+        self._notification_info_set: set[NotificationInfo] = set()
         self._provider_schema_validator = 
_create_provider_info_schema_validator()
         self._customized_form_fields_schema_validator = (
             _create_customized_form_field_behaviours_schema_validator()
@@ -528,6 +536,12 @@ class ProvidersManager(LoggingMixin, metaclass=Singleton):
         """Lazy initialization of providers executors information."""
         self.initialize_providers_list()
         self._discover_executors()
+   
+    @provider_info_cache("notifications")
+    def initialize_providers_notifications(self):
+        """Lazy initialization of providers notifications information."""
+        self.initialize_providers_list()
+        self._discover_notifications()
 
     @provider_info_cache("config")
     def initialize_providers_configuration(self):
@@ -1025,6 +1039,14 @@ class ProvidersManager(LoggingMixin, 
metaclass=Singleton):
                 e,
             )
 
+    def _discover_notifications(self) -> None:
+        """Retrieves all notifications defined in the providers."""
+        for provider_package, provider in self._provider_dict.items():
+            if provider.data.get("notifications"):
+                for notification_class_name in provider.data["notifications"]:
+                    if _correctness_check(provider_package, 
notification_class_name, provider):
+                        
self._notification_info_set.add(notification_class_name)
+
     def _discover_extra_links(self) -> None:
         """Retrieves all extra links defined in the providers."""
         for provider_package, provider in self._provider_dict.items():
@@ -1101,6 +1123,12 @@ class ProvidersManager(LoggingMixin, 
metaclass=Singleton):
                         )
                     )
 
+    @property
+    def notification(self) -> list[NotificationInfo]:
+        """Returns information about available providers notifications 
class."""
+        self.initialize_providers_notifications()
+        return sorted(self._notification_info_set)
+
     @property
     def trigger(self) -> list[TriggerInfo]:
         """Returns information about available providers trigger class."""
diff --git a/scripts/in_container/verify_providers.py 
b/scripts/in_container/verify_providers.py
index 08193a62db..c332423f12 100755
--- a/scripts/in_container/verify_providers.py
+++ b/scripts/in_container/verify_providers.py
@@ -52,6 +52,7 @@ class EntityType(Enum):
     Hooks = "Hooks"
     Secrets = "Secrets"
     Trigger = "Trigger"
+    Notification = "Notification"
 
 
 class EntityTypeSummary(NamedTuple):
@@ -83,6 +84,7 @@ ENTITY_NAMES = {
     EntityType.Hooks: "Hooks",
     EntityType.Secrets: "Secrets",
     EntityType.Trigger: "Trigger",
+    EntityType.Notification: "Notification",
 }
 
 TOTALS: dict[EntityType, int] = {
@@ -92,6 +94,7 @@ TOTALS: dict[EntityType, int] = {
     EntityType.Transfers: 0,
     EntityType.Secrets: 0,
     EntityType.Trigger: 0,
+    EntityType.Notification: 0,
 }
 
 OPERATORS_PATTERN = r".*Operator$"
@@ -101,6 +104,7 @@ SECRETS_PATTERN = r".*Backend$"
 TRANSFERS_PATTERN = r".*To[A-Z0-9].*Operator$"
 WRONG_TRANSFERS_PATTERN = r".*Transfer$|.*TransferOperator$"
 TRIGGER_PATTERN = r".*Trigger$"
+NOTIFICATION_PATTERN = r".*Notification$"
 
 ALL_PATTERNS = {
     OPERATORS_PATTERN,
@@ -110,6 +114,7 @@ ALL_PATTERNS = {
     TRANSFERS_PATTERN,
     WRONG_TRANSFERS_PATTERN,
     TRIGGER_PATTERN,
+    NOTIFICATION_PATTERN,
 }
 
 EXPECTED_SUFFIXES: dict[EntityType, str] = {
@@ -119,6 +124,7 @@ EXPECTED_SUFFIXES: dict[EntityType, str] = {
     EntityType.Secrets: "Backend",
     EntityType.Transfers: "Operator",
     EntityType.Trigger: "Trigger",
+    EntityType.Notification: "Notification",
 }
 
 
@@ -462,6 +468,7 @@ def get_package_class_summary(
     from airflow.secrets import BaseSecretsBackend
     from airflow.sensors.base import BaseSensorOperator
     from airflow.triggers.base import BaseTrigger
+    from airflow.notifications.basenotifier import BaseNotifier
 
     all_verified_entities: dict[EntityType, VerifiedEntities] = {
         EntityType.Operators: find_all_entities(
@@ -522,6 +529,14 @@ def get_package_class_summary(
             expected_class_name_pattern=TRIGGER_PATTERN,
             unexpected_class_name_patterns=ALL_PATTERNS - {TRIGGER_PATTERN},
         ),
+        EntityType.Notification: find_all_entities(
+            imported_classes=imported_classes,
+            base_package=full_package_name,
+            sub_package_pattern_match=r".*\.notifications\..*",
+            ancestor_match=BaseNotifier,
+            expected_class_name_pattern=NOTIFICATION_PATTERN,
+            unexpected_class_name_patterns=ALL_PATTERNS - 
{NOTIFICATION_PATTERN},
+        ),
     }
     for entity in EntityType:
         print_wrong_naming(entity, 
all_verified_entities[entity].wrong_entities)
diff --git a/tests/always/test_providers_manager.py 
b/tests/always/test_providers_manager.py
index 7e05d1cfb1..afeab528e1 100644
--- a/tests/always/test_providers_manager.py
+++ b/tests/always/test_providers_manager.py
@@ -379,6 +379,11 @@ class TestProviderManager:
         trigger_class_names = list(provider_manager.trigger)
         assert len(trigger_class_names) > 10
 
+    def test_notification(self):
+        provider_manager = ProvidersManager()
+        notification_class_names = list(provider_manager.notification)
+        assert len(notification_class_names) > 5
+
     @patch("airflow.providers_manager.import_string")
     def test_optional_feature_no_warning(self, mock_importlib_import_string):
         with self._caplog.at_level(logging.WARNING):

Reply via email to