From e0135c320c135427b88fc0afeefd7fede5ea1c5a Mon Sep 17 00:00:00 2001 From: Hagen Wierstorf Date: Wed, 11 Oct 2023 16:12:07 +0200 Subject: [PATCH] Switch project to use pyproject.toml (#60) * Switch project to use pyproject.toml * Fix docs --- .flake8 | 10 + .github/workflows/{flake8.yml => linter.yml} | 2 +- .github/workflows/publish.yml | 8 +- .pre-commit-config.yaml | 16 +- CONTRIBUTING.rst | 70 ++++--- README.rst | 4 +- audplot/__init__.py | 22 +- audplot/core/api.py | 2 +- docs/conf.py | 13 +- docs/requirements.txt | 1 + pyproject.toml | 199 +++++++++++++++++++ setup.cfg | 57 ------ setup.py | 4 - 13 files changed, 289 insertions(+), 119 deletions(-) create mode 100644 .flake8 rename .github/workflows/{flake8.yml => linter.yml} (97%) create mode 100644 pyproject.toml delete mode 100644 setup.cfg delete mode 100644 setup.py 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 00bb119..ceb16c1 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -26,7 +26,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install setuptools wheel twine + pip install build twine virtualenv # PyPI package - name: Build and publish @@ -34,10 +34,10 @@ jobs: TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} run: | - python setup.py sdist bdist_wheel + python -m build python -m twine upload dist/* - # Docuemntation + # Documentation - name: Install doc dependencies run: | pip install -r requirements.txt @@ -65,7 +65,7 @@ jobs: CHANGELOG="${CHANGELOG//$'\n'/'%0A'}" CHANGELOG="${CHANGELOG//$'\r'/'%0D'}" echo "Got changelog: $CHANGELOG" - echo "::set-output name=body::$CHANGELOG" + echo "body=$CHANGELOG" >> $GITHUB_OUTPUT - name: Create release on Github id: create_release 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 eb70db1..d910255 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/audplot/issues/new/ .. _pull request: https://github.com/audeering/audplot/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/audplot/ - cd audplot - # Create virutal environment for this project - # e.g. - # virtualenv --python="python3" $HOME/.envs/audplot - # source $HOME/.envs/audplot/bin/activate - pip install -r requirements.txt + git clone https://github.com/audeering/audplot/ + cd audplot + # Create virtual environment for this project + # e.g. + # virtualenv --python="python3" $HOME/.envs/audplot + # source $HOME/.envs/audplot/bin/activate + pip install -r requirements.txt -.. _Github: https://github.com/audeering/audplot -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/audplot/ +.. _Github: https://github.com/audeering/audplot/ + 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 audfoo/ tests/ + codespell audfoo/ 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 + 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 @@ -93,13 +105,13 @@ Running the Tests You'll need pytest_ for that. It can be installed with:: - pip install -r tests/requirements.txt + pip install -r tests/requirements.txt To execute the tests, simply run:: - python -m pytest + python -m pytest -.. _pytest: https://pytest.org/ +.. _pytest: https://pytest.org Creating a New Release diff --git a/README.rst b/README.rst index 647d587..e387b9b 100644 --- a/README.rst +++ b/README.rst @@ -13,14 +13,14 @@ and machine learning problems (e.g. confusion matrix). .. |tests| image:: https://github.com/audeering/audplot/workflows/Test/badge.svg :target: https://github.com/audeering/audplot/actions?query=workflow%3ATest :alt: Test status -.. |coverage| image:: https://codecov.io/gh/audeering/audplot/branch/master/graph/badge.svg?token=t5c5Ky64Ch +.. |coverage| image:: https://codecov.io/gh/audeering/audplot/branch/main/graph/badge.svg?token=t5c5Ky64Ch :target: https://codecov.io/gh/audeering/audplot/ :alt: code coverage .. |docs| image:: https://img.shields.io/pypi/v/audplot?label=docs :target: https://audeering.github.io/audplot/ :alt: audplot's documentation .. |license| image:: https://img.shields.io/badge/license-MIT-green.svg - :target: https://github.com/audeering/audplot/blob/master/LICENSE + :target: https://github.com/audeering/audplot/blob/main/LICENSE :alt: audplot's MIT license .. |python-versions| image:: https://img.shields.io/pypi/pyversions/audplot.svg :target: https://pypi.org/project/audplot/ diff --git a/audplot/__init__.py b/audplot/__init__.py index 79cfe53..c0ac3c2 100644 --- a/audplot/__init__.py +++ b/audplot/__init__.py @@ -1,15 +1,13 @@ -from audplot.core.api import ( - cepstrum, - confusion_matrix, - detection_error_tradeoff, - distribution, - human_format, - scatter, - series, - signal, - spectrum, - waveform, -) +from audplot.core.api import cepstrum +from audplot.core.api import confusion_matrix +from audplot.core.api import detection_error_tradeoff +from audplot.core.api import distribution +from audplot.core.api import human_format +from audplot.core.api import scatter +from audplot.core.api import series +from audplot.core.api import signal +from audplot.core.api import spectrum +from audplot.core.api import waveform # Disencourage from audfoo import * diff --git a/audplot/core/api.py b/audplot/core/api.py index cf95540..18625e6 100644 --- a/audplot/core/api.py +++ b/audplot/core/api.py @@ -7,6 +7,7 @@ import pandas as pd import seaborn as sns + # The scipy implementation is faster, # but scipy is not an official dependency of audplot try: @@ -59,7 +60,6 @@ def cepstrum( >>> plt.tight_layout() """ - ax = ax or plt.gca() cc_matrix = cc_matrix[channel] if cc_matrix.ndim == 3 else cc_matrix diff --git a/docs/conf.py b/docs/conf.py index 648ffb0..08c3fb8 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,20 +1,21 @@ -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'] +author = ', '.join(author['name'] for author in config['project']['authors']) copyright = f'2020-{date.today().year} audEERING GmbH' -project = config['metadata']['name'] +project = config['project']['name'] version = audeer.git_repo_version() -title = f'{project} Documentation' +title = 'Documentation' # General ----------------------------------------------------------------- diff --git a/docs/requirements.txt b/docs/requirements.txt index 0b19a76..99edb12 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -5,3 +5,4 @@ sphinx-audeering-theme >=1.1.3 sphinx-autodoc-typehints sphinx-copybutton sphinxcontrib-katex +toml diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..73d695a --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,199 @@ +# ===== PROJECT =========================================================== +# +[project] +name = 'audplot' +authors = [ + {name = 'Johannes Wagner', email = 'jwagner@audeering.com'}, + {name = 'Hagen Wierstorf', email = 'hwierstorf@audeering.com'}, +] +description = 'A Python plotting package' +readme = 'README.rst' +license = {file = 'LICENSE'} +keywords = [ + 'plot', + 'machine learning', +] +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 = [ + 'audmath', + 'audmetric >=1.1.0', + # https://github.com/matplotlib/matplotlib/issues/24127 + 'matplotlib != 3.6.1', + 'seaborn', +] +# Get version dynamically from git +# (needs setuptools_scm tools config below) +dynamic = ['version'] + +[project.urls] +repository = 'https://github.com/audeering/audplot/' +documentation = 'https://audeering.github.io/audplot/' + + +# ===== 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 = './audplot.egg-info,./build,./docs/api,./docs/_templates' + + +# ----- pytest ------------------------------------------------------------ +# +[tool.pytest.ini_options] +cache_dir = '.cache/pytest' +xfail_strict = true +addopts = ''' + --doctest-plus + --cov=audplot + --cov-fail-under=100 + --cov-report term-missing + --cov-report xml +''' + + +# ----- 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 +] +'tests/*' = [ + 'D101', # Missing docstring in public class + 'D102', # Missing docstring in public method +] + + +# ----- 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 audplot +# +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', + 'audresample', + '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 -------------------------------------------------------- +# +# 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 6a9827f..0000000 --- a/setup.cfg +++ /dev/null @@ -1,57 +0,0 @@ -[metadata] -name = audplot -author = Johannes Wagner, Hagen Wierstorf -author_email = jwagner@audeering.com, hwierstorf@audeering.com -url = https://github.com/audeering/audplot/ -project_urls = - Documentation = https://audeering.github.io/audplot/ -description = A Python plotting package -long_description = file: README.rst, CHANGELOG.rst -license = MIT License -license_file = LICENSE -keywords = example -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] -packages = find: -install_requires = - audmath - audmetric >=1.1.0 - # https://github.com/matplotlib/matplotlib/issues/24127 - matplotlib != 3.6.1 - seaborn -setup_requires = - setuptools_scm - -[tool:pytest] -addopts = - --doctest-plus - --cov=audplot - --cov-fail-under=100 - --cov-report xml - --cov-report term-missing -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 deleted file mode 100644 index 0eb5031..0000000 --- a/setup.py +++ /dev/null @@ -1,4 +0,0 @@ -from setuptools import setup - - -setup(use_scm_version=True)