This repository has been archived on 2024-12-19. You can view files and clone it, but cannot push or open issues or pull requests.
PyBitmessage-2024-12-19/fabfile/tasks.py
2018-05-11 08:40:18 +01:00

148 lines
4.4 KiB
Python

"""
Fabric tasks for PyBitmessage devops operations.
"""
import os
import sys
from fabric.api import run, task, hide, cd
from fabvenv import virtualenv
from fabfile.lib import pycodestyle, flake8, pylint, autopep8, PROJECT_ROOT, VENV_ROOT, coerce_bool, flatten
def get_results(file_list):
"""Take a list of files and resuln the results of applying the tools"""
results = []
for path_to_file in file_list:
result = {}
result['pycodestyle_violations'] = [
i
for i in pycodestyle(path_to_file).split("\n")
if i
]
result['flake8_violations'] = [
i
for i in flake8(path_to_file).split("\n")
if i
]
result['pylint_violations'] = [
i
for i in pylint(path_to_file).split("\n")
if all([
i,
not i.startswith(' '),
not i.startswith('\r'),
not i.startswith('-'),
not i.startswith('Y'),
not i.startswith('*'),
not i.startswith('Using config file'),
])
]
result['path_to_file'] = path_to_file
result['total_violations'] = sum(
[
len(result['pycodestyle_violations']),
len(result['flake8_violations']),
len(result['pylint_violations']),
]
)
results.append(result)
return results
def print_item(item, verbose, details):
"""Print an item with the appropriate verbosity / detail"""
if verbose:
line = "{0} {1} {2} {3} {4}".format(
item['total_violations'],
len(item['pycodestyle_violations']),
len(item['flake8_violations']),
len(item['pylint_violations']),
item['path_to_file'],
)
else:
line = item['path_to_file']
print line
if details:
print "pycodestyle:"
for detail in flatten(item['pycodestyle_violations']):
print detail
print
print "flake8:"
for detail in flatten(item['flake8_violations']):
print detail
print
print "pylint:"
for detail in flatten(item['pylint_violations']):
print detail
print
@task
def code_quality(top=10, verbose=True, details=False, fix=False, filename=None):
"""
Check code quality.
By default this command will analyse each Python file in the project with a variety of tools and display the count
or details of the violations discovered, sorted by most iolations first.
Default usage:
$ fab -H localhost code_quality
Options:
top: Display / fix only the top violating files, a value of 0 will display / fix all files
verbose: Display a header and the counts. Without this you just get the filenames in order
details: Display the violations one per line after the count/file summary
fix: Run autopep8 on the displayed file(s)
filename: Rather than analysing all files and displaying / fixing the top N, just analyse / diaply / fix the
specified file
Intended to be temporary until we have improved code quality and have safeguards to maintain it in place.
"""
verbose = coerce_bool(verbose)
details = coerce_bool(details)
fix = coerce_bool(fix)
end = int(top) if int(top) else -1
with hide('warnings', 'running', 'stdout'): # pylint: disable=not-context-manager
with virtualenv(VENV_ROOT):
if filename:
filename = os.path.abspath(filename)
if not os.path.exists(filename):
print "Bad filename, specify a Python file"
sys.exit(1)
else:
file_list = [filename]
else:
with cd(PROJECT_ROOT): # pylint: disable=not-context-manager
file_list = [
os.path.abspath(i.rstrip('\r'))
for i in run('find . -name "*.py"').split("\n")
]
if fix:
for path_to_file in file_list:
autopep8(path_to_file)
results = get_results(file_list)
if verbose:
print "\ntotal pycodestyle flake8 pylint path_to_file\n"
# Sort and slice
for item in sorted(
results,
reverse=True,
key=lambda x: x['total_violations']
)[:end]:
print_item(item, verbose, details)