blob: 14fbb4d22da77213aabe4e6aea4077cb8c2536d3 [file] [edit]
#!/usr/bin/env python3
# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""
Fix some flake8 errors by rewriting files for which flake8 emitted
an error/warning. Usage (from the root dir):
$ python3 -m flake8 --exit-zero | python3 scripts/fix_flake8.py
"""
import shutil
import sys
import tempfile
from collections import defaultdict
from collections import namedtuple
from pprint import pprint as pp # NOQA
ntentry = namedtuple('ntentry', 'msg, issue, lineno, pos, descr')
# =====================================================================
# utils
# =====================================================================
def enter_pdb():
from pdb import set_trace as st # trick GIT commit hook
sys.stdin = open('/dev/tty')
st()
def read_lines(fname):
with open(fname, 'rt') as f:
return f.readlines()
def read_line(fname, lineno):
with open(fname, 'rt') as f:
for i, line in enumerate(f, 1):
if i == lineno:
return line
raise ValueError("lineno too big")
def write_file(fname, newlines):
with tempfile.NamedTemporaryFile('wt', delete=False) as f:
for line in newlines:
f.write(line)
shutil.move(f.name, fname)
# =====================================================================
# handlers
# =====================================================================
def handle_f401(fname, lineno):
""" This is 'module imported but not used'
Able to handle this case:
import os
...but not this:
from os import listdir
"""
line = read_line(fname, lineno).strip()
if line.startswith('import '):
return True
else:
mods = line.partition(' import ')[2] # everything after import
return ',' not in mods
# =====================================================================
# converters
# =====================================================================
def remove_lines(fname, entries):
"""Check if we should remove lines, then do it.
Return the numner of lines removed.
"""
to_remove = []
for entry in entries:
msg, issue, lineno, pos, descr = entry
# 'module imported but not used'
if issue == 'F401' and handle_f401(fname, lineno):
to_remove.append(lineno)
# 'blank line(s) at end of file'
elif issue == 'W391':
lines = read_lines(fname)
i = len(lines) - 1
while lines[i] == '\n':
to_remove.append(i + 1)
i -= 1
# 'too many blank lines'
elif issue == 'E303':
howmany = descr.replace('(', '').replace(')', '')
howmany = int(howmany[-1])
for x in range(lineno - howmany, lineno):
to_remove.append(x)
if to_remove:
newlines = []
for i, line in enumerate(read_lines(fname), 1):
if i not in to_remove:
newlines.append(line)
print("removing line(s) from %s" % fname)
write_file(fname, newlines)
return len(to_remove)
def add_lines(fname, entries):
"""Check if we should remove lines, then do it.
Return the numner of lines removed.
"""
EXPECTED_BLANK_LINES = (
'E302', # 'expected 2 blank limes, found 1'
'E305') # ìexpected 2 blank lines after class or fun definition'
to_add = {}
for entry in entries:
msg, issue, lineno, pos, descr = entry
if issue in EXPECTED_BLANK_LINES:
howmany = 2 if descr.endswith('0') else 1
to_add[lineno] = howmany
if to_add:
newlines = []
for i, line in enumerate(read_lines(fname), 1):
if i in to_add:
newlines.append('\n' * to_add[i])
newlines.append(line)
print("adding line(s) to %s" % fname)
write_file(fname, newlines)
return len(to_add)
# =====================================================================
# main
# =====================================================================
def build_table():
table = defaultdict(list)
for line in sys.stdin:
line = line.strip()
if not line:
break
fields = line.split(':')
fname, lineno, pos = fields[:3]
issue = fields[3].split()[0]
descr = fields[3].strip().partition(' ')[2]
lineno, pos = int(lineno), int(pos)
table[fname].append(ntentry(line, issue, lineno, pos, descr))
return table
def main():
table = build_table()
# remove lines (unused imports)
removed = 0
for fname, entries in table.items():
removed += remove_lines(fname, entries)
if removed:
print("%s lines were removed from some file(s); please re-run" %
removed)
return
# add lines (missing \n between functions/classes)
added = 0
for fname, entries in table.items():
added += add_lines(fname, entries)
if added:
print("%s lines were added from some file(s); please re-run" %
added)
return
main()