Giter VIP home page Giter VIP logo

autohooks's Introduction

Greenbone Logo

Autohooks

PyPI release Build and test Python package codecov

Library for managing and writing git hooks in Python using pyproject.toml for its settings.

Looking for automatic formatting and linting, e.g., with black and ruff, while creating a git commit using a pure Python implementation? Do you just want to have your git hook settings in the pyproject.toml file too?

Welcome to autohooks!

Why?

Several outstanding libraries for managing and executing git hooks exist already. To name a few: husky, lint-staged, precise-commits or pre-commit.

However, they need another interpreter besides python (like husky), require a different config file besides pyproject.toml or are too ambiguous (like pre-commit). pre-commit is written in python but has support hooks written in all kind of languages. Additionally, it maintains the dependencies by itself and does not install them in the current environment.

Solution

autohooks is a pure python library that installs a minimal executable git hook. It allows the decision of how to maintain the hook dependencies by supporting different modes and stores its settings in the well known pyproject.toml file.

Autohooks

Requirements

Python 3.9+ is required for autohooks.

Plugins

  • Python code formatting via black

  • Python code formatting via autopep8

  • Python code linting via ruff

  • Python code linting via pylint

  • Python code linting via flake8

  • Python code linting via mypy

  • Python import sorting via isort

  • Running tests via pytest

Installing autohooks

Quick installation of ruff and black plugins using poetry:

poetry add --dev autohooks autohooks-plugin-black autohooks-plugin-ruff
poetry run autohooks activate --mode poetry
poetry run autohooks plugins add autohooks.plugins.black autohooks.plugins.ruff

The output of autohooks activate should be similar to

 ✓ autohooks pre-commit hook installed at /autohooks-test/.git/hooks/pre-commit using poetry mode.

Autohooks has an extensible plugin model. Each plugin provides different functionality which often requires to install additional dependencies.

For managing these dependencies currently three modes are supported by autohooks:

  • pythonpath for dependency management via pip
  • poetry for dependency management via poetry (recommended)
  • pipenv for dependency management via pipenv

These modes handle how autohooks, the plugins and their dependencies are loaded during git hook execution.

If no mode is specified in the pyproject.toml config file and no mode is set during activation, autohooks will use the pythonpath mode by default.

For more details on using pip, poetry or pipenv in conjunction with these modes see the documentation.

Command Completion

autohooks comes with support for command line completion in bash and zsh.

Setup for bash

echo "source ~/.autohooks-complete.bash" >> ~/.bashrc
autohooks --print-completion bash > ~/.autohooks-complete.bash

Alternatively, you can use the result of the completion command directly with the eval function of your bash shell:

eval "$(autohooks --print-completion bash)"

Setup for zsh

echo 'fpath=("$HOME/.zsh.d" $fpath)' >> ~/.zsh
mkdir -p ~/.zsh.d/
autohooks --print-completion zsh > ~/.zsh.d/_autohooks

Alternatively, you can use the result of the completion command directly with the eval function of your zsh shell:

eval "$(autohooks --print-completion zsh)"

Maintainer

This project is maintained by Greenbone AG.

Contributing

Your contributions are highly appreciated. Please create a pull request on GitHub. Bigger changes need to be discussed with the development team via the issues section at GitHub first.

License

Copyright (C) 2019 - 2024 Greenbone AG

Licensed under the GNU General Public License v3.0 or later.

autohooks's People

Contributors

bjoernricks avatar dependabot-preview[bot] avatar dependabot[bot] avatar emme1990 avatar gkedge avatar greenbonebot avatar k-schlosser avatar kidylee avatar leoiv avatar swaterkamp avatar wiegandm avatar y0urself avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

autohooks's Issues

autohooks.utils.GitError: Git command '['git', '-C', '...', 'rev-parse', '--git-dir']' returned non-zero exit status 128

Hi,

I have autohooks installed using pythonpath method.

If I run git commit --amend -m "Test" in root directory of repository, the autohooks runs correctly:

➜  test git:(temp) ✗ gc --amend -m "Test"
ℹ autohooks => pre-commit
ℹ     Running check_top_directory_names
✖         Could not validate top directory name of path testes/dsdsa

However if I run it inside the testes directory, I get following error:

➜  testes git:(temp) ✗ gc --amend -m "Test"
fatal: not a git repository: '.git'
could not determine .git directory. 
Traceback (most recent call last):
  File ".git/hooks/pre-commit", line 8, in <module>
    sys.exit(run())
  File "/home/ubuntu/anaconda3/lib/python3.7/site-packages/autohooks/precommit/run.py", line 90, in run
    pre_commit_hook = PreCommitHook()
  File "/home/ubuntu/anaconda3/lib/python3.7/site-packages/autohooks/hooks.py", line 44, in __init__
    self.pre_commit_hook_path = get_pre_commit_hook_path()
  File "/home/ubuntu/anaconda3/lib/python3.7/site-packages/autohooks/hooks.py", line 35, in get_pre_commit_hook_path
    git_hook_dir_path = get_git_hook_directory_path()
  File "/home/ubuntu/anaconda3/lib/python3.7/site-packages/autohooks/utils.py", line 70, in get_git_hook_directory_path
    git_dir_path = get_git_directory_path()
  File "/home/ubuntu/anaconda3/lib/python3.7/site-packages/autohooks/utils.py", line 54, in get_git_directory_path
    raise e from None
  File "/home/ubuntu/anaconda3/lib/python3.7/site-packages/autohooks/utils.py", line 49, in get_git_directory_path
    git_dir = exec_git('-C', pwd, 'rev-parse', '--git-dir').rstrip()
  File "/home/ubuntu/anaconda3/lib/python3.7/site-packages/autohooks/utils.py", line 42, in exec_git
    raise GitError(e.returncode, e.cmd, e.output, e.stderr) from None
autohooks.utils.GitError: Git command '['git', '-C', '...', 'rev-parse', '--git-dir']' returned non-zero exit status 128

If I run git -C `pwd` rev-parse --git-dir command inside the tested directory, I get proper result - a path which points to .git directory in repository root path.

Why command executed using exec_git method returns non-zero exit status 128 and the same command executed directly from the terminal returns proper result?

Btw. In my case .autohooks directory is another git submodule, because I want to store code of hooks in other repository than the one where pre-commit hooks are used.

Pipenv mode is broken by the --split-string (-S) argument of env in the shebang

Hi,

I found myself stuck for an hour trying to make the pipenv mode work. This made me take a look at the pre-commit script managed by autohooks.

I noticed that the --split-string (-S) argument of env (coreutils) is used in the shebang. But it doesn't seem to be available in every version of /usr/bin/env and using it breaks pipenv mode for me.

The change was brought by this commit.

My platform information

lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 18.04.3 LTS
Release:	18.04
Codename:	bionic

My env version

/usr/bin/env --version
env (GNU coreutils) 8.28
Copyright © 2017 Free Software Foundation, Inc.
License GPLv3+ : GNU GPL version 3 ou ultérieure
<http://gnu.org/licenses/gpl.html>
Ceci est un logiciel libre. Vous êtes libre de le modifier et de le redistribuer.
Ce logiciel n'est accompagné d'ABSOLUMENT AUCUNE GARANTIE, dans les limites
permises par la loi.

Écrit par Richard Mlynarik et David MacKenzie.

The error I get

From a pipenv virtualenv:

$ autohooks activate --force  --mode pipenv
$ git commit -m "foo"
/usr/bin/env : option invalide -- 'S'
Saisissez « /usr/bin/env --help » pour plus d'informations.

This is because the shebang used in the pre-commit script managed by autohooks is
#!/usr/bin/env -S pipenv run python3.

The whole script content is:

#!/usr/bin/env -S pipenv run python3
# meta = { version = 1 }

import sys

try:
    from autohooks.precommit import run
    sys.exit(run())
except ImportError:
    print(
        "Error: autohooks is not installed. To force creating a commit without "
        "verification via autohooks run 'git commit --no-verify'.",
        file=sys.stderr,
    )
    sys.exit(1)

Workaround

The only way for me to make it work for now is to force the pythonpath mode which rewrites the shebang of the previous script to #!/usr/bin/env python3

Questions/Recommandations

What are your recommandation for this problem?
I assume that upgrading my /usr/bin/env version should solve everything but maybe a minimum requirement should be explicitly mentioned in the install doc.
I found this interesting issue about pipenv shebang and it seems like -S is not available on Ubuntu. Is it a choice to make pipenv mode unavailable on Ubuntu?

Support ruff

It would be great if autohooks could support ruff.

BTW, I think the fact that this tool uses pyproject.toml (unlike pre-commit) is a big plus that you could highlight in your documentation.

Windows Problem

poetry run autohooks activate not working, giving KeyError PWD and after setting it manually, it's not performing any autohooks task as define in pyproject.toml.

Poetry Hooks

I've been using autohooks for the last months due its amount of plugins and because it's a quite simple to use, especially in my case that I use poetry for dependencies management. Poetry have some features if you use pre-commit, as explained in their official documentation page:
https://python-poetry.org/docs/master/pre-commit-hooks/

I'd like to know if there's a plugin that can do the features mentioned on the link above or if there's an intention to develop a plugin for those commands.

If it doesn't, I may be intersted in developing a plugin for that.

Thank you in advance!

commit fails on Windows with Python encoding error

I setup the git pre-commit hook using autohooks. My first attempt at a commit resulted in the following traceback:

Traceback (most recent call last):
  File "F:\dev\project\user\formatting\.git\hooks\pre-commit", line 8, in <module>
    sys.exit(run())
  File "G:\miniconda\envs\myenv\lib\site-packages\autohooks\precommit\run.py", line 103, in run
    term.bold_info('autohooks => pre-commit')
  File "G:\miniconda\envs\myenv\lib\site-packages\autohooks\terminal.py", line 116, in bold_info
    self._print_status(message, Signs.INFO, cf.cyan, style)
  File "G:\miniconda\envs\myenv\lib\site-packages\autohooks\terminal.py", line 79, in _print_status
    print(style(output))
  File "G:\miniconda\envs\myenv\lib\encodings\cp1252.py", line 19, in encode
    return codecs.charmap_encode(input,self.errors,encoding_table)[0]
UnicodeEncodeError: 'charmap' codec can't encode character '\u2139' in position 0: character maps to <undefined>

(Feature Request) Mandatory hooks / less graceful ImportError failure

Hi team & thanks for a great library!

Our team uses an app development workflow based on pyenv and poetry - with autohooks and its plugins installed locally to the project+virtual environment.

Our devs are often not actually in the virtual environment shell when doing stuff: Instead using commands like poetry run to trigger scripts and poetry add to update dependencies.

Unfortunately this often includes not being in the env when running git commit, and autohooks is currently pretty lax about this per the example pre-commit hook below:

#!/usr/bin/env python3

import sys

try:
    from autohooks.precommit import run
    sys.exit(run())
except ImportError:
    print('autohooks not installed. Ignoring pre-commit hook.')
    sys.exit(0)

I would love to see the ability (maybe via configuration if it's not for everybody?) to fail more forcefully in this case: For us it's much more likely that a forgetful developer is committing from the wrong environment than that there's an installation issue we want to tolerate!

additional hooks (ie commit-msg)

Hello there,

First off:
I'm glad i found autohooks as it addresses the downsides i see with pre-commit when using it with python (namely configuration via pyproject.toml and being able to managing dependencies with poetry)

Now to my question:
I'm trying to integrate commitizen which is normally ran in the commit-msg-hook.
After digging through autohooks-code it seems like it is only managing the pre-commit-hook.

It would be great if we could manage all the hooks.

(I'll call the individual hooks in .git/hooks/ stages from now on)

The requirements i see:

  • allow managing of all stages
  • have activate register a script for all stages by default
  • add config-option to define which stages to register
  • add argument to activate to define which stages to register (aka "i only want pre-commit and commit-msg")
  • allow plugins to define which stage they run in by default
  • allow the user to override which stage a plugin runs in

I would be glad to get some feedback on this idea.

thanks in advance

Request to add ruff

Hi! I've recently discovered your project and immediately added a bunch of autohooks plugins to my projects.

I wanted to add ruff pre-commit so I followed your documentation and created my own by creating a fork of your pylint plugin.

What is your usual workflow for this? Should I publish the plugin to PyPI or would you rather create a fork to keep everything under the same team?

Thanks for everything, love your work!

Request to publish new version

Dependency check reported CVE-2024-21503 in black, this way it is suggested to update to use version 24.3.0.

I see the update already was made on the main branch thanks to dependabot.

I would like to request a new release from this package, because there is a need for the vulnerability fix in our project.

Output overwritten by carriage return

Often -- but not always -- the output of autohooks is overwritten in my terminal by itself. For example, running autohooks check very briefly flashes single lines of text before they are overwritten by the following line. The final line is also overwritten, meaning no output is visible once the command is finished.

The behaviour described above is consistent among multiple terminal emulators and shells. However, sometimes the lines are displayed properly and then change back to being overwritten, in the same environment in subsequent runs of autohooks.

I strongly suspect this is related to erikrose/blessings#146. Capturing the output with script(1) does indeed show carriage return control characters (\r, ^M) being present at the end of every line:

Script started on 2019-12-20 08:49:42+01:00 [TERM="xterm-256color" TTY="/dev/pts/5" COLUMNS="212" LINES="58"]
^[7^[7^[[1Gautohooks pre-commit hook is active. ^[[206G [ ^[[32mok^[(B^[[m ]^M
^[8^[8^[7^[7^[[1Gautohooks pre-commit hook is outdated. Please run 'autohooks activate --force' to update your pre-commit hook. ^[[201G [ ^[[33mwarning^[(B^[[m ]^M
^[8^[8^[7^[7^[[1Gautohooks mode "pythonpath" in pre-commit hook python-gvm/.git/hooks/pre-commit differs from mode "pipenv" in python-gvm/pyproject.toml. ^[[201G [ ^[[33mwarning^[(B^[[m ]^M
^[8^[8^[7^[7^[[1GUsing autohooks mode "pythonpath". ^[[204G [ ^[[36minfo^[(B^[[m ]^M
^[8^[8^[7^[7^[[1GPlugin "autohooks.plugins.black" active and loadable. ^[[206G [ ^[[32mok^[(B^[[m ]^M
^[8^[8^[7^[7^[[1GPlugin "autohooks.plugins.pylint" active and loadable. ^[[206G [ ^[[32mok^[(B^[[m ]^M
^[8^[8
Script done on 2019-12-20 08:49:42+01:00 [COMMAND_EXIT_CODE="0"]

Enable system wide autohooks called from git commit in a virtual environment (eg. to support PyCharm)

Thanks for a great utility that I'm glad supports pyproject.toml.

I have run into an issue. I installed autohooks and plugins:

python3 -m pip install --user autohooks
python3 -m pip install --user autohooks-plugin-isort
python3 -m pip install --user autohooks-plugin-black
python3 -m pip install --user autohooks-plugin-pylint
python3 -m pip install --user autohooks-plugin-flake8

I added to my pyproject.toml:

[tool.autohooks]
mode = "pythonpath"
pre-commit = ["autohooks.plugins.black", "autohooks.plugins.flake8", "autohooks.plugins.isort", "autohooks.plugins.pylint"]

I activated and checked status. All looked fine.

mcarans@Holly [~/Programming/hdx-python-utilities] ± main S:2 ?:1 ✗                                                                                                                                                                                                           [hdx-python-utilitiespy-3.10.7] [16:58:48]
> autohooks activate --force
 ✓ autohooks settings written to /home/mcarans/Programming/hdx-python-utilities/pyproject.toml.
 ✓ autohooks pre-commit hook installed at /home/mcarans/Programming/hdx-python-utilities/.git/hooks/pre-commit using pythonpath mode.
mcarans@Holly [~/Programming/hdx-python-utilities] ± main S:2 U:1 ?:1 ✗                                                                                                                                                                                                       [hdx-python-utilitiespy-3.10.7] [17:05:14]
> autohooks check
 ✓ autohooks pre-commit hook is active.
 ✓ autohooks pre-commit hook is up-to-date.
 ℹ Using autohooks mode "pythonpath".
 ✓ Plugin "autohooks.plugins.black" active and loadable.
 ✓ Plugin "autohooks.plugins.flake8" active and loadable.
 ✓ Plugin "autohooks.plugins.isort" active and loadable.
 ✓ Plugin "autohooks.plugins.pylint" active and loadable.

I changed a file and tried to commit. It failed:

mcarans@Holly [~/Programming/hdx-python-utilities] ± main S:2 U:1 ?:1 ✗                                                                                                                                                                                                       [hdx-python-utilitiespy-3.10.7] [17:05:23]
> git commit -m "test git hook"
Error: autohooks is not installed. To force creating a commit without verification via autohooks run 'git commit --no-verify'.

What have I got wrong or missed?

Terminal class fails to determine witdth in NeoVim

I just introduced autohooks into one of my project. 🎉
Unfortunately get the error listed below, when I do my commit from within NeoVim with the fugitive plugin for Git. Apparently does the printing to the terminal not work correctly here. Unfortunately does this block the commit for me.

autohooks => pre-commit
Running autohooks.plugins.black
Traceback (most recent call last):
  File "/home/thore/.cache/pypoetry/virtualenvs/gandyns-py3.8/lib/python3.8/site-packages/autohooks/precommit/run.py", line 122, in run
    retval = plugin.precommit(config=config.get_config())
  File "/home/thore/.cache/pypoetry/virtualenvs/gandyns-py3.8/lib/python3.8/site-packages/autohooks/plugins/black/black.py", line 82, in preco
mmit
    ok('No staged files for black available.')
  File "/home/thore/.cache/pypoetry/virtualenvs/gandyns-py3.8/lib/python3.8/site-packages/autohooks/api/__init__.py", line 35, in ok
    __term.ok(message)
  File "/home/thore/.cache/pypoetry/virtualenvs/gandyns-py3.8/lib/python3.8/site-packages/autohooks/terminal.py", line 65, in ok
    self._print_end(message, 'ok', self._term.green)
  File "/home/thore/.cache/pypoetry/virtualenvs/gandyns-py3.8/lib/python3.8/site-packages/autohooks/terminal.py", line 37, in _print_end
    width = self._term.width - 1
TypeError: unsupported operand type(s) for -: 'NoneType' and 'int'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File ".git/hooks/pre-commit", line 8, in <module>
    sys.exit(run())
  File "/home/thore/.cache/pypoetry/virtualenvs/gandyns-py3.8/lib/python3.8/site-packages/autohooks/precommit/run.py", line 140, in run
    term.error(
  File "/home/thore/.cache/pypoetry/virtualenvs/gandyns-py3.8/lib/python3.8/site-packages/autohooks/terminal.py", line 71, in error
    self._print_end(message, 'error', self._term.red)
  File "/home/thore/.cache/pypoetry/virtualenvs/gandyns-py3.8/lib/python3.8/site-packages/autohooks/terminal.py", line 37, in _print_end
    width = self._term.width - 1
TypeError: unsupported operand type(s) for -: 'NoneType' and 'int'

When creating a custom hook in .authooks directory I get: No module named 'autohooks.plugin.flake8'

├── .autohooks
  ├── init.py
  └── flake8.py

init.py -

from .flake8 import precommit

pyproject.toml -

[tool.autohooks]
mode = "pipenv"
pre-commit = ["autohooks.plugins.black","autohooks.plugins.flake8"]

I'm not sure how to make the plugin available to autohook.

Full error;

ℹ Running autohooks.plugins.flake8
An error occurred while importing pre-commit hook autohooks.plugins.flake8. No module named
'autohooks.plugins.flake8'.

Windows Support?

autohooks/terminal.py depends on the curses package, which I believe is not supported on Windows. When I run the command
poetry run autohooks activate,
I receive the error
ModuleNotFoundError: No module named _curses.
Am I suppose to use a different command to activate the git hooks on Windows?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.