mirror of
https://github.com/beetbox/beets.git
synced 2025-12-06 08:39:17 +01:00
Replace setup.py packaging by Poetry (#5266)
Migrate `beets` package configuration to Poetry which nowadays seems to be the gold standard. I have been using Poetry since 2019 and I have mostly been happy a happy user: it makes local dev setup easy and has the tools I need to maintain python packages day to day, including reliable dependency resolution, versioning and publishing to Pypi. It's a user-friendly tool, so it should make it more straightforward for contributors to setup and navigate the codebase, and ultimately, hopefully facilitate more frequent releases! Since poetry manages local virtual environment, we do not have much need for tox any more. Therefore, it was replaced by a task runner `poethepoet`. Type `poe` in the project directory to see the available commands. - [x] Documentation. (If you've added a new command-line flag, for example, find the appropriate page under `docs/` to describe it.) - [x] Changelog. (Add an entry to `docs/changelog.rst` to the bottom of one of the lists near the top of the document.) - [x] Tests. (Very much encouraged but not strictly required.)
This commit is contained in:
commit
d7bf28deed
38 changed files with 3448 additions and 618 deletions
16
.github/flake8-problem-matcher.json
vendored
16
.github/flake8-problem-matcher.json
vendored
|
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "flake8",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^(.*?):(\\d+):(\\d+): (.*)$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"column": 3,
|
||||
"message": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
25
.github/sphinx-problem-matcher.json
vendored
25
.github/sphinx-problem-matcher.json
vendored
|
|
@ -1,18 +1,15 @@
|
|||
{
|
||||
"problemMatcher": [
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "sphinx",
|
||||
"pattern": [
|
||||
{
|
||||
"owner": "sphinx",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^Warning, treated as error:$"
|
||||
},
|
||||
{
|
||||
"regexp": "^(.*?):(\\d+):(.*)$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"message": 3
|
||||
}
|
||||
]
|
||||
"regexp": "^([^:]+):(\\d+): (WARNING: )?(.+)$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"message": 4
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
120
.github/workflows/ci.yaml
vendored
120
.github/workflows/ci.yaml
vendored
|
|
@ -1,104 +1,56 @@
|
|||
name: ci
|
||||
name: Test
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
env:
|
||||
PY_COLORS: 1
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ${{ matrix.platform }}
|
||||
name: Run tests
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [ubuntu-latest, windows-latest]
|
||||
python-version: ["3.8", "3.9", "3.x"]
|
||||
|
||||
python-version: ["3.8", "3.9"]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
env:
|
||||
PY_COLORS: 1
|
||||
|
||||
IS_MAIN_PYTHON: ${{ matrix.python-version == '3.8' && matrix.platform == 'ubuntu-latest' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v2
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install Python tools
|
||||
uses: BrandonLWhite/pipx-install-action@v0.1.1
|
||||
- name: Setup Python with poetry caching
|
||||
# poetry cache requires poetry to already be installed, weirdly
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
cache: poetry
|
||||
|
||||
- name: Install base dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install tox sphinx
|
||||
|
||||
- name: Install optional dependencies
|
||||
if: matrix.platform != 'windows-latest'
|
||||
- name: Install PyGobject dependencies on Ubuntu
|
||||
if: matrix.platform == 'ubuntu-latest'
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install ffmpeg # For replaygain
|
||||
sudo apt install ffmpeg gobject-introspection libgirepository1.0-dev
|
||||
poetry install --extras replaygain
|
||||
|
||||
- name: Test older Python versions with tox
|
||||
if: matrix.python-version != '3.x'
|
||||
run: |
|
||||
tox -e py-test
|
||||
- name: Install Python dependencies
|
||||
run: poetry install --only=main,test
|
||||
|
||||
- name: Upload code coverage
|
||||
if: matrix.python-version == '3.8' && matrix.platform == 'ubuntu-latest'
|
||||
run: |
|
||||
pip install codecov || true
|
||||
codecov || true
|
||||
- if: ${{ ! env.IS_MAIN_PYTHON }}
|
||||
name: Test without coverage
|
||||
run: poe test --no-cov
|
||||
|
||||
- name: Test latest Python version with tox and mypy
|
||||
if: matrix.python-version == '3.x'
|
||||
# continue-on-error is not ideal since it doesn't give a visible
|
||||
# warning, but there doesn't seem to be anything better:
|
||||
# https://github.com/actions/toolkit/issues/399
|
||||
- if: ${{ env.IS_MAIN_PYTHON }}
|
||||
name: Test with coverage
|
||||
uses: liskin/gh-problem-matcher-wrap@v3
|
||||
with:
|
||||
linters: pytest
|
||||
run: poe test
|
||||
|
||||
- if: ${{ env.IS_MAIN_PYTHON }}
|
||||
name: Upload code coverage
|
||||
continue-on-error: true
|
||||
run: |
|
||||
tox -vv -e py-mypy
|
||||
|
||||
test-docs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
env:
|
||||
PY_COLORS: 1
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set up Python 3.x
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: "3.x"
|
||||
|
||||
- name: Install base dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install tox sphinx
|
||||
|
||||
- name: Add problem matcher
|
||||
run: echo "::add-matcher::.github/sphinx-problem-matcher.json"
|
||||
|
||||
- name: Build and check docs using tox
|
||||
run: tox -e docs
|
||||
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set up Python 3.x
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: "3.x"
|
||||
|
||||
- name: Install base dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install tox sphinx
|
||||
|
||||
- name: Add problem matcher
|
||||
run: echo "::add-matcher::.github/flake8-problem-matcher.json"
|
||||
|
||||
- name: Lint with flake8
|
||||
run: tox -e py-lint
|
||||
run: poetry run codecov
|
||||
|
|
|
|||
14
.github/workflows/formatting_check.yml
vendored
14
.github/workflows/formatting_check.yml
vendored
|
|
@ -1,14 +0,0 @@
|
|||
name: formatting_check
|
||||
run-name: Check code formatting
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
formatting_check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Run formatting check
|
||||
uses: paolorechia/pox@v1.0.1
|
||||
with:
|
||||
tox_env: "format_check"
|
||||
33
.github/workflows/integration_test.yaml
vendored
33
.github/workflows/integration_test.yaml
vendored
|
|
@ -2,34 +2,29 @@ name: integration tests
|
|||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 0 * * SUN' # run every Sunday at midnight
|
||||
- cron: "0 0 * * SUN" # run every Sunday at midnight
|
||||
jobs:
|
||||
test_integration:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
env:
|
||||
PY_COLORS: 1
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set up latest Python version
|
||||
uses: actions/setup-python@v2
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install Python tools
|
||||
uses: BrandonLWhite/pipx-install-action@v0.1.1
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.9-dev
|
||||
python-version: 3.8
|
||||
cache: poetry
|
||||
|
||||
- name: Install base dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install tox sphinx
|
||||
- name: Install dependencies
|
||||
run: poetry install
|
||||
|
||||
- name: Test with tox
|
||||
run: |
|
||||
tox -e int
|
||||
- name: Test
|
||||
env:
|
||||
INTEGRATION_TEST: 1
|
||||
run: poe test
|
||||
|
||||
- name: Check external links in docs
|
||||
run: |
|
||||
tox -e links
|
||||
run: poe check-docs-links
|
||||
|
||||
- name: Notify on failure
|
||||
if: ${{ failure() }}
|
||||
|
|
|
|||
128
.github/workflows/lint.yml
vendored
Normal file
128
.github/workflows/lint.yml
vendored
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
name: Lint check
|
||||
run-name: Lint code
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
env:
|
||||
PYTHON_VERSION: 3.8
|
||||
|
||||
jobs:
|
||||
changed-files:
|
||||
runs-on: ubuntu-latest
|
||||
name: Get changed files
|
||||
outputs:
|
||||
any_docs_changed: ${{ steps.changed-doc-files.outputs.any_changed }}
|
||||
any_python_changed: ${{ steps.changed-python-files.outputs.any_changed }}
|
||||
changed_doc_files: ${{ steps.changed-doc-files.outputs.all_changed_files }}
|
||||
changed_python_files: ${{ steps.changed-python-files.outputs.all_changed_files }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Get changed docs files
|
||||
id: changed-doc-files
|
||||
uses: tj-actions/changed-files@v44
|
||||
with:
|
||||
files: |
|
||||
docs/**
|
||||
- name: Get changed python files
|
||||
id: changed-python-files
|
||||
uses: tj-actions/changed-files@v44
|
||||
with:
|
||||
files: |
|
||||
**.py
|
||||
|
||||
format:
|
||||
if: needs.changed-files.outputs.any_python_changed == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
name: Check formatting
|
||||
needs: changed-files
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install Python tools
|
||||
uses: BrandonLWhite/pipx-install-action@v0.1.1
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
cache: poetry
|
||||
|
||||
- name: Install dependencies
|
||||
run: poetry install --only=format
|
||||
|
||||
- name: Check code formatting
|
||||
# the job output will contain colored diffs with what needs adjusting
|
||||
run: poe check-format
|
||||
|
||||
lint:
|
||||
if: needs.changed-files.outputs.any_python_changed == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
name: Check linting
|
||||
needs: changed-files
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install Python tools
|
||||
uses: BrandonLWhite/pipx-install-action@v0.1.1
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
cache: poetry
|
||||
|
||||
- name: Install dependencies
|
||||
run: poetry install --only=lint
|
||||
|
||||
- name: Lint code
|
||||
uses: liskin/gh-problem-matcher-wrap@v3
|
||||
with:
|
||||
linters: flake8
|
||||
run: poe lint ${{ needs.changed-files.outputs.changed_python_files }}
|
||||
|
||||
mypy:
|
||||
if: needs.changed-files.outputs.any_python_changed == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
name: Check types with mypy
|
||||
needs: changed-files
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install Python tools
|
||||
uses: BrandonLWhite/pipx-install-action@v0.1.1
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
cache: poetry
|
||||
|
||||
- name: Install dependencies
|
||||
run: poetry install --only=typing
|
||||
|
||||
- name: Type check code
|
||||
uses: liskin/gh-problem-matcher-wrap@v3
|
||||
continue-on-error: true
|
||||
with:
|
||||
linters: mypy
|
||||
run: poe check-types --show-column-numbers --no-error-summary ${{ needs.changed-files.outputs.changed_python_files }}
|
||||
|
||||
docs:
|
||||
if: needs.changed-files.outputs.any_docs_changed == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
name: Check docs
|
||||
needs: changed-files
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install Python tools
|
||||
uses: BrandonLWhite/pipx-install-action@v0.1.1
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
cache: poetry
|
||||
|
||||
- name: Install dependencies
|
||||
run: poetry install --only=docs
|
||||
|
||||
- name: Add Sphinx problem matcher
|
||||
run: echo "::add-matcher::.github/sphinx-problem-matcher.json"
|
||||
|
||||
- name: Build docs
|
||||
run: |
|
||||
poe docs |& tee /tmp/output
|
||||
# fail the job if there are issues
|
||||
grep -q " WARNING:" /tmp/output && exit 1 || exit 0
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -74,6 +74,7 @@ target/
|
|||
.env
|
||||
|
||||
# virtualenv
|
||||
env/
|
||||
venv/
|
||||
.venv/
|
||||
ENV/
|
||||
|
|
|
|||
146
CONTRIBUTING.rst
146
CONTRIBUTING.rst
|
|
@ -62,33 +62,84 @@ Programming
|
|||
information in the `“For Developers” section of the
|
||||
docs <https://beets.readthedocs.io/en/stable/dev/>`__.
|
||||
|
||||
.. _development-tools:
|
||||
|
||||
Development Tools
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
In order to develop beets, you will need a few tools installed:
|
||||
|
||||
- `poetry`_ 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.
|
||||
|
||||
If you do not have `pipx`_ installed in your system, follow `pipx-installation-instructions`_ or
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ python3 -m pip install --user pipx
|
||||
|
||||
Install `poetry`_ and `poethepoet`_ using `pipx`_::
|
||||
|
||||
$ pipx install poetry poethepoet
|
||||
|
||||
.. _pipx: https://pipx.pypa.io/stable
|
||||
.. _pipx-installation-instructions: https://pipx.pypa.io/stable/installation/
|
||||
|
||||
.. _getting-the-source:
|
||||
|
||||
Getting the Source
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The easiest way to get started with the latest beets source is to use
|
||||
`pip`_ to install an “editable” package. This
|
||||
can be done with one command:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pip install -e git+https://github.com/beetbox/beets.git#egg=beets
|
||||
|
||||
Or, equivalently:
|
||||
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:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ git clone https://github.com/beetbox/beets.git
|
||||
$ cd beets
|
||||
$ pip install -e .
|
||||
$ poetry install
|
||||
|
||||
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.
|
||||
|
||||
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::
|
||||
|
||||
$ poetry shell
|
||||
|
||||
You should see ``(beets-py38)`` prefix in your shell prompt. Now you can run
|
||||
commands directly, for example::
|
||||
|
||||
$ (beets-py38) pytest
|
||||
|
||||
Additionally, `poethepoet`_ task runner assists us with the most common
|
||||
operations. Formatting, linting, testing are defined as ``poe`` tasks in
|
||||
`pyproject.toml`_. Run::
|
||||
|
||||
$ poe
|
||||
|
||||
to see all available tasks. They can be used like this, for example
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ poe lint # check code style
|
||||
$ poe format # fix formatting issues
|
||||
$ poe test # run tests
|
||||
# ... fix failing tests
|
||||
$ poe test --lf # re-run failing tests (note the additional pytest option)
|
||||
$ poe check-types --pretty # check types with an extra option for mypy
|
||||
|
||||
If you already have a released version of beets installed, you may need
|
||||
to remove it first by typing ``pip uninstall beets``. The pip command
|
||||
above will put the beets source in a ``src/beets`` directory and install
|
||||
the ``beet`` CLI script to a standard location on your system. You may
|
||||
want to use the ``--src`` option to specify the parent directory where
|
||||
the source will be checked out and the ``--user`` option such that the
|
||||
package will be installed to your home directory (compare with the
|
||||
output of ``pip install --help``).
|
||||
|
||||
Code Contribution Ideas
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -116,6 +167,9 @@ Code Contribution Ideas
|
|||
Sphinx <https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html>`__
|
||||
to, for example, refer to a class name.
|
||||
|
||||
.. _poethepoet: https://poethepoet.natn.io/index.html
|
||||
.. _poetry: https://python-poetry.org/docs/
|
||||
|
||||
Your First Contribution
|
||||
=======================
|
||||
|
||||
|
|
@ -153,8 +207,7 @@ request and your code will ship in no time.
|
|||
listed.
|
||||
6. Add a changelog entry to ``docs/changelog.rst`` near the top of the
|
||||
document.
|
||||
7. Run the tests and style checker. The easiest way to run the tests is
|
||||
to use `tox`_. For more information on running tests, see :ref:`testing`.
|
||||
7. Run the tests and style checker, see :ref:`testing`.
|
||||
8. Push to your fork and open a pull request! We’ll be in touch shortly.
|
||||
9. If you add commits to a pull request, please add a comment or
|
||||
re-request a review after you push them since GitHub doesn’t
|
||||
|
|
@ -223,9 +276,9 @@ Style
|
|||
|
||||
We follow `black`_ formatting and `google's docstring format`_.
|
||||
|
||||
You can use ``tox -e lint`` to check your code for any style errors.
|
||||
Running ``tox -e format`` will automatically format your code according
|
||||
to the specifications required by the project.
|
||||
Use ``poe check-format`` and ``poe lint`` to check your code for style and
|
||||
linting errors. Running ``poe format`` will automatically format your code
|
||||
according to the specifications required by the project.
|
||||
|
||||
.. _black: https://black.readthedocs.io/en/stable/
|
||||
.. _google's docstring format: https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings
|
||||
|
|
@ -280,45 +333,45 @@ Testing
|
|||
Running the Tests
|
||||
-----------------
|
||||
|
||||
To run the tests for multiple Python versions, compile the docs, and
|
||||
check style, use `tox`_. Just type ``tox`` or use something like
|
||||
``tox -e py38`` to test a specific configuration. You can use the
|
||||
``--parallel`` flag to make this go faster.
|
||||
Use ``poe`` to run tests::
|
||||
|
||||
$ poe test [pytest options]
|
||||
|
||||
You can disable a hand-selected set of "slow" tests by setting the
|
||||
environment variable SKIP_SLOW_TESTS before running them.
|
||||
environment variable ``SKIP_SLOW_TESTS``, for example::
|
||||
|
||||
Other ways to run the tests:
|
||||
|
||||
- ``python testall.py`` (ditto)
|
||||
- ``python -m unittest discover -p 'test_*'`` (ditto)
|
||||
- `pytest`_
|
||||
$ SKIP_SLOW_TESTS=1 poe test
|
||||
|
||||
Coverage
|
||||
^^^^^^^^
|
||||
|
||||
``tox -e cov`` will add coverage info for tests: Coverage is pretty low
|
||||
still -- see the current status on `Codecov`_.
|
||||
Coverage is measured automatically when running the tests. If you find it takes
|
||||
a while to calculate, disable it::
|
||||
|
||||
$ poe test --no-cov
|
||||
|
||||
You are welcome to explore coverage by opening the HTML report in
|
||||
``.reports/html/index.html``.
|
||||
|
||||
Note that for each covered line the report shows **which tests cover it**
|
||||
(expand the list on the right-hand side of the affected line).
|
||||
|
||||
You can find project coverage status on `Codecov`_.
|
||||
|
||||
Red Flags
|
||||
^^^^^^^^^
|
||||
|
||||
The `pytest-random`_ plugin makes it easy to randomize the order of
|
||||
tests. ``py.test test --random`` will occasionally turn up failing tests
|
||||
tests. ``poe test --random`` will occasionally turn up failing tests
|
||||
that reveal ordering dependencies—which are bad news!
|
||||
|
||||
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 'test' in ``extras_require`` in `setup.py`_.
|
||||
To install the test dependencies, run ``python -m pip install .[test]``.
|
||||
Or, just run a test suite with ``tox`` which will install them
|
||||
automatically.
|
||||
|
||||
.. _setup.py: https://github.com/beetbox/beets/blob/master/setup.py
|
||||
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`_.
|
||||
|
||||
Writing Tests
|
||||
-------------
|
||||
|
|
@ -351,13 +404,12 @@ others. See `unittest.mock`_ for more info.
|
|||
|
||||
.. _Codecov: https://codecov.io/github/beetbox/beets
|
||||
.. _pytest-random: https://github.com/klrmn/pytest-random
|
||||
.. _tox: https://tox.readthedocs.io/en/latest/
|
||||
.. _pytest: https://docs.pytest.org/en/stable/
|
||||
.. _pyproject.toml: https://github.com/beetbox/beets/tree/master/pyproject.toml
|
||||
.. _test: https://github.com/beetbox/beets/tree/master/test
|
||||
.. _`https://github.com/beetbox/beets/blob/master/test/test_template.py#L224`: https://github.com/beetbox/beets/blob/master/test/test_template.py#L224
|
||||
.. _unittest: https://docs.python.org/3/library/unittest.html
|
||||
.. _integration test: https://github.com/beetbox/beets/actions?query=workflow%3A%22integration+tests%22
|
||||
.. _unittest.mock: https://docs.python.org/3/library/unittest.mock.html
|
||||
.. _documentation: https://beets.readthedocs.io/en/stable/
|
||||
.. _pip: https://pip.pypa.io/en/stable/
|
||||
.. _vim: https://www.vim.org/
|
||||
|
|
|
|||
|
|
@ -13,7 +13,27 @@ Bug fixes:
|
|||
|
||||
For packagers:
|
||||
|
||||
* The minimum Python version is now 3.8.
|
||||
* The minimum supported Python version is now 3.8.
|
||||
|
||||
Other changes:
|
||||
|
||||
* :doc:`contributing`: The project now uses `poetry` for packaging and
|
||||
dependency management. This change affects project management and mostly
|
||||
affects beets developers. Please see updates in :ref:`getting-the-source` and
|
||||
:ref:`testing` for more information.
|
||||
* :doc:`contributing`: Since `poetry` now manages local virtual environments,
|
||||
`tox` has been replaced by a task runner `poethepoet`. This change affects
|
||||
beets developers and contributors. Please see updates in the
|
||||
:ref:`development-tools` section for more details. Type ``poe`` while in
|
||||
the project directory to see the available commands.
|
||||
* Installation instructions have been made consistent across plugins
|
||||
documentation. Users should simply install `beets` with an `extra` of the
|
||||
corresponding plugin name in order to install extra dependencies for that
|
||||
plugin.
|
||||
* GitHub workflows have been reorganised for clarity: style, linting, type and
|
||||
docs checks now live in separate jobs and are named accordingly.
|
||||
* Added caching for dependency installation in all CI jobs which speeds them up
|
||||
a bit, especially the tests.
|
||||
|
||||
2.0.0 (May 30, 2024)
|
||||
--------------------
|
||||
|
|
|
|||
12
docs/conf.py
12
docs/conf.py
|
|
@ -11,8 +11,8 @@ master_doc = "index"
|
|||
project = "beets"
|
||||
copyright = "2016, Adrian Sampson"
|
||||
|
||||
version = '2.0'
|
||||
release = '2.0.0'
|
||||
version = "2.0"
|
||||
release = "2.0.0"
|
||||
|
||||
pygments_style = "sphinx"
|
||||
|
||||
|
|
@ -60,9 +60,9 @@ man_pages = [
|
|||
]
|
||||
|
||||
# Options for pydata theme
|
||||
html_theme = 'pydata_sphinx_theme'
|
||||
html_theme = "pydata_sphinx_theme"
|
||||
html_theme_options = {
|
||||
'collapse_navigation': True,
|
||||
"collapse_navigation": True,
|
||||
"logo": {
|
||||
"text": "beets",
|
||||
},
|
||||
|
|
@ -70,5 +70,5 @@ html_theme_options = {
|
|||
}
|
||||
html_title = "beets"
|
||||
html_logo = "_static/beets_logo_nobg.png"
|
||||
html_static_path = ['_static']
|
||||
html_css_files = ['beets.css']
|
||||
html_static_path = ["_static"]
|
||||
html_css_files = ["beets.css"]
|
||||
|
|
|
|||
15
docs/faq.rst
15
docs/faq.rst
|
|
@ -149,18 +149,19 @@ it's helpful to run on the "bleeding edge". To run the latest source:
|
|||
and ``python3`` instead of ``pip`` and ``python`` respectively.
|
||||
- Use ``pip`` to install the latest snapshot tarball. Type:
|
||||
``pip install https://github.com/beetbox/beets/tarball/master``
|
||||
- Grab the source using git. First, clone the repository:
|
||||
``git clone https://github.com/beetbox/beets.git``.
|
||||
Then, ``cd beets`` and ``python setup.py install``.
|
||||
- Use ``pip`` to install an "editable" version of beets based on an
|
||||
automatic source checkout. For example, run
|
||||
``pip install -e git+https://github.com/beetbox/beets#egg=beets``
|
||||
to clone beets and install it, allowing you to modify the source
|
||||
in-place to try out changes.
|
||||
- Combine the previous two approaches, cloning the source yourself,
|
||||
and then installing in editable mode:
|
||||
``git clone https://github.com/beetbox/beets.git`` then
|
||||
``pip install -e beets``. This approach lets you decide where the
|
||||
- Clone source code and install it in editable mode
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
git clone https://github.com/beetbox/beets.git
|
||||
poetry install
|
||||
|
||||
This approach lets you decide where the
|
||||
source is stored, with any changes immediately reflected in your
|
||||
environment.
|
||||
|
||||
|
|
|
|||
|
|
@ -21,13 +21,12 @@ to run. Its source can be found on `GitHub`_, and while it is possible to
|
|||
compile the extractor from source, AcousticBrainz would prefer if you used
|
||||
their binary (see the AcousticBrainz `FAQ`_).
|
||||
|
||||
The ``absubmit`` plugin also requires `requests`_, which you can install
|
||||
using `pip`_ by typing::
|
||||
Then, install ``beets`` with ``absubmit`` extra
|
||||
|
||||
pip install requests
|
||||
pip install "beets[absubmit]"
|
||||
|
||||
Lastly, enable the plugin in your configuration (see :ref:`using-plugins`).
|
||||
|
||||
After installing both the extractor binary and requests you can enable
|
||||
the plugin ``absubmit`` in your configuration (see :ref:`using-plugins`).
|
||||
|
||||
Submitting Data
|
||||
---------------
|
||||
|
|
|
|||
|
|
@ -12,19 +12,10 @@ read the :ref:`aura-issues` section.
|
|||
Install
|
||||
-------
|
||||
|
||||
The ``aura`` plugin depends on `Flask`_, which can be installed using
|
||||
``python -m pip install flask``. Then you can enable the ``aura`` plugin in
|
||||
your configuration (see :ref:`using-plugins`).
|
||||
To use the ``aura`` plugin, first enable it in your configuration (see
|
||||
:ref:`using-plugins`). Then, install ``beets`` with ``aura`` extra
|
||||
|
||||
It is likely that you will need to enable :ref:`aura-cors`, which introduces
|
||||
an additional dependency: `flask-cors`_. This can be installed with
|
||||
``python -m pip install flask-cors``.
|
||||
|
||||
If `Pillow`_ is installed (``python -m pip install Pillow``) then the optional
|
||||
``width`` and ``height`` attributes are included in image resource objects.
|
||||
|
||||
.. _flask-cors: https://flask-cors.readthedocs.io
|
||||
.. _Pillow: https://pillow.readthedocs.io
|
||||
pip install "beets[aura]"
|
||||
|
||||
|
||||
Usage
|
||||
|
|
|
|||
|
|
@ -10,13 +10,12 @@ both MusicBrainz and (to a lesser degree) `Discogs`_ show no matches.
|
|||
|
||||
Installation
|
||||
------------
|
||||
|
||||
To use the ``beatport`` plugin, first enable it in your configuration (see
|
||||
:ref:`using-plugins`). Then, install the `requests`_ and `requests_oauthlib`_
|
||||
libraries (which we need for querying and authorizing with the Beatport API)
|
||||
by typing::
|
||||
:ref:`using-plugins`). Then, install ``beets`` with ``beatport`` extra
|
||||
|
||||
pip install requests requests_oauthlib
|
||||
.. code-block:: bash
|
||||
|
||||
pip install "beets[beatport]"
|
||||
|
||||
You will also need to register for a `Beatport`_ account. The first time you
|
||||
run the :ref:`import-cmd` command after enabling the plugin, it will ask you
|
||||
|
|
@ -41,6 +40,4 @@ Configuration
|
|||
|
||||
This plugin can be configured like other metadata source plugins as described in :ref:`metadata-source-plugin-configuration`.
|
||||
|
||||
.. _requests: https://requests.readthedocs.io/en/master/
|
||||
.. _requests_oauthlib: https://github.com/requests/requests-oauthlib
|
||||
.. _Beatport: https://www.beatport.com/
|
||||
|
|
|
|||
|
|
@ -26,6 +26,13 @@ You will also need the various GStreamer plugin packages to make everything
|
|||
work. See the :doc:`/plugins/chroma` documentation for more information on
|
||||
installing GStreamer plugins.
|
||||
|
||||
Once you have system dependencies installed, install ``beets`` with ``bpd``
|
||||
extra which installs Python bindings for ``GStreamer``:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
pip install "beets[bpd]"
|
||||
|
||||
.. _GStreamer: https://gstreamer.freedesktop.org/download
|
||||
.. _Homebrew: https://brew.sh
|
||||
|
||||
|
|
|
|||
|
|
@ -23,18 +23,23 @@ If you're willing to pay the performance cost for fingerprinting, read on!
|
|||
Installing Dependencies
|
||||
-----------------------
|
||||
|
||||
To get fingerprinting working, you'll need to install three things: the
|
||||
`Chromaprint`_ library or command-line tool, an audio decoder, and the
|
||||
`pyacoustid`_ Python library (version 0.6 or later).
|
||||
To get fingerprinting working, you'll need to install three things:
|
||||
|
||||
First, install pyacoustid itself. You can do this using `pip`_, like so::
|
||||
1. `pyacoustid`_ Python library (version 0.6 or later). You can install it by
|
||||
installing ``beets`` with ``chroma`` extra
|
||||
|
||||
$ pip install pyacoustid
|
||||
.. code-block:: bash
|
||||
|
||||
.. _pip: https://pip.pypa.io
|
||||
pip install "beets[chroma]"
|
||||
|
||||
Then, you will need to install `Chromaprint`_, either as a dynamic library or
|
||||
in the form of a command-line tool (``fpcalc``).
|
||||
2. the `Chromaprint`_ library_ or |command-line-tool|_
|
||||
3. an |audio-decoder|_
|
||||
|
||||
.. |command-line-tool| replace:: command line tool
|
||||
.. |audio-decoder| replace:: audio decoder
|
||||
|
||||
|
||||
.. _command-line-tool:
|
||||
|
||||
Installing the Binary Command-Line Tool
|
||||
'''''''''''''''''''''''''''''''''''''''
|
||||
|
|
@ -47,6 +52,8 @@ executable somewhere like ``/usr/local/bin``.
|
|||
|
||||
.. _download: https://acoustid.org/chromaprint
|
||||
|
||||
.. _library:
|
||||
|
||||
Installing the Library
|
||||
''''''''''''''''''''''
|
||||
|
||||
|
|
@ -58,6 +65,11 @@ chromaprint``.
|
|||
|
||||
.. _Homebrew: https://brew.sh/
|
||||
|
||||
.. _audio-decoder:
|
||||
|
||||
Audio Decoder
|
||||
'''''''''''''
|
||||
|
||||
You will also need a mechanism for decoding audio files supported by the
|
||||
`audioread`_ library:
|
||||
|
||||
|
|
|
|||
|
|
@ -15,11 +15,11 @@ Installation
|
|||
------------
|
||||
|
||||
To use the ``discogs`` plugin, first enable it in your configuration (see
|
||||
:ref:`using-plugins`). Then, install the `python3-discogs-client`_ library by typing:
|
||||
:ref:`using-plugins`). Then, install ``beets`` with ``discogs`` extra
|
||||
|
||||
.. code-block:: console
|
||||
.. code-block:: bash
|
||||
|
||||
$ pip install python3-discogs-client
|
||||
pip install "beets[discogs]"
|
||||
|
||||
You will also need to register for a `Discogs`_ account, and provide
|
||||
authentication credentials via a personal access token or an OAuth2
|
||||
|
|
|
|||
|
|
@ -10,10 +10,15 @@ displaying album art in some media players (iPods, for example).
|
|||
Embedding Art Automatically
|
||||
---------------------------
|
||||
|
||||
To automatically embed discovered album art into imported files, just enable
|
||||
the ``embedart`` plugin (see :doc:`/plugins/index`). You'll also want to enable the
|
||||
:doc:`/plugins/fetchart` to obtain the images to be embedded. Art will be
|
||||
embedded after each album has its cover art set.
|
||||
To use the ``embedart`` plugin, first enable it in your configuration (see
|
||||
:ref:`using-plugins`). Then, install ``beets`` with ``embedart`` extra
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pip install "beets[embedart]"
|
||||
|
||||
You'll also want to enable the :doc:`/plugins/fetchart` to obtain the images to
|
||||
be embedded. Art will be embedded after each album has its cover art set.
|
||||
|
||||
This behavior can be disabled with the ``auto`` config option (see below).
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,20 @@
|
|||
EmbyUpdate Plugin
|
||||
=================
|
||||
|
||||
``embyupdate`` is a plugin that lets you automatically update `Emby`_'s library whenever you change your beets library.
|
||||
``embyupdate`` is a plugin that lets you automatically update `Emby`_'s library
|
||||
whenever you change your beets library.
|
||||
|
||||
To use ``embyupdate`` plugin, enable it in your configuration (see :ref:`using-plugins`). Then, you'll want to configure the specifics of your Emby server. You can do that using an ``emby:`` section in your ``config.yaml``, which looks like this::
|
||||
To use it, first enable the your configuration (see :ref:`using-plugins`).
|
||||
Then, install ``beets`` with ``embyupdate`` extra
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pip install "beets[embyupdate]"
|
||||
|
||||
Then, you'll want to configure the specifics of your Emby server. You can do
|
||||
that using an ``emby`` section in your ``config.yaml``
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
emby:
|
||||
host: localhost
|
||||
|
|
@ -11,14 +22,9 @@ To use ``embyupdate`` plugin, enable it in your configuration (see :ref:`using-p
|
|||
username: user
|
||||
apikey: apikey
|
||||
|
||||
To use the ``embyupdate`` plugin you need to install the `requests`_ library with::
|
||||
|
||||
pip install requests
|
||||
|
||||
With that all in place, you'll see beets send the "update" command to your Emby server every time you change your beets library.
|
||||
|
||||
.. _Emby: https://emby.media/
|
||||
.. _requests: https://requests.readthedocs.io/en/master/
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
|
|
|||
|
|
@ -5,13 +5,11 @@ The ``fetchart`` plugin retrieves album art images from various sources on the
|
|||
Web and stores them as image files.
|
||||
|
||||
To use the ``fetchart`` plugin, first enable it in your configuration (see
|
||||
:ref:`using-plugins`). Then, install the `requests`_ library by typing::
|
||||
:ref:`using-plugins`). Then, install ``beets`` with ``fetchart`` extra
|
||||
|
||||
pip install requests
|
||||
.. code-block:: bash
|
||||
|
||||
The plugin uses `requests`_ to fetch album art from the Web.
|
||||
|
||||
.. _requests: https://requests.readthedocs.io/en/master/
|
||||
pip install "beets[fetchart]"
|
||||
|
||||
Fetching Album Art During Import
|
||||
--------------------------------
|
||||
|
|
@ -260,10 +258,6 @@ the list of sources in your configuration.
|
|||
Spotify
|
||||
'''''''
|
||||
|
||||
Spotify backend requires `BeautifulSoup`_, which you can install using `pip`_ by typing::
|
||||
|
||||
pip install beautifulsoup4
|
||||
|
||||
Spotify backend is enabled by default and will update album art if a valid Spotify album id is found.
|
||||
|
||||
.. _pip: https://pip.pypa.io
|
||||
|
|
|
|||
|
|
@ -29,18 +29,21 @@ To update multiple Kodi instances, specify them as an array::
|
|||
pwd: kodi2
|
||||
|
||||
|
||||
To use the ``kodiupdate`` plugin you need to install the `requests`_ library with::
|
||||
To use the ``kodiupdate`` plugin, first enable it in your configuration (see
|
||||
:ref:`using-plugins`). Then, install ``beets`` with ``kodiupdate`` extra
|
||||
|
||||
pip install requests
|
||||
.. code-block:: bash
|
||||
|
||||
pip install "beets[kodiupdate]"
|
||||
|
||||
You'll also need to enable JSON-RPC in Kodi.
|
||||
|
||||
You'll also need to enable JSON-RPC in Kodi in order the use the plugin.
|
||||
In Kodi's interface, navigate to System/Settings/Network/Services and choose "Allow control of Kodi via HTTP."
|
||||
|
||||
With that all in place, you'll see beets send the "update" command to your Kodi
|
||||
host every time you change your beets library.
|
||||
|
||||
.. _Kodi: https://kodi.tv/
|
||||
.. _requests: https://requests.readthedocs.io/en/master/
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
|
|
|||
|
|
@ -10,12 +10,12 @@ to your albums and items.
|
|||
Installation
|
||||
------------
|
||||
|
||||
The plugin requires `pylast`_, which you can install using `pip`_ by typing::
|
||||
To use the ``lastgenre`` plugin, first enable it in your configuration (see
|
||||
:ref:`using-plugins`). Then, install ``beets`` with ``lastgenre`` extra
|
||||
|
||||
pip install pylast
|
||||
.. code-block:: bash
|
||||
|
||||
After you have pylast installed, enable the ``lastgenre`` plugin in your
|
||||
configuration (see :ref:`using-plugins`).
|
||||
pip install "beets[lastgenre]"
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
|
@ -31,8 +31,6 @@ The genre list file should contain one genre per line. Blank lines are ignored.
|
|||
For the curious, the default genre list is generated by a `script that scrapes
|
||||
Wikipedia`_.
|
||||
|
||||
.. _pip: https://pip.pypa.io
|
||||
.. _pylast: https://github.com/pylast/pylast
|
||||
.. _script that scrapes Wikipedia: https://gist.github.com/1241307
|
||||
.. _internal whitelist: https://raw.githubusercontent.com/beetbox/beets/master/beetsplug/lastgenre/genres.txt
|
||||
|
||||
|
|
|
|||
|
|
@ -11,21 +11,18 @@ with this field.
|
|||
Installation
|
||||
------------
|
||||
|
||||
The plugin requires `pylast`_, which you can install using `pip`_ by typing::
|
||||
To use the ``lastimport`` plugin, first enable it in your configuration (see
|
||||
:ref:`using-plugins`). Then, install ``beets`` with ``lastimport`` extra
|
||||
|
||||
pip install pylast
|
||||
.. code-block:: bash
|
||||
|
||||
After you have pylast installed, enable the ``lastimport`` plugin in your
|
||||
configuration (see :ref:`using-plugins`).
|
||||
pip install "beets[lastimport]"
|
||||
|
||||
Next, add your Last.fm username to your beets configuration file::
|
||||
|
||||
lastfm:
|
||||
user: beetsfanatic
|
||||
|
||||
.. _pip: https://pip.pypa.io
|
||||
.. _pylast: https://github.com/pylast/pylast
|
||||
|
||||
Importing Play Counts
|
||||
---------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -13,22 +13,19 @@ and, optionally, the Google custom search API.
|
|||
Fetch Lyrics During Import
|
||||
--------------------------
|
||||
|
||||
To automatically fetch lyrics for songs you import, enable the ``lyrics``
|
||||
plugin in your configuration (see :ref:`using-plugins`).
|
||||
Then, install the `requests`_ library by typing::
|
||||
To automatically fetch lyrics for songs you import, first enable it in your
|
||||
configuration (see :ref:`using-plugins`). Then, install ``beets`` with
|
||||
``lyrics`` extra
|
||||
|
||||
pip install requests
|
||||
.. code-block:: bash
|
||||
|
||||
The plugin uses `requests`_ to download lyrics.
|
||||
pip install "beets[lyrics]"
|
||||
|
||||
When importing new files, beets will now fetch lyrics for files that don't
|
||||
already have them. The lyrics will be stored in the beets database. If the
|
||||
``import.write`` config option is on, then the lyrics will also be written to
|
||||
the files' tags.
|
||||
|
||||
.. _requests: https://requests.readthedocs.io/en/master/
|
||||
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
|
|
@ -130,12 +127,7 @@ few suggestions.
|
|||
Activate Google Custom Search
|
||||
------------------------------
|
||||
|
||||
Using the Google backend requires `BeautifulSoup`_, which you can install
|
||||
using `pip`_ by typing::
|
||||
|
||||
pip install beautifulsoup4
|
||||
|
||||
You also need to `register for a Google API key`_. Set the ``google_API_key``
|
||||
You need to `register for a Google API key`_. Set the ``google_API_key``
|
||||
configuration option to your key.
|
||||
Then add ``google`` to the list of sources in your configuration (or use
|
||||
default list, which includes it as long as you have an API key).
|
||||
|
|
@ -153,17 +145,11 @@ default, beets use a list of sources known to be scrapeable.
|
|||
Note that the Google custom search API is limited to 100 queries per day.
|
||||
After that, the lyrics plugin will fall back on other declared data sources.
|
||||
|
||||
.. _pip: https://pip.pypa.io
|
||||
.. _BeautifulSoup: https://www.crummy.com/software/BeautifulSoup/bs4/doc/
|
||||
|
||||
Activate Genius and Tekstowo.pl Lyrics
|
||||
--------------------------------------
|
||||
|
||||
Using the Genius or Tekstowo.pl backends requires `BeautifulSoup`_, which
|
||||
you can install using `pip`_ by typing::
|
||||
|
||||
pip install beautifulsoup4
|
||||
|
||||
These backends are enabled by default.
|
||||
|
||||
.. _lyrics-translation:
|
||||
|
|
@ -171,16 +157,10 @@ These backends are enabled by default.
|
|||
Activate On-the-Fly Translation
|
||||
-------------------------------
|
||||
|
||||
Using the Bing Translation API requires `langdetect`_, which you can install
|
||||
using `pip`_ by typing::
|
||||
|
||||
pip install langdetect
|
||||
|
||||
You also need to register for a Microsoft Azure Marketplace free account and
|
||||
You need to register for a Microsoft Azure Marketplace free account and
|
||||
to the `Microsoft Translator API`_. Follow the four steps process, specifically
|
||||
at step 3 enter ``beets`` as *Client ID* and copy/paste the generated
|
||||
*Client secret* into your ``bing_client_secret`` configuration, alongside
|
||||
``bing_lang_to`` target `language code`.
|
||||
|
||||
.. _langdetect: https://pypi.python.org/pypi/langdetect
|
||||
.. _Microsoft Translator API: https://docs.microsoft.com/en-us/azure/cognitive-services/translator/translator-how-to-signup
|
||||
|
|
|
|||
|
|
@ -19,8 +19,12 @@ Installation
|
|||
Enable the ``metasync`` plugin in your configuration (see
|
||||
:ref:`using-plugins`).
|
||||
|
||||
To synchronize with Amarok, you'll need the `dbus-python`_ library. There are
|
||||
packages for most major Linux distributions.
|
||||
To synchronize with Amarok, you'll need the `dbus-python`_ library. In such
|
||||
case, install ``beets`` with ``metasync`` extra
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pip install "beets[metasync]"
|
||||
|
||||
.. _dbus-python: https://dbus.freedesktop.org/releases/dbus-python/
|
||||
|
||||
|
|
|
|||
|
|
@ -21,13 +21,10 @@ Installing Dependencies
|
|||
This plugin requires the python-mpd2 library in order to talk to the MPD
|
||||
server.
|
||||
|
||||
Install the library from `pip`_, like so::
|
||||
To use the ``mpdstats`` plugin, first enable it in your configuration (see
|
||||
:ref:`using-plugins`). Then, install ``beets`` with ``mpdstats`` extra
|
||||
|
||||
$ pip install python-mpd2
|
||||
|
||||
Add the ``mpdstats`` plugin to your configuration (see :ref:`using-plugins`).
|
||||
|
||||
.. _pip: https://pip.pypa.io
|
||||
pip install "beets[mpdstats]"
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
|
|
|||
|
|
@ -4,11 +4,15 @@ PlexUpdate Plugin
|
|||
``plexupdate`` is a very simple plugin for beets that lets you automatically
|
||||
update `Plex`_'s music library whenever you change your beets library.
|
||||
|
||||
To use ``plexupdate`` plugin, enable it in your configuration
|
||||
(see :ref:`using-plugins`).
|
||||
Then, you'll probably want to configure the specifics of your Plex server.
|
||||
You can do that using an ``plex:`` section in your ``config.yaml``,
|
||||
which looks like this:
|
||||
Firstly, install ``beets`` with ``plexupdate`` extra
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
pip install "beets[plexupdate]"
|
||||
|
||||
Then, enable ``plexupdate`` plugin it in your configuration (see :ref:`using-plugins`).
|
||||
Optionally, configure the specifics of your Plex server. You can do this using
|
||||
a ``plex:`` section in your ``config.yaml``:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
|
|
@ -19,17 +23,10 @@ which looks like this:
|
|||
|
||||
The ``token`` key is optional: you'll need to use it when in a Plex Home (see Plex's own `documentation about tokens`_).
|
||||
|
||||
To use the ``plexupdate`` plugin you need to install the `requests`_ library with:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ pip install beets[plexupdate]
|
||||
|
||||
With that all in place, you'll see beets send the "update" command to your Plex
|
||||
server every time you change your beets library.
|
||||
|
||||
.. _Plex: https://plex.tv/
|
||||
.. _requests: https://requests.readthedocs.io/en/master/
|
||||
.. _documentation about tokens: https://support.plex.tv/hc/en-us/articles/204059436-Finding-your-account-token-X-Plex-Token
|
||||
|
||||
Configuration
|
||||
|
|
@ -48,4 +45,4 @@ The available options under the ``plex:`` section are:
|
|||
- **secure**: Use secure connections to the Plex server.
|
||||
Default: ``False``
|
||||
- **ignore_cert_errors**: Ignore TLS certificate errors when using secure connections.
|
||||
Default: ``False``
|
||||
Default: ``False``
|
||||
|
|
|
|||
|
|
@ -33,8 +33,16 @@ You will need at least GStreamer 1.0 and `PyGObject 3.x`_ (a.k.a. ``python-gi``)
|
|||
.. _PyGObject 3.x: https://pygobject.readthedocs.io/en/latest/
|
||||
.. _GStreamer: https://gstreamer.freedesktop.org/
|
||||
|
||||
Then, enable the ``replaygain`` plugin (see :ref:`using-plugins`) and specify
|
||||
the GStreamer backend by adding this to your configuration file::
|
||||
Then, install ``beets`` with ``replaygain`` extra which installs
|
||||
``GStreamer`` bindings for Python
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pip install "beets[replaygain]"
|
||||
|
||||
Lastly, enable the ``replaygain`` plugin in your configuration (see
|
||||
:ref:`using-plugins`) and specify the GStreamer backend by adding this to your
|
||||
configuration file::
|
||||
|
||||
replaygain:
|
||||
backend: gstreamer
|
||||
|
|
|
|||
|
|
@ -10,11 +10,17 @@ also provides a command that lets you manually remove files' tags.
|
|||
Automatic Scrubbing
|
||||
-------------------
|
||||
|
||||
To automatically remove files' tags before writing new ones, just
|
||||
enable the ``scrub`` plugin (see :ref:`using-plugins`). When importing new files (with
|
||||
``import.write`` turned on) or modifying files' tags with the ``beet modify``
|
||||
command, beets will first strip all types of tags entirely and then write the
|
||||
database-tracked metadata to the file.
|
||||
To automatically remove files' tags before writing new ones, enable ``scrub``
|
||||
plugin in your configuration (see :ref:`using-plugins`) and install ``beets``
|
||||
with ``scrub`` extra
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pip install "beets[scrub]"
|
||||
|
||||
When importing new files (with ``import.write`` turned on) or modifying files'
|
||||
tags with the ``beet modify`` command, beets will first strip all types of tags
|
||||
entirely and then write the database-tracked metadata to the file.
|
||||
|
||||
This behavior can be disabled with the ``auto`` config option (see below).
|
||||
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@ library whenever you change your beets library.
|
|||
To use ``sonosupdate`` plugin, enable it in your configuration
|
||||
(see :ref:`using-plugins`).
|
||||
|
||||
To use the ``sonosupdate`` plugin you need to install the `soco`_ library with::
|
||||
To use the ``sonosupdate`` plugin, first enable it in your configuration (see
|
||||
:ref:`using-plugins`). Then, install ``beets`` with ``sonosupdate`` extra
|
||||
|
||||
pip install soco
|
||||
pip install "beets[sonosupdate]"
|
||||
|
||||
With that all in place, you'll see beets send the "update" command to your Sonos
|
||||
controller every time you change your beets library.
|
||||
|
||||
.. _Sonos: https://sonos.com/
|
||||
.. _soco: http://python-soco.com
|
||||
|
|
|
|||
|
|
@ -5,11 +5,15 @@ The ``thumbnails`` plugin creates thumbnails for your album folders with the
|
|||
album cover. This works on freedesktop.org-compliant file managers such as
|
||||
Nautilus or Thunar, and is therefore POSIX-only.
|
||||
|
||||
To use the ``thumbnails`` plugin, enable it (see :doc:`/plugins/index`) as well
|
||||
as the :doc:`/plugins/fetchart`. You'll need 2 additional python packages:
|
||||
:pypi:`pyxdg` and :pypi:`pathlib`.
|
||||
To use the ``thumbnails`` plugin, enable ``thumbnails`` and
|
||||
:doc:`/plugins/fetchart` in your configuration (see :ref:`using-plugins`) and
|
||||
install ``beets`` with ``thumbnails`` and ``fetchart`` extras
|
||||
|
||||
``thumbnails`` needs to resize the covers, and therefore requires either
|
||||
.. code-block:: bash
|
||||
|
||||
pip install "beets[fetchart,thumbnails]"
|
||||
|
||||
``thumbnails`` need to resize the covers, and therefore requires either
|
||||
`ImageMagick`_ or `Pillow`_.
|
||||
|
||||
.. _Pillow: https://github.com/python-pillow/Pillow
|
||||
|
|
|
|||
|
|
@ -15,16 +15,12 @@ drastically increase the number of people who can use beets.
|
|||
Install
|
||||
-------
|
||||
|
||||
The Web interface depends on `Flask`_. To get it, just run ``pip install
|
||||
flask``. Then enable the ``web`` plugin in your configuration (see
|
||||
:ref:`using-plugins`).
|
||||
To use the ``web`` plugin, first enable it in your configuration (see
|
||||
:ref:`using-plugins`). Then, install ``beets`` with ``web`` extra
|
||||
|
||||
If you need CORS (it's disabled by default---see :ref:`web-cors`, below), then
|
||||
you also need `flask-cors`_. Just type ``pip install flask-cors``.
|
||||
|
||||
.. _flask-cors: https://github.com/CoryDolphin/flask-cors
|
||||
.. _CORS: https://en.wikipedia.org/wiki/Cross-origin_resource_sharing
|
||||
.. code-block:: bash
|
||||
|
||||
pip install "beets[web]"
|
||||
|
||||
Run the Server
|
||||
--------------
|
||||
|
|
@ -101,8 +97,7 @@ server as the API. (You will get an arcane error about ``XMLHttpRequest``
|
|||
otherwise.) A technology called `CORS`_ lets you relax this restriction.
|
||||
|
||||
If you want to use an in-browser client hosted elsewhere (or running from a
|
||||
different server on your machine), first install the `flask-cors`_ plugin by
|
||||
typing ``pip install flask-cors``. Then set the ``cors`` configuration option to
|
||||
different server on your machine), set the ``cors`` configuration option to
|
||||
the "origin" (protocol, host, and optional port number) where the client is
|
||||
served. Or set it to ``'*'`` to enable access from all origins. Note that there
|
||||
are security implications if you set the origin to ``'*'``, so please research
|
||||
|
|
@ -118,6 +113,7 @@ For example::
|
|||
host: 0.0.0.0
|
||||
cors: 'http://example.com'
|
||||
|
||||
.. _CORS: https://en.wikipedia.org/wiki/Cross-origin_resource_sharing
|
||||
.. _reverse-proxy:
|
||||
|
||||
Reverse Proxy Support
|
||||
|
|
|
|||
|
|
@ -11,10 +11,11 @@ from pathlib import Path
|
|||
from typing import Callable
|
||||
|
||||
import click
|
||||
import tomli
|
||||
from packaging.version import Version, parse
|
||||
|
||||
BASE = Path(__file__).parent.parent.absolute()
|
||||
BEETS_INIT = BASE / "beets" / "__init__.py"
|
||||
PYPROJECT = BASE / "pyproject.toml"
|
||||
CHANGELOG = BASE / "docs" / "changelog.rst"
|
||||
|
||||
MD_CHANGELOG_SECTION_LIST = re.compile(r"- .+?(?=\n\n###|$)", re.DOTALL)
|
||||
|
|
@ -51,7 +52,11 @@ Changelog goes here! Please add your entry to the bottom of one of the lists bel
|
|||
UpdateVersionCallable = Callable[[str, Version], str]
|
||||
FILENAME_AND_UPDATE_TEXT: list[tuple[Path, UpdateVersionCallable]] = [
|
||||
(
|
||||
BEETS_INIT,
|
||||
PYPROJECT,
|
||||
lambda text, new: re.sub(r"(?<=\nversion = )[^\n]+", f'"{new}"', text),
|
||||
),
|
||||
(
|
||||
BASE / "beets" / "__init__.py",
|
||||
lambda text, new: re.sub(
|
||||
r"(?<=__version__ = )[^\n]+", f'"{new}"', text
|
||||
),
|
||||
|
|
@ -65,12 +70,8 @@ def validate_new_version(
|
|||
ctx: click.Context, param: click.Argument, value: Version
|
||||
) -> Version:
|
||||
"""Validate the version is newer than the current one."""
|
||||
with BEETS_INIT.open() as f:
|
||||
contents = f.read()
|
||||
|
||||
m = re.search(r'(?<=__version__ = ")[^"]+', contents)
|
||||
assert m, "Current version not found in __init__.py"
|
||||
current = parse(m.group())
|
||||
with PYPROJECT.open("rb") as f:
|
||||
current = parse(tomli.load(f)["tool"]["poetry"]["version"])
|
||||
|
||||
if not value > current:
|
||||
msg = f"version must be newer than {current}"
|
||||
|
|
|
|||
2755
poetry.lock
generated
Normal file
2755
poetry.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
215
pyproject.toml
215
pyproject.toml
|
|
@ -1,3 +1,217 @@
|
|||
[tool.poetry]
|
||||
name = "beets"
|
||||
version = "2.0.0"
|
||||
description = "music tagger and library organizer"
|
||||
authors = ["Adrian Sampson <adrian@radbox.org>"]
|
||||
maintainers = ["Serene-Arc"]
|
||||
license = "MIT"
|
||||
readme = "README.rst"
|
||||
homepage = "https://beets.io/"
|
||||
repository = "https://github.com/beetbox/beets"
|
||||
documentation = "https://beets.readthedocs.io/en/stable/"
|
||||
classifiers = [
|
||||
"Topic :: Multimedia :: Sound/Audio",
|
||||
"Topic :: Multimedia :: Sound/Audio :: Players :: MP3",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Environment :: Console",
|
||||
"Environment :: Web Environment",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: Implementation :: CPython",
|
||||
]
|
||||
packages = [
|
||||
{ include = "beets" },
|
||||
{ include = "beetsplug" },
|
||||
]
|
||||
|
||||
[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.8,<4"
|
||||
|
||||
click = ">=8.1.7"
|
||||
colorama = { version = "*", markers = "sys_platform == 'win32'" }
|
||||
confuse = ">=1.5.0"
|
||||
jellyfish = "*"
|
||||
mediafile = ">=0.12.0"
|
||||
munkres = ">=1.0.0"
|
||||
musicbrainzngs = ">=0.4"
|
||||
packaging = ">=24.0"
|
||||
pyyaml = "*"
|
||||
tomli = ">=2.0.1"
|
||||
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 }
|
||||
mutagen = { version = ">=1.33", optional = true }
|
||||
Pillow = { version = "*", optional = true }
|
||||
py7zr = { version = "*", optional = true }
|
||||
pyacoustid = { version = "*", 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 }
|
||||
requests = { version = "*", optional = true }
|
||||
requests-oauthlib = { version = ">=0.6.1", optional = true }
|
||||
soco = { version = "*", optional = true }
|
||||
|
||||
[tool.poetry.group.test.dependencies]
|
||||
beautifulsoup4 = "*"
|
||||
codecov = ">=2.1.13"
|
||||
flask = "*"
|
||||
mock = "*"
|
||||
pylast = "*"
|
||||
pytest = "*"
|
||||
pytest-cov = "*"
|
||||
pytest-flask = "*"
|
||||
python-mpd2 = "*"
|
||||
python3-discogs-client = ">=2.3.15"
|
||||
py7zr = "*"
|
||||
pyxdg = "*"
|
||||
rarfile = "*"
|
||||
reflink = "*"
|
||||
requests_oauthlib = "*"
|
||||
responses = ">=0.3.0"
|
||||
|
||||
[tool.poetry.group.format.dependencies]
|
||||
isort = { version = "<5.14", extras = ["colors"] }
|
||||
black = "<24.3"
|
||||
|
||||
[tool.poetry.group.lint.dependencies]
|
||||
flake8 = "*"
|
||||
flake8-docstrings = "*"
|
||||
pep8-naming = "*"
|
||||
|
||||
[tool.poetry.group.typing.dependencies]
|
||||
mypy = "*"
|
||||
types-beautifulsoup4 = "*"
|
||||
types-Flask-Cors = "*"
|
||||
types-Pillow = "*"
|
||||
types-PyYAML = "*"
|
||||
types-requests = "*"
|
||||
types-urllib3 = "*"
|
||||
|
||||
[tool.poetry.group.docs.dependencies]
|
||||
pydata-sphinx-theme = "*"
|
||||
sphinx = "*"
|
||||
|
||||
[tool.poetry.extras]
|
||||
# inline comments note required external / non-python dependencies
|
||||
absubmit = ["requests"] # extractor binary from https://acousticbrainz.org/download
|
||||
aura = ["flask", "flask-cors", "Pillow"]
|
||||
# badfiles # mp3val and flac
|
||||
beatport = ["requests-oauthlib"]
|
||||
bpd = ["PyGObject"] # python-gi and GStreamer 1.0+
|
||||
chroma = ["pyacoustid"] # chromaprint or fpcalc
|
||||
# convert # ffmpeg
|
||||
discogs = ["python3-discogs-client"]
|
||||
embedart = ["Pillow"] # ImageMagick
|
||||
embyupdate = ["requests"]
|
||||
fetchart = ["beautifulsoup4", "langdetect", "Pillow", "requests"]
|
||||
import = ["py7zr", "rarfile"]
|
||||
# ipfs # go-ipfs
|
||||
# keyfinder # KeyFinder
|
||||
kodiupdate = ["requests"]
|
||||
lastgenre = ["pylast"]
|
||||
lastimport = ["pylast"]
|
||||
lyrics = ["beautifulsoup4", "langdetect", "requests"]
|
||||
metasync = ["dbus-python"]
|
||||
mpdstats = ["python-mpd2"]
|
||||
plexupdate = ["requests"]
|
||||
reflink = ["reflink"]
|
||||
replaygain = [
|
||||
"PyGObject",
|
||||
] # python-gi and GStreamer 1.0+ or mp3gain/aacgain or Python Audio Tools or ffmpeg
|
||||
scrub = ["mutagen"]
|
||||
sonosupdate = ["soco"]
|
||||
thumbnails = ["Pillow", "pyxdg"]
|
||||
web = ["flask", "flask-cors"]
|
||||
|
||||
[tool.poetry.scripts]
|
||||
beet = "beets.ui:main"
|
||||
release = "extra.release:cli"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core>=1.0.0"]
|
||||
build-backend = "poetry.core.masonry.api"
|
||||
|
||||
[tool.pipx-install]
|
||||
poethepoet = ">=0.26"
|
||||
poetry = ">=1.8"
|
||||
|
||||
# We use a default path '.' to make black and isort behave like flake8 and
|
||||
# mypy do: they act on the entire codebase (flake8 does it by default, and
|
||||
# mypy follows our configuration) by default. Positional command-line arguments
|
||||
# override this. Therefore, locally you can run `poe check-format <some-path>`
|
||||
# to quickly check a specific path.
|
||||
#
|
||||
# Note: both tools respect .gitignore, therefore if we see them format
|
||||
# something unwanted locally, we should add these paths to .gitignore.
|
||||
[tool.poe.tasks._black]
|
||||
help = "Run black"
|
||||
cmd = "black $OPTS $path"
|
||||
args = { path = { help = "Path to blacken", positional = true, multiple = true, default = "." } }
|
||||
|
||||
[tool.poe.tasks._isort]
|
||||
help = "Run isort"
|
||||
cmd = "isort $OPTS $path"
|
||||
args = { path = { help = "Path to isort", positional = true, multiple = true, default = "." } }
|
||||
|
||||
[tool.poe.tasks.bump]
|
||||
help = "Bump project version and update relevant files"
|
||||
cmd = "release bump $version"
|
||||
args = { version = { help = "The new version to set", positional = true, required = true } }
|
||||
|
||||
[tool.poe.tasks.changelog]
|
||||
help = "Print the latest version's changelog in Markdown"
|
||||
cmd = "release changelog"
|
||||
|
||||
[tool.poe.tasks.check-docs-links]
|
||||
help = "Check the documentation for broken URLs"
|
||||
cmd = "make -C docs linkcheck"
|
||||
|
||||
[tool.poe.tasks.check-format]
|
||||
help = "Check the code for style issues"
|
||||
ref = "format"
|
||||
env.OPTS = "--check --diff --color"
|
||||
|
||||
[tool.poe.tasks.check-types]
|
||||
help = "Check the code for typing issues. Accepts mypy options."
|
||||
cmd = "mypy"
|
||||
|
||||
[tool.poe.tasks.docs]
|
||||
help = "Build documentation"
|
||||
cmd = "make -C docs html"
|
||||
|
||||
[tool.poe.tasks.format]
|
||||
help = "Format the codebase"
|
||||
ignore_fail = "return_non_zero"
|
||||
sequence = ["_black $path", "_isort $path"]
|
||||
args = { path = { help = "Path to format", positional = true, multiple = true, default = "." } }
|
||||
|
||||
[tool.poe.tasks.lint]
|
||||
help = "Check the code for linting issues. Accepts flake8 options."
|
||||
cmd = "flake8"
|
||||
|
||||
[tool.poe.tasks.update-dependencies]
|
||||
help = "Update dependencies to their latest versions."
|
||||
cmd = "poetry update -vv"
|
||||
|
||||
[tool.poe.tasks.test]
|
||||
help = "Run tests with pytest"
|
||||
cmd = "pytest"
|
||||
|
||||
[tool.black]
|
||||
line-length = 80
|
||||
target-version = ["py38", "py39", "py310", "py311"]
|
||||
|
|
@ -8,4 +222,3 @@ py_version = 38
|
|||
multi_line_output = 3
|
||||
line_length = 80
|
||||
indent = 4
|
||||
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ per-file-ignores =
|
|||
./beets/mediafile.py:D
|
||||
|
||||
[mypy]
|
||||
files = beets,beetsplug,test
|
||||
files = beets,beetsplug,test,extra,docs
|
||||
allow_any_generics = false
|
||||
# FIXME: Would be better to actually type the libraries (if under our control),
|
||||
# or write our own stubs. For now, silence errors
|
||||
|
|
|
|||
189
setup.py
189
setup.py
|
|
@ -1,189 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# This file is part of beets.
|
||||
# Copyright 2016, Adrian Sampson.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from setuptools import setup
|
||||
|
||||
|
||||
def _read(fn):
|
||||
path = os.path.join(os.path.dirname(__file__), fn)
|
||||
return open(path).read()
|
||||
|
||||
|
||||
def build_manpages():
|
||||
# Go into the docs directory and build the manpage.
|
||||
docdir = os.path.join(os.path.dirname(__file__), "docs")
|
||||
curdir = os.getcwd()
|
||||
os.chdir(docdir)
|
||||
try:
|
||||
subprocess.check_call(["make", "man"])
|
||||
except OSError:
|
||||
print("Could not build manpages (make man failed)!", file=sys.stderr)
|
||||
return
|
||||
finally:
|
||||
os.chdir(curdir)
|
||||
|
||||
# Copy resulting manpages.
|
||||
mandir = os.path.join(os.path.dirname(__file__), "man")
|
||||
if os.path.exists(mandir):
|
||||
shutil.rmtree(mandir)
|
||||
shutil.copytree(os.path.join(docdir, "_build", "man"), mandir)
|
||||
|
||||
|
||||
# Build manpages if we're making a source distribution tarball.
|
||||
if "sdist" in sys.argv:
|
||||
build_manpages()
|
||||
|
||||
|
||||
setup(
|
||||
name="beets",
|
||||
version="2.0.0",
|
||||
description="music tagger and library organizer",
|
||||
author="Adrian Sampson",
|
||||
author_email="adrian@radbox.org",
|
||||
url="https://beets.io/",
|
||||
license="MIT",
|
||||
platforms="ALL",
|
||||
long_description=_read("README.rst"),
|
||||
test_suite="test.testall.suite",
|
||||
zip_safe=False,
|
||||
include_package_data=True, # Install plugin resources.
|
||||
packages=[
|
||||
"beets",
|
||||
"beets.autotag",
|
||||
"beets.dbcore",
|
||||
"beets.test",
|
||||
"beets.ui",
|
||||
"beets.util",
|
||||
"beetsplug",
|
||||
"beetsplug.bpd",
|
||||
"beetsplug.lastgenre",
|
||||
"beetsplug.metasync",
|
||||
"beetsplug.web",
|
||||
],
|
||||
entry_points={
|
||||
"console_scripts": [
|
||||
"beet = beets.ui:main",
|
||||
],
|
||||
},
|
||||
install_requires=[
|
||||
"confuse>=1.5.0",
|
||||
"jellyfish",
|
||||
"mediafile>=0.12.0",
|
||||
"munkres>=1.0.0",
|
||||
"musicbrainzngs>=0.4",
|
||||
"pyyaml",
|
||||
"typing_extensions",
|
||||
"unidecode>=1.3.6",
|
||||
]
|
||||
+ (
|
||||
# Support for ANSI console colors on Windows.
|
||||
["colorama"]
|
||||
if (sys.platform == "win32")
|
||||
else []
|
||||
),
|
||||
extras_require={
|
||||
"test": [
|
||||
"beautifulsoup4",
|
||||
"flask",
|
||||
"mock",
|
||||
"pylast",
|
||||
"pytest",
|
||||
"pytest-cov",
|
||||
"pytest-flask",
|
||||
"python-mpd2",
|
||||
"python3-discogs-client>=2.3.15",
|
||||
"py7zr",
|
||||
"pyxdg",
|
||||
"rarfile",
|
||||
"reflink",
|
||||
"requests_oauthlib",
|
||||
"responses>=0.3.0",
|
||||
],
|
||||
"lint": [
|
||||
"flake8",
|
||||
"flake8-docstrings",
|
||||
"pep8-naming",
|
||||
],
|
||||
"mypy": [
|
||||
"mypy",
|
||||
"types-beautifulsoup4",
|
||||
"types-Flask-Cors",
|
||||
"types-Pillow",
|
||||
"types-PyYAML",
|
||||
"types-requests",
|
||||
"types-urllib3",
|
||||
],
|
||||
"docs": [
|
||||
"pydata_sphinx_theme",
|
||||
"sphinx",
|
||||
],
|
||||
# Plugin (optional) dependencies:
|
||||
"absubmit": ["requests"],
|
||||
"beatport": ["requests-oauthlib>=0.6.1"],
|
||||
"bpd": ["PyGObject"],
|
||||
"chroma": ["pyacoustid"],
|
||||
"discogs": ["python3-discogs-client>=2.3.15"],
|
||||
"embedart": ["Pillow"],
|
||||
"embyupdate": ["requests"],
|
||||
"fetchart": ["requests", "Pillow", "beautifulsoup4"],
|
||||
"import": ["rarfile", "py7zr"],
|
||||
"kodiupdate": ["requests"],
|
||||
"lastgenre": ["pylast"],
|
||||
"lastimport": ["pylast"],
|
||||
"lyrics": ["requests", "beautifulsoup4", "langdetect"],
|
||||
"metasync": ["dbus-python"],
|
||||
"mpdstats": ["python-mpd2>=0.4.2"],
|
||||
"plexupdate": ["requests"],
|
||||
"reflink": ["reflink"],
|
||||
"replaygain": ["PyGObject"],
|
||||
"scrub": ["mutagen>=1.33"],
|
||||
"sonosupdate": ["soco"],
|
||||
"thumbnails": ["pyxdg", "Pillow"],
|
||||
"web": ["flask", "flask-cors"],
|
||||
},
|
||||
# Non-Python/non-PyPI plugin dependencies:
|
||||
# chroma: chromaprint or fpcalc
|
||||
# convert: ffmpeg
|
||||
# badfiles: mp3val and flac
|
||||
# bpd: python-gi and GStreamer 1.0+
|
||||
# embedart: ImageMagick
|
||||
# absubmit: extractor binary from https://acousticbrainz.org/download
|
||||
# keyfinder: KeyFinder
|
||||
# replaygain: python-gi and GStreamer 1.0+
|
||||
# or mp3gain/aacgain
|
||||
# or Python Audio Tools
|
||||
# or ffmpeg
|
||||
# ipfs: go-ipfs
|
||||
classifiers=[
|
||||
"Topic :: Multimedia :: Sound/Audio",
|
||||
"Topic :: Multimedia :: Sound/Audio :: Players :: MP3",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Environment :: Console",
|
||||
"Environment :: Web Environment",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: Implementation :: CPython",
|
||||
],
|
||||
)
|
||||
67
tox.ini
67
tox.ini
|
|
@ -1,67 +0,0 @@
|
|||
# Tox (http://tox.testrun.org/) is a tool for running tests
|
||||
# in multiple virtualenvs. This configuration file will run the
|
||||
# test suite on all supported python versions. To use it, "pip install tox"
|
||||
# and then run "tox" from this directory.
|
||||
|
||||
[tox]
|
||||
envlist = py38-{cov,lint,mypy}, docs, format, format_check
|
||||
|
||||
[_test]
|
||||
deps = .[test]
|
||||
|
||||
[_lint]
|
||||
deps = .[lint]
|
||||
files = beets beetsplug beet test setup.py docs
|
||||
|
||||
[_mypy]
|
||||
deps =
|
||||
.[mypy]
|
||||
.[test]
|
||||
|
||||
[testenv]
|
||||
deps =
|
||||
{test,cov}: {[_test]deps}
|
||||
lint: {[_lint]deps}
|
||||
mypy: {[_mypy]deps}
|
||||
passenv = INTEGRATION_TEST
|
||||
commands =
|
||||
test: python -m pytest {posargs}
|
||||
lint: python -m flake8 {posargs} {[_lint]files}
|
||||
mypy: mypy
|
||||
|
||||
[testenv:docs]
|
||||
basepython = python3.10
|
||||
deps =
|
||||
sphinx>=5
|
||||
pydata_sphinx_theme
|
||||
commands = sphinx-build -W -q -b html docs {envtmpdir}/html {posargs}
|
||||
|
||||
# checks all links in the docs
|
||||
[testenv:links]
|
||||
deps = sphinx
|
||||
allowlist_externals = /bin/bash
|
||||
commands = /bin/bash -c '! sphinx-build -b linkcheck docs {envtmpdir}/linkcheck | grep "broken\s"'
|
||||
|
||||
[testenv:int]
|
||||
deps = {[_test]deps}
|
||||
setenv = INTEGRATION_TEST = 1
|
||||
passenv = GITHUB_ACTIONS
|
||||
commands = python -bb -m pytest {posargs}
|
||||
|
||||
[testenv:format]
|
||||
deps =
|
||||
isort==5.13.2
|
||||
black==24.2.0
|
||||
skip_install = True
|
||||
commands =
|
||||
isort beets beetsplug test
|
||||
black beets beetsplug test
|
||||
|
||||
[testenv:format_check]
|
||||
deps =
|
||||
isort==5.13.2
|
||||
black==24.2.0
|
||||
skip_install = True
|
||||
commands =
|
||||
isort beets beetsplug test --check --diff
|
||||
black beets beetsplug test --check --diff
|
||||
Loading…
Reference in a new issue