|
| 1 | +# Copyright (c) 2019 Red Hat, Inc. |
| 2 | +# |
| 3 | +# Permission is hereby granted, free of charge, to any person obtaining a copy |
| 4 | +# of this software and associated documentation files (the "Software"), to |
| 5 | +# deal in the Software without restriction, including without limitation the |
| 6 | +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
| 7 | +# sell copies of the Software, and to permit persons to whom the Software is |
| 8 | +# furnished to do so, subject to the following conditions: |
| 9 | +# |
| 10 | +# The above copyright notice and this permission notice shall be included in |
| 11 | +# all copies or substantial portions of the Software. |
| 12 | +# |
| 13 | +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 14 | +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 15 | +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 16 | +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 17 | +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| 18 | +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| 19 | +# DEALINGS IN THE SOFTWARE. |
| 20 | +"""Linter module for pre-commit related code.""" |
| 21 | + |
| 22 | +import os |
| 23 | + |
| 24 | +import sh |
| 25 | + |
| 26 | +from molecule import logger |
| 27 | +from molecule import util |
| 28 | +from molecule.verifier.lint import base |
| 29 | + |
| 30 | +LOG = logger.get_logger(__name__) |
| 31 | + |
| 32 | + |
| 33 | +class PreCommit(base.Base): |
| 34 | + """ |
| 35 | + Pre-commit tool verifier wrapper. |
| 36 | +
|
| 37 | + This class is used to lint files by executing the pre-commit |
| 38 | + command line tool for files in the test folder with a prefix |
| 39 | + of ``test_``. |
| 40 | +
|
| 41 | + `Pre-Commit`_ is not the default verifier linter. |
| 42 | +
|
| 43 | + `Pre-Commit`_ is a linter for python files and more. |
| 44 | +
|
| 45 | + Additional options can be passed to ``pre-commit`` through the options |
| 46 | + dict. Any option set in this section will override the defaults. |
| 47 | +
|
| 48 | + .. code-block:: yaml |
| 49 | +
|
| 50 | + verifier: |
| 51 | + name: testinfra |
| 52 | + lint: |
| 53 | + name: pre-commit |
| 54 | + options: |
| 55 | + remove-tabs: |
| 56 | +
|
| 57 | + Test file linting can be disabled by setting ``enabled`` to False. |
| 58 | +
|
| 59 | + .. code-block:: yaml |
| 60 | +
|
| 61 | + verifier: |
| 62 | + name: testinfra |
| 63 | + lint: |
| 64 | + name: pre-commit |
| 65 | + enabled: False |
| 66 | +
|
| 67 | + Environment variables can be passed to lint. |
| 68 | +
|
| 69 | + .. code-block:: yaml |
| 70 | +
|
| 71 | + verifier: |
| 72 | + name: testinfra |
| 73 | + lint: |
| 74 | + name: pre-commit |
| 75 | + env: |
| 76 | + FOO: bar |
| 77 | +
|
| 78 | + Example pre-commit configuration file (``.pre-commit-config.yaml``) to run |
| 79 | + flake8. |
| 80 | +
|
| 81 | + .. code-block:: yaml |
| 82 | +
|
| 83 | + repos: |
| 84 | + - repo: local |
| 85 | + hooks: |
| 86 | + - id: flake8 |
| 87 | + name: flake8 |
| 88 | + entry: python -m flake8 --max-line-length=120 |
| 89 | + language: system |
| 90 | + types: [python] |
| 91 | +
|
| 92 | + .. _`Pre-Commit`: https://pre-commit.com/ |
| 93 | + """ |
| 94 | + |
| 95 | + def __init__(self, config): |
| 96 | + """ |
| 97 | + Set up the requirements to execute ``pre-commit`` tool. |
| 98 | +
|
| 99 | + :param config: An instance of a Molecule config. |
| 100 | + """ |
| 101 | + super(PreCommit, self).__init__(config) |
| 102 | + self._precommit_command = None |
| 103 | + if config: |
| 104 | + self._tests = self._get_tests() |
| 105 | + |
| 106 | + @property |
| 107 | + def default_options(self): |
| 108 | + """Default options for pre-commit tool runtime.""" |
| 109 | + return {} |
| 110 | + |
| 111 | + @property |
| 112 | + def default_env(self): |
| 113 | + """Default environment variables for pre-commit tool runtime.""" |
| 114 | + return util.merge_dicts(os.environ.copy(), self._config.env) |
| 115 | + |
| 116 | + def bake(self): |
| 117 | + """Bake a ready to execute ``pre-commit`` command.""" |
| 118 | + self._precommit_command = sh.Command('pre-commit').bake( |
| 119 | + 'run', |
| 120 | + self.options, |
| 121 | + '--files', |
| 122 | + self._tests, |
| 123 | + _env=self.env, |
| 124 | + _out=LOG.out, |
| 125 | + _err=LOG.error, |
| 126 | + ) |
| 127 | + |
| 128 | + def execute(self): |
| 129 | + """Execute the pre-commit command.""" |
| 130 | + if not self.enabled: |
| 131 | + msg = 'Skipping, verifier_lint is disabled.' |
| 132 | + LOG.warn(msg) |
| 133 | + return |
| 134 | + |
| 135 | + if not self._tests: |
| 136 | + msg = 'Skipping, no tests found.' |
| 137 | + LOG.warn(msg) |
| 138 | + return |
| 139 | + |
| 140 | + if self._precommit_command is None: |
| 141 | + self.bake() |
| 142 | + |
| 143 | + msg = 'Executing pre-commit on files found in {}/...'.format( |
| 144 | + self._config.verifier.directory |
| 145 | + ) |
| 146 | + LOG.info(msg) |
| 147 | + |
| 148 | + try: |
| 149 | + util.run_command(self._precommit_command, debug=self._config.debug) |
| 150 | + msg = 'Lint completed successfully.' |
| 151 | + LOG.success(msg) |
| 152 | + except sh.ErrorReturnCode as e: |
| 153 | + util.sysexit(e.exit_code) |
| 154 | + |
| 155 | + def _get_tests(self): |
| 156 | + """ |
| 157 | + Get a list of test files from the verifier's directory. |
| 158 | +
|
| 159 | + :return: list |
| 160 | + """ |
| 161 | + return list(util.os_walk(self._config.verifier.directory, 'test_*.py')) |
0 commit comments