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]