orion222 opened a new pull request, #45991:
URL: https://github.com/apache/superset/pull/45991

   ### SUMMARY
   
   Extensions can only use what `superset_core` exposes. `superset_core` can 
run raw SQL (`Database.execute`, #36529), but it has no way to run a chart's 
query or walk a dashboard's charts. That logic lives only inside Superset: 
`ChartDataCommand` behind `/api/v1/chart/data`, and the per-chart loop in the 
Excel dashboard export.
   
   This PR adds `superset_core.exports`, a small API for extensions that export 
chart and dashboard data. The first consumer is a Google Sheets export 
extension, but nothing here is Google-specific.
   
   | Function | New or exposed |
   |---|---|
   | `run_query_context(payload)` | Exposed. The `/api/v1/chart/data` flow 
(schema load, `ChartDataCommand.validate()`/`run()`, client-side 
post-processing) as one call. JSON row data only. |
   | `iter_dashboard_chart_results(dashboard_id, active_data_mask)` | Exposed. 
The Excel export's per-chart loop, moved into `chart_results.py`. A failed 
chart is reported, not raised. |
   | `describe_dashboard_export(dashboard_id, active_data_mask)` | **New.** 
Title, a permalink for the exported filter state, the applied native filters 
and Explore links. This is the last commit, so it can be dropped on its own. |
   | `build_tab_name(raw, used, max_len)` | Exposed. `sanitize_sheet_name` with 
a length parameter and Excel-only rules switched off. |
   | `can_export_data()` | Exposed. `ChartDataRestApi._has_export_permission`. |
   | `can_export_dashboard(dashboard_id)` | Exposed. Dashboard access plus 
`can_export on Dashboard`, the check Excel's dashboard export applies. |
   | `as_user(user_id)` | Exposed. `override_user`. Background tasks don't set 
`g.user`, and extensions can't import `superset.utils.core`. |
   
   The types and stubs live in `superset-core`. Superset injects its 
implementations at startup (`core_api_injection.py`), the same way as `queries` 
and `tasks`. Celery workers get them through `create_app()`.
   
   **The Excel dashboard export is refactored onto the shared per-chart helper, 
and its output doesn't change.** `build_workbook` keeps its own layout-order 
loop, its image branch and its precomputed-plan handling. Only data charts go 
through `chart_result()`. A workbook built before and after the change is 
identical apart from its timestamp. No existing test assertion changed. Only 
patch targets moved, in the `mocks` fixture of 
`tests/unit_tests/dashboards/test_excel_export_workbook.py` and in the `mocks` 
fixture and `_builder_hook` of 
`tests/unit_tests/tasks/test_export_dashboard_excel.py`.
   
   **Design decisions:**
   - `run_query_context` doesn't check the export permission. Excel's dashboard 
export is gated by `can_export on Dashboard`, not `can_csv`, so enforcing it in 
the shared helper would change who can use Excel. Extensions call 
`can_export_data()` themselves, as documented.
   - **Integer IDs.** These match the code the functions sit next to: the 
`superset_core` DAOs, `POST /api/v1/dashboard/<pk>/export_xlsx/`, and the 
frontend menus, which have integer IDs at hand. This departs from the UUID 
preference for new public APIs, so I'm calling it out here.
   - `describe_dashboard_export` lists native filters only. Exports never apply 
cross-filters, because `get_dashboard_filter_context` reads 
`native_filter_configuration` only.
   - A `post_processed` result comes back as row records, with the row labels 
as a leading column. Client processing returns a column-keyed dict for JSON, so 
the helper converts it.
   
   **Security:** no new permission, and no path returns data the user couldn't 
get from `/api/v1/chart/data`. `run_query_context` goes through 
`raise_for_access`: datasource access, RLS, and guest dashboard membership 
through the stamped `dashboardId`/`slice_id`. `describe_dashboard_export` 
checks dashboard access before it creates a permalink. `as_user` is reachable 
only from Python running inside Superset, which is operator-installed extension 
code, the same trust boundary as `override_user`. It isn't an HTTP surface.
   
   ### BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
   
   Not applicable (backend API only).
   
   ### TESTING INSTRUCTIONS
   
   Unit tests:
   
   ```bash
   pytest tests/unit_tests/dashboards 
tests/unit_tests/tasks/test_export_dashboard_excel.py \
     tests/unit_tests/utils/excel_streaming_tests.py tests/unit_tests/charts 
tests/unit_tests/core
   pytest superset-core/tests   # separate process, as in CI
   ```
   
   Excel regression check:
   1. Export a dashboard with "Export Data to Excel", on this branch and on 
`master`.
   2. Include an image-mode export with a mix of table and non-table charts.
   3. Check that the sheets, their order and names, and the Export Summary 
sheet are identical.
   
   The new API:
   1. In a Superset shell, call 
`superset_core.exports.export.run_query_context(...)` with a chart's saved 
query context.
   2. Call `iter_dashboard_chart_results(dashboard_id, {})` inside 
`as_user(<id>)`.
   
   Docs: `docs/developer_docs/extensions/exports.md`.
   
   ### ADDITIONAL INFORMATION
   - [ ] Has associated issue:
   - [ ] Required feature flags:
   - [ ] Changes UI
   - [ ] Includes DB Migration (follow approval process in 
[SIP-59](https://github.com/apache/superset/issues/13351))
     - [ ] Migration is atomic, supports rollback & is backwards-compatible
     - [ ] Confirm DB migration upgrade and downgrade tested
     - [ ] Runtime estimates and downtime expectations provided
   - [x] Introduces new feature or API
   - [ ] Removes existing feature or API
   


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

  • [PR] feat(c... orion222 (via GitHub) via notifications
    • Re: [P... codeant-ai-for-open-source[bot] (via GitHub) via notifications
    • Re: [P... codeant-ai-for-open-source[bot] (via GitHub) via notifications
    • Re: [P... codeant-ai-for-open-source[bot] (via GitHub) via notifications
    • Re: [P... orion222 (via GitHub) via notifications
    • Re: [P... orion222 (via GitHub) via notifications
    • Re: [P... codeant-ai-for-open-source[bot] (via GitHub) via notifications
    • Re: [P... orion222 (via GitHub) via notifications
    • Re: [P... codecov[bot] (via GitHub) via notifications
    • Re: [P... codeant-ai-for-open-source[bot] (via GitHub) via notifications
    • Re: [P... codeant-ai-for-open-source[bot] (via GitHub) via notifications

Reply via email to