動機
各所(主に
tl;dr
多くの
前提
タイトルにvenvとsetup.py / setup.cfgではなくpyproject.tomlでの
な
- Python >= 3.8
- pip >= 23.1
- setuptools >= 45
用語
- PEP: Python Enhancement Proposalsの
略。 新機能や 改善案などが 提出され集められた もの - Setuptools: pip(インストーラー)が
バックエンドと して 使える パッケージャライブラリの 1つ
- Absolute Import: 絶対インポートとも
言われ、 パッケージ名からの 絶対パスで インポートする 書き方
基本の 構成の pyproject.toml
[build-system]
requires = ["setuptools>=45", "wheel"]
[project]
name = "my-awesome-package"
readme = "README.md"
license = {file = "LICENSE"}
authors = [{name = "Peacock", email = "[email protected]"}]
urls = {repository = "https://github.com/peacock0803sz/my-awesome-package"}
dynamic = ["version"]
requires-python = ">=3.8"
dependencies = [
"" # 依存パッケージをここに書く
]
[project.optional-dependencies]
test = ["pytest"] # 他テストに必要なもの(freezegunとか)など
dev = ["black", "flake8", "mypy"]
# mypy / blackの設定などこの
プロジェクト構成 & pyproject.toml例いろいろ
.git がpackage_dirオプションのpip install --editableでmy_awesome_package)を
1. snake_case の フォルダを 直下に 置く タイプ
説明不要なfrom my_awesome_package import ...のように
.
├── LICENSE / README.md etc ...
├── my_awesome_package
│ ├── __init__.py
│ └── main.py
├── tests
│ ├── conftest.py
│ └── test_main.py
├── pyproject.toml
└── setup.cfg2. src/ を 一度 切って その 下に 1つ以上の サブパッケージを 置く タイプ
.
├── LICENSE / README.md etc ...
├── pyproject.toml
├── setup.cfg
└── src
├── core
│ ├── __init__.py
│ └── main.py
├── misc
│ ├── __init__.py
│ └── main.py
└── tests
├── conftest.py
└── core
└── test_main.pyこのmy_awesome_package)にpyproject.tomlに
...
[tool.setuptools.package-dir]
my_awesome_package = "src"
"_" = "src/tests" # src/tests配下を除外するためのハック
...3. snake_case で 1ファイルのみで 済ませる タイプ
Webフレームワークの
.
├── LICENSE / README.md etc ...
├── pyproject.toml
├── setup.cfg
├── my_awesome_package.py
└── tests
├── conftest.py
└── test_main.py4. . 区切りで 名前空間を 切っていきたい タイプ
一番src/my/__init__.py(Package Rootの__init__.py)でpyproject.tomlには
.
├── LICENSE / README.md etc ...
├── pyproject.toml
├── setup.cfg
└── src
├── my
│ └── awesome
│ └── package
│ ├── __init__.py
│ └── main.py
└── tests
├── conftest.py
└── test_main.py基本パターンからpyproject.tomlに
...
[tool.setuptools.packages.find]
where = ["src"]
exclude = ["tests"] # testsをsrcの下に置く場合
namespaces = false
...こうするfrom my.awesome.package import ...と
あなたが やりたいと 思っている こと、 ほぼ出来ますよ
開発用にだけインストールする パッケージ指定
Pipfile(pipenv)の[dev-packages], poetry(pyproject.toml)の[tool.poetry.group.*.dependencies]に-cオプションと
[project.optional-dependencies]
test = ["pytest"] # 他テストに必要なもの(freezegunとか)など
dev = ["black", "flake8", "mypy"]名前(キー)に
タスクランナー(npm scripts)的な もの
pyproject.tomlにここで[dev]のようにproject.optional-dependences)をもちろんサードパーティーパッケージの
:::details 2023/01/05 打ち消し線を
[project.scripts]
my_awesome_cmd = "some_package.module:func"
dev_cmd = "some_package.module:dev_func [dev]" # extrasを指定する場合残念ながら出来ない こと
依存パッケージをpyproject.toml / constraints.txtを
References (参考資料)
全て
- Package Discovery and Namespace Packages
- Setuptools公式ドキュメント内の
パッケージ検索と 名前 空間に ついての ユーザーガイド
- Setuptools公式ドキュメント内の
- Declaring project metadata - Python Packaging User Guide
- PEP 621の
採択・実装を うけて 書かれた ユーザー向けガイド
- PEP 621の
- peacock0803sz/python-template
- 拙作の
Pythonパッケージ用テンプレートリポジトリ(パッケージ本体は 書いていない )
- 拙作の
Notes
-
残念ながら
LSP(pyright / pylance)の 読み込み可能モジュールには 出て こないようです。 もっと 良い 方法が あったら コメント等で 教えてください。 ↩ -
https://setuptools.pypa.io/en/latest/userguide/package_discovery.html#legacy-namespace-packages ↩
-
https://zenn.dev/peacock0803sz/articles/acd723d5a5fa0b(拙作参考記事) ↩
-
https://packaging.python.org/en/latest/specifications/declaring-project-metadata/#entry-points ↩