shahar1 commented on code in PR #74817:
URL: https://github.com/apache/airflow/pull/74817#discussion_r4306616490


##########
providers/amazon/src/airflow/providers/amazon/aws/transfers/sql_to_s3.py:
##########
@@ -220,7 +221,23 @@ def _strip_suffixes(
                 return path[: -len(suffix)]
         return path
 
+    def _ensure_parquet_engine(self) -> None:
+        needs_parquet = self.file_format == FILE_FORMAT.PARQUET or (
+            ("dtype_backend", "pyarrow") in self.read_kwargs.items()
+        )
+        if self.df_type != "pandas" or not needs_parquet:
+            return
+        if any(importlib.util.find_spec(engine) for engine in ("pyarrow", 
"fastparquet")):
+            return
+
+        from airflow.providers.common.compat.sdk import 
AirflowOptionalProviderFeatureException

Review Comment:
   **nit** — `airflow.providers.common.compat.sdk` is already imported at 
module level (`AirflowException, BaseHook, BaseOperator`), so this 
function-level import gains nothing. Add 
`AirflowOptionalProviderFeatureException` to the top-level import.
   
   > Imports at top of file. Valid exceptions: circular imports, lazy loading 
for worker isolation, `TYPE_CHECKING` blocks. (AGENTS.md → Coding Standards)



##########
providers/amazon/tests/unit/amazon/aws/transfers/test_sql_to_s3.py:
##########
@@ -199,6 +199,41 @@ def test_fix_dtypes_not_called(self, mock_s3_hook):
 
         mock_fix_dtypes.assert_not_called()
 
+    @pytest.mark.parametrize(
+        ("df_type", "file_format", "read_kwargs", "available_engines", 
"should_raise"),
+        [
+            pytest.param("pandas", "parquet", {}, set(), True, 
id="pandas-parquet-no-engine"),
+            pytest.param("pandas", "parquet", {}, {"fastparquet"}, False, 
id="pandas-parquet-fastparquet"),
+            pytest.param(
+                "pandas", "csv", {"dtype_backend": "pyarrow"}, set(), True, 
id="pandas-pyarrow-backend"
+            ),
+            pytest.param("pandas", "csv", {}, set(), False, 
id="pandas-csv-no-engine"),
+            pytest.param("polars", "parquet", {}, set(), False, 
id="polars-parquet-no-engine"),
+        ],
+    )
+    @mock.patch("importlib.util.find_spec")
+    def test_parquet_engine_required(
+        self, mock_find_spec, df_type, file_format, read_kwargs, 
available_engines, should_raise
+    ):
+        mock_find_spec.side_effect = lambda name: object() if name in 
available_engines else None
+        op = SqlToS3Operator(
+            query="query",
+            s3_bucket="bucket",
+            s3_key="key",
+            sql_conn_id="mysql_conn_id",
+            task_id="task_id",
+            df_type=df_type,
+            file_format=file_format,
+            read_kwargs=read_kwargs,
+            dag=None,
+        )
+
+        if should_raise:
+            with pytest.raises(AirflowOptionalProviderFeatureException, 
match=r"\[parquet\]"):
+                op._ensure_parquet_engine()

Review Comment:
   **minor** — this tests the helper but not the wiring. Removing 
`self._ensure_parquet_engine()` from `execute()` keeps every test green, so the 
"checks before querying" behaviour is untested. Drive the raising case through 
`op.execute(None)` and assert the hook's `get_df` was never called.
   
   > Every changed or added behaviour must have a test; every test must fail 
without the PR's change. (AGENTS.md → Testing Standards)



##########
providers/amazon/tests/unit/amazon/aws/transfers/test_sql_to_s3.py:
##########
@@ -199,6 +199,41 @@ def test_fix_dtypes_not_called(self, mock_s3_hook):
 
         mock_fix_dtypes.assert_not_called()
 
+    @pytest.mark.parametrize(
+        ("df_type", "file_format", "read_kwargs", "available_engines", 
"should_raise"),
+        [
+            pytest.param("pandas", "parquet", {}, set(), True, 
id="pandas-parquet-no-engine"),
+            pytest.param("pandas", "parquet", {}, {"fastparquet"}, False, 
id="pandas-parquet-fastparquet"),
+            pytest.param(
+                "pandas", "csv", {"dtype_backend": "pyarrow"}, set(), True, 
id="pandas-pyarrow-backend"
+            ),
+            pytest.param("pandas", "csv", {}, set(), False, 
id="pandas-csv-no-engine"),
+            pytest.param("polars", "parquet", {}, set(), False, 
id="polars-parquet-no-engine"),
+        ],
+    )
+    @mock.patch("importlib.util.find_spec")

Review Comment:
   **nit** — add `autospec=True` here; the patch is also active process-wide 
during operator construction, not just the helper call.
   
   > Use `spec`/`autospec` when mocking. (AGENTS.md → Testing Standards)



##########
providers/amazon/src/airflow/providers/amazon/aws/transfers/sql_to_s3.py:
##########
@@ -220,7 +221,23 @@ def _strip_suffixes(
                 return path[: -len(suffix)]
         return path
 
+    def _ensure_parquet_engine(self) -> None:
+        needs_parquet = self.file_format == FILE_FORMAT.PARQUET or (
+            ("dtype_backend", "pyarrow") in self.read_kwargs.items()
+        )
+        if self.df_type != "pandas" or not needs_parquet:
+            return
+        if any(importlib.util.find_spec(engine) for engine in ("pyarrow", 
"fastparquet")):

Review Comment:
   **minor** — `dtype_backend="pyarrow"` needs pyarrow itself, so fastparquet 
must not satisfy this check. With fastparquet installed and pyarrow missing, 
the check passes and `read_sql` then fails with pandas' generic ``ImportError: 
`Import pyarrow` failed.`` (reproduced on pandas 3.0.6). Require `pyarrow` when 
`dtype_backend="pyarrow"`, and accept either engine only for Parquet output. A 
parametrize case with `dtype_backend="pyarrow"` and only `fastparquet` 
available would cover it.



-- 
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