mirror of
https://github.com/PyCQA/flake8.git
synced 2026-03-31 19:26:52 +00:00
Split up flake8/run.py
I've preserved the API for users expecting their hooks and other things to work. That said, I'm working on #51 now as well.
This commit is contained in:
parent
08099588df
commit
3bd8a21f62
4 changed files with 270 additions and 270 deletions
80
flake8/hooks.py
Normal file
80
flake8/hooks.py
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
import os
|
||||
from flake8.util import _initpep8, pep8style, skip_file
|
||||
from subprocess import Popen, PIPE
|
||||
|
||||
|
||||
def git_hook(complexity=-1, strict=False, ignore=None, lazy=False):
|
||||
from flake8.main import check_file
|
||||
_initpep8()
|
||||
if ignore:
|
||||
pep8style.options.ignore = ignore
|
||||
|
||||
warnings = 0
|
||||
|
||||
gitcmd = "git diff-index --cached --name-only HEAD"
|
||||
if lazy:
|
||||
gitcmd = gitcmd.replace('--cached ', '')
|
||||
|
||||
_, files_modified, _ = run(gitcmd)
|
||||
for filename in files_modified:
|
||||
ext = os.path.splitext(filename)[-1]
|
||||
if ext != '.py':
|
||||
continue
|
||||
if not os.path.exists(filename):
|
||||
continue
|
||||
warnings += check_file(path=filename, ignore=ignore,
|
||||
complexity=complexity)
|
||||
|
||||
if strict:
|
||||
return warnings
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def hg_hook(ui, repo, **kwargs):
|
||||
from flake8.main import check_file
|
||||
_initpep8()
|
||||
complexity = ui.config('flake8', 'complexity', default=-1)
|
||||
warnings = 0
|
||||
|
||||
for file_ in _get_files(repo, **kwargs):
|
||||
warnings += check_file(file_, complexity)
|
||||
|
||||
strict = ui.configbool('flake8', 'strict', default=True)
|
||||
|
||||
if strict:
|
||||
return warnings
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def run(command):
|
||||
p = Popen(command.split(), stdout=PIPE, stderr=PIPE)
|
||||
p.wait()
|
||||
return (p.returncode, [line.strip() for line in p.stdout.readlines()],
|
||||
[line.strip() for line in p.stderr.readlines()])
|
||||
|
||||
|
||||
def _get_files(repo, **kwargs):
|
||||
seen = set()
|
||||
for rev in range(repo[kwargs['node']], len(repo)):
|
||||
for file_ in repo[rev].files():
|
||||
file_ = os.path.join(repo.root, file_)
|
||||
if file_ in seen or not os.path.exists(file_):
|
||||
continue
|
||||
seen.add(file_)
|
||||
if not file_.endswith('.py'):
|
||||
continue
|
||||
if skip_file(file_):
|
||||
continue
|
||||
yield file_
|
||||
|
||||
|
||||
def find_vcs():
|
||||
if os.path.isdir('.git'):
|
||||
if not os.path.isdir('.git/hooks'):
|
||||
os.mkdir('.git/hooks')
|
||||
return '.git/hooks/pre-commit'
|
||||
elif os.path.isdir('.hg'):
|
||||
return '.hg/hgrc'
|
||||
return ''
|
||||
169
flake8/main.py
Normal file
169
flake8/main.py
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
import os
|
||||
import sys
|
||||
import pep8
|
||||
import flakey
|
||||
import select
|
||||
import optparse
|
||||
from flake8 import mccabe
|
||||
from flake8 import __version__
|
||||
from flake8.util import _initpep8, skip_file
|
||||
|
||||
pep8style = None
|
||||
|
||||
|
||||
def get_parser():
|
||||
"""Create a custom OptionParser"""
|
||||
|
||||
def version(option, opt, value, parser):
|
||||
parser.print_usage()
|
||||
parser.print_version()
|
||||
sys.exit(0)
|
||||
|
||||
# Create our own parser
|
||||
parser = optparse.OptionParser('%prog [options] [file.py|directory]',
|
||||
version=version)
|
||||
parser.version = '{0} (pep8: {1}, flakey: {2})'.format(
|
||||
__version__, pep8.__version__, flakey.__version__)
|
||||
parser.remove_option('--version')
|
||||
# don't overlap with pep8's verbose option
|
||||
parser.add_option('--builtins', default='', dest='builtins',
|
||||
help="append builtin functions to flakey's "
|
||||
"_MAGIC_BUILTINS")
|
||||
parser.add_option('--ignore', default='',
|
||||
help='skip errors and warnings (e.g. E4,W)')
|
||||
parser.add_option('--exit-zero', action='store_true', default=False,
|
||||
help='Exit with status 0 even if there are errors')
|
||||
parser.add_option('--max-complexity', default=-1, action='store',
|
||||
type='int', help='McCabe complexity threshold')
|
||||
parser.add_option('-V', '--version', action='callback',
|
||||
callback=version,
|
||||
help='Print the version info for flake8')
|
||||
return parser
|
||||
|
||||
|
||||
def main():
|
||||
global pep8style
|
||||
|
||||
# parse out our flags so pep8 doesn't get confused
|
||||
parser = get_parser()
|
||||
opts, sys.argv = parser.parse_args()
|
||||
|
||||
# make sure pep8 gets the information it expects
|
||||
sys.argv.insert(0, 'pep8')
|
||||
|
||||
pep8style = pep8.StyleGuide(parse_argv=True, config_file=True)
|
||||
options = pep8style.options
|
||||
complexity = opts.max_complexity
|
||||
builtins = set(opts.builtins.split(','))
|
||||
warnings = 0
|
||||
stdin = None
|
||||
|
||||
if builtins:
|
||||
orig_builtins = set(flakey.checker._MAGIC_GLOBALS)
|
||||
flakey.checker._MAGIC_GLOBALS = orig_builtins | builtins
|
||||
|
||||
if pep8style.paths and options.filename is not None:
|
||||
for path in _get_python_files(pep8style.paths):
|
||||
if path == '-':
|
||||
if stdin is None:
|
||||
stdin = read_stdin()
|
||||
warnings += check_code(stdin, opts.ignore, complexity)
|
||||
else:
|
||||
warnings += check_file(path, opts.ignore, complexity)
|
||||
else:
|
||||
stdin = read_stdin()
|
||||
warnings += check_code(stdin, opts.ignore, complexity)
|
||||
|
||||
if opts.exit_zero:
|
||||
raise SystemExit(0)
|
||||
|
||||
raise SystemExit(warnings)
|
||||
|
||||
|
||||
def check_file(path, ignore=(), complexity=-1):
|
||||
if pep8style.excluded(path):
|
||||
return 0
|
||||
warning = flakey.checkPath(path)
|
||||
warnings = flakey.print_messages(warning, ignore=ignore)
|
||||
warnings += pep8style.input_file(path)
|
||||
if complexity > -1:
|
||||
warnings += mccabe.get_module_complexity(path, complexity)
|
||||
return warnings
|
||||
|
||||
|
||||
def check_code(code, ignore=(), complexity=-1):
|
||||
warning = flakey.check(code, 'stdin')
|
||||
warnings = flakey.print_messages(warning, ignore=ignore)
|
||||
warnings += pep8style.input_file(None, lines=code.split('\n'))
|
||||
if complexity > -1:
|
||||
warnings += mccabe.get_code_complexity(code, complexity)
|
||||
return warnings
|
||||
|
||||
|
||||
def read_stdin():
|
||||
# wait for 1 second on the stdin fd
|
||||
reads, __, __ = select.select([sys.stdin], [], [], 1.)
|
||||
if reads == []:
|
||||
print('input not specified')
|
||||
raise SystemExit(1)
|
||||
|
||||
return sys.stdin.read()
|
||||
|
||||
|
||||
try:
|
||||
from setuptools import Command
|
||||
except ImportError:
|
||||
Flake8Command = None
|
||||
else:
|
||||
class Flake8Command(Command):
|
||||
description = "Run flake8 on modules registered in setuptools"
|
||||
user_options = []
|
||||
|
||||
def initialize_options(self):
|
||||
pass
|
||||
|
||||
def finalize_options(self):
|
||||
pass
|
||||
|
||||
def distribution_files(self):
|
||||
if self.distribution.packages:
|
||||
for package in self.distribution.packages:
|
||||
yield package.replace(".", os.path.sep)
|
||||
|
||||
if self.distribution.py_modules:
|
||||
for filename in self.distribution.py_modules:
|
||||
yield "%s.py" % filename
|
||||
|
||||
def run(self):
|
||||
_initpep8()
|
||||
|
||||
# _get_python_files can produce the same file several
|
||||
# times, if one of its paths is a parent of another. Keep
|
||||
# a set of checked files to de-duplicate.
|
||||
checked = set()
|
||||
|
||||
warnings = 0
|
||||
for path in _get_python_files(self.distribution_files()):
|
||||
if path not in checked:
|
||||
warnings += check_file(path)
|
||||
checked.add(path)
|
||||
|
||||
raise SystemExit(warnings > 0)
|
||||
|
||||
|
||||
def _get_python_files(paths):
|
||||
for path in paths:
|
||||
if os.path.isdir(path):
|
||||
for dirpath, dirnames, filenames in os.walk(path):
|
||||
if pep8style.excluded(dirpath):
|
||||
continue
|
||||
for filename in filenames:
|
||||
if not filename.endswith('.py'):
|
||||
continue
|
||||
fullpath = os.path.join(dirpath, filename)
|
||||
if not skip_file(fullpath) or pep8style.excluded(fullpath):
|
||||
yield fullpath
|
||||
|
||||
else:
|
||||
if not skip_file(path) or pep8style.excluded(path):
|
||||
yield path
|
||||
274
flake8/run.py
274
flake8/run.py
|
|
@ -2,276 +2,10 @@
|
|||
"""
|
||||
Implementation of the command-line I{flake8} tool.
|
||||
"""
|
||||
import sys
|
||||
import os
|
||||
import os.path
|
||||
import optparse
|
||||
from subprocess import PIPE, Popen
|
||||
import select
|
||||
|
||||
from flake8 import mccabe
|
||||
from flake8.util import skip_file
|
||||
from flake8 import __version__
|
||||
import pep8
|
||||
import flakey
|
||||
|
||||
pep8style = None
|
||||
|
||||
|
||||
def check_file(path, ignore=(), complexity=-1):
|
||||
if pep8style.excluded(path):
|
||||
return 0
|
||||
warning = flakey.checkPath(path)
|
||||
warnings = flakey.print_messages(warning, ignore=ignore)
|
||||
warnings += pep8style.input_file(path)
|
||||
if complexity > -1:
|
||||
warnings += mccabe.get_module_complexity(path, complexity)
|
||||
return warnings
|
||||
|
||||
|
||||
def check_code(code, ignore=(), complexity=-1):
|
||||
warning = flakey.check(code, 'stdin')
|
||||
warnings = flakey.print_messages(warning, ignore=ignore)
|
||||
warnings += pep8style.input_file(None, lines=code.split('\n'))
|
||||
if complexity > -1:
|
||||
warnings += mccabe.get_code_complexity(code, complexity)
|
||||
return warnings
|
||||
|
||||
|
||||
def _get_python_files(paths):
|
||||
for path in paths:
|
||||
if os.path.isdir(path):
|
||||
for dirpath, dirnames, filenames in os.walk(path):
|
||||
if pep8style.excluded(dirpath):
|
||||
continue
|
||||
for filename in filenames:
|
||||
if not filename.endswith('.py'):
|
||||
continue
|
||||
fullpath = os.path.join(dirpath, filename)
|
||||
if not skip_file(fullpath) or pep8style.excluded(fullpath):
|
||||
yield fullpath
|
||||
|
||||
else:
|
||||
if not skip_file(path) or pep8style.excluded(path):
|
||||
yield path
|
||||
|
||||
|
||||
def read_stdin():
|
||||
# wait for 1 second on the stdin fd
|
||||
reads, __, __ = select.select([sys.stdin], [], [], 1.)
|
||||
if reads == []:
|
||||
print('input not specified')
|
||||
raise SystemExit(1)
|
||||
|
||||
return sys.stdin.read()
|
||||
|
||||
|
||||
def get_parser():
|
||||
"""Create a custom OptionParser"""
|
||||
|
||||
def version(option, opt, value, parser):
|
||||
parser.print_usage()
|
||||
parser.print_version()
|
||||
sys.exit(0)
|
||||
|
||||
# Create our own parser
|
||||
parser = optparse.OptionParser('%prog [options] [file.py|directory]',
|
||||
version=version)
|
||||
parser.version = '{0} (pep8: {1}, flakey: {2})'.format(
|
||||
__version__, pep8.__version__, flakey.__version__)
|
||||
parser.remove_option('--version')
|
||||
# don't overlap with pep8's verbose option
|
||||
parser.add_option('--builtins', default='', dest='builtins',
|
||||
help="append builtin functions to flakey's "
|
||||
"_MAGIC_BUILTINS")
|
||||
parser.add_option('--ignore', default='',
|
||||
help='skip errors and warnings (e.g. E4,W)')
|
||||
parser.add_option('--exit-zero', action='store_true', default=False,
|
||||
help='Exit with status 0 even if there are errors')
|
||||
parser.add_option('--max-complexity', default=-1, action='store',
|
||||
type='int', help='McCabe complexity threshold')
|
||||
parser.add_option('-V', '--version', action='callback',
|
||||
callback=version,
|
||||
help='Print the version info for flake8')
|
||||
return parser
|
||||
|
||||
|
||||
def main():
|
||||
global pep8style
|
||||
|
||||
# parse out our flags so pep8 doesn't get confused
|
||||
parser = get_parser()
|
||||
opts, sys.argv = parser.parse_args()
|
||||
|
||||
# make sure pep8 gets the information it expects
|
||||
sys.argv.insert(0, 'pep8')
|
||||
|
||||
pep8style = pep8.StyleGuide(parse_argv=True, config_file=True)
|
||||
options = pep8style.options
|
||||
complexity = opts.max_complexity
|
||||
builtins = set(opts.builtins.split(','))
|
||||
warnings = 0
|
||||
stdin = None
|
||||
|
||||
if builtins:
|
||||
orig_builtins = set(flakey.checker._MAGIC_GLOBALS)
|
||||
flakey.checker._MAGIC_GLOBALS = orig_builtins | builtins
|
||||
|
||||
if pep8style.paths and options.filename is not None:
|
||||
for path in _get_python_files(pep8style.paths):
|
||||
if path == '-':
|
||||
if stdin is None:
|
||||
stdin = read_stdin()
|
||||
warnings += check_code(stdin, opts.ignore, complexity)
|
||||
else:
|
||||
warnings += check_file(path, opts.ignore, complexity)
|
||||
else:
|
||||
stdin = read_stdin()
|
||||
warnings += check_code(stdin, opts.ignore, complexity)
|
||||
|
||||
if opts.exit_zero:
|
||||
raise SystemExit(0)
|
||||
|
||||
raise SystemExit(warnings)
|
||||
|
||||
|
||||
def _get_files(repo, **kwargs):
|
||||
seen = set()
|
||||
for rev in range(repo[kwargs['node']], len(repo)):
|
||||
for file_ in repo[rev].files():
|
||||
file_ = os.path.join(repo.root, file_)
|
||||
if file_ in seen or not os.path.exists(file_):
|
||||
continue
|
||||
seen.add(file_)
|
||||
if not file_.endswith('.py'):
|
||||
continue
|
||||
if skip_file(file_):
|
||||
continue
|
||||
yield file_
|
||||
|
||||
|
||||
class _PEP8Options(object):
|
||||
# Default options taken from pep8.process_options()
|
||||
max_complexity = -1
|
||||
verbose = False
|
||||
quiet = False
|
||||
no_repeat = False
|
||||
exclude = [exc.rstrip('/') for exc in pep8.DEFAULT_EXCLUDE.split(',')]
|
||||
filename = ['*.py']
|
||||
select = []
|
||||
ignore = pep8.DEFAULT_IGNORE.split(',') # or []?
|
||||
show_source = False
|
||||
show_pep8 = False
|
||||
statistics = False
|
||||
count = False
|
||||
benchmark = False
|
||||
testsuite = ''
|
||||
doctest = False
|
||||
max_line_length = pep8.MAX_LINE_LENGTH
|
||||
|
||||
|
||||
def _initpep8():
|
||||
# default pep8 setup
|
||||
global pep8style
|
||||
if pep8style is None:
|
||||
pep8style = pep8.StyleGuide(config_file=True)
|
||||
pep8style.options.physical_checks = pep8.find_checks('physical_line')
|
||||
pep8style.options.logical_checks = pep8.find_checks('logical_line')
|
||||
pep8style.options.counters = dict.fromkeys(pep8.BENCHMARK_KEYS, 0)
|
||||
pep8style.options.messages = {}
|
||||
pep8style.options.max_line_length = 79
|
||||
pep8style.args = []
|
||||
|
||||
|
||||
def run(command):
|
||||
p = Popen(command.split(), stdout=PIPE, stderr=PIPE)
|
||||
p.wait()
|
||||
return (p.returncode, [line.strip() for line in p.stdout.readlines()],
|
||||
[line.strip() for line in p.stderr.readlines()])
|
||||
|
||||
|
||||
def git_hook(complexity=-1, strict=False, ignore=None, lazy=False):
|
||||
_initpep8()
|
||||
if ignore:
|
||||
pep8style.options.ignore = ignore
|
||||
|
||||
warnings = 0
|
||||
|
||||
gitcmd = "git diff-index --cached --name-only HEAD"
|
||||
if lazy:
|
||||
gitcmd = gitcmd.replace('--cached ', '')
|
||||
|
||||
_, files_modified, _ = run(gitcmd)
|
||||
for filename in files_modified:
|
||||
ext = os.path.splitext(filename)[-1]
|
||||
if ext != '.py':
|
||||
continue
|
||||
if not os.path.exists(filename):
|
||||
continue
|
||||
warnings += check_file(path=filename, ignore=ignore,
|
||||
complexity=complexity)
|
||||
|
||||
if strict:
|
||||
return warnings
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def hg_hook(ui, repo, **kwargs):
|
||||
_initpep8()
|
||||
complexity = ui.config('flake8', 'complexity', default=-1)
|
||||
warnings = 0
|
||||
|
||||
for file_ in _get_files(repo, **kwargs):
|
||||
warnings += check_file(file_, complexity)
|
||||
|
||||
strict = ui.configbool('flake8', 'strict', default=True)
|
||||
|
||||
if strict:
|
||||
return warnings
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
try:
|
||||
from setuptools import Command
|
||||
except ImportError:
|
||||
Flake8Command = None
|
||||
else:
|
||||
class Flake8Command(Command):
|
||||
description = "Run flake8 on modules registered in setuptools"
|
||||
user_options = []
|
||||
|
||||
def initialize_options(self):
|
||||
pass
|
||||
|
||||
def finalize_options(self):
|
||||
pass
|
||||
|
||||
def distribution_files(self):
|
||||
if self.distribution.packages:
|
||||
for package in self.distribution.packages:
|
||||
yield package.replace(".", os.path.sep)
|
||||
|
||||
if self.distribution.py_modules:
|
||||
for filename in self.distribution.py_modules:
|
||||
yield "%s.py" % filename
|
||||
|
||||
def run(self):
|
||||
_initpep8()
|
||||
|
||||
# _get_python_files can produce the same file several
|
||||
# times, if one of its paths is a parent of another. Keep
|
||||
# a set of checked files to de-duplicate.
|
||||
checked = set()
|
||||
|
||||
warnings = 0
|
||||
for path in _get_python_files(self.distribution_files()):
|
||||
if path not in checked:
|
||||
warnings += check_file(path)
|
||||
checked.add(path)
|
||||
|
||||
raise SystemExit(warnings > 0)
|
||||
from flake8.hooks import git_hook, hg_hook # noqa
|
||||
from flake8.main import main
|
||||
from flake8.main import (check_code, check_file, get_parser, # noqa
|
||||
Flake8Command) # noqa
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ from __future__ import with_statement
|
|||
import re
|
||||
import os
|
||||
|
||||
pep8style = None
|
||||
|
||||
|
||||
def skip_warning(warning, ignore=[]):
|
||||
# XXX quick dirty hack, just need to keep the line in the warning
|
||||
|
|
@ -40,3 +42,18 @@ def skip_file(path):
|
|||
finally:
|
||||
f.close()
|
||||
return _NOQA.search(content) is not None
|
||||
|
||||
|
||||
def _initpep8():
|
||||
# default pep8 setup
|
||||
global pep8style
|
||||
import pep8
|
||||
if pep8style is None:
|
||||
pep8style = pep8.StyleGuide(config_file=True)
|
||||
pep8style.options.physical_checks = pep8.find_checks('physical_line')
|
||||
pep8style.options.logical_checks = pep8.find_checks('logical_line')
|
||||
pep8style.options.counters = dict.fromkeys(pep8.BENCHMARK_KEYS, 0)
|
||||
pep8style.options.messages = {}
|
||||
pep8style.options.max_line_length = 79
|
||||
pep8style.args = []
|
||||
return pep8style
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue