# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['autohooks',
 'autohooks.api',
 'autohooks.cli',
 'autohooks.precommit',
 'tests',
 'tests.api',
 'tests.api.git',
 'tests.cli']

package_data = \
{'': ['*']}

modules = \
['CHANGELOG', 'RELEASE', 'poetry']
install_requires = \
['pontos>=22.8.0', 'rich>=12.5.1,<13.0.0', 'tomlkit>=0.5.11']

entry_points = \
{'console_scripts': ['autohooks = autohooks.cli:main']}

setup_kwargs = {
    'name': 'autohooks',
    'version': '22.8.0',
    'description': 'Library for managing git hooks',
    'long_description': '![Greenbone Logo](https://www.greenbone.net/wp-content/uploads/gb_new-logo_horizontal_rgb_small.png)\n# Autohooks <!-- omit in toc -->\n\n[![PyPI release](https://img.shields.io/pypi/v/autohooks.svg)](https://pypi.org/project/autohooks/)\n[![Build and test Python package](https://github.com/greenbone/autohooks/actions/workflows/ci-python.yml/badge.svg)](https://github.com/greenbone/autohooks/actions/workflows/ci-python.yml)\n[![codecov](https://codecov.io/gh/greenbone/autohooks/branch/main/graph/badge.svg?token=9IX7ucaFwj)](https://codecov.io/gh/greenbone/autohooks)\n\nLibrary for managing and writing [git hooks](https://git-scm.com/docs/githooks)\nin Python.\n\nLooking for automatic formatting or linting, e.g., with [black] and [pylint],\nwhile creating a git commit using a pure Python implementation?\nWelcome to **autohooks**!\n\n- [Why?](#why)\n- [Solution](#solution)\n- [Requirements](#requirements)\n- [Modes](#modes)\n  - [Pythonpath Mode](#pythonpath-mode)\n  - [Poetry Mode](#poetry-mode)\n  - [Pipenv Mode](#pipenv-mode)\n- [Installing autohooks](#installing-autohooks)\n  - [1. Choosing an autohooks Mode](#1-choosing-an-autohooks-mode)\n  - [2. Installing the autohooks Python Package into the Current Environment](#2-installing-the-autohooks-python-package-into-the-current-environment)\n  - [3. Configuring Plugins to Be Run](#3-configuring-plugins-to-be-run)\n  - [4. Activating the Git Hooks](#4-activating-the-git-hooks)\n- [Plugins](#plugins)\n- [Howto: Writing a Plugin](#howto-writing-a-plugin)\n  - [Linting Plugin](#linting-plugin)\n  - [Formatting Plugin](#formatting-plugin)\n- [Maintainer](#maintainer)\n- [Contributing](#contributing)\n- [License](#license)\n\n## Why?\n\nSeveral outstanding libraries for managing and executing git hooks exist already.\nTo name a few: [husky](https://github.com/typicode/husky),\n[lint-staged](https://github.com/okonet/lint-staged),\n[precise-commits](https://github.com/nrwl/precise-commits) or\n[pre-commit](https://github.com/pre-commit/pre-commit).\n\nHowever, they either need another interpreter besides python (like husky) or are\ntoo ambiguous (like pre-commit). pre-commit is written in python but has support\nhooks written in all kind of languages. Additionally, it maintains the dependencies by\nitself and does not install them in the current environment.\n\n## Solution\n\nautohooks is a pure python library that installs a minimal\n[executable git hook](https://github.com/greenbone/autohooks/blob/main/autohooks/precommit/template).\nIt allows the decision of how to maintain the hook dependencies\nby supporting different modes.\n\n![Autohooks](https://raw.githubusercontent.com/greenbone/autohooks/main/autohooks.gif)\n\n## Requirements\n\nPython 3.7+ is required for autohooks.\n\n## Modes\n\nCurrently three modes for using autohooks are supported:\n\n* `pythonpath`\n* `poetry`\n* `pipenv`\n\nThese modes handle how autohooks, the plugins and their dependencies are loaded\nduring git hook execution.\n\nIf no mode is specified in the [`pyproject.toml` config file](#configure-mode-and-plugins-to-be-run)\nand no mode is set during [activation](#activating-the-git-hooks), autohooks\nwill use the [pythonpath mode](#pythonpath-mode) by default.\n\n`poetry` or `pipenv` modes leverage the `/usr/bin/env` command using the\n`--split-string` (`-S`) option. If `autohooks` detects that it is\nrunning on an OS where `/usr/bin/env` is yet to support _split_strings_\n(notably ubuntu < 19.x), `autohooks` will automatically change to an\ninternally chosen `poetry_multiline`/`pipenv_mutliline` mode. The\n\'multiline\' modes *should not* be user-configured options; setting your\nproject to use `poetry` or `pipenv`allows team members the greatest\nlatitude to use an OS of their choice yet leverage the sane\n`/usr/bin/env --split-string` if possible. Though `poetry_multiline`\nwould generally work for all, it is very confusing sorcery.\n([Multiline shebang explained](https://rosettacode.org/wiki/Multiline_shebang#Python))\n\n### Pythonpath Mode\n\nIn the `pythonpath` mode, the user has to install autohooks, the desired\nplugins and their dependencies into the [PYTHONPATH](https://docs.python.org/3/library/sys.html#sys.path)\nmanually.\n\nThis can be achieved by running `python3 -m pip install --user autohooks ...` to put them\ninto the installation directory of the [current user](https://docs.python.org/3/library/site.html#site.USER_SITE)\nor with `python3 -m pip install autohooks ...` for a system wide installation.\n\nAlternatively, a [virtual environment](https://packaging.python.org/tutorials/installing-packages/#creating-and-using-virtual-environments)\ncould be used separating the installation from the global and user wide\nPython packages.\n\nIt is also possible to use [pipenv] for managing the virtual\nenvironment but activating the environment has to be done manually.\n\nTherefore it is even possible to run different versions of autohooks by\nusing the `pythonpath` mode and switching to a virtual environment.\n\n### Poetry Mode\n\nLike with the [pipenv mode](#pipenv-mode), it is possible to run autohooks in a\ndedicated environment controlled by [poetry]. By using the `poetry` mode the\nvirtual environment will be activated automatically in the background when\nexecuting the autohooks based git commit hook.\n\nUsing the `poetry` mode is highly recommended.\n\n### Pipenv Mode\n\nIn the `pipenv` mode [pipenv] is used to run autohooks in a dedicated virtual\nenvironment. Pipenv uses a lock file to install exact versions. Therefore the\ninstallation is deterministic and reliable between different developer setups.\nIn contrast to the `pythonpath` mode the activation of the virtual environment\nprovided by [pipenv] is done automatically in the background.\n\n## Installing autohooks\n\nFour steps are necessary for installing autohooks:\n\n1. Choosing an autohooks mode\n2. Installing the autohooks python package into the current environment\n3. Configuring plugins to be run\n4. Activating the [git hooks](https://git-scm.com/docs/githooks)\n\n### 1. Choosing an autohooks Mode\n\nFor its configuration, autohooks uses the *pyproject.toml* file specified in\n[PEP518](https://www.python.org/dev/peps/pep-0518/).\nAdding a *[tool.autohooks]* section allows to specify the desired [autohooks mode](#modes)\nand to set python modules to be run as [autohooks plugins](#plugins).\n\nThe mode can be set by adding a `mode =` line to the *pyproject.toml* file.\nCurrent possible options are `"pythonpath"`, `"pipenv"` and `"poetry"` (see\n[autohooks mode](#modes)). If the mode setting is missing, the `pythonpath` mode is used.\n\nExample *pyproject.toml*:\n\n```toml\n[tool.autohooks]\nmode = "pipenv"\n```\n\n### 2. Installing the autohooks Python Package into the Current Environment\n\nUsing [poetry] is highly recommended for installing the autohooks python package.\n\nTo install autohooks as a development dependency run\n\n```sh\npoetry add --dev autohooks\n```\n\nAlternatively, autohooks can be installed directly from GitHub by running\n\n```sh\npoetry add --dev git+https://github.com/greenbone/autohooks\n```\n\n### 3. Configuring Plugins to Be Run\n\nTo actually run an action on git hooks, [autohooks plugins](#plugins) have to be\ninstalled and configured, e.g., to install python linting via pylint run\n\n```bash\npoetry add --dev autohooks-plugin-pylint\n```\n\nAfterwards, the pylint plugin can be configured to run as a pre-commit git hook\nby adding the autohooks-plugins-pylint python module name to the `pre-commit`\nsetting in the `[tool.autohooks]` section in the *pyproject.toml* file.\n\nExample *pyproject.toml*:\n\n```toml\n[tool.autohooks]\nmode = "pipenv"\npre-commit = ["autohooks.plugins.pylint"]\n```\n\n### 4. Activating the Git Hooks\n\nBecause installing and activating git hooks automatically isn\'t reliable (with\nusing source distributions and different versions of pip) and even impossible\n(with using [wheels](https://www.python.org/dev/peps/pep-0427/)) the hooks need\nto be activated manually once in each installation.\n\nTo activate the git hooks run\n\n```bash\npoetry run autohooks activate\n```\n\nCalling `activate` also allows for overriding the [mode](#modes) defined in the\n*pyproject.toml* settings for testing purposes.\n\nExample:\n\n\n```bash\nautohooks activate --mode pipenv\n```\n\nPlease keep in mind that autohooks will always issue a warning if the mode used\nin the git hooks is different from the configured mode in the *pyproject.toml*\nfile.\n\nThe activation can always be verified by running `autohooks check`.\n\n## Plugins\n\n* Python code formatting via [black](https://github.com/greenbone/autohooks-plugin-black)\n\n* Python code formatting via [autopep8](https://github.com/LeoIV/autohooks-plugin-autopep8)\n\n* Python code linting via [pylint](https://github.com/greenbone/autohooks-plugin-pylint)\n\n* Python code linting via [flake8](https://github.com/greenbone/autohooks-plugin-flake8)\n\n* Python import sorting via [isort](https://github.com/greenbone/autohooks-plugin-isort)\n\n* Running tests via [pytest](https://github.com/greenbone/autohooks-plugin-pytest/)\n\n## Howto: Writing a Plugin\n\nPlugins need to be available in the\n[Python import path](https://docs.python.org/3/reference/import.html). The\neasiest way to achieve this is uploading a plugin to [PyPI](https://pypi.org/)\nand installing it via [pip] or [poetry].\n\nAlternatively, a plugin can also be put into a *.autohooks* directory in the root\ndirectory of the git repository where the hooks should be executed.\n\nAn autohooks plugin is a Python module which provides a **precommit** function.\nThe function must accept arbitrary keywords because the keywords are likely to\nchange in future. Therefore using **\\*\\*kwargs** is highly recommended.\nCurrently *config* and *report_progress* keyword arguments are passed to the\nprecommit function.\n\nExample:\n\n```python3\ndef precommit(config=None, report_progress=None, **kwargs):\n```\n\nThe config can be used to receive settings from the *pyproject.toml* file, e.g.,\n\n```toml\n[tool.autohooks.plugins.foo]\nbar = 2\n```\n\ncan be received with\n\n```python3\ndef precommit(**kwargs):\n    config = kwargs.get(\'config\')\n    default_value = 1\n    setting = config\n      .get(\'tool\', \'autohooks\', \'plugins\', \'foo\')\n      .get_value(\'bar\', default_value)\n    return 0\n```\n\nThe report_progress can be used since autohooks 22.8.0 to display a progress bar\nwhen running a plugin.\n\n```python3\ndef precommit(report_progress, **kwargs):\n    report_progress.init(len(files))\n\n    for file in files:\n      check_file(file)\n      report_progress.update()\n\n    return 0\n```\nWith autohooks it is possible to write all kinds of plugins. Most common are\nplugins for linting and formatting.\n\n### Linting Plugin\n\nUsually the standard call sequence for a linting plugin is the following:\n\n1. get list of staged files\n2. filter list of files for a specific file type\n3. stash unrelated changes\n4. apply checks on filtered list of files by calling some external tool\n5. raise exception if something did go wrong\n6. return 1 if check was not successful\n6. stage changes made by the tool\n7. unstash unrelated changes\n8. return 0\n\nExample plugin:\n\n```python3\nimport subprocess\n\nfrom autohooks.api import ok, fail\nfrom autohooks.api.git import get_staged_status, stash_unstaged_changes\nfrom autohooks.api.path import match\n\nDEFAULT_INCLUDE = (\'*.ext\')\n\n\ndef get_include(config)\n    if not config:\n        return DEFAULT_INCLUDE\n\n    config = config.get(\'tool\', \'autohooks\', \'plugins\', \'foo\')\n    return config.get_value(\'include\', DEFAULT_INCLUDE)\n\n\ndef precommit(**kwargs):\n    config = kwargs.get(\'config\')\n    include = get_include(config)\n\n    files = [f for f in get_staged_status() if match(f.path, include)]\n\n    if not files:\n      # not files to lint\n      return 0\n\n    with stash_unstaged_changes(files):\n        const failed = False\n        for file in files:\n            status = subprocess.call([\'foolinter\', str(file)])\n            if status:\n                fail(\'Could not validate {str(file)}\')\n                failed = True\n            else:\n                ok(\'Validated {str(file)}\')\n\n        return 1 if failed else 0\n```\n\n### Formatting Plugin\n\nUsually the standard call sequence for a formatting plugin is the following:\n\n1. get list of staged files\n2. filter list of files for a specific file type\n3. stash unrelated changes\n4. apply formatting on filtered list of files by calling some external tool\n5. raise exception if something did go wrong\n6. stage changes made by the tool\n7. unstash unrelated changes\n8. return 0\n\nExample plugin:\n\n```python3\nimport subprocess\n\nfrom autohooks.api import ok, error\nfrom autohooks.api.git import (\n    get_staged_status,\n    stage_files_from_status_list,\n    stash_unstaged_changes,\n)\nfrom autohooks.api.path import match\n\nDEFAULT_INCLUDE = (\'*.ext\')\n\n\ndef get_include(config)\n    if not config:\n        return DEFAULT_INCLUDE\n\n    config = config.get(\'tool\', \'autohooks\', \'plugins\', \'bar\')\n    return config.get_value(\'include\', DEFAULT_INCLUDE)\n\n\ndef precommit(**kwargs):\n    config = kwargs.get(\'config\')\n    include = get_include(config)\n\n    files = [f for f in get_staged_status() if match(f.path, include)]\n\n    if not files:\n      # not files to format\n      return 0\n\n    with stash_unstaged_changes(files):\n        for file in files:\n            # run formatter and raise exception if it fails\n            subprocess.run([\'barformatter\', str(file)], check=True)\n            ok(\'Formatted {str(file)}\')\n\n        return 0\n```\n\n## Maintainer\n\nThis project is maintained by [Greenbone Networks GmbH](https://www.greenbone.net/).\n\n## Contributing\n\nYour contributions are highly appreciated. Please\n[create a pull request](https://github.com/greenbone/autohooks/pulls)\non GitHub. Bigger changes need to be discussed with the development team via the\n[issues section at GitHub](https://github.com/greenbone/autohooks/issues)\nfirst.\n\n## License\n\nCopyright (C) 2019 - 2022 [Greenbone Networks GmbH](https://www.greenbone.net/)\n\nLicensed under the [GNU General Public License v3.0 or later](LICENSE).\n\n[black]: https://black.readthedocs.io/en/stable/\n[pip]: https://pip.pypa.io/en/stable/\n[pipenv]: https://pipenv.readthedocs.io/en/latest/\n[poetry]: https://python-poetry.org/\n[pylint]: https://pylint.readthedocs.io/en/latest/\n',
    'author': 'Greenbone Networks GmbH',
    'author_email': 'info@greenbone.net',
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://github.com/greenbone/autohooks',
    'packages': packages,
    'package_data': package_data,
    'py_modules': modules,
    'install_requires': install_requires,
    'entry_points': entry_points,
    'python_requires': '>=3.7,<4.0',
}


setup(**setup_kwargs)
