Plugins/CheckerPlugins/Pep8/Pep8Fixer.py

changeset 2891
6843b7d23279
parent 2890
86b03a0c94bc
child 2892
b601ede6dbbf
--- a/Plugins/CheckerPlugins/Pep8/Pep8Fixer.py	Thu Sep 05 20:02:02 2013 +0200
+++ b/Plugins/CheckerPlugins/Pep8/Pep8Fixer.py	Sat Sep 07 14:18:32 2013 +0200
@@ -32,7 +32,6 @@
                     ]
 
 
-# TODO: refine behavior for non-fixable issues
 class Pep8Fixer(QObject):
     """
     Class implementing a fixer for certain PEP 8 issues.
@@ -136,6 +135,8 @@
         
         self.__multiLineNumbers = None
         self.__docLineNumbers = None
+        
+        self.__lastID = 0
     
     def saveFile(self, encoding):
         """
@@ -148,9 +149,6 @@
             # no need to write
             return True
         
-        # apply deferred fixes
-        self.__finalize()
-        
         txt = "".join(self.__source)
         try:
             Utilities.writeEncodedFile(self.__filename, txt, encoding)
@@ -203,8 +201,9 @@
         @param line line number of issue (integer)
         @param pos character position of issue (integer)
         @param message message text (string)
-        @return flag indicating an applied fix (boolean) and a message for
-            the fix (string)
+        @return value indicating an applied/deferred fix (-1, 0, 1),
+            a message for the fix (string) and an ID for a deferred
+            fix (integer)
         """
         code = message.split(None, 1)[0].strip()
         
@@ -212,25 +211,46 @@
            self.__codeMatch(code) and \
            code in self.__fixes:
             res = self.__fixes[code](code, line, pos)
-            if res[0]:
+            if res[0] == 1:
                 self.__modified = True
                 self.fixed += 1
         else:
-            res = (False, "")
+            res = (0, "", 0)
         
         return res
     
-    def __finalize(self):
+    def finalize(self):
         """
-        Private method to apply all deferred fixes.
+        Public method to apply all deferred fixes.
         """
+        results = {}
+        
         # step 1: do fixes operating on logical lines first
-        for code, line, pos in self.__stackLogical:
-            self.__fixes[code](code, line, pos, apply=True)
+        for id_, code, line, pos in self.__stackLogical:
+            res, msg, _ = self.__fixes[code](code, line, pos, apply=True)
+            if res == 1:
+                self.__modified = True
+                self.fixed += 1
+            results[id_] = (res, msg)
         
         # step 2: do fixes that change the number of lines
-        for code, line, pos in reversed(self.__stack):
-            self.__fixes[code](code, line, pos, apply=True)
+        for id_, code, line, pos in reversed(self.__stack):
+            res, msg, _ = self.__fixes[code](code, line, pos, apply=True)
+            if res == 1:
+                self.__modified = True
+                self.fixed += 1
+            results[id_] = (res, msg)
+        
+        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 __getEol(self):
         """
@@ -441,8 +461,9 @@
         @param code code of the issue (string)
         @param line line number of the issue (integer)
         @param pos position inside line (integer)
-        @return flag indicating an applied fix (boolean) and a message for
-            the fix (string)
+        @return value indicating an applied/deferred fix (-1, 0, 1),
+            a message for the fix (string) and an ID for a deferred
+            fix (integer)
         """
         if self.__reindenter is None:
             self.__reindenter = Pep8Reindenter(self.__source)
@@ -455,9 +476,9 @@
             else:
                 msg = self.trUtf8(
                     "Indentation adjusted to be a multiple of four.")
-            return (True, msg)
+            return (1, msg, 0)
         else:
-            return (False, self.trUtf8("Fix for {0} failed.").format(code))
+            return (0, self.trUtf8("Fix for {0} failed.").format(code), 0)
     
     def __fixE121(self, code, line, pos, apply=False):
         """
@@ -469,21 +490,24 @@
         @param pos position inside line (integer)
         @keyparam apply flag indicating, that the fix should be applied
             (boolean)
-        @return flag indicating an applied fix (boolean) and a message for
-            the fix (string)
+        @return value indicating an applied/deferred fix (-1, 0, 1),
+            a message for the fix (string) and an ID for a deferred
+            fix (integer)
         """
         if apply:
             logical = self.__getLogical(line, pos)
             if logical:
                 # Fix by adjusting initial indent level.
                 self.__fixReindent(line, pos, logical)
+            if code == "E121":
+                msg = self.trUtf8("Indentation of continuation line corrected.")
+            elif code == "E124":
+                msg = self.trUtf8("Indentation of closing bracket corrected.")
+            return (1, msg, 0)
         else:
-            self.__stackLogical.append((code, line, pos))
-        if code == "E121":
-            msg = self.trUtf8("Indentation of continuation line corrected.")
-        elif code == "E124":
-            msg = self.trUtf8("Indentation of closing bracket corrected.")
-        return (True, msg)
+            id = self.__getID()
+            self.__stackLogical.append((id, code, line, pos))
+            return (-1, "", id)
     
     def __fixE122(self, code, line, pos, apply=False):
         """
@@ -495,8 +519,9 @@
         @param pos position inside line (integer)
         @keyparam apply flag indicating, that the fix should be applied
             (boolean)
-        @return flag indicating an applied fix (boolean) and a message for
-            the fix (string)
+        @return value indicating an applied/deferred fix (-1, 0, 1),
+            a message for the fix (string) and an ID for a deferred
+            fix (integer)
         """
         if apply:
             logical = self.__getLogical(line, pos)
@@ -510,11 +535,15 @@
                     indentation = self.__getIndent(text)
                     self.__source[line] = indentation + \
                         self.__indentWord + text.lstrip()
+            return (
+                1,
+                self.trUtf8(
+                    "Missing indentation of continuation line corrected."),
+                0)
         else:
-            self.__stackLogical.append((code, line, pos))
-        return (
-            True,
-            self.trUtf8("Missing indentation of continuation line corrected."))
+            id = self.__getID()
+            self.__stackLogical.append((id, code, line, pos))
+            return (-1, "", id)
     
     def __fixE123(self, code, line, pos, apply=False):
         """
@@ -526,8 +555,9 @@
         @param pos position inside line (integer)
         @keyparam apply flag indicating, that the fix should be applied
             (boolean)
-        @return flag indicating an applied fix (boolean) and a message for
-            the fix (string)
+        @return value indicating an applied/deferred fix (-1, 0, 1),
+            a message for the fix (string) and an ID for a deferred
+            fix (integer)
         """
         if apply:
             logical = self.__getLogical(line, pos)
@@ -542,10 +572,14 @@
                     self.__fixReindent(line, pos, logical)
                 else:
                     self.__source[row] = newText
+            return (
+                1,
+                self.trUtf8("Closing bracket aligned to opening bracket."),
+                0)
         else:
-            self.__stackLogical.append((code, line, pos))
-        return (
-            True, self.trUtf8("Closing bracket aligned to opening bracket."))
+            id = self.__getID()
+            self.__stackLogical.append((id, code, line, pos))
+            return (-1, "", id)
     
     def __fixE125(self, code, line, pos, apply=False):
         """
@@ -557,8 +591,9 @@
         @param pos position inside line (integer)
         @keyparam apply flag indicating, that the fix should be applied
             (boolean)
-        @return flag indicating an applied fix (boolean) and a message for
-            the fix (string)
+        @return value indicating an applied/deferred fix (-1, 0, 1),
+            a message for the fix (string) and an ID for a deferred
+            fix (integer)
         """
         if apply:
             logical = self.__getLogical(line, pos)
@@ -570,9 +605,11 @@
                     text = self.__source[row]
                     self.__source[row] = self.__getIndent(text) + \
                         self.__indentWord + text.lstrip()
+            return (1, self.trUtf8("Indentation level changed."), 0)
         else:
-            self.__stackLogical.append((code, line, pos))
-        return (True, self.trUtf8("Indentation level changed."))
+            id = self.__getID()
+            self.__stackLogical.append((id, code, line, pos))
+            return (-1, "", id)
     
     def __fixE126(self, code, line, pos, apply=False):
         """
@@ -584,8 +621,9 @@
         @param pos position inside line (integer)
         @keyparam apply flag indicating, that the fix should be applied
             (boolean)
-        @return flag indicating an applied fix (boolean) and a message for
-            the fix (string)
+        @return value indicating an applied/deferred fix (-1, 0, 1),
+            a message for the fix (string) and an ID for a deferred
+            fix (integer)
         """
         if apply:
             logical = self.__getLogical(line, pos)
@@ -601,11 +639,15 @@
                     self.__fixReindent(line, pos, logical)
                 else:
                     self.__source[row] = newText
+            return (
+                1,
+                self.trUtf8(
+                    "Indentation level of hanging indentation changed."),
+                0)
         else:
-            self.__stackLogical.append((code, line, pos))
-        return (
-            True,
-            self.trUtf8("Indentation level of hanging indentation changed."))
+            id = self.__getID()
+            self.__stackLogical.append((id, code, line, pos))
+            return (-1, "", id)
     
     def __fixE127(self, code, line, pos, apply=False):
         """
@@ -616,8 +658,9 @@
         @param pos position inside line (integer)
         @keyparam apply flag indicating, that the fix should be applied
             (boolean)
-        @return flag indicating an applied fix (boolean) and a message for
-            the fix (string)
+        @return value indicating an applied/deferred fix (-1, 0, 1),
+            a message for the fix (string) and an ID for a deferred
+            fix (integer)
         """
         if apply:
             logical = self.__getLogical(line, pos)
@@ -649,9 +692,11 @@
                     self.__fixReindent(line, pos, logical)
                 else:
                     self.__source[row] = newText
+            return (1, self.trUtf8("Visual indentation corrected."), 0)
         else:
-            self.__stackLogical.append((code, line, pos))
-        return (True, self.trUtf8("Visual indentation corrected."))
+            id = self.__getID()
+            self.__stackLogical.append((id, code, line, pos))
+            return (-1, "", id)
     
     def __fixE201(self, code, line, pos):
         """
@@ -661,22 +706,23 @@
         @param code code of the issue (string)
         @param line line number of the issue (integer)
         @param pos position inside line (integer)
-        @return flag indicating an applied fix (boolean) and a message for
-            the fix (string)
+        @return value indicating an applied/deferred fix (-1, 0, 1),
+            a message for the fix (string) and an ID for a deferred
+            fix (integer)
         """
         line = line - 1
         text = self.__source[line]
         
         if '"""' in text or "'''" in text or text.rstrip().endswith('\\'):
             return (
-                False, self.trUtf8("Extraneous whitespace cannot be removed."))
+                0, self.trUtf8("Extraneous whitespace cannot be removed."), 0)
         
         newText = self.__fixWhitespace(text, pos, '')
         if newText == text:
-            return (False, "")
+            return (0, "", 0)
         
         self.__source[line] = newText
-        return (True, self.trUtf8("Extraneous whitespace removed."))
+        return (1, self.trUtf8("Extraneous whitespace removed."), 0)
     
     def __fixE221(self, code, line, pos):
         """
@@ -687,25 +733,26 @@
         @param code code of the issue (string)
         @param line line number of the issue (integer)
         @param pos position inside line (integer)
-        @return flag indicating an applied fix (boolean) and a message for
-            the fix (string)
+        @return value indicating an applied/deferred fix (-1, 0, 1),
+            a message for the fix (string) and an ID for a deferred
+            fix (integer)
         """
         line = line - 1
         text = self.__source[line]
         
         if '"""' in text or "'''" in text or text.rstrip().endswith('\\'):
             return (
-                False, self.trUtf8("Extraneous whitespace cannot be removed."))
+                0, self.trUtf8("Extraneous whitespace cannot be removed."), 0)
         
         newText = self.__fixWhitespace(text, pos, ' ')
         if newText == text:
-            return (False, "")
+            return (0, "", 0)
         
         self.__source[line] = newText
         if code in ["E225", "E226", "E227", "E228"]:
-            return (True, self.trUtf8("Missing whitespace added."))
+            return (1, self.trUtf8("Missing whitespace added."), 0)
         else:
-            return (True, self.trUtf8("Extraneous whitespace removed."))
+            return (1, self.trUtf8("Extraneous whitespace removed."), 0)
     
     def __fixE231(self, code, line, pos):
         """
@@ -714,15 +761,16 @@
         @param code code of the issue (string)
         @param line line number of the issue (integer)
         @param pos position inside line (integer)
-        @return flag indicating an applied fix (boolean) and a message for
-            the fix (string)
+        @return value indicating an applied/deferred fix (-1, 0, 1),
+            a message for the fix (string) and an ID for a deferred
+            fix (integer)
         """
         line = line - 1
         pos = pos + 1
         self.__source[line] = self.__source[line][:pos] + \
                                " " + \
                                self.__source[line][pos:]
-        return (True, self.trUtf8("Missing whitespace added."))
+        return (1, self.trUtf8("Missing whitespace added."), 0)
     
     def __fixE251(self, code, line, pos):
         """
@@ -732,8 +780,9 @@
         @param code code of the issue (string)
         @param line line number of the issue (integer)
         @param pos position inside line (integer)
-        @return flag indicating an applied fix (boolean) and a message for
-            the fix (string)
+        @return value indicating an applied/deferred fix (-1, 0, 1),
+            a message for the fix (string) and an ID for a deferred
+            fix (integer)
         """
         line = line - 1
         text = self.__source[line]
@@ -756,7 +805,7 @@
             self.__source[line + 1] = self.__source[line + 1].lstrip()
         else:
             self.__source[line] = newText
-        return (True, self.trUtf8("Extraneous whitespace removed."))
+        return (1, self.trUtf8("Extraneous whitespace removed."), 0)
     
     def __fixE261(self, code, line, pos):
         """
@@ -766,8 +815,9 @@
         @param code code of the issue (string)
         @param line line number of the issue (integer)
         @param pos position inside line (integer)
-        @return flag indicating an applied fix (boolean) and a message for
-            the fix (string)
+        @return value indicating an applied/deferred fix (-1, 0, 1),
+            a message for the fix (string) and an ID for a deferred
+            fix (integer)
         """
         line = line - 1
         text = self.__source[line]
@@ -775,7 +825,7 @@
         right = text[pos:].lstrip(' \t#')
         newText = left + ("  # " + right if right.strip() else right)
         self.__source[line] = newText
-        return (True, self.trUtf8("Whitespace around comment sign corrected."))
+        return (1, self.trUtf8("Whitespace around comment sign corrected."), 0)
     
     def __fixE301(self, code, line, pos, apply=False):
         """
@@ -786,14 +836,17 @@
         @param pos position inside line (integer)
         @keyparam apply flag indicating, that the fix should be applied
             (boolean)
-        @return flag indicating an applied fix (boolean) and a message for
-            the fix (string)
+        @return value indicating an applied/deferred fix (-1, 0, 1),
+            a message for the fix (string) and an ID for a deferred
+            fix (integer)
         """
         if apply:
             self.__source.insert(line - 1, self.__getEol())
+            return (1, self.trUtf8("One blank line inserted."), 0)
         else:
-            self.__stack.append((code, line, pos))
-        return (True, self.trUtf8("One blank line inserted."))
+            id = self.__getID()
+            self.__stack.append((id, code, line, pos))
+            return (-1, "", id)
     
     def __fixE302(self, code, line, pos, apply=False):
         """
@@ -804,21 +857,22 @@
         @param pos position inside line (integer)
         @keyparam apply flag indicating, that the fix should be applied
             (boolean)
-        @return flag indicating an applied fix (boolean) and a message for
-            the fix (string)
+        @return value indicating an applied/deferred fix (-1, 0, 1),
+            a message for the fix (string) and an ID for a deferred
+            fix (integer)
         """
-        # count blank lines
-        index = line - 1
-        blanks = 0
-        while index:
-            if self.__source[index - 1].strip() == "":
-                blanks += 1
-                index -= 1
-            else:
-                break
-        delta = blanks - 2
-        
         if apply:
+            # count blank lines
+            index = line - 1
+            blanks = 0
+            while index:
+                if self.__source[index - 1].strip() == "":
+                    blanks += 1
+                    index -= 1
+                else:
+                    break
+            delta = blanks - 2
+            
             line -= 1
             if delta < 0:
                 # insert blank lines (one or two)
@@ -831,16 +885,18 @@
                     del self.__source[line - 1]
                     line -= 1
                     delta -= 1
+            
+            if delta < 0:
+                msg = self.trUtf8("%n blank line(s) inserted.", "", -delta)
+            elif delta > 0:
+                msg = self.trUtf8("%n superfluous lines removed", "", delta)
+            else:
+                msg = ""
+            return (1, msg, 0)
         else:
-            self.__stack.append((code, line, pos))
-        
-        if delta < 0:
-            msg = self.trUtf8("%n blank line(s) inserted.", "", -delta)
-        elif delta > 0:
-            msg = self.trUtf8("%n superfluous lines removed", "", delta)
-        else:
-            msg = ""
-        return (True, msg)
+            id = self.__getID()
+            self.__stack.append((id, code, line, pos))
+            return (-1, "", id)
     
     def __fixE303(self, code, line, pos, apply=False):
         """
@@ -851,8 +907,9 @@
         @param pos position inside line (integer)
         @keyparam apply flag indicating, that the fix should be applied
             (boolean)
-        @return flag indicating an applied fix (boolean) and a message for
-            the fix (string)
+        @return value indicating an applied/deferred fix (-1, 0, 1),
+            a message for the fix (string) and an ID for a deferred
+            fix (integer)
         """
         if apply:
             index = line - 3
@@ -862,9 +919,11 @@
                     index -= 1
                 else:
                     break
+            return (1, self.trUtf8("Superfluous blank lines removed."), 0)
         else:
-            self.__stack.append((code, line, pos))
-        return (True, self.trUtf8("Superfluous blank lines removed."))
+            id = self.__getID()
+            self.__stack.append((id, code, line, pos))
+            return (-1, "", id)
     
     def __fixE304(self, code, line, pos, apply=False):
         """
@@ -876,8 +935,9 @@
         @param pos position inside line (integer)
         @keyparam apply flag indicating, that the fix should be applied
             (boolean)
-        @return flag indicating an applied fix (boolean) and a message for
-            the fix (string)
+        @return value indicating an applied/deferred fix (-1, 0, 1),
+            a message for the fix (string) and an ID for a deferred
+            fix (integer)
         """
         if apply:
             index = line - 2
@@ -887,10 +947,15 @@
                     index -= 1
                 else:
                     break
+            return (
+                1,
+                self.trUtf8("Superfluous blank lines after function"
+                            " decorator removed."),
+                0)
         else:
-            self.__stack.append((code, line, pos))
-        return (True, self.trUtf8(
-            "Superfluous blank lines after function decorator removed."))
+            id = self.__getID()
+            self.__stack.append((id, code, line, pos))
+            return (-1, "", id)
     
     def __fixE401(self, code, line, pos, apply=False):
         """
@@ -901,27 +966,30 @@
         @param pos position inside line (integer)
         @keyparam apply flag indicating, that the fix should be applied
             (boolean)
-        @return flag indicating an applied fix (boolean) and a message for
-            the fix (string)
+        @return value indicating an applied/deferred fix (-1, 0, 1),
+            a message for the fix (string) and an ID for a deferred
+            fix (integer)
         """
         if apply:
             line = line - 1
             text = self.__source[line]
             if not text.lstrip().startswith("import"):
-                return (False, "")
+                return (0, "", 0)
             
             # pep8 (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:
-                return (False, "")
+                return (0, "", 0)
             
             newText = text[:pos].rstrip("\t ,") + self.__getEol() + \
                 self.__getIndent(text) + "import " + text[pos:].lstrip("\t ,")
             self.__source[line] = newText
+            return (1, self.trUtf8("Imports were put on separate lines."), 0)
         else:
-            self.__stack.append((code, line, pos))
-        return (True, self.trUtf8("Imports were put on separate lines."))
+            id = self.__getID()
+            self.__stack.append((id, code, line, pos))
+            return (-1, "", id)
     
     def __fixE501(self, code, line, pos, apply=False):
         """
@@ -932,8 +1000,9 @@
         @param pos position inside line (integer)
         @keyparam apply flag indicating, that the fix should be applied
             (boolean)
-        @return flag indicating an applied fix (boolean) and a message for
-            the fix (string)
+        @return value indicating an applied/deferred fix (-1, 0, 1),
+            a message for the fix (string) and an ID for a deferred
+            fix (integer)
         """
         multilineStringLines, docStringLines = self.__multilineStringLines()
         if apply:
@@ -957,9 +1026,13 @@
                     self.__source[line] = newText
                 if newNextText and newNextText != nextText:
                     self.__source[line + 1] = newNextText
+                return (1, self.trUtf8("Long lines have been shortened."), 0)
+            else:
+                return (0, "", 0)
         else:
-            self.__stack.append((code, line, pos))
-        return (True, self.trUtf8("Long lines have been shortened."))
+            id = self.__getID()
+            self.__stack.append((id, code, line, pos))
+            return (-1, "", id)
     
     def __fixE502(self, code, line, pos):
         """
@@ -968,12 +1041,13 @@
         @param code code of the issue (string)
         @param line line number of the issue (integer)
         @param pos position inside line (integer)
-        @return flag indicating an applied fix (boolean) and a message for
-            the fix (string)
+        @return value indicating an applied/deferred fix (-1, 0, 1),
+            a message for the fix (string) and an ID for a deferred
+            fix (integer)
         """
         self.__source[line - 1] = \
             self.__source[line - 1].rstrip("\n\r \t\\") + self.__getEol()
-        return (True, self.trUtf8("Redundant backslash in brackets removed."))
+        return (1, self.trUtf8("Redundant backslash in brackets removed."), 0)
     
     def __fixE701(self, code, line, pos, apply=False):
         """
@@ -984,8 +1058,9 @@
         @param pos position inside line (integer)
         @keyparam apply flag indicating, that the fix should be applied
             (boolean)
-        @return flag indicating an applied fix (boolean) and a message for
-            the fix (string)
+        @return value indicating an applied/deferred fix (-1, 0, 1),
+            a message for the fix (string) and an ID for a deferred
+            fix (integer)
         """
         if apply:
             line = line - 1
@@ -996,9 +1071,11 @@
                 self.__indentWord + text[pos:].lstrip("\n\r \t\\") + \
                 self.__getEol()
             self.__source[line] = newText
+            return (1, self.trUtf8("Compound statement corrected."), 0)
         else:
-            self.__stack.append((code, line, pos))
-        return (True, self.trUtf8("Compound statement corrected."))
+            id = self.__getID()
+            self.__stack.append((id, code, line, pos))
+            return (-1, "", id)
     
     def __fixE702(self, code, line, pos, apply=False):
         """
@@ -1010,8 +1087,9 @@
         @param pos position inside line (integer)
         @keyparam apply flag indicating, that the fix should be applied
             (boolean)
-        @return flag indicating an applied fix (boolean) and a message for
-            the fix (string)
+        @return value indicating an applied/deferred fix (-1, 0, 1),
+            a message for the fix (string) and an ID for a deferred
+            fix (integer)
         """
         if apply:
             line = line - 1
@@ -1027,9 +1105,11 @@
                 first = text[:pos].rstrip("\n\r \t;") + self.__getEol()
                 second = text[pos:].lstrip("\n\r \t;")
                 self.__source[line] = first + self.__getIndent(text) + second
+            return (1, self.trUtf8("Compound statement corrected."), 0)
         else:
-            self.__stack.append((code, line, pos))
-        return (True, self.trUtf8("Compound statement corrected."))
+            id = self.__getID()
+            self.__stack.append((id, code, line, pos))
+            return (-1, "", id)
     
     def __fixE711(self, code, line, pos):
         """
@@ -1038,32 +1118,33 @@
         @param code code of the issue (string)
         @param line line number of the issue (integer)
         @param pos position inside line (integer)
-        @return flag indicating an applied fix (boolean) and a message for
-            the fix (string)
+        @return value indicating an applied/deferred fix (-1, 0, 1),
+            a message for the fix (string) and an ID for a deferred
+            fix (integer)
         """
         line = line - 1
         text = self.__source[line]
         
         rightPos = pos + 2
         if rightPos >= len(text):
-            return (False, "")
+            return (0, "", 0)
         
         left = text[:pos].rstrip()
         center = text[pos:rightPos]
         right = text[rightPos:].lstrip()
         
         if not right.startswith(("None", "True", "False")):
-            return (False, "")
+            return (0, "", 0)
         
         if center.strip() == "==":
             center = "is"
         elif center.strip() == "!=":
             center = "is not"
         else:
-            return (False, "")
+            return (0, "", 0)
         
         self.__source[line] = " ".join([left, center, right])
-        return (True, self.trUtf8("Comparison to None/True/False corrected."))
+        return (1, self.trUtf8("Comparison to None/True/False corrected."), 0)
     
     def __fixW291(self, code, line, pos):
         """
@@ -1072,12 +1153,13 @@
         @param code code of the issue (string)
         @param line line number of the issue (integer)
         @param pos position inside line (integer)
-        @return flag indicating an applied fix (boolean) and a message for
-            the fix (string)
+        @return value indicating an applied/deferred fix (-1, 0, 1),
+            a message for the fix (string) and an ID for a deferred
+            fix (integer)
         """
         self.__source[line - 1] = re.sub(r'[\t ]+(\r?)$', r"\1",
                                          self.__source[line - 1])
-        return (True, self.trUtf8("Whitespace stripped from end of line."))
+        return (1, self.trUtf8("Whitespace stripped from end of line."), 0)
     
     def __fixW292(self, code, line, pos):
         """
@@ -1086,11 +1168,12 @@
         @param code code of the issue (string)
         @param line line number of the issue (integer)
         @param pos position inside line (integer)
-        @return flag indicating an applied fix (boolean) and a message for
-            the fix (string)
+        @return value indicating an applied/deferred fix (-1, 0, 1),
+            a message for the fix (string) and an ID for a deferred
+            fix (integer)
         """
         self.__source[line - 1] += self.__getEol()
-        return (True, self.trUtf8("newline added to end of file."))
+        return (1, self.trUtf8("newline added to end of file."), 0)
     
     def __fixW391(self, code, line, pos):
         """
@@ -1099,8 +1182,9 @@
         @param code code of the issue (string)
         @param line line number of the issue (integer)
         @param pos position inside line (integer)
-        @return flag indicating an applied fix (boolean) and a message for
-            the fix (string)
+        @return value indicating an applied/deferred fix (-1, 0, 1),
+            a message for the fix (string) and an ID for a deferred
+            fix (integer)
         """
         index = line - 1
         while index:
@@ -1109,8 +1193,8 @@
                 index -= 1
             else:
                 break
-        return (True, self.trUtf8(
-            "Superfluous trailing blank lines removed from end of file."))
+        return (1, self.trUtf8(
+            "Superfluous trailing blank lines removed from end of file."), 0)
     
     def __fixW603(self, code, line, pos):
         """
@@ -1119,11 +1203,12 @@
         @param code code of the issue (string)
         @param line line number of the issue (integer)
         @param pos position inside line (integer)
-        @return flag indicating an applied fix (boolean) and a message for
-            the fix (string)
+        @return value indicating an applied/deferred fix (-1, 0, 1),
+            a message for the fix (string) and an ID for a deferred
+            fix (integer)
         """
         self.__source[line - 1] = self.__source[line - 1].replace("<>", "!=")
-        return (True, self.trUtf8("'<>' replaced by '!='."))
+        return (1, self.trUtf8("'<>' replaced by '!='."), 0)
 
 
 class Pep8Reindenter(object):
@@ -1677,6 +1762,8 @@
             candidates = list(sorted(
                 set(candidates).union([self.__text]),
                 key=lambda x: self.__lineShorteningRank(x)))
+            if candidates[0] == self.__text:
+                return False, "", ""
             return True, candidates[0], ""
         
         source = self.__text
@@ -1912,6 +1999,10 @@
         """
         rank = 0
         if candidate.strip():
+            if candidate == self.__text:
+                # give the original a disadvantage
+                rank += 50
+            
             lines = candidate.split(self.__eol)
 
             offset = 0

eric ide

mercurial