Skip to main content

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:

output_main_1a.png

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 because FIXME was found in main_1.py
  • check_content_for("NotImplemented", "🚧", "fail") failed because NotImplemented was found in main_1.py
  • check_command("ruff check") failed because command ruff check returned non-zero output (because of unused import math)

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:

output_main_1b.png

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:

output_main_1c.png

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:

output_create_symlink.png

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

output_create_symlink.png

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)

Source distribution for simplegithooks 1.2.3.post0
File Size Uploaded Provenance
simplegithooks-1.2.3.post0.tar.gz 11.9 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for simplegithooks 1.2.3.post0
File Interpreter ABI Platform
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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page