src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/CodeStyleFixer.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9473
3f23dbf37dbe
--- a/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/CodeStyleFixer.py	Wed Jul 13 11:16:20 2022 +0200
+++ b/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/CodeStyleFixer.py	Wed Jul 13 14:55:47 2022 +0200
@@ -19,21 +19,82 @@
     import pycodestyle
 
 FixableCodeStyleIssues = [
-    "D111", "D112", "D121", "D131", "D141", "D142",
-    "D143", "D144", "D145",
-    "D221", "D222", "D231", "D242", "D243", "D244",
-    "D245", "D246", "D247",
-    "E101", "E111", "E121", "E122", "E123", "E124",
-    "E125", "E126", "E127", "E128", "E133", "E201",
-    "E202", "E203", "E211", "E221", "E222", "E223",
-    "E224", "E225", "E226", "E227", "E228", "E231",
-    "E241", "E242", "E251", "E261", "E262", "E271",
-    "E272", "E273", "E274", "E301", "E302", "E303",
-    "E304", "E305", "E306", "E307", "E308", "E401",
-    "E501", "E502", "E701", "E702", "E703", "E711",
+    "D111",
+    "D112",
+    "D121",
+    "D131",
+    "D141",
+    "D142",
+    "D143",
+    "D144",
+    "D145",
+    "D221",
+    "D222",
+    "D231",
+    "D242",
+    "D243",
+    "D244",
+    "D245",
+    "D246",
+    "D247",
+    "E101",
+    "E111",
+    "E121",
+    "E122",
+    "E123",
+    "E124",
+    "E125",
+    "E126",
+    "E127",
+    "E128",
+    "E133",
+    "E201",
+    "E202",
+    "E203",
+    "E211",
+    "E221",
+    "E222",
+    "E223",
+    "E224",
+    "E225",
+    "E226",
+    "E227",
+    "E228",
+    "E231",
+    "E241",
+    "E242",
+    "E251",
+    "E261",
+    "E262",
+    "E271",
+    "E272",
+    "E273",
+    "E274",
+    "E301",
+    "E302",
+    "E303",
+    "E304",
+    "E305",
+    "E306",
+    "E307",
+    "E308",
+    "E401",
+    "E501",
+    "E502",
+    "E701",
+    "E702",
+    "E703",
+    "E711",
     "E712",
-    "N804", "N805", "N806",
-    "W191", "W291", "W292", "W293", "W391", "W603",
+    "N804",
+    "N805",
+    "N806",
+    "W191",
+    "W291",
+    "W292",
+    "W293",
+    "W391",
+    "W603",
 ]
 
 
@@ -41,11 +102,22 @@
     """
     Class implementing a fixer for certain code style issues.
     """
-    def __init__(self, filename, sourceLines, fixCodes, noFixCodes,
-                 maxLineLength, blankLines, inPlace, eol, backup=False):
+
+    def __init__(
+        self,
+        filename,
+        sourceLines,
+        fixCodes,
+        noFixCodes,
+        maxLineLength,
+        blankLines,
+        inPlace,
+        eol,
+        backup=False,
+    ):
         """
         Constructor
-        
+
         @param filename name of the file to be fixed
         @type str
         @param sourceLines list of source lines including eol marker
@@ -71,30 +143,30 @@
         @type bool
         """
         super().__init__()
-        
+
         self.__filename = filename
         self.__origName = ""
         self.__source = sourceLines[:]  # save a copy
         self.__fixCodes = [c.strip() for c in fixCodes.split(",") if c.strip()]
-        self.__noFixCodes = [
-            c.strip() for c in noFixCodes.split(",") if c.strip()]
+        self.__noFixCodes = [c.strip() for c in noFixCodes.split(",") if c.strip()]
         self.__maxLineLength = maxLineLength
         self.__blankLines = {
             "toplevel": blankLines[0],
             "method": blankLines[1],
         }
         self.fixed = 0
-        
+
         self.__reindenter = None
         self.__indentWord = self.__getIndentWord()
-        
+
         if inPlace:
             self.__createBackup = backup
         else:
             self.__origName = self.__filename
             self.__filename = os.path.join(
                 os.path.dirname(self.__filename),
-                "fixed_" + os.path.basename(self.__filename))
+                "fixed_" + os.path.basename(self.__filename),
+            )
             self.__createBackup = False
         self.__eol = eol
 
@@ -183,85 +255,87 @@
         self.__stack = []
         # These need to be fixed before the file is saved but after all
         # inline fixes.
-        
+
         self.__multiLineNumbers = None
         self.__docLineNumbers = None
-        
+
         self.__lastID = 0
-    
+
     def saveFile(self, encoding):
         """
         Public method to save the modified file.
-        
+
         @param encoding encoding of the source file (string)
         @return error message on failure (tuple of str)
         """
         import codecs
-        
+
         if not self.__modified:
             # no need to write
             return None
-        
+
         if self.__createBackup:
             # create a backup file before writing any changes
             if os.path.islink(self.__filename):
-                bfn = '{0}~'.format(os.path.realpath(self.__filename))
+                bfn = "{0}~".format(os.path.realpath(self.__filename))
             else:
-                bfn = '{0}~'.format(self.__filename)
+                bfn = "{0}~".format(self.__filename)
             with contextlib.suppress(OSError):
                 os.remove(bfn)
             with contextlib.suppress(OSError):
                 os.rename(self.__filename, bfn)
-        
+
         txt = "".join(self.__source)
         try:
-            enc = 'utf-8' if encoding == 'utf-8-bom' else encoding
+            enc = "utf-8" if encoding == "utf-8-bom" else encoding
             txt = txt.encode(enc)
-            if encoding == 'utf-8-bom':
+            if encoding == "utf-8-bom":
                 txt = codecs.BOM_UTF8 + txt
-            
+
             with open(self.__filename, "wb") as fp:
                 fp.write(txt)
         except (OSError, UnicodeError) as err:
             # Could not save the file! Skipping it. Reason: {0}
             return ("FIXWRITE_ERROR", [str(err)])
-        
+
         return None
-    
+
     def __codeMatch(self, code):
         """
         Private method to check, if the code should be fixed.
-        
+
         @param code to check (string)
         @return flag indicating it should be fixed (boolean)
         """
+
         def mutualStartswith(a, b):
             """
             Local helper method to compare the beginnings of two strings
             against each other.
-            
+
             @return flag indicating that one string starts with the other
                 (boolean)
             """
             return b.startswith(a) or a.startswith(b)
-        
-        if (
-            self.__noFixCodes and
-            any(mutualStartswith(code.lower(), noFixCode.lower())
-                for noFixCode in [c.strip() for c in self.__noFixCodes])
+
+        if self.__noFixCodes and any(
+            mutualStartswith(code.lower(), noFixCode.lower())
+            for noFixCode in [c.strip() for c in self.__noFixCodes]
         ):
             return False
 
         if self.__fixCodes:
-            return any(mutualStartswith(code.lower(), fixCode.lower())
-                       for fixCode in [c.strip() for c in self.__fixCodes])
+            return any(
+                mutualStartswith(code.lower(), fixCode.lower())
+                for fixCode in [c.strip() for c in self.__fixCodes]
+            )
 
         return True
-    
+
     def fixIssue(self, line, pos, code):
         """
         Public method to fix the fixable issues.
-        
+
         @param line line number of the issue
         @type int
         @param pos position inside line
@@ -274,9 +348,9 @@
         @rtype tuple of (int, str, list, int)
         """
         if (
-            line <= len(self.__source) and
-            self.__codeMatch(code) and
-            code in self.__fixes
+            line <= len(self.__source)
+            and self.__codeMatch(code)
+            and code in self.__fixes
         ):
             res = self.__fixes[code](code, line, pos)
             if res[0] == 1:
@@ -284,17 +358,17 @@
                 self.fixed += 1
         else:
             res = (0, "", [], 0)
-        
+
         return res
-    
+
     def finalize(self):
         """
         Public method to apply all deferred fixes.
-        
+
         @return dictionary containing the fix results
         """
         results = {}
-        
+
         # step 1: do fixes operating on logical lines first
         for id_, code, line, pos in self.__stackLogical:
             res, msg, args, _ = self.__fixes[code](code, line, pos, apply=True)
@@ -302,7 +376,7 @@
                 self.__modified = True
                 self.fixed += 1
             results[id_] = (res, msg, args)
-        
+
         # step 2: do fixes that change the number of lines
         for id_, code, line, pos in reversed(self.__stack):
             res, msg, args, _ = self.__fixes[code](code, line, pos, apply=True)
@@ -310,23 +384,23 @@
                 self.__modified = True
                 self.fixed += 1
             results[id_] = (res, msg, args)
-        
+
         return results
-    
+
     def __getID(self):
         """
         Private method to get the ID for a deferred fix.
-        
+
         @return ID for a deferred fix (integer)
         """
         self.__lastID += 1
         return self.__lastID
-    
+
     def __findLogical(self):
         """
         Private method to extract the index of all the starts and ends of
         lines.
-        
+
         @return tuple containing two lists of integer with start and end tuples
             of lines
         """
@@ -336,9 +410,13 @@
         sio = StringIO("".join(self.__source))
         parens = 0
         for t in tokenize.generate_tokens(sio.readline):
-            if t[0] in [tokenize.COMMENT, tokenize.DEDENT,
-                        tokenize.INDENT, tokenize.NL,
-                        tokenize.ENDMARKER]:
+            if t[0] in [
+                tokenize.COMMENT,
+                tokenize.DEDENT,
+                tokenize.INDENT,
+                tokenize.NL,
+                tokenize.ENDMARKER,
+            ]:
                 continue
             if not parens and t[0] in [tokenize.NEWLINE, tokenize.SEMI]:
                 last_newline = True
@@ -348,17 +426,17 @@
                 logical_start.append((t[2][0] - 1, t[2][1]))
                 last_newline = False
             if t[0] == tokenize.OP:
-                if t[1] in '([{':
+                if t[1] in "([{":
                     parens += 1
-                elif t[1] in '}])':
+                elif t[1] in "}])":
                     parens -= 1
         return logical_start, logical_end
-    
+
     def __getLogical(self, line, pos):
         """
         Private method to get the logical line corresponding to the given
         position.
-        
+
         @param line line number of the issue (integer)
         @param pos position inside line (integer)
         @return tuple of a tuple of two integers giving the start of the
@@ -382,39 +460,39 @@
                 break
         if ls is None:
             return None
-        
-        original = self.__source[ls[0]:le[0] + 1]
+
+        original = self.__source[ls[0] : le[0] + 1]
         return ls, le, original
-    
+
     def __getIndentWord(self):
         """
         Private method to determine the indentation type.
-        
+
         @return string to be used for an indentation (string)
         """
         sio = StringIO("".join(self.__source))
-        indentWord = "    "     # default in case of failure
+        indentWord = "    "  # default in case of failure
         with contextlib.suppress(SyntaxError, tokenize.TokenError):
             for token in tokenize.generate_tokens(sio.readline):
                 if token[0] == tokenize.INDENT:
                     indentWord = token[1]
                     break
         return indentWord
-    
+
     def __getIndent(self, line):
         """
         Private method to get the indentation string.
-        
+
         @param line line to determine the indentation string from (string)
         @return indentation string (string)
         """
         return line.replace(line.lstrip(), "")
-    
+
     def __multilineStringLines(self):
         """
         Private method to determine the line numbers that are within multi line
         strings and these which are part of a documentation string.
-        
+
         @return tuple of a set of line numbers belonging to a multi line
             string and a set of line numbers belonging to a multi line
             documentation string (tuple of two set of integer)
@@ -424,31 +502,29 @@
             sio = StringIO(source)
             self.__multiLineNumbers = set()
             self.__docLineNumbers = set()
-            previousTokenType = ''
+            previousTokenType = ""
             with contextlib.suppress(SyntaxError, tokenize.TokenError):
                 for t in tokenize.generate_tokens(sio.readline):
                     tokenType = t[0]
                     startRow = t[2][0]
                     endRow = t[3][0]
 
-                    if (tokenType == tokenize.STRING and startRow != endRow):
+                    if tokenType == tokenize.STRING and startRow != endRow:
                         if previousTokenType != tokenize.INDENT:
-                            self.__multiLineNumbers |= set(
-                                range(startRow, 1 + endRow))
+                            self.__multiLineNumbers |= set(range(startRow, 1 + endRow))
                         else:
-                            self.__docLineNumbers |= set(
-                                range(startRow, 1 + endRow))
+                            self.__docLineNumbers |= set(range(startRow, 1 + endRow))
 
                     previousTokenType = tokenType
-        
+
         return self.__multiLineNumbers, self.__docLineNumbers
-    
+
     def __fixReindent(self, line, pos, logical):
         """
         Private method to fix a badly indented line.
 
         This is done by adding or removing from its initial indent only.
-        
+
         @param line line number of the issue (integer)
         @param pos position inside line (integer)
         @param logical logical line structure
@@ -457,14 +533,14 @@
         """
         if not logical:
             raise ValueError("Bad value for 'logical' parameter.")
-        
+
         ls, _, original = logical
 
         rewrapper = IndentationWrapper(original)
         valid_indents = rewrapper.pep8Expected()
         if not rewrapper.rel_indent:
             return False
-        
+
         if line > ls[0]:
             # got a valid continuation line number
             row = line - ls[0] - 1
@@ -473,14 +549,14 @@
             got = rewrapper.rel_indent[row]
         else:
             return False
-        
+
         line1 = ls[0] + row
         # always pick the expected indent, for now.
         indent_to = valid[0]
 
         if got != indent_to:
             orig_line = self.__source[line1]
-            new_line = ' ' * (indent_to) + orig_line.lstrip()
+            new_line = " " * (indent_to) + orig_line.lstrip()
             if new_line == orig_line:
                 return False
             else:
@@ -488,11 +564,11 @@
                 return True
         else:
             return False
-    
+
     def __fixWhitespace(self, line, offset, replacement):
         """
         Private method to correct whitespace at the given offset.
-        
+
         @param line line to be corrected (string)
         @param offset offset within line (integer)
         @param replacement replacement string (string)
@@ -504,13 +580,13 @@
             return line
         else:
             return left + replacement + right
-    
+
     def __fixD111(self, code, line, pos):
         """
         Private method to fix docstring enclosed in wrong quotes.
-       
+
         Codes: D111
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -523,8 +599,7 @@
         @rtype tuple of (int, str, list or int, int)
         """
         line -= 1
-        quotes = re.match(r"""\s*[ru]?('''|'|\")""",
-                          self.__source[line]).group(1)
+        quotes = re.match(r"""\s*[ru]?('''|'|\")""", self.__source[line]).group(1)
         left, right = self.__source[line].split(quotes, 1)
         self.__source[line] = left + '"""' + right
         while line < len(self.__source):
@@ -533,16 +608,16 @@
                 self.__source[line] = left + '"""' + right
                 break
             line += 1
-        
+
         # Triple single quotes converted to triple double quotes.
         return (1, "FIXD111", [], 0)
-    
+
     def __fixD112(self, code, line, pos):
         """
         Private method to fix docstring 'r' in leading quotes.
-        
+
         Codes: D112
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -559,22 +634,22 @@
             insertChar = "r"
         else:
             return (0, "", 0)
-        
+
         newText = (
-            self.__getIndent(self.__source[line]) +
-            insertChar +
-            self.__source[line].lstrip()
+            self.__getIndent(self.__source[line])
+            + insertChar
+            + self.__source[line].lstrip()
         )
         self.__source[line] = newText
         # Introductory quotes corrected to be {0}"""
-        return (1, 'FIXD112', [insertChar], 0)
-    
+        return (1, "FIXD112", [insertChar], 0)
+
     def __fixD121(self, code, line, pos, apply=False):
         """
         Private method to fix a single line docstring on multiple lines.
-       
+
         Codes: D121
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -590,21 +665,17 @@
         """
         if apply:
             line -= 1
-            if not self.__source[line].lstrip().startswith(
-                    ('"""', 'r"""', 'u"""')):
+            if not self.__source[line].lstrip().startswith(('"""', 'r"""', 'u"""')):
                 # only correctly formatted docstrings will be fixed
                 return (0, "", [], 0)
-            
-            docstring = (
-                self.__source[line].rstrip() +
-                self.__source[line + 1].strip()
-            )
+
+            docstring = self.__source[line].rstrip() + self.__source[line + 1].strip()
             if docstring.endswith('"""'):
                 docstring += self.__eol
             else:
                 docstring += self.__source[line + 2].lstrip()
                 self.__source[line + 2] = ""
-            
+
             self.__source[line] = docstring
             self.__source[line + 1] = ""
             # Single line docstring put on one line.
@@ -613,14 +684,14 @@
             fixId = self.__getID()
             self.__stack.append((fixId, code, line, pos))
             return (-1, "", [], fixId)
-    
+
     def __fixD131(self, code, line, pos):
         """
         Private method to fix a docstring summary not ending with a
         period.
-       
+
         Codes: D131
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -634,41 +705,41 @@
         """
         line -= 1
         newText = ""
-        if (
-            self.__source[line].rstrip().endswith(('"""', "'''")) and
-            self.__source[line].lstrip().startswith(('"""', 'r"""', 'u"""'))
-        ):
+        if self.__source[line].rstrip().endswith(('"""', "'''")) and self.__source[
+            line
+        ].lstrip().startswith(('"""', 'r"""', 'u"""')):
             # it is a one-liner
             newText = (
-                self.__source[line].rstrip()[:-3].rstrip() +
-                "." +
-                self.__source[line].rstrip()[-3:] +
-                self.__eol
+                self.__source[line].rstrip()[:-3].rstrip()
+                + "."
+                + self.__source[line].rstrip()[-3:]
+                + self.__eol
             )
         else:
-            if (
-                line < len(self.__source) - 1 and
-                (not self.__source[line + 1].strip() or
-                 self.__source[line + 1].lstrip().startswith("@") or
-                 (self.__source[line + 1].strip() in ('"""', "'''") and
-                  not self.__source[line].lstrip().startswith("@")))
+            if line < len(self.__source) - 1 and (
+                not self.__source[line + 1].strip()
+                or self.__source[line + 1].lstrip().startswith("@")
+                or (
+                    self.__source[line + 1].strip() in ('"""', "'''")
+                    and not self.__source[line].lstrip().startswith("@")
+                )
             ):
                 newText = self.__source[line].rstrip() + "." + self.__eol
-        
+
         if newText:
             self.__source[line] = newText
             # Period added to summary line.
             return (1, "FIXD131", [], 0)
         else:
             return (0, "", [], 0)
-    
+
     def __fixD141(self, code, line, pos, apply=False):
         """
         Private method to fix a function/method docstring preceded by a
         blank line.
-       
+
         Codes: D141
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -691,14 +762,14 @@
             fixId = self.__getID()
             self.__stack.append((fixId, code, line, pos))
             return (-1, "", [], fixId)
-    
+
     def __fixD142(self, code, line, pos, apply=False):
         """
         Private method to fix a class docstring not preceded by a
         blank line.
-       
+
         Codes: D142
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -721,14 +792,14 @@
             fixId = self.__getID()
             self.__stack.append((fixId, code, line, pos))
             return (-1, "", [], fixId)
-    
+
     def __fixD143(self, code, line, pos, apply=False):
         """
         Private method to fix a class docstring not followed by a
         blank line.
-       
+
         Codes: D143
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -751,14 +822,14 @@
             fixId = self.__getID()
             self.__stack.append((fixId, code, line, pos))
             return (-1, "", [], fixId)
-    
+
     def __fixD144(self, code, line, pos, apply=False):
         """
         Private method to fix a docstring summary not followed by a
         blank line.
-       
+
         Codes: D144
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -777,7 +848,7 @@
             if not self.__source[line].rstrip().endswith("."):
                 # only correct summary lines can be fixed here
                 return (0, "", 0)
-            
+
             self.__source[line] += self.__eol
             # Blank line inserted after docstring summary.
             return (1, "FIXD144", [], 0)
@@ -785,14 +856,14 @@
             fixId = self.__getID()
             self.__stack.append((fixId, code, line, pos))
             return (-1, "", [], fixId)
-    
+
     def __fixD145(self, code, line, pos, apply=False):
         """
         Private method to fix the last paragraph of a multi-line docstring
         not followed by a blank line.
-       
+
         Codes: D143
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -815,14 +886,14 @@
             fixId = self.__getID()
             self.__stack.append((fixId, code, line, pos))
             return (-1, "", [], fixId)
-    
+
     def __fixD221(self, code, line, pos, apply=False):
         """
         Private method to fix leading and trailing quotes of docstring
         not on separate lines.
-       
+
         Codes: D221, D222
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -849,14 +920,7 @@
             else:
                 # trailing
                 first, second = source[:-3].strip(), source[-3:]
-            newText = (
-                indent +
-                first +
-                self.__eol +
-                indent +
-                second +
-                self.__eol
-            )
+            newText = indent + first + self.__eol + indent + second + self.__eol
             self.__source[line] = newText
             if code == "D221":
                 # Leading quotes put on separate line.
@@ -869,14 +933,14 @@
             fixId = self.__getID()
             self.__stack.append((fixId, code, line, pos))
             return (-1, "", [], fixId)
-    
+
     def __fixD242(self, code, line, pos, apply=False):
         """
         Private method to fix a class or function/method docstring preceded
         by a blank line.
-       
+
         Codes: D242, D244
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -904,14 +968,14 @@
             fixId = self.__getID()
             self.__stack.append((fixId, code, line, pos))
             return (-1, "", [], fixId)
-    
+
     def __fixD243(self, code, line, pos, apply=False):
         """
         Private method to fix a class or function/method docstring followed
         by a blank line.
-       
+
         Codes: D243, D245
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -939,14 +1003,14 @@
             fixId = self.__getID()
             self.__stack.append((fixId, code, line, pos))
             return (-1, "", [], fixId)
-    
+
     def __fixD247(self, code, line, pos, apply=False):
         """
         Private method to fix a last paragraph of a docstring followed
         by a blank line.
-       
+
         Codes: D247
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -969,13 +1033,13 @@
             fixId = self.__getID()
             self.__stack.append((fixId, code, line, pos))
             return (-1, "", [], fixId)
-    
+
     def __fixE101(self, code, line, pos):
         """
         Private method to fix obsolete tab usage and indentation errors.
-        
+
         Codes: E101, E111, W191
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -1002,14 +1066,14 @@
             return (1, msg, [], 0)
         else:
             return (0, "", [], 0)
-    
+
     def __fixE121(self, code, line, pos, apply=False):
         """
         Private method to fix the indentation of continuation lines and
         closing brackets.
-       
+
         Codes: E121, E124
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -1041,13 +1105,13 @@
             fixId = self.__getID()
             self.__stackLogical.append((fixId, code, line, pos))
             return (-1, "", [], fixId)
-    
+
     def __fixE122(self, code, line, pos, apply=False):
         """
         Private method to fix a missing indentation of continuation lines.
-        
+
         Codes: E122
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -1072,8 +1136,7 @@
                     text = self.__source[line]
                     indentation = self.__getIndent(text)
                     self.__source[line] = (
-                        indentation +
-                        self.__indentWord + text.lstrip()
+                        indentation + self.__indentWord + text.lstrip()
                     )
                 # Missing indentation of continuation line corrected.
                 return (1, "FIXE122", [], 0)
@@ -1082,13 +1145,13 @@
             fixId = self.__getID()
             self.__stackLogical.append((fixId, code, line, pos))
             return (-1, "", [], fixId)
-    
+
     def __fixE123(self, code, line, pos, apply=False):
         """
         Private method to fix the indentation of a closing bracket lines.
-        
+
         Codes: E123
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -1124,14 +1187,14 @@
             fixId = self.__getID()
             self.__stackLogical.append((fixId, code, line, pos))
             return (-1, "", [], fixId)
-    
+
     def __fixE125(self, code, line, pos, apply=False):
         """
         Private method to fix the indentation of continuation lines not
         distinguishable from next logical line.
-       
+
         Codes: E125
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -1154,8 +1217,7 @@
                     row = line - 1
                     text = self.__source[row]
                     self.__source[row] = (
-                        self.__getIndent(text) +
-                        self.__indentWord + text.lstrip()
+                        self.__getIndent(text) + self.__indentWord + text.lstrip()
                     )
                 # Indentation level changed.
                 return (1, "FIXE125", [], 0)
@@ -1164,14 +1226,14 @@
             fixId = self.__getID()
             self.__stackLogical.append((fixId, code, line, pos))
             return (-1, "", [], fixId)
-    
+
     def __fixE126(self, code, line, pos, apply=False):
         """
         Private method to fix over-indented/under-indented hanging
         indentation.
-       
+
         Codes: E126, E133
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -1193,8 +1255,9 @@
                 row = line - 1
                 text = self.__source[row]
                 newText = (
-                    self.__getIndent(logicalLines[0]) +
-                    self.__indentWord + text.lstrip()
+                    self.__getIndent(logicalLines[0])
+                    + self.__indentWord
+                    + text.lstrip()
                 )
                 if newText == text:
                     # fall back to slower method
@@ -1210,13 +1273,13 @@
             fixId = self.__getID()
             self.__stackLogical.append((fixId, code, line, pos))
             return (-1, "", [], fixId)
-    
+
     def __fixE127(self, code, line, pos, apply=False):
         """
         Private method to fix over/under indented lines.
-       
+
         Codes: E127, E128
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -1238,16 +1301,16 @@
                 row = line - 1
                 text = self.__source[row]
                 newText = text
-                
-                if logicalLines[0].rstrip().endswith('\\'):
+
+                if logicalLines[0].rstrip().endswith("\\"):
                     newText = (
-                        self.__getIndent(logicalLines[0]) +
-                        self.__indentWord +
-                        text.lstrip()
+                        self.__getIndent(logicalLines[0])
+                        + self.__indentWord
+                        + text.lstrip()
                     )
                 else:
                     startIndex = None
-                    for symbol in '([{':
+                    for symbol in "([{":
                         if symbol in logicalLines[0]:
                             foundIndex = logicalLines[0].find(symbol) + 1
                             if startIndex is None:
@@ -1256,8 +1319,8 @@
                                 startIndex = min(startIndex, foundIndex)
 
                     if startIndex is not None:
-                        newText = startIndex * ' ' + text.lstrip()
-                    
+                        newText = startIndex * " " + text.lstrip()
+
                 if newText == text:
                     # fall back to slower method
                     changed = self.__fixReindent(line, pos, logical)
@@ -1272,13 +1335,13 @@
             fixId = self.__getID()
             self.__stackLogical.append((fixId, code, line, pos))
             return (-1, "", [], fixId)
-    
+
     def __fixE201(self, code, line, pos):
         """
         Private method to fix extraneous whitespace.
-       
+
         Codes: E201, E202, E203, E211
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -1292,25 +1355,25 @@
         """
         line -= 1
         text = self.__source[line]
-        
-        if '"""' in text or "'''" in text or text.rstrip().endswith('\\'):
+
+        if '"""' in text or "'''" in text or text.rstrip().endswith("\\"):
             return (0, "", [], 0)
-        
-        newText = self.__fixWhitespace(text, pos, '')
+
+        newText = self.__fixWhitespace(text, pos, "")
         if newText == text:
             return (0, "", [], 0)
-        
+
         self.__source[line] = newText
         # Extraneous whitespace removed.
         return (1, "FIXE201", [], 0)
-    
+
     def __fixE221(self, code, line, pos):
         """
         Private method to fix extraneous whitespace around operator or
         keyword.
-       
+
         Codes: E221, E222, E223, E224, E241, E242, E271, E272, E273, E274
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -1324,23 +1387,23 @@
         """
         line -= 1
         text = self.__source[line]
-        
-        if '"""' in text or "'''" in text or text.rstrip().endswith('\\'):
+
+        if '"""' in text or "'''" in text or text.rstrip().endswith("\\"):
             return (0, "", [], 0)
-        
-        newText = self.__fixWhitespace(text, pos, ' ')
+
+        newText = self.__fixWhitespace(text, pos, " ")
         if newText == text:
             return (0, "", [], 0)
-        
+
         self.__source[line] = newText
         return (1, "FIXE221", [], 0)
-    
+
     def __fixE225(self, code, line, pos):
         """
         Private method to fix extraneous whitespaces around operator.
-       
+
         Codes: E225, E226, E227, E228
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -1354,13 +1417,13 @@
         """
         line -= 1
         text = self.__source[line]
-        
-        if '"""' in text or "'''" in text or text.rstrip().endswith('\\'):
+
+        if '"""' in text or "'''" in text or text.rstrip().endswith("\\"):
             return (0, "", [], 0)
-        
+
         newText = text
         # determine length of operator
-        tokens = '<>*/=^&|%!+-'
+        tokens = "<>*/=^&|%!+-"
         pos2 = pos
         token_delimiter = len(tokens)
         for _ in range(3):
@@ -1370,22 +1433,22 @@
                 token_delimiter = 5
             else:
                 break
-        if pos2 < len(text) and text[pos2] not in ' \t':
-            newText = self.__fixWhitespace(newText, pos2, ' ')
-        newText = self.__fixWhitespace(newText, pos, ' ')
+        if pos2 < len(text) and text[pos2] not in " \t":
+            newText = self.__fixWhitespace(newText, pos2, " ")
+        newText = self.__fixWhitespace(newText, pos, " ")
         if newText == text:
             return (0, "", [], 0)
-        
+
         self.__source[line] = newText
         # Missing whitespaces added.
         return (1, "FIXE225", [], 0)
-    
+
     def __fixE231(self, code, line, pos):
         """
         Private method to fix missing whitespace after ',;:'.
-        
+
         Codes: E231
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -1400,20 +1463,18 @@
         line -= 1
         pos += 1
         self.__source[line] = (
-            self.__source[line][:pos] +
-            " " +
-            self.__source[line][pos:]
+            self.__source[line][:pos] + " " + self.__source[line][pos:]
         )
         # Missing whitespace added.
         return (1, "FIXE231", [], 0)
-    
+
     def __fixE251(self, code, line, pos):
         """
         Private method to fix extraneous whitespace around keyword and
         default parameter equals.
-       
+
         Codes: E251
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -1427,32 +1488,30 @@
         """
         line -= 1
         text = self.__source[line]
-        
+
         # This is necessary since pycodestyle sometimes reports columns that
         # goes past the end of the physical line. This happens in cases like,
         # foo(bar\n=None)
         col = min(pos, len(text) - 1)
         newText = (
-            text
-            if text[col].strip() else
-            text[:col].rstrip() + text[col:].lstrip()
+            text if text[col].strip() else text[:col].rstrip() + text[col:].lstrip()
         )
-        
+
         # There could be an escaped newline
-        if newText.endswith(('=\\\n', '=\\\r\n', '=\\\r')):
+        if newText.endswith(("=\\\n", "=\\\r\n", "=\\\r")):
             self.__source[line] = newText.rstrip("\n\r \t\\")
             self.__source[line + 1] = self.__source[line + 1].lstrip()
         else:
             self.__source[line] = newText
         # Extraneous whitespace removed.
         return (1, "FIXE251", [], 0)
-    
+
     def __fixE261(self, code, line, pos):
         """
         Private method to fix whitespace before or after inline comment.
-        
+
         Codes: E261, E262
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -1466,20 +1525,20 @@
         """
         line -= 1
         text = self.__source[line]
-        left = text[:pos].rstrip(' \t#')
-        right = text[pos:].lstrip(' \t#')
+        left = text[:pos].rstrip(" \t#")
+        right = text[pos:].lstrip(" \t#")
         newText = left + ("  # " + right if right.strip() else right)
         self.__source[line] = newText
         # Whitespace around comment sign corrected.
         return (1, "FIXE261", [], 0)
-    
+
     def __fixBlankLinesBefore(self, code, line, pos, apply=False):
         """
         Private method to fix the need for blank lines before class, function
         and method definitions.
-       
+
         Codes: E301, E302, E303, E305, E306, E307, E308
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -1500,7 +1559,7 @@
                 blankLinesBefore = 1
             else:
                 blankLinesBefore = self.__blankLines["toplevel"]
-            
+
             # count blank lines
             index = line - 1
             blanks = 0
@@ -1511,7 +1570,7 @@
                 else:
                     break
             delta = blanks - blankLinesBefore
-            
+
             line -= 1
             if delta < 0:
                 # insert blank lines (one or two)
@@ -1534,14 +1593,14 @@
             fixId = self.__getID()
             self.__stack.append((fixId, code, line, pos))
             return (-1, "", [], fixId)
-    
+
     def __fixE304(self, code, line, pos, apply=False):
         """
         Private method to fix superfluous blank lines after a function
         decorator.
-       
+
         Codes: E304
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -1569,13 +1628,13 @@
             fixId = self.__getID()
             self.__stack.append((fixId, code, line, pos))
             return (-1, "", [], fixId)
-    
+
     def __fixE401(self, code, line, pos, apply=False):
         """
         Private method to fix multiple imports on one line.
-       
+
         Codes: E401
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -1594,19 +1653,19 @@
             text = self.__source[line]
             if not text.lstrip().startswith("import"):
                 return (0, "", [], 0)
-            
+
             # pycodestyle (1.3.1) reports false positive if there is an import
             # statement followed by a semicolon and some unrelated
             # statement with commas in it.
-            if ';' in text:
+            if ";" in text:
                 return (0, "", [], 0)
-            
+
             newText = (
-                text[:pos].rstrip("\t ,") +
-                self.__eol +
-                self.__getIndent(text) +
-                "import " +
-                text[pos:].lstrip("\t ,")
+                text[:pos].rstrip("\t ,")
+                + self.__eol
+                + self.__getIndent(text)
+                + "import "
+                + text[pos:].lstrip("\t ,")
             )
             self.__source[line] = newText
             # Imports were put on separate lines.
@@ -1615,13 +1674,13 @@
             fixId = self.__getID()
             self.__stack.append((fixId, code, line, pos))
             return (-1, "", [], fixId)
-    
+
     def __fixE501(self, code, line, pos, apply=False):
         """
         Private method to fix the long lines by breaking them.
-       
+
         Codes: E501
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -1636,9 +1695,7 @@
         @rtype tuple of (int, str, list or int, int)
         """
         if apply:
-            multilineStringLines, docStringLines = (
-                self.__multilineStringLines()
-            )
+            multilineStringLines, docStringLines = self.__multilineStringLines()
             isDocString = line in docStringLines
             line -= 1
             text = self.__source[line]
@@ -1651,9 +1708,14 @@
             else:
                 nextText = ""
             shortener = LineShortener(
-                text, prevText, nextText,
-                maxLength=self.__maxLineLength, eol=self.__eol,
-                indentWord=self.__indentWord, isDocString=isDocString)
+                text,
+                prevText,
+                nextText,
+                maxLength=self.__maxLineLength,
+                eol=self.__eol,
+                indentWord=self.__indentWord,
+                isDocString=isDocString,
+            )
             changed, newText, newNextText = shortener.shorten()
             if changed:
                 if newText != text:
@@ -1670,13 +1732,13 @@
             fixId = self.__getID()
             self.__stack.append((fixId, code, line, pos))
             return (-1, "", [], fixId)
-    
+
     def __fixE502(self, code, line, pos):
         """
         Private method to fix redundant backslash within brackets.
-       
+
         Codes: E502
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -1689,18 +1751,17 @@
         @rtype tuple of (int, str, list or int, int)
         """
         self.__source[line - 1] = (
-            self.__source[line - 1].rstrip("\n\r \t\\") +
-            self.__eol
+            self.__source[line - 1].rstrip("\n\r \t\\") + self.__eol
         )
         # Redundant backslash in brackets removed.
         return (1, "FIXE502", [], 0)
-    
+
     def __fixE701(self, code, line, pos, apply=False):
         """
         Private method to fix colon-separated compound statements.
-       
+
         Codes: E701
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -1718,14 +1779,14 @@
             line -= 1
             text = self.__source[line]
             pos += 1
-            
+
             newText = (
-                text[:pos] +
-                self.__eol +
-                self.__getIndent(text) +
-                self.__indentWord +
-                text[pos:].lstrip("\n\r \t\\") +
-                self.__eol
+                text[:pos]
+                + self.__eol
+                + self.__getIndent(text)
+                + self.__indentWord
+                + text[pos:].lstrip("\n\r \t\\")
+                + self.__eol
             )
             self.__source[line] = newText
             # Compound statement corrected.
@@ -1734,13 +1795,13 @@
             fixId = self.__getID()
             self.__stack.append((fixId, code, line, pos))
             return (-1, "", [], fixId)
-    
+
     def __fixE702(self, code, line, pos, apply=False):
         """
         Private method to fix semicolon-separated compound statements.
-        
+
         Codes: E702, E703
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -1757,7 +1818,7 @@
         if apply:
             line -= 1
             text = self.__source[line]
-            
+
             if text.rstrip().endswith("\\"):
                 # normalize '1; \\\n2' into '1; 2'
                 self.__source[line] = text.rstrip("\n\r \t\\")
@@ -1774,13 +1835,13 @@
             fixId = self.__getID()
             self.__stack.append((fixId, code, line, pos))
             return (-1, "", [], fixId)
-    
+
     def __fixE711(self, code, line, pos):
         """
         Private method to fix comparison with None.
-       
+
         Codes: E711, E712
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -1794,36 +1855,36 @@
         """
         line -= 1
         text = self.__source[line]
-        
+
         rightPos = pos + 2
         if rightPos >= len(text):
             return (0, "", 0)
-        
+
         left = text[:pos].rstrip()
         center = text[pos:rightPos]
         right = text[rightPos:].lstrip()
-        
+
         if not right.startswith(("None", "True", "False")):
             return (0, "", [], 0)
-        
+
         if center.strip() == "==":
             center = "is"
         elif center.strip() == "!=":
             center = "is not"
         else:
             return (0, "", [], 0)
-        
+
         self.__source[line] = " ".join([left, center, right])
         # Comparison to None/True/False corrected.
         return (1, "FIXE711", [], 0)
-    
+
     def __fixN804(self, code, line, pos, apply=False):
         """
         Private method to fix a wrong first argument of normal and
         class methods.
-       
+
         Codes: N804, N805
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -1844,15 +1905,15 @@
                 arg = "cls"
             else:
                 arg = "self"
-            
+
             if text.rstrip().endswith("("):
                 newText = (
-                    text +
-                    self.__getIndent(text) +
-                    self.__indentWord +
-                    arg +
-                    "," +
-                    self.__eol
+                    text
+                    + self.__getIndent(text)
+                    + self.__indentWord
+                    + arg
+                    + ","
+                    + self.__eol
                 )
             else:
                 index = text.find("(") + 1
@@ -1870,13 +1931,13 @@
             fixId = self.__getID()
             self.__stack.append((fixId, code, line, pos))
             return (-1, "", [], fixId)
-    
+
     def __fixN806(self, code, line, pos, apply=False):
         """
         Private method to fix a wrong first argument of static methods.
-        
+
         Codes: N806
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -1896,7 +1957,7 @@
             index = text.find("(") + 1
             left = text[:index]
             right = text[index:]
-            
+
             if right.startswith(("cls", "self")):
                 # cls or self are on the definition line
                 if right.startswith("cls"):
@@ -1923,26 +1984,24 @@
                 right = right.lstrip(", ")
                 if right.startswith("):"):
                     # merge with previous line
-                    self.__source[line - 1] = (
-                        self.__source[line - 1].rstrip() + right
-                    )
+                    self.__source[line - 1] = self.__source[line - 1].rstrip() + right
                     self.__source[line] = ""
                 else:
                     self.__source[line] = indent + right
-            
+
             # '{0}' argument removed.
             return (1, "FIXN806", [arg], 0)
         else:
             fixId = self.__getID()
             self.__stack.append((fixId, code, line, pos))
             return (-1, "", [], fixId)
-    
+
     def __fixW291(self, code, line, pos):
         """
         Private method to fix trailing whitespace.
-       
+
         Codes: W291, W293
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -1954,17 +2013,18 @@
             message and an ID for a deferred fix
         @rtype tuple of (int, str, list or int, int)
         """
-        self.__source[line - 1] = re.sub(r'[\t ]+(\r?)$', r"\1",
-                                         self.__source[line - 1])
+        self.__source[line - 1] = re.sub(
+            r"[\t ]+(\r?)$", r"\1", self.__source[line - 1]
+        )
         # Whitespace stripped from end of line.
         return (1, "FIXW291", [], 0)
-    
+
     def __fixW292(self, code, line, pos):
         """
         Private method to fix a missing newline at the end of file.
-       
+
         Codes: W292
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -1979,13 +2039,13 @@
         self.__source[line - 1] += self.__eol
         # newline added to end of file.
         return (1, "FIXW292", [], 0)
-    
+
     def __fixW391(self, code, line, pos):
         """
         Private method to fix trailing blank lines.
-       
+
         Codes: W391
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -2006,13 +2066,13 @@
                 break
         # Superfluous trailing blank lines removed from end of file.
         return (1, "FIXW391", [], 0)
-    
+
     def __fixW603(self, code, line, pos):
         """
         Private method to fix the not equal notation.
-       
+
         Codes: W603
-        
+
         @param code code of the issue
         @type str
         @param line line number of the issue
@@ -2036,10 +2096,11 @@
 
     Released to the public domain, by Tim Peters, 03 October 2000.
     """
+
     def __init__(self, sourceLines):
         """
         Constructor
-        
+
         @param sourceLines list of source lines including eol marker
             (list of string)
         """
@@ -2050,8 +2111,7 @@
         # File lines, rstripped & tab-expanded.  Dummy at start is so
         # that we can use tokenize's 1-based line numbering easily.
         # Note that a line is all-blank iff it's "\n".
-        self.lines = [line.rstrip().expandtabs() + "\n"
-                      for line in self.raw]
+        self.lines = [line.rstrip().expandtabs() + "\n" for line in self.raw]
         self.lines.insert(0, None)
         self.index = 1  # index into self.lines of next line
 
@@ -2060,18 +2120,18 @@
         # signal that tokenize doesn't know what to do about them;
         # indeed, they're our headache!
         self.stats = []
-    
+
     def run(self):
         """
         Public method to run the re-indenter.
-        
+
         @return flag indicating that a change was done (boolean)
         """
         try:
             stats = self.__genStats(tokenize.generate_tokens(self.getline))
         except (SyntaxError, tokenize.TokenError):
             return False
-        
+
         # Remove trailing empty lines.
         lines = self.lines
         while lines and lines[-1] == "\n":
@@ -2113,9 +2173,9 @@
                             jline, jlevel = stats[j]
                             if jlevel >= 0:
                                 want = (
-                                    have +
-                                    self.__getlspace(after[jline - 1]) -
-                                    self.__getlspace(lines[jline])
+                                    have
+                                    + self.__getlspace(after[jline - 1])
+                                    - self.__getlspace(lines[jline])
                                 )
                                 break
                     if want < 0:
@@ -2138,23 +2198,23 @@
                         remove = min(self.__getlspace(line), -diff)
                         after.append(line[remove:])
         return self.raw != self.after
-    
+
     def fixedLine(self, line):
         """
         Public method to get a fixed line.
-        
+
         @param line number of the line to retrieve (integer)
         @return fixed line (string)
         """
         if line < len(self.after):
             return self.after[line]
-        
+
         return ""
-    
+
     def getline(self):
         """
         Public method to get a line of text for tokenize.
-        
+
         @return line of text (string)
         """
         if self.index >= len(self.lines):
@@ -2167,7 +2227,7 @@
     def __genStats(self, tokens):
         """
         Private method to generate the re-indent statistics.
-        
+
         @param tokens tokens generator (tokenize._tokenize)
         @return reference to the generated statistics
         """
@@ -2208,15 +2268,15 @@
                 # must be the first token of the next program statement, or an
                 # ENDMARKER.
                 find_stmt = False
-                if line:   # not endmarker
+                if line:  # not endmarker
                     stats.append((sline, level))
-        
+
         return stats
-    
+
     def __getlspace(self, line):
         """
         Private method to count number of leading blanks.
-        
+
         @param line line to check (string)
         @return number of leading blanks (integer)
         """
@@ -2233,22 +2293,29 @@
 
     Each instance operates on a single logical line.
     """
-    SKIP_TOKENS = frozenset([
-        tokenize.COMMENT, tokenize.NL, tokenize.INDENT,
-        tokenize.DEDENT, tokenize.NEWLINE, tokenize.ENDMARKER
-    ])
+
+    SKIP_TOKENS = frozenset(
+        [
+            tokenize.COMMENT,
+            tokenize.NL,
+            tokenize.INDENT,
+            tokenize.DEDENT,
+            tokenize.NEWLINE,
+            tokenize.ENDMARKER,
+        ]
+    )
 
     def __init__(self, physical_lines):
         """
         Constructor
-        
+
         @param physical_lines list of physical lines to operate on
             (list of strings)
         """
         self.lines = physical_lines
         self.tokens = []
         self.rel_indent = None
-        sio = StringIO(''.join(physical_lines))
+        sio = StringIO("".join(physical_lines))
         for t in tokenize.generate_tokens(sio.readline):
             if not len(self.tokens) and t[0] in self.SKIP_TOKENS:
                 continue
@@ -2260,7 +2327,7 @@
     def __buildTokensLogical(self, tokens):
         """
         Private method to build a logical line from a list of tokens.
-        
+
         @param tokens list of tokens as generated by tokenize.generate_tokens
         @return logical line (string)
         """
@@ -2276,15 +2343,16 @@
                 start_line, start = t[2]
                 if end_line != start_line:  # different row
                     prev_text = self.lines[end_line - 1][end - 1]
-                    if prev_text == ',' or (prev_text not in '{[(' and
-                                            text not in '}])'):
-                        logical.append(' ')
+                    if prev_text == "," or (
+                        prev_text not in "{[(" and text not in "}])"
+                    ):
+                        logical.append(" ")
                 elif end != start:  # different column
                     fill = self.lines[end_line - 1][end:start]
                     logical.append(fill)
             logical.append(text)
             previous = t
-        logical_line = ''.join(logical)
+        logical_line = "".join(logical)
         return logical_line
 
     def pep8Expected(self):
@@ -2314,7 +2382,7 @@
             # bug, really.
             return valid_indents
 
-        indent_next = self.logical_line.endswith(':')
+        indent_next = self.logical_line.endswith(":")
 
         row = depth = 0
         parens = [0] * nrows
@@ -2328,8 +2396,10 @@
             newline = row < start[0] - first_row
             if newline:
                 row = start[0] - first_row
-                newline = (not last_token_multiline and
-                           token_type not in (tokenize.NL, tokenize.NEWLINE))
+                newline = not last_token_multiline and token_type not in (
+                    tokenize.NL,
+                    tokenize.NEWLINE,
+                )
 
             if newline:
                 # This is where the differences start. Instead of looking at
@@ -2352,7 +2422,7 @@
                 # list
                 vi = []
                 add_second_chances = False
-                if token_type == tokenize.OP and text in ']})':
+                if token_type == tokenize.OP and text in "]})":
                     # this line starts with a closing bracket, so it needs to
                     # be closed at the same indent as the opening one.
                     if indent[depth]:
@@ -2382,8 +2452,7 @@
                     vi.append(indent_level + hang)
 
                 # about the best we can do without look-ahead
-                if (indent_next and vi[0] == indent_level + 4 and
-                        nrows == row + 1):
+                if indent_next and vi[0] == indent_level + 4 and nrows == row + 1:
                     vi[0] += 4
 
                 if add_second_chances:
@@ -2391,9 +2460,9 @@
                     min_indent = vi[0]
                     for col, what in indent_chances.items():
                         if col > min_indent and (
-                            what is True or
-                            (what == str and token_type == tokenize.STRING) or
-                            (what == text and token_type == tokenize.OP)
+                            what is True
+                            or (what == str and token_type == tokenize.STRING)
+                            or (what == text and token_type == tokenize.OP)
                         ):
                             vi.append(col)
                     vi = sorted(vi)
@@ -2404,33 +2473,31 @@
                 # pycodestyle.
                 visual_indent = indent_chances.get(start[1])
                 last_indent = start
-                rel_indent[row] = (
-                    pycodestyle.expand_indent(line) - indent_level
-                )
+                rel_indent[row] = pycodestyle.expand_indent(line) - indent_level
                 hang = rel_indent[row] - rel_indent[open_row]
 
-                if token_type == tokenize.OP and text in ']})':
+                if token_type == tokenize.OP and text in "]})":
                     pass
                 elif visual_indent is True and not indent[depth]:
                     indent[depth] = start[1]
 
             # line altered: comments shouldn't define a visual indent
-            if parens[row] and not indent[depth] and token_type not in (
-                tokenize.NL, tokenize.COMMENT
+            if (
+                parens[row]
+                and not indent[depth]
+                and token_type not in (tokenize.NL, tokenize.COMMENT)
             ):
                 indent[depth] = start[1]
                 indent_chances[start[1]] = True
-            elif token_type == tokenize.STRING or text in (
-                'u', 'ur', 'b', 'br'
-            ):
+            elif token_type == tokenize.STRING or text in ("u", "ur", "b", "br"):
                 indent_chances[start[1]] = str
 
             if token_type == tokenize.OP:
-                if text in '([{':
+                if text in "([{":
                     depth += 1
                     indent.append(0)
                     parens[row] += 1
-                elif text in ')]}' and depth > 0:
+                elif text in ")]}" and depth > 0:
                     prev_indent = indent.pop() or last_indent[1]
                     for d in range(depth):
                         if indent[d] > prev_indent:
@@ -2448,7 +2515,7 @@
                 if start[1] not in indent_chances:
                     indent_chances[start[1]] = text
 
-            last_token_multiline = (start[0] != end[0])
+            last_token_multiline = start[0] != end[0]
 
         return valid_indents
 
@@ -2457,11 +2524,20 @@
     """
     Class used to shorten lines to a given maximum of characters.
     """
-    def __init__(self, curLine, prevLine, nextLine, maxLength=88, eol="\n",
-                 indentWord="    ", isDocString=False):
+
+    def __init__(
+        self,
+        curLine,
+        prevLine,
+        nextLine,
+        maxLength=88,
+        eol="\n",
+        indentWord="    ",
+        isDocString=False,
+    ):
         """
         Constructor
-        
+
         @param curLine text to work on (string)
         @param prevLine line before the text to work on (string)
         @param nextLine line after the text to work on (string)
@@ -2478,18 +2554,18 @@
         self.__eol = eol
         self.__indentWord = indentWord
         self.__isDocString = isDocString
-    
+
     def shorten(self):
         """
         Public method to shorten the line wrapped by the class instance.
-        
+
         @return tuple of a flag indicating successful shortening, the
             shortened line and the changed next line (boolean, string, string)
         """
         # 1. check for comment
-        if self.__text.lstrip().startswith('#'):
+        if self.__text.lstrip().startswith("#"):
             lastComment = True
-            if self.__nextText.lstrip().startswith('#'):
+            if self.__nextText.lstrip().startswith("#"):
                 lastComment = False
 
             # Wrap commented lines.
@@ -2498,13 +2574,13 @@
                 return False, "", ""
             else:
                 return True, newText, ""
-        elif '#' in self.__text:
+        elif "#" in self.__text:
             pos = self.__text.rfind("#")
             newText = (
-                self.__text[:pos].rstrip() +
-                self.__eol +
-                self.__getIndent(self.__text) +
-                self.__text[pos:]
+                self.__text[:pos].rstrip()
+                + self.__eol
+                + self.__getIndent(self.__text)
+                + self.__text[pos:]
             )
             if newText == self.__text:
                 return False, "", ""
@@ -2528,36 +2604,31 @@
                         # eric doc comment
                         # create a new line and indent it
                         newText = (
-                            first +
-                            self.__eol +
-                            self.__getIndent(first) +
-                            self.__indentWord +
-                            second
+                            first
+                            + self.__eol
+                            + self.__getIndent(first)
+                            + self.__indentWord
+                            + second
                         )
                         newNext = ""
                     else:
                         newText = first + self.__eol
                         newNext = (
-                            self.__getIndent(self.__nextText) +
-                            second.rstrip() +
-                            " " +
-                            self.__nextText.lstrip()
+                            self.__getIndent(self.__nextText)
+                            + second.rstrip()
+                            + " "
+                            + self.__nextText.lstrip()
                         )
                 else:
                     # empty line, add a new line
-                    newText = (
-                        first +
-                        self.__eol +
-                        self.__getIndent(first) +
-                        second
-                    )
+                    newText = first + self.__eol + self.__getIndent(first) + second
                     newNext = ""
             return True, newText, newNext
-        
+
         indent = self.__getIndent(self.__text)
-        source = self.__text[len(indent):]
+        source = self.__text[len(indent) :]
         sio = StringIO(source)
-        
+
         # Check for multi line string.
         try:
             tokens = list(tokenize.generate_tokens(sio.readline))
@@ -2566,10 +2637,10 @@
                 # just join the continuation line and let the next run
                 # handle it once it tokenizes ok
                 newText = (
-                    indent +
-                    source.rstrip()[:-1].rstrip() +
-                    " " +
-                    self.__nextText.lstrip()
+                    indent
+                    + source.rstrip()[:-1].rstrip()
+                    + " "
+                    + self.__nextText.lstrip()
                 )
                 if indent:
                     newNext = indent
@@ -2585,25 +2656,30 @@
 
         # Handle statements by putting the right hand side on a line by itself.
         # This should let the next pass shorten it.
-        if source.startswith('return '):
+        if source.startswith("return "):
             newText = (
-                indent +
-                'return (' +
-                self.__eol +
-                indent + self.__indentWord + re.sub('^return ', '', source) +
-                indent + ')' + self.__eol
+                indent
+                + "return ("
+                + self.__eol
+                + indent
+                + self.__indentWord
+                + re.sub("^return ", "", source)
+                + indent
+                + ")"
+                + self.__eol
             )
             return True, newText, ""
-        
+
         candidates = self.__shortenLine(tokens, source, indent)
         if candidates:
             candidates = sorted(
                 set(candidates).union([self.__text]),
-                key=lambda x: self.__lineShorteningRank(x))
+                key=lambda x: self.__lineShorteningRank(x),
+            )
             if candidates[0] == self.__text:
                 return False, "", ""
             return True, candidates[0], ""
-        
+
         source = self.__text
         rs = source.rstrip()
         if rs.endswith(("'", '"')) and " " in source:
@@ -2616,91 +2692,103 @@
             while blank > maxLen and blank != -1:
                 blank = source.rfind(" ", 0, blank)
             if blank != -1:
-                if source[blank + 1:].startswith(quote):
+                if source[blank + 1 :].startswith(quote):
                     first = source[:maxLen]
                     second = source[maxLen:]
                 else:
                     first = source[:blank]
-                    second = source[blank + 1:]
+                    second = source[blank + 1 :]
                 return (
                     True,
-                    first + quote + " \\" + self.__eol +
-                    indent + self.__indentWord + quote + second,
-                    "")
+                    first
+                    + quote
+                    + " \\"
+                    + self.__eol
+                    + indent
+                    + self.__indentWord
+                    + quote
+                    + second,
+                    "",
+                )
             else:
                 # Cannot break
                 return False, "", ""
-        
+
         return False, "", ""
-    
+
     def __shortenComment(self, isLast):
         """
         Private method to shorten a comment line.
-        
+
         @param isLast flag indicating, that the line is the last comment line
             (boolean)
         @return shortened comment line (string)
         """
         if len(self.__text) <= self.__maxLength:
             return self.__text
-        
+
         newText = self.__text.rstrip()
 
         # PEP 8 recommends 72 characters for comment text.
-        indentation = self.__getIndent(newText) + '# '
-        maxLength = min(self.__maxLength,
-                        len(indentation) + 72)
+        indentation = self.__getIndent(newText) + "# "
+        maxLength = min(self.__maxLength, len(indentation) + 72)
 
         MIN_CHARACTER_REPEAT = 5
         if (
-            len(newText) - len(newText.rstrip(newText[-1])) >=
-            MIN_CHARACTER_REPEAT and
-            not newText[-1].isalnum()
+            len(newText) - len(newText.rstrip(newText[-1])) >= MIN_CHARACTER_REPEAT
+            and not newText[-1].isalnum()
         ):
             # Trim comments that end with things like ---------
             return newText[:maxLength] + self.__eol
         elif isLast and re.match(r"\s*#+\s*\w+", newText):
             import textwrap
-            splitLines = textwrap.wrap(newText.lstrip(" \t#"),
-                                       initial_indent=indentation,
-                                       subsequent_indent=indentation,
-                                       width=maxLength,
-                                       break_long_words=False,
-                                       break_on_hyphens=False)
+
+            splitLines = textwrap.wrap(
+                newText.lstrip(" \t#"),
+                initial_indent=indentation,
+                subsequent_indent=indentation,
+                width=maxLength,
+                break_long_words=False,
+                break_on_hyphens=False,
+            )
             return self.__eol.join(splitLines) + self.__eol
         else:
             return newText + self.__eol
-    
+
     def __breakMultiline(self):
         """
         Private method to break multi line strings.
-        
+
         @return tuple of the shortened line and the changed next line
             (string, string)
         """
         indentation = self.__getIndent(self.__text)
 
         # Handle special case.
-        for symbol in '([{':
+        for symbol in "([{":
             # Only valid if symbol is not on a line by itself.
             if (
-                symbol in self.__text and
-                self.__text.strip() != symbol and
-                self.__text.rstrip().endswith((',', '%'))
+                symbol in self.__text
+                and self.__text.strip() != symbol
+                and self.__text.rstrip().endswith((",", "%"))
             ):
                 index = 1 + self.__text.find(symbol)
 
                 if index <= len(self.__indentWord) + len(indentation):
                     continue
 
-                if self.__isProbablyInsideStringOrComment(
-                        self.__text, index - 1):
+                if self.__isProbablyInsideStringOrComment(self.__text, index - 1):
                     continue
 
-                return (self.__text[:index].rstrip() + self.__eol +
-                        indentation + self.__indentWord +
-                        self.__text[index:].lstrip(), "")
-        
+                return (
+                    self.__text[:index].rstrip()
+                    + self.__eol
+                    + indentation
+                    + self.__indentWord
+                    + self.__text[index:].lstrip(),
+                    "",
+                )
+
         newText = self.__text
         newNext = self.__nextText
         blank = newText.rfind(" ")
@@ -2717,29 +2805,23 @@
                     newNext = ""
                 else:
                     newNext = (
-                        self.__getIndent(newNext) +
-                        second +
-                        " " +
-                        newNext.lstrip()
+                        self.__getIndent(newNext) + second + " " + newNext.lstrip()
                     )
             else:
                 # empty line, add a new line
                 newText = first + self.__eol
                 newNext = (
-                    self.__getIndent(newNext) +
-                    second +
-                    self.__eol +
-                    newNext.lstrip()
+                    self.__getIndent(newNext) + second + self.__eol + newNext.lstrip()
                 )
             return newText, newNext
         else:
             return None
-    
+
     def __isProbablyInsideStringOrComment(self, line, index):
         """
         Private method to check, if the given string might be inside a string
         or comment.
-        
+
         @param line line to check (string)
         @param index position inside line to check (integer)
         @return flag indicating the possibility of being inside a string
@@ -2752,16 +2834,16 @@
                 return True
 
         # Check against being in a comment.
-        pos = line.find('#')
+        pos = line.find("#")
         if pos != -1 and pos <= index:
             return True
 
         return False
-    
+
     def __shortenLine(self, tokens, source, indent):
         """
         Private method to shorten a line of code at an operator.
-        
+
         @param tokens tokens of the line as generated by tokenize
             (list of token)
         @param source code string to work at (string)
@@ -2769,85 +2851,89 @@
         @return list of candidates (list of string)
         """
         candidates = []
-        
+
         for tkn in tokens:
             tokenType = tkn[0]
             tokenString = tkn[1]
 
-            if (
-                tokenType == tokenize.COMMENT and
-                not self.__prevText.rstrip().endswith('\\')
+            if tokenType == tokenize.COMMENT and not self.__prevText.rstrip().endswith(
+                "\\"
             ):
                 # Move inline comments to previous line.
                 offset = tkn[2][1]
                 first = source[:offset]
                 second = source[offset:]
                 candidates.append(
-                    indent + second.strip() + self.__eol +
-                    indent + first.strip() + self.__eol)
-            elif tokenType == tokenize.OP and tokenString != '=':
+                    indent
+                    + second.strip()
+                    + self.__eol
+                    + indent
+                    + first.strip()
+                    + self.__eol
+                )
+            elif tokenType == tokenize.OP and tokenString != "=":
                 # Don't break on '=' after keyword as this violates PEP 8.
                 offset = tkn[2][1] + 1
                 first = source[:offset]
 
                 secondIndent = indent
-                if first.rstrip().endswith('('):
+                if first.rstrip().endswith("("):
                     secondIndent += self.__indentWord
-                elif '(' in first:
-                    secondIndent += ' ' * (1 + first.find('('))
+                elif "(" in first:
+                    secondIndent += " " * (1 + first.find("("))
                 else:
                     secondIndent += self.__indentWord
 
-                second = (secondIndent + source[offset:].lstrip())
+                second = secondIndent + source[offset:].lstrip()
                 if not second.strip():
                     continue
 
                 # Do not begin a line with a comma
-                if second.lstrip().startswith(','):
+                if second.lstrip().startswith(","):
                     continue
-                
+
                 # Do end a line with a dot
-                if first.rstrip().endswith('.'):
+                if first.rstrip().endswith("."):
                     continue
-                
-                if tokenString in '+-*/,':
-                    newText = first + ' \\' + self.__eol + second
+
+                if tokenString in "+-*/,":
+                    newText = first + " \\" + self.__eol + second
                 else:
                     newText = first + self.__eol + second
 
                 # Only fix if syntax is okay.
                 if self.__checkSyntax(self.__normalizeMultiline(newText)):
                     candidates.append(indent + newText)
-        
+
         return candidates
-    
+
     def __normalizeMultiline(self, text):
         """
         Private method to remove multiline-related code that will cause syntax
         error.
-        
+
         @param text code line to work on (string)
         @return normalized code line (string)
         """
-        for quote in '\'"':
+        for quote in "'\"":
             dictPattern = r"^{q}[^{q}]*{q} *: *".format(q=quote)
             if re.match(dictPattern, text):
-                if not text.strip().endswith('}'):
-                    text += '}'
-                return '{' + text
-
-        if text.startswith('def ') and text.rstrip().endswith(':'):
+                if not text.strip().endswith("}"):
+                    text += "}"
+                return "{" + text
+
+        if text.startswith("def ") and text.rstrip().endswith(":"):
             # Do not allow ':' to be alone. That is invalid.
             splitText = [item.strip() for item in text.split(self.__eol)]
-            if ':' not in splitText and 'def' not in splitText:
-                return text[len('def'):].strip().rstrip(':')
+            if ":" not in splitText and "def" not in splitText:
+                return text[len("def") :].strip().rstrip(":")
 
         return text
-    
+
     def __lineShorteningRank(self, candidate):
         """
         Private method to rank a candidate.
-        
+
         @param candidate candidate line to rank (string)
         @return rank of the candidate (integer)
         """
@@ -2856,27 +2942,24 @@
             if candidate == self.__text:
                 # give the original a disadvantage
                 rank += 50
-            
+
             lines = candidate.split(self.__eol)
 
             offset = 0
-            if lines[0].rstrip()[-1] not in '([{':
-                for symbol in '([{':
+            if lines[0].rstrip()[-1] not in "([{":
+                for symbol in "([{":
                     offset = max(offset, 1 + lines[0].find(symbol))
 
             maxLength = max(offset + len(x.strip()) for x in lines)
             rank += maxLength
             rank += len(lines)
 
-            badStartingSymbol = {
-                '(': ')',
-                '[': ']',
-                '{': '}'}.get(lines[0][-1], None)
+            badStartingSymbol = {"(": ")", "[": "]", "{": "}"}.get(lines[0][-1], None)
 
             if (
-                len(lines) > 1 and
-                badStartingSymbol and
-                lines[1].lstrip().startswith(badStartingSymbol)
+                len(lines) > 1
+                and badStartingSymbol
+                and lines[1].lstrip().startswith(badStartingSymbol)
             ):
                 rank += 20
 
@@ -2885,65 +2968,64 @@
                 rank += 100
 
             for currentLine in lines:
-                for badStart in ['.', '%', '+', '-', '/']:
+                for badStart in [".", "%", "+", "-", "/"]:
                     if currentLine.startswith(badStart):
                         rank += 100
 
-                for ending in '([{':
+                for ending in "([{":
                     # Avoid lonely opening. They result in longer lines.
-                    if (
-                        currentLine.endswith(ending) and
-                        len(currentLine.strip()) <= len(self.__indentWord)
+                    if currentLine.endswith(ending) and len(currentLine.strip()) <= len(
+                        self.__indentWord
                     ):
                         rank += 100
 
-                if currentLine.endswith('%'):
+                if currentLine.endswith("%"):
                     rank -= 20
 
                 # Try to break list comprehensions at the "for".
-                if currentLine.lstrip().startswith('for'):
+                if currentLine.lstrip().startswith("for"):
                     rank -= 50
 
                 rank += 10 * self.__countUnbalancedBrackets(currentLine)
         else:
             rank = 100000
-        
+
         return max(0, rank)
-    
+
     def __countUnbalancedBrackets(self, line):
         """
         Private method to determine the number of unmatched open/close
         brackets.
-        
+
         @param line line to work at (string)
         @return number of unmatched open/close brackets (integer)
         """
         count = 0
-        for opening, closing in ['()', '[]', '{}']:
+        for opening, closing in ["()", "[]", "{}"]:
             # __IGNORE_WARNING_M613__
             count += abs(line.count(opening) - line.count(closing))
-        
+
         return count
-    
+
     def __getIndent(self, line):
         """
         Private method to get the indentation string.
-        
+
         @param line line to determine the indentation string from (string)
         @return indentation string (string)
         """
         # copied from CodeStyleFixer
         return line.replace(line.lstrip(), "")
-    
+
     def __checkSyntax(self, code):
         """
         Private method to check the syntax of the given code fragment.
-        
+
         @param code code fragment to check (string)
         @return flag indicating syntax is ok (boolean)
         """
         code = code.replace("\r\n", "\n").replace("\r", "\n")
         try:
-            return compile(code, '<string>', 'exec')
+            return compile(code, "<string>", "exec")
         except (SyntaxError, TypeError, UnicodeDecodeError):
             return False

eric ide

mercurial