Skip to main content
Edit this page on GitHub

开发指南

贡献文档

最新的文档和教程可在 https://superset.apache.org/ 获取。

文档站点使用 Docusaurus 2 构建,这是一个现代的静态网站生成器,其源代码位于 ./docs 目录中。

本地开发

要为文档站点设置具有热重载的本地开发环境:

cd docs
yarn install # 安装 NPM 依赖
yarn start # 在 http://localhost:3000 启动开发服务器

构建

要创建并提供文档站点的生产构建:

yarn build
yarn serve

部署

master 分支的提交会触发文档站点的重新构建和重新部署。提交以 docs: 前缀修改文档的拉取请求。

创建可视化插件

Superset 中的可视化功能使用 JavaScript 或 TypeScript 实现。Superset 预装了多种可视化类型(以下简称“viz 插件”),这些插件可以在 superset-frontend/plugins 目录下找到。Viz 插件在 superset-frontend/src/visualizations/presets/MainPreset.js 中添加到应用程序中。Superset 项目始终欢迎审查高质量的新 viz 插件提案。然而,对于高度定制的 viz 类型,建议维护 Superset 的一个分支,并手动添加自定义构建的 viz 插件。

注意: 有关创建和部署自定义可视化插件的额外社区生成资源可以在 Superset Wiki 上找到。

前提条件

为了创建新的 viz 插件,您需要以下内容:

  • 运行 MacOS 或 Linux(Windows 未正式支持,但可能有效)
  • Node.js 16
  • npm 7 或 8

还建议对 React 和 npm/Node 系统有一般性的熟悉。

创建一个简单的 Hello World viz 插件

要开始,您需要 Superset Yeoman 生成器。建议使用与您使用的 Superset 版本一起提供的模板版本。可以通过以下方式安装:

npm i -g yo
cd superset-frontend/packages/generator-superset
npm i
npm link

之后,您可以继续创建您的 viz 插件。为您的 viz 插件创建一个新目录,前缀为 superset-plugin-chart,并运行 Yeoman 生成器:

mkdir /tmp/superset-plugin-chart-hello-world
cd /tmp/superset-plugin-chart-hello-world

初始化 viz 插件:

yo @superset-ui/superset

之后,生成器会询问几个问题(默认值应该可以):

$ yo @superset-ui/superset
_-----_ ╭──────────────────────────╮
| | │ Welcome to the │
|--(o)--| │ generator-superset │
`---------´ │ generator! │
( _´U`_ ) ╰──────────────────────────╯
/___A___\ /
| ~ |
__'.___.'__
´ ` |° ´ Y `
? Package name: superset-plugin-chart-hello-world
? Description: Hello World
? What type of chart would you like? Time-series chart
create package.json
create .gitignore
create babel.config.js
create jest.config.js
create README.md
create tsconfig.json
create src/index.ts
create src/plugin/buildQuery.ts
create src/plugin/controlPanel.ts
create src/plugin/index.ts
create src/plugin/transformProps.ts
create src/types.ts
create src/SupersetPluginChartHelloWorld.tsx
create test/index.test.ts
create test/__mocks__/mockExportString.js
create test/plugin/buildQuery.test.ts
create test/plugin/transformProps.test.ts
create types/external.d.ts
create src/images/thumbnail.png

要构建 viz 插件,请运行以下命令:

npm i --force
npm run build

或者,要在开发模式下运行 viz 插件(=每当更改时重新构建),请使用以下命令启动开发服务器:

npm run dev

要将包添加到 Superset,请转到 Superset 源文件夹中的 superset-frontend 子目录并运行

npm i -S /tmp/superset-plugin-chart-hello-world

如果您将包发布到 npm,自然也可以直接从那里安装。之后,编辑 superset-frontend/src/visualizations/presets/MainPreset.js 并进行以下更改:

import { SupersetPluginChartHelloWorld } from 'superset-plugin-chart-hello-world';

以导入 viz 插件,并在传递给 plugins 属性的数组中稍后添加以下内容:

new SupersetPluginChartHelloWorld().configure({ key: 'ext-hello-world' }),

之后,viz 插件应该会在您运行 Superset 时显示,例如开发服务器:

npm run dev-server

测试

Python 测试

所有Python测试都在tox这一标准化测试框架中进行。 所有Python测试可以通过tox的任意环境来运行,具体操作如下:

tox -e <environment>

例如:

tox -e py38

或者,你也可以通过以下方式运行单个文件中的所有测试:

tox -e <environment> -- tests/test_file.py

或者针对特定测试:

tox -e <environment> -- tests/test_file.py::TestClassName::test_method_name

请注意,测试环境使用临时目录来定义SQLite数据库,这些数据库在每次调用测试命令组之前都会被清除。

Superset代码库中还包含一个用于运行Python集成测试的实用脚本。README文件可以在这里找到

例如,要运行所有集成测试,请从根目录运行此脚本:

scripts/tests/run.sh

你可以使用pytest来运行位于'./tests/unit_tests'中的单元测试。这是一种无需任何数据库设置即可运行独立测试的简单方法:

pytest ./link_to_test.py

使用本地Presto连接进行测试

如果你碰巧更改了Presto/Trino的数据库引擎规范,你可以使用Docker运行本地Presto集群:

docker run -p 15433:15433 starburstdata/presto:350-e.6

然后更新SUPERSET__SQLALCHEMY_EXAMPLES_URI以指向本地Presto集群:

export SUPERSET__SQLALCHEMY_EXAMPLES_URI=presto://localhost:15433/memory/default

前端测试

我们使用JestEnzyme来测试TypeScript/JavaScript。可以通过以下方式运行测试:

cd superset-frontend
npm run test

要运行单个测试文件:

npm run test -- path/to/file.js

e2e集成测试

我们使用Cypress进行端到端集成测试。一个快速入门的简单选项是利用tox在隔离环境中运行整个测试套件。

tox -e cypress

或者,你可以通过以下步骤在开发环境中进行低层次的设置:

首先设置Python/Flask后端:

export SUPERSET_CONFIG=tests.integration_tests.superset_test_config
export SUPERSET_TESTENV=true
export CYPRESS_BASE_URL="http://localhost:8081"
superset db upgrade
superset load_test_users
superset init
superset load-examples --load-test-data
superset run --port 8081

在另一个终端中,准备前端并运行Cypress测试:

cd superset-frontend
npm run build-instrumented

cd cypress-base
npm install

# 通过无头Chrome浏览器运行测试(需要Chrome 64+)
npm run cypress-run-chrome

# 运行特定文件中的测试
npm run cypress-run-chrome -- --spec cypress/e2e/explore/link.test.ts

# 运行特定文件并启用视频录制
npm run cypress-run-chrome -- --spec cypress/e2e/dashboard/index.test.js --config video=true

# 打开Cypress UI
npm run cypress-debug

# 若要指向不同于默认URL(http://localhost:8088)的其他URL,请在运行脚本前设置环境变量
# 例如,CYPRESS_BASE_URL="http://localhost:9000"
CYPRESS_BASE_URL=<your url> npm run cypress open

参见superset-frontend/cypress_build.sh

作为替代方案,你可以使用docker compose环境进行测试:

确保你在/etc/hosts文件中添加了以下行: 127.0.0.1 db

如果你已经启动了Docker环境,请使用以下命令确保数据库实例为全新状态: docker compose down -v

启动环境:

CYPRESS_CONFIG=true docker compose up

它将在端口8088上提供后端和前端服务。

运行Cypress测试:

cd cypress-base
npm install
npm run cypress open

调试服务器应用

按照以下说明调试在Docker容器内运行的Flask应用。

首先在./docker-compose.yaml文件中添加以下内容:

superset:
env_file: docker/.env
image: *superset-image
container_name: superset_app
command: ["/app/docker/docker-bootstrap.sh", "app"]
restart: unless-stopped
+ cap_add:
+ - SYS_PTRACE
ports:
- 8088:8088
+ - 5678:5678
user: "root"
depends_on: *superset-depends-on
volumes: *superset-volumes
environment:
CYPRESS_CONFIG: "${CYPRESS_CONFIG}"

像往常一样启动Superset:

docker compose up

将所需的库和包安装到Docker容器中:

进入superset_app容器:

docker exec -it superset_app /bin/bash
root@39ce8cf9d6ab:/app#

在容器内运行以下命令:

apt update
apt install -y gdb
apt install -y net-tools
pip install debugpy

查找Flask进程的PID。请确保使用第一个PID。每次更改Python代码时,Flask应用都会重新生成一个子进程。因此,使用第一个PID非常重要。

ps -ef

UID PID PPID C STIME TTY TIME CMD
root 1 0 0 14:09 ? 00:00:00 bash /app/docker/docker-bootstrap.sh app
root 6 1 4 14:09 ? 00:00:04 /usr/local/bin/python /usr/bin/flask run -p 8088 --with-threads --reload --debugger --host=0.0.0.0
root 10 6 7 14:09 ? 00:00:07 /usr/local/bin/python /usr/bin/flask run -p 8088 --with-threads --reload --debugger --host=0.0.0.0

将debugpy注入到正在运行的Flask进程中。在此例中,PID为6。

python3 -m debugpy --listen 0.0.0.0:5678 --pid 6

验证debugpy是否在5678端口上监听

netstat -tunap

Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:5678 0.0.0.0:* LISTEN 462/python
tcp 0 0 0.0.0.0:8088 0.0.0.0:* LISTEN 6/python

现在您可以准备将调试器附加到进程中。使用VSCode,您可以配置一个启动配置文件.vscode/launch.json,如下所示。

{
"version": "0.2.0",
"configurations": [
{
"name": "Attach to Superset App in Docker Container",
"type": "python",
"request": "attach",
"connect": {
"host": "127.0.0.1",
"port": 5678
},
"pathMappings": [
{
"localRoot": "${workspaceFolder}",
"remoteRoot": "/app"
}
]
},
]
}

VSCode不会立即在断点处停止。我们已经附加到PID 6,但它还不知道任何子进程。为了“唤醒”调试器,您需要修改一个Python文件。这将触发Flask重新加载代码并创建一个新的子进程。VSCode将检测到这个新子进程,断点将被激活。

在Kubernetes环境中调试服务器应用

要在Kubernetes集群内的POD中调试运行的Flask,您需要确保POD以root用户运行并被授予SYS_TRACE能力。这些设置不应在生产环境中使用。

  securityContext:
capabilities:
add: ["SYS_PTRACE"]

更多详情请参见为容器设置能力

一旦POD以root用户运行并具有SYS_PTRACE能力,它将能够调试Flask应用。

您可以按照与docker compose相同的说明进行操作。进入POD并安装所需的库和包;gdb、netstat和debugpy。

通常在Kubernetes环境中,节点无法从集群外部访问。因此,VSCode将无法远程连接到Kubernetes节点上的5678端口。为了实现这一点,您需要创建一个将5678端口转发到本地机器的隧道。

kubectl port-forward  pod/superset-<some random id> 5678:5678

现在您可以使用与上面相同的配置启动VSCode调试器。VSCode将连接到127.0.0.1:5678,该端口由kubectl转发到远程Kubernetes POD。

Storybook

Superset包含一个Storybook,用于预览各种Superset组件的布局/样式及其变体。要打开并查看Storybook:

cd superset-frontend
npm run storybook

在为Superset贡献新的React组件时,请尝试在组件的jsx/tsx文件旁边添加一个Story。

贡献翻译

我们使用Flask-Babel来翻译Superset。 在Python文件中,我们使用以下 翻译函数 来自Flask-Babel

  • gettextlazy_gettext(通常别名为_):用于翻译单数字符串。
  • ngettext:用于翻译可能变为复数的字符串。
from flask_babel import lazy_gettext as _

然后将其包裹在可翻译的字符串上,例如_('Translate me')。 在提取过程中,传递给_的字符串字面量将被添加到每个语言生成的.po文件中,以便稍后进行翻译。

在运行时,_函数将返回给定字符串的当前语言的翻译,或者如果没有可用的翻译,则返回字符串本身。

在TypeScript/JavaScript中,技术类似: 我们导入t(简单翻译)、tn(包含数字的翻译)。

import { t, tn } from "@superset-ui/translation";

启用语言选择

LANGUAGES变量添加到您的superset_config.py中。拥有多个 option inside 将在导航栏右侧的 UI 中添加一个语言选择下拉菜单。

LANGUAGES = {
'en': {'flag': 'us', 'name': 'English'},
'fr': {'flag': 'fr', 'name': 'French'},
'zh': {'flag': 'cn', 'name': 'Chinese'},
}

创建新的语言字典

首先检查目标语言的语言代码是否已经存在。检查目标语言的两字母 ISO 639-1 代码是否已经存在于 superset/translations 目录中:

ls superset/translations | grep -E "^[a-z]{2}\/"

如果您的语言已经有预先存在的翻译,请跳到下一节。

以下语言已经由 Flask AppBuilder 支持,这将使将应用程序翻译成您的目标语言变得更加容易:Flask AppBuilder i18n 文档

要为新语言创建字典,首先确保安装了必要的依赖项:

pip install -r superset/translations/requirements.txt

然后运行以下命令,其中 LANGUAGE_CODE 替换为目标语言的语言代码:

pybabel init -i superset/translations/messages.pot -d superset/translations -l LANGUAGE_CODE

例如,要为芬兰语(语言代码 fi)添加翻译,请运行以下命令:

pybabel init -i superset/translations/messages.pot -d superset/translations -l fi

提取新的翻译字符串

在翻译工作期间,我们需要定期从后端和前端提取字符串,以编译所有需要翻译的字符串列表。这个过程不会自动发生,是收集字符串并将其放入 .po 文件中进行翻译的必要步骤,以便它们可以随后被编译。

这个脚本正是为此而设计的:

./scripts/translations/babel_update.sh

更新语言文件

运行以下命令以使用新提取的字符串更新语言文件。

 pybabel update -i superset/translations/messages.pot -d superset/translations --ignore-obsolete

然后,您可以在 superset/translation 下找到的文件中翻译收集到的字符串,每个语言有一个文件夹。您可以使用 Poedit 更方便地翻译 po 文件。这里有一个教程

要在 MacOS 上进行翻译,您可以通过 Homebrew 安装 poedit

brew install poedit

之后,只需启动 poedit 应用程序并打开 messages.po 文件。对于芬兰语翻译,这将是 superset/translations/fi/LC_MESSAGES/messages.po

应用翻译

为了使翻译在前端可用,我们需要将 PO 文件转换为一组 JSON 文件。要转换所有 PO 文件为格式化的 JSON 文件,您可以使用 build-translation 脚本

# 如果尚未安装依赖项,请先安装
cd superset-frontend/ && npm ci
# 编译前端的翻译
npm run build-translation

最后,为了使翻译生效,我们需要使用 pybabel 将翻译目录编译为后端的二进制 MO 文件。

# 在项目根目录中
pybabel compile -d superset/translations

代码检查

Python

我们使用 Pylint 进行代码检查,可以通过以下方式调用:

# 对于 python
tox -e pylint

在最佳实践方面,请避免全局禁用 Pylint 消息(通过 .pylintrc)或在文件头部禁用,尽管有一些例外情况。禁用应该在行内进行,因为它可以防止掩盖问题,并提供禁用该消息的原因的上下文。

此外,Python 代码使用 Black 自动格式化,该工具配置为预提交钩子。还有许多编辑器集成

TypeScript

cd superset-frontend
npm ci
# 运行 eslint 检查
npm run eslint -- .
# 运行 tsc (typescript) 检查
npm run type

如果使用带有 vscode 的 eslint 扩展,请将以下内容放入工作区 settings.json 文件中:

"eslint.workingDirectories": [
"superset-frontend"
]