前から気になっていた[[uv]]を試してみる。
- [[uv]]のバージョンは 0.5.14
- [[Python]]のバージョンは3.12.7
- 環境は[[Ubuntu]]([[WSL]])。
## インストール
[[mise]]でインストールする。
```console
mise use -g uv
```
## サンプルプロジェクトで動作確認
`uv init` でプロジェクトの作成、`uv add` で依存関係の追加。
```console
$ uv init uv-sandbox
Initialized project `uv-sandbox` at `/home/tadashi-aikawa/tmp/uv-sandbox`
$ cd $_
$ uv add owlmixin
Using CPython 3.12.7 interpreter at: /home/tadashi-aikawa/.local/share/mise/installs/python/3.12.7/bin/python3.12
Creating virtual environment at: .venv
Resolved 3 packages in 1.04s
Prepared 2 packages in 364ms
Installed 2 packages in 15ms
+ owlmixin==6.2.4
+ pyyaml==6.0.2
$ uv add --dev ruff
Resolved 4 packages in 558ms
Prepared 1 package in 669ms
Installed 1 package in 14ms
+ ruff==0.8.5
$ uv run which ruff
/home/tadashi-aikawa/tmp/uv-sandbox/.venv/bin/ruff
```
コードを書いてみる。
```python
from owlmixin import TIterator
def main():
result = (
TIterator([1, 10, 100])
.map(lambda x: x * 2)
.filter(lambda x: x > 10)
.to_pretty_json()
)
print(result)
if __name__ == "__main__":
main()
```
実行してみる。
```console
$ uv run hello.py
[
20,
200
]
```
## OwlMixinをuvに移行
[[🦉OwlMixin]]を[[Poetry]]から[[uv]]に移行してみる。
### Python 3.13 のインストール
ついでに[[Python 3.13]]にも対応したいのでインストールする。
```console
mise use -g
[email protected]
```
### 仮想環境の削除
ついでにキャッシュも削除しておく。
```console
rm -rf .venv .ruff_cache .pytest_cache
```
### Poetryに関する情報を移行
以下を参考に。
<div class="link-card">
<div class="link-card-header">
<img src="https://cdn.sstatic.net/Sites/stackoverflow/Img/favicon.ico?v=ec617d715196" class="link-card-site-icon"/>
<span class="link-card-site-name">Stack Overflow</span>
</div>
<div class="link-card-body">
<div class="link-card-content">
<p class="link-card-title">How to migrate from Poetry to UV package manager?</p>
<p class="link-card-description">I'm planning to switch from poetry to the uv Python package manager, but I can't find any migration guides. Currently, I'm using poetry and already have ... </p>
</div>
<img src="https://cdn.sstatic.net/Sites/stackoverflow/Img/
[email protected]?v=73d79a89bded" class="link-card-image" />
</div>
<a href="https://stackoverflow.com/questions/79118841/how-to-migrate-from-poetry-to-uv-package-manager"></a>
</div>
#### pyproject.toml の変更
[[pdm]]コマンドで[[pyproject.toml]]が移行しやすくなるそう。
```console
uvx pdm import pyproject.toml
```
もともとの[[pyproject.toml]]は以下。
```toml
[tool.poetry]
name = "owlmixin"
version = "6.2.4"
description = "Mixin which converts ``data class instance`` and others each other more simple."
authors = ["tadashi-aikawa <
[email protected]>"]
license = "MIT"
readme = "README.md"
homepage = "https://github.com/tadashi-aikawa/owlmixin"
repository = "https://github.com/tadashi-aikawa/owlmixin"
documentation = "https://tadashi-aikawa.github.io/owlmixin/"
keywords = ["dict", "json", "yaml", "parser", "mixin"]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Utilities",
]
[tool.poetry.dependencies]
python = "^3.8"
pyyaml = "^6.0"
[tool.poetry.dev-dependencies]
sphinx = "^5.0"
pytest = "^7.2"
mock = "^3.0"
pytest-cov = "^4.0"
[tool.poetry.group.dev.dependencies]
ruff = "^0.3.7"
[tool.ruff.lint]
# import順を最適化
extend-select = ["I"]
[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401"]
```
コマンド実行後、以下が **追加** される。
```toml
[tool.pdm.dev-dependencies]
dev = [
"ruff<1.0.0,>=0.3.7",
]
[tool.pdm.build]
includes = []
[build-system]
requires = ["pdm-backend"]
build-backend = "pdm.backend"
[project]
authors = [
{name = "tadashi-aikawa", email = "
[email protected]"},
]
license = {text = "MIT"}
requires-python = "<4.0,>=3.8"
dependencies = [
"pyyaml<7.0,>=6.0",
]
name = "owlmixin"
version = "6.2.4"
description = "Mixin which converts ``data class instance`` and others each other more simple."
readme = "README.md"
keywords = [
"dict",
"json",
"yaml",
"parser",
"mixin",
]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Utilities",
]
[project.urls]
homepage = "https://github.com/tadashi-aikawa/owlmixin"
repository = "https://github.com/tadashi-aikawa/owlmixin"
documentation = "https://tadashi-aikawa.github.io/owlmixin/"
[dependency-groups]
dev = [
"ruff<1.0.0,>=0.3.7",
]
```
続いて以下の変更を加える。
- `[tool.poetry]` から始まるセクションはすべて削除
- `[tool.pdm.*]` を すべて削除
- `[build-system]` を削除
整理して最終的には以下。
```toml
[project]
authors = [
{name = "tadashi-aikawa", email = "
[email protected]"},
]
license = {text = "MIT"}
requires-python = "<4.0,>=3.8"
dependencies = [
"pyyaml<7.0,>=6.0",
]
name = "owlmixin"
version = "6.2.4"
description = "Mixin which converts ``data class instance`` and others each other more simple."
readme = "README.md"
keywords = [
"dict",
"json",
"yaml",
"parser",
"mixin",
]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Utilities",
]
[project.urls]
homepage = "https://github.com/tadashi-aikawa/owlmixin"
repository = "https://github.com/tadashi-aikawa/owlmixin"
documentation = "https://tadashi-aikawa.github.io/owlmixin/"
[dependency-groups]
dev = [
"ruff<1.0.0,>=0.3.7",
]
[tool.ruff.lint]
# import順を最適化
extend-select = ["I"]
[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401"]
```
#### lockfileの作成
[[poetry.lock]]を削除して、[[uv]]のlockfileをつくる。
```console
$ rm poetry.lock
$ uv sync
Using CPython 3.13.1 interpreter at: /home/tadashi-aikawa/.local/share/mise/installs/python/3.13.1/bin/python3
Creating virtual environment at: .venv
Resolved 3 packages in 312ms
Prepared 1 package in 255ms
Installed 2 packages in 17ms
+ pyyaml==6.0.2
+ ruff==0.8.5
```
### Makefileの変更
`poetry` を `uv` に置換していく。差分はシンプルなので省略。
### 足りない依存関係の追加
よく見ると [[pyproject.toml]] の以下が移行できていない...
```toml
[tool.poetry.dev-dependencies]
sphinx = "^5.0"
pytest = "^7.2"
mock = "^3.0"
pytest-cov = "^4.0"
```
`[dependency-groups]` に追加する。
```toml
[dependency-groups]
dev = [
"ruff<1.0.0,>=0.3.7",
"sphinx<6.0,>=5.0",
"pytest<8.0,>=7.2",
"mock<4.0,>=3.0",
"pytest-cov<5.0,>=4.0",
]
```
```console
uv sync
```
### 動作確認
テストを実行したところAll Greenになった。
```console
make test
```
### READMEの修正
[[Poetry]]に関する記述をすべて[[uv]]に変更する。
### make serve-docs が失敗する問題
[[📝Python3.13でSphinxのmake htmlを実行するとNo module named 'imghdr'エラー]] を踏んだので[[Sphinx]]を7系にバージョンアップ。どさくさに紛れて[[Ruff]]も一応minをあげておく。
```diff
[dependency-groups]
dev = [
- "ruff<1.0.0,>=0.3.7",
+ "ruff<1.0.0,>=0.8.5",
- "sphinx<6.0,>=5.0",
+ "sphinx<8.0,>=7",
"pytest<8.0,>=7.2",
"mock<4.0,>=3.0",
"pytest-cov<5.0,>=4.0",
]
```
気になるコマンド出たけど実害はなさそう...たぶん。
```console
build succeeded, 1 warning.
Look for any errors in the above output or in _build/linkcheck
```
### GitHub Actionsの変更
[[GitHub Actions]]の設定ファイルを変更。
- [[Poetry]]を[[uv]]に変更
- `poetry.lock` -> `uv.lock`
- [[Python 3.8]]を削除
- [[Python 3.13]]を追加
分かりにくいところ。
```diff
- name: Install dependencies
run: |
- python -m pip install --upgrade pip poetry
- poetry install
+ pipx install uv
+ uv sync
```
### パッケージのビルド
普通に実行したら `dist` 配下に作成された。
```console
uv build
```
[\[build-system\]の記載がないとビルドしないと書かれていた](https://docs.astral.sh/uv/guides/publish/#preparing-your-project-for-packaging) から失敗すると思ったのだが...
>If your project does not include a [build-system] definition in the pyproject.toml, uv will not build it by default. This means that your project may not be ready for distribution. Read more about the effect of declaring a build system in the project concept documentation.
### パッケージのパブリッシュ
[[GitHub Actions]]でリリースする場合はcredentialsは不要らしい。
> For publishing to PyPI from GitHub Actions, you don't need to set any credentials. Instead, add a trusted publisher to the PyPI project.
代わりにTrusted Publisherを追加するとのこと。
<div class="link-card-v2">
<div class="link-card-v2-site">
<img class="link-card-v2-site-icon" src="https://docs.pypi.org/assets/favicon.ico" />
<span class="link-card-v2-site-name">docs.pypi.org</span>
</div>
<div class="link-card-v2-title">
Adding a Trusted Publisher to an Existing PyPI Project - PyPI Docs
</div>
<a href="https://docs.pypi.org/trusted-publishers/adding-a-publisher/"></a>
</div>
https://pypi.org/manage/project/owlmixin/settings/publishing/ から追加する。
![[Pasted image 20250103152500.png]]
![[Pasted image 20250103152539.png]]
これで[[GitHub Actions]]にてsecretを指定する必要はなくなったので、トークンを登録していたら削除する。
[[📝Trusted Publisherに登録したリポジトリのGitHub ActionsからPyPIにpublishするとTrusted publishing errorになる]]場合は、`id-token: write` のパーミッションをつける必要がある。
> [!info]
> 最新情報は [[Trusted PublishingでGitHub Actionsからパッケージをアップロード (PyPI)|Trusted PublishingでGitHub Actionsからパッケージをアップロード]] を参照。
`uv publish` コマンド実行時に [[📝uv publishで license-file introduced in metadata version 2.4, not 2.1 エラー]] が発生する問題に遭遇。`[build-system]` を指定することで凌ぐ。
```toml
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
```