Python 套件的持續維護與版本控制至關重要,讓使用者在套件更新時程式碼仍能正常運作。本文詳細介紹版本控制的最佳實務,包含語義化版本控制的規則及主要、次要、修補版本的使用時機。同時說明如何使用 Read the Docs 自動建立和釋出套件檔案,並透過設定 .readthedocs.yml 組態檔來自定義檔案建置環境。此外,文章也示範如何使用 Poetry 管理套件版本,包含手動修改版本號和使用 poetry version 指令進行版本升級。最後,文章介紹如何使用 Python Semantic Release (PSR) 工具自動化版本升級流程,並搭配 Angular 提交訊息格式管理版本,以及釋出套件到 PyPI 的完整步驟。
釋出與版本控制
在前面的章節中,我們討論瞭如何從零開始開發一個 Python 套件,包括建立 Python 原始碼、開發測試框架、撰寫檔案,並透過 PyPI 釋出到線上。本章將介紹套件開發工作流程中的下一個步驟:更新您的套件。
7.1 版本編號
版本控制是指為您的套件的不同版本新增唯一的識別碼。這個識別碼可以是根據名稱或數字的,但大多數 Python 套件使用語義化版本控制。在語義化版本控制中,版本號由三個整數 A.B.C 組成,其中 A 是「主要」版本,B 是「次要」版本,C 是「修補」版本。軟體的第一個版本通常從 0.1.0 開始,然後從那裡遞增。
### 版本變更範例
| 發布型別 | 版本變更 | 描述 |
| --- | --- | --- |
| 主要版本 | 2.X.X -> 3.0.0 | 包含破壞性變更,例如 print 成為函式、整數除法結果變為浮點數等。 |
| 次要版本 | 3.8.X -> 3.9.0 | 新增功能和最佳化,例如新增字串方法來移除字首和字尾。 |
| 修補版本 | 3.9.5 -> 3.9.6 | 包含錯誤修復和維護更新,例如更新 str.format() 方法的錯誤訊息。 |
內容解密:
- 表格展示了 Python 的主要、次要和修補版本的變更範例。
- 主要版本的變更通常包含破壞性變更,需要使用者調整程式碼。
- 次要版本的變更包含新功能和最佳化,但保持向後相容。
- 修補版本的變更主要針對錯誤修復和維護更新。
版本控制的最佳實踐
大多數情況下,您會進行修補和次要版本的釋出。我們將在第 7.5 節中討論主要版本、破壞性變更以及如何棄用套件功能。
即使有上述,版本控制仍然需要您使用最佳判斷力。例如,小型套件可能會為每個修復的錯誤釋出一個修補版本,或為每個新增的功能釋出一個次要版本。相比之下,大型套件通常會將多個錯誤修復合併到一個修補版本中,或將多個功能合併到一個次要版本中。
為什麼需要版本控制?
- 確保使用者的程式碼不會因為套件更新而中斷。
- 提供清晰的變更記錄,幫助使用者瞭解更新內容。
- 有助於管理相依性,讓使用者可以選擇適合其專案的版本。
線上檔案託管
使用 Read the Docs 託管檔案
- 前往 Read the Docs 網站並建立帳戶。
- 點選「Import a Project」。
- 選擇「Import Manually」。
- 輸入專案詳細資訊,包括套件名稱、GitHub 儲存函式庫 URL 和預設分支(例如 main)。
- 點選「Next」並選擇「Build version」。
完成上述步驟後,您的檔案應該會成功在 Read the Docs 上建置,並且可以透過建置頁面上的「View Docs」按鈕存取。例如,pycounts 的檔案現在可以在 https://pycounts.readthedocs.io/en/latest/ 瀏覽。此檔案將在每次您推播變更到指定的預設分支時自動重新建置。
.readthedocs.yml 組態檔案的作用
- 指定 Read the Docs 建置檔案時使用的 Python 版本。
- 列出建置檔案所需的額外套件(在
docs/requirements.txt中指定)。
# .readthedocs.yml 示例
version: 2
sphinx:
configuration: docs/conf.py
python:
version: 3.8
install:
- requirements: docs/requirements.txt
內容解密:
.readthedocs.yml檔案是 Read the Docs 的組態檔案,用於指定建置環境和依賴項。sphinx.configuration指定了 Sphinx 檔案的組態檔案路徑。python.version指定了建置檔案時使用的 Python 版本。python.install部分列出了需要安裝的依賴項,以確保檔案能夠正確建置。
版本升級管理
在軟體開發過程中,版本控制是至關重要的一環。當準備發布新版本的套件時,如何有效地升級版本號是一個需要仔細考慮的問題。本章節將探討手動和自動兩種版本升級的方法。
手動版本升級
對於使用 Poetry 管理的專案,版本號儲存在 pyproject.toml 檔案中。假設我們要對 pycounts 套件進行修補版本的升級,可以直接在 pyproject.toml 檔案中手動修改版本號。
[tool.poetry]
name = "pycounts"
version = "0.1.1"
description = "Calculate word counts in a text file!"
authors = ["Tomas Beuzen"]
license = "MIT"
readme = "README.md"
內容解密:
tool.poetry部分定義了 Poetry 專案的基本資訊。version欄位指定了套件的當前版本。- 手動修改
version的值可以變更套件的版本號。
另一種方法是使用 Poetry 提供的 poetry version 命令來升級版本號。例如,執行 poetry version patch 可以將版本號從 0.1.0 升級到 0.1.1。
$ poetry version patch
Bumping version from 0.1.0 to 0.1.1
內容解密:
poetry version patch命令用於升級修補版本。- 執行該命令後,Poetry 自動更新
pyproject.toml中的version欄位。
自動版本升級
為了提高效率,可以使用工具自動化版本升級的過程。Python Semantic Release (PSR) 是一個根據 Git 提交訊息自動升級版本號的工具。
使用 PSR 的步驟:
安裝 PSR:首先,需要將 PSR 安裝為開發依賴。
$ poetry add --dev python-semantic-release組態 PSR:需要在
pyproject.toml中新增組態,告訴 PSR 版本號的儲存位置。[tool.semantic_release] version_variable = "pyproject.toml:version"內容解密:
[tool.semantic_release]部分是 PSR 的組態區塊。version_variable指定了版本號在pyproject.toml檔案中的位置。
使用 PSR 升級版本:執行
semantic-release version命令,PSR 會根據之前的 Git 提交訊息來決定如何升級版本號。
PSR 使用 Angular 提交訊息格式來解析提交訊息並決定版本升級的型別。例如:
fix型別的提交會觸發修補版本的升級。feat型別的提交會觸發次版本的升級。- 提交訊息中包含
BREAKING CHANGE:會觸發主要版本的升級。
$ git commit -m "fix(mod_plotting): fix confusing error message in plot_words"
$ semantic-release version -v DEBUG
內容解密:
- 提交訊息的格式對於 PSR 自動升級版本號至關重要。
-v DEBUG引數讓 PSR 輸出詳細的除錯資訊,有助於瞭解其工作過程。
透過使用 PSR,可以實作版本號的自動化管理,從而提高開發效率並減少人為錯誤。
釋出與版本控制
使用 semantic-release 自動版本控制
執行 $ semantic-release version -v DEBUG 指令後,系統會自動建立新的版本號。以下是執行的詳細步驟:
- 讀取目前版本號:系統會從
pyproject.toml檔案中讀取目前的版本號0.1.0。 - 評估版本更新:根據提交的 commit 訊息,系統會評估是否需要更新版本號。在這個例子中,commit 訊息為
fix(code): change confusing error...,被判定為需要進行 patch 版本更新。 - 更新版本號:系統會將版本號從
0.1.0更新為0.1.1。 - 寫入新的版本號:更新後的版本號會被寫入
pyproject.toml檔案中。 - 提交版本更新:系統會將更新後的版本號提交到 Git 儲存函式庫,並建立一個新的 tag。
程式碼範例
$ semantic-release version -v DEBUG
Creating new version
debug: get_current_version_by_config_file()
debug: Parsing current version: path=PosixPath('pyproject.toml')
debug: Regex matched version: 0.1.0
debug: get_current_version_by_config_file -> 0.1.0
Current version: 0.1.0
debug: evaluate_version_bump('0.1.0', None)
debug: parse_commit_message('fix(code): change confusing error... )
debug: parse_commit_message -> ParsedCommit(bump=1, type='fix')
debug: Commits found since last release: 1
debug: evaluate_version_bump -> patch
debug: get_new_version('0.1.0', 'patch')
debug: get_new_version -> 0.1.1
debug: set_new_version('0.1.1')
debug: Writing new version number: path=PosixPath('pyproject.toml')
debug: set_new_version -> True
debug: commit_new_version('0.1.1')
debug: commit_new_version -> [main d82fa3f] 0.1.1
debug: Author: semantic-release <semantic-release>
debug: 1 file changed, 5 insertions(+), 1 deletion(-)
debug: tag_new_version('0.1.1')
debug: tag_new_version ->
Bumping with a patch version to 0.1.1
內容解密:
semantic-release version -v DEBUG:執行 semantic-release 的版本控制指令,並開啟 DEBUG 模式以顯示詳細的執行過程。get_current_version_by_config_file():從pyproject.toml檔案中讀取目前的版本號。evaluate_version_bump('0.1.0', None):根據 commit 訊息評估是否需要更新版本號。parse_commit_message('fix(code): change confusing error... ):解析 commit 訊息以判斷需要進行的版本更新型別。get_new_version('0.1.0', 'patch'):計算新的版本號,在這個例子中是0.1.1。set_new_version('0.1.1'):將新的版本號寫入pyproject.toml檔案中。commit_new_version('0.1.1'):將更新後的版本號提交到 Git 儲存函式庫。tag_new_version('0.1.1'):為新的版本建立一個 tag。
釋出新版本的檢查清單
釋出新版本前,需要進行以下步驟:
Step 1:修改套件原始碼
在釋出新版本前,需要對套件的原始碼進行修改。例如,在 pycounts 套件中,我們新增了一個 datasets 模組,並升級了測試框架。
Step 2:記錄變更
在釋出新版本前,需要記錄所有的變更。例如,在 CHANGELOG.md 檔案中,我們記錄了以下變更:
# Changelog
<!--next-version-placeholder-->
## v0.2.0 (10/09/2021)
### Feature
- 新增 datasets 模組以載入範例資料
### Fix
- 檢查傳遞給 `plotting.plot_words()` 的引數型別
### Tests
- 為所有套件模組新增新的測試
## v0.1.0 (24/08/2021)
- 第一次釋出 `pycounts`
Step 3:更新版本號
可以使用 PSR 工具自動更新版本號。首先,需要安裝 PSR 作為開發相依性:
$ poetry add --dev python-semantic-release
然後,可以使用以下指令更新版本號:
$ semantic-release version
這個指令會根據 commit 訊息自動更新版本號。
程式碼範例(安裝 PSR)
$ poetry add --dev python-semantic-release
內容解密:
poetry add --dev python-semantic-release:將 PSR 安裝為開發相依性。- 使用 PSR 更新版本號:根據 commit 訊息自動更新版本號。
使用 Plantuml 圖表展示流程
此圖示展示了釋出新版本的流程,從修改套件原始碼到釋出新版本的每個步驟。
圖表說明:
- 節點 A:流程的開始。
- 節點 B:對套件原始碼進行必要的修改。
- 節點 C:將變更記錄在變更日誌中。
- 節點 D:使用 PSR 自動更新套件的版本號。
- 節點 E:完成所有準備步驟後,正式釋出新版本的套件。
發布與版本控制的完整流程
在軟體開發過程中,發布新版本是一個重要的里程碑。本章節將詳細介紹如何使用 semantic-release、poetry 和 pytest 等工具來發布和管理 Python 套件的新版本。
步驟 1-3:準備與版本更新
首先,使用 semantic-release version 命令來更新套件版本。這個命令會根據提交歷史自動計算出新的版本號。例如,從 0.1.0 更新到 0.2.0。
$ semantic-release version
Creating new version
Current version: 0.1.0
Bumping with a minor version to 0.2.0
內容解密:
semantic-release version命令用於自動更新版本號。- 版本號的更新規則依據提交歷史中的變更型別(如 feature、fix 等)來決定。
- 新版本號會被寫入
pyproject.toml檔案中,並且會建立一個新的 Git tag(如v0.2.0)。
步驟 4:執行測試與構建檔案
在發布新版本之前,需要確保套件的測試能夠透過,並且檔案能夠正確構建。
$ poetry install
Installing the current project: pycounts (0.2.0)
$ pytest tests/ --cov=pycounts
========================= test session starts =========================
---
-
---
---
coverage: platform darwin, python 3.9.6-final-0
---
-
---
-
---
Name Stmts Miss Cover
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
src/pycounts/__init__.py 2 0 100%
src/pycounts/data/__init__.py 0 0 100%
src/pycounts/datasets.py 5 0 100%
src/pycounts/plotting.py 12 0 100%
src/pycounts/pycounts.py 16 0 100%
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
TOTAL 35 0 100%
========================== 7 passed in 0.41s ==========================
內容解密:
- 使用
poetry install命令重新安裝套件,以確保使用的是最新版本。 - 使用
pytest和pytest-cov命令執行測試並檢查測試覆寫率。 - 確保所有測試都透過,並且測試覆寫率達到 100%。
接下來,檢查檔案是否能夠正確構建:
$ cd docs
$ make clean html
Running Sphinx
...
build succeeded.
The HTML pages are in _build/html.
內容解密:
- 使用
make clean html命令清除舊的檔案並重新構建。 - 確保檔案構建成功,並且沒有錯誤或警告。
步驟 5:標記版本與發布
使用 Git tag 標記新版本,並將變更推播到遠端倉函式庫。
$ git tag v0.2.0
$ git push
$ git push --tags
內容解密:
- 使用
git tag命令建立一個新的 tag,以標記新版本。 - 使用
git push和git push --tags命令將變更和新 tag 推播到遠端倉函式庫。
在 GitHub 上建立一個新的 release,並關聯到剛剛建立的 tag。
圖示:GitHub Release 流程
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
title Python套件版本控制釋出與維護
package "Git 版本控制" {
package "工作區域" {
component [工作目錄
Working Directory] as work
component [暫存區
Staging Area] as stage
component [本地倉庫
Local Repository] as local
component [遠端倉庫
Remote Repository] as remote
}
package "基本操作" {
component [git add] as add
component [git commit] as commit
component [git push] as push
component [git pull] as pull
}
package "分支管理" {
component [git branch] as branch
component [git merge] as merge
component [git rebase] as rebase
}
}
work --> add : 加入暫存
add --> stage : 暫存變更
stage --> commit : 提交變更
commit --> local : 版本記錄
local --> push : 推送遠端
remote --> pull : 拉取更新
branch --> merge : 合併分支
note right of stage
git status 查看狀態
git diff 比較差異
end note
@enduml此圖示展示了在 GitHub 上建立 release 的流程。
步驟 6:構建與發布套件到 PyPI
使用 poetry build 命令構建套件的發行版本。
$ poetry build
Building pycounts (0.2.0)
- Building sdist
- Built pycounts-0.2.0.tar.gz
- Building wheel
- Built pycounts-0.2.0-py3-none-any.whl
內容解密:
- 使用
poetry build命令構建套件的原始碼發行版(sdist)和 wheel 發行版。 - 發行版檔案將被生成在
dist目錄下。
先發布到 TestPyPI,以測試發布流程是否正確。
$ poetry publish -r test-pypi
內容解密:
- 使用
poetry publish命令發布套件到 TestPyPI。 - TestPyPI 用於測試發布流程,確保一切正常。
確認無誤後,再發布到 PyPI。
$ poetry publish
內容解密:
- 使用
poetry publish命令發布套件到 PyPI。 - 這將使套件可以被公眾安裝和使用。