AGEFreighterを公開するにあたってTest PyPIから本番に移行し、それに伴っていくつかファイルをちゃんと作る必要もあったので、備忘録を兼ねてまとめておく。
環境整備
まずuvで以下の準備をする。
uv init agefreighter
cd agefreighter
uv venv
source .venv/bin/activate
Pythonのバージョンを指定する場合は、以下。
uv init agefreighter -p 3.10.0
これで、以下の状態になる。
.
├── README.md
├── hello.py
└── pyproject.toml
hello.pyは不要なので削除する。
毎回、sourceコマンドを実行するのが面倒な場合は、こちらのエントリーでも見てください。
コードと関連ファイル
age_freighter.pyとテストコードであるtest_agefreighter.py、テストデータを入れる。
.
├── README.md
├── data
│ ├── actorfilms.csv
│ ├── cities.csv
│ ├── countries.csv
│ └── edges.csv
├── pyproject.toml
├── src
│ └── agefreighter
│ ├── __init__.py
│ └── agefreighter.py
├── tests
│ └── test_agefreighter.py
└── uv.lock
src/agefreighter/__init__.pyの中身は以下の通り。これが無いとパッケージを見つけてくれない。
from .agefreighter import AgeFreighter
tests/test_agefreighter.pyを実行すると、あれやこれやのパッケージが無いと言われるので、逐一、uv addする。
uv add pandas
pyproject.tomlは以下の通り。dependenciesはuv addした際に更新されるので特に問題はないかと。build-systemとhatchに関する設定を追加してある。
[project]
name = "agefreighter"
authors = [
{name = "Rio Fujita", email = "rifujita@microsoft.com"},
]
version = "0.3.0"
license = {file = "LICENSE"}
description = "AgeFreighter is a Python package that helps you to create a graph database using Azure Database for PostgreSQL."
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
"asyncio>=3.4.3",
"networkx>=3.4.2",
"numpy>=2.1.3",
"pandas>=2.2.3",
"psycopg>=3.2.3",
"psycopg-pool>=3.2.4",
"pyarrow>=18.1.0",
"resource>=0.2.1",
"typing-extensions>=4.12.2",
"neo4j>=5.27.0",
]
[tool.uv.workspace]
members = ["agefreighter"]
[project.urls]
Homepage = "https://github.com/rioriost/agefreighter"
Issues = "https://github.com/rioriost/agefreighter/issues"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.sdist]
include = [
"src/agefreighter/*.py",
"/tests",
]
exclude = [
"uv.lock",
"/data/*",
"dist/.DS_Store",
]
[tool.hatch.build.targets.wheel]
packages = ["src/agefreighter"]
LICENSEファイルを追加する。中身はMITにしてある。ダミーデータを生成するスクリプトも追加。README.mdはGitHub Copilotにお願いすると良い感じのテンプレートを教えてくれるので、それを編集。
.
├── LICENSE
├── README.md
├── data
│ ├── actorfilms.csv
│ ├── cities.csv
│ ├── countries.csv
│ └── edges.csv
├── pyproject.toml
├── src
│ └── agefreighter
│ ├── __init__.py
│ └── agefreighter.py
├── tests
│ ├── dummy_generator.py
│ └── test_agefreighter.py
└── uv.lock
5 directories, 12 files
ビルド
ビルドサブコマンドを実行する。
uv build
すると、distsディレクトリにファイルが生成される。
├── LICENSE
├── README.md
├── data
│ ├── actorfilms.csv
│ ├── cities.csv
│ ├── countries.csv
│ └── edges.csv
├── dist
│ ├── agefreighter-0.3.0-py3-none-any.whl
│ └── agefreighter-0.3.0.tar.gz
├── pyproject.toml
├── src
│ └── agefreighter
│ └── agefreighter.py
├── tests
│ ├── dummy_generator.py
│ └── test_agefreighter.py
└── uv.lock
公開の準備
pypi.orgでアカウントを作成したら、[アカウント設定]→[APIトークン]で[APIトークンの追加]。生成されたトークンを、.zprofile等に環境変数として入れておくでも、パスワードマネージャに保存するでも、お好きなように。
export PYPI_TOKEN='pypi-xxxxxxx'
公開
publishサブコマンドで公開。
uv publish --token=$PYPI_TOKEN
まとめ
uvを使うと簡単。