=========
+1.3 (UNRELEASED)
+----------------
+
++* Read user configuration from ``~/.config/pep8``
++ and local configuration from ``./.pep8``. (Issue #22)
++
+* Suggest less error-prone alternatives for E712 errors.
+
+* Rewrite E27 checks to run faster.
+
+
+1.2 (2012-06-01)
+----------------
+
+* Add E121 through E128 for continuation line indentation. These
+ checks are disabled by default. If you want to force all checks,
+ use switch ``--select=E,W``. Patch by Sam Vilain. (Issue #64)
+
+* Add E721 for direct type comparisons. (Issue #47)
+
+* Add E711 and E712 for comparisons to singletons. (Issue #46)
+
+* Fix spurious E225 and E701 for function annotations. (Issue #29)
+
+* Add E502 for explicit line join between brackets.
+
+* Fix E901 when printing source with ``--show-source``.
+
+* Report all errors for each checker, instead of reporting only the
+ first occurence for each line.
+
+* Option ``--show-pep8`` implies ``--first``.
+
+
+1.1 (2012-05-24)
+----------------
+
+* Add E901 for syntax errors. (Issues #63 and #30)
+
+* Add E271, E272, E273 and E274 for extraneous whitespace around
+ keywords. (Issue #57)
+
+* Add ``tox.ini`` configuration file for tests. (Issue #61)
+
+* Add ``.travis.yml`` configuration file for continuous integration.
+ (Issue #62)
+
+
+1.0.1 (2012-04-06)
+------------------
+
+* Fix inconsistent version numbers.
+
+
+1.0 (2012-04-04)
+----------------
+
+* Fix W602 ``raise`` to handle multi-char names. (Issue #53)
+
+
+0.7.0 (2012-03-26)
+------------------
+
+* Now ``--first`` prints only the first occurence of each error.
+ The ``--repeat`` flag becomes obsolete because it is the default
+ behaviour. (Issue #6)
+
+* Allow to specify ``--max-line-length``. (Issue #36)
+
+* Make the shebang more flexible. (Issue #26)
+
+* Add testsuite to the bundle. (Issue #25)
+
+* Fixes for Jython. (Issue #49)
+
+* Add PyPI classifiers. (Issue #43)
+
+* Fix the ``--exclude`` option. (Issue #48)
+
+* Fix W602, accept ``raise`` with 3 arguments. (Issue #34)
+
+* Correctly select all tests if ``DEFAULT_IGNORE == ''``.
+
+
+0.6.1 (2010-10-03)
+------------------
+
+* Fix inconsistent version numbers. (Issue #21)
+
+
0.6.0 (2010-09-19)
------------------
try:
frozenset
except NameError:
- from sets import ImmutableSet as frozenset
+ from sets import Set as set, ImmutableSet as frozenset
++try:
++ from configparser import RawConfigParser
++except ImportError:
++ from ConfigParser import RawConfigParser
DEFAULT_EXCLUDE = '.svn,CVS,.bzr,.hg,.git'
-DEFAULT_IGNORE = 'E24'
+DEFAULT_IGNORE = 'E12,E24'
++DEFAULT_CONFIG = os.path.join(
++ os.getenv("XDG_CONFIG_HOME") or
++ os.path.join(os.getenv("HOME"), ".config"), "pep8")
MAX_LINE_LENGTH = 79
-DEFAULT_CONFIG = os.path.expanduser('~/.pep8')
-DEFAULT_OPTION_LIST = ('verbose', 'quiet', 'repeat', 'exclude', 'filename',
- 'select', 'ignore', 'show-source', 'show-pep8', 'statistics',
- 'count', 'benchmark', 'testsuite', 'doctest', 'config')
+SINGLETONS = frozenset(['False', 'None', 'True'])
+KEYWORDS = frozenset(keyword.kwlist + ['print']) - SINGLETONS
INDENT_REGEX = re.compile(r'([ \t]*)')
RAISE_COMMA_REGEX = re.compile(r'raise\s+\w+\s*(,)')
print("Test passed.")
++def read_config(options, args, arglist, parser):
++ config = RawConfigParser()
++
++ user_conf = options.config
++ if os.path.isfile(user_conf):
++ if options.verbose:
++ print('user configuration: %s' % user_conf)
++ config.read(user_conf)
++
++ if len(args) == 1:
++ parent, tail = os.path.abspath(args[0]), True
++ while tail:
++ local_conf = os.path.join(parent, '.pep8')
++ if os.path.isfile(local_conf):
++ if options.verbose:
++ print('local configuration: %s' % local_conf)
++ config.read(local_conf)
++ break
++ parent, tail = os.path.split(parent)
++
++ if config.has_section('pep8'):
++ option_list = dict([(o.dest, o.type or o.action)
++ for o in parser.option_list if o.dest])
++
++ # First, read the defaut values
++ options, _ = parser.parse_args([])
++
++ # Second, parse the configuration
++ for opt in config.options('pep8'):
++ opt_type = option_list.get(opt)
++ if not opt_type:
++ print('Unknown option: %s' % opt)
++ elif opt_type in ('int', 'count'):
++ value = config.getint('pep8', opt)
++ elif opt_type == 'string':
++ value = config.get('pep8', opt)
++ else:
++ assert opt_type in ('store_true', 'store_false')
++ value = config.getboolean('pep8', opt)
++ setattr(options, opt, value)
++
++ # Third, overwrite with the command-line options
++ options, _ = parser.parse_args(arglist, values=options)
++
++ return options
++
def process_options(arglist=None):
"""
Process options passed either via arglist or via command line args.
help="measure processing speed")
parser.add_option('--testsuite', metavar='dir',
help="run regression tests from dir")
+ parser.add_option('--max-line-length', type='int', metavar='n',
+ default=MAX_LINE_LENGTH,
+ help="set maximum allowed line length (default: %d)" %
+ MAX_LINE_LENGTH)
parser.add_option('--doctest', action='store_true',
help="run doctest on myself")
- parser.add_option('--config', metavar='config-file',
- default=DEFAULT_CONFIG,
++ parser.add_option('--config', metavar='path', default=DEFAULT_CONFIG,
+ help='config file location')
+
options, args = parser.parse_args(arglist)
+ if options.show_pep8:
+ options.repeat = False
if options.testsuite:
args.append(options.testsuite)
-- if not args and not options.doctest:
-- parser.error('input not specified')
-
- if options.config and os.path.isfile(options.config):
- config = ConfigParser.RawConfigParser()
- config.read(options.config)
- for opt in DEFAULT_OPTION_LIST:
- p_opt = opt.replace('-', '_')
- try:
- options.__dict__[p_opt] = config.get('pep8', opt)
- except ConfigParser.NoOptionError:
- try:
- options.__dict__[p_opt] = config.get('pep8', p_opt)
- except ConfigParser.NoOptionError:
- pass
++ elif not options.doctest:
++ if not args:
++ if os.path.exists('.pep8'):
++ args = ['.']
++ else:
++ parser.error('input not specified')
++ options = read_config(options, args, arglist, parser)
+
options.prog = os.path.basename(sys.argv[0])
options.exclude = options.exclude.split(',')
- for index in range(len(options.exclude)):
- options.exclude[index] = options.exclude[index].rstrip('/')
+ for index, value in enumerate(options.exclude):
+ options.exclude[index] = value.rstrip('/')
if options.filename:
options.filename = options.filename.split(',')
+
if options.select:
options.select = options.select.split(',')
else: