mcpField
P
packaging-python-libraries

packaging-python-libraries

github.com/wdm0006開発109101 回インストール2 日前に更新
リポジトリ

packaging-python-libraries について

Pythonライブラリ開発者向けのパッケージ化とリリースのガイドです。`pyproject.toml`、ビルド、PyPI公開、依存関係を扱い、wheelの内容確認とクリーン環境での検証を重視します。

主な機能

  1. 01`pyproject.toml`の設定
  2. 02`uv`による配布物のビルド
  3. 03PyPI公開メタデータの確認
  4. 04依存関係とパッケージデータの設定
  5. 05wheelの内容確認
  6. 06クリーン環境でのインストール検証

活用シーン

  1. 01Pythonライブラリのリリース設定を準備
  2. 02sdistとwheelをビルドして確認
  3. 03配布物から欠落したサブパッケージやデータを特定
  4. 04公開前にインストール済みパッケージの実モジュールを検証

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/wdm0006/python-skills --skill packaging-python-libraries

インストール後、Claude Code で/packaging-python-librariesを入力して読み込まれたか確認します。

同梱ファイルCONDA.md

詳細

Python ライブラリのパッケージ化

pyproject.toml の基本

[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "my-package"
version = "1.0.0"
description = "Short description"
readme = "README.md"
requires-python = ">=3.10"
license = {text = "MIT"}
dependencies = []

[project.optional-dependencies]
dev = ["pytest>=7.0", "ruff>=0.1", "mypy>=1.0"]

[project.urls]
Homepage = "https://github.com/user/package"
Documentation = "https://package.readthedocs.io"

[project.scripts]
mycli = "my_package.cli:main"

[tool.setuptools.packages.find]
where = ["src"]

ビルド

uv build                     # Creates sdist + wheel in dist/
uvx twine check dist/*       # Validate metadata

PyPI への公開

CI からのトラステッドパブリッシング(トークンを保存しない方法)を推奨します。詳しくは以下の CI セクションをご覧ください。手動で公開する場合は、uvx 経由で twine を使ってアップロードします。

uvx twine upload --repository testpypi dist/*  # Test first
uvx twine upload dist/*                         # Production (uses a PyPI token)

GitHub Actions(トラステッドパブリッシング)

公開は、managing-python-releases スキルにある、タグをトリガーとする標準リリースワークフローによって自動化されています。1 つのパイプラインで uv を使ってビルドし、トラステッドパブリッシングで公開します。../release-management/AUTOMATION.md をご覧ください。ここに別のコピーを管理しないでください。

依存関係のベストプラクティス

# DO: Minimum versions
dependencies = ["requests>=2.28", "click>=8.0"]

# DON'T: Exact pins (locks users)
dependencies = ["requests==2.28.1"]

# DO: Optional for features
[project.optional-dependencies]
cli = ["click>=8.0"]

パッケージデータの同梱

[tool.setuptools.package-data]
my_package = ["py.typed", "data/*.json"]
from importlib.resources import files
data = files("my_package.data").joinpath("file.json").read_text()

直接参照の依存関係には実際のビルドが必要です

toolkit @ https://example.com/toolkit.whl のような依存関係は、ビルドバックエンドを呼び出さずにインストールのドライランで解決される場合があります。Hatchling を使用している場合、直接参照を明示的に許可しないと、実際の wheel ビルドで失敗します。

[project]
dependencies = [
    "toolkit @ https://example.com/releases/toolkit.whl",
]

[tool.hatch.metadata]
allow-direct-references = true

このケースでは、パッケージ化の確認に uv pip install --dry-run . を使わないでください。プロジェクトをビルドせずに成功と報告する可能性があります。uv build(または実際に uv pip install . を実行)して、設定済みのバックエンドにメタデータを検証させてください。

uv build
uvx twine check dist/*

詳細なテンプレートについては、以下をご覧ください。

ビルドしたアーティファクトを検証する(ビルドの成功は、正しい wheel の証明にはなりません)

uv build が成功したということは、バックエンドが実行されたことを示すだけで、wheel にコードが含まれていることを示すものではありません。ビルドバックエンドは設定に基づいてファイルを選択します。Hatchling では [tool.hatch.build.targets.wheel](only-include / packages / include)、setuptools では [tool.setuptools.packages.find] が該当します。この設定を誤ると、サブパッケージやデータファイルが欠落した wheel が、エラーなしでそのまま出荷されてしまいます。twine check でも検出できません。検証するのはメタデータであり、内容ではないからです。

公開前に、必ず wheel の中身を確認し、クリーンな環境にインストールしてください。

uv build
uv run python -m zipfile -l dist/*.whl # list every file the wheel contains
# ^ confirm ALL your subpackages (my_pkg/, my_pkg/sub/) and data files are there,
#   not just the top-level module.

よくある落とし穴は、ファイルの選択範囲を狭くしすぎることです。次の設定では server.py だけが含まれ、server/ パッケージ全体と data/ が気付かないうちに除外されます。

# DON'T — over-narrow include drops everything else
[tool.hatch.build]
only-include = ["server.py"]

# DO — include the package (and any data dirs); let the backend walk it
[tool.hatch.build.targets.wheel]
packages = ["src/my_pkg"]

**名前の衝突に関する落とし穴:**トップレベルのモジュール foo.py とパッケージディレクトリ foo/ の両方を、絶対に同梱しないでください。パッケージがモジュールを隠すため、import foo は(多くの場合、ほとんど空の)foo/__init__.py を読み込みます。また、コンソールエントリポイント foo = "foo:main" は、そのパッケージに main がないため失敗します。どちらか一方(通常はパッケージ)を選び、もう一方を削除してください。

次に、ソースツリーではなくクリーンな環境へのインストールで動作を確認してください。

uv venv /tmp/verify && uv pip install --python /tmp/verify/bin/python dist/*.whl
cd /tmp && /tmp/verify/bin/python -c "import my_pkg; my_pkg.submodule.real_func"
mycli --help                           # exercise each console script too

リポジトリのルート以外のディレクトリから実行してください。そうしないと、wheel が空でも import my_pkg は sys.path 上のソースツリーを読み込んで「動作」してしまいます。また、単にトップレベルの名前をインポートできるかではなく、実在するシンボル(my_pkg.submodule.real_func)を検証してください。隠れている空のパッケージに対して import foo が成功しても、何の証明にもなりません。import foo; print("ok") だけを実行する CI のスモークテストは、誤った成功判定です。配布パッケージが使用可能かどうかに関係なく成功してしまいます。

チェックリスト

Before Release:
- [ ] pyproject.toml valid
- [ ] README.md informative
- [ ] LICENSE file exists
- [ ] Version set correctly
- [ ] twine check passes
- [ ] `uv run python -m zipfile -l dist/*.whl` shows every subpackage + data file
- [ ] Direct-reference dependencies pass a real backend build (not only install dry-run)
- [ ] No module/package name collision (no foo.py AND foo/)
- [ ] Installed the wheel into a clean venv and imported a real submodule
      symbol from a directory outside the repo (not just the top-level name)
- [ ] Each console script runs after a clean install

After Release:
- [ ] pip install works
- [ ] Import works
- [ ] GitHub release created

詳細情報

このスキルは、Will McGinnis による Guide to Developing High-Quality Python Libraries の Distribution セクションに基づいています。詳しくは、以下の記事をご覧ください。

コメント