Package: iprecommit
A simple tool to manage pre-commit hooks for git.Install it with pip (outside a virtual environment so it works with multiple projects):pip3installiprecommitThen, initialize a pre-commit check in your git repository:cdpath/to/some/git/repo
iprecommitinitiprecommit initwill create a file calledprecommit.pyin the root of your git repository that defines your pre-commit checks. It's human-editable and self-explanatory.Now, whenever you rungit commit, the checks inprecommit.pywill be run automatically. You can also run the pre-commit checks manually:iprecommitMany pre-commit issues can be fixed automatically. To do so, runiprecommitfixPass the--workingflag toiprecommitandiprecommit fixto operate on both staged and unstaged changes.User guidePrecommit file formatTheprecommit.pyfile thatprecommitgenerates will look something like this:fromiprecommitimportchecksdefinit(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.pymust define a function calledinitthat accepts a single parameter, calledprecommitby convention.precommit.checkregisters 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.PythonFormatwill only run on Python files. If you want to limit a check to a certain set of files, the check functions accept aexcludeparameter which should be a list of Unix filename patterns:precommit.check(checks.NoWhiteSpaceInFilePath(exclude=["data/*.csv"]))You can also opt-in files with theincludeparameter. See thePythonfnmatchmodulefor details on the pattern syntax forexcludeandinclude.Sinceprecommit.pyis a Python file, you can disable checks by commenting them out.The defaultprecommit.pyhas 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.PythonFormatrequires theblackcode formatter.precommit initwillnotinstall these automatically. You have to install them yourself.Writing your own checksiprecommitcomes 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-inchecks.Commandcheck:precommit.check(checks.Command("UnitTests",["./test"]))If the command requires the names of the files to be passed to it, usepass_files=True:precommit.check(checks.Command("FileCheck",["check_file"],pass_files=True))Restrict the types of files that the command runs on withinclude:precommit.check(checks.Command("FileCheck",["check_file"],pass_files=True,include=["*.py"]))This will invoke the commandcheck_fileonce, passing all files ending in.pywith staged changes as command-line arguments.If the command only accepts one file at a time, useseparately:precommit.check(checks.Command("FileCheck",["check_file"],pass_files=True,separately=True,include=["*.py"]))This will invokecheck_fileon 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 iniprecommit/checks.pyin this repository for guidance.DoNotSubmitis a good example of a simple custom check.DevelopmentThe core logic for running checks and applying fixes is iniprecommit/lib.py. The built-in checks are defined iniprecommit/checks.py, and the pre-commit configuration template is atiprecommit/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 featuresYou can see features that I've considered but ultimately rejected by looking atthe issues marked 'wontfix' on GitHub. Some notable ones include:Support for non-UTF-8 file pathsSupport for customizing the name ofprecommit.pyCaching results of pre-commit checks