Skip to main content

Dead-simple Git pre-commit hooks

Project description

A simple tool to manage pre-commit hooks for git.

Install it with pip (outside a virtual environment so it works with multiple projects):

pip3 install iprecommit

Then, initialize a pre-commit check in your git repository:

cd path/to/some/git/repo
iprecommit init

iprecommit init will create a file called precommit.py in the root of your git repository that defines your pre-commit checks. It's human-editable and self-explanatory.

Now, whenever you run git commit, the checks in precommit.py will be run automatically. You can also run the pre-commit checks manually:

iprecommit

Many pre-commit issues can be fixed automatically. To do so, run

iprecommit fix

Pass the --working flag to iprecommit and iprecommit fix to operate on both staged and unstaged changes.

User guide

Precommit file format

The precommit.py file that precommit generates will look something like this:

from iprecommit import checks


def init(precommit):
    precommit.check(checks.NoStagedAndUnstagedChanges())
    precommit.check(checks.NoWhitespaceInFilePath())
    precommit.check(checks.DoNotSubmit())

    # Check Python format with black.
    precommit.check(checks.PythonFormat())

    # Lint Python code with flake8.
    precommit.check(checks.PythonLint())

    # Check the order of Python imports with isort.
    precommit.check(checks.PythonImportOrder())

    # Check Python static type annotations with mypy.
    precommit.check(checks.PythonTypes())

    # Lint JavaScript code with ESLint.
    precommit.check(checks.JavaScriptLint())

precommit.py must define a function called init that accepts a single parameter, called precommit by convention.

precommit.check registers a pre-commit check. Checks are run in the order they are registered. The built-in checks know what kind of files they should be invoked on, so, e.g., checks.PythonFormat will only run on Python files. If you want to limit a check to a certain set of files, the check functions accept a exclude parameter which should be a list of Unix filename patterns:

precommit.check(checks.NoWhiteSpaceInFilePath(exclude=["data/*.csv"]))

You can also opt-in files with the include parameter. See the Python fnmatch module for details on the pattern syntax for exclude and include.

Since precommit.py is a Python file, you can disable checks by commenting them out.

The default precommit.py has checks for a number of languages. There is no overhead for checks for languages that you don't use. They will simply never be run.

Some pre-commit checks require other programs to be installed on the computer, e.g. PythonFormat requires the black code formatter. precommit init will not install these automatically. You have to install them yourself.

Writing your own checks

iprecommit comes with some useful checks out of the box, but sometimes you need to write your own checks. Doing so is straightforward.

To run a shell command and check that its exit status is zero, use the built-in checks.Command check:

precommit.check(checks.Command("UnitTests", ["./test"]))

If the command requires the names of the files to be passed to it, use pass_files=True:

precommit.check(checks.Command("FileCheck", ["check_file"], pass_files=True))

Restrict the types of files that the command runs on with include:

precommit.check(checks.Command("FileCheck", ["check_file"], pass_files=True, include=["*.py"]))

This will invoke the command check_file once, passing all files ending in .py with staged changes as command-line arguments.

If the command only accepts one file at a time, use separately:

precommit.check(checks.Command("FileCheck", ["check_file"], pass_files=True, separately=True, include=["*.py"]))

This will invoke check_file on each Python file with staged changes.

If you want to implement the logic of your check in Python rather than invoke a shell command, then look at the built-in checks in iprecommit/checks.py in this repository for guidance. DoNotSubmit is a good example of a simple custom check.

Development

The core logic for running checks and applying fixes is in iprecommit/lib.py. The built-in checks are defined in iprecommit/checks.py, and the pre-commit configuration template is at iprecommit/precommit.py.template.

Run the test suite with ./functional_test, which simulates an actual user session: creating a git repository and virtual environment, installing precommit, and running it as a shell command.

Missing features

You can see features that I've considered but ultimately rejected by looking at the issues marked 'wontfix' on GitHub. Some notable ones include:

  • Support for non-UTF-8 file paths
  • Support for customizing the name of precommit.py
  • Caching results of pre-commit checks

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

iprecommit-0.2.tar.gz (6.5 kB view details)

Uploaded Source

Built Distribution

iprecommit-0.2-py3-none-any.whl (7.9 kB view details)

Uploaded Python 3

File details

Details for the file iprecommit-0.2.tar.gz.

File metadata

  • Download URL: iprecommit-0.2.tar.gz
  • Upload date:
  • Size: 6.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.7.1 CPython/3.11.5 Darwin/22.6.0

File hashes

Hashes for iprecommit-0.2.tar.gz
Algorithm Hash digest
SHA256 aa8531c9e8ba9c7dff2890b5bb901d60bead8b3e2dc1e4b9b33688ebe17719b4
MD5 dbf63f1cfef17a5d3f8e524668755931
BLAKE2b-256 35e527635531e8a6fbb53045f0fb04d3abb31a521e3cedbd680db0cfad337352

See more details on using hashes here.

File details

Details for the file iprecommit-0.2-py3-none-any.whl.

File metadata

  • Download URL: iprecommit-0.2-py3-none-any.whl
  • Upload date:
  • Size: 7.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.7.1 CPython/3.11.5 Darwin/22.6.0

File hashes

Hashes for iprecommit-0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 02c45642bbfda8b8eecbab3e9418ce28a17489f81ec2452274334ee36ad6c297
MD5 28eb4b93940801b4296c6996e726bb7d
BLAKE2b-256 d90cce1690dee23991bf52556451f4b5877ad63899dfdf51dbd846ce2488c3bd

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page