feat(build): migrate from Prettier to Oxfmt for performant code formatting (#42434)

This commit is contained in:
Đỗ Trọng Hải
2026-08-04 00:27:05 +07:00
committed by GitHub
parent 10f7927603
commit e4ef84ca72
2328 changed files with 90728 additions and 32682 deletions

View File

@@ -34,45 +34,40 @@ Alert component for displaying important messages to users. Wraps Ant Design Ale
<StoryWithControls
component={Alert}
props={{
closable: true,
type: 'info',
message: 'This is a sample alert message.',
description: 'Sample description for additional context.',
showIcon: true
}}
closable: true,
type: 'info',
message: 'This is a sample alert message.',
description: 'Sample description for additional context.',
showIcon: true,
}}
controls={[
{
name: 'type',
label: 'Type',
type: 'select',
options: [
'info',
'error',
'warning',
'success'
]
},
{
name: 'closable',
label: 'Closable',
type: 'boolean'
},
{
name: 'showIcon',
label: 'Show Icon',
type: 'boolean'
},
{
name: 'message',
label: 'Message',
type: 'text'
},
{
name: 'description',
label: 'Description',
type: 'text'
}
]}
{
name: 'type',
label: 'Type',
type: 'select',
options: ['info', 'error', 'warning', 'success'],
},
{
name: 'closable',
label: 'Closable',
type: 'boolean',
},
{
name: 'showIcon',
label: 'Show Icon',
type: 'boolean',
},
{
name: 'message',
label: 'Message',
type: 'text',
},
{
name: 'description',
label: 'Description',
type: 'text',
},
]}
/>
## Try It
@@ -95,13 +90,13 @@ function Demo() {
## Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `closable` | `boolean` | `true` | Whether the Alert can be closed with a close button. |
| `type` | `string` | `"info"` | Type of the alert (e.g., info, error, warning, success). |
| `message` | `string` | `"This is a sample alert message."` | Message |
| `description` | `string` | `"Sample description for additional context."` | Description |
| `showIcon` | `boolean` | `true` | Whether to display an icon in the Alert. |
| Prop | Type | Default | Description |
| ------------- | --------- | ---------------------------------------------- | -------------------------------------------------------- |
| `closable` | `boolean` | `true` | Whether the Alert can be closed with a close button. |
| `type` | `string` | `"info"` | Type of the alert (e.g., info, error, warning, success). |
| `message` | `string` | `"This is a sample alert message."` | Message |
| `description` | `string` | `"Sample description for additional context."` | Description |
| `showIcon` | `boolean` | `true` | Whether to display an icon in the Alert. |
## Usage in Extensions
@@ -112,11 +107,7 @@ import { Alert } from '@apache-superset/core/components';
function MyExtension() {
return (
<Alert
closable
type="info"
message="This is a sample alert message."
/>
<Alert closable type="info" message="This is a sample alert message." />
);
}
```
@@ -128,4 +119,4 @@ function MyExtension() {
---
*This page was auto-generated from the component's Storybook story.*
_This page was auto-generated from the component's Storybook story._

View File

@@ -39,11 +39,7 @@ All components are exported from the `@apache-superset/core/components` package:
import { Alert } from '@apache-superset/core/components';
export function MyExtensionPanel() {
return (
<Alert type="info">
Welcome to my extension!
</Alert>
);
return <Alert type="info">Welcome to my extension!</Alert>;
}
```
@@ -68,7 +64,7 @@ export default {
},
};
export const InteractiveMyComponent = (args) => <MyComponent {...args} />;
export const InteractiveMyComponent = args => <MyComponent {...args} />;
InteractiveMyComponent.args = {
variant: 'primary',

View File

@@ -152,6 +152,7 @@ from .api import MyExtensionAPI
- **Host context**: `/api/v1/` with original ID
For an extension with publisher `my-org` and name `dataset-tools`, the endpoint above would be accessible at:
```
/extensions/my-org/dataset-tools/hello
```

View File

@@ -34,10 +34,10 @@ Extensions run in the same context as Superset during runtime. This means extens
The core packages follow [semantic versioning](https://semver.org/) and provide stable, documented APIs:
| Package | Language | Description |
|---------|----------|-------------|
| Package | Language | Description |
| ----------------------- | --------------------- | -------------------------------------------------- |
| `@apache-superset/core` | JavaScript/TypeScript | Frontend APIs, UI components, hooks, and utilities |
| `apache-superset-core` | Python | Backend APIs, models, DAOs, and utilities |
| `apache-superset-core` | Python | Backend APIs, models, DAOs, and utilities |
**Benefits of using core packages:**
@@ -116,12 +116,14 @@ Abstracting libraries like React or SQLAlchemy would:
Extension developers should depend on and use core libraries directly:
**Frontend (examples):**
- [React](https://react.dev/) - UI framework
- [Ant Design](https://ant.design/) - UI component library (prefer Superset components from `@apache-superset/core/components` when available to preserve visual consistency)
- [Emotion](https://emotion.sh/) - CSS-in-JS styling
- ...
**Backend (examples):**
- [SQLAlchemy](https://www.sqlalchemy.org/) - Database toolkit
- [Flask](https://flask.palletsprojects.com/) - Web framework
- [Flask-AppBuilder](https://flask-appbuilder.readthedocs.io/) - Application framework

View File

@@ -35,7 +35,7 @@ Packaging is handled by the `superset-extensions bundle` command, which:
To deploy an extension, place the `.supx` file in the extensions directory configured via `EXTENSIONS_PATH` in your `superset_config.py`:
``` python
```python
EXTENSIONS_PATH = "/path/to/extensions"
```

View File

@@ -80,6 +80,7 @@ dataset-references/
```
**Note**: With publisher `my-org` and name `dataset-references`, the technical names are:
- Directory name: `dataset-references` (kebab-case)
- Backend Python namespace: `my_org.dataset_references`
- Backend distribution package: `my_org-dataset_references`

View File

@@ -30,16 +30,16 @@ Extensions can replace Superset's default text editors with custom implementatio
Superset uses text editors in various places throughout the application:
| Language | Locations |
|----------|-----------|
| `sql` | SQL Lab, Metric/Filter Popovers |
| `json` | Dashboard Properties, Annotation Modal, Theme Modal |
| `css` | Dashboard Properties, CSS Template Modal |
| `markdown` | Dashboard Markdown component |
| `yaml` | Template Params Editor |
| `javascript` | Custom JavaScript editor contexts |
| `python` | Custom Python editor contexts |
| `text` | Plain text editor contexts |
| Language | Locations |
| ------------ | --------------------------------------------------- |
| `sql` | SQL Lab, Metric/Filter Popovers |
| `json` | Dashboard Properties, Annotation Modal, Theme Modal |
| `css` | Dashboard Properties, CSS Template Modal |
| `markdown` | Dashboard Markdown component |
| `yaml` | Template Params Editor |
| `javascript` | Custom JavaScript editor contexts |
| `python` | Custom Python editor contexts |
| `text` | Plain text editor contexts |
By registering an editor for a language, your extension replaces the default Ace editor in **all** locations that use that language.
@@ -170,7 +170,7 @@ Superset passes keyboard shortcuts via the `hotkeys` prop. Each hotkey includes
```typescript
interface EditorHotkey {
name: string;
key: string; // e.g., "Ctrl-Enter", "Alt-Shift-F"
key: string; // e.g., "Ctrl-Enter", "Alt-Shift-F"
description?: string;
exec: (handle: EditorHandle) => void;
}
@@ -185,9 +185,9 @@ Superset passes static autocomplete suggestions via the `keywords` prop. These i
```typescript
interface EditorKeyword {
name: string;
value?: string; // Text to insert (defaults to name)
meta?: string; // Category like "table", "column", "function"
score?: number; // Sorting priority
value?: string; // Text to insert (defaults to name)
meta?: string; // Category like "table", "column", "function"
score?: number; // Sorting priority
}
```

View File

@@ -106,7 +106,11 @@ This example adds primary, secondary, and context actions to the editor:
import { commands, menus, sqlLab } from '@apache-superset/core';
commands.registerCommand(
{ id: 'my-extension.format', title: 'Format Query', icon: 'FormatPainterOutlined' },
{
id: 'my-extension.format',
title: 'Format Query',
icon: 'FormatPainterOutlined',
},
async () => {
const tab = sqlLab.getCurrentTab();
if (tab) {

View File

@@ -33,9 +33,11 @@ Model Context Protocol (MCP) integration allows extensions to register custom AI
MCP enables extensions to extend Superset's AI capabilities in two ways:
### MCP Tools
Tools are Python functions that AI agents can call to perform specific tasks. They provide executable functionality that extends Superset's capabilities.
**Examples of MCP tools:**
- Data processing and transformation functions
- Custom analytics calculations
- Integration with external APIs
@@ -43,9 +45,11 @@ Tools are Python functions that AI agents can call to perform specific tasks. Th
- Business-specific operations
### MCP Prompts
Prompts provide interactive guidance and context to AI agents. They help agents understand how to better assist users with specific workflows or domain knowledge.
**Examples of MCP prompts:**
- Step-by-step workflow guidance
- Domain-specific context and knowledge
- Interactive troubleshooting assistance
@@ -76,6 +80,7 @@ This creates a tool that AI agents can call by name. The tool name defaults to t
The `@tool` decorator accepts several optional parameters:
**Parameter details:**
- **`name`**: Tool identifier (AI agents use this to call your tool)
- **`description`**: Explains what the tool does (helps AI agents decide when to use it)
- **`tags`**: Categories for organization and discovery
@@ -213,6 +218,7 @@ Agent: I generated the number 42 for you.
```
The AI agent sees your tool's:
- **Name**: How to call it
- **Description**: What it does and when to use it
- **Parameters**: What inputs it expects (from Pydantic schema)
@@ -377,18 +383,21 @@ async def troubleshoot_charts(ctx: Context) -> str:
### Prompt Best Practices
#### Content Structure
- **Use clear headings** and sections for easy navigation
- **Provide actionable steps** rather than just theory
- **Include examples** relevant to the user's domain
- **Offer next steps** to continue the workflow
#### Interactive Design
- **Ask questions** to engage the user
- **Provide options** for different scenarios
- **Reference specific Superset features** by name
- **Link to related tools** when appropriate
#### Context Awareness
```python
@prompt("analytics_extension.context_aware_guide")
async def context_aware_guide(ctx: Context) -> str:

View File

@@ -36,9 +36,9 @@ This page serves as a registry of community-created Superset extensions. These e
| [SQL Lab Export to Parquet](https://github.com/rusackas/superset-extensions/tree/main/sqllab_parquet) | Export SQL Lab query results directly to Apache Parquet format with Snappy compression. | Evan Rusackas | <a href="/img/extensions/parquet-export.png" target="_blank"><img src="/img/extensions/parquet-export.png" alt="SQL Lab Export to Parquet" width="120" /></a> |
| [SQL Lab Query Comparison](https://github.com/michael-s-molina/superset-extensions/tree/main/query-comparison) | A SQL Lab extension that enables side-by-side comparison of query results across different tabs, with GitHub-style diff visualization showing added/removed rows and columns. | Michael S. Molina | <a href="/img/extensions/query-comparison.png" target="_blank"><img src="/img/extensions/query-comparison.png" alt="Query Comparison" width="120" /></a> |
| [SQL Lab Result Stats](https://github.com/michael-s-molina/superset-extensions/tree/main/result-stats) | A SQL Lab extension that automatically computes statistics for query results, providing type-aware analysis including numeric metrics (min, max, mean, median, std dev), string analysis (length, empty counts), and date range information. | Michael S. Molina | <a href="/img/extensions/result-stats.png" target="_blank"><img src="/img/extensions/result-stats.png" alt="Result Stats" width="120" /></a> |
| [Editor Snippets](https://github.com/michael-s-molina/superset-extensions/tree/main/editor-snippets) | A SQL Lab extension for managing and inserting reusable code snippets into the editor, with server-side persistence per user. | Michael S. Molina | <a href="/img/extensions/editor-snippets.png" target="_blank"><img src="/img/extensions/editor-snippets.png" alt="Editor Snippets" width="120" /></a> |
| [Editor Snippets](https://github.com/michael-s-molina/superset-extensions/tree/main/editor-snippets) | A SQL Lab extension for managing and inserting reusable code snippets into the editor, with server-side persistence per user. | Michael S. Molina | <a href="/img/extensions/editor-snippets.png" target="_blank"><img src="/img/extensions/editor-snippets.png" alt="Editor Snippets" width="120" /></a> |
| [SQL Lab Query Estimator](https://github.com/michael-s-molina/superset-extensions/tree/main/query-estimator) | A SQL Lab panel that analyzes query execution plans to estimate resource impact, detect performance issues like Cartesian products and high-cost operations, and visualize the query plan tree. | Michael S. Molina | <a href="/img/extensions/query-estimator.png" target="_blank"><img src="/img/extensions/query-estimator.png" alt="Query Estimator" width="120" /></a> |
| [Editors Bundle](https://github.com/michael-s-molina/superset-extensions/tree/main/editors-bundle) | A Superset extension that demonstrates how to provide custom code editors for different languages. This extension showcases the editor contribution system by registering alternative editors that can replace Superset's default Ace editor. | Michael S. Molina | <a href="/img/extensions/editors-bundle.png" target="_blank"><img src="/img/extensions/editors-bundle.png" alt="Editors Bundle" width="120" /></a> |
| [Editors Bundle](https://github.com/michael-s-molina/superset-extensions/tree/main/editors-bundle) | A Superset extension that demonstrates how to provide custom code editors for different languages. This extension showcases the editor contribution system by registering alternative editors that can replace Superset's default Ace editor. | Michael S. Molina | <a href="/img/extensions/editors-bundle.png" target="_blank"><img src="/img/extensions/editors-bundle.png" alt="Editors Bundle" width="120" /></a> |
## How to Add Your Extension

View File

@@ -37,6 +37,7 @@ FEATURE_FLAGS = {
```
When GTF is disabled:
- The Task List UI menu item is hidden
- The `/api/v1/task/*` endpoints return 404
- Calling or scheduling a `@task`-decorated function raises `GlobalTaskFrameworkDisabledError`
@@ -79,10 +80,10 @@ print(task.status) # "success"
### Async vs Sync Execution
| Method | When to Use |
|--------|-------------|
| `.schedule()` | Long-running operations, background processing, when you need to return immediately |
| Direct call | Short operations, when deduplication matters, when you need the result before responding |
| Method | When to Use |
| ------------- | ---------------------------------------------------------------------------------------- |
| `.schedule()` | Long-running operations, background processing, when you need to return immediately |
| Direct call | Short operations, when deduplication matters, when you need the result before responding |
Both execution modes provide the same task features: deduplication, progress tracking, cancellation, and visibility in the Task List UI. The difference is whether execution happens in a Celery worker (async) or inline (sync).
@@ -100,15 +101,15 @@ PENDING ──→ IN_PROGRESS ────→ SUCCESS
└─────────────┴──────────→ ABORTED (user cancel)
```
| Status | Description |
|--------|-------------|
| `PENDING` | Queued, awaiting execution |
| `IN_PROGRESS` | Executing |
| `ABORTING` | Abort/timeout triggered, abort handlers running |
| `SUCCESS` | Completed successfully |
| `FAILURE` | Failed with error or abort/cleanup handler exception |
| `ABORTED` | Cancelled by user/admin |
| `TIMED_OUT` | Exceeded configured timeout |
| Status | Description |
| ------------- | ---------------------------------------------------- |
| `PENDING` | Queued, awaiting execution |
| `IN_PROGRESS` | Executing |
| `ABORTING` | Abort/timeout triggered, abort handlers running |
| `SUCCESS` | Completed successfully |
| `FAILURE` | Failed with error or abort/cleanup handler exception |
| `ABORTED` | Cancelled by user/admin |
| `TIMED_OUT` | Exceeded configured timeout |
## Context API
@@ -139,11 +140,11 @@ Call `update_task()` once per iteration for best performance. Frequent DB writes
The `progress` parameter accepts three formats:
| Format | Example | Display |
|--------|---------|---------|
| Format | Example | Display |
| ----------------- | ------------------- | ---------------------- |
| `tuple[int, int]` | `progress=(3, 100)` | 3 of 100 (3%) with ETA |
| `float` (0.0-1.0) | `progress=0.5` | 50% with ETA |
| `int` | `progress=42` | 42 processed |
| `float` (0.0-1.0) | `progress=0.5` | 50% with ETA |
| `int` | `progress=42` | 42 processed |
:::tip
Use the tuple format `(current, total)` whenever possible. It provides the richest information to users: showing both the count and percentage, while still computing ETA automatically.
@@ -159,10 +160,10 @@ In the Task List UI, when a payload is defined, an info icon appears in the **De
Register handlers to run cleanup logic or respond to abort requests:
| Handler | When it runs | Use case |
|---------|--------------|----------|
| `on_cleanup` | Always (success, failure, abort) | Release resources, close connections |
| `on_abort` | When task is aborted | Set stop flag, cancel external operations |
| Handler | When it runs | Use case |
| ------------ | -------------------------------- | ----------------------------------------- |
| `on_cleanup` | Always (success, failure, abort) | Release resources, close connections |
| `on_abort` | When task is aborted | Set stop flag, cancel external operations |
```python
@task
@@ -187,6 +188,7 @@ Multiple handlers of the same type execute in LIFO order (last registered runs f
**All registered handlers will always be attempted, even if one fails.** This ensures that a failure in one handler doesn't prevent other handlers from running their cleanup logic.
For example, if you have three cleanup handlers and the second one throws an exception:
1. Handler 3 runs ✓
2. Handler 2 throws an exception ✗ (logged, but execution continues)
3. Handler 1 runs ✓
@@ -200,6 +202,7 @@ Write handlers to be independent and self-contained. Don't assume previous handl
## Making Tasks Abortable
When users click **Cancel** in the Task List, the system decides whether to **abort** (stop) the task or **unsubscribe** (remove the user from a shared task). Abort occurs when:
- It's a private or system task
- It's a shared task and the user is the last subscriber
- An admin checks **Force abort** to stop the task for all subscribers
@@ -229,6 +232,7 @@ def abortable_task(items: list[str]) -> None:
```
**Key points:**
- Registering `on_abort` marks the task as abortable and starts the abort listener
- The abort handler fires automatically when abort is triggered
- Use a flag pattern to gracefully stop processing at safe points
@@ -283,11 +287,11 @@ The timeout timer starts when the task begins executing (status changes to `IN_P
### Timeout Precedence
| Source | Priority | Example |
|--------|----------|---------|
| `TaskOptions.timeout` | Highest | `options=TaskOptions(timeout=600)` |
| `@task(timeout=...)` | Default | `@task(timeout=300)` |
| Not set | No timeout | Task runs indefinitely |
| Source | Priority | Example |
| --------------------- | ---------- | ---------------------------------- |
| `TaskOptions.timeout` | Highest | `options=TaskOptions(timeout=600)` |
| `@task(timeout=...)` | Default | `@task(timeout=300)` |
| Not set | No timeout | Task runs indefinitely |
Call-time options always override decorator defaults, allowing tasks to have sensible defaults while permitting callers to extend or shorten the timeout for specific use cases.
@@ -345,11 +349,11 @@ def shared_task(): ...
def system_task(): ...
```
| Scope | Visibility | Cancel Behavior |
|-------|------------|-----------------|
| `PRIVATE` | Creator only | Cancels immediately |
| `SHARED` | All subscribers | Last subscriber cancels; others unsubscribe |
| `SYSTEM` | Admins only | Admin cancels |
| Scope | Visibility | Cancel Behavior |
| --------- | --------------- | ------------------------------------------- |
| `PRIVATE` | Creator only | Cancels immediately |
| `SHARED` | All subscribers | Last subscriber cancels; others unsubscribe |
| `SYSTEM` | Admins only | Admin cancels |
## Task Cleanup
@@ -393,11 +397,11 @@ By default, abort detection and sync join-and-wait use database polling. Configu
### TaskContext Methods
| Method | Description |
|--------|-------------|
| `update_task(progress, payload)` | Update progress and/or custom payload |
| `on_cleanup(handler)` | Register cleanup handler |
| `on_abort(handler)` | Register abort handler (makes task abortable) |
| Method | Description |
| -------------------------------- | --------------------------------------------- |
| `update_task(progress, payload)` | Update progress and/or custom payload |
| `on_cleanup(handler)` | Register cleanup handler |
| `on_abort(handler)` | Register abort handler (makes task abortable) |
### TaskOptions
@@ -429,6 +433,7 @@ def risky_task() -> None:
```
On failure, the framework records:
- `error_message`: Exception message
- `exception_type`: Exception class name
- `stack_trace`: Full traceback (visible when `SHOW_STACKTRACE=True`)