diff --git a/.gitignore b/.gitignore index 4d0b867d..481e3341 100644 --- a/.gitignore +++ b/.gitignore @@ -136,6 +136,3 @@ modern-python-boilerplate/ # Code editors .vscode - -# Caches -.flakeheaven_cache diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4f3d840c..252a7d1b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,6 @@ +--- repos: -- repo: https://github.com/pre-commit/pre-commit-hooks + - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.5.0 hooks: - id: check-toml @@ -13,24 +14,18 @@ repos: exclude: "^{{cookiecutter.project_name}}/" - id: end-of-file-fixer exclude: "^{{cookiecutter.project_name}}/" -- repo: https://github.com/timothycrosley/isort + - repo: https://github.com/timothycrosley/isort rev: 5.12.0 hooks: - id: isort exclude: "^{{cookiecutter.project_name}}/" -- repo: https://github.com/psf/black + - repo: https://github.com/psf/black rev: 23.11.0 hooks: - id: black exclude: "^{{cookiecutter.project_name}}/" -- repo: local + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.1.7 hooks: - - id: flakeheaven - name: flakeheaven - description: "`FlakeHeaven` it's a Flake8 wrapper to make it cools." - entry: poetry run flakeheaven - args: [lint] - language: system - types: [python] - require_serial: true + - id: ruff exclude: "^{{cookiecutter.project_name}}/" diff --git a/CHANGELOG.md b/CHANGELOG.md index 34c7b35f..329d4be9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,10 +6,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added +- Ruff `^0.1.7`. + ### Changed - mypy from `^1.7.0` to `^1.7.1`. - actions/setup-python from `v4.7.1` to `v5.0.0`. +### Removed +- falke8 and flakeheaven. + ## [2.3.1] - 2023-11-18 ### Changed - actions/setup-python from `v4.6.1` to `v4.7.1`. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fccb3157..a84398ca 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -66,7 +66,7 @@ work, tests, or other changes before your pull request can be ultimately accepte ### Python Code Style -All Python code is linted with [Flake8](https://github.com/PyCQA/flake8) and formated with +All Python code is linted with [Ruff](https://github.com/astral-sh/ruff) and formated with [Isort](https://github.com/PyCQA/isort) and [Black](https://github.com/psf/black). You can execute `inv[oke] lint` and `inv[oke] format`. diff --git a/README.md b/README.md index 22a2f390..d7da19fd 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ * Dependency tracking using [Poetry][poetry] * Testing setup with [Pytest][pytest] * [Github Actions][github actions] ready for Continuous Integration testing -* Linting provided by [Flake8][flake8] with [flakeheaven][flakeheaven] +* Linting provided by [Ruff][ruff] * Docstring linting provided by [Darglint][darglint] using the [Google Python Style Guide][google styleguide] * Static type checking by [Mypy][mypy] * Formatting provided by [Black][black] and [Isort][isort] @@ -77,8 +77,7 @@ This cookiecutter was built for learning purpose and inspired by: [poetry]: https://python-poetry.org/ [pytest]: https://github.com/pytest-dev/pytest [github actions]: https://github.com/features/actions -[flake8]: https://gitlab.com/pycqa/flake8 -[flakeheaven]: https://github.com/flakeheaven/flakeheaven +[ruff]: https://github.com/astral-sh/ruff [isort]: https://github.com/timothycrosley/isort [black]: https://github.com/psf/black [darglint]: https://github.com/terrencepreilly/darglint diff --git a/docs/invoke.rst b/docs/invoke.rst index 031ba84b..e0d05a29 100644 --- a/docs/invoke.rst +++ b/docs/invoke.rst @@ -22,12 +22,12 @@ Execute `inv[oke] --list` to see the list of available commands. clean-tests Clean up files from testing. coverage Create coverage report. docs Build documentation. - flake8 Run flake8. format Format code. hooks Run pre-commit hooks. install-hooks Install pre-commit hooks. lint Run all linting. mypy Run mypy. + ruff Run ruff. security Run security related checks. tests Run tests. version Bump version. diff --git a/docs/tutorial.rst b/docs/tutorial.rst index 3644d6e6..51119002 100644 --- a/docs/tutorial.rst +++ b/docs/tutorial.rst @@ -55,7 +55,7 @@ You will find one folder named after the ``[project_name]``. Move into this fold mypackage $ git add . mypackage $ git commit -m "Initial skeleton." mypackage $ git remote add origin git@github.com:myusername/mypackage.git - mypackage $ git push -u origin master + mypackage $ git push -u origin main Where ``myusername`` and ``mypackage`` are adjusted for your username and package name. diff --git a/poetry.lock b/poetry.lock index 32697ae5..3e3781d2 100644 --- a/poetry.lock +++ b/poetry.lock @@ -30,24 +30,6 @@ types-python-dateutil = ">=2.8.10" doc = ["doc8", "sphinx (>=7.0.0)", "sphinx-autobuild", "sphinx-autodoc-typehints", "sphinx_rtd_theme (>=1.3.0)"] test = ["dateparser (==1.*)", "pre-commit", "pytest", "pytest-cov", "pytest-mock", "pytz (==2021.1)", "simplejson (==3.*)"] -[[package]] -name = "attrs" -version = "23.1.0" -description = "Classes Without Boilerplate" -optional = false -python-versions = ">=3.7" -files = [ - {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, - {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, -] - -[package.extras] -cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] -dev = ["attrs[docs,tests]", "pre-commit"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] -tests = ["attrs[tests-no-zope]", "zope-interface"] -tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] - [[package]] name = "babel" version = "2.13.1" @@ -65,29 +47,6 @@ pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""} [package.extras] dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] -[[package]] -name = "bandit" -version = "1.7.5" -description = "Security oriented static analyser for python code." -optional = false -python-versions = ">=3.7" -files = [ - {file = "bandit-1.7.5-py3-none-any.whl", hash = "sha256:75665181dc1e0096369112541a056c59d1c5f66f9bb74a8d686c3c362b83f549"}, - {file = "bandit-1.7.5.tar.gz", hash = "sha256:bdfc739baa03b880c2d15d0431b31c658ffc348e907fe197e54e0389dd59e11e"}, -] - -[package.dependencies] -colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""} -GitPython = ">=1.0.1" -PyYAML = ">=5.3.1" -rich = "*" -stevedore = ">=1.20.0" - -[package.extras] -test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "pylint (==1.9.4)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)", "tomli (>=1.1.0)"] -toml = ["tomli (>=1.1.0)"] -yaml = ["PyYAML"] - [[package]] name = "binaryornot" version = "0.4.4" @@ -347,17 +306,6 @@ pyyaml = ">=5.3.1" requests = ">=2.23.0" rich = "*" -[[package]] -name = "darglint" -version = "1.8.1" -description = "A utility for ensuring Google-style docstrings stay up to date with the source code." -optional = false -python-versions = ">=3.6,<4.0" -files = [ - {file = "darglint-1.8.1-py3-none-any.whl", hash = "sha256:5ae11c259c17b0701618a20c3da343a3eb98b3bc4b5a83d31cdd94f5ebdced8d"}, - {file = "darglint-1.8.1.tar.gz", hash = "sha256:080d5106df149b199822e7ee7deb9c012b49891538f14a11be681044f0bb20da"}, -] - [[package]] name = "distlib" version = "0.3.7" @@ -399,17 +347,6 @@ tomli = {version = "*", markers = "python_version < \"3.11\""} conda = ["pyyaml"] pipenv = ["pipenv (<=2022.12.19)"] -[[package]] -name = "entrypoints" -version = "0.4" -description = "Discover and load entry points from installed packages." -optional = false -python-versions = ">=3.6" -files = [ - {file = "entrypoints-0.4-py3-none-any.whl", hash = "sha256:f174b5ff827504fd3cd97cc3f8649f3693f51538c7e4bdf3ef002c8429d42f9f"}, - {file = "entrypoints-0.4.tar.gz", hash = "sha256:b706eddaa9218a19ebcd67b56818f05bb27589b1ca9e8d797b74affad4ccacd4"}, -] - [[package]] name = "exceptiongroup" version = "1.1.3" @@ -440,209 +377,6 @@ docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1 testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] typing = ["typing-extensions (>=4.8)"] -[[package]] -name = "flake8" -version = "4.0.1" -description = "the modular source code checker: pep8 pyflakes and co" -optional = false -python-versions = ">=3.6" -files = [ - {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"}, - {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"}, -] - -[package.dependencies] -mccabe = ">=0.6.0,<0.7.0" -pycodestyle = ">=2.8.0,<2.9.0" -pyflakes = ">=2.4.0,<2.5.0" - -[[package]] -name = "flake8-annotations" -version = "2.9.1" -description = "Flake8 Type Annotation Checks" -optional = false -python-versions = ">=3.7,<4.0" -files = [ - {file = "flake8-annotations-2.9.1.tar.gz", hash = "sha256:11f09efb99ae63c8f9d6b492b75fe147fbc323179fddfe00b2e56eefeca42f57"}, - {file = "flake8_annotations-2.9.1-py3-none-any.whl", hash = "sha256:a4385158a7a9fc8af1d8820a2f4c8d03387997006a83f5f8bfe5bc6085bdf88a"}, -] - -[package.dependencies] -attrs = ">=21.4" -flake8 = ">=3.7" - -[[package]] -name = "flake8-bandit" -version = "3.0.0" -description = "Automated security testing with bandit and flake8." -optional = false -python-versions = ">=3.6" -files = [ - {file = "flake8_bandit-3.0.0-py2.py3-none-any.whl", hash = "sha256:61b617f4f7cdaa0e2b1e6bf7b68afb2b619a227bb3e3ae00dd36c213bd17900a"}, - {file = "flake8_bandit-3.0.0.tar.gz", hash = "sha256:54d19427e6a8d50322a7b02e1841c0a7c22d856975f3459803320e0e18e2d6a1"}, -] - -[package.dependencies] -bandit = ">=1.7.3" -flake8 = "*" -flake8-polyfill = "*" -pycodestyle = "*" - -[[package]] -name = "flake8-blind-except" -version = "0.2.1" -description = "A flake8 extension that checks for blind except: statements" -optional = false -python-versions = "*" -files = [ - {file = "flake8-blind-except-0.2.1.tar.gz", hash = "sha256:f25a575a9dcb3eeb3c760bf9c22db60b8b5a23120224ed1faa9a43f75dd7dd16"}, -] - -[[package]] -name = "flake8-broken-line" -version = "0.6.0" -description = "Flake8 plugin to forbid backslashes for line breaks" -optional = false -python-versions = ">=3.7,<4.0" -files = [ - {file = "flake8-broken-line-0.6.0.tar.gz", hash = "sha256:a02268f11a18837c83c59013a36cc00fee9e17a042745cc0c9895f1c9f6acc16"}, - {file = "flake8_broken_line-0.6.0-py3-none-any.whl", hash = "sha256:c0ab336ff7de228dbffbe56d67b3615bb21fb15f3ed0604fa7bdf9feb72d7d88"}, -] - -[package.dependencies] -flake8 = ">=3.5,<6" - -[[package]] -name = "flake8-bugbear" -version = "23.3.12" -description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." -optional = false -python-versions = ">=3.7" -files = [ - {file = "flake8-bugbear-23.3.12.tar.gz", hash = "sha256:e3e7f74c8a49ad3794a7183353026dabd68c74030d5f46571f84c1fb0eb79363"}, - {file = "flake8_bugbear-23.3.12-py3-none-any.whl", hash = "sha256:beb5c7efcd7ccc2039ef66a77bb8db925e7be3531ff1cb4d0b7030d0e2113d72"}, -] - -[package.dependencies] -attrs = ">=19.2.0" -flake8 = ">=3.0.0" - -[package.extras] -dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit", "pytest", "tox"] - -[[package]] -name = "flake8-builtins" -version = "2.2.0" -description = "Check for python builtins being used as variables or parameters" -optional = false -python-versions = ">=3.8" -files = [ - {file = "flake8_builtins-2.2.0-py3-none-any.whl", hash = "sha256:7ee5766d9c60e5d579dfda84e65c6d0e6c26005f6f59cb9bf722462d7987a807"}, - {file = "flake8_builtins-2.2.0.tar.gz", hash = "sha256:392d5af3a0720c5a863aa93dc47f48c879081345a143fe9f20d995fe9ff5686a"}, -] - -[package.dependencies] -flake8 = "*" - -[package.extras] -test = ["pytest"] - -[[package]] -name = "flake8-docstrings" -version = "1.7.0" -description = "Extension for flake8 which uses pydocstyle to check docstrings" -optional = false -python-versions = ">=3.7" -files = [ - {file = "flake8_docstrings-1.7.0-py2.py3-none-any.whl", hash = "sha256:51f2344026da083fc084166a9353f5082b01f72901df422f74b4d953ae88ac75"}, - {file = "flake8_docstrings-1.7.0.tar.gz", hash = "sha256:4c8cc748dc16e6869728699e5d0d685da9a10b0ea718e090b1ba088e67a941af"}, -] - -[package.dependencies] -flake8 = ">=3" -pydocstyle = ">=2.1" - -[[package]] -name = "flake8-logging-format" -version = "0.9.0" -description = "" -optional = false -python-versions = "*" -files = [ - {file = "flake8-logging-format-0.9.0.tar.gz", hash = "sha256:e830cc49091e4b8ab9ea3da69a3da074bd631ce9a7db300e5c89fb48ba4a6986"}, -] - -[package.extras] -lint = ["flake8"] -test = ["PyHamcrest", "pytest", "pytest-cov"] - -[[package]] -name = "flake8-polyfill" -version = "1.0.2" -description = "Polyfill package for Flake8 plugins" -optional = false -python-versions = "*" -files = [ - {file = "flake8-polyfill-1.0.2.tar.gz", hash = "sha256:e44b087597f6da52ec6393a709e7108b2905317d0c0b744cdca6208e670d8eda"}, - {file = "flake8_polyfill-1.0.2-py2.py3-none-any.whl", hash = "sha256:12be6a34ee3ab795b19ca73505e7b55826d5f6ad7230d31b18e106400169b9e9"}, -] - -[package.dependencies] -flake8 = "*" - -[[package]] -name = "flakeheaven" -version = "3.3.0" -description = "FlakeHeaven is a [Flake8](https://gitlab.com/pycqa/flake8) wrapper to make it cool." -optional = false -python-versions = ">=3.7,<4.0" -files = [ - {file = "flakeheaven-3.3.0-py3-none-any.whl", hash = "sha256:ae246197a178845b30b63fc03023f7ba925cc84cc96314ec19807dafcd6b39a3"}, - {file = "flakeheaven-3.3.0.tar.gz", hash = "sha256:eb07860e028ff8dd56cce742c4766624a37a4ce397fd34300254ab623d13047b"}, -] - -[package.dependencies] -colorama = "*" -entrypoints = "*" -flake8 = ">=4.0.1,<5.0.0" -pygments = "*" -toml = "*" -urllib3 = "*" - -[package.extras] -docs = ["alabaster", "myst-parser (>=0.18.0,<0.19.0)", "pygments-github-lexers", "sphinx"] - -[[package]] -name = "gitdb" -version = "4.0.11" -description = "Git Object Database" -optional = false -python-versions = ">=3.7" -files = [ - {file = "gitdb-4.0.11-py3-none-any.whl", hash = "sha256:81a3407ddd2ee8df444cbacea00e2d038e40150acfa3001696fe0dcf1d3adfa4"}, - {file = "gitdb-4.0.11.tar.gz", hash = "sha256:bf5421126136d6d0af55bc1e7c1af1c397a34f5b7bd79e776cd3e89785c2b04b"}, -] - -[package.dependencies] -smmap = ">=3.0.1,<6" - -[[package]] -name = "gitpython" -version = "3.1.40" -description = "GitPython is a Python library used to interact with Git repositories" -optional = false -python-versions = ">=3.7" -files = [ - {file = "GitPython-3.1.40-py3-none-any.whl", hash = "sha256:cf14627d5a8049ffbf49915732e5eddbe8134c3bdb9d476e6182b676fc573f8a"}, - {file = "GitPython-3.1.40.tar.gz", hash = "sha256:22b126e9ffb671fdd0c129796343a02bf67bf2994b35449ffc9321aa755e18a4"}, -] - -[package.dependencies] -gitdb = ">=4.0.1,<5" - -[package.extras] -test = ["black", "coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock", "mypy", "pre-commit", "pytest", "pytest-cov", "pytest-instafail", "pytest-subtests", "pytest-sugar"] - [[package]] name = "identify" version = "2.5.32" @@ -857,17 +591,6 @@ docs = ["alabaster (==0.7.13)", "autodocsumm (==0.2.11)", "sphinx (==7.0.1)", "s lint = ["flake8 (==6.0.0)", "flake8-bugbear (==23.7.10)", "mypy (==1.4.1)", "pre-commit (>=2.4,<4.0)"] tests = ["pytest", "pytz", "simplejson"] -[[package]] -name = "mccabe" -version = "0.6.1" -description = "McCabe checker, plugin for flake8" -optional = false -python-versions = "*" -files = [ - {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, - {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, -] - [[package]] name = "mdurl" version = "0.1.2" @@ -973,17 +696,6 @@ files = [ {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, ] -[[package]] -name = "pbr" -version = "6.0.0" -description = "Python Build Reasonableness" -optional = false -python-versions = ">=2.6" -files = [ - {file = "pbr-6.0.0-py2.py3-none-any.whl", hash = "sha256:4a7317d5e3b17a3dccb6a8cfe67dab65b20551404c52c8ed41279fa4f0cb4cda"}, - {file = "pbr-6.0.0.tar.gz", hash = "sha256:d1377122a5a00e2f940ee482999518efe16d745d423a670c27773dfbc3c9a7d9"}, -] - [[package]] name = "platformdirs" version = "3.11.0" @@ -1032,45 +744,6 @@ nodeenv = ">=0.11.1" pyyaml = ">=5.1" virtualenv = ">=20.10.0" -[[package]] -name = "pycodestyle" -version = "2.8.0" -description = "Python style guide checker" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -files = [ - {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"}, - {file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"}, -] - -[[package]] -name = "pydocstyle" -version = "6.3.0" -description = "Python docstring style checker" -optional = false -python-versions = ">=3.6" -files = [ - {file = "pydocstyle-6.3.0-py3-none-any.whl", hash = "sha256:118762d452a49d6b05e194ef344a55822987a462831ade91ec5c06fd2169d019"}, - {file = "pydocstyle-6.3.0.tar.gz", hash = "sha256:7ce43f0c0ac87b07494eb9c0b462c0b73e6ff276807f204d6b53edc72b7e44e1"}, -] - -[package.dependencies] -snowballstemmer = ">=2.2.0" - -[package.extras] -toml = ["tomli (>=1.2.3)"] - -[[package]] -name = "pyflakes" -version = "2.4.0" -description = "passive checker of Python programs" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"}, - {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"}, -] - [[package]] name = "pygments" version = "2.17.0" @@ -1347,6 +1020,32 @@ files = [ {file = "ruamel.yaml.clib-0.2.8.tar.gz", hash = "sha256:beb2e0404003de9a4cab9753a8805a8fe9320ee6673136ed7f04255fe60bb512"}, ] +[[package]] +name = "ruff" +version = "0.1.7" +description = "An extremely fast Python linter and code formatter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.1.7-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:7f80496854fdc65b6659c271d2c26e90d4d401e6a4a31908e7e334fab4645aac"}, + {file = "ruff-0.1.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:1ea109bdb23c2a4413f397ebd8ac32cb498bee234d4191ae1a310af760e5d287"}, + {file = "ruff-0.1.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b0c2de9dd9daf5e07624c24add25c3a490dbf74b0e9bca4145c632457b3b42a"}, + {file = "ruff-0.1.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:69a4bed13bc1d5dabf3902522b5a2aadfebe28226c6269694283c3b0cecb45fd"}, + {file = "ruff-0.1.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de02ca331f2143195a712983a57137c5ec0f10acc4aa81f7c1f86519e52b92a1"}, + {file = "ruff-0.1.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:45b38c3f8788a65e6a2cab02e0f7adfa88872696839d9882c13b7e2f35d64c5f"}, + {file = "ruff-0.1.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6c64cb67b2025b1ac6d58e5ffca8f7b3f7fd921f35e78198411237e4f0db8e73"}, + {file = "ruff-0.1.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9dcc6bb2f4df59cb5b4b40ff14be7d57012179d69c6565c1da0d1f013d29951b"}, + {file = "ruff-0.1.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df2bb4bb6bbe921f6b4f5b6fdd8d8468c940731cb9406f274ae8c5ed7a78c478"}, + {file = "ruff-0.1.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:276a89bcb149b3d8c1b11d91aa81898fe698900ed553a08129b38d9d6570e717"}, + {file = "ruff-0.1.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:90c958fe950735041f1c80d21b42184f1072cc3975d05e736e8d66fc377119ea"}, + {file = "ruff-0.1.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6b05e3b123f93bb4146a761b7a7d57af8cb7384ccb2502d29d736eaade0db519"}, + {file = "ruff-0.1.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:290ecab680dce94affebefe0bbca2322a6277e83d4f29234627e0f8f6b4fa9ce"}, + {file = "ruff-0.1.7-py3-none-win32.whl", hash = "sha256:416dfd0bd45d1a2baa3b1b07b1b9758e7d993c256d3e51dc6e03a5e7901c7d80"}, + {file = "ruff-0.1.7-py3-none-win_amd64.whl", hash = "sha256:4af95fd1d3b001fc41325064336db36e3d27d2004cdb6d21fd617d45a172dd96"}, + {file = "ruff-0.1.7-py3-none-win_arm64.whl", hash = "sha256:0683b7bfbb95e6df3c7c04fe9d78f631f8e8ba4868dfc932d43d690698057e2e"}, + {file = "ruff-0.1.7.tar.gz", hash = "sha256:dffd699d07abf54833e5f6cc50b85a6ff043715da8788c4a79bcd4ab4734d306"}, +] + [[package]] name = "safety" version = "2.4.0b2" @@ -1400,17 +1099,6 @@ files = [ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] -[[package]] -name = "smmap" -version = "5.0.1" -description = "A pure Python implementation of a sliding window memory map manager" -optional = false -python-versions = ">=3.7" -files = [ - {file = "smmap-5.0.1-py3-none-any.whl", hash = "sha256:e6d8668fa5f93e706934a62d7b4db19c8d9eb8cf2adbb75ef1b675aa332b69da"}, - {file = "smmap-5.0.1.tar.gz", hash = "sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62"}, -] - [[package]] name = "snowballstemmer" version = "2.2.0" @@ -1546,20 +1234,6 @@ files = [ lint = ["docutils-stubs", "flake8", "mypy"] test = ["pytest"] -[[package]] -name = "stevedore" -version = "5.1.0" -description = "Manage dynamic plugins for Python applications" -optional = false -python-versions = ">=3.8" -files = [ - {file = "stevedore-5.1.0-py3-none-any.whl", hash = "sha256:8cc040628f3cea5d7128f2e76cf486b2251a4e543c7b938f58d9a377f6694a2d"}, - {file = "stevedore-5.1.0.tar.gz", hash = "sha256:a54534acf9b89bc7ed264807013b505bf07f74dbe4bcfa37d32bd063870b087c"}, -] - -[package.dependencies] -pbr = ">=2.0.0,<2.1.0 || >2.1.0" - [[package]] name = "text-unidecode" version = "1.3" @@ -1571,17 +1245,6 @@ files = [ {file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"}, ] -[[package]] -name = "toml" -version = "0.10.2" -description = "Python Library for Tom's Obvious, Minimal Language" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, - {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, -] - [[package]] name = "tomli" version = "2.0.1" @@ -1734,4 +1397,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "<3.12,>=3.8" -content-hash = "9c2f883264779da5641a7183ccd0310207aa86bd819c5f7259077edec0a7cd35" +content-hash = "f65985561cc662667932013962bab240b34f19b5646aaed28d31570610c5a9a6" diff --git a/pyproject.toml b/pyproject.toml index c1e47058..753b12f3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,22 +44,10 @@ pytest = "^7.4.3" xdoctest = "^1.1.2" pytest-cookies = "^0.7.0" -[tool.poetry.group.format.dependencies] +[tool.poetry.group.linters.dependencies] isort = "^5.12.0" black = "^23.11.0" - -[tool.poetry.group.linters.dependencies] -flake8 = ">=4.0.1,<5.0.0" -flakeheaven = "^3.3.0" -flake8-builtins = "^2.2.0" -flake8-blind-except = "^0.2.1" -flake8-logging-format = "^0.9.0" -flake8-bugbear = "^23.3.12" -flake8-annotations = "^2.9.1" -flake8-docstrings = "^1.7.0" -flake8-bandit = "^3.0.0" -flake8-broken-line = "^0.6.0" -darglint = "^1.8.1" +ruff = "^0.1.7" [tool.poetry.group.security.dependencies] safety = "^2.4.0b2" @@ -71,24 +59,43 @@ mypy = "^1.7.1" sphinx = "^7.1.2" recommonmark = "^0.7.1" -[tool.flakeheaven] -format = "grouped" -max_line_length = 99 -show_source = true -docstring-convention = "google" -extended_default_ignore = [] - -[tool.flakeheaven.plugins] -pyflakes = ["+*"] -pycodestyle = ["+*"] -mccabe = ["+*"] -flake8-annotations = ["+*", "-ANN1??", "-ANN401"] -flake8-docstrings = ["+*", "-D212"] -"flake8-*" = ["+*"] -pylint = ["-C????", "-E????", "+F????", "+I????", "-R????", "-W????"] - -[tool.flakeheaven.exceptions."tests/"] -flake8-bandit = ["-S101"] +[tool.ruff] +target-version = "py38" +show-source = true +line-length = 99 +fix = true +unfixable = [ + "ERA", # Don't remove commented-out code +] +extend-exclude = [ + "docs/*", +] +select = [ + "E", "F", "W", # flake8 + "C", # mccabe + "I", # isort + "N", # pep8-naming + "D", # flake8-docstrings + "ANN", # flake8-annotations + "S", # flake8-bandit + "BLE", # flake8-blind-except + "B", # flake8-bugbear + "A", # flake8-builtins + "G", # flake8-logging-format + "ERA", # eradicate + "ISC", # flake8-implicit-str-concat + "RUF", # Ruff-specific rules +] +ignore = ["ANN101"] + +[tool.ruff.per-file-ignores] +"tests/*" = ["S101"] + +[tool.ruff.mccabe] +max-complexity = 10 + +[tool.ruff.pydocstyle] +convention = "google" [tool.isort] multi_line_output = 3 diff --git a/tasks.py b/tasks.py index 494cc7dc..8537014f 100644 --- a/tasks.py +++ b/tasks.py @@ -1,5 +1,4 @@ -""" -Tasks for maintaining the project. +"""Tasks for maintaining the project. Execute 'invoke --list' for guidance on using Invoke """ @@ -32,8 +31,7 @@ def _run(c: Context, command: str) -> Optional[Result]: @task() -def bake(c, replay=False): - # type: (Context, bool) -> None +def bake(c: Context, replay: bool = False) -> None: """Bake the cookie.""" bake_options = ( ["--replay", "--overwrite-if-exists"] @@ -44,8 +42,7 @@ def bake(c, replay=False): @task() -def watch(c, replay=False): - # type: (Context, bool) -> None +def watch(c: Context, replay: bool = False) -> None: """Bake and watch for changes.""" bake(c, replay=replay) _run( @@ -57,8 +54,7 @@ def watch(c, replay=False): @task() -def clean_build(c): - # type: (Context) -> None +def clean_build(c: Context) -> None: """Clean up files from package building.""" _run(c, "rm -fr build/") _run(c, "rm -fr dist/") @@ -68,8 +64,7 @@ def clean_build(c): @task() -def clean_python(c): - # type: (Context) -> None +def clean_python(c: Context) -> None: """Clean up python file artifacts.""" _run(c, "find . -name '*.pyc' -exec rm -f {} +") _run(c, "find . -name '*.pyo' -exec rm -f {} +") @@ -78,42 +73,36 @@ def clean_python(c): @task() -def clean_tests(c): - # type: (Context) -> None +def clean_tests(c: Context) -> None: """Clean up files from testing.""" _run(c, "rm -fr .pytest_cache") @task() -def clean_docs(c): - # type: (Context) -> None +def clean_docs(c: Context) -> None: """Clean up files from documentation builds.""" _run(c, f"rm -fr {DOCS_BUILD_DIR}") @task(pre=[clean_build, clean_python, clean_tests, clean_docs]) -def clean(c): - # type: (Context) -> None +def clean(c: Context) -> None: """Run all clean sub-tasks.""" @task() -def install_hooks(c): - # type: (Context) -> None +def install_hooks(c: Context) -> None: """Install pre-commit hooks.""" _run(c, "poetry run pre-commit install") @task() -def hooks(c): - # type: (Context) -> None +def hooks(c: Context) -> None: """Run pre-commit hooks.""" _run(c, "poetry run pre-commit run --all-files") @task(name="format", help={"check": "Checks if source is formatted without applying changes"}) -def format_(c, check=False): - # type: (Context, bool) -> None +def format_(c: Context, check: bool = False) -> None: """Format code.""" isort_options = ["--check-only", "--diff"] if check else [] _run(c, f"poetry run isort {' '.join(isort_options)} {PYTHON_TARGETS_STR}") @@ -122,15 +111,13 @@ def format_(c, check=False): @task() -def flake8(c): - # type: (Context) -> None - """Run flake8.""" - _run(c, f"poetry run flakeheaven lint {PYTHON_TARGETS_STR}") +def ruff(c: Context) -> None: + """Run ruff.""" + _run(c, f"poetry run ruff check {PYTHON_TARGETS_STR}") @task() -def security(c): - # type: (Context) -> None +def security(c: Context) -> None: """Run security related checks.""" _run( c, @@ -139,22 +126,19 @@ def security(c): ) -@task(pre=[flake8, security, call(format_, check=True)]) -def lint(c): - # type: (Context) -> None +@task(pre=[ruff, security, call(format_, check=True)]) +def lint(c: Context) -> None: """Run all linting.""" @task() -def mypy(c): - # type: (Context) -> None +def mypy(c: Context) -> None: """Run mypy.""" _run(c, f"poetry run mypy {PYTHON_TARGETS_STR}") @task() -def tests(c): - # type: (Context) -> None +def tests(c: Context) -> None: """Run tests.""" pytest_options = ["--xdoctest"] _run(c, f"poetry run pytest {' '.join(pytest_options)} {TEST_DIR}") @@ -166,8 +150,7 @@ def tests(c): "open_browser": "Open the docs in the web browser", } ) -def docs(c, serve=False, open_browser=False): - # type: (Context, bool, bool) -> None +def docs(c: Context, serve: bool = False, open_browser: bool = False) -> None: """Build documentation.""" build_docs = f"sphinx-build -b html {DOCS_DIR} {DOCS_BUILD_DIR}" _run(c, build_docs) @@ -183,8 +166,7 @@ def docs(c, serve=False, open_browser=False): "dry_run": "Don't write any files, just pretend. (default: False)", } ) -def version(c, part, dry_run=False): - # type: (Context, str, bool) -> None +def version(c: Context, part: str, dry_run: bool = False) -> None: """Bump version.""" bump_options = ["--dry-run"] if dry_run else [] _run(c, f"poetry run bump2version {' '.join(bump_options)} {part}") diff --git a/tests/test_bake_project.py b/tests/test_bake_project.py index 3a254350..0e8063f5 100644 --- a/tests/test_bake_project.py +++ b/tests/test_bake_project.py @@ -2,10 +2,10 @@ import datetime import os import shlex -import subprocess # noqa: S404 +import subprocess import sys from contextlib import contextmanager -from typing import Any, Dict, Generator, List +from typing import Dict, Generator, List, Optional import pytest from cookiecutter.utils import rmtree @@ -42,18 +42,17 @@ def inside_dir(dirpath: str) -> Generator[None, None, None]: @contextmanager -def bake_in_temp_dir(cookies: Cookies, *args: Any, **kwargs: Any) -> Result: - """Delete the temporal directory that is created when executing the tests. +def bake_in_temp_dir(cookies: Cookies, extra_context: Optional[Dict[str, str]] = None) -> Result: + """Bake a cookie and clean up the temporary directory created during tests. Args: - cookies: A cookie to be baked and its temporal files will be removed. - *args: Variable length argument list to be passed to the bake command. - **kwargs: Arbitrary keyword arguments to be passed to the bake command. + cookies: The cookie to be baked, and its temporal files will be removed. + extra_context: An optional additional context to be provided to the bake command. Yields: The baked cookie. """ - result = cookies.bake(*args, **kwargs) + result = cookies.bake(extra_context=extra_context) try: yield result finally: diff --git a/{{cookiecutter.project_name}}/.gitignore b/{{cookiecutter.project_name}}/.gitignore index 55df344b..b8eb5b1a 100644 --- a/{{cookiecutter.project_name}}/.gitignore +++ b/{{cookiecutter.project_name}}/.gitignore @@ -133,6 +133,3 @@ dmypy.json # Code editors .vscode - -# Caches -.flakeheaven_cache diff --git a/{{cookiecutter.project_name}}/.pre-commit-config.yaml b/{{cookiecutter.project_name}}/.pre-commit-config.yaml index 7e95208a..2213af56 100644 --- a/{{cookiecutter.project_name}}/.pre-commit-config.yaml +++ b/{{cookiecutter.project_name}}/.pre-commit-config.yaml @@ -1,5 +1,6 @@ +--- repos: -- repo: https://github.com/pre-commit/pre-commit-hooks + - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.5.0 hooks: - id: check-toml @@ -8,21 +9,15 @@ repos: - id: check-merge-conflict - id: check-json - id: end-of-file-fixer -- repo: https://github.com/timothycrosley/isort + - repo: https://github.com/timothycrosley/isort rev: 5.12.0 hooks: - id: isort -- repo: https://github.com/psf/black + - repo: https://github.com/psf/black rev: 23.11.0 hooks: - id: black -- repo: local + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.1.4 hooks: - - id: flakeheaven - name: flakeheaven - description: "`FlakeHeaven` it's a Flake8 wrapper to make it cools." - entry: poetry run flakeheaven - args: [lint] - language: system - types: [python] - require_serial: true + - id: ruff diff --git a/{{cookiecutter.project_name}}/CONTRIBUTING.md b/{{cookiecutter.project_name}}/CONTRIBUTING.md index 1470382b..7954d29c 100644 --- a/{{cookiecutter.project_name}}/CONTRIBUTING.md +++ b/{{cookiecutter.project_name}}/CONTRIBUTING.md @@ -66,7 +66,7 @@ work, tests, or other changes before your pull request can be ultimately accepte ### Python Code Style -All Python code is linted with [Flake8](https://github.com/PyCQA/flake8) and formated with +All Python code is linted with [Ruff](https://github.com/astral-sh/ruff) and formated with [Isort](https://github.com/PyCQA/isort) and [Black](https://github.com/psf/black). You can execute `inv[oke] lint` and `inv[oke] format`. diff --git a/{{cookiecutter.project_name}}/pyproject.toml b/{{cookiecutter.project_name}}/pyproject.toml index fe5ab00d..6eaf741a 100644 --- a/{{cookiecutter.project_name}}/pyproject.toml +++ b/{{cookiecutter.project_name}}/pyproject.toml @@ -64,22 +64,10 @@ xdoctest = "^1.1.2" coverage = {version = "^7.3.2", extras = ["toml"]} pytest-cov = "^4.1.0" -[tool.poetry.group.format.dependencies] +[tool.poetry.group.linters.dependencies] isort = "^5.12.0" black = "^23.11.0" - -[tool.poetry.group.linters.dependencies] -flake8 = ">=4.0.1,<5.0.0" -flakeheaven = "^3.3.0" -flake8-builtins = "^2.2.0" -flake8-blind-except = "^0.2.1" -flake8-logging-format = "^0.9.0" -flake8-bugbear = "^23.3.12" -flake8-annotations = "^2.9.1" -flake8-docstrings = "^1.7.0" -flake8-bandit = "^3.0.0" -flake8-broken-line = "^0.6.0" -darglint = "^1.8.1" +ruff = "^0.1.7" [tool.poetry.group.security.dependencies] safety = "^2.4.0b2" @@ -115,24 +103,46 @@ show_missing = true [tool.coverage.html] directory = "htmlcov" -[tool.flakeheaven] -format = "grouped" -max_line_length = 99 -show_source = true -docstring-convention = "google" -extended_default_ignore = [] - -[tool.flakeheaven.plugins] -pyflakes = ["+*"] -pycodestyle = ["+*"] -mccabe = ["+*"] -flake8-annotations = ["+*", "-ANN1??", "-ANN401"] -flake8-docstrings = ["+*", "-D212"] -"flake8-*" = ["+*"] -pylint = ["-C????", "-E????", "+F????", "+I????", "-R????", "-W????"] - -[tool.flakeheaven.exceptions."tests/"] -flake8-bandit = ["-S101"] +[tool.ruff] +target-version = "py38" +show-source = true +line-length = 99 +fix = true +unfixable = [ + "ERA", # Don't remove commented-out code +] +extend-exclude = [ + "docs/*", +] +select = [ + "E", "F", "W", # flake8 + "C", # mccabe + "I", # isort + "N", # pep8-naming + "D", # flake8-docstrings + "ANN", # flake8-annotations + "S", # flake8-bandit + "BLE", # flake8-blind-except + "B", # flake8-bugbear + "A", # flake8-builtins + "G", # flake8-logging-format + "ERA", # eradicate + "ISC", # flake8-implicit-str-concat + "RUF", # Ruff-specific rules +] +ignore = ["ANN101"] + +[tool.ruff.per-file-ignores] +"tests/*" = ["S101"] + +[tool.ruff.mccabe] +max-complexity = 10 + +[tool.ruff.isort] +known-first-party = ["{{ cookiecutter.project_slug }}"] + +[tool.ruff.pydocstyle] +convention = "google" [tool.isort] multi_line_output = 3 diff --git a/{{cookiecutter.project_name}}/tasks.py b/{{cookiecutter.project_name}}/tasks.py index f810cbe0..cff74e69 100644 --- a/{{cookiecutter.project_name}}/tasks.py +++ b/{{cookiecutter.project_name}}/tasks.py @@ -1,5 +1,4 @@ -""" -Tasks for maintaining the project. +"""Tasks for maintaining the project. Execute 'invoke --list' for guidance on using Invoke """ @@ -35,8 +34,7 @@ def _run(c: Context, command: str) -> Optional[Result]: @task() -def clean_build(c): - # type: (Context) -> None +def clean_build(c: Context) -> None: """Clean up files from package building.""" _run(c, "rm -fr build/") _run(c, "rm -fr dist/") @@ -46,8 +44,7 @@ def clean_build(c): @task() -def clean_python(c): - # type: (Context) -> None +def clean_python(c: Context) -> None: """Clean up python file artifacts.""" _run(c, "find . -name '*.pyc' -exec rm -f {} +") _run(c, "find . -name '*.pyo' -exec rm -f {} +") @@ -56,8 +53,7 @@ def clean_python(c): @task() -def clean_tests(c): - # type: (Context) -> None +def clean_tests(c: Context) -> None: """Clean up files from testing.""" _run(c, f"rm -f {COVERAGE_FILE}") _run(c, f"rm -fr {COVERAGE_DIR}") @@ -65,35 +61,30 @@ def clean_tests(c): @task() -def clean_docs(c): - # type: (Context) -> None +def clean_docs(c: Context) -> None: """Clean up files from documentation builds.""" _run(c, f"rm -fr {DOCS_BUILD_DIR}") @task(pre=[clean_build, clean_python, clean_tests, clean_docs]) -def clean(c): - # type: (Context) -> None +def clean(c: Context) -> None: """Run all clean sub-tasks.""" @task() -def install_hooks(c): - # type: (Context) -> None +def install_hooks(c: Context) -> None: """Install pre-commit hooks.""" _run(c, "poetry run pre-commit install") @task() -def hooks(c): - # type: (Context) -> None +def hooks(c: Context) -> None: """Run pre-commit hooks.""" _run(c, "poetry run pre-commit run --all-files") @task(name="format", help={"check": "Checks if source is formatted without applying changes"}) -def format_(c, check=False): - # type: (Context, bool) -> None +def format_(c: Context, check: bool = False) -> None: """Format code.""" isort_options = ["--check-only", "--diff"] if check else [] _run(c, f"poetry run isort {' '.join(isort_options)} {PYTHON_TARGETS_STR}") @@ -102,15 +93,13 @@ def format_(c, check=False): @task() -def flake8(c): - # type: (Context) -> None - """Run flake8.""" - _run(c, f"poetry run flakeheaven lint {PYTHON_TARGETS_STR}") +def ruff(c: Context) -> None: + """Run ruff.""" + _run(c, f"poetry run ruff check {PYTHON_TARGETS_STR}") @task() -def security(c): - # type: (Context) -> None +def security(c: Context) -> None: """Run security related checks.""" _run( c, @@ -119,22 +108,19 @@ def security(c): ) -@task(pre=[flake8, security, call(format_, check=True)]) -def lint(c): - # type: (Context) -> None +@task(pre=[ruff, security, call(format_, check=True)]) +def lint(c: Context) -> None: """Run all linting.""" @task() -def mypy(c): - # type: (Context) -> None +def mypy(c: Context) -> None: """Run mypy.""" _run(c, f"poetry run mypy {PYTHON_TARGETS_STR}") @task() -def tests(c): - # type: (Context) -> None +def tests(c: Context) -> None: """Run tests.""" pytest_options = ["--xdoctest", "--cov", "--cov-report=", "--cov-fail-under=0"] _run(c, f"poetry run pytest {' '.join(pytest_options)} {TEST_DIR} {SOURCE_DIR}") @@ -146,8 +132,7 @@ def tests(c): "open_browser": "Open the coverage report in the web browser (requires --fmt html)", } ) -def coverage(c, fmt="report", open_browser=False): - # type: (Context, str, bool) -> None +def coverage(c: Context, fmt: str = "report", open_browser: bool = False) -> None: """Create coverage report.""" if any(Path().glob(".coverage.*")): _run(c, "poetry run coverage combine") @@ -162,8 +147,7 @@ def coverage(c, fmt="report", open_browser=False): "open_browser": "Open the docs in the web browser", } ) -def docs(c, serve=False, open_browser=False): - # type: (Context, bool, bool) -> None +def docs(c: Context, serve: bool = False, open_browser: bool = False) -> None: """Build documentation.""" _run(c, f"sphinx-apidoc -o {DOCS_DIR} {SOURCE_DIR}") build_docs = f"sphinx-build -b html {DOCS_DIR} {DOCS_BUILD_DIR}" @@ -180,8 +164,7 @@ def docs(c, serve=False, open_browser=False): "dry_run": "Don't write any files, just pretend. (default: False)", } ) -def version(c, part, dry_run=False): - # type: (Context, str, bool) -> None +def version(c: Context, part: str, dry_run: bool = False) -> None: """Bump version.""" bump_options = ["--dry-run"] if dry_run else [] _run(c, f"poetry run bump2version {' '.join(bump_options)} {part}")