推奨設定例¶
Pythonプロジェクト向けの推奨構成例(pyproject.toml・pre-commit・タスクランナー・CI設定)。 設定して実行するところから始める場合ははじめにを参照。
pyproject.toml¶
pyfltr本体の設定([tool.pyfltr])と、呼び出される各ツール(ruff / mypy / pytest)の設定を1つのpyproject.tomlにまとめた例。
preset = "latest": 各時点での推奨ツール構成。詳細はプリセット設定を参照python = true: Python系ツールのゲートを開ける。推奨ツール(ruff-format / ruff-check / mypy / pylint / pyright / pytest / uv-sort)を一式有効化する- Python系ツール一式は本体依存に同梱されているため、
uvx pyfltr単発で利用できる - dev依存に固定する場合は
uv add --dev "pyfltr[python]"(pip環境ではpip install pyfltr)を使う
- Python系ツール一式は本体依存に同梱されているため、
pylint-args: pylintに追加で渡す引数。--load-plugins=pylint_pydanticと--enable-error-code=unused-awaitable(mypy)は自動オプションで既定有効のため個別指定不要[tool.pylint."messages control"]: pylintのdisableリストをpyproject.tomlに集約することで、.pylintrcを別途配置する必要がなくなり設定の所在がpyproject.toml1ファイルにまとまる- ruffの
Dカテゴリがmissing-*-docstring相当を検出するため、 pylint側の同系ルールは無効化しても品質低下は招かない missing-class-docstringはテストクラスに対する儀礼的docstring付与を無効化するmissing-module-docstringは__init__.py等でモジュールdocstring要求を緩和する目的で無効化する
- ruffの
- ruffの
per-file-ignores: テストコード(**_test.py)とpackage init(__init__.py)のdocstring要求を除外する実用的な調整
uvx pyfltrでの実行ではpyproject.tomlにpyfltrを記述する必要はなく、[tool.pyfltr]セクションのみで完結する。
dev依存に固定する場合のみ[dependency-groups] devに"pyfltr[python]"を追加する(後置の併記例)。
[tool.pyfltr]
preset = "latest"
python = true
pylint-args = ["--jobs=4"]
[tool.pylint."messages control"]
disable = [
"broad-exception-caught",
"duplicate-code",
"fixme",
"invalid-name",
"line-too-long",
"logging-fstring-interpolation",
"logging-not-lazy",
"missing-class-docstring",
"missing-function-docstring",
"missing-module-docstring",
"no-else-return",
"too-few-public-methods",
"too-many-arguments",
"too-many-boolean-expressions",
"too-many-branches",
"too-many-instance-attributes",
"too-many-locals",
"too-many-nested-blocks",
"too-many-positional-arguments",
"too-many-public-methods",
"too-many-return-statements",
"too-many-statements",
]
[tool.ruff]
# https://docs.astral.sh/ruff/configuration/
line-length = 128
[tool.ruff.lint]
# https://docs.astral.sh/ruff/linter/#rule-selection
select = [
# pydocstyle
"D",
# pycodestyle
"E",
# Pyflakes
"F",
# pyupgrade
"UP",
# flake8-bugbear
"B",
# flake8-simplify
"SIM",
# flake8-import-conventions
"ICN",
# isort
"I",
]
ignore = [
"D107", # Missing docstring in `__init__`
"D415", # First line should end with a period
"D403", # First word of the first line should be properly capitalized(日本語docstringにそぐわないため)
]
[tool.ruff.lint.pydocstyle]
convention = "google"
[tool.ruff.lint.per-file-ignores]
"**_test.py" = ["D"]
"**/__init__.py" = ["D104"] # Missing docstring in public package
[tool.mypy]
# https://mypy.readthedocs.io/en/stable/config_file.html
allow_redefinition = true
check_untyped_defs = true
ignore_missing_imports = true
strict_optional = true
strict_equality = true
warn_no_return = true
warn_redundant_casts = true
warn_unused_configs = true
show_error_codes = true
[tool.pytest.ini_options]
# https://docs.pytest.org/en/latest/reference/reference.html#ini-options-ref
addopts = "--showlocals -p no:cacheprovider --maxfail=5 --durations=30 --durations-min=0.5 --timeout=60 -n 4"
log_level = "DEBUG"
xfail_strict = true
asyncio_mode = "strict"
asyncio_default_fixture_loop_scope = "session"
asyncio_default_test_loop_scope = "session"
--timeout=60はpytest-timeoutプラグインが必要。
-n 4はpytest-xdistプラグインが必要で、4プロセス並列でテストを実行する。
ランナー別の有効条件は次の通り。
python-runner = "direct"経路では、pyfltrのvenv配下のpytestを直接起動するため 本体依存のpytest-timeout・pytest-xdistがそのまま利用できるuvx pyfltrをuv.lock不在のディレクトリで実行する標準シナリオでは、uv経路の前提が満たされずshutil.whichによるdirectフォールバックが発生する- この場合もpyfltrの本体venv同梱のpytestが採用されるため本体依存のプラグインが有効
uv経路(既定)でcwdのuv.lockにpytestが登録されている場合は、 利用者プロジェクトのvenvでpytestが解決される- プロジェクト側に
pytest-timeout・pytest-xdistを導入する (uv add --dev pytest-timeout pytest-xdist等)
- プロジェクト側に
uvx経路(per-tool直接指定でpytest用の独立環境が生成される場合)は、 当該環境側へのpytest-timeout・pytest-xdistの導入が別途必要- pytest-xdistの並列実行下では、ポート番号・一時ファイル名・グローバル状態の競合に注意する
- 間欠失敗するテストは並列前提に修正するか
-p no:xdist等でxdist対象外へ退避させる
- 間欠失敗するテストは並列前提に修正するか
typosの許可語設定¶
プロジェクト固有の許可語がある場合はpyproject.tomlの[tool.typos]セクションに追記する。
typos-cliはpyproject.tomlの[tool.typos]を公式にサポートしているため、_typos.tomlを別ファイルとして管理する必要はない。
識別子(変数名・関数名)単位で許可したい場合は[tool.typos.default.extend-identifiers]を使う。
詳細はtypos公式ドキュメントを参照。
依存の脆弱性監査の有効化(任意)¶
依存パッケージの脆弱性をpyfltrの枠組みでまとめて監査したい場合はuv-auditを有効化する。
uv audit(uv 0.10.8以降)がpyproject.tomlを対象にPython依存の既知脆弱性を検査する。
外部脆弱性データベースへ問い合わせるためネットワーク接続が必須で結果が変動する。
ネットワークが不安定なCIで失敗扱いを避けたい場合はuv-audit-severity = "warning"で警告扱いに切り替える。
既定引数uv-audit-args = ["audit", "--frozen", "--no-progress"]は--frozenを含み、監査時にuv.lockを書き換えない。
脆弱性監査の結果はコード変更と無関係に外部データベースの更新で変動する。
このためコミット毎やpre-commitではなく、日次・週次の定期実行に向く。
監査ツールのみをまとめて実行する場合は--commands=auditを指定する。
GitHub Actionsではscheduleトリガーの専用ワークフローへ切り出し、
通常のpush/PR用CIへ混在させない構成を推奨する。
SARIF出力(--output-format=sarif)とgithub/codeql-action/upload-sarifを
組み合わせると、GitHub Code Scanningにアラート管理を委ねられる。
同一の脆弱性は1件のアラートに集約され、解消後の定期実行で自動クローズされる。
JS/TSを併用するプロジェクトでの推奨設定¶
JS/TSを併用するプロジェクトでは、js-runnerをプロジェクトのパッケージマネージャーに合わせる。
既定のpnpxはツールを都度取得するため、CIで毎回ダウンロードが発生する。
pnpmやnpmなど、プロジェクトで使用しているパッケージマネージャーを指定すると、
package.jsonで管理済みのパッケージを再利用できる。
pnpm / npm / yarn / directではtextlint-packagesは無視される(package.json側でインストールする前提のため)。
textlintのプリセットやルールもpackage.jsonのdevDependenciesで管理する。
詳細は設定項目(ツール別)の「js-runner経由で実行するツール」を参照。
.pre-commit-config.yaml¶
- repo: local
hooks:
- id: pyfltr
name: pyfltr
entry: uvx pyfltr fast
types_or: [python, markdown, toml]
require_serial: true
language: system
注意: default_language_versionにはプロジェクトが要求するPythonバージョンを指定する。
PEP 695型パラメーター構文(def f[T](): ...)を使用するプロジェクトではPython 3.12以上が必要。
バージョンが不一致だとcheck-astやdebug-statementsフックがSyntaxErrorで失敗する。
ポイント。
uvx pyfltr fast: uvがキャッシュするため2回目以降は実用速度で動作し、毎回最新版を取得して実行する- dev依存にpyfltrを加えている場合は
entry: uv run --frozen pyfltr fastに置き換えてもよい
- dev依存にpyfltrを加えている場合は
fast: mypy / pylint / pytestなど重いコマンドを除外した高速サブセット- formatterがファイルを修正しただけではフックを失敗と判定しない
types_or: 必要な種別を列挙する- markdownはtextlint / markdownlint、TOML(pyproject.toml)でuv-sort
require_serial: true: pyfltr自身が内部で並列化するため、pre-commit側での多重起動を抑止する
pre-commit統合の自動スキップなど双方向の挙動はトラブルシューティングを参照。
pyfltrとpre-commitの呼び出し経路¶
pyfltrはpre-commitを内部で呼び出し、pre-commitはpyfltrをフックとして呼び出す。
git commit経由でpre-commitが起動した場合は、pyfltrがPRE_COMMIT=1を検出して
内部のpre-commit統合を自動スキップし、二重実行を防ぐ。
sequenceDiagram
participant U as git commit
participant PC as pre-commit
participant PH as pre-commit-hooks
participant PF as pyfltr fast
U->>PC: フック起動
PC->>PH: check-yaml, trailing-whitespace等
PC->>PF: pyfltr fast(local hook)
Note over PF: PRE_COMMIT=1 検出で<br/>pre-commit統合をスキップ
PF->>PF: ruff-format, ruff-check等
逆にmake test等からpyfltr runを呼び出した場合は、pyfltr側がSKIP=pyfltr付きで
pre-commit runを変更ファイル指定(--files <対象>)で起動する。
各hook内部のtypes・types_or・files・excludeフィルタはファイル指定起動でも適用されるため、関係するhookのみ動作する。
これによりpre-commit-hooks(check-yaml等)を統合実行できる。
詳細な挙動と無効化手順はトラブルシューティングを参照。
タスクランナー¶
pyfltrを呼び出すタスクランナーの設定例。
言語を問わずuvx pyfltrを利用できる。
pre-commitはpyfltrの依存に含まれるため、uvx pre-commitで利用可能になる。
Makefile¶
uvx方式ではuvがキャッシュするため2回目以降は実用速度で動作し、毎回最新版を取得して実行できる。
.PHONY: format test
# フォーマット + 軽量lint(開発時の手動実行用。自動修正あり)
format:
uvx pyfltr fast
# 全チェック実行(これを通過すればコミット可能)
test:
uvx pyfltr run
dev依存にpyfltrを固定する運用ではUV_FROZENでlockfileを尊重しつつ、
uv sync後にuv run pyfltr ...を呼び出す形に置き換えることができる。
export UV_FROZEN := 1
help:
@cat Makefile
# 開発環境のセットアップ
setup:
uv sync --all-groups --all-extras
uvx pre-commit install
# 依存パッケージをアップグレードし全テスト実行
update:
env --unset UV_FROZEN uv sync --upgrade --all-groups
uvx pre-commit autoupdate
$(MAKE) test
# フォーマット + 軽量lint(開発時の手動実行用。自動修正あり)
format:
uv run pyfltr fast
# 全チェック実行(これを通過すればコミット可能)
test:
uv run pyfltr run
.PHONY: help setup update format test
mise.toml¶
言語を問わず利用可能。
[tools]
...
uv = "latest"
[tasks.setup]
description = "開発環境のセットアップ"
run = [
"...",
"uvx pre-commit install",
]
[tasks.format]
description = "フォーマット + 軽量lint(開発時の手動実行用。自動修正あり)"
run = [
"uvx pyfltr fast",
]
[tasks.test]
description = "全チェック (pyfltr run がpre-commitを内部で呼び出す)"
run = [
"uvx pyfltr run",
]
[tasks.ci]
description = "CI向け全チェック (差分検知で失敗)"
run = [
"uvx pyfltr ci",
]
ポイント:
setup: 開発環境のセットアップformat:pyfltr fast(fix段→formatter段→軽量linter段 + 内部pre-commit統合)を実行する- pre-commit-fastが既定でTrueのため、pre-commit-hooks(check-yaml等)もこの1コマンドで実行される
test: ローカル開発用pyfltr runがpre-commitを内部で呼び出すため、1コマンドで全チェックが完結する
ci: CI用pyfltr ciはformatter差分も含めて失敗扱いにする
.markdownlint-cli2.yaml¶
markdownlint-cli2が読み込む設定ファイル。$schemaを指定してエディタ補完を有効化する。
$schema: https://raw.githubusercontent.com/DavidAnson/markdownlint-cli2/v0.20.0/schema/markdownlint-cli2-config-schema.json
config:
# コードブロック/表を除外し、127文字を上限とする
line-length:
line_length: 127
code_blocks: false
tables: false
# コードブロック内でタブ文字を許可(Makefileなど用)
no-hard-tabs:
code_blocks: false
.textlintrc.yaml¶
textlintで技術文書向けの複数プリセットと誤用語チェックを併用する例。
対応するtextlint-packagesの設定例は本ページ後半の「textlint-packagesのカスタマイズ」節を参照。
rules:
preset-ja-technical-writing:
# ラベル型見出し("ポイント:", "例:" など)のため、文末句点の強制を無効化する
ja-no-mixed-period: false
# 技術文書における自然な助詞連結(「〜かどうかを検討するか」など)が頻出するため無効化する
no-doubled-joshi: false
# 全角丸括弧の閉じが改行をまたぐ書き方をfalse positiveとして誤検出するため無効化する
no-unmatched-pair: false
# 入れ子括弧の閉じ`))`連続をfalse positiveとして誤検出するため無効化する
ja-no-successive-word: false
# 引用文や詳細な技術説明で100文字超過が避けられないため緩和する
sentence-length:
max: 120
# ドキュメントを常体(である調)で統一する方針のため
no-mix-dearu-desumasu:
preferInHeader: ""
preferInBody: "である"
preferInList: "である"
strict: false
preset-jtf-style:
"1.1.3.箇条書き":
shouldUsePoint: false # 箇条書きは「。」をつけない
# 和文の半角ピリオド・カンマ禁止ルール。`.gitignore`等のコード識別子の半角ピリオドを
# 句点へ自動変換して破壊するため無効化する(lintは通過し検出できないため)
"1.2.1.句点(。)と読点(、)": false
"4.1.3.ピリオド(.)、カンマ(,)": false
# 改行折り返し時に全角括弧の前後スペースをfalse positiveとして誤検出するため無効化する
"3.3.かっこ類と隣接する文字の間のスペースの有無": false
# コロン終端のラベル記法を多用するため無効化する
"4.2.7.コロン(:)": false
ja-no-abusage: true
textlint-packagesのカスタマイズ¶
追加のtextlintプリセットを使う場合はtextlint-packagesにパッケージ名を列挙する
(pnpx / npx起動時に--package / -pとして展開される)。
[tool.pyfltr]
textlint-packages = [
"textlint-rule-preset-ja-technical-writing",
"textlint-rule-preset-jtf-style",
"textlint-rule-ja-no-abusage",
]
共通のコマンドライン引数を追加したい場合は textlint-args を使う。
lint専用のオプション(--format=compact など)は textlint-lint-args に分離する。
旧版のtextlint-args = ["--format", "compact", ...]をそのまま引き継いでもクラッシュしない。
pyfltrはfix段の起動コマンドから--formatペアを自動除去するため。
ただし新規設定ではtextlint-lint-argsに書くことを推奨する。
呼び出し方の使い分け¶
状況に応じてpyfltrの呼び出し方を以下のいずれかから選ぶ。
コンテナ外では「常に最新版を使う」(uvx pyfltr ...)か「dev依存にバージョンを固定する」
(uv run pyfltr ...)かをプロジェクト判断で選択する。
| 状況 | 呼び出し方 | 補足 |
|---|---|---|
| 公式Dockerイメージ内(CI推奨構成) | pyfltr ... |
イメージ同梱の本体を直接呼ぶ。uvキャッシュ経由の解決を経由しない |
| コンテナ外・常に最新版を使う | uvx pyfltr ... |
uvが毎回最新を解決する。ローカル開発・軽量CIで使用 |
| コンテナ外・dev依存に固定する | uv run pyfltr ... |
uv add --dev "pyfltr[python]"済みのプロジェクトで使う。UV_FROZENとの併用が有効 |
CI¶
GitHub Actionsでpyfltrを実行する構成の例。
リリース時に発行する公式Dockerイメージghcr.io/ak110/pyfltrをcontainer:として利用する形が標準的。
uv / pnpm / mise / hadolint / pinact / shellcheck等が同梱されているため、
セットアップステップを毎回実行する必要がない。
キャッシュディレクトリは/cache配下にまとめて配置済み(uvは/cache/uv、pnpmは/cache/pnpm、miseは/cache/mise)。
Dockerイメージにpyfltr本体を同梱しているため、CI内ではpyfltrを直接呼び出す。
uvx pyfltrを使うとコンテナ起動ごとにuvキャッシュ経由のツール解決が実行され、コンテナ同梱版を使う利点が薄れるため。
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.11", "3.12", "3.13"]
container:
image: ghcr.io/ak110/pyfltr:latest
defaults:
run:
shell: bash
env:
UV_PYTHON: ${{ matrix.python-version }}
steps:
- uses: actions/checkout@v6
- name: Cache /cache
uses: actions/cache@v5
with:
path: /cache
key: pyfltr-cache-${{ runner.os }}-py${{ matrix.python-version }}
- name: Run pyfltr
run: pyfltr ci --output-format=github-annotations
ポイント。
image: ghcr.io/ak110/pyfltr:latest:vX.Y.Zタグも併発行されるため、再現性を重視する場合は固定タグを指定する- イメージには
UV_FROZEN=1とpnpm config set minimum-release-age 1440が事前設定されているため、 CIワークフロー側で同じ環境変数や設定を再指定する必要はない
- イメージには
defaults.run.shell: bash: GitHub Actionsのcontainer:既定シェルはshであり、 既存ワークフローで多用されるset -euo pipefail等のbash前提の記述を通すために指定するUV_PYTHON:uv runが必要なCPythonをロックファイルとmatrix値に従って自動取得するactions/setup-pythonは不要- 単一バージョンで十分な場合は
strategy.matrixとUV_PYTHONを省ける
actions/cache:/cache配下を一括キャッシュする- uv / pnpm / miseのキャッシュは内容アドレス指定のため、ロックファイル変更時も追加分がそのまま蓄積される
- キーはOSのみで足り、ロックファイルhashなどの細かい無効化は不要
pyfltr ci: イメージ同梱のpyfltrをそのまま使う- uvキャッシュを介した解決を毎回経由せず、コンテナビルド時に確定したバージョンで実行できる
- 特定バージョンに固定したい場合は
image:のタグ(vX.Y.Z)で揃える
--output-format=github-annotations:::error file=.../::warning file=...形式の行を標準出力へ出力する- プル要求の該当ファイル行にコメントとして表示される
追加のシステムパッケージが必要な場合¶
公式Dockerイメージの既定ユーザーは非root(sudo無し)のため、aptでシステムパッケージを追加するには
container.optionsで--user rootを指定する。
ただし--user root実行時は、checkoutステップが用意したワークスペースの所有者と、コンテナ実行ユーザー(root)が一致しない。
この不一致によりpre-commit等のgit操作がdubious ownershipで停止する。
git config --global --add safe.directoryで対象ワークスペースを信頼対象に追加して回避する。
PDFを画像化するpdf2imageが必要とするpoppler-utilsの導入とsafe.directory設定を含めた例を次に示す。
container:
image: ghcr.io/ak110/pyfltr:latest
options: --user root
steps:
- uses: actions/checkout@v6
- name: safe.directory の設定
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
- name: システムパッケージ導入
run: |
apt-get update
apt-get install -y --no-install-recommends poppler-utils
Dockerイメージを使わない場合(setup-uv方式)¶
自前runner制約等でDockerイメージを使用できない場合は、astral-sh/setup-uvでuvを導入し、Node.js / pnpmを別途セットアップする。
UV_FROZEN・PYTHONDEVMODE等の環境変数やpnpm config set minimum-release-age 1440は
ワークフロー側で個別指定が必要となる(Dockerイメージでは事前設定済み)。
env:
PYTHONDEVMODE: "1"
UV_FROZEN: "1"
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.11", "3.12", "3.13", "3.14"]
steps:
- uses: actions/checkout@v6
- uses: astral-sh/setup-uv@v8
with:
python-version: ${{ matrix.python-version }}
enable-cache: true
- uses: actions/setup-node@v6
with:
node-version: "lts/*"
- uses: pnpm/action-setup@v6
with:
version: latest
- run: pnpm config set minimum-release-age 1440 --global
- run: uvx pyfltr ci --output-format=github-annotations
- run: uv cache prune --ci
uv cache prune --ciはプレビルドwheelをキャッシュから除去し、ソースビルドwheelのみ保持する。
GitHub Actionsのような高帯域環境ではキャッシュサイズを削減できる。
帯域が限られる環境では--ciを外し、プレビルドwheelもキャッシュに残す方が再取得を回避できる。
PRの差分ファイルのみを対象にする¶
PR(プルリクエスト)で変更したファイルだけを対象に実行する場合は--changed-sinceを使う。
ベースブランチとの差分ファイルのみにチェック対象を限定し、大規模リポジトリでの実行時間を短縮できる。
- name: Test with pyfltr (changed files only)
run: uvx pyfltr ci --changed-since=origin/main --output-format=github-annotations
--changed-since=origin/mainはorigin/mainからの差分ファイルに限定して実行する。
対象はgit diff --name-onlyが返すコミット差分・trackedファイルの作業ツリー差分・staged差分の和集合となり、
untrackedの新規ファイルは対象外。
gitが不在またはrefが解決できない場合は警告を出力して全体実行へフォールバックする。
GitLab CIでMerge Requestへ表示する¶
GitLab CIでは--output-format=code-qualityでCode Climate JSON issue形式のサブセットを出力する。
これをartifacts:reports:codequalityとしてアップロードするとMerge Request画面のCode Quality widgetに反映される。
MR diffインライン表示はUltimate tier限定。
stages:
- lint
pyfltr:
stage: lint
image: ghcr.io/astral-sh/uv:python3.13-bookworm
variables:
PYTHONDEVMODE: "1"
UV_FROZEN: "1"
script:
- uvx pyfltr ci --output-format=code-quality --output-file=code-quality-report.json
artifacts:
when: always
reports:
codequality: code-quality-report.json
ポイント。
--output-format=code-quality: Code Climate JSON issue形式の配列を出力する--output-fileを指定するとstdoutには従来のtext整形出力が並行して出るため、ジョブログで進捗を確認できる
artifacts:reports:codequality: 生成したJSONファイルをGitLabに取り込む- Merge Request画面のCode Quality widget(全tier)とMR diffインライン表示(Ultimate tier)に反映される
when: always: ジョブが失敗してもアーティファクトを残す指定- lintエラーで
exit 1したときもレポートを取り込めるようにする
- lintエラーで
Python以外のプロジェクトでの推奨設定例については推奨設定例(非Pythonプロジェクト)を参照。