diff --git a/README b/README.rst similarity index 96% rename from README rename to README.rst index 2c08bf7..acd1a6e 100644 --- a/README +++ b/README.rst @@ -151,7 +151,7 @@ files listed in your ``py_modules`` and ``packages``. If any warnings are found, the command will exit with an error code:: $ python setup.py flake8 - + Original projects @@ -160,8 +160,9 @@ Original projects Flake8 is just a glue project, all the merits go to the creators of the original projects: -- pep8: http://github.com/jcrocholl/pep8/ +- pep8: https://github.com/jcrocholl/pep8/ - PyFlakes: http://divmod.org/trac/wiki/DivmodPyflakes +- flakey: https://bitbucket.org/icordasc/flakey - McCabe: http://nedbatchelder.com/blog/200803/python_code_complexity_microtool.html Warning / Error codes @@ -207,7 +208,7 @@ pep8: - W603: '<>' is deprecated, use '!=' - W604: backticks are deprecated, use 'repr()' -pyflakes: +flakey: - W402: imported but unused - W403: import from line shadowed by loop variable @@ -228,6 +229,15 @@ McCabe: CHANGES ======= +2.0.0 - 2013-01-xx +------------------ + +- Fixes #13: pep8 and flakey are now external dependencies +- Split run.py into main.py and hooks.py for better logic +- Expose our parser for our users +- New feature: Install git and hg hooks automagically +- By relying on flakey, we also fixed #45 and #35 + 1.7.0 - 2012-12-21 ------------------ diff --git a/flake8/hooks.py b/flake8/hooks.py index 970fffa..7d493b8 100644 --- a/flake8/hooks.py +++ b/flake8/hooks.py @@ -1,5 +1,7 @@ import os -from flake8.util import _initpep8, pep8style, skip_file +import sys +from flake8.util import (_initpep8, pep8style, skip_file, get_parser, + ConfigParser) from subprocess import Popen, PIPE @@ -78,3 +80,65 @@ def find_vcs(): elif os.path.isdir('.hg'): return '.hg/hgrc' return '' + + +git_hook_file = """#!/usr/bin/env python +import sys +import os +from flake8.hooks import git_hook + +COMPLEXITY = os.getenv('FLAKE8_COMPLEXITY', 10) +STRICT = os.getenv('FLAKE8_STRICT', False) + + +if __name__ == '__main__': + sys.exit(git_hook(complexity=COMPLEXITY, strict=STRICT)) +""" + + +def _install_hg_hook(path): + c = ConfigParser() + c.readfp(open(path, 'r')) + if not c.has_section('hooks'): + c.add_section('hooks') + + if not c.has_option('hooks', 'commit'): + c.set('hooks', 'commit', 'python:flake8.hooks.hg_hook') + + if not c.has_option('hooks', 'qrefresh'): + c.set('hooks', 'qrefresh', 'python:flake8.hooks.hg_hook') + + if not c.has_section('flake8'): + c.add_section('flake8') + + if not c.has_option('flake8', 'complexity'): + c.set('flake8', 'complexity', str(os.getenv('FLAKE8_COMPLEXITY', 10))) + + if not c.has_option('flake8', 'strict'): + c.set('flake8', 'strict', os.getenv('FLAKE8_STRICT', False)) + + c.write(open(path, 'w+')) + + +def install_hook(): + vcs = find_vcs() + + if not vcs: + p = get_parser() + sys.stderr.write('Error: could not find either a git or mercurial ' + 'directory. Please re-run this in a proper ' + 'repository.') + p.print_help() + sys.exit(1) + + status = 0 + if 'git' in vcs: + with open(vcs, 'w+') as fd: + fd.write(git_hook_file) + os.chmod(vcs, 744) + elif 'hg' in vcs: + _install_hg_hook(vcs) + else: + status = 1 + + sys.exit(status) diff --git a/flake8/main.py b/flake8/main.py index df92450..4cb8969 100644 --- a/flake8/main.py +++ b/flake8/main.py @@ -3,42 +3,8 @@ 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 +from flake8.util import _initpep8, skip_file, get_parser, pep8style def main(): @@ -48,6 +14,10 @@ def main(): parser = get_parser() opts, sys.argv = parser.parse_args() + if opts.install_hook: + from flake8.hooks import install_hook + install_hook() + # make sure pep8 gets the information it expects sys.argv.insert(0, 'pep8') diff --git a/flake8/util.py b/flake8/util.py index 1323857..17ce56f 100644 --- a/flake8/util.py +++ b/flake8/util.py @@ -1,10 +1,61 @@ from __future__ import with_statement import re import os +import optparse + +try: + # Python 2 + from ConfigParser import ConfigParser +except ImportError: + # Python 3 + from configparser import ConfigParser pep8style = None +def get_parser(): + """Create a custom OptionParser""" + from flake8 import __version__ + import flakey + import pep8 + + def version(option, opt, value, parser): + parser.print_usage() + parser.print_version() + sys.exit(0) + + def help(option, opt, value, parser): + parser.print_help() + p = pep8.get_parser() + p.print_help() + + # Create our own parser + parser = optparse.OptionParser('%prog [options] [file.py|directory]', + version=version, add_help_option=False) + 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') + parser.add_option('--install-hook', default=False, action='store_true', + help='Install the appropriate hook for this ' + 'repository.', dest='install_hook') + parser.add_option('-h', '--help', action='callback', callback=help, + help='Print this message and exit') + return parser + + def skip_warning(warning, ignore=[]): # XXX quick dirty hack, just need to keep the line in the warning if not hasattr(warning, 'message'): diff --git a/setup.py b/setup.py index 0cb9cee..0b6360d 100644 --- a/setup.py +++ b/setup.py @@ -28,7 +28,7 @@ else: from flake8 import __version__ -README = open('README').read() +README = open('README.rst').read() setup( name="flake8",