Plugins/CheckerPlugins/Pep8/Pep8Fixer.py

branch
Py2 comp.
changeset 3056
9986ec0e559a
parent 2911
ce77f0b1ee67
parent 2937
de26bc76d6ee
equal deleted inserted replaced
2911:ce77f0b1ee67 3056:9986ec0e559a
2 2
3 # Copyright (c) 2011 - 2013 Detlev Offenbach <detlev@die-offenbachs.de> 3 # Copyright (c) 2011 - 2013 Detlev Offenbach <detlev@die-offenbachs.de>
4 # 4 #
5 5
6 """ 6 """
7 Module implementing a class to fix certain PEP 8 issues. 7 Module implementing a class to fix certain code style issues.
8 """ 8 """
9 9
10 from __future__ import unicode_literals # __IGNORE_WARNING__ 10 from __future__ import unicode_literals # __IGNORE_WARNING__
11 11
12 import os 12 import os
20 20
21 from . import pep8 21 from . import pep8
22 22
23 import Utilities 23 import Utilities
24 24
25 Pep8FixableIssues = ["E101", "E111", "E121", "E122", "E123", "E124", 25 Pep8FixableIssues = ["D111", "D112", "D113", "D121", "D131", "D141",
26 "E125", "E126", "E127", "E128", "E133", "W191", 26 "D142", "D143", "D144", "D145",
27 "E201", "E202", "E203", "E211", "E221", "E222", 27 "D221", "D222", "D231", "D242", "D243", "D244",
28 "E223", "E224", "E225", "E226", "E227", "E228", 28 "D245", "D246", "D247",
29 "E231", "E241", "E242", "E251", "E261", "E262", 29 "E101", "E111", "E121", "E122", "E123", "E124",
30 "E271", "E272", "E273", "E274", "W291", "W292", 30 "E125", "E126", "E127", "E128", "E133", "E201",
31 "W293", "E301", "E302", "E303", "E304", "W391", 31 "E202", "E203", "E211", "E221", "E222", "E223",
32 "E401", "E501", "E502", "W603", "E701", "E702", 32 "E224", "E225", "E226", "E227", "E228", "E231",
33 "E703", "E711", "E712" 33 "E241", "E242", "E251", "E261", "E262", "E271",
34 ] 34 "E272", "E273", "E274", "E301", "E302", "E303",
35 "E304", "E401", "E501", "E502", "E701", "E702",
36 "E703", "E711", "E712",
37 "N804", "N805", "N806",
38 "W191", "W291", "W292", "W293", "W391", "W603",
39 ]
35 40
36 41
37 class Pep8Fixer(QObject): 42 class Pep8Fixer(QObject):
38 """ 43 """
39 Class implementing a fixer for certain PEP 8 issues. 44 Class implementing a fixer for certain code style issues.
40 """ 45 """
41 def __init__(self, project, filename, sourceLines, fixCodes, noFixCodes, 46 def __init__(self, project, filename, sourceLines, fixCodes, noFixCodes,
42 maxLineLength, inPlace): 47 maxLineLength, inPlace):
43 """ 48 """
44 Constructor 49 Constructor
70 self.__eol = "" 75 self.__eol = ""
71 self.__indentWord = self.__getIndentWord() 76 self.__indentWord = self.__getIndentWord()
72 77
73 if not inPlace: 78 if not inPlace:
74 self.__origName = self.__filename 79 self.__origName = self.__filename
75 self.__filename = os.path.join(os.path.dirname(self.__filename), 80 self.__filename = os.path.join(
81 os.path.dirname(self.__filename),
76 "fixed_" + os.path.basename(self.__filename)) 82 "fixed_" + os.path.basename(self.__filename))
77 83
78 self.__fixes = { 84 self.__fixes = {
85 "D111": self.__fixD111,
86 "D112": self.__fixD112,
87 "D113": self.__fixD112,
88 "D121": self.__fixD121,
89 "D131": self.__fixD131,
90 "D141": self.__fixD141,
91 "D142": self.__fixD142,
92 "D143": self.__fixD143,
93 "D144": self.__fixD144,
94 "D145": self.__fixD145,
95 "D221": self.__fixD221,
96 "D222": self.__fixD221,
97 "D231": self.__fixD131,
98 "D242": self.__fixD242,
99 "D243": self.__fixD243,
100 "D244": self.__fixD242,
101 "D245": self.__fixD243,
102 "D246": self.__fixD144,
103 "D247": self.__fixD247,
79 "E101": self.__fixE101, 104 "E101": self.__fixE101,
80 "E111": self.__fixE101, 105 "E111": self.__fixE101,
81 "E121": self.__fixE121, 106 "E121": self.__fixE121,
82 "E122": self.__fixE122, 107 "E122": self.__fixE122,
83 "E123": self.__fixE123, 108 "E123": self.__fixE123,
85 "E125": self.__fixE125, 110 "E125": self.__fixE125,
86 "E126": self.__fixE126, 111 "E126": self.__fixE126,
87 "E127": self.__fixE127, 112 "E127": self.__fixE127,
88 "E128": self.__fixE127, 113 "E128": self.__fixE127,
89 "E133": self.__fixE126, 114 "E133": self.__fixE126,
90 "W191": self.__fixE101,
91 "E201": self.__fixE201, 115 "E201": self.__fixE201,
92 "E202": self.__fixE201, 116 "E202": self.__fixE201,
93 "E203": self.__fixE201, 117 "E203": self.__fixE201,
94 "E211": self.__fixE201, 118 "E211": self.__fixE201,
95 "E221": self.__fixE221, 119 "E221": self.__fixE221,
108 "E262": self.__fixE261, 132 "E262": self.__fixE261,
109 "E271": self.__fixE221, 133 "E271": self.__fixE221,
110 "E272": self.__fixE221, 134 "E272": self.__fixE221,
111 "E273": self.__fixE221, 135 "E273": self.__fixE221,
112 "E274": self.__fixE221, 136 "E274": self.__fixE221,
113 "W291": self.__fixW291,
114 "W292": self.__fixW292,
115 "W293": self.__fixW291,
116 "E301": self.__fixE301, 137 "E301": self.__fixE301,
117 "E302": self.__fixE302, 138 "E302": self.__fixE302,
118 "E303": self.__fixE303, 139 "E303": self.__fixE303,
119 "E304": self.__fixE304, 140 "E304": self.__fixE304,
120 "W391": self.__fixW391,
121 "E401": self.__fixE401, 141 "E401": self.__fixE401,
122 "E501": self.__fixE501, 142 "E501": self.__fixE501,
123 "E502": self.__fixE502, 143 "E502": self.__fixE502,
124 "W603": self.__fixW603,
125 "E701": self.__fixE701, 144 "E701": self.__fixE701,
126 "E702": self.__fixE702, 145 "E702": self.__fixE702,
127 "E703": self.__fixE702, 146 "E703": self.__fixE702,
128 "E711": self.__fixE711, 147 "E711": self.__fixE711,
129 "E712": self.__fixE711, 148 "E712": self.__fixE711,
149 "N804": self.__fixN804,
150 "N805": self.__fixN804,
151 "N806": self.__fixN806,
152 "W191": self.__fixE101,
153 "W291": self.__fixW291,
154 "W292": self.__fixW292,
155 "W293": self.__fixW291,
156 "W391": self.__fixW391,
157 "W603": self.__fixW603,
130 } 158 }
131 self.__modified = False 159 self.__modified = False
132 self.__stackLogical = [] # these need to be fixed before the file 160 self.__stackLogical = [] # these need to be fixed before the file
133 # is saved but after all other inline 161 # is saved but after all other inline
134 # fixes. These work with logical lines. 162 # fixes. These work with logical lines.
135 self.__stack = [] # these need to be fixed before the file 163 self.__stack = [] # these need to be fixed before the file
136 # is saved but after all inline fixes 164 # is saved but after all inline fixes
137 165
138 self.__multiLineNumbers = None 166 self.__multiLineNumbers = None
139 self.__docLineNumbers = None 167 self.__docLineNumbers = None
168
169 self.__lastID = 0
140 170
141 def saveFile(self, encoding): 171 def saveFile(self, encoding):
142 """ 172 """
143 Public method to save the modified file. 173 Public method to save the modified file.
144 174
146 @return flag indicating success (boolean) 176 @return flag indicating success (boolean)
147 """ 177 """
148 if not self.__modified: 178 if not self.__modified:
149 # no need to write 179 # no need to write
150 return True 180 return True
151
152 # apply deferred fixes
153 self.__finalize()
154 181
155 txt = "".join(self.__source) 182 txt = "".join(self.__source)
156 try: 183 try:
157 Utilities.writeEncodedFile(self.__filename, txt, encoding) 184 Utilities.writeEncodedFile(self.__filename, txt, encoding)
158 except (IOError, Utilities.CodingError, UnicodeError) as err: 185 except (IOError, Utilities.CodingError, UnicodeError) as err:
159 E5MessageBox.critical(self, 186 E5MessageBox.critical(
160 self.trUtf8("Fix PEP 8 issues"), 187 self,
188 self.trUtf8("Fix Code Style Issues"),
161 self.trUtf8( 189 self.trUtf8(
162 """<p>Could not save the file <b>{0}</b>.""" 190 """<p>Could not save the file <b>{0}</b>."""
163 """ Skipping it.</p><p>Reason: {1}</p>""") 191 """ Skipping it.</p><p>Reason: {1}</p>""")
164 .format(self.__filename, str(err)) 192 .format(self.__filename, str(err))
165 ) 193 )
166 return False 194 return False
167 195
168 return True 196 return True
169 197
202 Public method to fix the fixable issues. 230 Public method to fix the fixable issues.
203 231
204 @param line line number of issue (integer) 232 @param line line number of issue (integer)
205 @param pos character position of issue (integer) 233 @param pos character position of issue (integer)
206 @param message message text (string) 234 @param message message text (string)
207 @return flag indicating an applied fix (boolean) and a message for 235 @return value indicating an applied/deferred fix (-1, 0, 1),
208 the fix (string) 236 a message for the fix (string) and an ID for a deferred
237 fix (integer)
209 """ 238 """
210 code = message.split(None, 1)[0].strip() 239 code = message.split(None, 1)[0].strip()
211 240
212 if line <= len(self.__source) and \ 241 if line <= len(self.__source) and \
213 self.__codeMatch(code) and \ 242 self.__codeMatch(code) and \
214 code in self.__fixes: 243 code in self.__fixes:
215 res = self.__fixes[code](code, line, pos) 244 res = self.__fixes[code](code, line, pos)
216 if res[0]: 245 if res[0] == 1:
217 self.__modified = True 246 self.__modified = True
218 self.fixed += 1 247 self.fixed += 1
219 else: 248 else:
220 res = (False, "") 249 res = (0, "", 0)
221 250
222 return res 251 return res
223 252
224 def __finalize(self): 253 def finalize(self):
225 """ 254 """
226 Private method to apply all deferred fixes. 255 Public method to apply all deferred fixes.
227 """ 256 """
257 results = {}
258
228 # step 1: do fixes operating on logical lines first 259 # step 1: do fixes operating on logical lines first
229 for code, line, pos in self.__stackLogical: 260 for id_, code, line, pos in self.__stackLogical:
230 self.__fixes[code](code, line, pos, apply=True) 261 res, msg, _ = self.__fixes[code](code, line, pos, apply=True)
262 if res == 1:
263 self.__modified = True
264 self.fixed += 1
265 results[id_] = (res, msg)
231 266
232 # step 2: do fixes that change the number of lines 267 # step 2: do fixes that change the number of lines
233 for code, line, pos in reversed(self.__stack): 268 for id_, code, line, pos in reversed(self.__stack):
234 self.__fixes[code](code, line, pos, apply=True) 269 res, msg, _ = self.__fixes[code](code, line, pos, apply=True)
270 if res == 1:
271 self.__modified = True
272 self.fixed += 1
273 results[id_] = (res, msg)
274
275 return results
276
277 def __getID(self):
278 """
279 Private method to get the ID for a deferred fix.
280
281 @return ID for a deferred fix (integer)
282 """
283 self.__lastID += 1
284 return self.__lastID
235 285
236 def __getEol(self): 286 def __getEol(self):
237 """ 287 """
238 Private method to get the applicable eol string. 288 Private method to get the applicable eol string.
239 289
432 if right.startswith("#"): 482 if right.startswith("#"):
433 return line 483 return line
434 else: 484 else:
435 return left + replacement + right 485 return left + replacement + right
436 486
487 def __fixD111(self, code, line, pos):
488 """
489 Private method to fix docstring enclosed in wrong quotes (D111).
490
491 @param code code of the issue (string)
492 @param line line number of the issue (integer)
493 @param pos position inside line (integer)
494 @return value indicating an applied/deferred fix (-1, 0, 1),
495 a message for the fix (string) and an ID for a deferred
496 fix (integer)
497 """
498 line = line - 1
499 left, right = self.__source[line].split("'''", 1)
500 self.__source[line] = left + '"""' + right
501 while line < len(self.__source):
502 if self.__source[line].rstrip().endswith("'''"):
503 left, right = self.__source[line].rsplit("'''", 1)
504 self.__source[line] = left + '"""' + right
505 break
506 line += 1
507
508 return (
509 1,
510 self.trUtf8(
511 "Triple single quotes converted to triple double quotes."),
512 0)
513
514 def __fixD112(self, code, line, pos):
515 """
516 Private method to fix docstring 'r' or 'u' in leading quotes
517 (D112, D113).
518
519 @param code code of the issue (string)
520 @param line line number of the issue (integer)
521 @param pos position inside line (integer)
522 @return value indicating an applied/deferred fix (-1, 0, 1),
523 a message for the fix (string) and an ID for a deferred
524 fix (integer)
525 """
526 line = line - 1
527 if code == "D112":
528 insertChar = "r"
529 elif code == "D113":
530 insertChar = "u"
531 else:
532 return (0, "", 0)
533
534 newText = self.__getIndent(self.__source[line]) + \
535 insertChar + self.__source[line].lstrip()
536 self.__source[line] = newText
537 return (
538 1,
539 self.trUtf8('Introductory quotes corrected to be {0}"""')
540 .format(insertChar),
541 0)
542
543 def __fixD121(self, code, line, pos, apply=False):
544 """
545 Private method to fix a single line docstring on multiple lines (D121).
546
547 @param code code of the issue (string)
548 @param line line number of the issue (integer)
549 @param pos position inside line (integer)
550 @keyparam apply flag indicating, that the fix should be applied
551 (boolean)
552 @return value indicating an applied/deferred fix (-1, 0, 1),
553 a message for the fix (string) and an ID for a deferred
554 fix (integer)
555 """
556 if apply:
557 line = line - 1
558 if not self.__source[line].lstrip().startswith(
559 ('"""', 'r"""', 'u"""')):
560 # only correctly formatted docstrings will be fixed
561 return (0, "", 0)
562
563 docstring = self.__source[line].rstrip() + \
564 self.__source[line + 1].strip()
565 if docstring.endswith('"""'):
566 docstring += self.__getEol()
567 else:
568 docstring += self.__source[line + 2].lstrip()
569 self.__source[line + 2] = ""
570
571 self.__source[line] = docstring
572 self.__source[line + 1] = ""
573 return (
574 1,
575 self.trUtf8("Single line docstring put on one line."),
576 0)
577 else:
578 id = self.__getID()
579 self.__stack.append((id, code, line, pos))
580 return (-1, "", id)
581
582 def __fixD131(self, code, line, pos):
583 """
584 Private method to fix a docstring summary not ending with a
585 period (D131).
586
587 @param code code of the issue (string)
588 @param line line number of the issue (integer)
589 @param pos position inside line (integer)
590 @return value indicating an applied/deferred fix (-1, 0, 1),
591 a message for the fix (string) and an ID for a deferred
592 fix (integer)
593 """
594 line = line - 1
595 newText = ""
596 if self.__source[line].rstrip().endswith(('"""', "'''")) and \
597 self.__source[line].lstrip().startswith(('"""', 'r"""', 'u"""')):
598 # it is a one-liner
599 newText = self.__source[line].rstrip()[:-3].rstrip() + "." + \
600 self.__source[line].rstrip()[-3:] + self.__getEol()
601 else:
602 if line < len(self.__source) - 1 and \
603 (not self.__source[line + 1].strip() or
604 self.__source[line + 1].lstrip().startswith("@") or
605 (self.__source[line + 1].strip() in ('"""', "'''") and
606 not self.__source[line].lstrip().startswith("@"))):
607 newText = self.__source[line].rstrip() + "." + self.__getEol()
608
609 if newText:
610 self.__source[line] = newText
611 return (1, self.trUtf8("Period added to summary line."), 0)
612 else:
613 return (0, "", 0)
614
615 def __fixD141(self, code, line, pos, apply=False):
616 """
617 Private method to fix a function/method docstring preceded by a
618 blank line (D141).
619
620 @param code code of the issue (string)
621 @param line line number of the issue (integer)
622 @param pos position inside line (integer)
623 @keyparam apply flag indicating, that the fix should be applied
624 (boolean)
625 @return value indicating an applied/deferred fix (-1, 0, 1),
626 a message for the fix (string) and an ID for a deferred
627 fix (integer)
628 """
629 if apply:
630 line = line - 1
631 self.__source[line - 1] = ""
632 return (
633 1,
634 self.trUtf8(
635 "Blank line before function/method docstring removed."),
636 0)
637 else:
638 id = self.__getID()
639 self.__stack.append((id, code, line, pos))
640 return (-1, "", id)
641
642 def __fixD142(self, code, line, pos, apply=False):
643 """
644 Private method to fix a class docstring not preceded by a
645 blank line (D142).
646
647 @param code code of the issue (string)
648 @param line line number of the issue (integer)
649 @param pos position inside line (integer)
650 @keyparam apply flag indicating, that the fix should be applied
651 (boolean)
652 @return value indicating an applied/deferred fix (-1, 0, 1),
653 a message for the fix (string) and an ID for a deferred
654 fix (integer)
655 """
656 if apply:
657 line = line - 1
658 self.__source[line] = self.__getEol() + self.__source[line]
659 return (
660 1,
661 self.trUtf8("Blank line inserted before class docstring."),
662 0)
663 else:
664 id = self.__getID()
665 self.__stack.append((id, code, line, pos))
666 return (-1, "", id)
667
668 def __fixD143(self, code, line, pos, apply=False):
669 """
670 Private method to fix a class docstring not followed by a
671 blank line (D143).
672
673 @param code code of the issue (string)
674 @param line line number of the issue (integer)
675 @param pos position inside line (integer)
676 @keyparam apply flag indicating, that the fix should be applied
677 (boolean)
678 @return value indicating an applied/deferred fix (-1, 0, 1),
679 a message for the fix (string) and an ID for a deferred
680 fix (integer)
681 """
682 if apply:
683 line = line - 1
684 self.__source[line] += self.__getEol()
685 return (
686 1,
687 self.trUtf8("Blank line inserted after class docstring."),
688 0)
689 else:
690 id = self.__getID()
691 self.__stack.append((id, code, line, pos))
692 return (-1, "", id)
693
694 def __fixD144(self, code, line, pos, apply=False):
695 """
696 Private method to fix a docstring summary not followed by a
697 blank line (D144).
698
699 @param code code of the issue (string)
700 @param line line number of the issue (integer)
701 @param pos position inside line (integer)
702 @keyparam apply flag indicating, that the fix should be applied
703 (boolean)
704 @return value indicating an applied/deferred fix (-1, 0, 1),
705 a message for the fix (string) and an ID for a deferred
706 fix (integer)
707 """
708 if apply:
709 line = line - 1
710 if not self.__source[line].rstrip().endswith("."):
711 # only correct summary lines can be fixed here
712 return (0, "", 0)
713
714 self.__source[line] += self.__getEol()
715 return (
716 1,
717 self.trUtf8("Blank line inserted after docstring summary."),
718 0)
719 else:
720 id = self.__getID()
721 self.__stack.append((id, code, line, pos))
722 return (-1, "", id)
723
724 def __fixD145(self, code, line, pos, apply=False):
725 """
726 Private method to fix the last paragraph of a multi-line docstring
727 not followed by a blank line (D143).
728
729 @param code code of the issue (string)
730 @param line line number of the issue (integer)
731 @param pos position inside line (integer)
732 @keyparam apply flag indicating, that the fix should be applied
733 (boolean)
734 @return value indicating an applied/deferred fix (-1, 0, 1),
735 a message for the fix (string) and an ID for a deferred
736 fix (integer)
737 """
738 if apply:
739 line = line - 1
740 self.__source[line] = self.__getEol() + self.__source[line]
741 return (
742 1,
743 self.trUtf8("Blank line inserted after last paragraph"
744 " of docstring."),
745 0)
746 else:
747 id = self.__getID()
748 self.__stack.append((id, code, line, pos))
749 return (-1, "", id)
750
751 def __fixD221(self, code, line, pos, apply=False):
752 """
753 Private method to fix leading and trailing quotes of docstring
754 not on separate lines (D221, D222).
755
756 @param code code of the issue (string)
757 @param line line number of the issue (integer)
758 @param pos position inside line (integer)
759 @keyparam apply flag indicating, that the fix should be applied
760 (boolean)
761 @return value indicating an applied/deferred fix (-1, 0, 1),
762 a message for the fix (string) and an ID for a deferred
763 fix (integer)
764 """
765 if apply:
766 line = line - 1
767 indent = self.__getIndent(self.__source[line])
768 source = self.__source[line].strip()
769 if code == "D221":
770 # leading
771 if source.startswith(("r", "u")):
772 first, second = source[:4], source[4:].strip()
773 else:
774 first, second = source[:3], source[3:].strip()
775 else:
776 # trailing
777 first, second = source[:-3].strip(), source[-3:]
778 newText = indent + first + self.__getEol() + \
779 indent + second + self.__getEol()
780 self.__source[line] = newText
781 if code == "D221":
782 msg = self.trUtf8("Leading quotes put on separate line.")
783 else:
784 msg = self.trUtf8("Trailing quotes put on separate line.")
785 return (1, msg, 0)
786 else:
787 id = self.__getID()
788 self.__stack.append((id, code, line, pos))
789 return (-1, "", id)
790
791 def __fixD242(self, code, line, pos, apply=False):
792 """
793 Private method to fix a class or function/method docstring preceded
794 by a blank line (D242, D244).
795
796 @param code code of the issue (string)
797 @param line line number of the issue (integer)
798 @param pos position inside line (integer)
799 @keyparam apply flag indicating, that the fix should be applied
800 (boolean)
801 @return value indicating an applied/deferred fix (-1, 0, 1),
802 a message for the fix (string) and an ID for a deferred
803 fix (integer)
804 """
805 if apply:
806 line = line - 1
807 self.__source[line - 1] = ""
808 if code == "D242":
809 msg = self.trUtf8("Blank line before class docstring removed.")
810 else:
811 msg = self.trUtf8(
812 "Blank line before function/method docstring removed.")
813 return (1, msg, 0)
814 else:
815 id = self.__getID()
816 self.__stack.append((id, code, line, pos))
817 return (-1, "", id)
818
819 def __fixD243(self, code, line, pos, apply=False):
820 """
821 Private method to fix a class or function/method docstring followed
822 by a blank line (D243, D245).
823
824 @param code code of the issue (string)
825 @param line line number of the issue (integer)
826 @param pos position inside line (integer)
827 @keyparam apply flag indicating, that the fix should be applied
828 (boolean)
829 @return value indicating an applied/deferred fix (-1, 0, 1),
830 a message for the fix (string) and an ID for a deferred
831 fix (integer)
832 """
833 if apply:
834 line = line - 1
835 self.__source[line + 1] = ""
836 if code == "D243":
837 msg = self.trUtf8("Blank line after class docstring removed.")
838 else:
839 msg = self.trUtf8(
840 "Blank line after function/method docstring removed.")
841 return (1, msg, 0)
842 else:
843 id = self.__getID()
844 self.__stack.append((id, code, line, pos))
845 return (-1, "", id)
846
847 def __fixD247(self, code, line, pos, apply=False):
848 """
849 Private method to fix a last paragraph of a docstring followed
850 by a blank line (D247).
851
852 @param code code of the issue (string)
853 @param line line number of the issue (integer)
854 @param pos position inside line (integer)
855 @keyparam apply flag indicating, that the fix should be applied
856 (boolean)
857 @return value indicating an applied/deferred fix (-1, 0, 1),
858 a message for the fix (string) and an ID for a deferred
859 fix (integer)
860 """
861 if apply:
862 line = line - 1
863 self.__source[line - 1] = ""
864 return (
865 1,
866 self.trUtf8("Blank line after last paragraph removed."),
867 0)
868 else:
869 id = self.__getID()
870 self.__stack.append((id, code, line, pos))
871 return (-1, "", id)
872
437 def __fixE101(self, code, line, pos): 873 def __fixE101(self, code, line, pos):
438 """ 874 """
439 Private method to fix obsolete tab usage and indentation errors 875 Private method to fix obsolete tab usage and indentation errors
440 (E101, E111, W191). 876 (E101, E111, W191).
441 877
442 @param code code of the issue (string) 878 @param code code of the issue (string)
443 @param line line number of the issue (integer) 879 @param line line number of the issue (integer)
444 @param pos position inside line (integer) 880 @param pos position inside line (integer)
445 @return flag indicating an applied fix (boolean) and a message for 881 @return value indicating an applied/deferred fix (-1, 0, 1),
446 the fix (string) 882 a message for the fix (string) and an ID for a deferred
883 fix (integer)
447 """ 884 """
448 if self.__reindenter is None: 885 if self.__reindenter is None:
449 self.__reindenter = Pep8Reindenter(self.__source) 886 self.__reindenter = Pep8Reindenter(self.__source)
450 self.__reindenter.run() 887 self.__reindenter.run()
451 fixedLine = self.__reindenter.fixedLine(line - 1) 888 fixedLine = self.__reindenter.fixedLine(line - 1)
452 if fixedLine is not None: 889 if fixedLine is not None and fixedLine != self.__source[line - 1]:
453 self.__source[line - 1] = fixedLine 890 self.__source[line - 1] = fixedLine
454 if code in ["E101", "W191"]: 891 if code in ["E101", "W191"]:
455 msg = self.trUtf8("Tab converted to 4 spaces.") 892 msg = self.trUtf8("Tab converted to 4 spaces.")
456 else: 893 else:
457 msg = self.trUtf8( 894 msg = self.trUtf8(
458 "Indentation adjusted to be a multiple of four.") 895 "Indentation adjusted to be a multiple of four.")
459 return (True, msg) 896 return (1, msg, 0)
460 else: 897 else:
461 return (False, self.trUtf8("Fix for {0} failed.").format(code)) 898 return (0, "", 0)
462 899
463 def __fixE121(self, code, line, pos, apply=False): 900 def __fixE121(self, code, line, pos, apply=False):
464 """ 901 """
465 Private method to fix the indentation of continuation lines and 902 Private method to fix the indentation of continuation lines and
466 closing brackets (E121,E124). 903 closing brackets (E121, E124).
467 904
468 @param code code of the issue (string) 905 @param code code of the issue (string)
469 @param line line number of the issue (integer) 906 @param line line number of the issue (integer)
470 @param pos position inside line (integer) 907 @param pos position inside line (integer)
471 @keyparam apply flag indicating, that the fix should be applied 908 @keyparam apply flag indicating, that the fix should be applied
472 (boolean) 909 (boolean)
473 @return flag indicating an applied fix (boolean) and a message for 910 @return value indicating an applied/deferred fix (-1, 0, 1),
474 the fix (string) 911 a message for the fix (string) and an ID for a deferred
912 fix (integer)
475 """ 913 """
476 if apply: 914 if apply:
477 logical = self.__getLogical(line, pos) 915 logical = self.__getLogical(line, pos)
478 if logical: 916 if logical:
479 # Fix by adjusting initial indent level. 917 # Fix by adjusting initial indent level.
480 self.__fixReindent(line, pos, logical) 918 changed = self.__fixReindent(line, pos, logical)
481 else: 919 if changed:
482 self.__stackLogical.append((code, line, pos)) 920 if code == "E121":
483 if code == "E121": 921 msg = self.trUtf8(
484 msg = self.trUtf8("Indentation of continuation line corrected.") 922 "Indentation of continuation line corrected.")
485 elif code == "E124": 923 elif code == "E124":
486 msg = self.trUtf8("Indentation of closing bracket corrected.") 924 msg = self.trUtf8(
487 return (True, msg) 925 "Indentation of closing bracket corrected.")
926 return (1, msg, 0)
927 return (0, "", 0)
928 else:
929 id = self.__getID()
930 self.__stackLogical.append((id, code, line, pos))
931 return (-1, "", id)
488 932
489 def __fixE122(self, code, line, pos, apply=False): 933 def __fixE122(self, code, line, pos, apply=False):
490 """ 934 """
491 Private method to fix a missing indentation of continuation lines 935 Private method to fix a missing indentation of continuation lines
492 (E122). 936 (E122).
494 @param code code of the issue (string) 938 @param code code of the issue (string)
495 @param line line number of the issue (integer) 939 @param line line number of the issue (integer)
496 @param pos position inside line (integer) 940 @param pos position inside line (integer)
497 @keyparam apply flag indicating, that the fix should be applied 941 @keyparam apply flag indicating, that the fix should be applied
498 (boolean) 942 (boolean)
499 @return flag indicating an applied fix (boolean) and a message for 943 @return value indicating an applied/deferred fix (-1, 0, 1),
500 the fix (string) 944 a message for the fix (string) and an ID for a deferred
945 fix (integer)
501 """ 946 """
502 if apply: 947 if apply:
503 logical = self.__getLogical(line, pos) 948 logical = self.__getLogical(line, pos)
504 if logical: 949 if logical:
505 # Fix by adding an initial indent. 950 # Fix by adding an initial indent.
509 line = line - 1 954 line = line - 1
510 text = self.__source[line] 955 text = self.__source[line]
511 indentation = self.__getIndent(text) 956 indentation = self.__getIndent(text)
512 self.__source[line] = indentation + \ 957 self.__source[line] = indentation + \
513 self.__indentWord + text.lstrip() 958 self.__indentWord + text.lstrip()
514 else: 959 return (
515 self.__stackLogical.append((code, line, pos)) 960 1,
516 return ( 961 self.trUtf8(
517 True, 962 "Missing indentation of continuation line corrected."),
518 self.trUtf8("Missing indentation of continuation line corrected.")) 963 0)
964 return (0, "", 0)
965 else:
966 id = self.__getID()
967 self.__stackLogical.append((id, code, line, pos))
968 return (-1, "", id)
519 969
520 def __fixE123(self, code, line, pos, apply=False): 970 def __fixE123(self, code, line, pos, apply=False):
521 """ 971 """
522 Private method to fix the indentation of a closing bracket lines 972 Private method to fix the indentation of a closing bracket lines
523 (E123). 973 (E123).
525 @param code code of the issue (string) 975 @param code code of the issue (string)
526 @param line line number of the issue (integer) 976 @param line line number of the issue (integer)
527 @param pos position inside line (integer) 977 @param pos position inside line (integer)
528 @keyparam apply flag indicating, that the fix should be applied 978 @keyparam apply flag indicating, that the fix should be applied
529 (boolean) 979 (boolean)
530 @return flag indicating an applied fix (boolean) and a message for 980 @return value indicating an applied/deferred fix (-1, 0, 1),
531 the fix (string) 981 a message for the fix (string) and an ID for a deferred
982 fix (integer)
532 """ 983 """
533 if apply: 984 if apply:
534 logical = self.__getLogical(line, pos) 985 logical = self.__getLogical(line, pos)
535 if logical: 986 if logical:
536 # Fix by deleting whitespace to the correct level. 987 # Fix by deleting whitespace to the correct level.
538 row = line - 1 989 row = line - 1
539 text = self.__source[row] 990 text = self.__source[row]
540 newText = self.__getIndent(logicalLines[0]) + text.lstrip() 991 newText = self.__getIndent(logicalLines[0]) + text.lstrip()
541 if newText == text: 992 if newText == text:
542 # fall back to slower method 993 # fall back to slower method
543 self.__fixReindent(line, pos, logical) 994 changed = self.__fixReindent(line, pos, logical)
544 else: 995 else:
545 self.__source[row] = newText 996 self.__source[row] = newText
546 else: 997 changed = True
547 self.__stackLogical.append((code, line, pos)) 998 if changed:
548 return ( 999 return (1, self.trUtf8(
549 True, self.trUtf8("Closing bracket aligned to opening bracket.")) 1000 "Closing bracket aligned to opening bracket."),
1001 0)
1002 return (0, "", 0)
1003 else:
1004 id = self.__getID()
1005 self.__stackLogical.append((id, code, line, pos))
1006 return (-1, "", id)
550 1007
551 def __fixE125(self, code, line, pos, apply=False): 1008 def __fixE125(self, code, line, pos, apply=False):
552 """ 1009 """
553 Private method to fix the indentation of continuation lines not 1010 Private method to fix the indentation of continuation lines not
554 distinguishable from next logical line (E125). 1011 distinguishable from next logical line (E125).
556 @param code code of the issue (string) 1013 @param code code of the issue (string)
557 @param line line number of the issue (integer) 1014 @param line line number of the issue (integer)
558 @param pos position inside line (integer) 1015 @param pos position inside line (integer)
559 @keyparam apply flag indicating, that the fix should be applied 1016 @keyparam apply flag indicating, that the fix should be applied
560 (boolean) 1017 (boolean)
561 @return flag indicating an applied fix (boolean) and a message for 1018 @return value indicating an applied/deferred fix (-1, 0, 1),
562 the fix (string) 1019 a message for the fix (string) and an ID for a deferred
1020 fix (integer)
563 """ 1021 """
564 if apply: 1022 if apply:
565 logical = self.__getLogical(line, pos) 1023 logical = self.__getLogical(line, pos)
566 if logical: 1024 if logical:
567 # Fix by adjusting initial indent level. 1025 # Fix by adjusting initial indent level.
569 if not modified: 1027 if not modified:
570 row = line - 1 1028 row = line - 1
571 text = self.__source[row] 1029 text = self.__source[row]
572 self.__source[row] = self.__getIndent(text) + \ 1030 self.__source[row] = self.__getIndent(text) + \
573 self.__indentWord + text.lstrip() 1031 self.__indentWord + text.lstrip()
574 else: 1032 return (1, self.trUtf8("Indentation level changed."), 0)
575 self.__stackLogical.append((code, line, pos)) 1033 return (0, "", 0)
576 return (True, self.trUtf8("Indentation level changed.")) 1034 else:
1035 id = self.__getID()
1036 self.__stackLogical.append((id, code, line, pos))
1037 return (-1, "", id)
577 1038
578 def __fixE126(self, code, line, pos, apply=False): 1039 def __fixE126(self, code, line, pos, apply=False):
579 """ 1040 """
580 Private method to fix over-indented/under-indented hanging 1041 Private method to fix over-indented/under-indented hanging
581 indentation (E126, E133). 1042 indentation (E126, E133).
583 @param code code of the issue (string) 1044 @param code code of the issue (string)
584 @param line line number of the issue (integer) 1045 @param line line number of the issue (integer)
585 @param pos position inside line (integer) 1046 @param pos position inside line (integer)
586 @keyparam apply flag indicating, that the fix should be applied 1047 @keyparam apply flag indicating, that the fix should be applied
587 (boolean) 1048 (boolean)
588 @return flag indicating an applied fix (boolean) and a message for 1049 @return value indicating an applied/deferred fix (-1, 0, 1),
589 the fix (string) 1050 a message for the fix (string) and an ID for a deferred
1051 fix (integer)
590 """ 1052 """
591 if apply: 1053 if apply:
592 logical = self.__getLogical(line, pos) 1054 logical = self.__getLogical(line, pos)
593 if logical: 1055 if logical:
594 # Fix by deleting whitespace to the left. 1056 # Fix by deleting whitespace to the left.
597 text = self.__source[row] 1059 text = self.__source[row]
598 newText = self.__getIndent(logicalLines[0]) + \ 1060 newText = self.__getIndent(logicalLines[0]) + \
599 self.__indentWord + text.lstrip() 1061 self.__indentWord + text.lstrip()
600 if newText == text: 1062 if newText == text:
601 # fall back to slower method 1063 # fall back to slower method
602 self.__fixReindent(line, pos, logical) 1064 changed = self.__fixReindent(line, pos, logical)
603 else: 1065 else:
604 self.__source[row] = newText 1066 self.__source[row] = newText
605 else: 1067 changed = True
606 self.__stackLogical.append((code, line, pos)) 1068 if changed:
607 return ( 1069 return (1, self.trUtf8(
608 True, 1070 "Indentation level of hanging indentation changed."),
609 self.trUtf8("Indentation level of hanging indentation changed.")) 1071 0)
1072 return (0, "", 0)
1073 else:
1074 id = self.__getID()
1075 self.__stackLogical.append((id, code, line, pos))
1076 return (-1, "", id)
610 1077
611 def __fixE127(self, code, line, pos, apply=False): 1078 def __fixE127(self, code, line, pos, apply=False):
612 """ 1079 """
613 Private method to fix over/under indented lines (E127, E128). 1080 Private method to fix over/under indented lines (E127, E128).
614 1081
615 @param code code of the issue (string) 1082 @param code code of the issue (string)
616 @param line line number of the issue (integer) 1083 @param line line number of the issue (integer)
617 @param pos position inside line (integer) 1084 @param pos position inside line (integer)
618 @keyparam apply flag indicating, that the fix should be applied 1085 @keyparam apply flag indicating, that the fix should be applied
619 (boolean) 1086 (boolean)
620 @return flag indicating an applied fix (boolean) and a message for 1087 @return value indicating an applied/deferred fix (-1, 0, 1),
621 the fix (string) 1088 a message for the fix (string) and an ID for a deferred
1089 fix (integer)
622 """ 1090 """
623 if apply: 1091 if apply:
624 logical = self.__getLogical(line, pos) 1092 logical = self.__getLogical(line, pos)
625 if logical: 1093 if logical:
626 # Fix by inserting/deleting whitespace to the correct level. 1094 # Fix by inserting/deleting whitespace to the correct level.
645 if startIndex is not None: 1113 if startIndex is not None:
646 newText = startIndex * ' ' + text.lstrip() 1114 newText = startIndex * ' ' + text.lstrip()
647 1115
648 if newText == text: 1116 if newText == text:
649 # fall back to slower method 1117 # fall back to slower method
650 self.__fixReindent(line, pos, logical) 1118 changed = self.__fixReindent(line, pos, logical)
651 else: 1119 else:
652 self.__source[row] = newText 1120 self.__source[row] = newText
653 else: 1121 changed = True
654 self.__stackLogical.append((code, line, pos)) 1122 if changed:
655 return (True, self.trUtf8("Visual indentation corrected.")) 1123 return (1, self.trUtf8("Visual indentation corrected."), 0)
1124 return (0, "", 0)
1125 else:
1126 id = self.__getID()
1127 self.__stackLogical.append((id, code, line, pos))
1128 return (-1, "", id)
656 1129
657 def __fixE201(self, code, line, pos): 1130 def __fixE201(self, code, line, pos):
658 """ 1131 """
659 Private method to fix extraneous whitespace (E201, E202, 1132 Private method to fix extraneous whitespace (E201, E202,
660 E203, E211). 1133 E203, E211).
661 1134
662 @param code code of the issue (string) 1135 @param code code of the issue (string)
663 @param line line number of the issue (integer) 1136 @param line line number of the issue (integer)
664 @param pos position inside line (integer) 1137 @param pos position inside line (integer)
665 @return flag indicating an applied fix (boolean) and a message for 1138 @return value indicating an applied/deferred fix (-1, 0, 1),
666 the fix (string) 1139 a message for the fix (string) and an ID for a deferred
1140 fix (integer)
667 """ 1141 """
668 line = line - 1 1142 line = line - 1
669 text = self.__source[line] 1143 text = self.__source[line]
670 1144
671 if '"""' in text or "'''" in text or text.rstrip().endswith('\\'): 1145 if '"""' in text or "'''" in text or text.rstrip().endswith('\\'):
672 return ( 1146 return (0, "", 0)
673 False, self.trUtf8("Extraneous whitespace cannot be removed."))
674 1147
675 newText = self.__fixWhitespace(text, pos, '') 1148 newText = self.__fixWhitespace(text, pos, '')
676 if newText == text: 1149 if newText == text:
677 return (False, "") 1150 return (0, "", 0)
678 1151
679 self.__source[line] = newText 1152 self.__source[line] = newText
680 return (True, self.trUtf8("Extraneous whitespace removed.")) 1153 return (1, self.trUtf8("Extraneous whitespace removed."), 0)
681 1154
682 def __fixE221(self, code, line, pos): 1155 def __fixE221(self, code, line, pos):
683 """ 1156 """
684 Private method to fix extraneous whitespace around operator or 1157 Private method to fix extraneous whitespace around operator or
685 keyword (E221, E222, E223, E224, E225, E226, E227, E228, E241, 1158 keyword (E221, E222, E223, E224, E225, E226, E227, E228, E241,
686 E242, E271, E272, E273, E274). 1159 E242, E271, E272, E273, E274).
687 1160
688 @param code code of the issue (string) 1161 @param code code of the issue (string)
689 @param line line number of the issue (integer) 1162 @param line line number of the issue (integer)
690 @param pos position inside line (integer) 1163 @param pos position inside line (integer)
691 @return flag indicating an applied fix (boolean) and a message for 1164 @return value indicating an applied/deferred fix (-1, 0, 1),
692 the fix (string) 1165 a message for the fix (string) and an ID for a deferred
1166 fix (integer)
693 """ 1167 """
694 line = line - 1 1168 line = line - 1
695 text = self.__source[line] 1169 text = self.__source[line]
696 1170
697 if '"""' in text or "'''" in text or text.rstrip().endswith('\\'): 1171 if '"""' in text or "'''" in text or text.rstrip().endswith('\\'):
698 return ( 1172 return (0, "", 0)
699 False, self.trUtf8("Extraneous whitespace cannot be removed."))
700 1173
701 newText = self.__fixWhitespace(text, pos, ' ') 1174 newText = self.__fixWhitespace(text, pos, ' ')
702 if newText == text: 1175 if newText == text:
703 return (False, "") 1176 return (0, "", 0)
704 1177
705 self.__source[line] = newText 1178 self.__source[line] = newText
706 if code in ["E225", "E226", "E227", "E228"]: 1179 if code in ["E225", "E226", "E227", "E228"]:
707 return (True, self.trUtf8("Missing whitespace added.")) 1180 return (1, self.trUtf8("Missing whitespace added."), 0)
708 else: 1181 else:
709 return (True, self.trUtf8("Extraneous whitespace removed.")) 1182 return (1, self.trUtf8("Extraneous whitespace removed."), 0)
710 1183
711 def __fixE231(self, code, line, pos): 1184 def __fixE231(self, code, line, pos):
712 """ 1185 """
713 Private method to fix missing whitespace after ',;:'. 1186 Private method to fix missing whitespace after ',;:'.
714 1187
715 @param code code of the issue (string) 1188 @param code code of the issue (string)
716 @param line line number of the issue (integer) 1189 @param line line number of the issue (integer)
717 @param pos position inside line (integer) 1190 @param pos position inside line (integer)
718 @return flag indicating an applied fix (boolean) and a message for 1191 @return value indicating an applied/deferred fix (-1, 0, 1),
719 the fix (string) 1192 a message for the fix (string) and an ID for a deferred
1193 fix (integer)
720 """ 1194 """
721 line = line - 1 1195 line = line - 1
722 pos = pos + 1 1196 pos = pos + 1
723 self.__source[line] = self.__source[line][:pos] + \ 1197 self.__source[line] = self.__source[line][:pos] + \
724 " " + \ 1198 " " + self.__source[line][pos:]
725 self.__source[line][pos:] 1199 return (1, self.trUtf8("Missing whitespace added."), 0)
726 return (True, self.trUtf8("Missing whitespace added."))
727 1200
728 def __fixE251(self, code, line, pos): 1201 def __fixE251(self, code, line, pos):
729 """ 1202 """
730 Private method to fix extraneous whitespace around keyword and 1203 Private method to fix extraneous whitespace around keyword and
731 default parameter equals (E251). 1204 default parameter equals (E251).
732 1205
733 @param code code of the issue (string) 1206 @param code code of the issue (string)
734 @param line line number of the issue (integer) 1207 @param line line number of the issue (integer)
735 @param pos position inside line (integer) 1208 @param pos position inside line (integer)
736 @return flag indicating an applied fix (boolean) and a message for 1209 @return value indicating an applied/deferred fix (-1, 0, 1),
737 the fix (string) 1210 a message for the fix (string) and an ID for a deferred
1211 fix (integer)
738 """ 1212 """
739 line = line - 1 1213 line = line - 1
740 text = self.__source[line] 1214 text = self.__source[line]
741 1215
742 # This is necessary since pep8 sometimes reports columns that goes 1216 # This is necessary since pep8 sometimes reports columns that goes
755 if newText.endswith(('=\\\n', '=\\\r\n', '=\\\r')): 1229 if newText.endswith(('=\\\n', '=\\\r\n', '=\\\r')):
756 self.__source[line] = newText.rstrip("\n\r \t\\") 1230 self.__source[line] = newText.rstrip("\n\r \t\\")
757 self.__source[line + 1] = self.__source[line + 1].lstrip() 1231 self.__source[line + 1] = self.__source[line + 1].lstrip()
758 else: 1232 else:
759 self.__source[line] = newText 1233 self.__source[line] = newText
760 return (True, self.trUtf8("Extraneous whitespace removed.")) 1234 return (1, self.trUtf8("Extraneous whitespace removed."), 0)
761 1235
762 def __fixE261(self, code, line, pos): 1236 def __fixE261(self, code, line, pos):
763 """ 1237 """
764 Private method to fix whitespace before or after inline comment 1238 Private method to fix whitespace before or after inline comment
765 (E261, E262). 1239 (E261, E262).
766 1240
767 @param code code of the issue (string) 1241 @param code code of the issue (string)
768 @param line line number of the issue (integer) 1242 @param line line number of the issue (integer)
769 @param pos position inside line (integer) 1243 @param pos position inside line (integer)
770 @return flag indicating an applied fix (boolean) and a message for 1244 @return value indicating an applied/deferred fix (-1, 0, 1),
771 the fix (string) 1245 a message for the fix (string) and an ID for a deferred
1246 fix (integer)
772 """ 1247 """
773 line = line - 1 1248 line = line - 1
774 text = self.__source[line] 1249 text = self.__source[line]
775 left = text[:pos].rstrip(' \t#') 1250 left = text[:pos].rstrip(' \t#')
776 right = text[pos:].lstrip(' \t#') 1251 right = text[pos:].lstrip(' \t#')
777 newText = left + (" # " + right if right.strip() else right) 1252 newText = left + (" # " + right if right.strip() else right)
778 self.__source[line] = newText 1253 self.__source[line] = newText
779 return (True, self.trUtf8("Whitespace around comment sign corrected.")) 1254 return (1, self.trUtf8("Whitespace around comment sign corrected."), 0)
780 1255
781 def __fixE301(self, code, line, pos, apply=False): 1256 def __fixE301(self, code, line, pos, apply=False):
782 """ 1257 """
783 Private method to fix the need for one blank line (E301). 1258 Private method to fix the need for one blank line (E301).
784 1259
785 @param code code of the issue (string) 1260 @param code code of the issue (string)
786 @param line line number of the issue (integer) 1261 @param line line number of the issue (integer)
787 @param pos position inside line (integer) 1262 @param pos position inside line (integer)
788 @keyparam apply flag indicating, that the fix should be applied 1263 @keyparam apply flag indicating, that the fix should be applied
789 (boolean) 1264 (boolean)
790 @return flag indicating an applied fix (boolean) and a message for 1265 @return value indicating an applied/deferred fix (-1, 0, 1),
791 the fix (string) 1266 a message for the fix (string) and an ID for a deferred
1267 fix (integer)
792 """ 1268 """
793 if apply: 1269 if apply:
794 self.__source.insert(line - 1, self.__getEol()) 1270 self.__source.insert(line - 1, self.__getEol())
795 else: 1271 return (1, self.trUtf8("One blank line inserted."), 0)
796 self.__stack.append((code, line, pos)) 1272 else:
797 return (True, self.trUtf8("One blank line inserted.")) 1273 id = self.__getID()
1274 self.__stack.append((id, code, line, pos))
1275 return (-1, "", id)
798 1276
799 def __fixE302(self, code, line, pos, apply=False): 1277 def __fixE302(self, code, line, pos, apply=False):
800 """ 1278 """
801 Private method to fix the need for two blank lines (E302). 1279 Private method to fix the need for two blank lines (E302).
802 1280
803 @param code code of the issue (string) 1281 @param code code of the issue (string)
804 @param line line number of the issue (integer) 1282 @param line line number of the issue (integer)
805 @param pos position inside line (integer) 1283 @param pos position inside line (integer)
806 @keyparam apply flag indicating, that the fix should be applied 1284 @keyparam apply flag indicating, that the fix should be applied
807 (boolean) 1285 (boolean)
808 @return flag indicating an applied fix (boolean) and a message for 1286 @return value indicating an applied/deferred fix (-1, 0, 1),
809 the fix (string) 1287 a message for the fix (string) and an ID for a deferred
810 """ 1288 fix (integer)
811 # count blank lines 1289 """
812 index = line - 1
813 blanks = 0
814 while index:
815 if self.__source[index - 1].strip() == "":
816 blanks += 1
817 index -= 1
818 else:
819 break
820 delta = blanks - 2
821
822 if apply: 1290 if apply:
1291 # count blank lines
1292 index = line - 1
1293 blanks = 0
1294 while index:
1295 if self.__source[index - 1].strip() == "":
1296 blanks += 1
1297 index -= 1
1298 else:
1299 break
1300 delta = blanks - 2
1301
823 line -= 1 1302 line -= 1
824 if delta < 0: 1303 if delta < 0:
825 # insert blank lines (one or two) 1304 # insert blank lines (one or two)
826 while delta < 0: 1305 while delta < 0:
827 self.__source.insert(line, self.__getEol()) 1306 self.__source.insert(line, self.__getEol())
828 delta += 1 1307 delta += 1
1308 changed = True
829 elif delta > 0: 1309 elif delta > 0:
830 # delete superfluous blank lines 1310 # delete superfluous blank lines
831 while delta > 0: 1311 while delta > 0:
832 del self.__source[line - 1] 1312 del self.__source[line - 1]
833 line -= 1 1313 line -= 1
834 delta -= 1 1314 delta -= 1
835 else: 1315 changed = True
836 self.__stack.append((code, line, pos)) 1316 else:
837 1317 changed = False
838 if delta < 0: 1318
839 msg = self.trUtf8("%n blank line(s) inserted.", "", -delta) 1319 if changed:
840 elif delta > 0: 1320 if delta < 0:
841 msg = self.trUtf8("%n superfluous lines removed", "", delta) 1321 msg = self.trUtf8(
842 else: 1322 "%n blank line(s) inserted.", "", -delta)
843 msg = "" 1323 elif delta > 0:
844 return (True, msg) 1324 msg = self.trUtf8(
1325 "%n superfluous lines removed", "", delta)
1326 else:
1327 msg = ""
1328 return (1, msg, 0)
1329 return (0, "", 0)
1330 else:
1331 id = self.__getID()
1332 self.__stack.append((id, code, line, pos))
1333 return (-1, "", id)
845 1334
846 def __fixE303(self, code, line, pos, apply=False): 1335 def __fixE303(self, code, line, pos, apply=False):
847 """ 1336 """
848 Private method to fix superfluous blank lines (E303). 1337 Private method to fix superfluous blank lines (E303).
849 1338
850 @param code code of the issue (string) 1339 @param code code of the issue (string)
851 @param line line number of the issue (integer) 1340 @param line line number of the issue (integer)
852 @param pos position inside line (integer) 1341 @param pos position inside line (integer)
853 @keyparam apply flag indicating, that the fix should be applied 1342 @keyparam apply flag indicating, that the fix should be applied
854 (boolean) 1343 (boolean)
855 @return flag indicating an applied fix (boolean) and a message for 1344 @return value indicating an applied/deferred fix (-1, 0, 1),
856 the fix (string) 1345 a message for the fix (string) and an ID for a deferred
1346 fix (integer)
857 """ 1347 """
858 if apply: 1348 if apply:
859 index = line - 3 1349 index = line - 3
860 while index: 1350 while index:
861 if self.__source[index].strip() == "": 1351 if self.__source[index].strip() == "":
862 del self.__source[index] 1352 del self.__source[index]
863 index -= 1 1353 index -= 1
864 else: 1354 else:
865 break 1355 break
866 else: 1356 return (1, self.trUtf8("Superfluous blank lines removed."), 0)
867 self.__stack.append((code, line, pos)) 1357 else:
868 return (True, self.trUtf8("Superfluous blank lines removed.")) 1358 id = self.__getID()
1359 self.__stack.append((id, code, line, pos))
1360 return (-1, "", id)
869 1361
870 def __fixE304(self, code, line, pos, apply=False): 1362 def __fixE304(self, code, line, pos, apply=False):
871 """ 1363 """
872 Private method to fix superfluous blank lines after a function 1364 Private method to fix superfluous blank lines after a function
873 decorator (E304). 1365 decorator (E304).
875 @param code code of the issue (string) 1367 @param code code of the issue (string)
876 @param line line number of the issue (integer) 1368 @param line line number of the issue (integer)
877 @param pos position inside line (integer) 1369 @param pos position inside line (integer)
878 @keyparam apply flag indicating, that the fix should be applied 1370 @keyparam apply flag indicating, that the fix should be applied
879 (boolean) 1371 (boolean)
880 @return flag indicating an applied fix (boolean) and a message for 1372 @return value indicating an applied/deferred fix (-1, 0, 1),
881 the fix (string) 1373 a message for the fix (string) and an ID for a deferred
1374 fix (integer)
882 """ 1375 """
883 if apply: 1376 if apply:
884 index = line - 2 1377 index = line - 2
885 while index: 1378 while index:
886 if self.__source[index].strip() == "": 1379 if self.__source[index].strip() == "":
887 del self.__source[index] 1380 del self.__source[index]
888 index -= 1 1381 index -= 1
889 else: 1382 else:
890 break 1383 break
891 else: 1384 return (1, self.trUtf8(
892 self.__stack.append((code, line, pos)) 1385 "Superfluous blank lines after function decorator removed."),
893 return (True, self.trUtf8( 1386 0)
894 "Superfluous blank lines after function decorator removed.")) 1387 else:
1388 id = self.__getID()
1389 self.__stack.append((id, code, line, pos))
1390 return (-1, "", id)
895 1391
896 def __fixE401(self, code, line, pos, apply=False): 1392 def __fixE401(self, code, line, pos, apply=False):
897 """ 1393 """
898 Private method to fix multiple imports on one line (E401). 1394 Private method to fix multiple imports on one line (E401).
899 1395
900 @param code code of the issue (string) 1396 @param code code of the issue (string)
901 @param line line number of the issue (integer) 1397 @param line line number of the issue (integer)
902 @param pos position inside line (integer) 1398 @param pos position inside line (integer)
903 @keyparam apply flag indicating, that the fix should be applied 1399 @keyparam apply flag indicating, that the fix should be applied
904 (boolean) 1400 (boolean)
905 @return flag indicating an applied fix (boolean) and a message for 1401 @return value indicating an applied/deferred fix (-1, 0, 1),
906 the fix (string) 1402 a message for the fix (string) and an ID for a deferred
1403 fix (integer)
907 """ 1404 """
908 if apply: 1405 if apply:
909 line = line - 1 1406 line = line - 1
910 text = self.__source[line] 1407 text = self.__source[line]
911 if not text.lstrip().startswith("import"): 1408 if not text.lstrip().startswith("import"):
912 return (False, "") 1409 return (0, "", 0)
913 1410
914 # pep8 (1.3.1) reports false positive if there is an import 1411 # pep8 (1.3.1) reports false positive if there is an import
915 # statement followed by a semicolon and some unrelated 1412 # statement followed by a semicolon and some unrelated
916 # statement with commas in it. 1413 # statement with commas in it.
917 if ';' in text: 1414 if ';' in text:
918 return (False, "") 1415 return (0, "", 0)
919 1416
920 newText = text[:pos].rstrip("\t ,") + self.__getEol() + \ 1417 newText = text[:pos].rstrip("\t ,") + self.__getEol() + \
921 self.__getIndent(text) + "import " + text[pos:].lstrip("\t ,") 1418 self.__getIndent(text) + "import " + text[pos:].lstrip("\t ,")
922 self.__source[line] = newText 1419 self.__source[line] = newText
923 else: 1420 return (1, self.trUtf8("Imports were put on separate lines."), 0)
924 self.__stack.append((code, line, pos)) 1421 else:
925 return (True, self.trUtf8("Imports were put on separate lines.")) 1422 id = self.__getID()
1423 self.__stack.append((id, code, line, pos))
1424 return (-1, "", id)
926 1425
927 def __fixE501(self, code, line, pos, apply=False): 1426 def __fixE501(self, code, line, pos, apply=False):
928 """ 1427 """
929 Private method to fix the long lines by breaking them (E501). 1428 Private method to fix the long lines by breaking them (E501).
930 1429
931 @param code code of the issue (string) 1430 @param code code of the issue (string)
932 @param line line number of the issue (integer) 1431 @param line line number of the issue (integer)
933 @param pos position inside line (integer) 1432 @param pos position inside line (integer)
934 @keyparam apply flag indicating, that the fix should be applied 1433 @keyparam apply flag indicating, that the fix should be applied
935 (boolean) 1434 (boolean)
936 @return flag indicating an applied fix (boolean) and a message for 1435 @return value indicating an applied/deferred fix (-1, 0, 1),
937 the fix (string) 1436 a message for the fix (string) and an ID for a deferred
1437 fix (integer)
938 """ 1438 """
939 multilineStringLines, docStringLines = self.__multilineStringLines() 1439 multilineStringLines, docStringLines = self.__multilineStringLines()
940 if apply: 1440 if apply:
941 isDocString = line in docStringLines 1441 isDocString = line in docStringLines
942 line = line - 1 1442 line = line - 1
947 prevText = "" 1447 prevText = ""
948 if line < len(self.__source) - 1: 1448 if line < len(self.__source) - 1:
949 nextText = self.__source[line + 1] 1449 nextText = self.__source[line + 1]
950 else: 1450 else:
951 nextText = "" 1451 nextText = ""
952 shortener = Pep8LineShortener(text, prevText, nextText, 1452 shortener = Pep8LineShortener(
953 maxLength=self.__maxLineLength, eol=self.__getEol(), 1453 text, prevText, nextText,
954 indentWord=self.__indentWord, isDocString=isDocString) 1454 maxLength=self.__maxLineLength, eol=self.__getEol(),
1455 indentWord=self.__indentWord, isDocString=isDocString)
955 changed, newText, newNextText = shortener.shorten() 1456 changed, newText, newNextText = shortener.shorten()
956 if changed: 1457 if changed:
957 if newText != text: 1458 if newText != text:
958 self.__source[line] = newText 1459 self.__source[line] = newText
959 if newNextText and newNextText != nextText: 1460 if newNextText and newNextText != nextText:
960 self.__source[line + 1] = newNextText 1461 self.__source[line + 1] = newNextText
961 else: 1462 return (1, self.trUtf8("Long lines have been shortened."), 0)
962 self.__stack.append((code, line, pos)) 1463 else:
963 return (True, self.trUtf8("Long lines have been shortened.")) 1464 return (0, "", 0)
1465 else:
1466 id = self.__getID()
1467 self.__stack.append((id, code, line, pos))
1468 return (-1, "", id)
964 1469
965 def __fixE502(self, code, line, pos): 1470 def __fixE502(self, code, line, pos):
966 """ 1471 """
967 Private method to fix redundant backslash within brackets (E502). 1472 Private method to fix redundant backslash within brackets (E502).
968 1473
969 @param code code of the issue (string) 1474 @param code code of the issue (string)
970 @param line line number of the issue (integer) 1475 @param line line number of the issue (integer)
971 @param pos position inside line (integer) 1476 @param pos position inside line (integer)
972 @return flag indicating an applied fix (boolean) and a message for 1477 @return value indicating an applied/deferred fix (-1, 0, 1),
973 the fix (string) 1478 a message for the fix (string) and an ID for a deferred
1479 fix (integer)
974 """ 1480 """
975 self.__source[line - 1] = \ 1481 self.__source[line - 1] = \
976 self.__source[line - 1].rstrip("\n\r \t\\") + self.__getEol() 1482 self.__source[line - 1].rstrip("\n\r \t\\") + self.__getEol()
977 return (True, self.trUtf8("Redundant backslash in brackets removed.")) 1483 return (1, self.trUtf8("Redundant backslash in brackets removed."), 0)
978 1484
979 def __fixE701(self, code, line, pos, apply=False): 1485 def __fixE701(self, code, line, pos, apply=False):
980 """ 1486 """
981 Private method to fix colon-separated compund statements (E701). 1487 Private method to fix colon-separated compound statements (E701).
982 1488
983 @param code code of the issue (string) 1489 @param code code of the issue (string)
984 @param line line number of the issue (integer) 1490 @param line line number of the issue (integer)
985 @param pos position inside line (integer) 1491 @param pos position inside line (integer)
986 @keyparam apply flag indicating, that the fix should be applied 1492 @keyparam apply flag indicating, that the fix should be applied
987 (boolean) 1493 (boolean)
988 @return flag indicating an applied fix (boolean) and a message for 1494 @return value indicating an applied/deferred fix (-1, 0, 1),
989 the fix (string) 1495 a message for the fix (string) and an ID for a deferred
1496 fix (integer)
990 """ 1497 """
991 if apply: 1498 if apply:
992 line = line - 1 1499 line = line - 1
993 text = self.__source[line] 1500 text = self.__source[line]
994 pos = pos + 1 1501 pos = pos + 1
995 1502
996 newText = text[:pos] + self.__getEol() + self.__getIndent(text) + \ 1503 newText = text[:pos] + self.__getEol() + self.__getIndent(text) + \
997 self.__indentWord + text[pos:].lstrip("\n\r \t\\") + \ 1504 self.__indentWord + text[pos:].lstrip("\n\r \t\\") + \
998 self.__getEol() 1505 self.__getEol()
999 self.__source[line] = newText 1506 self.__source[line] = newText
1000 else: 1507 return (1, self.trUtf8("Compound statement corrected."), 0)
1001 self.__stack.append((code, line, pos)) 1508 else:
1002 return (True, self.trUtf8("Compound statement corrected.")) 1509 id = self.__getID()
1510 self.__stack.append((id, code, line, pos))
1511 return (-1, "", id)
1003 1512
1004 def __fixE702(self, code, line, pos, apply=False): 1513 def __fixE702(self, code, line, pos, apply=False):
1005 """ 1514 """
1006 Private method to fix semicolon-separated compound statements 1515 Private method to fix semicolon-separated compound statements
1007 (E702, E703). 1516 (E702, E703).
1009 @param code code of the issue (string) 1518 @param code code of the issue (string)
1010 @param line line number of the issue (integer) 1519 @param line line number of the issue (integer)
1011 @param pos position inside line (integer) 1520 @param pos position inside line (integer)
1012 @keyparam apply flag indicating, that the fix should be applied 1521 @keyparam apply flag indicating, that the fix should be applied
1013 (boolean) 1522 (boolean)
1014 @return flag indicating an applied fix (boolean) and a message for 1523 @return value indicating an applied/deferred fix (-1, 0, 1),
1015 the fix (string) 1524 a message for the fix (string) and an ID for a deferred
1525 fix (integer)
1016 """ 1526 """
1017 if apply: 1527 if apply:
1018 line = line - 1 1528 line = line - 1
1019 text = self.__source[line] 1529 text = self.__source[line]
1020 1530
1026 self.__source[line] = text.rstrip("\n\r \t;") + self.__getEol() 1536 self.__source[line] = text.rstrip("\n\r \t;") + self.__getEol()
1027 else: 1537 else:
1028 first = text[:pos].rstrip("\n\r \t;") + self.__getEol() 1538 first = text[:pos].rstrip("\n\r \t;") + self.__getEol()
1029 second = text[pos:].lstrip("\n\r \t;") 1539 second = text[pos:].lstrip("\n\r \t;")
1030 self.__source[line] = first + self.__getIndent(text) + second 1540 self.__source[line] = first + self.__getIndent(text) + second
1031 else: 1541 return (1, self.trUtf8("Compound statement corrected."), 0)
1032 self.__stack.append((code, line, pos)) 1542 else:
1033 return (True, self.trUtf8("Compound statement corrected.")) 1543 id = self.__getID()
1544 self.__stack.append((id, code, line, pos))
1545 return (-1, "", id)
1034 1546
1035 def __fixE711(self, code, line, pos): 1547 def __fixE711(self, code, line, pos):
1036 """ 1548 """
1037 Private method to fix comparison with None (E711, E712). 1549 Private method to fix comparison with None (E711, E712).
1038 1550
1039 @param code code of the issue (string) 1551 @param code code of the issue (string)
1040 @param line line number of the issue (integer) 1552 @param line line number of the issue (integer)
1041 @param pos position inside line (integer) 1553 @param pos position inside line (integer)
1042 @return flag indicating an applied fix (boolean) and a message for 1554 @return value indicating an applied/deferred fix (-1, 0, 1),
1043 the fix (string) 1555 a message for the fix (string) and an ID for a deferred
1556 fix (integer)
1044 """ 1557 """
1045 line = line - 1 1558 line = line - 1
1046 text = self.__source[line] 1559 text = self.__source[line]
1047 1560
1048 rightPos = pos + 2 1561 rightPos = pos + 2
1049 if rightPos >= len(text): 1562 if rightPos >= len(text):
1050 return (False, "") 1563 return (0, "", 0)
1051 1564
1052 left = text[:pos].rstrip() 1565 left = text[:pos].rstrip()
1053 center = text[pos:rightPos] 1566 center = text[pos:rightPos]
1054 right = text[rightPos:].lstrip() 1567 right = text[rightPos:].lstrip()
1055 1568
1056 if not right.startswith(("None", "True", "False")): 1569 if not right.startswith(("None", "True", "False")):
1057 return (False, "") 1570 return (0, "", 0)
1058 1571
1059 if center.strip() == "==": 1572 if center.strip() == "==":
1060 center = "is" 1573 center = "is"
1061 elif center.strip() == "!=": 1574 elif center.strip() == "!=":
1062 center = "is not" 1575 center = "is not"
1063 else: 1576 else:
1064 return (False, "") 1577 return (0, "", 0)
1065 1578
1066 self.__source[line] = " ".join([left, center, right]) 1579 self.__source[line] = " ".join([left, center, right])
1067 return (True, self.trUtf8("Comparison to None/True/False corrected.")) 1580 return (1, self.trUtf8("Comparison to None/True/False corrected."), 0)
1581
1582 def __fixN804(self, code, line, pos, apply=False):
1583 """
1584 Private method to fix a wrong first argument of normal and
1585 class methods (N804, N805).
1586
1587 @param code code of the issue (string)
1588 @param line line number of the issue (integer)
1589 @param pos position inside line (integer)
1590 @keyparam apply flag indicating, that the fix should be applied
1591 (boolean)
1592 @return value indicating an applied/deferred fix (-1, 0, 1),
1593 a message for the fix (string) and an ID for a deferred
1594 fix (integer)
1595 """
1596 if apply:
1597 line = line - 1
1598 text = self.__source[line]
1599 if code == "N804":
1600 arg = "cls"
1601 else:
1602 arg = "self"
1603
1604 if text.rstrip().endswith("("):
1605 newText = text + self.__getIndent(text) + \
1606 self.__indentWord + arg + "," + self.__getEol()
1607 else:
1608 index = text.find("(") + 1
1609 left = text[:index]
1610 right = text[index:]
1611 if right.startswith(")"):
1612 center = arg
1613 else:
1614 center = arg + ", "
1615 newText = left + center + right
1616 self.__source[line] = newText
1617 return (1, self.trUtf8("'{0}' argument added.").format(arg), 0)
1618 else:
1619 id = self.__getID()
1620 self.__stack.append((id, code, line, pos))
1621 return (-1, "", id)
1622
1623 def __fixN806(self, code, line, pos, apply=False):
1624 """
1625 Private method to fix a wrong first argument of static methods
1626 (N806).
1627
1628 @param code code of the issue (string)
1629 @param line line number of the issue (integer)
1630 @param pos position inside line (integer)
1631 @keyparam apply flag indicating, that the fix should be applied
1632 (boolean)
1633 @return value indicating an applied/deferred fix (-1, 0, 1),
1634 a message for the fix (string) and an ID for a deferred
1635 fix (integer)
1636 """
1637 if apply:
1638 line = line - 1
1639 text = self.__source[line]
1640 index = text.find("(") + 1
1641 left = text[:index]
1642 right = text[index:]
1643
1644 if right.startswith(("cls", "self")):
1645 # cls or self are on the definition line
1646 if right.startswith("cls"):
1647 right = right[3:]
1648 arg = "cls"
1649 else:
1650 right = right[4:]
1651 arg = "self"
1652 right = right.lstrip(", ")
1653 newText = left + right
1654 self.__source[line] = newText
1655 else:
1656 # they are on the next line
1657 line = line + 1
1658 text = self.__source[line]
1659 indent = self.__getIndent(text)
1660 right = text.lstrip()
1661 if right.startswith("cls"):
1662 right = right[3:]
1663 arg = "cls"
1664 else:
1665 right = right[4:]
1666 arg = "self"
1667 right = right.lstrip(", ")
1668 if right.startswith("):"):
1669 # merge with previous line
1670 self.__source[line - 1] = \
1671 self.__source[line - 1].rstrip() + right
1672 self.__source[line] = ""
1673 else:
1674 self.__source[line] = indent + right
1675
1676 return (1, self.trUtf8("'{0}' argument removed.").format(arg), 0)
1677 else:
1678 id = self.__getID()
1679 self.__stack.append((id, code, line, pos))
1680 return (-1, "", id)
1068 1681
1069 def __fixW291(self, code, line, pos): 1682 def __fixW291(self, code, line, pos):
1070 """ 1683 """
1071 Private method to fix trailing whitespace (W291, W293). 1684 Private method to fix trailing whitespace (W291, W293).
1072 1685
1073 @param code code of the issue (string) 1686 @param code code of the issue (string)
1074 @param line line number of the issue (integer) 1687 @param line line number of the issue (integer)
1075 @param pos position inside line (integer) 1688 @param pos position inside line (integer)
1076 @return flag indicating an applied fix (boolean) and a message for 1689 @return value indicating an applied/deferred fix (-1, 0, 1),
1077 the fix (string) 1690 a message for the fix (string) and an ID for a deferred
1691 fix (integer)
1078 """ 1692 """
1079 self.__source[line - 1] = re.sub(r'[\t ]+(\r?)$', r"\1", 1693 self.__source[line - 1] = re.sub(r'[\t ]+(\r?)$', r"\1",
1080 self.__source[line - 1]) 1694 self.__source[line - 1])
1081 return (True, self.trUtf8("Whitespace stripped from end of line.")) 1695 return (1, self.trUtf8("Whitespace stripped from end of line."), 0)
1082 1696
1083 def __fixW292(self, code, line, pos): 1697 def __fixW292(self, code, line, pos):
1084 """ 1698 """
1085 Private method to fix a missing newline at the end of file (W292). 1699 Private method to fix a missing newline at the end of file (W292).
1086 1700
1087 @param code code of the issue (string) 1701 @param code code of the issue (string)
1088 @param line line number of the issue (integer) 1702 @param line line number of the issue (integer)
1089 @param pos position inside line (integer) 1703 @param pos position inside line (integer)
1090 @return flag indicating an applied fix (boolean) and a message for 1704 @return value indicating an applied/deferred fix (-1, 0, 1),
1091 the fix (string) 1705 a message for the fix (string) and an ID for a deferred
1706 fix (integer)
1092 """ 1707 """
1093 self.__source[line - 1] += self.__getEol() 1708 self.__source[line - 1] += self.__getEol()
1094 return (True, self.trUtf8("newline added to end of file.")) 1709 return (1, self.trUtf8("newline added to end of file."), 0)
1095 1710
1096 def __fixW391(self, code, line, pos): 1711 def __fixW391(self, code, line, pos):
1097 """ 1712 """
1098 Private method to fix trailing blank lines (W391). 1713 Private method to fix trailing blank lines (W391).
1099 1714
1100 @param code code of the issue (string) 1715 @param code code of the issue (string)
1101 @param line line number of the issue (integer) 1716 @param line line number of the issue (integer)
1102 @param pos position inside line (integer) 1717 @param pos position inside line (integer)
1103 @return flag indicating an applied fix (boolean) and a message for 1718 @return value indicating an applied/deferred fix (-1, 0, 1),
1104 the fix (string) 1719 a message for the fix (string) and an ID for a deferred
1720 fix (integer)
1105 """ 1721 """
1106 index = line - 1 1722 index = line - 1
1107 while index: 1723 while index:
1108 if self.__source[index].strip() == "": 1724 if self.__source[index].strip() == "":
1109 del self.__source[index] 1725 del self.__source[index]
1110 index -= 1 1726 index -= 1
1111 else: 1727 else:
1112 break 1728 break
1113 return (True, self.trUtf8( 1729 return (1, self.trUtf8(
1114 "Superfluous trailing blank lines removed from end of file.")) 1730 "Superfluous trailing blank lines removed from end of file."), 0)
1115 1731
1116 def __fixW603(self, code, line, pos): 1732 def __fixW603(self, code, line, pos):
1117 """ 1733 """
1118 Private method to fix the not equal notation (W603). 1734 Private method to fix the not equal notation (W603).
1119 1735
1120 @param code code of the issue (string) 1736 @param code code of the issue (string)
1121 @param line line number of the issue (integer) 1737 @param line line number of the issue (integer)
1122 @param pos position inside line (integer) 1738 @param pos position inside line (integer)
1123 @return flag indicating an applied fix (boolean) and a message for 1739 @return value indicating an applied/deferred fix (-1, 0, 1),
1124 the fix (string) 1740 a message for the fix (string) and an ID for a deferred
1741 fix (integer)
1125 """ 1742 """
1126 self.__source[line - 1] = self.__source[line - 1].replace("<>", "!=") 1743 self.__source[line - 1] = self.__source[line - 1].replace("<>", "!=")
1127 return (True, self.trUtf8("'<>' replaced by '!='.")) 1744 return (1, self.trUtf8("'<>' replaced by '!='."), 0)
1128 1745
1129 1746
1130 class Pep8Reindenter(object): 1747 class Pep8Reindenter(object):
1131 """ 1748 """
1132 Class to reindent badly-indented code to uniformly use four-space 1749 Class to reindent badly-indented code to uniformly use four-space
1676 candidates = self.__shortenLine(tokens, source, indent) 2293 candidates = self.__shortenLine(tokens, source, indent)
1677 if candidates: 2294 if candidates:
1678 candidates = list(sorted( 2295 candidates = list(sorted(
1679 set(candidates).union([self.__text]), 2296 set(candidates).union([self.__text]),
1680 key=lambda x: self.__lineShorteningRank(x))) 2297 key=lambda x: self.__lineShorteningRank(x)))
2298 if candidates[0] == self.__text:
2299 return False, "", ""
1681 return True, candidates[0], "" 2300 return True, candidates[0], ""
1682 2301
1683 source = self.__text 2302 source = self.__text
1684 rs = source.rstrip() 2303 rs = source.rstrip()
1685 if rs.endswith(("'", '"')) and " " in source: 2304 if rs.endswith(("'", '"')) and " " in source:
1696 first = source[:maxLen] 2315 first = source[:maxLen]
1697 second = source[maxLen:] 2316 second = source[maxLen:]
1698 else: 2317 else:
1699 first = source[:blank] 2318 first = source[:blank]
1700 second = source[blank + 1:] 2319 second = source[blank + 1:]
1701 return (True, 2320 return (
2321 True,
1702 first + quote + " \\" + self.__eol + 2322 first + quote + " \\" + self.__eol +
1703 indent + self.__indentWord + quote + second, 2323 indent + self.__indentWord + quote + second,
1704 "") 2324 "")
1705 else: 2325 else:
1706 # Cannot break 2326 # Cannot break
1725 indentation = self.__getIndent(newText) + '# ' 2345 indentation = self.__getIndent(newText) + '# '
1726 maxLength = min(self.__maxLength, 2346 maxLength = min(self.__maxLength,
1727 len(indentation) + 72) 2347 len(indentation) + 72)
1728 2348
1729 MIN_CHARACTER_REPEAT = 5 2349 MIN_CHARACTER_REPEAT = 5
1730 if (len(newText) - len(newText.rstrip(newText[-1])) >= \ 2350 if len(newText) - len(newText.rstrip(newText[-1])) >= \
1731 MIN_CHARACTER_REPEAT and 2351 MIN_CHARACTER_REPEAT and \
1732 not newText[-1].isalnum()): 2352 not newText[-1].isalnum():
1733 # Trim comments that end with things like --------- 2353 # Trim comments that end with things like ---------
1734 return newText[:maxLength] + self.__eol 2354 return newText[:maxLength] + self.__eol
1735 elif isLast and re.match(r"\s*#+\s*\w+", newText): 2355 elif isLast and re.match(r"\s*#+\s*\w+", newText):
1736 import textwrap 2356 import textwrap
1737 splitLines = textwrap.wrap(newText.lstrip(" \t#"), 2357 splitLines = textwrap.wrap(newText.lstrip(" \t#"),
1838 ): 2458 ):
1839 # Move inline comments to previous line. 2459 # Move inline comments to previous line.
1840 offset = tkn[2][1] 2460 offset = tkn[2][1]
1841 first = source[:offset] 2461 first = source[:offset]
1842 second = source[offset:] 2462 second = source[offset:]
1843 candidates.append(indent + second.strip() + self.__eol + 2463 candidates.append(
1844 indent + first.strip() + self.__eol) 2464 indent + second.strip() + self.__eol +
2465 indent + first.strip() + self.__eol)
1845 elif tokenType == tokenize.OP and tokenString != '=': 2466 elif tokenType == tokenize.OP and tokenString != '=':
1846 # Don't break on '=' after keyword as this violates PEP 8. 2467 # Don't break on '=' after keyword as this violates PEP 8.
1847 2468
1848 assert tokenType != tokenize.INDENT 2469 assert tokenType != tokenize.INDENT
1849 2470
1911 @param candidate candidate line to rank (string) 2532 @param candidate candidate line to rank (string)
1912 @return rank of the candidate (integer) 2533 @return rank of the candidate (integer)
1913 """ 2534 """
1914 rank = 0 2535 rank = 0
1915 if candidate.strip(): 2536 if candidate.strip():
2537 if candidate == self.__text:
2538 # give the original a disadvantage
2539 rank += 50
2540
1916 lines = candidate.split(self.__eol) 2541 lines = candidate.split(self.__eol)
1917 2542
1918 offset = 0 2543 offset = 0
1919 if lines[0].rstrip()[-1] not in '([{': 2544 if lines[0].rstrip()[-1] not in '([{':
1920 for symbol in '([{': 2545 for symbol in '([{':
1943 if currentLine.startswith(badStart): 2568 if currentLine.startswith(badStart):
1944 rank += 100 2569 rank += 100
1945 2570
1946 for ending in '([{': 2571 for ending in '([{':
1947 # Avoid lonely opening. They result in longer lines. 2572 # Avoid lonely opening. They result in longer lines.
1948 if (currentLine.endswith(ending) and 2573 if currentLine.endswith(ending) and \
1949 len(currentLine.strip()) <= \ 2574 len(currentLine.strip()) <= len(self.__indentWord):
1950 len(self.__indentWord)):
1951 rank += 100 2575 rank += 100
1952 2576
1953 if currentLine.endswith('%'): 2577 if currentLine.endswith('%'):
1954 rank -= 20 2578 rank -= 20
1955 2579

eric ide

mercurial