開發指南
貢獻文件
最新的文件和教學可在 https://superset.dev.org.tw/ 取得。
文件網站是使用 Docusaurus 2 建立的,這是一個現代靜態網站產生器,其原始碼位於 ./docs
。
本地開發
要為文件網站設定具有熱重載功能的本地開發環境
cd docs
yarn install # Installs NPM dependencies
yarn start # Starts development server at https://127.0.0.1:3000
建置
要建立並提供文件網站的生產版本
yarn build
yarn serve
部署
對 master
的提交會觸發文件網站的重建和重新部署。提交修改文件的 pull request 時,請加上 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 Generator。建議使用與您使用的 Superset 版本一起發布的範本版本。可以透過執行以下操作來安裝:
npm i -g yo
cd superset-frontend/packages/generator-superset
npm i
npm link
之後,您可以繼續建立您的 viz 外掛程式。使用字首 superset-plugin-chart
為您的 viz 外掛程式建立新目錄,並執行 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' }),
之後,當您執行 Superset(例如開發伺服器)時,viz 外掛程式應該會出現
npm run dev-server
測試
Python 測試
所有 python 測試都是在 tox 這個標準化的測試框架中進行的。可以使用 tox 的任何 環境來執行所有 python 測試,透過
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 整合測試。可以在這裡找到讀我檔案
例如,若要執行所有整合測試,請從根目錄執行此指令碼
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://127.0.0.1:15433/memory/default
前端測試
我們使用 Jest 和 Enzyme 來測試 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="https://127.0.0.1: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
# run tests via headless Chrome browser (requires Chrome 64+)
npm run cypress-run-chrome
# run tests from a specific file
npm run cypress-run-chrome -- --spec cypress/e2e/explore/link.test.ts
# run specific file with video capture
npm run cypress-run-chrome -- --spec cypress/e2e/dashboard/index.test.js --config video=true
# to open the cypress ui
npm run cypress-debug
# to point cypress to a url other than the default (https://127.0.0.1:8088) set the environment variable before running the script
# e.g., CYPRESS_BASE_URL="https://127.0.0.1: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
的以下 翻譯函式
gettext
和lazy_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
。在其中加入一個以上的選項,將會在導覽列右側的 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
指令碼
# Install dependencies if you haven't already
cd superset-frontend/ && npm ci
# Compile translations for the frontend
npm run build-translation
最後,為了讓翻譯生效,我們需要使用 pybabel
將翻譯目錄編譯為後端的二進制 MO 檔案。
# inside the project root
pybabel compile -d superset/translations
程式碼檢查
Python
我們使用 Pylint 進行程式碼檢查,可以透過以下方式叫用
# for python
tox -e pylint
就最佳實務而言,請避免全域(透過 .pylintrc
)或在檔案標頭的頂層全面停用 Pylint 訊息,儘管有一些例外情況。應內嵌停用,因為這樣可以防止遮蓋問題,並提供停用該訊息的原因。
此外,Python 程式碼會使用 Black 自動格式化,該程式碼會設定為預先提交勾點。還有許多 編輯器整合
TypeScript
cd superset-frontend
npm ci
# run eslint checks
npm run eslint -- .
# run tsc (typescript) checks
npm run type
如果使用 vscode 的 eslint 擴充功能,請將以下內容放入您的工作區 settings.json
檔案中
"eslint.workingDirectories": [
"superset-frontend"
]