Write pretty and concise Git hooks in Python.
Project description
SimpleGitHooks
Write pretty and concise Git hooks in Python. SimpleGitHooks lets you write an entire Git hook directly in Python, without using YAML. It’s ideal when you want full control and all your logic contained in a single file.
Installing
You can install via pip:
pip install simplegithooks
Hooks
PreCommit
Write simple pre-commit Git hook in your .git/hooks/pre-commit:
#!/usr/bin/env python
from simplegithooks import PreCommit
pre_commit = PreCommit(__file__)
pre_commit.add_ignored_file("src/simplegithooks/pre-commit.py")
pre_commit.check_content_for("FIXME", "❌", "error")
pre_commit.check_content_for("NotImplemented", "🚧", "fail")
pre_commit.check_content_for("TODO", "⚠️", "warning", prevent=False)
pre_commit.check_command("ruff check")
print(pre_commit.results())
print(pre_commit.summary())
exit(pre_commit.rc)
Let's say you have such file in staged changes main_1.py because you've forgot to finish:
import math
def add(b, c):
# TODO add typing
return b + c
def divide(a, b):
# FIXME secure dividing by zero
return a / b
def sqrt():
raise NotImplementedError
And when you try to commit this file using git commit -m "message" the output will be:
What happened here? Let's focus only on checks that prevents us from commit this change:
- by default all checks prevents commit, unless you explicitly pass
prevent=False check_content_for("FIXME", "❌", "error")failed becauseFIXMEwas found inmain_1.pycheck_content_for("NotImplemented", "🚧", "fail")failed becauseNotImplementedwas found inmain_1.pycheck_command("ruff check")failed because commandruff checkreturned non-zero output (because of unused importmath)
Then if you fix issues the code now looks more on less like this:
import math
def add(b, c):
# TODO add typing
return b + c
def divide(a, b):
try:
return a / b
except Exception:
return float("inf")
def sqrt(x):
return math.sqrt(x)
The output after commit will be:
Now check_content_for("TODO", "⚠️", "warning", prevent=False) failed because TODO was found in main_1.py, yet this is not preventing us from commit changes, so commit command was succeeded but with warningCommit allowed conditionally.
Still we can do better 😉, so let's try harder:
import math
from typing import Any
def add(b:Any, c:Any):
return b + c
def divide(a, b):
try:
return a / b
except Exception:
return float("inf")
def sqrt(x):
return math.sqrt(x)
Finally we reached our goal:
PrePush
Write simple pre-push Git hook in your .git/hooks/pre-push:
#!/usr/bin/env python
import sys
from simplegithooks import GitHook, PrePushConfig
pre_push = GitHook(__file__, PrePushConfig())
pre_push.add_ignored_files(["pre_push_example.py", "*.svg", "README.md"])
pre_push.check_command("rm -rf build/")
pre_push.check_command("rm -rf dist/")
pre_push.check_command("pytest")
print(pre_push.results())
print(pre_push.summary())
sys.exit(pre_push.rc)
You'll get similar outputs like for pre-commit.
Common config
Ignoring files
pre_commit.add_ignored_file("src/obsolete.py")
pre_commit.add_ignored_files(["src/stub1.py", "src/stub2.py"])
Support for Python's pathlib.Path pattern matching
pre_commit.add_ignored_files(["pre-commit.py", "*.svg", "README.md"])
Filter results
print(pre_commit.results("error"))
print(pre_commit.results("warning"))
print(pre_commit.results("error", preventing_only=True))
print(pre_commit.results("warning", preventing_only=True))
Check commands which RC=0 means failure
pre_commit.check_command("true", rc_zero_succes=False) # ❯ true (ERROR, RC!=0 SUCCESS) 🔒
pre_commit.check_command("false", rc_zero_succes=False) # ❯ false (OK, RC!=0 SUCCESS)
Creating a symlink
Run simplegithooks pre-commit --install path/to/pre_commit.py or simplegithooks pre-push --install path/to/pre_push.py to create a symlink for you repository:
If a hook file already exists, an additional message e.g. WARNING: file '/home/user/project/.git/hooks/pre-commit' already exists and will be overwritten. will be shown as below
Troubleshooting
If you pass a bad hook name you'll receive a hint if there is a typo e.g. Unknown or unsupported hook: preccomyt, did you mean: pre-commit
In case of any problem while creating a symlink you'll get Failure, couldn't create the symbolic link. instead of success message.
License
This repository is licensed under the MIT License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file simplegithooks-1.2.1.tar.gz.
File metadata
- Download URL: simplegithooks-1.2.1.tar.gz
- Upload date:
- Size: 11.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.22 {"installer":{"name":"uv","version":"0.9.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f597dce546dcee865f6eebf6eaedffb9917a49534e23f9d4684ae76d3ba4e9be
|
|
| MD5 |
53622db3f754720495d794da756b207c
|
|
| BLAKE2b-256 |
a8eb9f9a09c3070cd34ce653edab3aa04ebc51cb9c6e2f6626879d0fedfc2c58
|
File details
Details for the file simplegithooks-1.2.1-py3-none-any.whl.
File metadata
- Download URL: simplegithooks-1.2.1-py3-none-any.whl
- Upload date:
- Size: 11.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.22 {"installer":{"name":"uv","version":"0.9.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
99e842f89774dafc1ea1f07f43a49374b725ed586ae6d19dfb47c8ef8def86be
|
|
| MD5 |
d63ed6032c91f71c8cf752a8a5603584
|
|
| BLAKE2b-256 |
4a4001791820d571ae3cc4940c39ca438f2235dadaea42050b336f36a5e4bb88
|