632 kind, value, char = None, None, None |
632 kind, value, char = None, None, None |
633 try: |
633 try: |
634 while True: |
634 while True: |
635 start, end = None, None |
635 start, end = None, None |
636 while not (kind == tokenize.NAME and value == 'def'): |
636 while not (kind == tokenize.NAME and value == 'def'): |
637 kind, value, (line, char), _, _ = \ |
637 kind, value, (line, char), _, _ = ( |
638 next(tokenGenerator) |
638 next(tokenGenerator) |
|
639 ) |
639 start = line - 1, char |
640 start = line - 1, char |
640 kind, value, (line, char), _, _ = \ |
641 kind, value, (line, char), _, _ = ( |
641 self.__skipIndentedBlock(tokenGenerator) |
642 self.__skipIndentedBlock(tokenGenerator) |
|
643 ) |
642 end = line - 1, char |
644 end = line - 1, char |
643 startLine = classContext.start() + start[0] |
645 startLine = classContext.start() + start[0] |
644 endLine = classContext.start() + end[0] |
646 endLine = classContext.start() + end[0] |
645 context = DocStyleContext( |
647 context = DocStyleContext( |
646 self.__source[startLine:endLine], |
648 self.__source[startLine:endLine], |
647 startLine, "def") |
649 startLine, "def") |
648 if startLine > 0: |
650 if startLine > 0: |
649 if self.__source[startLine - 1].strip() == \ |
651 if ( |
650 "@staticmethod": |
652 self.__source[startLine - 1].strip() == |
|
653 "@staticmethod" |
|
654 ): |
651 context.setSpecial("staticmethod") |
655 context.setSpecial("staticmethod") |
652 elif self.__source[startLine - 1].strip() == \ |
656 elif ( |
653 "@classmethod": |
657 self.__source[startLine - 1].strip() == |
|
658 "@classmethod" |
|
659 ): |
654 context.setSpecial("classmethod") |
660 context.setSpecial("classmethod") |
655 contexts.append(context) |
661 contexts.append(context) |
656 except StopIteration: |
662 except StopIteration: |
657 pass |
663 pass |
658 self.__methodsCache = contexts |
664 self.__methodsCache = contexts |
701 docstring = docstringContext.ssource() |
707 docstring = docstringContext.ssource() |
702 if (not docstring or not docstring.strip() or |
708 if (not docstring or not docstring.strip() or |
703 not docstring.strip('\'"')): |
709 not docstring.strip('\'"')): |
704 self.__error(context.start(), 0, "D101") |
710 self.__error(context.start(), 0, "D101") |
705 |
711 |
706 if self.__docType == "eric" and \ |
712 if ( |
707 docstring.strip('\'"').strip() == "Module documentation goes here.": |
713 self.__docType == "eric" and |
|
714 docstring.strip('\'"').strip() == |
|
715 "Module documentation goes here." |
|
716 ): |
708 self.__error(docstringContext.end(), 0, "D201") |
717 self.__error(docstringContext.end(), 0, "D201") |
709 return |
718 return |
710 |
719 |
711 def __checkFunctionDocstring(self, docstringContext, context): |
720 def __checkFunctionDocstring(self, docstringContext, context): |
712 """ |
721 """ |
732 docstring = docstringContext.ssource() |
741 docstring = docstringContext.ssource() |
733 if (not docstring or not docstring.strip() or |
742 if (not docstring or not docstring.strip() or |
734 not docstring.strip('\'"')): |
743 not docstring.strip('\'"')): |
735 self.__error(context.start(), 0, code) |
744 self.__error(context.start(), 0, code) |
736 |
745 |
737 if self.__docType == "eric" and \ |
746 if ( |
738 docstring.strip('\'"').strip() == \ |
747 self.__docType == "eric" and |
739 "Function documentation goes here.": |
748 docstring.strip('\'"').strip() == |
|
749 "Function documentation goes here." |
|
750 ): |
740 self.__error(docstringContext.end(), 0, "D202") |
751 self.__error(docstringContext.end(), 0, "D202") |
741 return |
752 return |
742 |
753 |
743 def __checkClassDocstring(self, docstringContext, context): |
754 def __checkClassDocstring(self, docstringContext, context): |
744 """ |
755 """ |
765 if (not docstring or not docstring.strip() or |
776 if (not docstring or not docstring.strip() or |
766 not docstring.strip('\'"')): |
777 not docstring.strip('\'"')): |
767 self.__error(context.start(), 0, code) |
778 self.__error(context.start(), 0, code) |
768 return |
779 return |
769 |
780 |
770 if self.__docType == "eric" and \ |
781 if ( |
771 docstring.strip('\'"').strip() == "Class documentation goes here.": |
782 self.__docType == "eric" and |
|
783 docstring.strip('\'"').strip() == "Class documentation goes here." |
|
784 ): |
772 self.__error(docstringContext.end(), 0, "D206") |
785 self.__error(docstringContext.end(), 0, "D206") |
773 return |
786 return |
774 |
787 |
775 def __checkTripleDoubleQuotes(self, docstringContext, context): |
788 def __checkTripleDoubleQuotes(self, docstringContext, context): |
776 """ |
789 """ |
812 """ |
825 """ |
813 if docstringContext is None: |
826 if docstringContext is None: |
814 return |
827 return |
815 |
828 |
816 docstring = docstringContext.ssource().strip() |
829 docstring = docstringContext.ssource().strip() |
817 if not docstring.startswith('u"""') and \ |
830 if ( |
818 any(ord(char) > 127 for char in docstring): |
831 not docstring.startswith('u"""') and |
|
832 any(ord(char) > 127 for char in docstring) |
|
833 ): |
819 self.__error(docstringContext.start(), 0, "D113") |
834 self.__error(docstringContext.start(), 0, "D113") |
820 |
835 |
821 def __checkOneLiner(self, docstringContext, context): |
836 def __checkOneLiner(self, docstringContext, context): |
822 """ |
837 """ |
823 Private method to check, that one-liner docstrings fit on |
838 Private method to check, that one-liner docstrings fit on |
925 if docstringContext is None: |
940 if docstringContext is None: |
926 return |
941 return |
927 |
942 |
928 functionName = context.source()[0].lstrip().split()[1].split("(")[0] |
943 functionName = context.source()[0].lstrip().split()[1].split("(")[0] |
929 summary, lineNumber = self.__getSummaryLine(docstringContext) |
944 summary, lineNumber = self.__getSummaryLine(docstringContext) |
930 if functionName + "(" in summary.replace(" ", "") and \ |
945 if ( |
931 not functionName + "()" in summary.replace(" ", ""): |
946 functionName + "(" in summary.replace(" ", "") and |
|
947 not functionName + "()" in summary.replace(" ", "") |
|
948 ): |
932 # report only, if it is not an abbreviated form (i.e. function() ) |
949 # report only, if it is not an abbreviated form (i.e. function() ) |
933 self.__error(docstringContext.start() + lineNumber, 0, "D133") |
950 self.__error(docstringContext.start() + lineNumber, 0, "D133") |
934 |
951 |
935 def __checkReturnType(self, docstringContext, context): |
952 def __checkReturnType(self, docstringContext, context): |
936 """ |
953 """ |
963 if docstringContext is None: |
980 if docstringContext is None: |
964 return |
981 return |
965 |
982 |
966 contextLines = context.source() |
983 contextLines = context.source() |
967 cti = 0 |
984 cti = 0 |
968 while cti < len(contextLines) and \ |
985 while ( |
969 not contextLines[cti].strip().startswith( |
986 cti < len(contextLines) and |
970 ('"""', 'r"""', 'u"""', "'''", "r'''", "u'''")): |
987 not contextLines[cti].strip().startswith( |
|
988 ('"""', 'r"""', 'u"""', "'''", "r'''", "u'''")) |
|
989 ): |
971 cti += 1 |
990 cti += 1 |
972 if cti == len(contextLines): |
991 if cti == len(contextLines): |
973 return |
992 return |
974 |
993 |
975 if not contextLines[cti - 1].strip(): |
994 if not contextLines[cti - 1].strip(): |
986 if docstringContext is None: |
1005 if docstringContext is None: |
987 return |
1006 return |
988 |
1007 |
989 contextLines = context.source() |
1008 contextLines = context.source() |
990 cti = 0 |
1009 cti = 0 |
991 while cti < len(contextLines) and \ |
1010 while ( |
|
1011 cti < len(contextLines) and |
992 not contextLines[cti].strip().startswith( |
1012 not contextLines[cti].strip().startswith( |
993 ('"""', 'r"""', 'u"""', "'''", "r'''", "u'''")): |
1013 ('"""', 'r"""', 'u"""', "'''", "r'''", "u'''")) |
|
1014 ): |
994 cti += 1 |
1015 cti += 1 |
995 if cti == len(contextLines): |
1016 if cti == len(contextLines): |
996 return |
1017 return |
997 |
1018 |
998 start = cti |
1019 start = cti |
999 if contextLines[cti].strip() in ( |
1020 if contextLines[cti].strip() in ( |
1000 '"""', 'r"""', 'u"""', "'''", "r'''", "u'''"): |
1021 '"""', 'r"""', 'u"""', "'''", "r'''", "u'''"): |
1001 # it is a multi line docstring |
1022 # it is a multi line docstring |
1002 cti += 1 |
1023 cti += 1 |
1003 |
1024 |
1004 while cti < len(contextLines) and \ |
1025 while ( |
1005 not contextLines[cti].strip().endswith(('"""', "'''")): |
1026 cti < len(contextLines) and |
|
1027 not contextLines[cti].strip().endswith(('"""', "'''")) |
|
1028 ): |
1006 cti += 1 |
1029 cti += 1 |
1007 end = cti |
1030 end = cti |
1008 if cti >= len(contextLines) - 1: |
1031 if cti >= len(contextLines) - 1: |
1009 return |
1032 return |
1010 |
1033 |
1087 summaryLines, lineNumber = self.__getSummaryLines(docstringContext) |
1110 summaryLines, lineNumber = self.__getSummaryLines(docstringContext) |
1088 if summaryLines: |
1111 if summaryLines: |
1089 if summaryLines[-1].lstrip().startswith("@"): |
1112 if summaryLines[-1].lstrip().startswith("@"): |
1090 summaryLines.pop(-1) |
1113 summaryLines.pop(-1) |
1091 summary = " ".join([s.strip() for s in summaryLines if s]) |
1114 summary = " ".join([s.strip() for s in summaryLines if s]) |
1092 if summary and not summary.endswith(".") and \ |
1115 if ( |
1093 not summary.split(None, 1)[0].lower() == "constructor": |
1116 summary and |
|
1117 not summary.endswith(".") and |
|
1118 not summary.split(None, 1)[0].lower() == "constructor" |
|
1119 ): |
1094 self.__error( |
1120 self.__error( |
1095 docstringContext.start() + lineNumber + |
1121 docstringContext.start() + lineNumber + |
1096 len(summaryLines) - 1, |
1122 len(summaryLines) - 1, |
1097 0, "D231") |
1123 0, "D231") |
1098 |
1124 |
1197 tokensLen = len(tokens) |
1223 tokensLen = len(tokens) |
1198 for i, token in enumerate(tokens): |
1224 for i, token in enumerate(tokens): |
1199 if token[1] == "raise": |
1225 if token[1] == "raise": |
1200 exceptions.add(tokens[i + 1][0]) |
1226 exceptions.add(tokens[i + 1][0]) |
1201 if tokens[i + 1][0] == tokenize.NAME: |
1227 if tokens[i + 1][0] == tokenize.NAME: |
1202 if tokensLen > (i + 2) and \ |
1228 if ( |
1203 tokens[i + 2][1] == ".": |
1229 tokensLen > (i + 2) and |
|
1230 tokens[i + 2][1] == "." |
|
1231 ): |
1204 raisedExceptions.add("{0}.{1}".format( |
1232 raisedExceptions.add("{0}.{1}".format( |
1205 tokens[i + 1][1], tokens[i + 3][1])) |
1233 tokens[i + 1][1], tokens[i + 3][1])) |
1206 else: |
1234 else: |
1207 raisedExceptions.add(tokens[i + 1][1]) |
1235 raisedExceptions.add(tokens[i + 1][1]) |
1208 |
1236 |
1209 if "@exception" not in docstringContext.ssource() and \ |
1237 if ( |
1210 "@throws" not in docstringContext.ssource() and \ |
1238 "@exception" not in docstringContext.ssource() and |
1211 "@raise" not in docstringContext.ssource(): |
1239 "@throws" not in docstringContext.ssource() and |
|
1240 "@raise" not in docstringContext.ssource() |
|
1241 ): |
1212 if (exceptions - |
1242 if (exceptions - |
1213 {tokenize.COMMENT, tokenize.NL, tokenize.NEWLINE} != |
1243 {tokenize.COMMENT, tokenize.NL, tokenize.NEWLINE} != |
1214 set()): |
1244 set()): |
1215 self.__error(docstringContext.end(), 0, "D250") |
1245 self.__error(docstringContext.end(), 0, "D250") |
1216 else: |
1246 else: |
1327 return |
1357 return |
1328 |
1358 |
1329 contextLines = context.source() |
1359 contextLines = context.source() |
1330 isClassContext = contextLines[0].lstrip().startswith("class ") |
1360 isClassContext = contextLines[0].lstrip().startswith("class ") |
1331 cti = 0 |
1361 cti = 0 |
1332 while cti < len(contextLines) and \ |
1362 while ( |
|
1363 cti < len(contextLines) and |
1333 not contextLines[cti].strip().startswith( |
1364 not contextLines[cti].strip().startswith( |
1334 ('"""', 'r"""', 'u"""', "'''", "r'''", "u'''")): |
1365 ('"""', 'r"""', 'u"""', "'''", "r'''", "u'''")) |
|
1366 ): |
1335 cti += 1 |
1367 cti += 1 |
1336 if cti == len(contextLines): |
1368 if cti == len(contextLines): |
1337 return |
1369 return |
1338 |
1370 |
1339 start = cti |
1371 start = cti |
1340 if contextLines[cti].strip() in ( |
1372 if contextLines[cti].strip() in ( |
1341 '"""', 'r"""', 'u"""', "'''", "r'''", "u'''"): |
1373 '"""', 'r"""', 'u"""', "'''", "r'''", "u'''"): |
1342 # it is a multi line docstring |
1374 # it is a multi line docstring |
1343 cti += 1 |
1375 cti += 1 |
1344 |
1376 |
1345 while cti < len(contextLines) and \ |
1377 while ( |
1346 not contextLines[cti].strip().endswith(('"""', "'''")): |
1378 cti < len(contextLines) and |
|
1379 not contextLines[cti].strip().endswith(('"""', "'''")) |
|
1380 ): |
1347 cti += 1 |
1381 cti += 1 |
1348 end = cti |
1382 end = cti |
1349 if cti >= len(contextLines) - 1: |
1383 if cti >= len(contextLines) - 1: |
1350 return |
1384 return |
1351 |
1385 |
1392 |
1426 |
1393 summary, lineNumber = self.__getSummaryLine(docstringContext) |
1427 summary, lineNumber = self.__getSummaryLine(docstringContext) |
1394 if summary: |
1428 if summary: |
1395 # check, if the first word is 'Constructor', 'Public', |
1429 # check, if the first word is 'Constructor', 'Public', |
1396 # 'Protected' or 'Private' |
1430 # 'Protected' or 'Private' |
1397 functionName, arguments = context.source()[0].lstrip()\ |
1431 functionName, arguments = ( |
1398 .split()[1].split("(", 1) |
1432 context.source()[0].lstrip().split()[1].split("(", 1) |
|
1433 ) |
1399 firstWord = summary.strip().split(None, 1)[0].lower() |
1434 firstWord = summary.strip().split(None, 1)[0].lower() |
1400 if functionName == '__init__': |
1435 if functionName == '__init__': |
1401 if firstWord != 'constructor': |
1436 if firstWord != 'constructor': |
1402 self.__error(docstringContext.start() + lineNumber, 0, |
1437 self.__error(docstringContext.start() + lineNumber, 0, |
1403 "D232", 'constructor') |
1438 "D232", 'constructor') |
1404 elif functionName.startswith('__') and \ |
1439 elif ( |
1405 functionName.endswith('__'): |
1440 functionName.startswith('__') and |
|
1441 functionName.endswith('__') |
|
1442 ): |
1406 if firstWord != 'special': |
1443 if firstWord != 'special': |
1407 self.__error(docstringContext.start() + lineNumber, 0, |
1444 self.__error(docstringContext.start() + lineNumber, 0, |
1408 "D232", 'special') |
1445 "D232", 'special') |
1409 elif context.special() == "staticmethod": |
1446 elif context.special() == "staticmethod": |
1410 secondWord = summary.strip().split(None, 2)[1].lower() |
1447 secondWord = summary.strip().split(None, 2)[1].lower() |
1414 elif secondWord == 'static': |
1451 elif secondWord == 'static': |
1415 if functionName.startswith(('__', 'on_')): |
1452 if functionName.startswith(('__', 'on_')): |
1416 if firstWord != 'private': |
1453 if firstWord != 'private': |
1417 self.__error(docstringContext.start() + lineNumber, |
1454 self.__error(docstringContext.start() + lineNumber, |
1418 0, "D232", 'private static') |
1455 0, "D232", 'private static') |
1419 elif functionName.startswith('_') or \ |
1456 elif ( |
1420 functionName.endswith('Event'): |
1457 functionName.startswith('_') or |
|
1458 functionName.endswith('Event') |
|
1459 ): |
1421 if firstWord != 'protected': |
1460 if firstWord != 'protected': |
1422 self.__error(docstringContext.start() + lineNumber, |
1461 self.__error(docstringContext.start() + lineNumber, |
1423 0, "D232", 'protected static') |
1462 0, "D232", 'protected static') |
1424 else: |
1463 else: |
1425 if firstWord != 'public': |
1464 if firstWord != 'public': |
1426 self.__error(docstringContext.start() + lineNumber, |
1465 self.__error(docstringContext.start() + lineNumber, |
1427 0, "D232", 'public static') |
1466 0, "D232", 'public static') |
1428 elif arguments.startswith(('cls,', 'cls)')) or \ |
1467 elif ( |
1429 context.special() == "classmethod": |
1468 arguments.startswith(('cls,', 'cls)')) or |
|
1469 context.special() == "classmethod" |
|
1470 ): |
1430 secondWord = summary.strip().split(None, 2)[1].lower() |
1471 secondWord = summary.strip().split(None, 2)[1].lower() |
1431 if firstWord != 'class' and secondWord != 'class': |
1472 if firstWord != 'class' and secondWord != 'class': |
1432 self.__error(docstringContext.start() + lineNumber, 0, |
1473 self.__error(docstringContext.start() + lineNumber, 0, |
1433 "D232", 'class') |
1474 "D232", 'class') |
1434 elif secondWord == 'class': |
1475 elif secondWord == 'class': |
1435 if functionName.startswith(('__', 'on_')): |
1476 if functionName.startswith(('__', 'on_')): |
1436 if firstWord != 'private': |
1477 if firstWord != 'private': |
1437 self.__error(docstringContext.start() + lineNumber, |
1478 self.__error(docstringContext.start() + lineNumber, |
1438 0, "D232", 'private class') |
1479 0, "D232", 'private class') |
1439 elif functionName.startswith('_') or \ |
1480 elif ( |
1440 functionName.endswith('Event'): |
1481 functionName.startswith('_') or |
|
1482 functionName.endswith('Event') |
|
1483 ): |
1441 if firstWord != 'protected': |
1484 if firstWord != 'protected': |
1442 self.__error(docstringContext.start() + lineNumber, |
1485 self.__error(docstringContext.start() + lineNumber, |
1443 0, "D232", 'protected class') |
1486 0, "D232", 'protected class') |
1444 else: |
1487 else: |
1445 if firstWord != 'public': |
1488 if firstWord != 'public': |
1447 0, "D232", 'public class') |
1490 0, "D232", 'public class') |
1448 elif functionName.startswith(('__', 'on_')): |
1491 elif functionName.startswith(('__', 'on_')): |
1449 if firstWord != 'private': |
1492 if firstWord != 'private': |
1450 self.__error(docstringContext.start() + lineNumber, 0, |
1493 self.__error(docstringContext.start() + lineNumber, 0, |
1451 "D232", 'private') |
1494 "D232", 'private') |
1452 elif functionName.startswith('_') or \ |
1495 elif ( |
1453 functionName.endswith('Event'): |
1496 functionName.startswith('_') or |
|
1497 functionName.endswith('Event') |
|
1498 ): |
1454 if firstWord != 'protected': |
1499 if firstWord != 'protected': |
1455 self.__error(docstringContext.start() + lineNumber, 0, |
1500 self.__error(docstringContext.start() + lineNumber, 0, |
1456 "D232", 'protected') |
1501 "D232", 'protected') |
1457 else: |
1502 else: |
1458 if firstWord != 'public': |
1503 if firstWord != 'public': |