Set up pre-commit hooks
- add pre-commit hooks: + run `nox -s lint` on staged *.py files + run common pre-commit hooks for validations that could not be achieved with tools in the develop environment so easily - add pre-merge hook: + run `nox -s _pre-commit-test-hook` before merges * ignores the paths to staged files passed in by the pre-commit framework * runs all test cases instead
This commit is contained in:
parent
c07a9ed19f
commit
7a5246556a
5 changed files with 196 additions and 2 deletions
48
.pre-commit-config.yaml
Normal file
48
.pre-commit-config.yaml
Normal file
|
@ -0,0 +1,48 @@
|
|||
default_stages:
|
||||
- commit
|
||||
fail_fast: true
|
||||
repos:
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: local-lint
|
||||
name: Lint the source files
|
||||
entry: nox -s lint --
|
||||
language: system
|
||||
stages:
|
||||
- commit
|
||||
types:
|
||||
- python
|
||||
verbose: true
|
||||
- id: local-test
|
||||
name: Run the entire test suite
|
||||
entry: nox -s _pre-commit-test-hook --
|
||||
language: system
|
||||
stages:
|
||||
- merge-commit
|
||||
types:
|
||||
- text
|
||||
verbose: true
|
||||
- repo: "https://github.com/pre-commit/pre-commit-hooks"
|
||||
rev: v4.6.0
|
||||
hooks:
|
||||
- id: check-added-large-files
|
||||
args:
|
||||
- "--maxkb=100"
|
||||
- id: check-builtin-literals
|
||||
- id: check-case-conflict
|
||||
- id: check-merge-conflict
|
||||
- id: check-toml
|
||||
- id: check-yaml
|
||||
- id: end-of-file-fixer
|
||||
stages:
|
||||
- commit
|
||||
- id: mixed-line-ending
|
||||
args:
|
||||
- "--fix=no"
|
||||
- id: no-commit-to-branch
|
||||
args:
|
||||
- "--branch"
|
||||
- main
|
||||
- id: trailing-whitespace
|
||||
stages:
|
||||
- commit
|
|
@ -95,6 +95,13 @@ The second task lints all source code files with
|
|||
[ruff](https://pypi.org/project/ruff/).
|
||||
`flake8` is configured with a couple of plug-ins.
|
||||
|
||||
You may want to install the [pre-commit](https://pre-commit.com/) hooks
|
||||
that come with the project:
|
||||
|
||||
`nox -s pre-commit-install`
|
||||
|
||||
Then, the linting and testing occurs automatically before every commit.
|
||||
|
||||
|
||||
#### Test Suite
|
||||
|
||||
|
|
38
noxfile.py
38
noxfile.py
|
@ -250,7 +250,10 @@ def test(session: nox.Session) -> None:
|
|||
install_unpinned(session, "-e", ".") # "-e" makes session reuseable
|
||||
install_pinned(session, *TEST_DEPENDENCIES)
|
||||
|
||||
args = session.posargs or (
|
||||
# If this function is run by the `pre-commit` framework, extra
|
||||
# arguments are dropped by the hack inside `pre_commit_test_hook()`
|
||||
posargs = () if session.env.get("_drop_posargs") else session.posargs
|
||||
args = posargs or (
|
||||
"--cov",
|
||||
"--no-cov-on-fail",
|
||||
TESTS_LOCATION,
|
||||
|
@ -321,6 +324,39 @@ def test_docstrings(session: nox.Session) -> None:
|
|||
session.run("xdoctest", "src/lalib")
|
||||
|
||||
|
||||
@nox_session(name="pre-commit-install", python=MAIN_PYTHON, venv_backend="none")
|
||||
def pre_commit_install(session: nox.Session) -> None:
|
||||
"""Install `pre-commit` hooks."""
|
||||
for type_ in ("pre-commit", "pre-merge-commit"):
|
||||
session.run(
|
||||
"poetry",
|
||||
"run",
|
||||
"pre-commit",
|
||||
"install",
|
||||
f"--hook-type={type_}",
|
||||
external=True,
|
||||
)
|
||||
|
||||
|
||||
@nox_session(name="_pre-commit-test-hook", python=MAIN_PYTHON, reuse_venv=False)
|
||||
def pre_commit_test_hook(session: nox.Session) -> None:
|
||||
"""`pre-commit` hook to run all tests before merges.
|
||||
|
||||
Ignores the paths to the staged files passed in by the
|
||||
`pre-commit` framework and executes all tests instead. So,
|
||||
`nox -s _pre-commit-test-hook -- FILE1, ...` drops the "FILE1, ...".
|
||||
"""
|
||||
do_not_reuse(session)
|
||||
|
||||
# Little Hack: Create a flag in the env(ironment) ...
|
||||
session.env["_drop_posargs"] = "true"
|
||||
|
||||
# ... and call `test()` directly because `session.notify()`
|
||||
# creates the "test" session as a new `nox.Session` object
|
||||
# that does not have the flag set
|
||||
test(session)
|
||||
|
||||
|
||||
def do_not_reuse(session: nox.Session, *, raise_error: bool = True) -> None:
|
||||
"""Do not reuse a session with the "-r" flag."""
|
||||
if session._runner.venv._reused: # noqa:SLF001
|
||||
|
|
103
poetry.lock
generated
103
poetry.lock
generated
|
@ -149,6 +149,17 @@ files = [
|
|||
{file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfgv"
|
||||
version = "3.4.0"
|
||||
description = "Validate configuration and produce human readable error messages."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"},
|
||||
{file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "charset-normalizer"
|
||||
version = "3.3.2"
|
||||
|
@ -360,6 +371,17 @@ tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.1
|
|||
[package.extras]
|
||||
toml = ["tomli"]
|
||||
|
||||
[[package]]
|
||||
name = "distlib"
|
||||
version = "0.3.8"
|
||||
description = "Distribution utilities"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"},
|
||||
{file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "docstring-parser-fork"
|
||||
version = "0.0.9"
|
||||
|
@ -407,6 +429,22 @@ files = [
|
|||
[package.extras]
|
||||
test = ["pytest (>=6)"]
|
||||
|
||||
[[package]]
|
||||
name = "filelock"
|
||||
version = "3.16.0"
|
||||
description = "A platform independent file lock."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "filelock-3.16.0-py3-none-any.whl", hash = "sha256:f6ed4c963184f4c84dd5557ce8fece759a3724b37b80c6c4f20a2f63a4dc6609"},
|
||||
{file = "filelock-3.16.0.tar.gz", hash = "sha256:81de9eb8453c769b63369f87f11131a7ab04e367f8d97ad39dc230daa07e3bec"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"]
|
||||
testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.1.1)", "pytest (>=8.3.2)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.3)"]
|
||||
typing = ["typing-extensions (>=4.12.2)"]
|
||||
|
||||
[[package]]
|
||||
name = "flake8"
|
||||
version = "7.1.1"
|
||||
|
@ -666,6 +704,20 @@ files = [
|
|||
[package.dependencies]
|
||||
flake8 = "*"
|
||||
|
||||
[[package]]
|
||||
name = "identify"
|
||||
version = "2.6.0"
|
||||
description = "File identification library for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "identify-2.6.0-py2.py3-none-any.whl", hash = "sha256:e79ae4406387a9d300332b5fd366d8994f1525e8414984e1a59e058b2eda2dd0"},
|
||||
{file = "identify-2.6.0.tar.gz", hash = "sha256:cb171c685bdc31bcc4c1734698736a7d5b6c8bf2e0c15117f4d469c8640ae5cf"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
license = ["ukkonen"]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "3.8"
|
||||
|
@ -922,6 +974,17 @@ files = [
|
|||
{file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nodeenv"
|
||||
version = "1.9.1"
|
||||
description = "Node.js virtual environment builder"
|
||||
optional = false
|
||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
||||
files = [
|
||||
{file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"},
|
||||
{file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "24.1"
|
||||
|
@ -1000,6 +1063,24 @@ files = [
|
|||
dev = ["pre-commit", "tox"]
|
||||
testing = ["pytest", "pytest-benchmark"]
|
||||
|
||||
[[package]]
|
||||
name = "pre-commit"
|
||||
version = "3.8.0"
|
||||
description = "A framework for managing and maintaining multi-language pre-commit hooks."
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
files = [
|
||||
{file = "pre_commit-3.8.0-py2.py3-none-any.whl", hash = "sha256:9a90a53bf82fdd8778d58085faf8d83df56e40dfe18f45b19446e26bf1b3a63f"},
|
||||
{file = "pre_commit-3.8.0.tar.gz", hash = "sha256:8bb6494d4a20423842e198980c9ecf9f96607a07ea29549e180eef9ae80fe7af"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
cfgv = ">=2.0.0"
|
||||
identify = ">=1.0.0"
|
||||
nodeenv = ">=0.11.1"
|
||||
pyyaml = ">=5.1"
|
||||
virtualenv = ">=20.10.0"
|
||||
|
||||
[[package]]
|
||||
name = "pycodestyle"
|
||||
version = "2.12.1"
|
||||
|
@ -1520,6 +1601,26 @@ h2 = ["h2 (>=4,<5)"]
|
|||
socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
|
||||
zstd = ["zstandard (>=0.18.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "virtualenv"
|
||||
version = "20.26.4"
|
||||
description = "Virtual Python Environment builder"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "virtualenv-20.26.4-py3-none-any.whl", hash = "sha256:48f2695d9809277003f30776d155615ffc11328e6a0a8c1f0ec80188d7874a55"},
|
||||
{file = "virtualenv-20.26.4.tar.gz", hash = "sha256:c17f4e0f3e6036e9f26700446f85c76ab11df65ff6d8a9cbfad9f71aabfcf23c"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
distlib = ">=0.3.7,<1"
|
||||
filelock = ">=3.12.2,<4"
|
||||
platformdirs = ">=3.9.1,<5"
|
||||
|
||||
[package.extras]
|
||||
docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
|
||||
test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"]
|
||||
|
||||
[[package]]
|
||||
name = "xdoctest"
|
||||
version = "1.2.0"
|
||||
|
@ -1573,4 +1674,4 @@ type = ["pytest-mypy"]
|
|||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.9"
|
||||
content-hash = "cc035dcf07b2024900d20f7e2873c3c4c5497e71fa493bf04a629a087f994ec3"
|
||||
content-hash = "3a34bd29eb4226a6054fe5ddba556605fcd621ceff7661334edf429d715c320f"
|
||||
|
|
|
@ -32,6 +32,8 @@ python = "^3.9"
|
|||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
|
||||
pre-commit = "^3.8"
|
||||
|
||||
# Code formatters
|
||||
autoflake = "^2.3"
|
||||
black = "^24.8"
|
||||
|
|
Loading…
Reference in a new issue