69 @type str |
69 @type str |
70 @param backup flag indicating to create a backup before fixing |
70 @param backup flag indicating to create a backup before fixing |
71 anything |
71 anything |
72 @type bool |
72 @type bool |
73 """ |
73 """ |
74 super(CodeStyleFixer, self).__init__() |
74 super().__init__() |
75 |
75 |
76 self.__filename = filename |
76 self.__filename = filename |
77 self.__origName = "" |
77 self.__origName = "" |
78 self.__source = sourceLines[:] # save a copy |
78 self.__source = sourceLines[:] # save a copy |
79 self.__fixCodes = [c.strip() for c in fixCodes.split(",") if c.strip()] |
79 self.__fixCodes = [c.strip() for c in fixCodes.split(",") if c.strip()] |
376 try: |
376 try: |
377 (logical_start, logical_end) = self.__findLogical() |
377 (logical_start, logical_end) = self.__findLogical() |
378 except (SyntaxError, tokenize.TokenError): |
378 except (SyntaxError, tokenize.TokenError): |
379 return None |
379 return None |
380 |
380 |
381 line = line - 1 |
381 line -= 1 |
382 ls = None |
382 ls = None |
383 le = None |
383 le = None |
384 for i in range(0, len(logical_start)): |
384 for i in range(0, len(logical_start)): |
385 x = logical_end[i] |
385 x = logical_end[i] |
386 if x[0] > line or (x[0] == line and x[1] > pos): |
386 if x[0] > line or (x[0] == line and x[1] > pos): |
531 @return value indicating an applied/deferred fix (-1, 0, 1), |
531 @return value indicating an applied/deferred fix (-1, 0, 1), |
532 a message code for the fix, a list of arguments for the |
532 a message code for the fix, a list of arguments for the |
533 message and an ID for a deferred fix |
533 message and an ID for a deferred fix |
534 @rtype tuple of (int, str, list or int, int) |
534 @rtype tuple of (int, str, list or int, int) |
535 """ |
535 """ |
536 line = line - 1 |
536 line -= 1 |
537 quotes = re.match(r"""\s*[ru]?('''|'|\")""", |
537 quotes = re.match(r"""\s*[ru]?('''|'|\")""", |
538 self.__source[line]).group(1) |
538 self.__source[line]).group(1) |
539 left, right = self.__source[line].split(quotes, 1) |
539 left, right = self.__source[line].split(quotes, 1) |
540 self.__source[line] = left + '"""' + right |
540 self.__source[line] = left + '"""' + right |
541 while line < len(self.__source): |
541 while line < len(self.__source): |
563 @return value indicating an applied/deferred fix (-1, 0, 1), |
563 @return value indicating an applied/deferred fix (-1, 0, 1), |
564 a message code for the fix, a list of arguments for the |
564 a message code for the fix, a list of arguments for the |
565 message and an ID for a deferred fix |
565 message and an ID for a deferred fix |
566 @rtype tuple of (int, str, list or int, int) |
566 @rtype tuple of (int, str, list or int, int) |
567 """ |
567 """ |
568 line = line - 1 |
568 line -= 1 |
569 if code == "D112": |
569 if code == "D112": |
570 insertChar = "r" |
570 insertChar = "r" |
571 else: |
571 else: |
572 return (0, "", 0) |
572 return (0, "", 0) |
573 |
573 |
598 a message code for the fix, a list of arguments for the |
598 a message code for the fix, a list of arguments for the |
599 message and an ID for a deferred fix |
599 message and an ID for a deferred fix |
600 @rtype tuple of (int, str, list or int, int) |
600 @rtype tuple of (int, str, list or int, int) |
601 """ |
601 """ |
602 if apply: |
602 if apply: |
603 line = line - 1 |
603 line -= 1 |
604 if not self.__source[line].lstrip().startswith( |
604 if not self.__source[line].lstrip().startswith( |
605 ('"""', 'r"""', 'u"""')): |
605 ('"""', 'r"""', 'u"""')): |
606 # only correctly formatted docstrings will be fixed |
606 # only correctly formatted docstrings will be fixed |
607 return (0, "", [], 0) |
607 return (0, "", [], 0) |
608 |
608 |
641 @return value indicating an applied/deferred fix (-1, 0, 1), |
641 @return value indicating an applied/deferred fix (-1, 0, 1), |
642 a message code for the fix, a list of arguments for the |
642 a message code for the fix, a list of arguments for the |
643 message and an ID for a deferred fix |
643 message and an ID for a deferred fix |
644 @rtype tuple of (int, str, list or int, int) |
644 @rtype tuple of (int, str, list or int, int) |
645 """ |
645 """ |
646 line = line - 1 |
646 line -= 1 |
647 newText = "" |
647 newText = "" |
648 if ( |
648 if ( |
649 self.__source[line].rstrip().endswith(('"""', "'''")) and |
649 self.__source[line].rstrip().endswith(('"""', "'''")) and |
650 self.__source[line].lstrip().startswith(('"""', 'r"""', 'u"""')) |
650 self.__source[line].lstrip().startswith(('"""', 'r"""', 'u"""')) |
651 ): |
651 ): |
692 a message code for the fix, a list of arguments for the |
692 a message code for the fix, a list of arguments for the |
693 message and an ID for a deferred fix |
693 message and an ID for a deferred fix |
694 @rtype tuple of (int, str, list or int, int) |
694 @rtype tuple of (int, str, list or int, int) |
695 """ |
695 """ |
696 if apply: |
696 if apply: |
697 line = line - 1 |
697 line -= 1 |
698 self.__source[line - 1] = "" |
698 self.__source[line - 1] = "" |
699 # Blank line before function/method docstring removed. |
699 # Blank line before function/method docstring removed. |
700 return (1, "FIXD141", [], 0) |
700 return (1, "FIXD141", [], 0) |
701 else: |
701 else: |
702 fixId = self.__getID() |
702 fixId = self.__getID() |
722 a message code for the fix, a list of arguments for the |
722 a message code for the fix, a list of arguments for the |
723 message and an ID for a deferred fix |
723 message and an ID for a deferred fix |
724 @rtype tuple of (int, str, list or int, int) |
724 @rtype tuple of (int, str, list or int, int) |
725 """ |
725 """ |
726 if apply: |
726 if apply: |
727 line = line - 1 |
727 line -= 1 |
728 self.__source[line] = self.__eol + self.__source[line] |
728 self.__source[line] = self.__eol + self.__source[line] |
729 # Blank line inserted before class docstring. |
729 # Blank line inserted before class docstring. |
730 return (1, "FIXD142", [], 0) |
730 return (1, "FIXD142", [], 0) |
731 else: |
731 else: |
732 fixId = self.__getID() |
732 fixId = self.__getID() |
752 a message code for the fix, a list of arguments for the |
752 a message code for the fix, a list of arguments for the |
753 message and an ID for a deferred fix |
753 message and an ID for a deferred fix |
754 @rtype tuple of (int, str, list or int, int) |
754 @rtype tuple of (int, str, list or int, int) |
755 """ |
755 """ |
756 if apply: |
756 if apply: |
757 line = line - 1 |
757 line -= 1 |
758 self.__source[line] += self.__eol |
758 self.__source[line] += self.__eol |
759 # Blank line inserted after class docstring. |
759 # Blank line inserted after class docstring. |
760 return (1, "FIXD143", [], 0) |
760 return (1, "FIXD143", [], 0) |
761 else: |
761 else: |
762 fixId = self.__getID() |
762 fixId = self.__getID() |
782 a message code for the fix, a list of arguments for the |
782 a message code for the fix, a list of arguments for the |
783 message and an ID for a deferred fix |
783 message and an ID for a deferred fix |
784 @rtype tuple of (int, str, list or int, int) |
784 @rtype tuple of (int, str, list or int, int) |
785 """ |
785 """ |
786 if apply: |
786 if apply: |
787 line = line - 1 |
787 line -= 1 |
788 if not self.__source[line].rstrip().endswith("."): |
788 if not self.__source[line].rstrip().endswith("."): |
789 # only correct summary lines can be fixed here |
789 # only correct summary lines can be fixed here |
790 return (0, "", 0) |
790 return (0, "", 0) |
791 |
791 |
792 self.__source[line] += self.__eol |
792 self.__source[line] += self.__eol |
816 a message code for the fix, a list of arguments for the |
816 a message code for the fix, a list of arguments for the |
817 message and an ID for a deferred fix |
817 message and an ID for a deferred fix |
818 @rtype tuple of (int, str, list or int, int) |
818 @rtype tuple of (int, str, list or int, int) |
819 """ |
819 """ |
820 if apply: |
820 if apply: |
821 line = line - 1 |
821 line -= 1 |
822 self.__source[line] = self.__eol + self.__source[line] |
822 self.__source[line] = self.__eol + self.__source[line] |
823 # Blank line inserted after last paragraph of docstring. |
823 # Blank line inserted after last paragraph of docstring. |
824 return (1, "FIXD145", [], 0) |
824 return (1, "FIXD145", [], 0) |
825 else: |
825 else: |
826 fixId = self.__getID() |
826 fixId = self.__getID() |
846 a message code for the fix, a list of arguments for the |
846 a message code for the fix, a list of arguments for the |
847 message and an ID for a deferred fix |
847 message and an ID for a deferred fix |
848 @rtype tuple of (int, str, list or int, int) |
848 @rtype tuple of (int, str, list or int, int) |
849 """ |
849 """ |
850 if apply: |
850 if apply: |
851 line = line - 1 |
851 line -= 1 |
852 indent = self.__getIndent(self.__source[line]) |
852 indent = self.__getIndent(self.__source[line]) |
853 source = self.__source[line].strip() |
853 source = self.__source[line].strip() |
854 if code == "D221": |
854 if code == "D221": |
855 # leading |
855 # leading |
856 if source.startswith(("r", "u")): |
856 if source.startswith(("r", "u")): |
900 a message code for the fix, a list of arguments for the |
900 a message code for the fix, a list of arguments for the |
901 message and an ID for a deferred fix |
901 message and an ID for a deferred fix |
902 @rtype tuple of (int, str, list or int, int) |
902 @rtype tuple of (int, str, list or int, int) |
903 """ |
903 """ |
904 if apply: |
904 if apply: |
905 line = line - 1 |
905 line -= 1 |
906 self.__source[line - 1] = "" |
906 self.__source[line - 1] = "" |
907 if code == "D242": |
907 if code == "D242": |
908 # Blank line before class docstring removed. |
908 # Blank line before class docstring removed. |
909 msg = "FIXD242" |
909 msg = "FIXD242" |
910 else: |
910 else: |
935 a message code for the fix, a list of arguments for the |
935 a message code for the fix, a list of arguments for the |
936 message and an ID for a deferred fix |
936 message and an ID for a deferred fix |
937 @rtype tuple of (int, str, list or int, int) |
937 @rtype tuple of (int, str, list or int, int) |
938 """ |
938 """ |
939 if apply: |
939 if apply: |
940 line = line - 1 |
940 line -= 1 |
941 self.__source[line + 1] = "" |
941 self.__source[line + 1] = "" |
942 if code == "D243": |
942 if code == "D243": |
943 # Blank line after class docstring removed. |
943 # Blank line after class docstring removed. |
944 msg = "FIXD243" |
944 msg = "FIXD243" |
945 else: |
945 else: |
970 a message code for the fix, a list of arguments for the |
970 a message code for the fix, a list of arguments for the |
971 message and an ID for a deferred fix |
971 message and an ID for a deferred fix |
972 @rtype tuple of (int, str, list or int, int) |
972 @rtype tuple of (int, str, list or int, int) |
973 """ |
973 """ |
974 if apply: |
974 if apply: |
975 line = line - 1 |
975 line -= 1 |
976 self.__source[line - 1] = "" |
976 self.__source[line - 1] = "" |
977 # Blank line after last paragraph removed. |
977 # Blank line after last paragraph removed. |
978 return (1, "FIXD247", [], 0) |
978 return (1, "FIXD247", [], 0) |
979 else: |
979 else: |
980 fixId = self.__getID() |
980 fixId = self.__getID() |
1077 if logical: |
1077 if logical: |
1078 # Fix by adding an initial indent. |
1078 # Fix by adding an initial indent. |
1079 modified = self.__fixReindent(line, pos, logical) |
1079 modified = self.__fixReindent(line, pos, logical) |
1080 if not modified: |
1080 if not modified: |
1081 # fall back to simple method |
1081 # fall back to simple method |
1082 line = line - 1 |
1082 line -= 1 |
1083 text = self.__source[line] |
1083 text = self.__source[line] |
1084 indentation = self.__getIndent(text) |
1084 indentation = self.__getIndent(text) |
1085 self.__source[line] = ( |
1085 self.__source[line] = ( |
1086 indentation + |
1086 indentation + |
1087 self.__indentWord + text.lstrip() |
1087 self.__indentWord + text.lstrip() |
1299 @return value indicating an applied/deferred fix (-1, 0, 1), |
1299 @return value indicating an applied/deferred fix (-1, 0, 1), |
1300 a message code for the fix, a list of arguments for the |
1300 a message code for the fix, a list of arguments for the |
1301 message and an ID for a deferred fix |
1301 message and an ID for a deferred fix |
1302 @rtype tuple of (int, str, list or int, int) |
1302 @rtype tuple of (int, str, list or int, int) |
1303 """ |
1303 """ |
1304 line = line - 1 |
1304 line -= 1 |
1305 text = self.__source[line] |
1305 text = self.__source[line] |
1306 |
1306 |
1307 if '"""' in text or "'''" in text or text.rstrip().endswith('\\'): |
1307 if '"""' in text or "'''" in text or text.rstrip().endswith('\\'): |
1308 return (0, "", [], 0) |
1308 return (0, "", [], 0) |
1309 |
1309 |
1331 @return value indicating an applied/deferred fix (-1, 0, 1), |
1331 @return value indicating an applied/deferred fix (-1, 0, 1), |
1332 a message code for the fix, a list of arguments for the |
1332 a message code for the fix, a list of arguments for the |
1333 message and an ID for a deferred fix |
1333 message and an ID for a deferred fix |
1334 @rtype tuple of (int, str, list or int, int) |
1334 @rtype tuple of (int, str, list or int, int) |
1335 """ |
1335 """ |
1336 line = line - 1 |
1336 line -= 1 |
1337 text = self.__source[line] |
1337 text = self.__source[line] |
1338 |
1338 |
1339 if '"""' in text or "'''" in text or text.rstrip().endswith('\\'): |
1339 if '"""' in text or "'''" in text or text.rstrip().endswith('\\'): |
1340 return (0, "", [], 0) |
1340 return (0, "", [], 0) |
1341 |
1341 |
1361 @return value indicating an applied/deferred fix (-1, 0, 1), |
1361 @return value indicating an applied/deferred fix (-1, 0, 1), |
1362 a message code for the fix, a list of arguments for the |
1362 a message code for the fix, a list of arguments for the |
1363 message and an ID for a deferred fix |
1363 message and an ID for a deferred fix |
1364 @rtype tuple of (int, str, list or int, int) |
1364 @rtype tuple of (int, str, list or int, int) |
1365 """ |
1365 """ |
1366 line = line - 1 |
1366 line -= 1 |
1367 text = self.__source[line] |
1367 text = self.__source[line] |
1368 |
1368 |
1369 if '"""' in text or "'''" in text or text.rstrip().endswith('\\'): |
1369 if '"""' in text or "'''" in text or text.rstrip().endswith('\\'): |
1370 return (0, "", [], 0) |
1370 return (0, "", [], 0) |
1371 |
1371 |
1406 @return value indicating an applied/deferred fix (-1, 0, 1), |
1406 @return value indicating an applied/deferred fix (-1, 0, 1), |
1407 a message code for the fix, a list of arguments for the |
1407 a message code for the fix, a list of arguments for the |
1408 message and an ID for a deferred fix |
1408 message and an ID for a deferred fix |
1409 @rtype tuple of (int, str, list or int, int) |
1409 @rtype tuple of (int, str, list or int, int) |
1410 """ |
1410 """ |
1411 line = line - 1 |
1411 line -= 1 |
1412 pos = pos + 1 |
1412 pos += 1 |
1413 self.__source[line] = ( |
1413 self.__source[line] = ( |
1414 self.__source[line][:pos] + |
1414 self.__source[line][:pos] + |
1415 " " + |
1415 " " + |
1416 self.__source[line][pos:] |
1416 self.__source[line][pos:] |
1417 ) |
1417 ) |
1434 @return value indicating an applied/deferred fix (-1, 0, 1), |
1434 @return value indicating an applied/deferred fix (-1, 0, 1), |
1435 a message code for the fix, a list of arguments for the |
1435 a message code for the fix, a list of arguments for the |
1436 message and an ID for a deferred fix |
1436 message and an ID for a deferred fix |
1437 @rtype tuple of (int, str, list or int, int) |
1437 @rtype tuple of (int, str, list or int, int) |
1438 """ |
1438 """ |
1439 line = line - 1 |
1439 line -= 1 |
1440 text = self.__source[line] |
1440 text = self.__source[line] |
1441 |
1441 |
1442 # This is necessary since pycodestyle sometimes reports columns that |
1442 # This is necessary since pycodestyle sometimes reports columns that |
1443 # goes past the end of the physical line. This happens in cases like, |
1443 # goes past the end of the physical line. This happens in cases like, |
1444 # foo(bar\n=None) |
1444 # foo(bar\n=None) |
1472 @return value indicating an applied/deferred fix (-1, 0, 1), |
1472 @return value indicating an applied/deferred fix (-1, 0, 1), |
1473 a message code for the fix, a list of arguments for the |
1473 a message code for the fix, a list of arguments for the |
1474 message and an ID for a deferred fix |
1474 message and an ID for a deferred fix |
1475 @rtype tuple of (int, str, list or int, int) |
1475 @rtype tuple of (int, str, list or int, int) |
1476 """ |
1476 """ |
1477 line = line - 1 |
1477 line -= 1 |
1478 text = self.__source[line] |
1478 text = self.__source[line] |
1479 left = text[:pos].rstrip(' \t#') |
1479 left = text[:pos].rstrip(' \t#') |
1480 right = text[pos:].lstrip(' \t#') |
1480 right = text[pos:].lstrip(' \t#') |
1481 newText = left + (" # " + right if right.strip() else right) |
1481 newText = left + (" # " + right if right.strip() else right) |
1482 self.__source[line] = newText |
1482 self.__source[line] = newText |
1598 a message code for the fix, a list of arguments for the |
1598 a message code for the fix, a list of arguments for the |
1599 message and an ID for a deferred fix |
1599 message and an ID for a deferred fix |
1600 @rtype tuple of (int, str, list or int, int) |
1600 @rtype tuple of (int, str, list or int, int) |
1601 """ |
1601 """ |
1602 if apply: |
1602 if apply: |
1603 line = line - 1 |
1603 line -= 1 |
1604 text = self.__source[line] |
1604 text = self.__source[line] |
1605 if not text.lstrip().startswith("import"): |
1605 if not text.lstrip().startswith("import"): |
1606 return (0, "", [], 0) |
1606 return (0, "", [], 0) |
1607 |
1607 |
1608 # pycodestyle (1.3.1) reports false positive if there is an import |
1608 # pycodestyle (1.3.1) reports false positive if there is an import |
1648 if apply: |
1648 if apply: |
1649 multilineStringLines, docStringLines = ( |
1649 multilineStringLines, docStringLines = ( |
1650 self.__multilineStringLines() |
1650 self.__multilineStringLines() |
1651 ) |
1651 ) |
1652 isDocString = line in docStringLines |
1652 isDocString = line in docStringLines |
1653 line = line - 1 |
1653 line -= 1 |
1654 text = self.__source[line] |
1654 text = self.__source[line] |
1655 if line > 0: |
1655 if line > 0: |
1656 prevText = self.__source[line - 1] |
1656 prevText = self.__source[line - 1] |
1657 else: |
1657 else: |
1658 prevText = "" |
1658 prevText = "" |
1723 a message code for the fix, a list of arguments for the |
1723 a message code for the fix, a list of arguments for the |
1724 message and an ID for a deferred fix |
1724 message and an ID for a deferred fix |
1725 @rtype tuple of (int, str, list or int, int) |
1725 @rtype tuple of (int, str, list or int, int) |
1726 """ |
1726 """ |
1727 if apply: |
1727 if apply: |
1728 line = line - 1 |
1728 line -= 1 |
1729 text = self.__source[line] |
1729 text = self.__source[line] |
1730 pos = pos + 1 |
1730 pos += 1 |
1731 |
1731 |
1732 newText = ( |
1732 newText = ( |
1733 text[:pos] + |
1733 text[:pos] + |
1734 self.__eol + |
1734 self.__eol + |
1735 self.__getIndent(text) + |
1735 self.__getIndent(text) + |
1763 a message code for the fix, a list of arguments for the |
1763 a message code for the fix, a list of arguments for the |
1764 message and an ID for a deferred fix |
1764 message and an ID for a deferred fix |
1765 @rtype tuple of (int, str, list or int, int) |
1765 @rtype tuple of (int, str, list or int, int) |
1766 """ |
1766 """ |
1767 if apply: |
1767 if apply: |
1768 line = line - 1 |
1768 line -= 1 |
1769 text = self.__source[line] |
1769 text = self.__source[line] |
1770 |
1770 |
1771 if text.rstrip().endswith("\\"): |
1771 if text.rstrip().endswith("\\"): |
1772 # normalize '1; \\\n2' into '1; 2' |
1772 # normalize '1; \\\n2' into '1; 2' |
1773 self.__source[line] = text.rstrip("\n\r \t\\") |
1773 self.__source[line] = text.rstrip("\n\r \t\\") |
1800 @return value indicating an applied/deferred fix (-1, 0, 1), |
1800 @return value indicating an applied/deferred fix (-1, 0, 1), |
1801 a message code for the fix, a list of arguments for the |
1801 a message code for the fix, a list of arguments for the |
1802 message and an ID for a deferred fix |
1802 message and an ID for a deferred fix |
1803 @rtype tuple of (int, str, list or int, int) |
1803 @rtype tuple of (int, str, list or int, int) |
1804 """ |
1804 """ |
1805 line = line - 1 |
1805 line -= 1 |
1806 text = self.__source[line] |
1806 text = self.__source[line] |
1807 |
1807 |
1808 rightPos = pos + 2 |
1808 rightPos = pos + 2 |
1809 if rightPos >= len(text): |
1809 if rightPos >= len(text): |
1810 return (0, "", 0) |
1810 return (0, "", 0) |
1846 a message code for the fix, a list of arguments for the |
1846 a message code for the fix, a list of arguments for the |
1847 message and an ID for a deferred fix |
1847 message and an ID for a deferred fix |
1848 @rtype tuple of (int, str, list or int, int) |
1848 @rtype tuple of (int, str, list or int, int) |
1849 """ |
1849 """ |
1850 if apply: |
1850 if apply: |
1851 line = line - 1 |
1851 line -= 1 |
1852 text = self.__source[line] |
1852 text = self.__source[line] |
1853 if code == "N804": |
1853 if code == "N804": |
1854 arg = "cls" |
1854 arg = "cls" |
1855 else: |
1855 else: |
1856 arg = "self" |
1856 arg = "self" |
1899 a message code for the fix, a list of arguments for the |
1899 a message code for the fix, a list of arguments for the |
1900 message and an ID for a deferred fix |
1900 message and an ID for a deferred fix |
1901 @rtype tuple of (int, str, list or int, int) |
1901 @rtype tuple of (int, str, list or int, int) |
1902 """ |
1902 """ |
1903 if apply: |
1903 if apply: |
1904 line = line - 1 |
1904 line -= 1 |
1905 text = self.__source[line] |
1905 text = self.__source[line] |
1906 index = text.find("(") + 1 |
1906 index = text.find("(") + 1 |
1907 left = text[:index] |
1907 left = text[:index] |
1908 right = text[index:] |
1908 right = text[index:] |
1909 |
1909 |
1918 right = right.lstrip(", ") |
1918 right = right.lstrip(", ") |
1919 newText = left + right |
1919 newText = left + right |
1920 self.__source[line] = newText |
1920 self.__source[line] = newText |
1921 else: |
1921 else: |
1922 # they are on the next line |
1922 # they are on the next line |
1923 line = line + 1 |
1923 line += 1 |
1924 text = self.__source[line] |
1924 text = self.__source[line] |
1925 indent = self.__getIndent(text) |
1925 indent = self.__getIndent(text) |
1926 right = text.lstrip() |
1926 right = text.lstrip() |
1927 if right.startswith("cls"): |
1927 if right.startswith("cls"): |
1928 right = right[3:] |
1928 right = right[3:] |