Skip to main content

Manage 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.1.tar.gz (13.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

iprecommit-0.1-py3-none-any.whl (24.9 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: iprecommit-0.1.tar.gz
  • Upload date:
  • Size: 13.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.1 requests/2.22.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.8.10

File hashes

Hashes for iprecommit-0.1.tar.gz
Algorithm Hash digest
SHA256 3d1ea334af5b2e0624955e7f145a7d86c733274c6fe3f6dfeaa67d2449d565f5
MD5 aaf1dada4d3daf344b51f5abb5587a71
BLAKE2b-256 351b4fce0f9c2c098d8fce725fc01961d1a529b5281bd70bfe675efcb9127274

See more details on using hashes here.

File details

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

File metadata

  • Download URL: iprecommit-0.1-py3-none-any.whl
  • Upload date:
  • Size: 24.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.1 requests/2.22.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.8.10

File hashes

Hashes for iprecommit-0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 3750d703c6e0a3b4618db8c2a46e770fc045cbb004fd67ccacc3af9cc8b77b4d
MD5 34e31ce9bc562d08ea4df1cc1d389619
BLAKE2b-256 11f7006299c2ad713ba78af32fdbccee7612c38490dbd355d5eaeaa5d66f510d

See more details on using hashes here.

Supported by

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