參與貢獻
感謝你有興趣貢獻 PyO3!歡迎所有人參與——請閱讀我們的行為準則以維持社群的正向與包容。
如果你正在尋找貢獻方向,請參考「開始參與貢獻」一節。如果你已找到想處理的特定議題並需要開發流程資訊,可參考「撰寫 Pull Request」一節。
若想熟悉程式碼庫,請參考 Architecture.md。
開始參與貢獻
歡迎從你感興趣的 PyO3 領域加入。我們使用 GitHub issues 記錄所有錯誤與想法。若你想處理某個議題,請隨時申請指派。
你可以在這裡瀏覽 PyO3 非公開部分的 API。
以下章節也提供一些適合開始貢獻 PyO3 的具體想法。
設定開發環境
要開發 PyO3,你需要在系統中安裝 Python 與 Rust。
- 我們建議使用 rustup 以便依專案選擇特定工具鏈。
- 也強烈建議使用 Pyenv 以便選擇特定 Python 版本。
- virtualenv 也可搭配或不搭配 Pyenv 使用特定已安裝的 Python 版本。
nox用於自動化多項 CI 任務。
使用 nox 進行測試、lint 等
Nox 用於自動化多項 CI 任務,也可在本地用來處理程式撰寫時的驗證工作。我們建議透過 nox 執行這些動作,以使用我們偏好的設定選項。你可以用 pip 安裝 nox 到全域 Python:pip install nox,或(建議)使用 pipx 安裝:pip install pipx、pipx install nox。
我們提供的主要 nox 指令如下:
nox -s test會執行完整的 Rust 與 Python 測試套件(>10 分鐘)nox -s test-rust -- skip-full會執行較短的 Rust 測試套件(2-3 分鐘)nox -s ruff會檢查 Python lint 並套用標準格式規則nox -s rustfmt會檢查基本 Rust lint 並套用標準格式規則nox -s rumdl會檢查指南中的 Markdownnox -s clippy會執行 clippy 提供 Rust 風格建議nox -s bench會對 Rust 程式碼進行效能基準測試nox -s codspeed會執行我們的 Rust 與 Python 效能測試套件nox -s coverage會分析測試覆蓋率並輸出coverage.json(或使用nox -s coverage lcov輸出lcov.info)nox -s check-guide會使用lychee檢查指南與文件註解中的所有連結。
使用 nox -l 列出可執行的完整子指令。
UI 測試
PyO3 使用 trybuild 來開發 UI 測試,以擷取某些巨集功能的 Rust 編譯器錯誤訊息。
Rust 編譯器的錯誤輸出會因是否安裝 rust-src 元件而不同。PyO3 的 CI 已安裝 rust-src,所以若要讓本地 UI 測試輸出一致,你也需要安裝它:
rustup component add rust-src
由於這些 UI 測試有多種 feature 組合,當你要全部更新(例如因新版 Rust 編譯器)時,使用 update-ui-tests nox session 會很有幫助:
nox -s update-ui-tests
可協助的方式
協助使用者找出錯誤
PyO3 Discord 伺服器 非常活躍,許多使用者對 PyO3 甚至 Rust 都很新。協助他們除錯是熟悉 PyO3 程式碼庫的好方法。
協助他人常會暴露錯誤、文件不足與缺漏的 API。建議立刻在 GitHub 開 issue,讓解法得以規劃並實作!
實作可直接開發的議題
解法清楚且尚未有人處理的議題會使用 needs-implementer 標籤。
若你覺得解法不夠清楚也別擔心!PyO3 核心貢獻者很樂意針對你的任何疑問提供指導,幫助你完成解法。
協助撰寫優質文件
PyO3 有使用 mdbook 的使用者指南,以及一般的 Rust API 文件。我們的目標是讓兩者都詳盡、易懂且保持最新。歡迎提出拉取請求來修正錯字、調整措辭、補充範例等。
目前文件有一些需要協助的特定重點領域:
- 與文件改進相關的議題會以 documentation 標籤追蹤。
- 並非所有 API 在建立時都有文件或範例。我們的目標是讓所有 PyO3 API 都有文件(#306)。若你看到某個 API 缺少文件,請撰寫並開啟 PR!
若要建置文件(包含所有功能),請安裝 nox 並執行
nox -s docs -- open
文件測試
我們在文件中使用大量程式碼區塊。變更時請執行 cargo test --doc 以確認文件測試仍可正常運作,或執行 cargo test 來跑包含文件測試在內的所有 Rust 測試。文件測試指南請見 https://doc.rust-lang.org/rustdoc/documentation-tests.html。
建置指南
你可以使用 mdbook 在本地建置以預覽使用者指南。
首先安裝 mdbook、mdbook-tabs 外掛,以及 nox。然後執行
nox -s build-guide -- --open
若要檢查指南中所有連結是否有效,請另行安裝 lychee 並改用 check-guide session:
nox -s check-guide
協助設計下一代 PyO3
尚未有明確解法的議題會使用 needs-design 標籤。
如果這些議題有你感興趣的,請加入該議題的討論!所有意見都很重要;若你還願意透過草稿 PR 嘗試 API 設計,那就更好了!
審查拉取請求
歡迎所有人對開放中的 PR 提出意見。請協助確保新的 PyO3 API 安全、效能良好、整潔且易用!
撰寫拉取請求
以下是撰寫 PR 時需要注意的幾點。
測試與持續整合
PyO3 儲存庫使用 GitHub Actions。若 CI 未通過,PR 會被阻止合併。所有 Rust 與 Python 程式碼都會檢查格式化、lint 與測試(若格式化失敗,流水線會提早中止以節省資源)。此外,Rust 程式碼中的所有警告都不被允許(使用 RUSTFLAGS="-D warnings")。
測試會在最新穩定版 Rust 編譯器與所有支援的 Python 版本上執行,並以最低支援的 Rust 版本測試 Python 3.9。
如果你新增了功能,請將其加入 Cargo.toml* 中的 full 功能集合,以便在 CI 中進行測試。
你可以用 nox 自行執行 CI 管線的各項元件,請見上方測試章節。
變更文件化
我們使用 towncrier 為每次發行生成變更日誌。
要將你的變更納入發行說明,請在 newsfragments 目錄中建立一個或多個新聞項目。有效的新聞項目應儲存為 <PR>.<CATEGORY>.md,其中 <PR> 為拉取請求編號,<CATEGORY> 為下列其中之一:
packaging- 用於相依性變更與 Python/Rust 版本相容性變更added- 用於新增功能changed- 用於既有功能的修改或棄用removed- 用於移除的功能fixed- 用於被歸類為錯誤修復的「變更」功能
僅文件的 PR 不需要新聞項目;將 PR 標題以 docs: 開頭即可略過檢查。
風格指南
泛型程式碼
PyO3 有許多泛型 API 以提升易用性,但代價可能是泛型程式碼膨脹。在合理的情況下,請嘗試實作泛型函式的具體子部分。這有兩種形式:
- 若該具體子部分無法被其他函式重用,請命名為
inner並保留為函式內部的區域項。 - 若該具體子部分會被其他函式重用,建議命名為
_foo,並將其放在原泛型函式foo的下方。
FFI 呼叫
PyO3 使用原始指標對 Python 的 C API 進行大量 FFI 呼叫。能避免時請避免在運算式中使用指向暫時值的指標:
// 危險
pyo3::ffi::Something(name.to_object(py).as_ptr());
// 因為以下重構會造成 use-after-free 錯誤:
let name = name.to_object(py).as_ptr();
pyo3::ffi::Something(name)
改用先綁定安全擁有的 PyObject 包裝,再傳給 ffi 函式:
let name: PyObject = name.to_object(py);
pyo3::ffi::Something(name.as_ptr())
// name 在離開作用域後會自動釋放
Python 與 Rust 版本支援政策
PyO3 旨在維持足夠的相容性,讓以 PyO3 建置的 Python 擴充能在多數常見軟體包管理系統中可行。
為了讓軟體包維護者的工作更簡單,PyO3 會盡可能承諾僅在同一時間調整最低支援的 Rust 與 Python 版本。此升級僅會出現在 0.x 版本,約每年一次,並在最舊支援的 Python 版本到達生命週期終點後進行。(可參考 https://endoflife.date/python 了解時間表。)
以下為各語言的相容性指引,所有 PR 都應遵循。
Python
PyO3 支援所有官方支援的 Python 版本,以及最新的 PyPy3 版本。這些版本都會在 CI 中測試。
新增對新 CPython 版本的支援
如果你打算新增對 CPython 預發行版本的支援,以下是(非完整)檢查清單:
- 等待最後一個 alpha 版本(通常為 alpha7),因為 ABI 直到第一個 beta 版才有保證
- 在
.github/workflows/ci.yml中新增 prerelease_ver-dev(例如3.14-dev),並在noxfile.py、pyo3-ffi/Cargo.toml的[package.metadata.cpython]區段max-version,以及pyo3-ffi/build.rs的max中提升版本 - 為該版本新增 abi3-prerelease 功能(例如
abi3-py314)- 在
pyo3-build-config/Cargo.toml中,將 abi3-most_current_stable 設為 [“abi3-prerelease”],並將 abi3-prerelease 設為 [“abi3”] - 在
pyo3-ffi/Cargo.toml中,將 abi3-most_current_stable 設為 [“abi3-prerelease”, “pyo3-build-config/abi3-most_current_stable”],並將 abi3-prerelease 設為 [“abi3”, “pyo3-build-config/abi3-prerelease”] - 在
Cargo.toml中,將 abi3-most_current_stable 設為 [“abi3-prerelease”, “pyo3-ffi/abi3-most_current_stable”],並將 abi3-prerelease 設為 [“abi3”, “pyo3-ffi/abi3-prerelease”]
- 在
- 使用
#[cfg(Py_prerelease])(例如#[cfg(Py_3_14)])與#[cfg(not(Py_prerelease]))來標示 CPython 穩定分支與預發行版之間的變更 - 不要為 CPython 標頭中任何以
_開頭的函式、結構或全域變數新增 Rust 綁定 - 如需協助請聯絡 @ngoldbaum 與 @davidhewitt
Rust
PyO3 旨在使用最新的 Rust 語言功能,以盡可能提高實作效率。
最低支援的 Rust 版本會在提升 Python 與 Rust 版本的發行時決定。當時設定的最低 Rust 版本不會高於當前 Debian、RHEL 與 Alpine Linux 發行版隨附的最低 Rust 版本。
CI 會測試最新穩定版 Rust 與最低支援 Rust 版本。由於 Rust 的穩定性保證,這足以確認中間所有版本的支援。
效能基準測試
PyO3 有兩組效能基準測試用於評估部分效能面向。目前測試套件還很小——若你願意協助擴充,歡迎新增基準測試並開 PR!
首先,在 pyo3-benches 子目錄中有以 Rust 為基礎的基準測試。你可以透過以下方式執行:
nox -s bench
其次,pytests 子目錄中包含一個以 Python 為基礎的基準測試。更多資訊請見此處。
程式碼覆蓋率
你可以檢視 PyO3 測試涵蓋與未涵蓋的程式碼。我們目標是 100% 覆蓋率——如果你發現覆蓋不足,請檢查覆蓋率並補上測試!
- 首先,請確保已安裝 llvm-cov cargo 外掛。在與
nox搭配使用前,你可能需要先透過 cargo 執行外掛一次。
cargo install cargo-llvm-cov
cargo llvm-cov
- 接著用以下方式產生
lcov.info檔案
nox -s coverage -- lcov
你可以安裝 IDE 外掛來檢視覆蓋率。例如使用 VSCode:
- 安裝 coverage-gutters 外掛。
- 在 VSCode 的
settings.json加入以下設定:
{
"coverage-gutters.coverageFileNames": [
"lcov.info",
"cov.xml",
"coverage.xml",
],
"coverage-gutters.showLineCoverage": true
}
- 你現在應該可以看到綠色高亮代表已測試的程式碼,紅色高亮代表未測試的程式碼。
贊助此專案
目前沒有代表 PyO3 接受贊助的官方組織。若你想為 PyO3 生態系提供較大規模的資金支持,請透過 GitHub 或 Discord 與我們聯絡,我們可進一步討論。
此外,我們部分維護者有個人的 GitHub 贊助頁面,若你願意支持將非常感謝: