Pre-Commit : Useful Hooks

code
analysis
linting
git
github
gitlab
pre-commit
Author

Neil Shephard

Published

May 7, 2023

I’m a big fan of pre-commit and have written about it before (see posts on pre-commit, pre-commit CI and pre-commit updating). This post discusses some of the hooks that I use and how to configure them.

Python Linting

Ruff

ruff is a Python linter written in Rust which means its considerably faster than many native linters. It aims for parity with Flake8 and covers a lot of the linting that PyLint undertakes too. Its configured via pyproject.toml which makes incorporating it into your Python Package simple.

repos:
  - repo: https://github.com/charliermarsh/ruff-pre-commit
    rev: v0.0.191
    hooks:
      - id: ruff

Configuration is, as noted, via pyproject.toml and you may find the post on Python Packaging worth reading to understand more on this.

[tool.ruff]
exclude = []
# per-file-ignores = []
line-length = 120
target-version = "py310"

# Allow autofix for all enabled rules (when `--fix`) is provided.
fixable = ["A", "B", "C", "D", "E", "F", "R", "S", "W", "U"]
unfixable = []

Black

Black is an opinionated formatter for Python that is PEP8 compliant. By using black to format your code you end up with a consistent style across the code base and commit changes end up being minimal. This helps speed up code-review of pull-requests.

repos:
  - repo: https://github.com/psf/black
    rev: 22.10.0
    hooks:
      - id: black
        types: [python]

Configuration is, as noted, via pyproject.toml and you may find the post on Python Packaging worth reading to understand more on this.

[tool.black]
line-length = 120
target-version = ["py38", "py39", "py310"]
include = "\\.pyi?$"

pydocstyle

You can check your docstrings are correctly written using the pydocstyle hook.

Its pretty straight-forward to use and accepts arguments so you can pass all the command line options you might want to use into the hook when it runs. It supports three different doc string styles, pep257, numpy and google.

    - repo  https://github.com/pycqa/pydocstyle
        rev: 6.3.0  # pick a git hash / tag to point to
        hooks:
        - id: pydocstyle
        args:
        - --convention=numpy
        # Optionally ignore rules
        - --ignore=D101,D2

Alternatively you can add configuration options to your projects pyproject.toml under a [tool.pydocstyle] section.

[tool.pydocstyle]
convention = "numpy"
ignore = [
  "D101",
  "D2"
]

Markdown Linting

markdownlint-cli2 is a useful and highly configurable hook for linting Markdown and CommonMark. I wanted to use it on this blog though which is written using Quarto and therefore uses PandocMarkdown with files that have extension .qmd. I therefore enable the hook in .pre-commit-config.yaml with a configuration file specified

repos:
- repo: https://github.com/DavidAnson/markdownlint-cli2
  rev: v0.6.0
  hooks:
    - id: markdownlint-cli2
      args: [.markdownlin-cli2.yaml]

..and add a sample configuration file (e.g. .mardownlint-cli2.yaml although other formats such as JSON can be used) is shown below and markdownlint-cli2 picks this up automatically.

# Configuration
config:
  # MD013 - line-length
  line_length:
    line_length: 120
    code_blocks: false
    tables: false
  html:
    allowed_elements:
      - div

# Globs
globs:
  - "**/*.qmd"
  - "*.qmd"

# Fix any fixable errors
fix: false

Emacs Lisp

As I use Emacs I have recourse to write some Emacs Lisp and so its useful to applying formatting to my .el files before committing them. lisp-format does the job nicely.

repos:
  - repo: https://github.com/eschulte/lisp-format
    rev: 088c8f78ca41204b44f2636275517ac09a2de6a9
    hooks:
      - id: lisp-format
        name: formatter of lisp code
        description: Run lisp-format against lisp files
        language: script
        files: \.(lisp|cl|asd|scm|el)$
        entry: lisp-format -i

Conclusion

There are a lot of hooks out there to be used with pre-commit and incorporated into your Continuous Integration pipeline with pre-commit.ci. Which you find useful will depend to a large extent on the languages that you are using for any given project. Here I’ve focused mainly on common tools for Python Packages, Markdown and Lisp but you can find hooks for Docker, Ansible, Rust, Go, JavaScript, C++ and many more, there is even gitlint which lints your commit messages! Checkout the long list of available hooks and try some out.

No matching items

Reuse

Citation

BibTeX citation:
@online{shephard2023,
  author = {Shephard, Neil},
  title = {Pre-Commit : {Useful} {Hooks}},
  date = {2023-05-07},
  url = {https://blog.nshephard.dev/posts/pre-commit-hooks/},
  langid = {en}
}
For attribution, please cite this work as:
Shephard, Neil. 2023. “Pre-Commit : Useful Hooks.” May 7, 2023. https://blog.nshephard.dev/posts/pre-commit-hooks/.