summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml1
-rw-r--r--CHANGES.txt22
-rw-r--r--docs/developer.rst2
-rw-r--r--docs/intro.rst13
-rwxr-xr-xpep8.py57
-rw-r--r--testsuite/E11.py22
-rw-r--r--testsuite/E22.py4
-rw-r--r--testsuite/E70.py19
-rw-r--r--testsuite/E73.py7
-rw-r--r--testsuite/W29.py4
-rw-r--r--testsuite/W39.py11
-rw-r--r--testsuite/test_api.py4
-rw-r--r--testsuite/test_shell.py2
13 files changed, 129 insertions, 39 deletions
diff --git a/.travis.yml b/.travis.yml
index 432b162..c50362b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,6 +4,7 @@ python:
- 2.7
- 3.2
- 3.3
+ - 3.4
- pypy
install:
- pip install -e .
diff --git a/CHANGES.txt b/CHANGES.txt
index e44ef4f..e18add4 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -5,14 +5,32 @@ Changelog
1.x (unreleased)
----------------
-Bug fixes:
+* Report E731 for lambda assignment. (Issue #277)
-* Skip the traceback on "Broken pipe" signal. (Issue #275)
+* Report E704 for one-liner def instead of E701. (Issue #277)
+
+* Replace codes E111, E112 and E113 with codes E114, E115 and E116
+ for wrong indentation of comments. (Issue #274)
* Report E266 instead of E265 when the block comment starts with
multiple ``#``. (Issue #270)
+1.5.7 (2014-05-29)
+------------------
+
+Bug fixes:
+
+* Skip the traceback on "Broken pipe" signal. (Issue #275)
+
+* Do not exit when an option in ``setup.cfg`` or ``tox.ini``
+ is not recognized.
+
+* Check the last line even if it does not end with a newline. (Issue #286)
+
+* Always open files in universal newlines mode in Python 2. (Issue #288)
+
+
1.5.6 (2014-04-14)
------------------
diff --git a/docs/developer.rst b/docs/developer.rst
index 205d593..7df1734 100644
--- a/docs/developer.rst
+++ b/docs/developer.rst
@@ -14,7 +14,7 @@ conditions of the :ref:`Expat license <license>`. Fork away!
* `Source code <https://github.com/jcrocholl/pep8>`_ and
`issue tracker <https://github.com/jcrocholl/pep8/issues>`_ on GitHub.
* `Continuous tests <http://travis-ci.org/jcrocholl/pep8>`_ against Python
- 2.6 through 3.3 and PyPy, on `Travis-CI platform
+ 2.6 through 3.4 and PyPy, on `Travis-CI platform
<http://about.travis-ci.org/>`_.
.. _available on GitHub: https://github.com/jcrocholl/pep8
diff --git a/docs/intro.rst b/docs/intro.rst
index c0ed737..88f0000 100644
--- a/docs/intro.rst
+++ b/docs/intro.rst
@@ -158,7 +158,8 @@ Configuration
The behaviour may be configured at two levels.
-The user settings are read from the ``~/.config/pep8`` file.
+The user settings are read from the ``~/.config/pep8`` file and
+for Windows from the ``~\.pep8`` file.
Example::
[pep8]
@@ -193,6 +194,12 @@ This is the current list of error and warning codes:
+----------+----------------------------------------------------------------------+
| E113 | unexpected indentation |
+----------+----------------------------------------------------------------------+
+| E114 | indentation is not a multiple of four (comment) |
++----------+----------------------------------------------------------------------+
+| E115 | expected an indented block (comment) |
++----------+----------------------------------------------------------------------+
+| E116 | unexpected indentation (comment) |
++----------+----------------------------------------------------------------------+
+----------+----------------------------------------------------------------------+
| E121 (^) | continuation line under-indented for hanging indent |
+----------+----------------------------------------------------------------------+
@@ -306,6 +313,8 @@ This is the current list of error and warning codes:
+----------+----------------------------------------------------------------------+
| E703 | statement ends with a semicolon |
+----------+----------------------------------------------------------------------+
+| E704 | multiple statements on one line (def) |
++----------+----------------------------------------------------------------------+
| E711 (^) | comparison to None should be 'if cond is None:' |
+----------+----------------------------------------------------------------------+
| E712 (^) | comparison to True should be 'if cond is True:' or 'if cond:' |
@@ -316,6 +325,8 @@ This is the current list of error and warning codes:
+----------+----------------------------------------------------------------------+
| E721 | do not compare types, use 'isinstance()' |
+----------+----------------------------------------------------------------------+
+| E731 | do not assign a lambda expression, use a def |
++----------+----------------------------------------------------------------------+
+----------+----------------------------------------------------------------------+
| **E9** | *Runtime* |
+----------+----------------------------------------------------------------------+
diff --git a/pep8.py b/pep8.py
index ac6bfed..b64dfda 100755
--- a/pep8.py
+++ b/pep8.py
@@ -46,7 +46,7 @@ W warnings
"""
from __future__ import with_statement
-__version__ = '1.5.7a0'
+__version__ = '1.6.0a0'
import os
import sys
@@ -353,20 +353,25 @@ def indentation(logical_line, previous_logical, indent_char,
Okay: a = 1
Okay: if a == 0:\n a = 1
E111: a = 1
+ E114: # a = 1
Okay: for item in items:\n pass
E112: for item in items:\npass
+ E115: for item in items:\n# Hi\n pass
Okay: a = 1\nb = 2
E113: a = 1\n b = 2
+ E116: a = 1\n # b = 2
"""
- if indent_char == ' ' and indent_level % 4:
- yield 0, "E111 indentation is not a multiple of four"
+ c = 0 if logical_line else 3
+ tmpl = "E11%d %s" if logical_line else "E11%d %s (comment)"
+ if indent_level % 4:
+ yield 0, tmpl % (1 + c, "indentation is not a multiple of four")
indent_expect = previous_logical.endswith(':')
if indent_expect and indent_level <= previous_indent_level:
- yield 0, "E112 expected an indented block"
- if indent_level > previous_indent_level and not indent_expect:
- yield 0, "E113 unexpected indentation"
+ yield 0, tmpl % (2 + c, "expected an indented block")
+ elif not indent_expect and indent_level > previous_indent_level:
+ yield 0, tmpl % (3 + c, "unexpected indentation")
def continued_indentation(logical_line, tokens, indent_level, hang_closing,
@@ -837,6 +842,9 @@ def compound_statements(logical_line):
on the same line, never do this for multi-clause statements.
Also avoid folding such long lines!
+ Always use a def statement instead of an assignment statement that
+ binds a lambda expression directly to a name.
+
Okay: if foo == 'blah':\n do_blah_thing()
Okay: do_one()
Okay: do_two()
@@ -850,20 +858,26 @@ def compound_statements(logical_line):
E701: try: something()
E701: finally: cleanup()
E701: if foo == 'blah': one(); two(); three()
-
E702: do_one(); do_two(); do_three()
E703: do_four(); # useless semicolon
+ E704: def f(x): return 2*x
+ E731: f = lambda x: 2*x
"""
line = logical_line
last_char = len(line) - 1
found = line.find(':')
while -1 < found < last_char:
before = line[:found]
- if (before.count('{') <= before.count('}') and # {'a': 1} (dict)
- before.count('[') <= before.count(']') and # [1:2] (slice)
- before.count('(') <= before.count(')') and # (Python 3 annotation)
- not LAMBDA_REGEX.search(before)): # lambda x: x
- yield found, "E701 multiple statements on one line (colon)"
+ if ((before.count('{') <= before.count('}') and # {'a': 1} (dict)
+ before.count('[') <= before.count(']') and # [1:2] (slice)
+ before.count('(') <= before.count(')'))): # (annotation)
+ if LAMBDA_REGEX.search(before):
+ yield 0, "E731 do not assign a lambda expression, use a def"
+ break
+ if before.startswith('def '):
+ yield 0, "E704 multiple statements on one line (def)"
+ else:
+ yield found, "E701 multiple statements on one line (colon)"
found = line.find(':', found + 1)
found = line.find(';')
while -1 < found:
@@ -1040,7 +1054,7 @@ if '' == ''.encode():
# Python 2: implicit encoding.
def readlines(filename):
"""Read the source code."""
- with open(filename) as f:
+ with open(filename, 'rU') as f:
return f.readlines()
isidentifier = re.compile(r'[a-zA-Z_]\w*').match
stdin_get_value = sys.stdin.read
@@ -1370,6 +1384,8 @@ class Checker(object):
tokengen = tokenize.generate_tokens(self.readline)
try:
for token in tokengen:
+ if token[2][0] > self.total_lines:
+ return
self.maybe_check_physical(token)
yield token
except (SyntaxError, tokenize.TokenError):
@@ -1452,10 +1468,8 @@ class Checker(object):
token[3] = (token[2][0], token[2][1] + len(token[1]))
self.tokens = [tuple(token)]
self.check_logical()
- if len(self.tokens) > 1 and (token_type == tokenize.ENDMARKER and
- self.tokens[-2][0] not in SKIP_TOKENS):
- self.tokens.pop()
- self.check_physical(self.tokens[-1][4])
+ if self.tokens:
+ self.check_physical(self.lines[-1])
self.check_logical()
return self.report.get_file_results()
@@ -1840,12 +1854,11 @@ def read_config(options, args, arglist, parser):
# Second, parse the configuration
for opt in config.options(pep8_section):
+ if opt.replace('_', '-') not in parser.config_options:
+ print(" unknown option '%s' ignored" % opt)
+ continue
if options.verbose > 1:
print(" %s = %s" % (opt, config.get(pep8_section, opt)))
- if opt.replace('_', '-') not in parser.config_options:
- print("Unknown option: '%s'\n not in [%s]" %
- (opt, ' '.join(parser.config_options)))
- sys.exit(1)
normalized_opt = opt.replace('-', '_')
opt_type = option_list[normalized_opt]
if opt_type in ('int', 'count'):
@@ -1921,7 +1934,7 @@ def _main():
# Handle "Broken pipe" gracefully
try:
signal.signal(signal.SIGPIPE, lambda signum, frame: sys.exit(1))
- except ValueError:
+ except AttributeError:
pass # not supported on Windows
pep8style = StyleGuide(parse_argv=True, config_file=True)
diff --git a/testsuite/E11.py b/testsuite/E11.py
index 98b9431..4ed1096 100644
--- a/testsuite/E11.py
+++ b/testsuite/E11.py
@@ -10,7 +10,27 @@ print
#: E113
print
print
-#: E111 E113
+#: E114 E116
mimetype = 'application/x-directory'
# 'httpd/unix-directory'
create_date = False
+#: E116 E116 E116
+def start(self):
+ if True:
+ self.master.start()
+ # try:
+ # self.master.start()
+ # except MasterExit:
+ # self.shutdown()
+ # finally:
+ # sys.exit()
+#: E115 E115 E115 E115 E115 E115
+def start(self):
+ if True:
+# try:
+# self.master.start()
+# except MasterExit:
+# self.shutdown()
+# finally:
+# sys.exit()
+ self.master.start()
diff --git a/testsuite/E22.py b/testsuite/E22.py
index 43a6f3f..56af307 100644
--- a/testsuite/E22.py
+++ b/testsuite/E22.py
@@ -135,8 +135,8 @@ baz(**kwargs)
negative = -1
spam(-1)
-negative
-lambda *args, **kw: (args, kw)
-lambda a, b=h[:], c=0: (a, b, c)
+func1(lambda *args, **kw: (args, kw))
+func2(lambda a, b=h[:], c=0: (a, b, c))
if not -5 < x < +5:
print >>sys.stderr, "x is out of range."
print >> sys.stdout, "x is an integer."
diff --git a/testsuite/E70.py b/testsuite/E70.py
index 64feefd..85ca666 100644
--- a/testsuite/E70.py
+++ b/testsuite/E70.py
@@ -1,13 +1,20 @@
-#: E701
+#: E701:1:5
if a: a = False
-#: E701
+#: E701:1:40
if not header or header[:6] != 'bytes=': return
-#: E702
+#: E702:1:10
a = False; b = True
-#: E702
+#: E702:1:17
import bdist_egg; bdist_egg.write_safety_flag(cmd.egg_info, safe)
-#: E703
+#: E703:1:13
import shlex;
-#: E702 E703
+#: E702:1:9 E703:1:23
del a[:]; a.append(42);
+#: E704:1:1
+def f(x): return 2
+#: E704:1:1 E226:1:19
+def f(x): return 2*x
+#: E704:2:5 E226:2:23
+while all is round:
+ def f(x): return 2*x
#:
diff --git a/testsuite/E73.py b/testsuite/E73.py
new file mode 100644
index 0000000..0673e0f
--- /dev/null
+++ b/testsuite/E73.py
@@ -0,0 +1,7 @@
+#: E731:1:1
+f = lambda x: 2 * x
+#: E731:1:1 E226:1:16
+f = lambda x: 2*x
+#: E731:2:5
+while False:
+ this = lambda y, z: 2 * x
diff --git a/testsuite/W29.py b/testsuite/W29.py
index 688667f..4050c2f 100644
--- a/testsuite/W29.py
+++ b/testsuite/W29.py
@@ -15,3 +15,7 @@ string with trailing whitespace'''
1+ 1
#: W292:1:27 E261:1:12 noeol
import this # no line feed
+#: W292:3:22 noeol
+class Test(object):
+ def __repr__(self):
+ return 'test'
diff --git a/testsuite/W39.py b/testsuite/W39.py
index 554814c..68f886b 100644
--- a/testsuite/W39.py
+++ b/testsuite/W39.py
@@ -1,6 +1,15 @@
-#: W391
+#: W391:2:1
# The next line is blank
+#: W391:3:1
+# Two additional empty lines
+
+
+#: W391:4:1 W293:3:1 W293:4:1 noeol
+# The last lines contain space
+
+
+
#: Okay
'''there is nothing wrong
with a multiline string at EOF
diff --git a/testsuite/test_api.py b/testsuite/test_api.py
index fba27c7..980fe9e 100644
--- a/testsuite/test_api.py
+++ b/testsuite/test_api.py
@@ -124,7 +124,7 @@ class APITestCase(unittest.TestCase):
report = pep8.StyleGuide().check_files([E11])
stdout = sys.stdout.getvalue().splitlines()
self.assertEqual(len(stdout), report.total_errors)
- self.assertEqual(report.total_errors, 6)
+ self.assertEqual(report.total_errors, 17)
self.assertFalse(sys.stderr)
self.reset()
@@ -132,7 +132,7 @@ class APITestCase(unittest.TestCase):
report = pep8.StyleGuide(paths=[E11]).check_files()
stdout = sys.stdout.getvalue().splitlines()
self.assertEqual(len(stdout), report.total_errors)
- self.assertEqual(report.total_errors, 6)
+ self.assertEqual(report.total_errors, 17)
self.assertFalse(sys.stderr)
self.reset()
diff --git a/testsuite/test_shell.py b/testsuite/test_shell.py
index e1205cc..e536852 100644
--- a/testsuite/test_shell.py
+++ b/testsuite/test_shell.py
@@ -75,7 +75,7 @@ class ShellTestCase(unittest.TestCase):
stdout = stdout.splitlines()
self.assertEqual(errcode, 1)
self.assertFalse(stderr)
- self.assertEqual(len(stdout), 6)
+ self.assertEqual(len(stdout), 17)
for line, num, col in zip(stdout, (3, 6, 9, 12), (3, 6, 1, 5)):
path, x, y, msg = line.split(':')
self.assertTrue(path.endswith(E11))