Currently maintaining two Python packages:
Previously, I used setup.py for packaging. However, when updating NJUlogin in November, I encountered this warning:
Therefore, I decided to switch to the new pyproject.toml approach for packaging. At the time, I briefly learned Poetry and adapted it for NJUlogin. Today, while updating mijia-api, I wanted to make a similar adaptation but realized I had forgotten how. So I'm writing this blog post to document it. It seems I'll be using Poetry more frequently for dependency management going forward.
Poetry positions itself as: "Python packaging and dependency management made easy." It works similarly to npm (if you're familiar with Node.js), managing dependencies via command-line interface.
But Poetry is too long—henceforth, you'll be called pop.
Check the official documentation: https://python-poetry.org/docs/#installation I installed it using pipx.
This generates the following pyproject.toml file:
However, since my package contains uppercase letters, I need to change the name under [tool.poetry] and manually add a packages entry. I also need to include other configurations from setup.py:
By default, Poetry creates the virtual environment in ~/.cache/pypoetry. You can modify this using pop config; see the documentation here. Personally, I prefer placing it within the project directory:
Then, you can install dependencies from requirements.txt, one by one. The following command writes dependencies into pyproject.toml and generates poetry.lock:
One major advantage of Poetry is its ability to display dependencies in a tree structure:
At this point, you can safely delete the original setup.py.
You can use poetry-dynamic-versioning to dynamically set the version, eliminating the need to manually update pyproject.toml each time.
Now, you can build with a single command:
Unlike twine, which stores PyPI tokens in ~/.pypirc, Poetry requires explicit configuration:
Then, you can publish:
********************************************************************************
With Python 2.7 end-of-life, support for building universal wheels
(i.e., wheels that support both Python 2 and Python 3)
is being obviated.
Please discontinue using this option, or if you still need it,
file an issue with pypa/setuptools describing your use case.
By 2025-Aug-30, you need to update your project and remove deprecated calls
or your builds will no longer be supported.
********************************************************************************
alias pop='poetry'
Set-Alias pop poetry
pop init
[tool.poetry]
name = "mijiaapi"
version = "0.0.0"
description = "A Python API for Xiaomi Mijia"
authors = ["Do1e <dpj.email@qq.com>"]
license = "GPLv3"
readme = "README.md"
[tool.poetry.dependencies]
python = "^3.12"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
2c2
< name = "mijiaapi"
---
> name = "mijiaAPI"
7a8,17
> homepage = "https://github.com/Do1e/mijia-api"
> repository = "https://github.com/Do1e/mijia-api"
> packages = [
> {include = "mijiaAPI"}
> ]
> classifiers = [
> "Programming Language :: Python :: 3",
> "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
> "Operating System :: OS Independent",
> ]
# Configure virtual environment to be inside the project directory
pop config virtualenvs.in-project true
# Create and use the virtual environment
pop env use python
# If using conda, this step is unnecessary—it will use the existing conda environment directly
source .venv/bin/activate
pop add requests qrcode
pop show --tree
# qrcode 8.0 QR Code image generator
# └── colorama *
# requests 2.32.3 Python HTTP for Humans.
# ├── certifi >=2017.4.17
# ├── charset-normalizer >=2,<4
# ├── idna >=2.5,<4
# └── urllib3 >=1.21.1,<3
git tag v1.3.0
pop self add "poetry-dynamic-versioning[plugin]"
pop dynamic-versioning enable
pop build
pop config pypi-token.pypi pypi-xxxxxx
pop publish