Replace poetry by uv

This commit is contained in:
Šarūnas Nejus
2026-04-14 21:06:24 +01:00
parent dbeba765f0
commit 99b5da869d
11 changed files with 4577 additions and 5081 deletions

View File

@@ -28,12 +28,10 @@ jobs:
- uses: actions/checkout@v5
- name: Install Python tools
uses: BrandonLWhite/pipx-install-action@v1.0.3
- name: Setup Python with poetry caching
# poetry cache requires poetry to already be installed, weirdly
uses: actions/setup-python@v6
- name: Install uv
uses: astral-sh/setup-uv@v8.1.0
with:
python-version: ${{ matrix.python-version }}
cache: poetry
- name: Install system dependencies on Windows
if: matrix.platform == 'windows-latest'
@@ -85,7 +83,7 @@ jobs:
- if: ${{ env.IS_MAIN_PYTHON != 'true' }}
name: Test without coverage
run: |
poetry install --without=lint --extras=autobpm --extras=discogs --extras=lyrics --extras=replaygain --extras=reflink --extras=fetchart --extras=chroma --extras=sonosupdate
uv sync --group test --extra autobpm --extra discogs --extra lyrics --extra replaygain --extra reflink --extra fetchart --extra chroma --extra sonosupdate
poe test
- if: ${{ env.IS_MAIN_PYTHON == 'true' }}
@@ -93,7 +91,7 @@ jobs:
env:
LYRICS_UPDATED: ${{ steps.lyrics-update.outputs.any_changed }}
run: |
poetry install --extras=autobpm --extras=discogs --extras=lyrics --extras=docs --extras=replaygain --extras=reflink --extras=fetchart --extras=chroma --extras=sonosupdate
uv sync --group test --extra autobpm --extra discogs --extra lyrics --extra docs --extra replaygain --extra reflink --extra fetchart --extra chroma --extra sonosupdate
poe docs
poe test-with-coverage

View File

@@ -14,10 +14,10 @@ jobs:
- uses: actions/checkout@v5
- name: Install Python tools
uses: BrandonLWhite/pipx-install-action@v1.0.3
- uses: actions/setup-python@v6
- name: Install uv
uses: astral-sh/setup-uv@v8.1.0
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: poetry
- name: Install system dependencies
run: |
@@ -34,7 +34,7 @@ jobs:
python3-gst-1.0
- name: Install dependencies
run: poetry install --extras=autobpm --extras=discogs --extras=lyrics --extras=docs --extras=replaygain --extras=reflink --extras=fetchart --extras=chroma --extras=sonosupdate
run: uv sync --group test --extra autobpm --extra discogs --extra lyrics --extra docs --extra replaygain --extra reflink --extra fetchart --extra chroma --extra sonosupdate
- name: Test
env:

View File

@@ -37,15 +37,15 @@ jobs:
with:
files: |
**.py
poetry.lock
uv.lock
- name: Check changed python files
id: changed-python-files
env:
CHANGED_PYTHON_FILES: ${{ steps.raw-changed-python-files.outputs.all_changed_files }}
run: |
if [[ " $CHANGED_PYTHON_FILES " == *" poetry.lock "* ]]; then
# if poetry.lock is changed, we need to check everything
if [[ " $CHANGED_PYTHON_FILES " == *" uv.lock "* ]]; then
# if uv.lock is changed, we need to check everything
CHANGED_PYTHON_FILES="."
fi
echo "all_changed_files=$CHANGED_PYTHON_FILES" >> "$GITHUB_OUTPUT"
@@ -59,13 +59,13 @@ jobs:
- uses: actions/checkout@v5
- name: Install Python tools
uses: BrandonLWhite/pipx-install-action@v1.0.3
- uses: actions/setup-python@v6
- name: Install uv
uses: astral-sh/setup-uv@v8.1.0
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: poetry
- name: Install dependencies
run: poetry install --only=lint
run: uv sync --only-group lint
- name: Check code formatting
# the job output will contain colored diffs with what needs adjusting
@@ -80,13 +80,13 @@ jobs:
- uses: actions/checkout@v5
- name: Install Python tools
uses: BrandonLWhite/pipx-install-action@v1.0.3
- uses: actions/setup-python@v6
- name: Install uv
uses: astral-sh/setup-uv@v8.1.0
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: poetry
- name: Install dependencies
run: poetry install --only=lint
run: uv sync --only-group lint
- name: Lint code
run: poe lint --output-format=github ${{ needs.changed-files.outputs.changed_python_files }}
@@ -100,13 +100,13 @@ jobs:
- uses: actions/checkout@v5
- name: Install Python tools
uses: BrandonLWhite/pipx-install-action@v1.0.3
- uses: actions/setup-python@v6
- name: Install uv
uses: astral-sh/setup-uv@v8.1.0
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: poetry
- name: Install dependencies
run: poetry install --only=typing
run: uv sync --only-group typing
- name: Type check code
uses: liskin/gh-problem-matcher-wrap@v3
@@ -125,13 +125,13 @@ jobs:
fetch-depth: 0 # needed to get the full git history for the changelog check
- name: Install Python tools
uses: BrandonLWhite/pipx-install-action@v1.0.3
- uses: actions/setup-python@v6
- name: Install uv
uses: astral-sh/setup-uv@v8.1.0
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: poetry
- name: Install dependencies
run: poetry install --extras=docs
run: uv sync --extra docs
- name: Add Sphinx problem matchers
run: |

View File

@@ -20,13 +20,13 @@ jobs:
- uses: actions/checkout@v5
- name: Install Python tools
uses: BrandonLWhite/pipx-install-action@v1.0.3
- uses: actions/setup-python@v6
- name: Install uv
uses: astral-sh/setup-uv@v8.1.0
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: poetry
- name: Install dependencies
run: poetry install --with=release --extras=docs
run: uv sync --group release --extra docs
- name: Bump project version
run: poe bump "${{ env.NEW_VERSION }}"
@@ -51,13 +51,13 @@ jobs:
- name: Install Python tools
uses: BrandonLWhite/pipx-install-action@v1.0.3
- uses: actions/setup-python@v6
- name: Install uv
uses: astral-sh/setup-uv@v8.1.0
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: poetry
- name: Install dependencies
run: poetry install --with=release --extras=docs
run: uv sync --group release --extra docs
- name: Install pandoc
run: sudo apt update && sudo apt install pandoc -y

View File

@@ -65,26 +65,27 @@ Development Tools
In order to develop beets, you will need a few tools installed:
- poetry_ for packaging, virtual environment and dependency management
- uv_ for packaging, virtual environment and dependency management
- poethepoet_ to run tasks, such as linting, formatting, testing
Python community recommends using pipx_ to install stand-alone command-line
applications such as above. pipx_ installs each application in an isolated
virtual environment, where its dependencies will not interfere with your system
and other CLI tools.
Follow the `uv installation instructions
<https://docs.astral.sh/uv/getting-started/installation/>`__ to install uv_.
If you do not have pipx_ installed in your system, follow `pipx installation
instructions <https://pipx.pypa.io/stable/how-to/install-pipx/>`__ or
poethepoet_ is a stand-alone CLI tool. The Python community recommends using
pipx_ to install such tools in isolated environments so their dependencies don't
interfere with your system. If you don't have pipx_ installed, follow the `pipx
installation instructions <https://pipx.pypa.io/stable/how-to/install-pipx/>`__
or run:
.. code-block:: sh
$ python3 -m pip install --user pipx
Install poetry_ and poethepoet_ using pipx_:
Then install poethepoet_:
::
$ pipx install poetry poethepoet
$ pipx install poethepoet
.. admonition:: Check ``tool.pipx-install`` section in ``pyproject.toml`` to see supported versions
@@ -92,7 +93,6 @@ Install poetry_ and poethepoet_ using pipx_:
[tool.pipx-install]
poethepoet = ">=0.26"
poetry = "<2"
.. _getting-the-source:
@@ -100,44 +100,39 @@ Getting the Source
++++++++++++++++++
The easiest way to get started with the latest beets source is to clone the
repository and install ``beets`` in a local virtual environment using poetry_.
This can be done with:
repository and install ``beets`` in a local virtual environment using uv_. This
can be done with:
.. code-block:: bash
$ git clone https://github.com/beetbox/beets.git
$ cd beets
$ poetry install
$ uv sync
This will install ``beets`` and all development dependencies into its own
virtual environment in your ``$POETRY_CACHE_DIR``. See ``poetry install --help``
for installation options, including installing ``extra`` dependencies for
plugins.
This will install ``beets`` and all development dependencies into a ``.venv``
virtual environment. See ``uv sync --help`` for options, including installing
``extra`` dependencies for plugins (e.g. ``uv sync --extra fetchart``).
If you will build the documentation you will need to run the following command:
.. code-block:: bash
$ poetry install -E docs
$ uv sync --extra docs
This will install the optional dependencies for the documentation.
In order to run something within this virtual environment, start the command
with ``poetry run`` to them, for example ``poetry run pytest``.
On the other hand, it may get tedious to type ``poetry run`` before every
command. Instead, you can activate the virtual environment in your shell with:
To run commands within this virtual environment, either activate it:
::
$ poetry shell
$ source .venv/bin/activate
$ pytest
You should see ``(beets-py3.10)`` prefix in your shell prompt. Now you can run
commands directly, for example:
Or prefix commands with ``uv run``:
::
$ (beets-py3.10) pytest
$ uv run pytest
Additionally, poethepoet_ task runner assists us with the most common
operations. Formatting, linting, testing are defined as ``poe`` tasks in
@@ -371,7 +366,7 @@ Test Dependencies
The tests have a few more dependencies than beets itself. (The additional
dependencies consist of testing utilities and dependencies of non-default
plugins exercised by the test suite.) The dependencies are listed under the
``tool.poetry.group.test.dependencies`` section in pyproject.toml_.
``test`` group in the ``dependency-groups`` section of pyproject.toml_.
Writing Tests
~~~~~~~~~~~~~
@@ -443,8 +438,6 @@ contributor.
.. _poethepoet: https://poethepoet.natn.io/index.html
.. _poetry: https://python-poetry.org/docs/
.. _pyproject.toml: https://github.com/beetbox/beets/blob/master/pyproject.toml
.. _pytest: https://docs.pytest.org/en/stable/
@@ -459,4 +452,6 @@ contributor.
.. _unittest: https://docs.python.org/3/library/unittest.html
.. _uv: https://docs.astral.sh/uv/
.. _vim: https://www.vim.org/

View File

@@ -79,14 +79,12 @@ and you're good to go!
information, see for example pep-3119_.
.. [3] There are a variety of packaging tools available for python, for example
you can use poetry_, setuptools_ or hatchling_.
you can use setuptools_ or hatchling_.
.. _hatchling: https://hatch.pypa.io/latest/config/build/#build-system
.. _pep-3119: https://peps.python.org/pep-3119/#rationale
.. _poetry: https://python-poetry.org/docs/pyproject/#packages
.. _setuptools: https://setuptools.pypa.io/en/latest/userguide/package_discovery.html#finding-simple-packages
.. _this article: https://realpython.com/python-namespace-package/#setting-up-some-namespace-packages

View File

@@ -153,7 +153,8 @@ helpful to run on the "bleeding edge". To run the latest source:
.. code-block:: shell
git clone https://github.com/beetbox/beets.git
poetry install
cd beets
pip install -e .
This approach lets you decide where the source is stored, with any changes
immediately reflected in your environment.

View File

@@ -209,7 +209,7 @@ def validate_new_version(
) -> Version:
"""Validate the version is newer than the current one."""
with PYPROJECT.open("rb") as f:
current = parse(tomli.load(f)["tool"]["poetry"]["version"])
current = parse(tomli.load(f)["project"]["version"])
if not value > current:
msg = f"version must be newer than {current}"

4882
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,12 @@
[tool.poetry]
[project]
name = "beets"
version = "2.12.0"
description = "music tagger and library organizer"
authors = ["Adrian Sampson <adrian@radbox.org>"]
maintainers = ["Serene-Arc"]
license = "MIT"
authors = [{ name = "Adrian Sampson", email = "adrian@radbox.org" }]
maintainers = [{ name = "Serene-Arc" }]
license = { text = "MIT" }
readme = "README.rst"
homepage = "https://beets.io/"
repository = "https://github.com/beetbox/beets"
documentation = "https://beets.readthedocs.io/en/stable/"
requires-python = ">=3.10,<3.15"
classifiers = [
"Topic :: Multimedia :: Sound/Audio",
"Topic :: Multimedia :: Sound/Audio :: Players :: MP3",
@@ -24,139 +22,86 @@ classifiers = [
"Programming Language :: Python :: 3.14",
"Programming Language :: Python :: Implementation :: CPython",
]
packages = [
{ include = "beets" },
{ include = "beetsplug" },
dependencies = [
"colorama ; sys_platform == 'win32'",
"confuse>=2.2.0",
"jellyfish",
"lap>=0.5.12",
"mediafile>=0.17.0",
"numpy>=2.0.2 ; python_version < '3.13'",
"numpy>=2.3.5 ; python_version >= '3.13'",
"packaging>=24.0",
"platformdirs>=3.5.0",
"pyyaml",
"requests>=2.32.5",
"requests-ratelimiter>=0.7.0",
"typing_extensions",
"unidecode>=1.3.6",
]
include = [ # extra files to include in the sdist
{ path = "docs", format = "sdist" },
{ path = "extra", format = "sdist" },
{ path = "man/**/*", format = "sdist" },
{ path = "test/*.py", format = "sdist" },
{ path = "test/rsrc/**/*", format = "sdist" },
[dependency-groups]
test = [
"beautifulsoup4",
"codecov>=2.1.13",
"flask",
"langdetect",
"pylast",
"pytest",
"pytest-cov",
"pytest-factoryboy>=2.8.1",
"pytest-flask",
"python-mpd2",
"python3-discogs-client>=2.3.15",
"py7zr",
"pyxdg",
"rarfile",
"requests-mock>=1.12.1",
"requests-oauthlib",
"responses>=0.3.0",
"titlecase>=2.4.1,<3",
]
exclude = ["docs/_build", "docs/modd.conf", "docs/**/*.css"]
[tool.poetry.urls]
Changelog = "https://github.com/beetbox/beets/blob/master/docs/changelog.rst"
"Bug Tracker" = "https://github.com/beetbox/beets/issues"
[tool.poetry.dependencies]
python = ">=3.10,<3.15"
colorama = { version = "*", markers = "sys_platform == 'win32'" }
confuse = ">=2.2.0"
jellyfish = "*"
lap = ">=0.5.12"
mediafile = ">=0.17.0"
numpy = [
{ python = "<3.13", version = ">=2.0.2" },
{ python = ">=3.13", version = ">=2.3.5" },
lint = [
"docstrfmt>=2.0.2",
"ruff>=0.13.0",
"sphinx-lint>=1.0.0",
]
packaging = ">=24.0"
platformdirs = ">=3.5.0"
pyyaml = "*"
requests = ">=2.32.5"
requests-ratelimiter = ">=0.7.0"
typing_extensions = "*"
unidecode = ">=1.3.6"
beautifulsoup4 = { version = "*", optional = true }
dbus-python = { version = "*", optional = true }
flask = { version = "*", optional = true }
flask-cors = { version = "*", optional = true }
langdetect = { version = "*", optional = true }
librosa = { version = ">=0.11", optional = true }
scipy = [ # for librosa
{ python = "<3.13", version = ">=1.13.1", optional = true },
{ python = ">=3.13", version = ">=1.16.1", optional = true },
typing = [
"mypy",
"types-beautifulsoup4",
"types-docutils>=0.22.2.20251006",
"types-Flask-Cors",
"types-Pillow",
"types-PyYAML",
"types-requests",
"types-urllib3",
]
numba = [ # for librosa
{ python = "<3.13", version = ">=0.60", optional = true },
{ python = ">=3.13", version = ">=0.63.1", optional = true },
release = [
"click>=8.1.7",
"tomli>=2.0.1",
]
mutagen = { version = ">=1.33", optional = true }
Pillow = { version = "*", optional = true }
py7zr = { version = "*", optional = true }
pyacoustid = { version = "^1.3.1", optional = true }
PyGObject = { version = "*", optional = true }
pylast = { version = "*", optional = true }
python-mpd2 = { version = ">=0.4.2", optional = true }
python3-discogs-client = { version = ">=2.3.15", optional = true }
pyxdg = { version = "*", optional = true }
rarfile = { version = "*", optional = true }
reflink = { version = "*", optional = true }
resampy = { version = ">=0.4.3", optional = true }
requests-oauthlib = { version = ">=0.6.1", optional = true }
soco = { version = "*", optional = true }
docutils = { version = ">=0.20.1", optional = true }
pydata-sphinx-theme = { version = "*", optional = true }
sphinx = { version = "<9", optional = true }
sphinx-design = { version = ">=0.6.1", optional = true }
sphinx-copybutton = { version = ">=0.5.2", optional = true }
sphinx-toolbox = { version = ">=4.1.0", optional = true }
titlecase = { version = "^2.4.1", optional = true }
[tool.poetry.group.test.dependencies]
beautifulsoup4 = "*"
codecov = ">=2.1.13"
flask = "*"
langdetect = "*"
pylast = "*"
pytest = "*"
pytest-cov = "*"
pytest-factoryboy = ">=2.8.1"
pytest-flask = "*"
python-mpd2 = "*"
python3-discogs-client = ">=2.3.15"
py7zr = "*"
pyxdg = "*"
rarfile = "*"
requests-mock = ">=1.12.1"
requests_oauthlib = "*"
responses = ">=0.3.0"
titlecase = "^2.4.1"
[tool.poetry.group.lint.dependencies]
docstrfmt = ">=2.0.2"
ruff = ">=0.13.0"
sphinx-lint = ">=1.0.0"
[tool.poetry.group.typing.dependencies]
mypy = "*"
types-beautifulsoup4 = "*"
types-docutils = ">=0.22.2.20251006"
types-Flask-Cors = "*"
types-Pillow = "*"
types-PyYAML = "*"
types-requests = "*"
types-urllib3 = "*"
[tool.poetry.group.release.dependencies]
click = ">=8.1.7"
tomli = ">=2.0.1"
[tool.poetry.extras]
[project.optional-dependencies]
# inline comments note required external / non-python dependencies
absubmit = ["requests"] # extractor binary from https://acousticbrainz.org/download
aura = ["flask", "flask-cors", "Pillow"]
autobpm = ["librosa", "resampy"]
autobpm = ["librosa>=0.11", "resampy>=0.4.3"]
# badfiles # mp3val and flac
beatport = ["requests-oauthlib"]
beatport = ["requests-oauthlib>=0.6.1"]
bpd = ["PyGObject"] # gobject-introspection, gstreamer1.0-plugins-base, python3-gst-1.0
chroma = ["pyacoustid"] # chromaprint or fpcalc
chroma = ["pyacoustid>=1.3.1,<2"] # chromaprint or fpcalc
# convert # ffmpeg
discogs = ["python3-discogs-client>=2.3.15"]
docs = [
"docutils",
"docutils>=0.20.1",
"pydata-sphinx-theme",
"sphinx",
"sphinx-lint",
"sphinx-design",
"sphinx-copybutton",
"sphinx-toolbox",
"sphinx<9",
"sphinx-lint>=1.0.0",
"sphinx-design>=0.6.1",
"sphinx-copybutton>=0.5.2",
"sphinx-toolbox>=4.1.0",
"titlecase>=2.4.1,<3",
]
discogs = ["python3-discogs-client"]
embedart = ["Pillow"] # ImageMagick
embyupdate = ["requests"]
fetchart = ["beautifulsoup4", "langdetect", "Pillow", "requests"]
@@ -168,29 +113,53 @@ lastgenre = ["pylast"]
lastimport = ["pylast"]
lyrics = ["beautifulsoup4", "langdetect", "requests"]
metasync = ["dbus-python"]
mpdstats = ["python-mpd2"]
mpdstats = ["python-mpd2>=0.4.2"]
plexupdate = ["requests"]
reflink = ["reflink"]
replaygain = [
"PyGObject",
] # python-gi and GStreamer 1.0+ or mp3gain/aacgain or Python Audio Tools or ffmpeg
scrub = ["mutagen"]
scrub = ["mutagen>=1.33"]
sonosupdate = ["soco"]
tidal = ["requests-oauthlib"]
tidal = ["requests-oauthlib>=0.6.1"]
titlecase = ["titlecase"]
thumbnails = ["Pillow", "pyxdg"]
web = ["flask", "flask-cors"]
[tool.poetry.scripts]
[project.scripts]
beet = "beets.ui:main"
[project.urls]
Homepage = "https://beets.io/"
Repository = "https://github.com/beetbox/beets"
Documentation = "https://beets.readthedocs.io/en/stable/"
Changelog = "https://github.com/beetbox/beets/blob/master/docs/changelog.rst"
"Bug Tracker" = "https://github.com/beetbox/beets/issues"
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["beets", "beetsplug"]
[tool.hatch.build.targets.sdist]
include = [
"beets/",
"beetsplug/",
"docs/",
"extra/",
"man/",
"test/",
]
exclude = [
"docs/_build/",
"docs/modd.conf",
"docs/**/*.css",
]
[tool.pipx-install]
poethepoet = ">=0.26"
poetry = ">=1.8,<2"
[tool.poe.tasks.build]
help = "Build the package"
@@ -198,7 +167,7 @@ shell = """
make -C docs man
rm -rf man
mv docs/_build/man .
poetry build
uv build
"""
[tool.poe.tasks.bump]
@@ -255,7 +224,7 @@ exit ${failed:-0}
[tool.poe.tasks.update-dependencies]
help = "Update dependencies to their latest versions."
cmd = "poetry update -vv"
cmd = "uv sync --upgrade"
[tool.poe.tasks.test]
help = "Run tests with pytest"

4417
uv.lock generated Normal file

File diff suppressed because it is too large Load Diff