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