Plugins/CheckerPlugins/Pep8/Pep8Fixer.py

changeset 2891
6843b7d23279
parent 2890
86b03a0c94bc
child 2892
b601ede6dbbf
equal deleted inserted replaced
2890:86b03a0c94bc 2891:6843b7d23279
30 "E401", "E501", "E502", "W603", "E701", "E702", 30 "E401", "E501", "E502", "W603", "E701", "E702",
31 "E703", "E711", "E712" 31 "E703", "E711", "E712"
32 ] 32 ]
33 33
34 34
35 # TODO: refine behavior for non-fixable issues
36 class Pep8Fixer(QObject): 35 class Pep8Fixer(QObject):
37 """ 36 """
38 Class implementing a fixer for certain PEP 8 issues. 37 Class implementing a fixer for certain PEP 8 issues.
39 """ 38 """
40 def __init__(self, project, filename, sourceLines, fixCodes, noFixCodes, 39 def __init__(self, project, filename, sourceLines, fixCodes, noFixCodes,
134 self.__stack = [] # these need to be fixed before the file 133 self.__stack = [] # these need to be fixed before the file
135 # is saved but after all inline fixes 134 # is saved but after all inline fixes
136 135
137 self.__multiLineNumbers = None 136 self.__multiLineNumbers = None
138 self.__docLineNumbers = None 137 self.__docLineNumbers = None
138
139 self.__lastID = 0
139 140
140 def saveFile(self, encoding): 141 def saveFile(self, encoding):
141 """ 142 """
142 Public method to save the modified file. 143 Public method to save the modified file.
143 144
145 @return flag indicating success (boolean) 146 @return flag indicating success (boolean)
146 """ 147 """
147 if not self.__modified: 148 if not self.__modified:
148 # no need to write 149 # no need to write
149 return True 150 return True
150
151 # apply deferred fixes
152 self.__finalize()
153 151
154 txt = "".join(self.__source) 152 txt = "".join(self.__source)
155 try: 153 try:
156 Utilities.writeEncodedFile(self.__filename, txt, encoding) 154 Utilities.writeEncodedFile(self.__filename, txt, encoding)
157 except (IOError, Utilities.CodingError, UnicodeError) as err: 155 except (IOError, Utilities.CodingError, UnicodeError) as err:
201 Public method to fix the fixable issues. 199 Public method to fix the fixable issues.
202 200
203 @param line line number of issue (integer) 201 @param line line number of issue (integer)
204 @param pos character position of issue (integer) 202 @param pos character position of issue (integer)
205 @param message message text (string) 203 @param message message text (string)
206 @return flag indicating an applied fix (boolean) and a message for 204 @return value indicating an applied/deferred fix (-1, 0, 1),
207 the fix (string) 205 a message for the fix (string) and an ID for a deferred
206 fix (integer)
208 """ 207 """
209 code = message.split(None, 1)[0].strip() 208 code = message.split(None, 1)[0].strip()
210 209
211 if line <= len(self.__source) and \ 210 if line <= len(self.__source) and \
212 self.__codeMatch(code) and \ 211 self.__codeMatch(code) and \
213 code in self.__fixes: 212 code in self.__fixes:
214 res = self.__fixes[code](code, line, pos) 213 res = self.__fixes[code](code, line, pos)
215 if res[0]: 214 if res[0] == 1:
216 self.__modified = True 215 self.__modified = True
217 self.fixed += 1 216 self.fixed += 1
218 else: 217 else:
219 res = (False, "") 218 res = (0, "", 0)
220 219
221 return res 220 return res
222 221
223 def __finalize(self): 222 def finalize(self):
224 """ 223 """
225 Private method to apply all deferred fixes. 224 Public method to apply all deferred fixes.
226 """ 225 """
226 results = {}
227
227 # step 1: do fixes operating on logical lines first 228 # step 1: do fixes operating on logical lines first
228 for code, line, pos in self.__stackLogical: 229 for id_, code, line, pos in self.__stackLogical:
229 self.__fixes[code](code, line, pos, apply=True) 230 res, msg, _ = self.__fixes[code](code, line, pos, apply=True)
231 if res == 1:
232 self.__modified = True
233 self.fixed += 1
234 results[id_] = (res, msg)
230 235
231 # step 2: do fixes that change the number of lines 236 # step 2: do fixes that change the number of lines
232 for code, line, pos in reversed(self.__stack): 237 for id_, code, line, pos in reversed(self.__stack):
233 self.__fixes[code](code, line, pos, apply=True) 238 res, msg, _ = self.__fixes[code](code, line, pos, apply=True)
239 if res == 1:
240 self.__modified = True
241 self.fixed += 1
242 results[id_] = (res, msg)
243
244 return results
245
246 def __getID(self):
247 """
248 Private method to get the ID for a deferred fix.
249
250 @return ID for a deferred fix (integer)
251 """
252 self.__lastID += 1
253 return self.__lastID
234 254
235 def __getEol(self): 255 def __getEol(self):
236 """ 256 """
237 Private method to get the applicable eol string. 257 Private method to get the applicable eol string.
238 258
439 (E101, E111, W191). 459 (E101, E111, W191).
440 460
441 @param code code of the issue (string) 461 @param code code of the issue (string)
442 @param line line number of the issue (integer) 462 @param line line number of the issue (integer)
443 @param pos position inside line (integer) 463 @param pos position inside line (integer)
444 @return flag indicating an applied fix (boolean) and a message for 464 @return value indicating an applied/deferred fix (-1, 0, 1),
445 the fix (string) 465 a message for the fix (string) and an ID for a deferred
466 fix (integer)
446 """ 467 """
447 if self.__reindenter is None: 468 if self.__reindenter is None:
448 self.__reindenter = Pep8Reindenter(self.__source) 469 self.__reindenter = Pep8Reindenter(self.__source)
449 self.__reindenter.run() 470 self.__reindenter.run()
450 fixedLine = self.__reindenter.fixedLine(line - 1) 471 fixedLine = self.__reindenter.fixedLine(line - 1)
453 if code in ["E101", "W191"]: 474 if code in ["E101", "W191"]:
454 msg = self.trUtf8("Tab converted to 4 spaces.") 475 msg = self.trUtf8("Tab converted to 4 spaces.")
455 else: 476 else:
456 msg = self.trUtf8( 477 msg = self.trUtf8(
457 "Indentation adjusted to be a multiple of four.") 478 "Indentation adjusted to be a multiple of four.")
458 return (True, msg) 479 return (1, msg, 0)
459 else: 480 else:
460 return (False, self.trUtf8("Fix for {0} failed.").format(code)) 481 return (0, self.trUtf8("Fix for {0} failed.").format(code), 0)
461 482
462 def __fixE121(self, code, line, pos, apply=False): 483 def __fixE121(self, code, line, pos, apply=False):
463 """ 484 """
464 Private method to fix the indentation of continuation lines and 485 Private method to fix the indentation of continuation lines and
465 closing brackets (E121,E124). 486 closing brackets (E121,E124).
467 @param code code of the issue (string) 488 @param code code of the issue (string)
468 @param line line number of the issue (integer) 489 @param line line number of the issue (integer)
469 @param pos position inside line (integer) 490 @param pos position inside line (integer)
470 @keyparam apply flag indicating, that the fix should be applied 491 @keyparam apply flag indicating, that the fix should be applied
471 (boolean) 492 (boolean)
472 @return flag indicating an applied fix (boolean) and a message for 493 @return value indicating an applied/deferred fix (-1, 0, 1),
473 the fix (string) 494 a message for the fix (string) and an ID for a deferred
495 fix (integer)
474 """ 496 """
475 if apply: 497 if apply:
476 logical = self.__getLogical(line, pos) 498 logical = self.__getLogical(line, pos)
477 if logical: 499 if logical:
478 # Fix by adjusting initial indent level. 500 # Fix by adjusting initial indent level.
479 self.__fixReindent(line, pos, logical) 501 self.__fixReindent(line, pos, logical)
480 else: 502 if code == "E121":
481 self.__stackLogical.append((code, line, pos)) 503 msg = self.trUtf8("Indentation of continuation line corrected.")
482 if code == "E121": 504 elif code == "E124":
483 msg = self.trUtf8("Indentation of continuation line corrected.") 505 msg = self.trUtf8("Indentation of closing bracket corrected.")
484 elif code == "E124": 506 return (1, msg, 0)
485 msg = self.trUtf8("Indentation of closing bracket corrected.") 507 else:
486 return (True, msg) 508 id = self.__getID()
509 self.__stackLogical.append((id, code, line, pos))
510 return (-1, "", id)
487 511
488 def __fixE122(self, code, line, pos, apply=False): 512 def __fixE122(self, code, line, pos, apply=False):
489 """ 513 """
490 Private method to fix a missing indentation of continuation lines 514 Private method to fix a missing indentation of continuation lines
491 (E122). 515 (E122).
493 @param code code of the issue (string) 517 @param code code of the issue (string)
494 @param line line number of the issue (integer) 518 @param line line number of the issue (integer)
495 @param pos position inside line (integer) 519 @param pos position inside line (integer)
496 @keyparam apply flag indicating, that the fix should be applied 520 @keyparam apply flag indicating, that the fix should be applied
497 (boolean) 521 (boolean)
498 @return flag indicating an applied fix (boolean) and a message for 522 @return value indicating an applied/deferred fix (-1, 0, 1),
499 the fix (string) 523 a message for the fix (string) and an ID for a deferred
524 fix (integer)
500 """ 525 """
501 if apply: 526 if apply:
502 logical = self.__getLogical(line, pos) 527 logical = self.__getLogical(line, pos)
503 if logical: 528 if logical:
504 # Fix by adding an initial indent. 529 # Fix by adding an initial indent.
508 line = line - 1 533 line = line - 1
509 text = self.__source[line] 534 text = self.__source[line]
510 indentation = self.__getIndent(text) 535 indentation = self.__getIndent(text)
511 self.__source[line] = indentation + \ 536 self.__source[line] = indentation + \
512 self.__indentWord + text.lstrip() 537 self.__indentWord + text.lstrip()
513 else: 538 return (
514 self.__stackLogical.append((code, line, pos)) 539 1,
515 return ( 540 self.trUtf8(
516 True, 541 "Missing indentation of continuation line corrected."),
517 self.trUtf8("Missing indentation of continuation line corrected.")) 542 0)
543 else:
544 id = self.__getID()
545 self.__stackLogical.append((id, code, line, pos))
546 return (-1, "", id)
518 547
519 def __fixE123(self, code, line, pos, apply=False): 548 def __fixE123(self, code, line, pos, apply=False):
520 """ 549 """
521 Private method to fix the indentation of a closing bracket lines 550 Private method to fix the indentation of a closing bracket lines
522 (E123). 551 (E123).
524 @param code code of the issue (string) 553 @param code code of the issue (string)
525 @param line line number of the issue (integer) 554 @param line line number of the issue (integer)
526 @param pos position inside line (integer) 555 @param pos position inside line (integer)
527 @keyparam apply flag indicating, that the fix should be applied 556 @keyparam apply flag indicating, that the fix should be applied
528 (boolean) 557 (boolean)
529 @return flag indicating an applied fix (boolean) and a message for 558 @return value indicating an applied/deferred fix (-1, 0, 1),
530 the fix (string) 559 a message for the fix (string) and an ID for a deferred
560 fix (integer)
531 """ 561 """
532 if apply: 562 if apply:
533 logical = self.__getLogical(line, pos) 563 logical = self.__getLogical(line, pos)
534 if logical: 564 if logical:
535 # Fix by deleting whitespace to the correct level. 565 # Fix by deleting whitespace to the correct level.
540 if newText == text: 570 if newText == text:
541 # fall back to slower method 571 # fall back to slower method
542 self.__fixReindent(line, pos, logical) 572 self.__fixReindent(line, pos, logical)
543 else: 573 else:
544 self.__source[row] = newText 574 self.__source[row] = newText
545 else: 575 return (
546 self.__stackLogical.append((code, line, pos)) 576 1,
547 return ( 577 self.trUtf8("Closing bracket aligned to opening bracket."),
548 True, self.trUtf8("Closing bracket aligned to opening bracket.")) 578 0)
579 else:
580 id = self.__getID()
581 self.__stackLogical.append((id, code, line, pos))
582 return (-1, "", id)
549 583
550 def __fixE125(self, code, line, pos, apply=False): 584 def __fixE125(self, code, line, pos, apply=False):
551 """ 585 """
552 Private method to fix the indentation of continuation lines not 586 Private method to fix the indentation of continuation lines not
553 distinguishable from next logical line (E125). 587 distinguishable from next logical line (E125).
555 @param code code of the issue (string) 589 @param code code of the issue (string)
556 @param line line number of the issue (integer) 590 @param line line number of the issue (integer)
557 @param pos position inside line (integer) 591 @param pos position inside line (integer)
558 @keyparam apply flag indicating, that the fix should be applied 592 @keyparam apply flag indicating, that the fix should be applied
559 (boolean) 593 (boolean)
560 @return flag indicating an applied fix (boolean) and a message for 594 @return value indicating an applied/deferred fix (-1, 0, 1),
561 the fix (string) 595 a message for the fix (string) and an ID for a deferred
596 fix (integer)
562 """ 597 """
563 if apply: 598 if apply:
564 logical = self.__getLogical(line, pos) 599 logical = self.__getLogical(line, pos)
565 if logical: 600 if logical:
566 # Fix by adjusting initial indent level. 601 # Fix by adjusting initial indent level.
568 if not modified: 603 if not modified:
569 row = line - 1 604 row = line - 1
570 text = self.__source[row] 605 text = self.__source[row]
571 self.__source[row] = self.__getIndent(text) + \ 606 self.__source[row] = self.__getIndent(text) + \
572 self.__indentWord + text.lstrip() 607 self.__indentWord + text.lstrip()
573 else: 608 return (1, self.trUtf8("Indentation level changed."), 0)
574 self.__stackLogical.append((code, line, pos)) 609 else:
575 return (True, self.trUtf8("Indentation level changed.")) 610 id = self.__getID()
611 self.__stackLogical.append((id, code, line, pos))
612 return (-1, "", id)
576 613
577 def __fixE126(self, code, line, pos, apply=False): 614 def __fixE126(self, code, line, pos, apply=False):
578 """ 615 """
579 Private method to fix over-indented/under-indented hanging 616 Private method to fix over-indented/under-indented hanging
580 indentation (E126, E133). 617 indentation (E126, E133).
582 @param code code of the issue (string) 619 @param code code of the issue (string)
583 @param line line number of the issue (integer) 620 @param line line number of the issue (integer)
584 @param pos position inside line (integer) 621 @param pos position inside line (integer)
585 @keyparam apply flag indicating, that the fix should be applied 622 @keyparam apply flag indicating, that the fix should be applied
586 (boolean) 623 (boolean)
587 @return flag indicating an applied fix (boolean) and a message for 624 @return value indicating an applied/deferred fix (-1, 0, 1),
588 the fix (string) 625 a message for the fix (string) and an ID for a deferred
626 fix (integer)
589 """ 627 """
590 if apply: 628 if apply:
591 logical = self.__getLogical(line, pos) 629 logical = self.__getLogical(line, pos)
592 if logical: 630 if logical:
593 # Fix by deleting whitespace to the left. 631 # Fix by deleting whitespace to the left.
599 if newText == text: 637 if newText == text:
600 # fall back to slower method 638 # fall back to slower method
601 self.__fixReindent(line, pos, logical) 639 self.__fixReindent(line, pos, logical)
602 else: 640 else:
603 self.__source[row] = newText 641 self.__source[row] = newText
604 else: 642 return (
605 self.__stackLogical.append((code, line, pos)) 643 1,
606 return ( 644 self.trUtf8(
607 True, 645 "Indentation level of hanging indentation changed."),
608 self.trUtf8("Indentation level of hanging indentation changed.")) 646 0)
647 else:
648 id = self.__getID()
649 self.__stackLogical.append((id, code, line, pos))
650 return (-1, "", id)
609 651
610 def __fixE127(self, code, line, pos, apply=False): 652 def __fixE127(self, code, line, pos, apply=False):
611 """ 653 """
612 Private method to fix over/under indented lines (E127, E128). 654 Private method to fix over/under indented lines (E127, E128).
613 655
614 @param code code of the issue (string) 656 @param code code of the issue (string)
615 @param line line number of the issue (integer) 657 @param line line number of the issue (integer)
616 @param pos position inside line (integer) 658 @param pos position inside line (integer)
617 @keyparam apply flag indicating, that the fix should be applied 659 @keyparam apply flag indicating, that the fix should be applied
618 (boolean) 660 (boolean)
619 @return flag indicating an applied fix (boolean) and a message for 661 @return value indicating an applied/deferred fix (-1, 0, 1),
620 the fix (string) 662 a message for the fix (string) and an ID for a deferred
663 fix (integer)
621 """ 664 """
622 if apply: 665 if apply:
623 logical = self.__getLogical(line, pos) 666 logical = self.__getLogical(line, pos)
624 if logical: 667 if logical:
625 # Fix by inserting/deleting whitespace to the correct level. 668 # Fix by inserting/deleting whitespace to the correct level.
647 if newText == text: 690 if newText == text:
648 # fall back to slower method 691 # fall back to slower method
649 self.__fixReindent(line, pos, logical) 692 self.__fixReindent(line, pos, logical)
650 else: 693 else:
651 self.__source[row] = newText 694 self.__source[row] = newText
652 else: 695 return (1, self.trUtf8("Visual indentation corrected."), 0)
653 self.__stackLogical.append((code, line, pos)) 696 else:
654 return (True, self.trUtf8("Visual indentation corrected.")) 697 id = self.__getID()
698 self.__stackLogical.append((id, code, line, pos))
699 return (-1, "", id)
655 700
656 def __fixE201(self, code, line, pos): 701 def __fixE201(self, code, line, pos):
657 """ 702 """
658 Private method to fix extraneous whitespace (E201, E202, 703 Private method to fix extraneous whitespace (E201, E202,
659 E203, E211). 704 E203, E211).
660 705
661 @param code code of the issue (string) 706 @param code code of the issue (string)
662 @param line line number of the issue (integer) 707 @param line line number of the issue (integer)
663 @param pos position inside line (integer) 708 @param pos position inside line (integer)
664 @return flag indicating an applied fix (boolean) and a message for 709 @return value indicating an applied/deferred fix (-1, 0, 1),
665 the fix (string) 710 a message for the fix (string) and an ID for a deferred
711 fix (integer)
666 """ 712 """
667 line = line - 1 713 line = line - 1
668 text = self.__source[line] 714 text = self.__source[line]
669 715
670 if '"""' in text or "'''" in text or text.rstrip().endswith('\\'): 716 if '"""' in text or "'''" in text or text.rstrip().endswith('\\'):
671 return ( 717 return (
672 False, self.trUtf8("Extraneous whitespace cannot be removed.")) 718 0, self.trUtf8("Extraneous whitespace cannot be removed."), 0)
673 719
674 newText = self.__fixWhitespace(text, pos, '') 720 newText = self.__fixWhitespace(text, pos, '')
675 if newText == text: 721 if newText == text:
676 return (False, "") 722 return (0, "", 0)
677 723
678 self.__source[line] = newText 724 self.__source[line] = newText
679 return (True, self.trUtf8("Extraneous whitespace removed.")) 725 return (1, self.trUtf8("Extraneous whitespace removed."), 0)
680 726
681 def __fixE221(self, code, line, pos): 727 def __fixE221(self, code, line, pos):
682 """ 728 """
683 Private method to fix extraneous whitespace around operator or 729 Private method to fix extraneous whitespace around operator or
684 keyword (E221, E222, E223, E224, E225, E226, E227, E228, E241, 730 keyword (E221, E222, E223, E224, E225, E226, E227, E228, E241,
685 E242, E271, E272, E273, E274). 731 E242, E271, E272, E273, E274).
686 732
687 @param code code of the issue (string) 733 @param code code of the issue (string)
688 @param line line number of the issue (integer) 734 @param line line number of the issue (integer)
689 @param pos position inside line (integer) 735 @param pos position inside line (integer)
690 @return flag indicating an applied fix (boolean) and a message for 736 @return value indicating an applied/deferred fix (-1, 0, 1),
691 the fix (string) 737 a message for the fix (string) and an ID for a deferred
738 fix (integer)
692 """ 739 """
693 line = line - 1 740 line = line - 1
694 text = self.__source[line] 741 text = self.__source[line]
695 742
696 if '"""' in text or "'''" in text or text.rstrip().endswith('\\'): 743 if '"""' in text or "'''" in text or text.rstrip().endswith('\\'):
697 return ( 744 return (
698 False, self.trUtf8("Extraneous whitespace cannot be removed.")) 745 0, self.trUtf8("Extraneous whitespace cannot be removed."), 0)
699 746
700 newText = self.__fixWhitespace(text, pos, ' ') 747 newText = self.__fixWhitespace(text, pos, ' ')
701 if newText == text: 748 if newText == text:
702 return (False, "") 749 return (0, "", 0)
703 750
704 self.__source[line] = newText 751 self.__source[line] = newText
705 if code in ["E225", "E226", "E227", "E228"]: 752 if code in ["E225", "E226", "E227", "E228"]:
706 return (True, self.trUtf8("Missing whitespace added.")) 753 return (1, self.trUtf8("Missing whitespace added."), 0)
707 else: 754 else:
708 return (True, self.trUtf8("Extraneous whitespace removed.")) 755 return (1, self.trUtf8("Extraneous whitespace removed."), 0)
709 756
710 def __fixE231(self, code, line, pos): 757 def __fixE231(self, code, line, pos):
711 """ 758 """
712 Private method to fix missing whitespace after ',;:'. 759 Private method to fix missing whitespace after ',;:'.
713 760
714 @param code code of the issue (string) 761 @param code code of the issue (string)
715 @param line line number of the issue (integer) 762 @param line line number of the issue (integer)
716 @param pos position inside line (integer) 763 @param pos position inside line (integer)
717 @return flag indicating an applied fix (boolean) and a message for 764 @return value indicating an applied/deferred fix (-1, 0, 1),
718 the fix (string) 765 a message for the fix (string) and an ID for a deferred
766 fix (integer)
719 """ 767 """
720 line = line - 1 768 line = line - 1
721 pos = pos + 1 769 pos = pos + 1
722 self.__source[line] = self.__source[line][:pos] + \ 770 self.__source[line] = self.__source[line][:pos] + \
723 " " + \ 771 " " + \
724 self.__source[line][pos:] 772 self.__source[line][pos:]
725 return (True, self.trUtf8("Missing whitespace added.")) 773 return (1, self.trUtf8("Missing whitespace added."), 0)
726 774
727 def __fixE251(self, code, line, pos): 775 def __fixE251(self, code, line, pos):
728 """ 776 """
729 Private method to fix extraneous whitespace around keyword and 777 Private method to fix extraneous whitespace around keyword and
730 default parameter equals (E251). 778 default parameter equals (E251).
731 779
732 @param code code of the issue (string) 780 @param code code of the issue (string)
733 @param line line number of the issue (integer) 781 @param line line number of the issue (integer)
734 @param pos position inside line (integer) 782 @param pos position inside line (integer)
735 @return flag indicating an applied fix (boolean) and a message for 783 @return value indicating an applied/deferred fix (-1, 0, 1),
736 the fix (string) 784 a message for the fix (string) and an ID for a deferred
785 fix (integer)
737 """ 786 """
738 line = line - 1 787 line = line - 1
739 text = self.__source[line] 788 text = self.__source[line]
740 789
741 # This is necessary since pep8 sometimes reports columns that goes 790 # This is necessary since pep8 sometimes reports columns that goes
754 if newText.endswith(('=\\\n', '=\\\r\n', '=\\\r')): 803 if newText.endswith(('=\\\n', '=\\\r\n', '=\\\r')):
755 self.__source[line] = newText.rstrip("\n\r \t\\") 804 self.__source[line] = newText.rstrip("\n\r \t\\")
756 self.__source[line + 1] = self.__source[line + 1].lstrip() 805 self.__source[line + 1] = self.__source[line + 1].lstrip()
757 else: 806 else:
758 self.__source[line] = newText 807 self.__source[line] = newText
759 return (True, self.trUtf8("Extraneous whitespace removed.")) 808 return (1, self.trUtf8("Extraneous whitespace removed."), 0)
760 809
761 def __fixE261(self, code, line, pos): 810 def __fixE261(self, code, line, pos):
762 """ 811 """
763 Private method to fix whitespace before or after inline comment 812 Private method to fix whitespace before or after inline comment
764 (E261, E262). 813 (E261, E262).
765 814
766 @param code code of the issue (string) 815 @param code code of the issue (string)
767 @param line line number of the issue (integer) 816 @param line line number of the issue (integer)
768 @param pos position inside line (integer) 817 @param pos position inside line (integer)
769 @return flag indicating an applied fix (boolean) and a message for 818 @return value indicating an applied/deferred fix (-1, 0, 1),
770 the fix (string) 819 a message for the fix (string) and an ID for a deferred
820 fix (integer)
771 """ 821 """
772 line = line - 1 822 line = line - 1
773 text = self.__source[line] 823 text = self.__source[line]
774 left = text[:pos].rstrip(' \t#') 824 left = text[:pos].rstrip(' \t#')
775 right = text[pos:].lstrip(' \t#') 825 right = text[pos:].lstrip(' \t#')
776 newText = left + (" # " + right if right.strip() else right) 826 newText = left + (" # " + right if right.strip() else right)
777 self.__source[line] = newText 827 self.__source[line] = newText
778 return (True, self.trUtf8("Whitespace around comment sign corrected.")) 828 return (1, self.trUtf8("Whitespace around comment sign corrected."), 0)
779 829
780 def __fixE301(self, code, line, pos, apply=False): 830 def __fixE301(self, code, line, pos, apply=False):
781 """ 831 """
782 Private method to fix the need for one blank line (E301). 832 Private method to fix the need for one blank line (E301).
783 833
784 @param code code of the issue (string) 834 @param code code of the issue (string)
785 @param line line number of the issue (integer) 835 @param line line number of the issue (integer)
786 @param pos position inside line (integer) 836 @param pos position inside line (integer)
787 @keyparam apply flag indicating, that the fix should be applied 837 @keyparam apply flag indicating, that the fix should be applied
788 (boolean) 838 (boolean)
789 @return flag indicating an applied fix (boolean) and a message for 839 @return value indicating an applied/deferred fix (-1, 0, 1),
790 the fix (string) 840 a message for the fix (string) and an ID for a deferred
841 fix (integer)
791 """ 842 """
792 if apply: 843 if apply:
793 self.__source.insert(line - 1, self.__getEol()) 844 self.__source.insert(line - 1, self.__getEol())
794 else: 845 return (1, self.trUtf8("One blank line inserted."), 0)
795 self.__stack.append((code, line, pos)) 846 else:
796 return (True, self.trUtf8("One blank line inserted.")) 847 id = self.__getID()
848 self.__stack.append((id, code, line, pos))
849 return (-1, "", id)
797 850
798 def __fixE302(self, code, line, pos, apply=False): 851 def __fixE302(self, code, line, pos, apply=False):
799 """ 852 """
800 Private method to fix the need for two blank lines (E302). 853 Private method to fix the need for two blank lines (E302).
801 854
802 @param code code of the issue (string) 855 @param code code of the issue (string)
803 @param line line number of the issue (integer) 856 @param line line number of the issue (integer)
804 @param pos position inside line (integer) 857 @param pos position inside line (integer)
805 @keyparam apply flag indicating, that the fix should be applied 858 @keyparam apply flag indicating, that the fix should be applied
806 (boolean) 859 (boolean)
807 @return flag indicating an applied fix (boolean) and a message for 860 @return value indicating an applied/deferred fix (-1, 0, 1),
808 the fix (string) 861 a message for the fix (string) and an ID for a deferred
809 """ 862 fix (integer)
810 # count blank lines 863 """
811 index = line - 1
812 blanks = 0
813 while index:
814 if self.__source[index - 1].strip() == "":
815 blanks += 1
816 index -= 1
817 else:
818 break
819 delta = blanks - 2
820
821 if apply: 864 if apply:
865 # count blank lines
866 index = line - 1
867 blanks = 0
868 while index:
869 if self.__source[index - 1].strip() == "":
870 blanks += 1
871 index -= 1
872 else:
873 break
874 delta = blanks - 2
875
822 line -= 1 876 line -= 1
823 if delta < 0: 877 if delta < 0:
824 # insert blank lines (one or two) 878 # insert blank lines (one or two)
825 while delta < 0: 879 while delta < 0:
826 self.__source.insert(line, self.__getEol()) 880 self.__source.insert(line, self.__getEol())
829 # delete superfluous blank lines 883 # delete superfluous blank lines
830 while delta > 0: 884 while delta > 0:
831 del self.__source[line - 1] 885 del self.__source[line - 1]
832 line -= 1 886 line -= 1
833 delta -= 1 887 delta -= 1
834 else: 888
835 self.__stack.append((code, line, pos)) 889 if delta < 0:
836 890 msg = self.trUtf8("%n blank line(s) inserted.", "", -delta)
837 if delta < 0: 891 elif delta > 0:
838 msg = self.trUtf8("%n blank line(s) inserted.", "", -delta) 892 msg = self.trUtf8("%n superfluous lines removed", "", delta)
839 elif delta > 0: 893 else:
840 msg = self.trUtf8("%n superfluous lines removed", "", delta) 894 msg = ""
841 else: 895 return (1, msg, 0)
842 msg = "" 896 else:
843 return (True, msg) 897 id = self.__getID()
898 self.__stack.append((id, code, line, pos))
899 return (-1, "", id)
844 900
845 def __fixE303(self, code, line, pos, apply=False): 901 def __fixE303(self, code, line, pos, apply=False):
846 """ 902 """
847 Private method to fix superfluous blank lines (E303). 903 Private method to fix superfluous blank lines (E303).
848 904
849 @param code code of the issue (string) 905 @param code code of the issue (string)
850 @param line line number of the issue (integer) 906 @param line line number of the issue (integer)
851 @param pos position inside line (integer) 907 @param pos position inside line (integer)
852 @keyparam apply flag indicating, that the fix should be applied 908 @keyparam apply flag indicating, that the fix should be applied
853 (boolean) 909 (boolean)
854 @return flag indicating an applied fix (boolean) and a message for 910 @return value indicating an applied/deferred fix (-1, 0, 1),
855 the fix (string) 911 a message for the fix (string) and an ID for a deferred
912 fix (integer)
856 """ 913 """
857 if apply: 914 if apply:
858 index = line - 3 915 index = line - 3
859 while index: 916 while index:
860 if self.__source[index].strip() == "": 917 if self.__source[index].strip() == "":
861 del self.__source[index] 918 del self.__source[index]
862 index -= 1 919 index -= 1
863 else: 920 else:
864 break 921 break
865 else: 922 return (1, self.trUtf8("Superfluous blank lines removed."), 0)
866 self.__stack.append((code, line, pos)) 923 else:
867 return (True, self.trUtf8("Superfluous blank lines removed.")) 924 id = self.__getID()
925 self.__stack.append((id, code, line, pos))
926 return (-1, "", id)
868 927
869 def __fixE304(self, code, line, pos, apply=False): 928 def __fixE304(self, code, line, pos, apply=False):
870 """ 929 """
871 Private method to fix superfluous blank lines after a function 930 Private method to fix superfluous blank lines after a function
872 decorator (E304). 931 decorator (E304).
874 @param code code of the issue (string) 933 @param code code of the issue (string)
875 @param line line number of the issue (integer) 934 @param line line number of the issue (integer)
876 @param pos position inside line (integer) 935 @param pos position inside line (integer)
877 @keyparam apply flag indicating, that the fix should be applied 936 @keyparam apply flag indicating, that the fix should be applied
878 (boolean) 937 (boolean)
879 @return flag indicating an applied fix (boolean) and a message for 938 @return value indicating an applied/deferred fix (-1, 0, 1),
880 the fix (string) 939 a message for the fix (string) and an ID for a deferred
940 fix (integer)
881 """ 941 """
882 if apply: 942 if apply:
883 index = line - 2 943 index = line - 2
884 while index: 944 while index:
885 if self.__source[index].strip() == "": 945 if self.__source[index].strip() == "":
886 del self.__source[index] 946 del self.__source[index]
887 index -= 1 947 index -= 1
888 else: 948 else:
889 break 949 break
890 else: 950 return (
891 self.__stack.append((code, line, pos)) 951 1,
892 return (True, self.trUtf8( 952 self.trUtf8("Superfluous blank lines after function"
893 "Superfluous blank lines after function decorator removed.")) 953 " decorator removed."),
954 0)
955 else:
956 id = self.__getID()
957 self.__stack.append((id, code, line, pos))
958 return (-1, "", id)
894 959
895 def __fixE401(self, code, line, pos, apply=False): 960 def __fixE401(self, code, line, pos, apply=False):
896 """ 961 """
897 Private method to fix multiple imports on one line (E401). 962 Private method to fix multiple imports on one line (E401).
898 963
899 @param code code of the issue (string) 964 @param code code of the issue (string)
900 @param line line number of the issue (integer) 965 @param line line number of the issue (integer)
901 @param pos position inside line (integer) 966 @param pos position inside line (integer)
902 @keyparam apply flag indicating, that the fix should be applied 967 @keyparam apply flag indicating, that the fix should be applied
903 (boolean) 968 (boolean)
904 @return flag indicating an applied fix (boolean) and a message for 969 @return value indicating an applied/deferred fix (-1, 0, 1),
905 the fix (string) 970 a message for the fix (string) and an ID for a deferred
971 fix (integer)
906 """ 972 """
907 if apply: 973 if apply:
908 line = line - 1 974 line = line - 1
909 text = self.__source[line] 975 text = self.__source[line]
910 if not text.lstrip().startswith("import"): 976 if not text.lstrip().startswith("import"):
911 return (False, "") 977 return (0, "", 0)
912 978
913 # pep8 (1.3.1) reports false positive if there is an import 979 # pep8 (1.3.1) reports false positive if there is an import
914 # statement followed by a semicolon and some unrelated 980 # statement followed by a semicolon and some unrelated
915 # statement with commas in it. 981 # statement with commas in it.
916 if ';' in text: 982 if ';' in text:
917 return (False, "") 983 return (0, "", 0)
918 984
919 newText = text[:pos].rstrip("\t ,") + self.__getEol() + \ 985 newText = text[:pos].rstrip("\t ,") + self.__getEol() + \
920 self.__getIndent(text) + "import " + text[pos:].lstrip("\t ,") 986 self.__getIndent(text) + "import " + text[pos:].lstrip("\t ,")
921 self.__source[line] = newText 987 self.__source[line] = newText
922 else: 988 return (1, self.trUtf8("Imports were put on separate lines."), 0)
923 self.__stack.append((code, line, pos)) 989 else:
924 return (True, self.trUtf8("Imports were put on separate lines.")) 990 id = self.__getID()
991 self.__stack.append((id, code, line, pos))
992 return (-1, "", id)
925 993
926 def __fixE501(self, code, line, pos, apply=False): 994 def __fixE501(self, code, line, pos, apply=False):
927 """ 995 """
928 Private method to fix the long lines by breaking them (E501). 996 Private method to fix the long lines by breaking them (E501).
929 997
930 @param code code of the issue (string) 998 @param code code of the issue (string)
931 @param line line number of the issue (integer) 999 @param line line number of the issue (integer)
932 @param pos position inside line (integer) 1000 @param pos position inside line (integer)
933 @keyparam apply flag indicating, that the fix should be applied 1001 @keyparam apply flag indicating, that the fix should be applied
934 (boolean) 1002 (boolean)
935 @return flag indicating an applied fix (boolean) and a message for 1003 @return value indicating an applied/deferred fix (-1, 0, 1),
936 the fix (string) 1004 a message for the fix (string) and an ID for a deferred
1005 fix (integer)
937 """ 1006 """
938 multilineStringLines, docStringLines = self.__multilineStringLines() 1007 multilineStringLines, docStringLines = self.__multilineStringLines()
939 if apply: 1008 if apply:
940 isDocString = line in docStringLines 1009 isDocString = line in docStringLines
941 line = line - 1 1010 line = line - 1
955 if changed: 1024 if changed:
956 if newText != text: 1025 if newText != text:
957 self.__source[line] = newText 1026 self.__source[line] = newText
958 if newNextText and newNextText != nextText: 1027 if newNextText and newNextText != nextText:
959 self.__source[line + 1] = newNextText 1028 self.__source[line + 1] = newNextText
960 else: 1029 return (1, self.trUtf8("Long lines have been shortened."), 0)
961 self.__stack.append((code, line, pos)) 1030 else:
962 return (True, self.trUtf8("Long lines have been shortened.")) 1031 return (0, "", 0)
1032 else:
1033 id = self.__getID()
1034 self.__stack.append((id, code, line, pos))
1035 return (-1, "", id)
963 1036
964 def __fixE502(self, code, line, pos): 1037 def __fixE502(self, code, line, pos):
965 """ 1038 """
966 Private method to fix redundant backslash within brackets (E502). 1039 Private method to fix redundant backslash within brackets (E502).
967 1040
968 @param code code of the issue (string) 1041 @param code code of the issue (string)
969 @param line line number of the issue (integer) 1042 @param line line number of the issue (integer)
970 @param pos position inside line (integer) 1043 @param pos position inside line (integer)
971 @return flag indicating an applied fix (boolean) and a message for 1044 @return value indicating an applied/deferred fix (-1, 0, 1),
972 the fix (string) 1045 a message for the fix (string) and an ID for a deferred
1046 fix (integer)
973 """ 1047 """
974 self.__source[line - 1] = \ 1048 self.__source[line - 1] = \
975 self.__source[line - 1].rstrip("\n\r \t\\") + self.__getEol() 1049 self.__source[line - 1].rstrip("\n\r \t\\") + self.__getEol()
976 return (True, self.trUtf8("Redundant backslash in brackets removed.")) 1050 return (1, self.trUtf8("Redundant backslash in brackets removed."), 0)
977 1051
978 def __fixE701(self, code, line, pos, apply=False): 1052 def __fixE701(self, code, line, pos, apply=False):
979 """ 1053 """
980 Private method to fix colon-separated compund statements (E701). 1054 Private method to fix colon-separated compund statements (E701).
981 1055
982 @param code code of the issue (string) 1056 @param code code of the issue (string)
983 @param line line number of the issue (integer) 1057 @param line line number of the issue (integer)
984 @param pos position inside line (integer) 1058 @param pos position inside line (integer)
985 @keyparam apply flag indicating, that the fix should be applied 1059 @keyparam apply flag indicating, that the fix should be applied
986 (boolean) 1060 (boolean)
987 @return flag indicating an applied fix (boolean) and a message for 1061 @return value indicating an applied/deferred fix (-1, 0, 1),
988 the fix (string) 1062 a message for the fix (string) and an ID for a deferred
1063 fix (integer)
989 """ 1064 """
990 if apply: 1065 if apply:
991 line = line - 1 1066 line = line - 1
992 text = self.__source[line] 1067 text = self.__source[line]
993 pos = pos + 1 1068 pos = pos + 1
994 1069
995 newText = text[:pos] + self.__getEol() + self.__getIndent(text) + \ 1070 newText = text[:pos] + self.__getEol() + self.__getIndent(text) + \
996 self.__indentWord + text[pos:].lstrip("\n\r \t\\") + \ 1071 self.__indentWord + text[pos:].lstrip("\n\r \t\\") + \
997 self.__getEol() 1072 self.__getEol()
998 self.__source[line] = newText 1073 self.__source[line] = newText
999 else: 1074 return (1, self.trUtf8("Compound statement corrected."), 0)
1000 self.__stack.append((code, line, pos)) 1075 else:
1001 return (True, self.trUtf8("Compound statement corrected.")) 1076 id = self.__getID()
1077 self.__stack.append((id, code, line, pos))
1078 return (-1, "", id)
1002 1079
1003 def __fixE702(self, code, line, pos, apply=False): 1080 def __fixE702(self, code, line, pos, apply=False):
1004 """ 1081 """
1005 Private method to fix semicolon-separated compound statements 1082 Private method to fix semicolon-separated compound statements
1006 (E702, E703). 1083 (E702, E703).
1008 @param code code of the issue (string) 1085 @param code code of the issue (string)
1009 @param line line number of the issue (integer) 1086 @param line line number of the issue (integer)
1010 @param pos position inside line (integer) 1087 @param pos position inside line (integer)
1011 @keyparam apply flag indicating, that the fix should be applied 1088 @keyparam apply flag indicating, that the fix should be applied
1012 (boolean) 1089 (boolean)
1013 @return flag indicating an applied fix (boolean) and a message for 1090 @return value indicating an applied/deferred fix (-1, 0, 1),
1014 the fix (string) 1091 a message for the fix (string) and an ID for a deferred
1092 fix (integer)
1015 """ 1093 """
1016 if apply: 1094 if apply:
1017 line = line - 1 1095 line = line - 1
1018 text = self.__source[line] 1096 text = self.__source[line]
1019 1097
1025 self.__source[line] = text.rstrip("\n\r \t;") + self.__getEol() 1103 self.__source[line] = text.rstrip("\n\r \t;") + self.__getEol()
1026 else: 1104 else:
1027 first = text[:pos].rstrip("\n\r \t;") + self.__getEol() 1105 first = text[:pos].rstrip("\n\r \t;") + self.__getEol()
1028 second = text[pos:].lstrip("\n\r \t;") 1106 second = text[pos:].lstrip("\n\r \t;")
1029 self.__source[line] = first + self.__getIndent(text) + second 1107 self.__source[line] = first + self.__getIndent(text) + second
1030 else: 1108 return (1, self.trUtf8("Compound statement corrected."), 0)
1031 self.__stack.append((code, line, pos)) 1109 else:
1032 return (True, self.trUtf8("Compound statement corrected.")) 1110 id = self.__getID()
1111 self.__stack.append((id, code, line, pos))
1112 return (-1, "", id)
1033 1113
1034 def __fixE711(self, code, line, pos): 1114 def __fixE711(self, code, line, pos):
1035 """ 1115 """
1036 Private method to fix comparison with None (E711, E712). 1116 Private method to fix comparison with None (E711, E712).
1037 1117
1038 @param code code of the issue (string) 1118 @param code code of the issue (string)
1039 @param line line number of the issue (integer) 1119 @param line line number of the issue (integer)
1040 @param pos position inside line (integer) 1120 @param pos position inside line (integer)
1041 @return flag indicating an applied fix (boolean) and a message for 1121 @return value indicating an applied/deferred fix (-1, 0, 1),
1042 the fix (string) 1122 a message for the fix (string) and an ID for a deferred
1123 fix (integer)
1043 """ 1124 """
1044 line = line - 1 1125 line = line - 1
1045 text = self.__source[line] 1126 text = self.__source[line]
1046 1127
1047 rightPos = pos + 2 1128 rightPos = pos + 2
1048 if rightPos >= len(text): 1129 if rightPos >= len(text):
1049 return (False, "") 1130 return (0, "", 0)
1050 1131
1051 left = text[:pos].rstrip() 1132 left = text[:pos].rstrip()
1052 center = text[pos:rightPos] 1133 center = text[pos:rightPos]
1053 right = text[rightPos:].lstrip() 1134 right = text[rightPos:].lstrip()
1054 1135
1055 if not right.startswith(("None", "True", "False")): 1136 if not right.startswith(("None", "True", "False")):
1056 return (False, "") 1137 return (0, "", 0)
1057 1138
1058 if center.strip() == "==": 1139 if center.strip() == "==":
1059 center = "is" 1140 center = "is"
1060 elif center.strip() == "!=": 1141 elif center.strip() == "!=":
1061 center = "is not" 1142 center = "is not"
1062 else: 1143 else:
1063 return (False, "") 1144 return (0, "", 0)
1064 1145
1065 self.__source[line] = " ".join([left, center, right]) 1146 self.__source[line] = " ".join([left, center, right])
1066 return (True, self.trUtf8("Comparison to None/True/False corrected.")) 1147 return (1, self.trUtf8("Comparison to None/True/False corrected."), 0)
1067 1148
1068 def __fixW291(self, code, line, pos): 1149 def __fixW291(self, code, line, pos):
1069 """ 1150 """
1070 Private method to fix trailing whitespace (W291, W293). 1151 Private method to fix trailing whitespace (W291, W293).
1071 1152
1072 @param code code of the issue (string) 1153 @param code code of the issue (string)
1073 @param line line number of the issue (integer) 1154 @param line line number of the issue (integer)
1074 @param pos position inside line (integer) 1155 @param pos position inside line (integer)
1075 @return flag indicating an applied fix (boolean) and a message for 1156 @return value indicating an applied/deferred fix (-1, 0, 1),
1076 the fix (string) 1157 a message for the fix (string) and an ID for a deferred
1158 fix (integer)
1077 """ 1159 """
1078 self.__source[line - 1] = re.sub(r'[\t ]+(\r?)$', r"\1", 1160 self.__source[line - 1] = re.sub(r'[\t ]+(\r?)$', r"\1",
1079 self.__source[line - 1]) 1161 self.__source[line - 1])
1080 return (True, self.trUtf8("Whitespace stripped from end of line.")) 1162 return (1, self.trUtf8("Whitespace stripped from end of line."), 0)
1081 1163
1082 def __fixW292(self, code, line, pos): 1164 def __fixW292(self, code, line, pos):
1083 """ 1165 """
1084 Private method to fix a missing newline at the end of file (W292). 1166 Private method to fix a missing newline at the end of file (W292).
1085 1167
1086 @param code code of the issue (string) 1168 @param code code of the issue (string)
1087 @param line line number of the issue (integer) 1169 @param line line number of the issue (integer)
1088 @param pos position inside line (integer) 1170 @param pos position inside line (integer)
1089 @return flag indicating an applied fix (boolean) and a message for 1171 @return value indicating an applied/deferred fix (-1, 0, 1),
1090 the fix (string) 1172 a message for the fix (string) and an ID for a deferred
1173 fix (integer)
1091 """ 1174 """
1092 self.__source[line - 1] += self.__getEol() 1175 self.__source[line - 1] += self.__getEol()
1093 return (True, self.trUtf8("newline added to end of file.")) 1176 return (1, self.trUtf8("newline added to end of file."), 0)
1094 1177
1095 def __fixW391(self, code, line, pos): 1178 def __fixW391(self, code, line, pos):
1096 """ 1179 """
1097 Private method to fix trailing blank lines (W391). 1180 Private method to fix trailing blank lines (W391).
1098 1181
1099 @param code code of the issue (string) 1182 @param code code of the issue (string)
1100 @param line line number of the issue (integer) 1183 @param line line number of the issue (integer)
1101 @param pos position inside line (integer) 1184 @param pos position inside line (integer)
1102 @return flag indicating an applied fix (boolean) and a message for 1185 @return value indicating an applied/deferred fix (-1, 0, 1),
1103 the fix (string) 1186 a message for the fix (string) and an ID for a deferred
1187 fix (integer)
1104 """ 1188 """
1105 index = line - 1 1189 index = line - 1
1106 while index: 1190 while index:
1107 if self.__source[index].strip() == "": 1191 if self.__source[index].strip() == "":
1108 del self.__source[index] 1192 del self.__source[index]
1109 index -= 1 1193 index -= 1
1110 else: 1194 else:
1111 break 1195 break
1112 return (True, self.trUtf8( 1196 return (1, self.trUtf8(
1113 "Superfluous trailing blank lines removed from end of file.")) 1197 "Superfluous trailing blank lines removed from end of file."), 0)
1114 1198
1115 def __fixW603(self, code, line, pos): 1199 def __fixW603(self, code, line, pos):
1116 """ 1200 """
1117 Private method to fix the not equal notation (W603). 1201 Private method to fix the not equal notation (W603).
1118 1202
1119 @param code code of the issue (string) 1203 @param code code of the issue (string)
1120 @param line line number of the issue (integer) 1204 @param line line number of the issue (integer)
1121 @param pos position inside line (integer) 1205 @param pos position inside line (integer)
1122 @return flag indicating an applied fix (boolean) and a message for 1206 @return value indicating an applied/deferred fix (-1, 0, 1),
1123 the fix (string) 1207 a message for the fix (string) and an ID for a deferred
1208 fix (integer)
1124 """ 1209 """
1125 self.__source[line - 1] = self.__source[line - 1].replace("<>", "!=") 1210 self.__source[line - 1] = self.__source[line - 1].replace("<>", "!=")
1126 return (True, self.trUtf8("'<>' replaced by '!='.")) 1211 return (1, self.trUtf8("'<>' replaced by '!='."), 0)
1127 1212
1128 1213
1129 class Pep8Reindenter(object): 1214 class Pep8Reindenter(object):
1130 """ 1215 """
1131 Class to reindent badly-indented code to uniformly use four-space 1216 Class to reindent badly-indented code to uniformly use four-space
1675 candidates = self.__shortenLine(tokens, source, indent) 1760 candidates = self.__shortenLine(tokens, source, indent)
1676 if candidates: 1761 if candidates:
1677 candidates = list(sorted( 1762 candidates = list(sorted(
1678 set(candidates).union([self.__text]), 1763 set(candidates).union([self.__text]),
1679 key=lambda x: self.__lineShorteningRank(x))) 1764 key=lambda x: self.__lineShorteningRank(x)))
1765 if candidates[0] == self.__text:
1766 return False, "", ""
1680 return True, candidates[0], "" 1767 return True, candidates[0], ""
1681 1768
1682 source = self.__text 1769 source = self.__text
1683 rs = source.rstrip() 1770 rs = source.rstrip()
1684 if rs.endswith(("'", '"')) and " " in source: 1771 if rs.endswith(("'", '"')) and " " in source:
1910 @param candidate candidate line to rank (string) 1997 @param candidate candidate line to rank (string)
1911 @return rank of the candidate (integer) 1998 @return rank of the candidate (integer)
1912 """ 1999 """
1913 rank = 0 2000 rank = 0
1914 if candidate.strip(): 2001 if candidate.strip():
2002 if candidate == self.__text:
2003 # give the original a disadvantage
2004 rank += 50
2005
1915 lines = candidate.split(self.__eol) 2006 lines = candidate.split(self.__eol)
1916 2007
1917 offset = 0 2008 offset = 0
1918 if lines[0].rstrip()[-1] not in '([{': 2009 if lines[0].rstrip()[-1] not in '([{':
1919 for symbol in '([{': 2010 for symbol in '([{':

eric ide

mercurial