From 950ac95b31937aa78c7076520ca8ac014afd43ac Mon Sep 17 00:00:00 2001 From: Lewis Barker Date: Fri, 20 Sep 2024 22:38:32 +0100 Subject: [PATCH] Add pre-commit The way that pre-commit installs tools via git tags and ignores the environment in use is neat but kind of annoying, since it means either duplicating them, only using the tool via pre-commit, or bypassing the typical setup with a "system" pre-commit configuration. For ruff I've removed it from the venv and can only use it via pre-commit, which seems fine since I only use it in simple ways, but could become annoying later. In the case of mypy I immediately ran into a problem with the fact that I would need to specify my dependencies (or type stubs for them) in the pre-commit configuration to get it to work correctly in the isolated environment. I absolutely don't want that duplication, so instead I'm using the "system" workaround, which isn't much extra configuration. This follows the logic described here: https://github.com/python/mypy/issues/13916. I also disabled pass_filenames due to it not making much sense with mypy, as described there. Another pain point is needing to have pre-commit available to commit, which right now means activating the appropriate environment. Probably a case where pipx would be ideal, but I don't feel like setting it up right now. --- .pre-commit-config.yaml | 26 ++++++++++++++++++++++++++ README.md | 24 +++++++++++++++++++----- pyproject.toml | 7 ++++--- requirements-dev.txt | 20 ++++++++++++++++++-- 4 files changed, 67 insertions(+), 10 deletions(-) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..652a45c --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,26 @@ +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.6.0 + hooks: + - id: check-added-large-files + - id: check-merge-conflict + - id: check-toml + - id: check-yaml + - id: end-of-file-fixer +- repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.6.6 + hooks: + - id: ruff + args: [ --fix ] + - id: ruff-format +# Following recommendations from https://github.com/python/mypy/issues/13916 +# This does make the mypy step slower +- repo: local + hooks: + - id: mypy + name: mypy + language: system + entry: mypy + types_or: [python, pyi] + args: ["--strict", ""] + pass_filenames: false diff --git a/README.md b/README.md index 575c565..6c96d22 100644 --- a/README.md +++ b/README.md @@ -52,16 +52,30 @@ After activating an environment with dev dependencies: pytest tests/ ``` -### Format and lint +### Formatting, linting, and type-checking +Formatting and linting are primarily done using ruff, and managed via pre-commit. +Type-checking is done using mypy, which is installed in the venv (outside of +pre-commit's isolated venv) and run by pre-commit (for reasons see +https://github.com/python/mypy/issues/13916). + +Set up pre-commit: ``` -ruff format && ruff check +pre-commit install ``` -To autofix linting errors (where possible): + +Checks will run before commit, and abort commit if any fail or make changes - in which +case the changes will need to be reviewed and git added. + +To run ruff manually on all files: ``` -ruff check --fix +pre-commit run ruff --all-files ``` -### Static type check +To run mypy manually on all files: +``` +pre-commit run mypy --all-files +``` +or ``` mypy --strict . ``` diff --git a/pyproject.toml b/pyproject.toml index 3f70bf9..5cfd19d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,13 +14,14 @@ dependencies = [ [project.optional-dependencies] dev = [ + "mypy", # Installed here but used via pre-commit "pip-tools", + "pre-commit", "pytest", "pytest-mock", - "ruff", - "mypy", ] +# Ruff is configured here but installed via pre-commit [tool.ruff.lint] select = [ "A", # flake8-builtins @@ -69,4 +70,4 @@ ignore = [ "tests/*" = [ "ARG002", # Pytest fixtures often require unused arguments "PLR2004", # Magic values in tests are fine -] \ No newline at end of file +] diff --git a/requirements-dev.txt b/requirements-dev.txt index 4ee3b52..65a6391 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -8,10 +8,18 @@ build==1.2.2 # via pip-tools certifi==2024.8.30 # via requests +cfgv==3.4.0 + # via pre-commit charset-normalizer==3.3.2 # via requests click==8.1.7 # via pip-tools +distlib==0.3.8 + # via virtualenv +filelock==3.16.1 + # via virtualenv +identify==2.6.1 + # via pre-commit idna==3.8 # via requests iniconfig==2.0.0 @@ -20,14 +28,20 @@ mypy==1.11.2 # via wordall (/home/lewis/repos/wordall/pyproject.toml) mypy-extensions==1.0.0 # via mypy +nodeenv==1.9.1 + # via pre-commit packaging==24.1 # via # build # pytest pip-tools==7.4.1 # via wordall (/home/lewis/repos/wordall/pyproject.toml) +platformdirs==4.3.6 + # via virtualenv pluggy==1.5.0 # via pytest +pre-commit==3.8.0 + # via wordall (/home/lewis/repos/wordall/pyproject.toml) pyproject-hooks==1.1.0 # via # build @@ -38,14 +52,16 @@ pytest==8.3.3 # wordall (/home/lewis/repos/wordall/pyproject.toml) pytest-mock==3.14.0 # via wordall (/home/lewis/repos/wordall/pyproject.toml) +pyyaml==6.0.2 + # via pre-commit requests==2.32.3 # via wordall (/home/lewis/repos/wordall/pyproject.toml) -ruff==0.6.4 - # via wordall (/home/lewis/repos/wordall/pyproject.toml) typing-extensions==4.12.2 # via mypy urllib3==2.2.2 # via requests +virtualenv==20.26.5 + # via pre-commit wheel==0.44.0 # via pip-tools