eric6/Plugins/CheckerPlugins/CodeStyleChecker/CodeStyleFixer.py

branch
maintenance
changeset 8273
698ae46f40a4
parent 8043
0acf98cd089a
parent 8259
2bbec88047dd
equal deleted inserted replaced
8190:fb0ef164f536 8273:698ae46f40a4
8 """ 8 """
9 9
10 import os 10 import os
11 import re 11 import re
12 import tokenize 12 import tokenize
13 import contextlib
13 from io import StringIO 14 from io import StringIO
14 15
15 # CodeStyleCheckerDialog tries to import FixableCodeStyleIssues which fails 16 # CodeStyleCheckerDialog tries to import FixableCodeStyleIssues which fails
16 # under Python3. So ignore it. 17 # under Python3. So ignore it.
17 try: 18 with contextlib.suppress(ImportError):
18 import pycodestyle 19 import pycodestyle
19 except ImportError:
20 pass
21 20
22 FixableCodeStyleIssues = [ 21 FixableCodeStyleIssues = [
23 "D111", "D112", "D121", "D131", "D141", "D142", 22 "D111", "D112", "D121", "D131", "D141", "D142",
24 "D143", "D144", "D145", 23 "D143", "D144", "D145",
25 "D221", "D222", "D231", "D242", "D243", "D244", 24 "D221", "D222", "D231", "D242", "D243", "D244",
36 "N804", "N805", "N806", 35 "N804", "N805", "N806",
37 "W191", "W291", "W292", "W293", "W391", "W603", 36 "W191", "W291", "W292", "W293", "W391", "W603",
38 ] 37 ]
39 38
40 39
41 class CodeStyleFixer(object): 40 class CodeStyleFixer:
42 """ 41 """
43 Class implementing a fixer for certain code style issues. 42 Class implementing a fixer for certain code style issues.
44 """ 43 """
45 def __init__(self, filename, sourceLines, fixCodes, noFixCodes, 44 def __init__(self, filename, sourceLines, fixCodes, noFixCodes,
46 maxLineLength, blankLines, inPlace, eol, backup=False): 45 maxLineLength, blankLines, inPlace, eol, backup=False):
69 @type str 68 @type str
70 @param backup flag indicating to create a backup before fixing 69 @param backup flag indicating to create a backup before fixing
71 anything 70 anything
72 @type bool 71 @type bool
73 """ 72 """
74 super(CodeStyleFixer, self).__init__() 73 super().__init__()
75 74
76 self.__filename = filename 75 self.__filename = filename
77 self.__origName = "" 76 self.__origName = ""
78 self.__source = sourceLines[:] # save a copy 77 self.__source = sourceLines[:] # save a copy
79 self.__fixCodes = [c.strip() for c in fixCodes.split(",") if c.strip()] 78 self.__fixCodes = [c.strip() for c in fixCodes.split(",") if c.strip()]
207 # create a backup file before writing any changes 206 # create a backup file before writing any changes
208 if os.path.islink(self.__filename): 207 if os.path.islink(self.__filename):
209 bfn = '{0}~'.format(os.path.realpath(self.__filename)) 208 bfn = '{0}~'.format(os.path.realpath(self.__filename))
210 else: 209 else:
211 bfn = '{0}~'.format(self.__filename) 210 bfn = '{0}~'.format(self.__filename)
212 try: 211 with contextlib.suppress(OSError):
213 os.remove(bfn) 212 os.remove(bfn)
214 except OSError: 213 with contextlib.suppress(OSError):
215 # if there was an error, ignore it
216 pass
217 try:
218 os.rename(self.__filename, bfn) 214 os.rename(self.__filename, bfn)
219 except OSError:
220 # if there was an error, ignore it
221 pass
222 215
223 txt = "".join(self.__source) 216 txt = "".join(self.__source)
224 try: 217 try:
225 enc = 'utf-8' if encoding == 'utf-8-bom' else encoding 218 enc = 'utf-8' if encoding == 'utf-8-bom' else encoding
226 txt = txt.encode(enc) 219 txt = txt.encode(enc)
250 @return flag indicating that one string starts with the other 243 @return flag indicating that one string starts with the other
251 (boolean) 244 (boolean)
252 """ 245 """
253 return b.startswith(a) or a.startswith(b) 246 return b.startswith(a) or a.startswith(b)
254 247
255 if self.__noFixCodes: 248 if (
256 for noFixCode in [c.strip() for c in self.__noFixCodes]: 249 self.__noFixCodes and
257 if mutualStartswith(code.lower(), noFixCode.lower()): 250 any(mutualStartswith(code.lower(), noFixCode.lower())
258 return False 251 for noFixCode in [c.strip() for c in self.__noFixCodes])
252 ):
253 return False
259 254
260 if self.__fixCodes: 255 if self.__fixCodes:
261 for fixCode in [c.strip() for c in self.__fixCodes]: 256 return any(mutualStartswith(code.lower(), fixCode.lower())
262 if mutualStartswith(code.lower(), fixCode.lower()): 257 for fixCode in [c.strip() for c in self.__fixCodes])
263 return True
264 return False
265 258
266 return True 259 return True
267 260
268 def fixIssue(self, line, pos, code): 261 def fixIssue(self, line, pos, code):
269 """ 262 """
376 try: 369 try:
377 (logical_start, logical_end) = self.__findLogical() 370 (logical_start, logical_end) = self.__findLogical()
378 except (SyntaxError, tokenize.TokenError): 371 except (SyntaxError, tokenize.TokenError):
379 return None 372 return None
380 373
381 line = line - 1 374 line -= 1
382 ls = None 375 ls = None
383 le = None 376 le = None
384 for i in range(0, len(logical_start)): 377 for i in range(0, len(logical_start)):
385 x = logical_end[i] 378 x = logical_end[i]
386 if x[0] > line or (x[0] == line and x[1] > pos): 379 if x[0] > line or (x[0] == line and x[1] > pos):
399 392
400 @return string to be used for an indentation (string) 393 @return string to be used for an indentation (string)
401 """ 394 """
402 sio = StringIO("".join(self.__source)) 395 sio = StringIO("".join(self.__source))
403 indentWord = " " # default in case of failure 396 indentWord = " " # default in case of failure
404 try: 397 with contextlib.suppress(SyntaxError, tokenize.TokenError):
405 for token in tokenize.generate_tokens(sio.readline): 398 for token in tokenize.generate_tokens(sio.readline):
406 if token[0] == tokenize.INDENT: 399 if token[0] == tokenize.INDENT:
407 indentWord = token[1] 400 indentWord = token[1]
408 break 401 break
409 except (SyntaxError, tokenize.TokenError):
410 pass
411 return indentWord 402 return indentWord
412 403
413 def __getIndent(self, line): 404 def __getIndent(self, line):
414 """ 405 """
415 Private method to get the indentation string. 406 Private method to get the indentation string.
432 source = "".join(self.__source) 423 source = "".join(self.__source)
433 sio = StringIO(source) 424 sio = StringIO(source)
434 self.__multiLineNumbers = set() 425 self.__multiLineNumbers = set()
435 self.__docLineNumbers = set() 426 self.__docLineNumbers = set()
436 previousTokenType = '' 427 previousTokenType = ''
437 try: 428 with contextlib.suppress(SyntaxError, tokenize.TokenError):
438 for t in tokenize.generate_tokens(sio.readline): 429 for t in tokenize.generate_tokens(sio.readline):
439 tokenType = t[0] 430 tokenType = t[0]
440 startRow = t[2][0] 431 startRow = t[2][0]
441 endRow = t[3][0] 432 endRow = t[3][0]
442 433
447 else: 438 else:
448 self.__docLineNumbers |= set( 439 self.__docLineNumbers |= set(
449 range(startRow, 1 + endRow)) 440 range(startRow, 1 + endRow))
450 441
451 previousTokenType = tokenType 442 previousTokenType = tokenType
452 except (SyntaxError, tokenize.TokenError):
453 pass
454 443
455 return self.__multiLineNumbers, self.__docLineNumbers 444 return self.__multiLineNumbers, self.__docLineNumbers
456 445
457 def __fixReindent(self, line, pos, logical): 446 def __fixReindent(self, line, pos, logical):
458 """ 447 """
531 @return value indicating an applied/deferred fix (-1, 0, 1), 520 @return value indicating an applied/deferred fix (-1, 0, 1),
532 a message code for the fix, a list of arguments for the 521 a message code for the fix, a list of arguments for the
533 message and an ID for a deferred fix 522 message and an ID for a deferred fix
534 @rtype tuple of (int, str, list or int, int) 523 @rtype tuple of (int, str, list or int, int)
535 """ 524 """
536 line = line - 1 525 line -= 1
537 quotes = re.match(r"""\s*[ru]?('''|'|\")""", 526 quotes = re.match(r"""\s*[ru]?('''|'|\")""",
538 self.__source[line]).group(1) 527 self.__source[line]).group(1)
539 left, right = self.__source[line].split(quotes, 1) 528 left, right = self.__source[line].split(quotes, 1)
540 self.__source[line] = left + '"""' + right 529 self.__source[line] = left + '"""' + right
541 while line < len(self.__source): 530 while line < len(self.__source):
563 @return value indicating an applied/deferred fix (-1, 0, 1), 552 @return value indicating an applied/deferred fix (-1, 0, 1),
564 a message code for the fix, a list of arguments for the 553 a message code for the fix, a list of arguments for the
565 message and an ID for a deferred fix 554 message and an ID for a deferred fix
566 @rtype tuple of (int, str, list or int, int) 555 @rtype tuple of (int, str, list or int, int)
567 """ 556 """
568 line = line - 1 557 line -= 1
569 if code == "D112": 558 if code == "D112":
570 insertChar = "r" 559 insertChar = "r"
571 else: 560 else:
572 return (0, "", 0) 561 return (0, "", 0)
573 562
598 a message code for the fix, a list of arguments for the 587 a message code for the fix, a list of arguments for the
599 message and an ID for a deferred fix 588 message and an ID for a deferred fix
600 @rtype tuple of (int, str, list or int, int) 589 @rtype tuple of (int, str, list or int, int)
601 """ 590 """
602 if apply: 591 if apply:
603 line = line - 1 592 line -= 1
604 if not self.__source[line].lstrip().startswith( 593 if not self.__source[line].lstrip().startswith(
605 ('"""', 'r"""', 'u"""')): 594 ('"""', 'r"""', 'u"""')):
606 # only correctly formatted docstrings will be fixed 595 # only correctly formatted docstrings will be fixed
607 return (0, "", [], 0) 596 return (0, "", [], 0)
608 597
641 @return value indicating an applied/deferred fix (-1, 0, 1), 630 @return value indicating an applied/deferred fix (-1, 0, 1),
642 a message code for the fix, a list of arguments for the 631 a message code for the fix, a list of arguments for the
643 message and an ID for a deferred fix 632 message and an ID for a deferred fix
644 @rtype tuple of (int, str, list or int, int) 633 @rtype tuple of (int, str, list or int, int)
645 """ 634 """
646 line = line - 1 635 line -= 1
647 newText = "" 636 newText = ""
648 if ( 637 if (
649 self.__source[line].rstrip().endswith(('"""', "'''")) and 638 self.__source[line].rstrip().endswith(('"""', "'''")) and
650 self.__source[line].lstrip().startswith(('"""', 'r"""', 'u"""')) 639 self.__source[line].lstrip().startswith(('"""', 'r"""', 'u"""'))
651 ): 640 ):
692 a message code for the fix, a list of arguments for the 681 a message code for the fix, a list of arguments for the
693 message and an ID for a deferred fix 682 message and an ID for a deferred fix
694 @rtype tuple of (int, str, list or int, int) 683 @rtype tuple of (int, str, list or int, int)
695 """ 684 """
696 if apply: 685 if apply:
697 line = line - 1 686 line -= 1
698 self.__source[line - 1] = "" 687 self.__source[line - 1] = ""
699 # Blank line before function/method docstring removed. 688 # Blank line before function/method docstring removed.
700 return (1, "FIXD141", [], 0) 689 return (1, "FIXD141", [], 0)
701 else: 690 else:
702 fixId = self.__getID() 691 fixId = self.__getID()
722 a message code for the fix, a list of arguments for the 711 a message code for the fix, a list of arguments for the
723 message and an ID for a deferred fix 712 message and an ID for a deferred fix
724 @rtype tuple of (int, str, list or int, int) 713 @rtype tuple of (int, str, list or int, int)
725 """ 714 """
726 if apply: 715 if apply:
727 line = line - 1 716 line -= 1
728 self.__source[line] = self.__eol + self.__source[line] 717 self.__source[line] = self.__eol + self.__source[line]
729 # Blank line inserted before class docstring. 718 # Blank line inserted before class docstring.
730 return (1, "FIXD142", [], 0) 719 return (1, "FIXD142", [], 0)
731 else: 720 else:
732 fixId = self.__getID() 721 fixId = self.__getID()
752 a message code for the fix, a list of arguments for the 741 a message code for the fix, a list of arguments for the
753 message and an ID for a deferred fix 742 message and an ID for a deferred fix
754 @rtype tuple of (int, str, list or int, int) 743 @rtype tuple of (int, str, list or int, int)
755 """ 744 """
756 if apply: 745 if apply:
757 line = line - 1 746 line -= 1
758 self.__source[line] += self.__eol 747 self.__source[line] += self.__eol
759 # Blank line inserted after class docstring. 748 # Blank line inserted after class docstring.
760 return (1, "FIXD143", [], 0) 749 return (1, "FIXD143", [], 0)
761 else: 750 else:
762 fixId = self.__getID() 751 fixId = self.__getID()
782 a message code for the fix, a list of arguments for the 771 a message code for the fix, a list of arguments for the
783 message and an ID for a deferred fix 772 message and an ID for a deferred fix
784 @rtype tuple of (int, str, list or int, int) 773 @rtype tuple of (int, str, list or int, int)
785 """ 774 """
786 if apply: 775 if apply:
787 line = line - 1 776 line -= 1
788 if not self.__source[line].rstrip().endswith("."): 777 if not self.__source[line].rstrip().endswith("."):
789 # only correct summary lines can be fixed here 778 # only correct summary lines can be fixed here
790 return (0, "", 0) 779 return (0, "", 0)
791 780
792 self.__source[line] += self.__eol 781 self.__source[line] += self.__eol
816 a message code for the fix, a list of arguments for the 805 a message code for the fix, a list of arguments for the
817 message and an ID for a deferred fix 806 message and an ID for a deferred fix
818 @rtype tuple of (int, str, list or int, int) 807 @rtype tuple of (int, str, list or int, int)
819 """ 808 """
820 if apply: 809 if apply:
821 line = line - 1 810 line -= 1
822 self.__source[line] = self.__eol + self.__source[line] 811 self.__source[line] = self.__eol + self.__source[line]
823 # Blank line inserted after last paragraph of docstring. 812 # Blank line inserted after last paragraph of docstring.
824 return (1, "FIXD145", [], 0) 813 return (1, "FIXD145", [], 0)
825 else: 814 else:
826 fixId = self.__getID() 815 fixId = self.__getID()
846 a message code for the fix, a list of arguments for the 835 a message code for the fix, a list of arguments for the
847 message and an ID for a deferred fix 836 message and an ID for a deferred fix
848 @rtype tuple of (int, str, list or int, int) 837 @rtype tuple of (int, str, list or int, int)
849 """ 838 """
850 if apply: 839 if apply:
851 line = line - 1 840 line -= 1
852 indent = self.__getIndent(self.__source[line]) 841 indent = self.__getIndent(self.__source[line])
853 source = self.__source[line].strip() 842 source = self.__source[line].strip()
854 if code == "D221": 843 if code == "D221":
855 # leading 844 # leading
856 if source.startswith(("r", "u")): 845 if source.startswith(("r", "u")):
900 a message code for the fix, a list of arguments for the 889 a message code for the fix, a list of arguments for the
901 message and an ID for a deferred fix 890 message and an ID for a deferred fix
902 @rtype tuple of (int, str, list or int, int) 891 @rtype tuple of (int, str, list or int, int)
903 """ 892 """
904 if apply: 893 if apply:
905 line = line - 1 894 line -= 1
906 self.__source[line - 1] = "" 895 self.__source[line - 1] = ""
907 if code == "D242": 896 if code == "D242":
908 # Blank line before class docstring removed. 897 # Blank line before class docstring removed.
909 msg = "FIXD242" 898 msg = "FIXD242"
910 else: 899 else:
935 a message code for the fix, a list of arguments for the 924 a message code for the fix, a list of arguments for the
936 message and an ID for a deferred fix 925 message and an ID for a deferred fix
937 @rtype tuple of (int, str, list or int, int) 926 @rtype tuple of (int, str, list or int, int)
938 """ 927 """
939 if apply: 928 if apply:
940 line = line - 1 929 line -= 1
941 self.__source[line + 1] = "" 930 self.__source[line + 1] = ""
942 if code == "D243": 931 if code == "D243":
943 # Blank line after class docstring removed. 932 # Blank line after class docstring removed.
944 msg = "FIXD243" 933 msg = "FIXD243"
945 else: 934 else:
970 a message code for the fix, a list of arguments for the 959 a message code for the fix, a list of arguments for the
971 message and an ID for a deferred fix 960 message and an ID for a deferred fix
972 @rtype tuple of (int, str, list or int, int) 961 @rtype tuple of (int, str, list or int, int)
973 """ 962 """
974 if apply: 963 if apply:
975 line = line - 1 964 line -= 1
976 self.__source[line - 1] = "" 965 self.__source[line - 1] = ""
977 # Blank line after last paragraph removed. 966 # Blank line after last paragraph removed.
978 return (1, "FIXD247", [], 0) 967 return (1, "FIXD247", [], 0)
979 else: 968 else:
980 fixId = self.__getID() 969 fixId = self.__getID()
1077 if logical: 1066 if logical:
1078 # Fix by adding an initial indent. 1067 # Fix by adding an initial indent.
1079 modified = self.__fixReindent(line, pos, logical) 1068 modified = self.__fixReindent(line, pos, logical)
1080 if not modified: 1069 if not modified:
1081 # fall back to simple method 1070 # fall back to simple method
1082 line = line - 1 1071 line -= 1
1083 text = self.__source[line] 1072 text = self.__source[line]
1084 indentation = self.__getIndent(text) 1073 indentation = self.__getIndent(text)
1085 self.__source[line] = ( 1074 self.__source[line] = (
1086 indentation + 1075 indentation +
1087 self.__indentWord + text.lstrip() 1076 self.__indentWord + text.lstrip()
1299 @return value indicating an applied/deferred fix (-1, 0, 1), 1288 @return value indicating an applied/deferred fix (-1, 0, 1),
1300 a message code for the fix, a list of arguments for the 1289 a message code for the fix, a list of arguments for the
1301 message and an ID for a deferred fix 1290 message and an ID for a deferred fix
1302 @rtype tuple of (int, str, list or int, int) 1291 @rtype tuple of (int, str, list or int, int)
1303 """ 1292 """
1304 line = line - 1 1293 line -= 1
1305 text = self.__source[line] 1294 text = self.__source[line]
1306 1295
1307 if '"""' in text or "'''" in text or text.rstrip().endswith('\\'): 1296 if '"""' in text or "'''" in text or text.rstrip().endswith('\\'):
1308 return (0, "", [], 0) 1297 return (0, "", [], 0)
1309 1298
1331 @return value indicating an applied/deferred fix (-1, 0, 1), 1320 @return value indicating an applied/deferred fix (-1, 0, 1),
1332 a message code for the fix, a list of arguments for the 1321 a message code for the fix, a list of arguments for the
1333 message and an ID for a deferred fix 1322 message and an ID for a deferred fix
1334 @rtype tuple of (int, str, list or int, int) 1323 @rtype tuple of (int, str, list or int, int)
1335 """ 1324 """
1336 line = line - 1 1325 line -= 1
1337 text = self.__source[line] 1326 text = self.__source[line]
1338 1327
1339 if '"""' in text or "'''" in text or text.rstrip().endswith('\\'): 1328 if '"""' in text or "'''" in text or text.rstrip().endswith('\\'):
1340 return (0, "", [], 0) 1329 return (0, "", [], 0)
1341 1330
1361 @return value indicating an applied/deferred fix (-1, 0, 1), 1350 @return value indicating an applied/deferred fix (-1, 0, 1),
1362 a message code for the fix, a list of arguments for the 1351 a message code for the fix, a list of arguments for the
1363 message and an ID for a deferred fix 1352 message and an ID for a deferred fix
1364 @rtype tuple of (int, str, list or int, int) 1353 @rtype tuple of (int, str, list or int, int)
1365 """ 1354 """
1366 line = line - 1 1355 line -= 1
1367 text = self.__source[line] 1356 text = self.__source[line]
1368 1357
1369 if '"""' in text or "'''" in text or text.rstrip().endswith('\\'): 1358 if '"""' in text or "'''" in text or text.rstrip().endswith('\\'):
1370 return (0, "", [], 0) 1359 return (0, "", [], 0)
1371 1360
1406 @return value indicating an applied/deferred fix (-1, 0, 1), 1395 @return value indicating an applied/deferred fix (-1, 0, 1),
1407 a message code for the fix, a list of arguments for the 1396 a message code for the fix, a list of arguments for the
1408 message and an ID for a deferred fix 1397 message and an ID for a deferred fix
1409 @rtype tuple of (int, str, list or int, int) 1398 @rtype tuple of (int, str, list or int, int)
1410 """ 1399 """
1411 line = line - 1 1400 line -= 1
1412 pos = pos + 1 1401 pos += 1
1413 self.__source[line] = ( 1402 self.__source[line] = (
1414 self.__source[line][:pos] + 1403 self.__source[line][:pos] +
1415 " " + 1404 " " +
1416 self.__source[line][pos:] 1405 self.__source[line][pos:]
1417 ) 1406 )
1434 @return value indicating an applied/deferred fix (-1, 0, 1), 1423 @return value indicating an applied/deferred fix (-1, 0, 1),
1435 a message code for the fix, a list of arguments for the 1424 a message code for the fix, a list of arguments for the
1436 message and an ID for a deferred fix 1425 message and an ID for a deferred fix
1437 @rtype tuple of (int, str, list or int, int) 1426 @rtype tuple of (int, str, list or int, int)
1438 """ 1427 """
1439 line = line - 1 1428 line -= 1
1440 text = self.__source[line] 1429 text = self.__source[line]
1441 1430
1442 # This is necessary since pycodestyle sometimes reports columns that 1431 # This is necessary since pycodestyle sometimes reports columns that
1443 # goes past the end of the physical line. This happens in cases like, 1432 # goes past the end of the physical line. This happens in cases like,
1444 # foo(bar\n=None) 1433 # foo(bar\n=None)
1445 col = min(pos, len(text) - 1) 1434 col = min(pos, len(text) - 1)
1446 if text[col].strip(): 1435 newText = (
1447 newText = text 1436 text
1448 else: 1437 if text[col].strip() else
1449 newText = text[:col].rstrip() + text[col:].lstrip() 1438 text[:col].rstrip() + text[col:].lstrip()
1439 )
1450 1440
1451 # There could be an escaped newline 1441 # There could be an escaped newline
1452 if newText.endswith(('=\\\n', '=\\\r\n', '=\\\r')): 1442 if newText.endswith(('=\\\n', '=\\\r\n', '=\\\r')):
1453 self.__source[line] = newText.rstrip("\n\r \t\\") 1443 self.__source[line] = newText.rstrip("\n\r \t\\")
1454 self.__source[line + 1] = self.__source[line + 1].lstrip() 1444 self.__source[line + 1] = self.__source[line + 1].lstrip()
1472 @return value indicating an applied/deferred fix (-1, 0, 1), 1462 @return value indicating an applied/deferred fix (-1, 0, 1),
1473 a message code for the fix, a list of arguments for the 1463 a message code for the fix, a list of arguments for the
1474 message and an ID for a deferred fix 1464 message and an ID for a deferred fix
1475 @rtype tuple of (int, str, list or int, int) 1465 @rtype tuple of (int, str, list or int, int)
1476 """ 1466 """
1477 line = line - 1 1467 line -= 1
1478 text = self.__source[line] 1468 text = self.__source[line]
1479 left = text[:pos].rstrip(' \t#') 1469 left = text[:pos].rstrip(' \t#')
1480 right = text[pos:].lstrip(' \t#') 1470 right = text[pos:].lstrip(' \t#')
1481 newText = left + (" # " + right if right.strip() else right) 1471 newText = left + (" # " + right if right.strip() else right)
1482 self.__source[line] = newText 1472 self.__source[line] = newText
1598 a message code for the fix, a list of arguments for the 1588 a message code for the fix, a list of arguments for the
1599 message and an ID for a deferred fix 1589 message and an ID for a deferred fix
1600 @rtype tuple of (int, str, list or int, int) 1590 @rtype tuple of (int, str, list or int, int)
1601 """ 1591 """
1602 if apply: 1592 if apply:
1603 line = line - 1 1593 line -= 1
1604 text = self.__source[line] 1594 text = self.__source[line]
1605 if not text.lstrip().startswith("import"): 1595 if not text.lstrip().startswith("import"):
1606 return (0, "", [], 0) 1596 return (0, "", [], 0)
1607 1597
1608 # pycodestyle (1.3.1) reports false positive if there is an import 1598 # pycodestyle (1.3.1) reports false positive if there is an import
1648 if apply: 1638 if apply:
1649 multilineStringLines, docStringLines = ( 1639 multilineStringLines, docStringLines = (
1650 self.__multilineStringLines() 1640 self.__multilineStringLines()
1651 ) 1641 )
1652 isDocString = line in docStringLines 1642 isDocString = line in docStringLines
1653 line = line - 1 1643 line -= 1
1654 text = self.__source[line] 1644 text = self.__source[line]
1655 if line > 0: 1645 if line > 0:
1656 prevText = self.__source[line - 1] 1646 prevText = self.__source[line - 1]
1657 else: 1647 else:
1658 prevText = "" 1648 prevText = ""
1723 a message code for the fix, a list of arguments for the 1713 a message code for the fix, a list of arguments for the
1724 message and an ID for a deferred fix 1714 message and an ID for a deferred fix
1725 @rtype tuple of (int, str, list or int, int) 1715 @rtype tuple of (int, str, list or int, int)
1726 """ 1716 """
1727 if apply: 1717 if apply:
1728 line = line - 1 1718 line -= 1
1729 text = self.__source[line] 1719 text = self.__source[line]
1730 pos = pos + 1 1720 pos += 1
1731 1721
1732 newText = ( 1722 newText = (
1733 text[:pos] + 1723 text[:pos] +
1734 self.__eol + 1724 self.__eol +
1735 self.__getIndent(text) + 1725 self.__getIndent(text) +
1763 a message code for the fix, a list of arguments for the 1753 a message code for the fix, a list of arguments for the
1764 message and an ID for a deferred fix 1754 message and an ID for a deferred fix
1765 @rtype tuple of (int, str, list or int, int) 1755 @rtype tuple of (int, str, list or int, int)
1766 """ 1756 """
1767 if apply: 1757 if apply:
1768 line = line - 1 1758 line -= 1
1769 text = self.__source[line] 1759 text = self.__source[line]
1770 1760
1771 if text.rstrip().endswith("\\"): 1761 if text.rstrip().endswith("\\"):
1772 # normalize '1; \\\n2' into '1; 2' 1762 # normalize '1; \\\n2' into '1; 2'
1773 self.__source[line] = text.rstrip("\n\r \t\\") 1763 self.__source[line] = text.rstrip("\n\r \t\\")
1800 @return value indicating an applied/deferred fix (-1, 0, 1), 1790 @return value indicating an applied/deferred fix (-1, 0, 1),
1801 a message code for the fix, a list of arguments for the 1791 a message code for the fix, a list of arguments for the
1802 message and an ID for a deferred fix 1792 message and an ID for a deferred fix
1803 @rtype tuple of (int, str, list or int, int) 1793 @rtype tuple of (int, str, list or int, int)
1804 """ 1794 """
1805 line = line - 1 1795 line -= 1
1806 text = self.__source[line] 1796 text = self.__source[line]
1807 1797
1808 rightPos = pos + 2 1798 rightPos = pos + 2
1809 if rightPos >= len(text): 1799 if rightPos >= len(text):
1810 return (0, "", 0) 1800 return (0, "", 0)
1846 a message code for the fix, a list of arguments for the 1836 a message code for the fix, a list of arguments for the
1847 message and an ID for a deferred fix 1837 message and an ID for a deferred fix
1848 @rtype tuple of (int, str, list or int, int) 1838 @rtype tuple of (int, str, list or int, int)
1849 """ 1839 """
1850 if apply: 1840 if apply:
1851 line = line - 1 1841 line -= 1
1852 text = self.__source[line] 1842 text = self.__source[line]
1853 if code == "N804": 1843 if code == "N804":
1854 arg = "cls" 1844 arg = "cls"
1855 else: 1845 else:
1856 arg = "self" 1846 arg = "self"
1899 a message code for the fix, a list of arguments for the 1889 a message code for the fix, a list of arguments for the
1900 message and an ID for a deferred fix 1890 message and an ID for a deferred fix
1901 @rtype tuple of (int, str, list or int, int) 1891 @rtype tuple of (int, str, list or int, int)
1902 """ 1892 """
1903 if apply: 1893 if apply:
1904 line = line - 1 1894 line -= 1
1905 text = self.__source[line] 1895 text = self.__source[line]
1906 index = text.find("(") + 1 1896 index = text.find("(") + 1
1907 left = text[:index] 1897 left = text[:index]
1908 right = text[index:] 1898 right = text[index:]
1909 1899
1918 right = right.lstrip(", ") 1908 right = right.lstrip(", ")
1919 newText = left + right 1909 newText = left + right
1920 self.__source[line] = newText 1910 self.__source[line] = newText
1921 else: 1911 else:
1922 # they are on the next line 1912 # they are on the next line
1923 line = line + 1 1913 line += 1
1924 text = self.__source[line] 1914 text = self.__source[line]
1925 indent = self.__getIndent(text) 1915 indent = self.__getIndent(text)
1926 right = text.lstrip() 1916 right = text.lstrip()
1927 if right.startswith("cls"): 1917 if right.startswith("cls"):
1928 right = right[3:] 1918 right = right[3:]
2037 self.__source[line - 1] = self.__source[line - 1].replace("<>", "!=") 2027 self.__source[line - 1] = self.__source[line - 1].replace("<>", "!=")
2038 # '<>' replaced by '!='. 2028 # '<>' replaced by '!='.
2039 return (1, "FIXW603", [], 0) 2029 return (1, "FIXW603", [], 0)
2040 2030
2041 2031
2042 class Reindenter(object): 2032 class Reindenter:
2043 """ 2033 """
2044 Class to reindent badly-indented code to uniformly use four-space 2034 Class to reindent badly-indented code to uniformly use four-space
2045 indentation. 2035 indentation.
2046 2036
2047 Released to the public domain, by Tim Peters, 03 October 2000. 2037 Released to the public domain, by Tim Peters, 03 October 2000.
2235 while i < n and line[i] == " ": 2225 while i < n and line[i] == " ":
2236 i += 1 2226 i += 1
2237 return i 2227 return i
2238 2228
2239 2229
2240 class IndentationWrapper(object): 2230 class IndentationWrapper:
2241 """ 2231 """
2242 Class used by fixers dealing with indentation. 2232 Class used by fixers dealing with indentation.
2243 2233
2244 Each instance operates on a single logical line. 2234 Each instance operates on a single logical line.
2245 """ 2235 """
2419 ) 2409 )
2420 hang = rel_indent[row] - rel_indent[open_row] 2410 hang = rel_indent[row] - rel_indent[open_row]
2421 2411
2422 if token_type == tokenize.OP and text in ']})': 2412 if token_type == tokenize.OP and text in ']})':
2423 pass 2413 pass
2424 elif visual_indent is True: 2414 elif visual_indent is True and not indent[depth]:
2425 if not indent[depth]: 2415 indent[depth] = start[1]
2426 indent[depth] = start[1]
2427 2416
2428 # line altered: comments shouldn't define a visual indent 2417 # line altered: comments shouldn't define a visual indent
2429 if parens[row] and not indent[depth] and token_type not in ( 2418 if parens[row] and not indent[depth] and token_type not in (
2430 tokenize.NL, tokenize.COMMENT 2419 tokenize.NL, tokenize.COMMENT
2431 ): 2420 ):
2462 last_token_multiline = (start[0] != end[0]) 2451 last_token_multiline = (start[0] != end[0])
2463 2452
2464 return valid_indents 2453 return valid_indents
2465 2454
2466 2455
2467 class LineShortener(object): 2456 class LineShortener:
2468 """ 2457 """
2469 Class used to shorten lines to a given maximum of characters. 2458 Class used to shorten lines to a given maximum of characters.
2470 """ 2459 """
2471 def __init__(self, curLine, prevLine, nextLine, maxLength=79, eol="\n", 2460 def __init__(self, curLine, prevLine, nextLine, maxLength=79, eol="\n",
2472 indentWord=" ", isDocString=False): 2461 indentWord=" ", isDocString=False):
2882 badStartingSymbol = { 2871 badStartingSymbol = {
2883 '(': ')', 2872 '(': ')',
2884 '[': ']', 2873 '[': ']',
2885 '{': '}'}.get(lines[0][-1], None) 2874 '{': '}'}.get(lines[0][-1], None)
2886 2875
2887 if len(lines) > 1: 2876 if (
2888 if (badStartingSymbol and 2877 len(lines) > 1 and
2889 lines[1].lstrip().startswith(badStartingSymbol)): 2878 badStartingSymbol and
2890 rank += 20 2879 lines[1].lstrip().startswith(badStartingSymbol)
2880 ):
2881 rank += 20
2891 2882
2892 if re.match(r".*[+\-\*/] \($", lines[0]): 2883 if re.match(r".*[+\-\*/] \($", lines[0]):
2893 # "1 * (\n" is ugly as hell. 2884 # "1 * (\n" is ugly as hell.
2894 rank += 100 2885 rank += 100
2895 2886

eric ide

mercurial