/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
7381.4.1 by Jelmer Vernooij
Add flake8 plugin.
1
#
2
# This program is free software; you can redistribute it and/or modify
3
# it under the terms of the GNU General Public License as published by
4
# the Free Software Foundation; either version 2 of the License, or
5
# (at your option) any later version.
6
#
7
# This program is distributed in the hope that it will be useful,
8
# but WITHOUT ANY WARRANTY; without even the implied warranty of
9
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
# GNU General Public License for more details.
11
#
12
# You should have received a copy of the GNU General Public License
13
# along with this program; if not, write to the Free Software
14
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15
16
"""Flake8 type checking before commits.
17
18
Set the ``flake8.pre_commit_check`` configuration variable to True
19
to enable this.
20
"""
21
22
23
from breezy.errors import BzrError, DependencyNotPresent
24
25
26
class Flake8Errors(BzrError):
27
28
    _fmt = (
29
        "Running in strict flake8 mode; aborting commit, "
30
        "since %(errors)d flake8 errors exist."
31
    )
32
33
    def __init__(self, errors):
34
        self.errors = errors
35
36
37
def _delta_files(tree_delta):
38
    for path, file_id, kind in tree_delta.added:
39
        if kind == "file":
40
            yield path
41
    for (
42
        path,
43
        file_id,
44
        kind,
45
        text_modified,
46
        meta_modified,
47
    ) in tree_delta.modified:
48
        if kind == "file" and text_modified:
49
            yield path
50
    for (
51
        oldpath,
52
        newpath,
53
        id,
54
        kind,
55
        text_modified,
56
        meta_modified,
57
    ) in tree_delta.renamed:
58
        if kind == "file" and text_modified:
59
            yield newpath
60
    for path, id, old_kind, new_kind in tree_delta.kind_changed:
61
        if new_kind == "file":
62
            yield path
63
64
65
def _copy_files_to(tree, target_dir, files):
66
    from breezy import osutils
67
68
    for relpath in files:
69
        target_path = os.path.join(target_dir, relpath)
70
        os.makedirs(os.path.dirname(target_path))
71
        with tree.get_file(relpath) as inf, open(target_path, "wb") as outf:
72
            osutils.pumpfile(inf, outf)
73
            yield target_path
74
75
76
def _update_paths(checker_manager, temp_prefix):
77
    temp_prefix_length = len(temp_prefix)
78
    for checker in checker_manager.checkers:
79
        filename = checker.display_name
80
        if filename.startswith(temp_prefix):
81
            checker.display_name = os.path.relpath(
82
                filename[temp_prefix_length:]
83
            )
84
85
86
def hook(config, tree_delta, future_tree):
87
    """Execute Flake8 on the files in git's index.
88
89
    Determine which files are about to be committed and run Flake8 over
90
    them to check for violations.
91
92
    :param bool strict:
93
        If True, return the total number of errors/violations found by
94
        Flake8. This will cause the hook to fail.
95
    :returns:
96
        Total number of errors found during the run.
97
    :rtype:
98
        int
99
    """
100
    try:
101
        from flake8.main import application
102
    except ImportError as e:
103
        raise DependencyNotPresent('flake8', e)
104
    import tempfile
105
106
    strict = config.get("flake8.strict")
107
108
    app = application.Application()
109
    with tempfile.TemporaryDirectory() as tempdir:
110
        filepaths = list(
111
            _copy_files_to(future_tree, tempdir, _delta_files(tree_delta))
112
        )
113
        app.initialize([tempdir])
114
        app.options._running_from_vcs = True
115
        app.run_checks(filepaths)
116
        _update_paths(app.file_checker_manager, tempdir)
117
        app.report_errors()
118
119
    if strict:
120
        if app.result_count:
121
            raise Flake8Errors(app.result_count)
122
123
124
def _check_flake8(local, master, old_revno, old_revid, future_revno,
125
                  future_revid, tree_delta, future_tree):
126
    branch = local or master
127
    config = branch.get_config_stack()
128
    if config.get("flake8.pre_commit_check"):
129
        hook(config, tree_delta, future_tree)
130
131
132
from breezy.branch import Branch
133
Branch.hooks.install_named_hook("pre_commit", _check_flake8, "Check flake8")