diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a4c488000..46ab2b203 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -39,24 +39,22 @@ jobs: sudo apt install ffmpeg poetry install --extras replaygain - - name: Test older Python versions with tox + - name: Test older Python versions if: matrix.python-version != '3.x' - run: | - tox -e py-test + run: poetry run project test - name: Upload code coverage if: matrix.python-version == '3.8' && matrix.platform == 'ubuntu-latest' continue-on-error: true run: codecov - - name: Test latest Python version with tox and mypy + - name: Check types 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 continue-on-error: true - run: | - tox -vv -e py-mypy + run: poetry run project check-types test-docs: runs-on: ubuntu-latest @@ -82,8 +80,8 @@ jobs: - name: Add problem matcher run: echo "::add-matcher::.github/sphinx-problem-matcher.json" - - name: Build and check docs using tox - run: tox -e docs + - name: Build and check docs + run: poetry run project docs lint: runs-on: ubuntu-latest @@ -107,4 +105,4 @@ jobs: run: echo "::add-matcher::.github/flake8-problem-matcher.json" - name: Lint with flake8 - run: tox -e py-lint + run: poetry run project lint diff --git a/.github/workflows/formatting_check.yml b/.github/workflows/formatting_check.yml index 76154fe4d..fda4890d1 100644 --- a/.github/workflows/formatting_check.yml +++ b/.github/workflows/formatting_check.yml @@ -5,10 +5,19 @@ jobs: formatting_check: runs-on: ubuntu-latest steps: + - uses: actions/checkout@v4 + + - name: Install Poetry + run: pipx install poetry + + - name: Set up Python 3.x + uses: actions/setup-python@v5 + with: + python-version: 3.8 + cache: poetry + - name: Install dependencies - uses: actions/checkout@v3 + run: poetry install - name: Run formatting check - uses: paolorechia/pox@v1.0.1 - with: - tox_env: "format_check" + run: poetry run project check-format diff --git a/.github/workflows/integration_test.yaml b/.github/workflows/integration_test.yaml index d19d267a3..bb234df23 100644 --- a/.github/workflows/integration_test.yaml +++ b/.github/workflows/integration_test.yaml @@ -2,7 +2,7 @@ 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 @@ -23,13 +23,13 @@ jobs: pip install poetry poetry install - - name: Test with tox - run: | - tox -e int + - name: Test + env: + INTEGRATION_TEST: 1 + run: poetry run project test - name: Check external links in docs - run: | - tox -e links + run: poetry run project check-docs-links - name: Notify on failure if: ${{ failure() }} diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 785b97892..e54076ba0 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -62,8 +62,10 @@ Programming information in the `“For Developers” section of the docs `__. -Tools -^^^^^ +.. _development-tools: + +Development Tools +^^^^^^^^^^^^^^^^^ In order to develop beets, you will need a few tools installed: @@ -88,6 +90,8 @@ Install `poetry`_ and `poethepoet`_ using `pipx`_:: .. _pipx: https://pipx.pypa.io/stable .. _pipx-installation-instructions: https://pipx.pypa.io/stable/installation/ +.. _getting-the-source: + Getting the Source ^^^^^^^^^^^^^^^^^^ @@ -203,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 @@ -273,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 @@ -330,31 +333,36 @@ 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 @@ -396,7 +404,6 @@ 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 diff --git a/poetry.lock b/poetry.lock index 90b39993e..31b9ea742 100644 --- a/poetry.lock +++ b/poetry.lock @@ -134,6 +134,52 @@ soupsieve = ">1.2" html5lib = ["html5lib"] lxml = ["lxml"] +[[package]] +name = "black" +version = "24.2.0" +description = "The uncompromising code formatter." +optional = false +python-versions = ">=3.8" +files = [ + {file = "black-24.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6981eae48b3b33399c8757036c7f5d48a535b962a7c2310d19361edeef64ce29"}, + {file = "black-24.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d533d5e3259720fdbc1b37444491b024003e012c5173f7d06825a77508085430"}, + {file = "black-24.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61a0391772490ddfb8a693c067df1ef5227257e72b0e4108482b8d41b5aee13f"}, + {file = "black-24.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:992e451b04667116680cb88f63449267c13e1ad134f30087dec8527242e9862a"}, + {file = "black-24.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:163baf4ef40e6897a2a9b83890e59141cc8c2a98f2dda5080dc15c00ee1e62cd"}, + {file = "black-24.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e37c99f89929af50ffaf912454b3e3b47fd64109659026b678c091a4cd450fb2"}, + {file = "black-24.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9de21bafcba9683853f6c96c2d515e364aee631b178eaa5145fc1c61a3cc92"}, + {file = "black-24.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:9db528bccb9e8e20c08e716b3b09c6bdd64da0dd129b11e160bf082d4642ac23"}, + {file = "black-24.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d84f29eb3ee44859052073b7636533ec995bd0f64e2fb43aeceefc70090e752b"}, + {file = "black-24.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e08fb9a15c914b81dd734ddd7fb10513016e5ce7e6704bdd5e1251ceee51ac9"}, + {file = "black-24.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:810d445ae6069ce64030c78ff6127cd9cd178a9ac3361435708b907d8a04c693"}, + {file = "black-24.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:ba15742a13de85e9b8f3239c8f807723991fbfae24bad92d34a2b12e81904982"}, + {file = "black-24.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7e53a8c630f71db01b28cd9602a1ada68c937cbf2c333e6ed041390d6968faf4"}, + {file = "black-24.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:93601c2deb321b4bad8f95df408e3fb3943d85012dddb6121336b8e24a0d1218"}, + {file = "black-24.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0057f800de6acc4407fe75bb147b0c2b5cbb7c3ed110d3e5999cd01184d53b0"}, + {file = "black-24.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:faf2ee02e6612577ba0181f4347bcbcf591eb122f7841ae5ba233d12c39dcb4d"}, + {file = "black-24.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:057c3dc602eaa6fdc451069bd027a1b2635028b575a6c3acfd63193ced20d9c8"}, + {file = "black-24.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:08654d0797e65f2423f850fc8e16a0ce50925f9337fb4a4a176a7aa4026e63f8"}, + {file = "black-24.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca610d29415ee1a30a3f30fab7a8f4144e9d34c89a235d81292a1edb2b55f540"}, + {file = "black-24.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:4dd76e9468d5536abd40ffbc7a247f83b2324f0c050556d9c371c2b9a9a95e31"}, + {file = "black-24.2.0-py3-none-any.whl", hash = "sha256:e8a6ae970537e67830776488bca52000eaa37fa63b9988e8c487458d9cd5ace6"}, + {file = "black-24.2.0.tar.gz", hash = "sha256:bce4f25c27c3435e4dace4815bcb2008b87e167e3bf4ee47ccdc5ce906eb4894"}, +] + +[package.dependencies] +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +packaging = ">=22.0" +pathspec = ">=0.9.0" +platformdirs = ">=2" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + [[package]] name = "brotli" version = "1.1.0" @@ -383,13 +429,13 @@ requests = ">=2.7.9" [[package]] name = "colorama" -version = "0.4.4" +version = "0.4.6" description = "Cross-platform colored terminal text." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ - {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, - {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] [[package]] @@ -766,6 +812,23 @@ files = [ {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, ] +[[package]] +name = "isort" +version = "5.13.2" +description = "A Python utility / library to sort Python imports." +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, + {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, +] + +[package.dependencies] +colorama = {version = ">=0.4.6", optional = true, markers = "extra == \"colors\""} + +[package.extras] +colors = ["colorama (>=0.4.6)"] + [[package]] name = "itsdangerous" version = "2.0.1" @@ -1259,6 +1322,17 @@ files = [ {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, ] +[[package]] +name = "pathspec" +version = "0.12.1" +description = "Utility library for gitignore style pattern matching of file paths." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, + {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, +] + [[package]] name = "pep8-naming" version = "0.12.1" @@ -1353,6 +1427,22 @@ files = [ docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"] tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] +[[package]] +name = "platformdirs" +version = "4.2.2" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." +optional = false +python-versions = ">=3.8" +files = [ + {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"}, + {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"}, +] + +[package.extras] +docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] +type = ["mypy (>=1.8)"] + [[package]] name = "pluggy" version = "1.0.0" @@ -2628,4 +2718,4 @@ web = ["flask", "flask-cors"] [metadata] lock-version = "2.0" python-versions = ">=3.8,<4" -content-hash = "697ebfc73bb20e4bf4ee41f639847212384102601d94b0231374f41e6932e5bd" +content-hash = "979ae1e0d13b43d98dde8c1506d338981d1babd82202b05082165ba73aa9ce79" diff --git a/pyproject.toml b/pyproject.toml index 5f12b7787..22adff8ad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -84,6 +84,10 @@ 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 = "*" diff --git a/tox.ini b/tox.ini deleted file mode 100644 index 9ab1ba613..000000000 --- a/tox.ini +++ /dev/null @@ -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