hhatto / autopep8

A tool that automatically formats Python code to conform to the PEP 8 style guide.
https://pypi.org/project/autopep8/
MIT License
4.56k stars 290 forks source link

Continuation line over-indented with indent-size = 2 (E126) #588

Open stinos opened 3 years ago

stinos commented 3 years ago

Python Code


def MyBarFunction(**kwargs):
  print(kwargs)

def Foo():
  MyBarFunction(this="a very very very long line", because="the arguments", are="long strings", so="must be broken up")

Command Line and Configuration

.flake8 file

[flake8]
ignore =
indent-size = 2
# For autopep8
aggressive = 1

Command Line

$ autopep8 -i /path/to/file
$ cat /path/to/file
def MyBarFunction(**kwargs):
  print(kwargs)

def Foo():
  MyBarFunction(
      this="a very very very long line",
      because="the arguments",
      are="long strings",
      so="must be broken up")
$ flake8 /path/to/file 
/path/to/file:7:7: E126 continuation line over-indented for hanging indent

i.e. the arguments for MyBarFunction are indented with 4 spaces, not 2.

While E126 is by default ignored by pycodestyle because PEP8 does not ecplicitly forbid this, I think for consistency autopep8 should continue indenting with the given indent size, not more.

Your Environment

stinos commented 3 years ago

patch (requires recent pycodestyle 2.7.0 because that has indent_size) :

@@ -236,7 +236,7 @@ pycodestyle.register_check(extended_blank_lines)

 def continued_indentation(logical_line, tokens, indent_level, hang_closing,
-                          indent_char, noqa):
+                          indent_char, noqa, indent_size):
     """Override pycodestyle's function to provide indentation information."""
     first_row = tokens[0][2][0]
     nrows = 1 + tokens[-1][2][0] - first_row
@@ -251,9 +251,8 @@ def continued_indentation(logical_line, tokens, indent_level, hang_closing,

     row = depth = 0
     valid_hangs = (
-        (DEFAULT_INDENT_SIZE,)
-        if indent_char != '\t' else (DEFAULT_INDENT_SIZE,
-                                     2 * DEFAULT_INDENT_SIZE)
+        (indent_size,)
+        if indent_char != '\t' else (indent_size, 2 * indent_size)
     )

     # Remember how many brackets were opened on each line.
@@ -321,7 +320,7 @@ def continued_indentation(logical_line, tokens, indent_level, hang_closing,
                     yield (start, 'E128 {}'.format(indent[depth]))
             elif (hanging_indent or
                   (indent_next and
-                   rel_indent[row] == 2 * DEFAULT_INDENT_SIZE)):
+                   rel_indent[row] == 2 * indent_size)):
                 # Hanging indent is verified.
                 if close_bracket and not hang_closing:
                     yield (start, 'E123 {}'.format(indent_level +
@@ -335,7 +334,7 @@ def continued_indentation(logical_line, tokens, indent_level, hang_closing,
                 pass
             else:
                 one_indented = (indent_level + rel_indent[open_row] +
-                                DEFAULT_INDENT_SIZE)
+                                indent_size)
                 # Indent is broken.
                 if hang <= 0:
                     error = ('E122', one_indented)
@@ -343,7 +342,7 @@ def continued_indentation(logical_line, tokens, indent_level, hang_closing,
                     error = ('E127', indent[depth])
                 elif not close_bracket and hangs[depth]:
                     error = ('E131', one_indented)
-                elif hang > DEFAULT_INDENT_SIZE:
+                elif hang > indent_size:
                     error = ('E126', one_indented)
                 else:
                     hangs[depth] = hang
@@ -416,10 +415,10 @@ def continued_indentation(logical_line, tokens, indent_level, hang_closing,
     if (
         indent_next and
         not last_line_begins_with_multiline and
-        pycodestyle.expand_indent(line) == indent_level + DEFAULT_INDENT_SIZE
+        pycodestyle.expand_indent(line) == indent_level + indent_size
     ):
         pos = (start[0], indent[0] + 4)
-        desired_indent = indent_level + 2 * DEFAULT_INDENT_SIZE
+        desired_indent = indent_level + 2 * indent_size
         if visual_indent:
             yield (pos, 'E129 {}'.format(desired_indent))
         else:
@@ -606,6 +605,7 @@ class FixPEP8(object):
             'select': self.options.select,
             'max_line_length': self.options.max_line_length,
             'hang_closing': self.options.hang_closing,
+            'indent_size': len(self.indent_word)
         }
         results = _execute_pep8(pep8_options, self.source)

@@ -3531,6 +3531,7 @@ def fix_lines(source_lines, options, filename=''):
             'select': options.select,
             'max_line_length': options.max_line_length,
             'hang_closing': options.hang_closing,
+            'indent_size': options.indent_size,
         }
         sio = io.StringIO(tmp_source)
         contents = sio.readlines()

Seems to work fine, though not heavily tested.

_reflow_lines also still referes to DEFAULT_INDENT_SIZE so could probably use the same treatment?

If you want I can make this into a PR

hhatto commented 3 years ago

@stinos Thanks for your work. Can you please create a pull request? Or you can just fork and push it to a branch. I'll test it here.

stinos commented 3 years ago

See https://github.com/stinos/autopep8/tree/no-default-indent-size

No PR because I figured this should probably tested somewhere and don't have time atm to figure out where

farfromunique commented 2 years ago

@hhatto It's been over a year, and this is still wanted. Is there any update on this?