Update docs for configuration
[third_party/pep8] / pep8.py
diff --git a/pep8.py b/pep8.py
index bb46c220cffccf3d2f436ec9cbd1bec98806b390..67b32d16d9320d436d813eedf9374664117df3bc 100755 (executable)
--- a/pep8.py
+++ b/pep8.py
@@ -47,8 +47,6 @@ W warnings
 """
 from __future__ import with_statement
 
-__version__ = '1.6.0a0'
-
 import os
 import sys
 import re
@@ -64,8 +62,10 @@ try:
 except ImportError:
     from ConfigParser import RawConfigParser
 
+__version__ = '1.6.0a0'
+
 DEFAULT_EXCLUDE = '.svn,CVS,.bzr,.hg,.git,__pycache__,.tox'
-DEFAULT_IGNORE = 'E123,E226,E24,E704'
+DEFAULT_IGNORE = 'E121,E123,E126,E226,E24,E704'
 try:
     if sys.platform == 'win32':
         DEFAULT_CONFIG = os.path.expanduser(r'~\.pep8')
@@ -754,6 +754,7 @@ def whitespace_around_named_parameter_equals(logical_line, tokens):
     Okay: boolean(a != b)
     Okay: boolean(a <= b)
     Okay: boolean(a >= b)
+    Okay: def foo(arg: int = 42):
 
     E251: def complex(real, imag = 0.0):
     E251: return magic(r = real, i = imag)
@@ -761,6 +762,8 @@ def whitespace_around_named_parameter_equals(logical_line, tokens):
     parens = 0
     no_space = False
     prev_end = None
+    annotated_func_arg = False
+    in_def = logical_line.startswith('def')
     message = "E251 unexpected spaces around keyword / parameter equals"
     for token_type, text, start, end, line in tokens:
         if token_type == tokenize.NL:
@@ -774,10 +777,17 @@ def whitespace_around_named_parameter_equals(logical_line, tokens):
                 parens += 1
             elif text == ')':
                 parens -= 1
-            elif parens and text == '=':
+            elif in_def and text == ':' and parens == 1:
+                annotated_func_arg = True
+            elif parens and text == ',' and parens == 1:
+                annotated_func_arg = False
+            elif parens and text == '=' and not annotated_func_arg:
                 no_space = True
                 if start != prev_end:
                     yield (prev_end, message)
+            if not parens:
+                annotated_func_arg = False
+
         prev_end = end
 
 
@@ -850,7 +860,8 @@ def module_imports_on_top_of_file(
     Okay: # this is a comment\nimport os
     Okay: '''this is a module docstring'''\nimport os
     Okay: r'''this is a module docstring'''\nimport os
-    Okay: __version__ = "123"\nimport os
+    Okay: try:\n    import x\nexcept:\n    pass\nelse:\n    pass\nimport y
+    Okay: try:\n    import x\nexcept:\n    pass\nfinally:\n    pass\nimport y
     E402: a=1\nimport os
     E402: 'One string'\n"Two string"\nimport os
     E402: a=1\nfrom sys import x
@@ -864,6 +875,8 @@ def module_imports_on_top_of_file(
             line = line[1:]
         return line and (line[0] == '"' or line[0] == "'")
 
+    allowed_try_keywords = ('try', 'except', 'else', 'finally')
+
     if indent_level:  # Allow imports in conditional statements or functions
         return
     if not logical_line:  # Allow empty lines or comments
@@ -873,10 +886,10 @@ def module_imports_on_top_of_file(
     line = logical_line
     if line.startswith('import ') or line.startswith('from '):
         if checker_state.get('seen_non_imports', False):
-            yield 0, "E402 import not at top of file"
-    elif line.startswith('__version__ '):
-        # These lines should be included after the module's docstring, before
-        # any other code, separated by a blank line above and below.
+            yield 0, "E402 module level import not at top of file"
+    elif any(line.startswith(kw) for kw in allowed_try_keywords):
+        # Allow try, except, else, finally keywords intermixed with imports in
+        # order to support conditional importing
         return
     elif is_string_literal(line):
         # The first literal is a docstring, allow it. Otherwise, report error.
@@ -1238,14 +1251,12 @@ def filename_match(filename, patterns, default=True):
     return any(fnmatch(filename, pattern) for pattern in patterns)
 
 
+def _is_eol_token(token):
+    return token[0] in NEWLINE or token[4][token[3][1]:].lstrip() == '\\\n'
 if COMMENT_WITH_NL:
-    def _is_eol_token(token):
-        return (token[0] in NEWLINE or
-                (token[0] == tokenize.COMMENT and token[1] == token[4]))
-else:
-    def _is_eol_token(token):
-        return token[0] in NEWLINE
-
+    def _is_eol_token(token, _eol_token=_is_eol_token):
+        return _eol_token(token) or (token[0] == tokenize.COMMENT and
+                                     token[1] == token[4])
 
 ##############################################################################
 # Framework to run all checks
@@ -1865,7 +1876,8 @@ def get_parser(prog='pep8', version=__version__):
     parser.add_option('--select', metavar='errors', default='',
                       help="select errors and warnings (e.g. E,W6)")
     parser.add_option('--ignore', metavar='errors', default='',
-                      help="skip errors and warnings (e.g. E4,W)")
+                      help="skip errors and warnings (e.g. E4,W) "
+                           "(default: %s)" % DEFAULT_IGNORE)
     parser.add_option('--show-source', action='store_true',
                       help="show source code for each error")
     parser.add_option('--show-pep8', action='store_true',