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 |
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 |
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). |
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). |
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 |