From 4e07823632b8d9ac8730f306c47d03499cbf0a56 Mon Sep 17 00:00:00 2001 From: Hagen Wierstorf Date: Tue, 15 Aug 2023 14:37:07 +0200 Subject: [PATCH] Switch project to use pyproject.toml (#51) * Start working * Use pyproject.toml * Fix codespell errors * Fix ruff errors * Update setup.py to work with pyproject.toml * Update publish Action * Fix metadata parsing in docs * Fix typos --- .flake8 | 10 + .github/workflows/{flake8.yml => linter.yml} | 2 +- .github/workflows/publish.yml | 2 +- .pre-commit-config.yaml | 16 +- CONTRIBUTING.rst | 52 +++-- README.rst | 6 +- audresample/__init__.py | 8 +- audresample/core/lib.py | 2 +- docs/conf.py | 10 +- docs/index.rst | 2 - docs/requirements.txt | 1 + pyproject.toml | 201 +++++++++++++++++++ setup.cfg | 55 ----- setup.py | 2 - tests/test-assets/generate_test_assets.py | 6 +- tests/test_remix.py | 2 +- tests/test_resample.py | 4 +- 17 files changed, 279 insertions(+), 102 deletions(-) create mode 100644 .flake8 rename .github/workflows/{flake8.yml => linter.yml} (97%) create mode 100644 pyproject.toml delete mode 100644 setup.cfg diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..cb2ed23 --- /dev/null +++ b/.flake8 @@ -0,0 +1,10 @@ +[flake8] +exclude = + .eggs, + build, +extend-ignore = + # math, https://github.com/PyCQA/pycodestyle/issues/513 + W503, +per-file-ignores = + # ignore unused imports + __init__.py: F401 diff --git a/.github/workflows/flake8.yml b/.github/workflows/linter.yml similarity index 97% rename from .github/workflows/flake8.yml rename to .github/workflows/linter.yml index f383de9..2f8baef 100644 --- a/.github/workflows/flake8.yml +++ b/.github/workflows/linter.yml @@ -1,4 +1,4 @@ -name: Flake8 +name: Linter on: push: diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index fc6bd7d..beb5848 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -33,7 +33,7 @@ jobs: - name: Install build dependencies run: | python -m pip install --upgrade pip - pip install build + pip install build virtualenv - name: Build wheels run: python -m build --wheel --outdir wheelhouse diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 68827d5..92a17ee 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,8 +7,18 @@ # $ pre-commit install # $ pre-commit run --all-files # +# +default_language_version: + python: python3.8 + repos: -- repo: https://github.com/pycqa/flake8 - rev: '5.0.4' + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.0.276 + hooks: + - id: ruff + - repo: https://github.com/codespell-project/codespell + rev: v2.2.4 hooks: - - id: flake8 + - id: codespell + additional_dependencies: + - tomli diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 5af598f..03792d5 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -3,8 +3,12 @@ Contributing Everyone is invited to contribute to this project. Feel free to create a `pull request`_ . -If you find errors, omissions, inconsistencies or other things -that need improvement, please create an issue_. +If you find errors, +omissions, +inconsistencies, +or other things +that need improvement, +please create an issue_. .. _issue: https://github.com/audeering/audresample/issues/new/ .. _pull request: https://github.com/audeering/audresample/compare/ @@ -13,30 +17,35 @@ that need improvement, please create an issue_. Development Installation ------------------------ -Instead of pip-installing the latest release from PyPI, +Instead of pip-installing the latest release from PyPI_, you should get the newest development version from Github_:: git clone https://github.com/audeering/audresample/ cd audresample - # Create virutal environment for this project + # Create virtual environment for this project # e.g. # virtualenv --python="python3" $HOME/.envs/audresample # source $HOME/.envs/audresample/bin/activate pip install -r requirements.txt -.. _Github: https://github.com/audeering/audresample -This way, your installation always stays up-to-date, +This way, +your installation always stays up-to-date, even if you pull new changes from the Github repository. +.. _PyPI: https://pypi.org/project/audresample/ +.. _Github: https://github.com/audeering/audresample/ + Coding Convention ----------------- We follow the PEP8_ convention for Python code -and check for correct syntax with flake8_. -Exceptions are defined under the ``[flake8]`` section -in :file:`setup.cfg`. +and check for correct syntax with ruff_. +In addition, +we check for common spelling errors with codespell_. +Both tools and possible exceptions +are defined in :file:`pyproject.toml`. The checks are executed in the CI using `pre-commit`_. You can enable those checks locally by executing:: @@ -45,22 +54,26 @@ You can enable those checks locally by executing:: pre-commit install pre-commit run --all-files -Afterwards flake8_ is executed +Afterwards ruff_ and codespell_ are executed every time you create a commit. -You can also install flake8_ +You can also install ruff_ and codespell_ and call it directly:: - pip install flake8 # consider system wide installation - flake8 + pip install ruff codespell # consider system wide installation + ruff check . + codespell It can be restricted to specific folders:: - flake8 audfoo/ tests/ + ruff check audresample/ tests/ + codespell audresample/ tests/ + +.. _codespell: https://github.com/codespell-project/codespell/ .. _PEP8: http://www.python.org/dev/peps/pep-0008/ -.. _flake8: https://flake8.pycqa.org/en/latest/index.html .. _pre-commit: https://pre-commit.com +.. _ruff: https://beta.ruff.rs Building the Documentation @@ -70,21 +83,20 @@ If you make changes to the documentation, you can re-create the HTML pages using Sphinx_. You can install it and a few other necessary packages with:: - pip install -r requirements.txt pip install -r docs/requirements.txt To create the HTML pages, use:: - python -m sphinx docs/ build/sphinx/html -b html + python -m sphinx docs/ build/sphinx/html -b html The generated files will be available in the directory :file:`build/sphinx/html/`. It is also possible to automatically check if all links are still valid:: - python -m sphinx docs/ build/sphinx/linkcheck -b linkcheck + python -m sphinx docs/ build/sphinx/html -b linkcheck -.. _Sphinx: http://sphinx-doc.org/ +.. _Sphinx: http://sphinx-doc.org Running the Tests @@ -99,7 +111,7 @@ To execute the tests, simply run:: python -m pytest -.. _pytest: https://pytest.org/ +.. _pytest: https://pytest.org Creating a New Release diff --git a/README.rst b/README.rst index 320f5ef..ce6ec55 100644 --- a/README.rst +++ b/README.rst @@ -37,15 +37,15 @@ Have a look at the installation_ and usage_ instructions. .. |tests| image:: https://github.com/audeering/audresample/workflows/Test/badge.svg :target: https://github.com/audeering/audresample/actions?query=workflow%3ATest :alt: Test status -.. |coverage| image:: https://codecov.io/gh/audeering/audresample/branch/master/graph/badge.svg?token=NPQDJ5T7HI +.. |coverage| image:: https://codecov.io/gh/audeering/audresample/branch/main/graph/badge.svg?token=NPQDJ5T7HI :target: https://codecov.io/gh/audeering/audresample/ :alt: code coverage .. |docs| image:: https://img.shields.io/pypi/v/audresample?label=docs :target: https://audeering.github.io/audresample/ :alt: audresample's documentation .. |license| image:: https://img.shields.io/badge/license-MIT-green.svg - :target: https://github.com/audeering/audfactory/blob/master/LICENSE - :alt: audfactory's MIT license + :target: https://github.com/audeering/audresample/blob/main/LICENSE + :alt: audresample's MIT license .. |python-versions| image:: https://img.shields.io/pypi/pyversions/audresample.svg :target: https://pypi.org/project/audresample/ :alt: audresamples's supported Python versions diff --git a/audresample/__init__.py b/audresample/__init__.py index e8aa934..8be20ed 100644 --- a/audresample/__init__.py +++ b/audresample/__init__.py @@ -1,9 +1,7 @@ from audresample.core import define -from audresample.core.api import ( - am_fm_synth, - remix, - resample, -) +from audresample.core.api import am_fm_synth +from audresample.core.api import remix +from audresample.core.api import resample from audresample.core.config import config diff --git a/audresample/core/lib.py b/audresample/core/lib.py index e56d32e..c189e14 100644 --- a/audresample/core/lib.py +++ b/audresample/core/lib.py @@ -68,7 +68,7 @@ def platform_name(): # resample -class ConverterConfig(ctypes.Structure): +class ConverterConfig(ctypes.Structure): # noqa: D101 _fields_ = [ ("srIn", ctypes.c_double), ("srOut", ctypes.c_double), diff --git a/docs/conf.py b/docs/conf.py index d249ff4..8795f21 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,19 +1,19 @@ -import configparser from datetime import date import os import shutil +import toml + import audeer -config = configparser.ConfigParser() -config.read(os.path.join('..', 'setup.cfg')) +config = toml.load(audeer.path('..', 'pyproject.toml')) # Project ----------------------------------------------------------------- -author = config['metadata']['author'] +project = config['project']['name'] +author = ', '.join(author['name'] for author in config['project']['authors']) copyright = f'2020-{date.today().year} audEERING GmbH' -project = config['metadata']['name'] version = audeer.git_repo_version() title = 'Documentation' diff --git a/docs/index.rst b/docs/index.rst index de7d2f4..9a18289 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,5 +1,3 @@ -.. documentation master file - .. include:: ../README.rst .. toctree:: diff --git a/docs/requirements.txt b/docs/requirements.txt index 65a0a6e..8d31bbc 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -6,3 +6,4 @@ sphinx sphinx-audeering-theme >=1.2.1 sphinx-autodoc-typehints sphinx-copybutton +toml diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..9daf524 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,201 @@ +# ===== PROJECT =========================================================== +# +[project] +name = 'audresample' +authors = [ + {name = 'Johannes Wagner', email= 'jwagner@audeering.com'}, + {name = 'Hagen Wierstorf', email = 'hwierstorf@audeering.com'}, + {name = 'Andrea Crespi'} +] +description = 'Resample and remix an audio signal' +readme = 'README.rst' +license = {file = 'LICENSE'} +keywords = [ + 'audio', + 'dsp', + 'resample', + 'remix', +] +classifiers = [ + 'Development Status :: 5 - Production/Stable', + 'Intended Audience :: Science/Research', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: MIT License', + 'Operating System :: OS Independent', + '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 :: 3.11', + 'Topic :: Scientific/Engineering', +] +dependencies = [ + 'numpy', +] +# Get version dynamically from git +# (needs setuptools_scm tools config below) +dynamic = ['version'] + +[project.urls] +repository = 'https://github.com/audeering/audresample/' +documentation = 'https://audeering.github.io/audresample/' + + +# ===== BUILD-SYSTEM ====================================================== +# +# Requirements for building the Python package +[build-system] +requires = ['setuptools>=45', 'setuptools_scm[toml]>=6.2'] +build-backend = 'setuptools.build_meta' + + +# ===== TOOL ============================================================== +# + +# ----- codespell --------------------------------------------------------- +[tool.codespell] +builtin = 'clear,rare,informal,usage,names' +skip = './audresample.egg-info,./build,./docs/api,./docs/_templates,./docs/examples,./benchmarks,./tests/test-assets' + + +# ----- pytest ------------------------------------------------------------ +# +[tool.pytest.ini_options] +cache_dir = '.cache/pytest' +xfail_strict = true +addopts = ''' + --doctest-plus + --cov=audresample + --cov-fail-under=100 + --cov-report term-missing + --cov-report xml + --ignore=docs/examples + --ignore=benchmarks + --ignore=tests/test-assets +''' + + +# ----- ruff -------------------------------------------------------------- +# +[tool.ruff] +select = [ + 'D', # pydocstyle + 'E', # pycodestyle errors + 'F', # Pyflakes + 'I', # isort + 'N', # pep8-naming + 'W', # pycodestyle warnings +] + +extend-ignore = [ + 'D100', # Missing docstring in public module + 'D103', # Missing docstring in public function + 'D104', # Missing docstring in public package + 'D107', # Missing docstring in `__init__` +] + +line-length = 79 + +cache-dir = '.cache/ruff' + +[tool.ruff.per-file-ignores] +'__init__.py' = [ + 'F401', # * imported but unused +] + + +# ----- I: isort ----- +# +# Check correct order/syntax of import statements +# +[tool.ruff.isort] + +# All from imports have their own line, e.g. +# +# from .utils import util_a +# from .utils import util_b +# +force-single-line = true + +# Sort by module names +# and not import before from, e.g. +# +# from datetime import date +# import os +# +force-sort-within-sections = true + +# Ensure we have two empty lines +# after last import +lines-after-imports = 2 + +# Group all audEERING packages into a separate section, e.g. +# +# import os +# +# import numpy as np +# +# import audresample +# +section-order = [ + 'future', + 'standard-library', + 'third-party', + 'audeering', + 'first-party', + 'local-folder', +] +[tool.ruff.isort.sections] +'audeering' = [ + 'audb', + 'audbackend', + 'audeer', + 'audfactory', + 'audformat', + 'audiofile', + 'audinterface', + 'audmath', + 'audmetric', + 'audobject', + 'audonnx', + 'audplot', + 'audsp', + 'audtorch', + 'opensmile', + 'sphinx-audeering-theme', +] + + +# ----- N: pep8-naming ----- +# +# Check variable/class names follow PEP8 naming convention +# +[tool.ruff.pep8-naming] +ignore-names = [ + 'config', # allow lowercase class name + 'test_*', # allow uppercase name when testing a class +] + + +# ----- W: pycodestyle ----- +# +# Check docstrings follow selected convention +# +[tool.ruff.pydocstyle] +convention = 'google' + + +# ----- setuptools -------------------------------------------------------- +# +# Disable package data to only select the matching binary in setup.py +[tool.setuptools] +include-package-data = false +# Find all (sub-)modules of the Python package +[tool.setuptools.packages.find] + + +# ----- setuptools_scm ---------------------------------------------------- +# +# Use setuptools_scm to get version from git +[tool.setuptools_scm] diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 7a34d7f..0000000 --- a/setup.cfg +++ /dev/null @@ -1,55 +0,0 @@ -[metadata] -name = audresample -author = Johannes Wagner, Andrea Crespi, Hagen Wierstorf -author_email = jwagner@audeering.com, acrespi@audeering.com, hwierstorf@audeering.com -url = https://github.com/audeering/audresample/ -project_urls = - Documentation = https://audeering.github.io/audresample/ -description = Provides functions to resample and remix a signal -long_description = file: README.rst, CHANGELOG.rst -license = MIT -license_files = LICENSE -keywords = audio, dsp, resample, remix -platforms= any -classifiers = - Development Status :: 5 - Production/Stable - Intended Audience :: Science/Research - Intended Audience :: Developers - License :: OSI Approved :: MIT License - Operating System :: OS Independent - 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 :: 3.11 - Topic :: Scientific/Engineering - -[options] -install_requires = - numpy -setup_requires = - setuptools_scm - -[tool:pytest] -addopts = - --doctest-plus - --ignore=docs/examples - --ignore=benchmarks - --ignore=tests/test-assets - --cov=audresample - --cov-fail-under=100 - --cov-report term-missing - --cov-report xml -xfail_strict = true - -[flake8] -exclude = - .eggs, - build, -extend-ignore = - # math, https://github.com/PyCQA/pycodestyle/issues/513 - W503, -per-file-ignores = - # ignore unused imports - __init__.py: F401, diff --git a/setup.py b/setup.py index 19a1b3d..2d55f7c 100644 --- a/setup.py +++ b/setup.py @@ -65,8 +65,6 @@ def platform_name(): library = '*.dll' setuptools.setup( - use_scm_version=True, - packages=setuptools.find_packages(), package_data={ 'audresample.core': [f'bin/{plat_name}/{library}'] }, diff --git a/tests/test-assets/generate_test_assets.py b/tests/test-assets/generate_test_assets.py index 6f9a800..01aba12 100644 --- a/tests/test-assets/generate_test_assets.py +++ b/tests/test-assets/generate_test_assets.py @@ -1,7 +1,9 @@ -import audsp -import audiofile as af import sox +import audiofile as af +import audsp + + dur = 1.0 channel_list = [1, 2] sr_list = [8000, 16000, 44100] diff --git a/tests/test_remix.py b/tests/test_remix.py index 4adf794..c5b7532 100644 --- a/tests/test_remix.py +++ b/tests/test_remix.py @@ -1,7 +1,7 @@ import ctypes -import pytest import numpy as np +import pytest import audresample diff --git a/tests/test_resample.py b/tests/test_resample.py index 9fed80e..2c42ec9 100644 --- a/tests/test_resample.py +++ b/tests/test_resample.py @@ -1,12 +1,14 @@ from glob import glob from os import path +import numpy as np import pytest + import audiofile as af -import numpy as np import audresample + resampled_wavs = glob('tests/test-assets/resampled__*.wav')