codeant-ai-for-open-source[bot] commented on code in PR #40885:
URL: https://github.com/apache/superset/pull/40885#discussion_r3570966150


##########
superset/charts/client_processing.py:
##########
@@ -403,5 +410,11 @@ def apply_client_processing(  # noqa: C901
                 index=show_default_index,
                 **current_app.config["CSV_EXPORT"],
             )
+        elif query["result_format"] == ChartDataResultFormat.XLSX:
+            excel.apply_column_types(processed_df, query["coltypes"])
+            query["data"] = excel.df_to_excel(
+                processed_df,
+                **current_app.config["EXCEL_EXPORT"],
+            )

Review Comment:
   **Suggestion:** The XLSX serialization path does not pass an explicit 
`index` flag, so pandas defaults to writing the index. This diverges from the 
chart export behavior that suppresses default `RangeIndex`, causing 
post-processed report attachments to gain an unexpected extra index column. 
Pass the same computed index policy used by the CSV branch (eg, based on 
whether the index is default). [logic error]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ XLSX attachments include unintended default index column.
   - ⚠️ XLSX report tables differ from CSV formatting policy.
   ```
   </details>
   <details>
   <summary><b>Steps of Reproduction βœ… </b></summary>
   
   ```mdx
   1. Construct a pandas DataFrame with a default `RangeIndex` (e.g., 
`pd.DataFrame({"city":
   ["Paris", "London"], "value": [10, 20]})`) and wrap it in a chart query 
result for the
   `table` viz type so that `post_processor` in `apply_client_processing` 
returns a frame
   with a `RangeIndex` (superset/charts/client_processing.py:283-305, 313-325).
   
   2. Call `apply_client_processing(result, form_data)` and observe that 
metadata computation
   sets `show_default_index = not isinstance(processed_df.index, 
pd.RangeIndex)` to `False`
   for this frame (client_processing.py:379), meaning default `RangeIndex` 
should not be
   shown in exports.
   
   3. For CSV result format, the code writes `query["data"] =
   csv.df_to_escaped_csv(processed_df, index=show_default_index,
   **current_app.config["CSV_EXPORT"])` (client_processing.py:405-412), passing 
`index=False`
   when the index is a `RangeIndex`, which omits the index as intended and 
matches other
   export paths like `query_context_processor`
   (superset/common/query_context_processor.py:2-23).
   
   4. For XLSX result format, the new branch at lines 413-418 calls
   `excel.apply_column_types(processed_df, query["coltypes"])` and then 
`query["data"] =
   excel.df_to_excel(processed_df, **current_app.config["EXCEL_EXPORT"])` 
without an explicit
   `index` argument. With default `EXCEL_EXPORT` (superset/config.py:1436) 
lacking an
   `"index"` key, `df.to_excel` inside `df_to_excel` 
(superset/utils/excel.py:14-22) defaults
   to `index=True`, causing the emitted XLSX bytes to include the `RangeIndex` 
as an extra
   first column even though `show_default_index` was `False` and CSV exports 
suppress it.
   ```
   </details>
   
   [![Fix in 
Cursor](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-cursor-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=47e44651449f4fbeaaa4e3c83777baba&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
 [![Fix in VSCode 
Claude](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-vscode-claude-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=47e44651449f4fbeaaa4e3c83777baba&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
   
   *(Use Cmd/Ctrl + Click for best experience)*
   <details>
   <summary><b>Prompt for AI Agent πŸ€– </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset/charts/client_processing.py
   **Line:** 413:418
   **Comment:**
        *Logic Error: The XLSX serialization path does not pass an explicit 
`index` flag, so pandas defaults to writing the index. This diverges from the 
chart export behavior that suppresses default `RangeIndex`, causing 
post-processed report attachments to gain an unexpected extra index column. 
Pass the same computed index policy used by the CSV branch (eg, based on 
whether the index is default).
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   Once fix is implemented, also check other comments on the same PR, and ask 
user if the user wants to fix the rest of the comments as well. if said yes, 
then fetch all the comments validate the correctness and implement a minimal fix
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F40885&comment_hash=667c0612dac607d6d4332268e1ad61b1a7f856732a2fad5c7a2131c0ff528131&reaction=like'>πŸ‘</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F40885&comment_hash=667c0612dac607d6d4332268e1ad61b1a7f856732a2fad5c7a2131c0ff528131&reaction=dislike'>πŸ‘Ž</a>



##########
superset/charts/client_processing.py:
##########
@@ -357,6 +357,13 @@ def apply_client_processing(  # noqa: C901
                 sep=sep,
                 decimal=decimal,
             )
+        elif query["result_format"] == ChartDataResultFormat.XLSX:
+            read_excel_kwargs = (
+                {"index_col": 0}
+                if current_app.config["EXCEL_EXPORT"].get("index", True)
+                else {}
+            )
+            df = pd.read_excel(BytesIO(data), **read_excel_kwargs)

Review Comment:
   **Suggestion:** The XLSX reader is deciding whether to consume an index 
column from `EXCEL_EXPORT["index"]`, but exported chart data does not reliably 
encode index presence from that config (it is based on the actual dataframe 
index shape). With the default config (`EXCEL_EXPORT` empty), this forces 
`index_col=0` and can drop the first real data column for files exported 
without an index. Derive index handling from the payload characteristics (or 
fallback-read logic), not from config alone. [logic error]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ XLSX post-processing drops first column when index absent.
   - ⚠️ Email chart XLSX attachments show misaligned columns and index.
   ```
   </details>
   <details>
   <summary><b>Steps of Reproduction βœ… </b></summary>
   
   ```mdx
   1. Start with the default Superset configuration where `EXCEL_EXPORT` is an 
empty dict
   (superset/config.py:1436), so 
`current_app.config["EXCEL_EXPORT"].get("index", True)`
   returns `True`.
   
   2. In a test or runtime flow, construct an XLSX payload for a simple table 
without an
   index column by calling `excel.df_to_excel(source_df, index=False)` as in
   `_assert_xlsx_client_processing`
   (superset/tests/unit_tests/charts/test_client_processing.py:2-18), and build 
`result =
   {"queries": [{"result_format": ChartDataResultFormat.XLSX, "data": 
xlsx_bytes}]}`.
   
   3. Call `apply_client_processing(result, form_data)` for a table viz
   (superset/charts/client_processing.py:313-325), which iterates queries and 
reaches the
   XLSX input branch at lines 360-366: `read_excel_kwargs = {"index_col": 0} if
   current_app.config["EXCEL_EXPORT"].get("index", True) else {}; df =
   pd.read_excel(BytesIO(data), **read_excel_kwargs)`.
   
   4. Because the XLSX payload was written without an index column, 
`pd.read_excel(...,
   index_col=0)` in `apply_client_processing` (client_processing.py:360-366) 
consumes the
   first real data column as the index, dropping it from `df.columns`. The 
subsequent
   metadata (`colnames`, `indexnames`, `rowcount`) and any XLSX post-processed 
exports built
   from this frame will be based on a corrupted table where the first data 
column has been
   turned into the index.
   ```
   </details>
   
   [![Fix in 
Cursor](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-cursor-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=b2a553bb15d4460b94188f677ed76581&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
 [![Fix in VSCode 
Claude](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-vscode-claude-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=b2a553bb15d4460b94188f677ed76581&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
   
   *(Use Cmd/Ctrl + Click for best experience)*
   <details>
   <summary><b>Prompt for AI Agent πŸ€– </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset/charts/client_processing.py
   **Line:** 360:366
   **Comment:**
        *Logic Error: The XLSX reader is deciding whether to consume an index 
column from `EXCEL_EXPORT["index"]`, but exported chart data does not reliably 
encode index presence from that config (it is based on the actual dataframe 
index shape). With the default config (`EXCEL_EXPORT` empty), this forces 
`index_col=0` and can drop the first real data column for files exported 
without an index. Derive index handling from the payload characteristics (or 
fallback-read logic), not from config alone.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   Once fix is implemented, also check other comments on the same PR, and ask 
user if the user wants to fix the rest of the comments as well. if said yes, 
then fetch all the comments validate the correctness and implement a minimal fix
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F40885&comment_hash=e3ea4d002ee7846fa51ca302af748161c6135b9fa35218f23549e8e32f19c8e8&reaction=like'>πŸ‘</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F40885&comment_hash=e3ea4d002ee7846fa51ca302af748161c6135b9fa35218f23549e8e32f19c8e8&reaction=dislike'>πŸ‘Ž</a>



##########
superset/commands/report/execute.py:
##########
@@ -897,6 +934,13 @@ def _get_notification_content(self) -> 
NotificationContent:  # noqa: C901
                 csv_data = self._get_csv_data()
                 if not csv_data:
                     error_text = "Unexpected missing csv file"
+            elif (
+                self._report_schedule.chart
+                and self._report_schedule.report_format == 
ReportDataFormat.XLSX
+            ):
+                xlsx_data = self._get_xlsx_data()
+                if not xlsx_data:
+                    error_text = "Unexpected missing xlsx file"

Review Comment:
   **Suggestion:** XLSX generation is wired only for chart-backed schedules, 
but there is no corresponding hard validation to reject dashboard schedules 
configured with XLSX. Since XLSX is now an accepted report format, a dashboard 
schedule can pass through content generation without hitting any attachment 
branch and send a misleading β€œsuccessful” email with no file. Add server-side 
validation that restricts XLSX to chart targets (or raise an explicit execution 
error when target is unsupported). [incomplete implementation]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ⚠️ Dashboard XLSX reports send emails without any attachments.
   - ⚠️ Users receive success notifications for unsupported XLSX dashboards.
   ```
   </details>
   <details>
   <summary><b>Steps of Reproduction βœ… </b></summary>
   
   ```mdx
   1. Create or update a `ReportSchedule` via the reports API using
   `ReportSchedulePostSchema` or `ReportSchedulePutSchema`, setting `dashboard` 
to a valid
   dashboard ID, leaving `chart` unset, and choosing `report_format="XLSX"`
   (superset/reports/schemas.py:9-13, 173-177). The schema only validates that
   `report_format` is one of `ReportDataFormat` values and does not restrict 
formats based on
   whether a chart or dashboard is targeted.
   
   2. Persist this schedule; the `ReportSchedule` model stores `report_format` 
as a string
   defaulting to `ReportDataFormat.PNG` but now also allowing `XLSX`
   (superset/reports/models.py:82-86, 120), with `dashboard_id` populated and 
`chart_id` left
   `NULL`.
   
   3. Trigger execution of this dashboard schedule so
   `BaseReportState._get_notification_content` runs
   (superset/commands/report/execute.py:903-123). In the attachment routing 
block
   (execute.py:919-985), PNG and PDF formats are handled unconditionally, CSV 
and XLSX
   formats are only handled when `self._report_schedule.chart` is truthy
   (execute.py:931-941), and there is no branch for a dashboard with 
`ReportDataFormat.XLSX`.
   For the dashboard-only schedule, the XLSX branch at lines 937-943 is 
skipped, leaving
   `xlsx_data` as `None` and `error_text` unset.
   
   4. `_get_notification_content` falls through to build a 
`NotificationContent` with a name
   derived from the dashboard title and `xlsx=None` (execute.py:102-121). The 
email
   notification plugin attaches XLSX data only if `content.xlsx` is set
   (superset/reports/notifications/email.py:106-118), so the schedule sends a 
"successful"
   dashboard email that advertises XLSX format in 
`header_data["notification_format"]` but
   contains no XLSX attachment and no explicit error explaining that dashboards 
do not
   support XLSX.
   ```
   </details>
   
   [![Fix in 
Cursor](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-cursor-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=bf2d002ee0724a449f3c4ab450f86d14&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
 [![Fix in VSCode 
Claude](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-vscode-claude-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=bf2d002ee0724a449f3c4ab450f86d14&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
   
   *(Use Cmd/Ctrl + Click for best experience)*
   <details>
   <summary><b>Prompt for AI Agent πŸ€– </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset/commands/report/execute.py
   **Line:** 937:943
   **Comment:**
        *Incomplete Implementation: XLSX generation is wired only for 
chart-backed schedules, but there is no corresponding hard validation to reject 
dashboard schedules configured with XLSX. Since XLSX is now an accepted report 
format, a dashboard schedule can pass through content generation without 
hitting any attachment branch and send a misleading β€œsuccessful” email with no 
file. Add server-side validation that restricts XLSX to chart targets (or raise 
an explicit execution error when target is unsupported).
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   Once fix is implemented, also check other comments on the same PR, and ask 
user if the user wants to fix the rest of the comments as well. if said yes, 
then fetch all the comments validate the correctness and implement a minimal fix
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F40885&comment_hash=8c672e32cf3911b9bc49f007d8bffcb9ffcde319db2e3b964912967e05e7ed81&reaction=like'>πŸ‘</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F40885&comment_hash=8c672e32cf3911b9bc49f007d8bffcb9ffcde319db2e3b964912967e05e7ed81&reaction=dislike'>πŸ‘Ž</a>



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


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to