| """Build step class for linting Python files with pylint.""" |
| |
| from __future__ import absolute_import |
| import logging |
| import os |
| |
| from helpers import git_utils |
| from helpers import pylint |
| from slave import base_step |
| |
| PYLINTRC_NAMES = ['pylintrc', '.pylintrc'] |
| |
| class PylintStep(base_step.BaseStep): |
| """Build step class for linting Python files.""" |
| |
| def __init__(self, pylintrc_file=None, **kwargs): |
| """Creates a PylintStep instance. |
| |
| Args: |
| **kwargs: Any additional args to pass to BaseStep. |
| """ |
| base_step.BaseStep.__init__(self, name='pylint', **kwargs) |
| self._pylintrc_file = pylintrc_file |
| |
| def run(self): |
| """Runs pylint on all changed files for the current commit. |
| |
| Sets a build property "review" with the output. |
| |
| Returns: |
| True iff there were no lint errors. |
| """ |
| changed_files = git_utils.changed_files( |
| self, directory=self.directory, file_extensions=['.py'], |
| file_exclusion_pattern=r'^.+_pb2.py$') |
| |
| changed_files = [f |
| for f in changed_files |
| if self.allow_listed(f) and not self.deny_listed(f)] |
| |
| if not self._pylintrc_file: |
| for name in PYLINTRC_NAMES: |
| path = os.path.join(self.directory, name) |
| if os.path.isfile(path): |
| self._pylintrc_file = path |
| break |
| try: |
| lint_output = pylint.RunPylint( |
| changed_files, pylintrc_file=self._pylintrc_file, cwd=self.directory, |
| executor=self) |
| comments = pylint.ParseLint(lint_output.splitlines()) |
| |
| if not comments: |
| logging.info('Autogenerated lint comments: looks clean') |
| return True |
| except pylint.PylintError as e: |
| message = str(e) |
| self.add_review({'message': message}) |
| return False |
| |
| self.add_review({'message': 'Autogenerated lint comments', |
| 'comments': comments}) |
| return False |