Project moved
This project has been renamed from SimpleGitHooks to GitHooks and moved to a new repository https://github.com/kamil-cy/githooks
Please visit the new home of this library here: ➡️ https://pypi.org/project/githooks/
The old simplegithooks package is no longer maintained.
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
Metadata
Release files for simplegithooks 1.2.3.post0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| simplegithooks-1.2.3.post0.tar.gz | 11.9 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| simplegithooks-1.2.3.post0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 23.5 kB
Release files / simplegithooks-1.2.3.post0.tar.gz
| Download URL | simplegithooks-1.2.3.post0.tar.gz |
|---|---|
| Size | 11.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0316a31ea5f9f3013c0501858e51c82a0ccee48e192be64d46d58d64ec136e36
|
|
BLAKE2b-256 checksum How to use checksums |
df1362031eece0d20205ffaf1a06837dc560af7a6de5dd9e183c86448a612003
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","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}
|
Release files / simplegithooks-1.2.3.post0-py3-none-any.whl
| Download URL | simplegithooks-1.2.3.post0-py3-none-any.whl |
|---|---|
| Size | 11.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2939c717d0f6186350bd3beae538e5b74e176a8c25fc0ba6ef89748a7a1d1021
|
|
BLAKE2b-256 checksum How to use checksums |
542caef731af200449d44d6633627d9cf37a71bc46088b07e6807c798d73fd96
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","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}
|
Security for simplegithooks 1.2.3.post0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.