Programmer-RD-AI commented on code in PR #54259:
URL: https://github.com/apache/airflow/pull/54259#discussion_r2280571447


##########
providers/elasticsearch/src/airflow/providers/elasticsearch/hooks/elasticsearch.py:
##########
@@ -235,20 +241,28 @@ class ElasticsearchPythonHook(BaseHook):
     """
     Interacts with Elasticsearch. This hook uses the official Elasticsearch 
Python Client.
 
+    .. deprecated:: 2.10.0
+        This hook is deprecated. Use 
:class:`~airflow.providers.elasticsearch.hooks.elasticsearch.ElasticsearchHook` 
instead.
+
     :param hosts: list: A list of a single or many Elasticsearch instances. 
Example: ["http://localhost:9200";]
     :param es_conn_args: dict: Additional arguments you might need to enter to 
connect to Elasticsearch.
                                 Example: {"ca_cert":"/path/to/cert", 
"basic_auth": "(user, pass)"}
     """
 
     def __init__(self, hosts: list[Any], es_conn_args: dict | None = None):

Review Comment:
   Optional: add `-> None` to make the return type explicit.
   
   ```suggestion
       def __init__(self, hosts: list[Any], es_conn_args: dict | None = None) 
-> None:
   ```



##########
providers/elasticsearch/src/airflow/providers/elasticsearch/hooks/elasticsearch.py:
##########
@@ -268,3 +282,448 @@ def search(self, query: dict[Any, Any], index: str = 
"_all") -> dict:
         es_client = self.get_conn
         result = es_client.search(index=index, body=query)
         return result["hits"]
+
+
+class ElasticsearchHook(BaseHook):
+    """
+    Hook for interacting with Elasticsearch.
+
+    This hook provides a convenient interface to Elasticsearch operations
+    including search, bulk operations, and data management.
+    """
+
+    conn_name_attr = "elasticsearch_conn_id"
+    default_conn_name = "elasticsearch_default"
+    conn_type = "elasticsearch"
+    hook_name = "Elasticsearch"
+
+    def __init__(
+        self, elasticsearch_conn_id: str = "elasticsearch_default", log_query: 
bool = False, **kwargs: Any
+    ) -> None:
+        """
+        Initialize the Elasticsearch Hook.
+
+        :param elasticsearch_conn_id: The Airflow connection ID for 
Elasticsearch.
+            Default: *elasticsearch_default*.
+        :param log_query: If *True*, queries will be logged for debugging 
purposes.
+            Default: *False*.
+        :param kwargs: Additional arguments passed to the parent BaseHook 
class.
+        """
+        import os
+
+        super().__init__()
+        self.conn_id = elasticsearch_conn_id
+        self.log_query = log_query
+
+        # Environment variables as fallback configuration
+        self.vars: dict[str, str | bool | None] = {
+            "host": os.getenv("ELASTICSEARCH_HOST"),
+            "port": os.getenv("ELASTICSEARCH_PORT"),
+            "username": os.getenv("ELASTICSEARCH_USERNAME"),
+            "password": os.getenv("ELASTICSEARCH_PASSWORD"),
+            "use_ssl": os.getenv("ELASTICSEARCH_USE_SSL", "false").lower() == 
"true",
+            "verify_certs": os.getenv("ELASTICSEARCH_VERIFY_CERTS", 
"true").lower() == "true",
+            "timeout": os.getenv("ELASTICSEARCH_TIMEOUT"),
+            "max_retries": os.getenv("ELASTICSEARCH_MAX_RETRIES"),
+        }
+
+    @cached_property
+    def conn(self) -> "AirflowConnection":
+        """Get the Airflow connection object for Elasticsearch."""
+        return self.get_connection(self.conn_id)
+
+    @cached_property
+    def client(self) -> Elasticsearch:
+        """
+        Create and return an Elasticsearch client with environment variable 
fallback.
+
+        Configuration priority:
+        1. Airflow connection (highest priority)
+        2. Environment variables (fallback)
+        3. Default values (last resort)
+
+        :return: Configured Elasticsearch client instance.
+        :raises AirflowConfigException: If client creation fails due to 
configuration issues.
+        """
+        # Get Airflow connection
+        conn = self.get_connection(self.conn_id)
+
+        # Configuration with fallback priority: connection -> env vars -> 
defaults
+        host = conn.host or self.vars["host"] or "localhost"
+        port = conn.port or (int(self.vars["port"]) if self.vars["port"] else 
None) or 9200
+        schema = conn.schema or ("https" if self.vars["use_ssl"] else "http")
+
+        # Build hosts list
+        hosts = [f"{schema}://{host}:{port}"]
+        client_args: dict[str, Any] = {"hosts": hosts}

Review Comment:
   Optional: Using `Any` here makes the type a bit too loose.  
   Might be clearer to define a more specific type for `client_args` (e.g. 
`dict[str, str | int | bool]` or a TypedDict) 
   so it’s easier to see what values are expected.
   



##########
providers/elasticsearch/src/airflow/providers/elasticsearch/hooks/elasticsearch.py:
##########
@@ -268,3 +282,448 @@ def search(self, query: dict[Any, Any], index: str = 
"_all") -> dict:
         es_client = self.get_conn
         result = es_client.search(index=index, body=query)
         return result["hits"]
+
+
+class ElasticsearchHook(BaseHook):
+    """
+    Hook for interacting with Elasticsearch.
+
+    This hook provides a convenient interface to Elasticsearch operations
+    including search, bulk operations, and data management.
+    """
+
+    conn_name_attr = "elasticsearch_conn_id"
+    default_conn_name = "elasticsearch_default"
+    conn_type = "elasticsearch"
+    hook_name = "Elasticsearch"
+
+    def __init__(
+        self, elasticsearch_conn_id: str = "elasticsearch_default", log_query: 
bool = False, **kwargs: Any
+    ) -> None:
+        """
+        Initialize the Elasticsearch Hook.
+
+        :param elasticsearch_conn_id: The Airflow connection ID for 
Elasticsearch.
+            Default: *elasticsearch_default*.
+        :param log_query: If *True*, queries will be logged for debugging 
purposes.
+            Default: *False*.
+        :param kwargs: Additional arguments passed to the parent BaseHook 
class.
+        """
+        import os
+
+        super().__init__()
+        self.conn_id = elasticsearch_conn_id
+        self.log_query = log_query
+
+        # Environment variables as fallback configuration
+        self.vars: dict[str, str | bool | None] = {
+            "host": os.getenv("ELASTICSEARCH_HOST"),
+            "port": os.getenv("ELASTICSEARCH_PORT"),
+            "username": os.getenv("ELASTICSEARCH_USERNAME"),
+            "password": os.getenv("ELASTICSEARCH_PASSWORD"),
+            "use_ssl": os.getenv("ELASTICSEARCH_USE_SSL", "false").lower() == 
"true",
+            "verify_certs": os.getenv("ELASTICSEARCH_VERIFY_CERTS", 
"true").lower() == "true",
+            "timeout": os.getenv("ELASTICSEARCH_TIMEOUT"),
+            "max_retries": os.getenv("ELASTICSEARCH_MAX_RETRIES"),
+        }
+
+    @cached_property
+    def conn(self) -> "AirflowConnection":
+        """Get the Airflow connection object for Elasticsearch."""
+        return self.get_connection(self.conn_id)
+
+    @cached_property
+    def client(self) -> Elasticsearch:
+        """
+        Create and return an Elasticsearch client with environment variable 
fallback.
+
+        Configuration priority:
+        1. Airflow connection (highest priority)
+        2. Environment variables (fallback)
+        3. Default values (last resort)
+
+        :return: Configured Elasticsearch client instance.
+        :raises AirflowConfigException: If client creation fails due to 
configuration issues.
+        """
+        # Get Airflow connection
+        conn = self.get_connection(self.conn_id)
+
+        # Configuration with fallback priority: connection -> env vars -> 
defaults
+        host = conn.host or self.vars["host"] or "localhost"
+        port = conn.port or (int(self.vars["port"]) if self.vars["port"] else 
None) or 9200

Review Comment:
   Might be safer to use `.get()` when accessing `self.vars` (e.g. 
`self.vars.get("host")`) 
   to avoid potential `KeyError`s if the key is missing. Keeps the same 
fallback behavior 
   without assuming the key is always present.
   



##########
providers/elasticsearch/src/airflow/providers/elasticsearch/hooks/elasticsearch.py:
##########
@@ -268,3 +282,448 @@ def search(self, query: dict[Any, Any], index: str = 
"_all") -> dict:
         es_client = self.get_conn
         result = es_client.search(index=index, body=query)
         return result["hits"]
+
+
+class ElasticsearchHook(BaseHook):
+    """
+    Hook for interacting with Elasticsearch.
+
+    This hook provides a convenient interface to Elasticsearch operations
+    including search, bulk operations, and data management.
+    """
+
+    conn_name_attr = "elasticsearch_conn_id"
+    default_conn_name = "elasticsearch_default"
+    conn_type = "elasticsearch"
+    hook_name = "Elasticsearch"
+
+    def __init__(
+        self, elasticsearch_conn_id: str = "elasticsearch_default", log_query: 
bool = False, **kwargs: Any

Review Comment:
   Optional: Instead of hardcoding `"elasticsearch_default"`, this could fall 
back to the class-level 
   `default_conn_name`. That way the default only needs to be maintained in one 
place.
   
   ```suggestion
           self, elasticsearch_conn_id: str = None, log_query: bool = False, 
**kwargs: Any
   ```



##########
providers/elasticsearch/src/airflow/providers/elasticsearch/hooks/elasticsearch.py:
##########
@@ -268,3 +282,448 @@ def search(self, query: dict[Any, Any], index: str = 
"_all") -> dict:
         es_client = self.get_conn
         result = es_client.search(index=index, body=query)
         return result["hits"]
+
+
+class ElasticsearchHook(BaseHook):
+    """
+    Hook for interacting with Elasticsearch.
+
+    This hook provides a convenient interface to Elasticsearch operations
+    including search, bulk operations, and data management.
+    """
+
+    conn_name_attr = "elasticsearch_conn_id"
+    default_conn_name = "elasticsearch_default"
+    conn_type = "elasticsearch"
+    hook_name = "Elasticsearch"
+
+    def __init__(
+        self, elasticsearch_conn_id: str = "elasticsearch_default", log_query: 
bool = False, **kwargs: Any
+    ) -> None:
+        """
+        Initialize the Elasticsearch Hook.
+
+        :param elasticsearch_conn_id: The Airflow connection ID for 
Elasticsearch.
+            Default: *elasticsearch_default*.
+        :param log_query: If *True*, queries will be logged for debugging 
purposes.
+            Default: *False*.
+        :param kwargs: Additional arguments passed to the parent BaseHook 
class.
+        """
+        import os
+
+        super().__init__()
+        self.conn_id = elasticsearch_conn_id
+        self.log_query = log_query
+
+        # Environment variables as fallback configuration
+        self.vars: dict[str, str | bool | None] = {
+            "host": os.getenv("ELASTICSEARCH_HOST"),
+            "port": os.getenv("ELASTICSEARCH_PORT"),
+            "username": os.getenv("ELASTICSEARCH_USERNAME"),
+            "password": os.getenv("ELASTICSEARCH_PASSWORD"),
+            "use_ssl": os.getenv("ELASTICSEARCH_USE_SSL", "false").lower() == 
"true",
+            "verify_certs": os.getenv("ELASTICSEARCH_VERIFY_CERTS", 
"true").lower() == "true",
+            "timeout": os.getenv("ELASTICSEARCH_TIMEOUT"),
+            "max_retries": os.getenv("ELASTICSEARCH_MAX_RETRIES"),
+        }
+
+    @cached_property
+    def conn(self) -> "AirflowConnection":
+        """Get the Airflow connection object for Elasticsearch."""
+        return self.get_connection(self.conn_id)
+
+    @cached_property
+    def client(self) -> Elasticsearch:
+        """
+        Create and return an Elasticsearch client with environment variable 
fallback.
+
+        Configuration priority:
+        1. Airflow connection (highest priority)
+        2. Environment variables (fallback)
+        3. Default values (last resort)
+
+        :return: Configured Elasticsearch client instance.
+        :raises AirflowConfigException: If client creation fails due to 
configuration issues.
+        """
+        # Get Airflow connection
+        conn = self.get_connection(self.conn_id)
+
+        # Configuration with fallback priority: connection -> env vars -> 
defaults
+        host = conn.host or self.vars["host"] or "localhost"
+        port = conn.port or (int(self.vars["port"]) if self.vars["port"] else 
None) or 9200
+        schema = conn.schema or ("https" if self.vars["use_ssl"] else "http")

Review Comment:
   For consistency with `host` and `port`, the `schema` fallback could follow 
the same 
   `conn → vars → default` structure, e.g.:
   
   ```suggestion
           schema = conn.schema or ("https" if self.vars.get("use_ssl") else 
None) or "http"
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to