# 如何自行建構 Python 的官方文件,並將其內文字體大小調大
紀錄如何於 Docker 容器環境自行建構 Python 的官方文件以滿足文字大小客製需求

[TOC]
## <ruby>問題<rp>(</rp><rt>Problem</rt><rp>)</rp></ruby>
* Python 官方文件的 PDF 版本在 reMarkable 電子紙平板電腦上呈現出來的內文字元大小偏小
* reMarkable 的 EPUB 支援有限,無法正常開啟/呈現部份電子書
## <ruby>解決方案<rp>(</rp><rt>Solution</rt><rp>)</rp></ruby>
手動建構一個字型與版型客製過的 Python 說明文件,改進 Python 文件在 reMarkable 電子紙平板電腦上的閱覽體驗
## <ruby>前備條件<rp>(</rp><rt>Prerequisites</rt><rp>)</rp></ruby>
以下說明完成本流程所需的前備條件:
* 您須已安裝近期版本的 [Docker Engine](https://docs.docker.com/engine/) {容器執行環境|container runtime}以創建建構文件用的作業系統容器
* 您須可以訪問{網際網路|internet}以獲取建構文件所需要的軟體
* 您須有基本的 GNU+Linux 作業系統操作經驗,包含但不限於:
+ {絕對路徑|absolute path}與{相對路徑|relative path}的理解
+ GNU Bash {殼層|shell}操作界面的使用
## <ruby>重現環境<rp>(</rp><rt>Reproducing environment</rt><rp>)</rp></ruby>
以下說明確認可以重現本教學內容的具體環境細節:
### <ruby>主端<rp>(</rp><rt>host</rt><rp>)</rp></ruby>作業系統
Ubuntu 23.10
### Docker Engine
24.0.5
### 建構文件所使用的 Python 軟體來源碼
3.12.2
## 取得 Python 來源程式碼<ruby>封存檔<rp>(</rp><rt>archive</rt><rp>)</rp></ruby>
1. 至 [Python 官方網站軟體下載頁](https://www.python.org/downloads/)選擇要下載的 Python 版本:

1. 然後於頁面下方的 Files 區塊選擇任一作業系統欄位為「Source release」的軟體來源碼封存檔下載連結下載 Python 的軟體來源碼封存檔:

於本教學中我們選擇 XZ 壓縮方式的軟體來源碼封存檔進行下載,因為 XZ 壓縮演算法的壓縮率較好故下載檔案的所需時間較少。
## <ruby>解開<rp>(</rp><rt>extract</rt><rp>)</rp></ruby> Python 來源程式碼封存檔
使用偏好的封存檔操作應用軟體將下載的軟體來源碼封存檔解開
:::info
**備註:** 您另可使用 [GNU Tar](https://www.gnu.org/software/tar/) 這個{命令列界面|command-line interface}的封存檔操作工具進行封存檔的解開操作:
```bash
cd /path/to/extraction/destination/dir
tar_opts=(
--extract
--file=/path/to/python-3.12.2.tar.xz
)
tar "${tar_opts[@]}"
```
:::
:::info
**附註:**
* `array=(...)` 為 Bash 的{索引式陣列|indexed array}語法,如上範例命令為例使用此語法可以以 Bash 註解的形式為命令參數新增說明文字
* `"${array[@]}"` 為 Bash 陣列的其中一種{參數展開|parameter expansion}語法,會將陣列中的元素以空白字元為分隔插入於展開處,您可以在展開命令前面加上 echo 命令(如 `echo "${array[@]}"`)以預覽展開結果
:::
## 創建並啟動一建構文件用的 Docker <ruby>容器<rp>(</rp><rt>container</rt><rp>)</rp></ruby>
為了確保重現環境的{一致性|consistency},我們使用 Docker 創建一個{作業系統容器|operating system container}並在其內進行文件建構作業
1. [啟動一<ruby>文字終端機<rp>(</rp><rt>text terminal</rt><rp>)</rp></ruby>模擬器應用軟體](https://hackmd.io/@elrm-tw/how-to-launch-a-text-terminal-emulator-application)
1. _以 root 身份_ 執行下列命令創建並啟動一<ruby>拋棄式<rp>(</rp><rt>ephemeral</rt><rp>)</rp></ruby>的 Ubuntu 22.04 容器:
```bash
python_source_dir=/path/to/Python-X.Y.Z
docker_run_opts=(
# 離開容器的作業階段時自動摧毀容器,節省磁碟空間使用
--rm
# 啟用標準輸入裝置(stdin)支援(使 bash shell 得以互動式模式運行)
--interactive
# 啟用偽 Teletype(TTY) 終端機模擬功能(使 bash shell 得以互動式模式正常運行)
--tty
# 創建一 bind-mount 式儲存空間(volume),將主端的 Python 軟體來源碼封存檔解開目錄
# 掛載到容器中的 /project 目錄下
--mount "type=bind,source=${python_source_dir},destination=/project"
)
docker run "${docker_run_opts[@]}" ubuntu:22.04
```
:::info
**附註:**
* 如您的使用者為 `docker` 使用者群組的成員則可以以一般使用者身份運行前述 `docker run` 命令(允許使用者直接訪問 Docker 服務[有潛在的安全風險](https://docs.docker.com/engine/security/#docker-daemon-attack-surface),應**僅開放給完全信任的使用者**使用)
* 如您位於僅能透過一 HTTP(S) 正向代理服務器才能連到網際網路的網路環境(如企業內部網路或是使用 [TetherFi](https://github.com/pyamsoft/tetherfi) 應用分享手機的行動網路給電腦),您可以在執行 `docker run` 命令前額外執行下列命令將本地的 HTTP(S) 正向代理服務設定(須已設定相關環境變數)繼承給 Docker 容器使用:
+ `docker_run_opts+=(--env http_proxy)`
+ `docker_run_opts+=(--env https_proxy)`
+ `docker_run_opts+=(--env no_proxy)`
:::
## 切換<ruby>作業目錄<rp>(</rp><rt>working directory</rt><rp>)</rp></ruby>至 Python 來源程式碼目錄樹中的說明文件目錄
執行下列命令切換作業目錄至 Python 來源程式碼目錄樹中的說明文件目錄
```bash
cd /project/Doc
```
## 改用本地的 Ubuntu <ruby>軟體庫鏡像服務<rp>(</rp><rt>software repository mirror</rt><rp>)</rp></ruby>
操作方式參閱《[如何改用本地的軟體庫鏡像服務 | 大家的 Linux 團圓飯](https://hackmd.io/@elrm-tw/how-to-switch-to-use-local-software-repository-mirror)》教學文件
## 更新<ruby>軟體包管理系統<rp>(</rp><rt>software package management system</rt><rp>)</rp></ruby>的本地<ruby>快取<rp>(</rp><rt>cache</rt><rp>)</rp></ruby>資料
操作方式參閱《[如何更新軟體包管理系統的本地快取資料 | 大家的 Linux 團圓飯](https://hackmd.io/@elrm-tw/how-to-refresh-package-manager-local-cache)》教學文件
## 安裝創建 Python <ruby>虛擬環境<rp>(</rp><rt>virtual environment</rt><rp>)</rp></ruby>的<ruby>依賴軟體<rp>(</rp><rt>software dependencies</rt><rp>)</rp></ruby>
因為 [Python 官方文件的 README 說明文件(Python-X.Y.Z/Doc/README)](https://github.com/python/cpython/tree/v3.12.2/Doc) 建議使用 Python 虛擬環境進行文件建構,所以我們要先安裝其依賴軟體:
* GNU Make {軟體建構自動化|build automation}工具
用於載入並執行建構 Python 說明文件用的 Makefile
* Python 第三版執行環境
提供 Python 虛擬環境的執行環境
* Python `venv` 模組
提供虛擬環境建構支援
於 Ubuntu 22.04 作業系統中可以 _以 root 身份_ 執行下列命令進行安裝:
```bash
pyvenv_dependency_pkgs=(
make
python3
python3-venv
)
apt install "${pyvenv_dependency_pkgs[@]}"
```
## 創建建構 Python 說明文件用的 Python 虛擬環境
執行下列命令以創建建構 Python 說明文件用的 Python 虛擬環境:
```bash
make venv
```
## 套用 Sphinx 配置修正:改用 US-Letter 紙張大小
Python 官方文件的 PDF 版本預設使用 A4 的紙張大小進行輸出,因 reMarkable 電子紙平板的螢幕解析度為 1872 x 1404,為 4:3 長寬比的螢幕,改用較接近 4:3 長寬比的 US-Letter 紙張大小較能夠避免頁面縮放貼合螢幕邊緣造成文字大小變小
編輯 conf.py Sphinx 配置檔,於「Options for LaTeX output」區域 `latex_elements` 字典的 `papersize` 鍵的值自 `a4` 修改為 `letter`
## 套用 Sphinx 配置修正:增加內文字體大小
編輯 conf.py Sphinx 配置檔,於「Options for LaTeX output」區域 `latex_elements` 字典的 `pointsize` 鍵的值自 `10pt` 修改為 `12pt`
:::info
**附註:** 這個設定似乎只支援以下三個數值:
* 10pt
* 11pt
* 12pt
:::
## 建構 LaTeX 版本文件
執行下列命令建構 LaTeX 格式的文件:
```bash
make latex
```
## 安裝建構 PDF 文件的依賴軟體
```bash
pdf_build_dependency_pkgs=(
# 提供 GNU Freefont 這個建構 PDF 文件需要的字型
fonts-freefont-otf
latexmk
texlive-xetex
texlive-fonts-recommended
xindy
)
apt_install_opts=(
# 不要安裝推薦安裝軟體包,避免非必要地下載太多實際上沒用到的軟體
--no-install-recommends
)
apt install "${apt_install_opts[@]}" "${pdf_build_dependency_pkgs[@]}"
```
## 自 LaTeX 版本文件建構 PDF 版本文件
切換作業目錄至 LaTeX 格式文件輸出目錄:
```bash
cd build/latex
```
然後執行下列命令建構 PDF 版本文件:
```bash
make all-pdf
```
順利的話建構好的 PDF 版本文件會存放於 build/latex 目錄中
## <ruby>參考資料<rp>(</rp><rt>References</rt><rp>)</rp></ruby>
以下列舉撰寫文文件期間所參考的第三方資源:
* [Download — Python 3.12.2 documentation](https://docs.python.org/3.12/download.html)
Python 官方提供的說明文件下載頁
* [Volumes | Docker Docs](https://docs.docker.com/storage/volumes/)
說明 `docker run` 命令的 `--volume` 參數值的格式與用法
* [Make - GNU Project - Free Software Foundation](https://www.gnu.org/software/make/)
說明 GNU Make 軟體的軟體分類為何
* [Second-generation CANVAS display](https://support.remarkable.com/s/article/Second-generation-CANVAS-display)
說明 reMarkable 2 電子紙平板的螢幕特性
* [Compare A4 with US Letter | Compare Paper Sizes | Paper Sizes](https://papersizes.io/compare?c1=a&p1=a4&c2=us&p2=letter)
以圖形化方式呈現 A4 跟 US Letter 紙張大小規格的差異
* [Letter Paper Size](https://papersizes.net/us/letter)
說明 US Letter 紙張大小規格的由來與應用
* [LaTeX font error: I can't find file `pzdr` - TeX - LaTeX Stack Exchange](https://tex.stackexchange.com/questions/50596/latex-font-error-i-cant-find-file-pzdr)
說明建構 PDF 版本文件時報錯找不到 pzdr 檔案時的解決方法
* [GNU FreeFont](https://www.gnu.org/software/freefont/)
說明 GNU FreeFont 這個建構 PDF 版本文件時會用到的字型家族的基本資訊
<style>
/* 調大旁註文字的字元大小 */
rt{
font-size: 10pt;
}
</style>