457 @param node reference to the AST node to be checked |
457 @param node reference to the AST node to be checked |
458 @type ast.BoolOp |
458 @type ast.BoolOp |
459 """ |
459 """ |
460 if isinstance(node.op, ast.Or): |
460 if isinstance(node.op, ast.Or): |
461 for variable in self.__getDuplicatedIsinstanceCall(node): |
461 for variable in self.__getDuplicatedIsinstanceCall(node): |
462 self.__error(node.lineno - 1, node.col_offset, "Y-101", variable) |
462 self.__error(node, "Y-101", variable) |
463 |
463 |
464 def __check102(self, node): |
464 def __check102(self, node): |
465 """ |
465 """ |
466 Private method to check for nested if statements without else blocks. |
466 Private method to check for nested if statements without else blocks. |
467 |
467 |
494 # pass |
494 # pass |
495 # elif b: <--- this is treated like a nested block |
495 # elif b: <--- this is treated like a nested block |
496 # if c: <--- |
496 # if c: <--- |
497 # d |
497 # d |
498 if isPattern1: |
498 if isPattern1: |
499 self.__error(node.lineno - 1, node.col_offset, "Y-102") |
499 self.__error(node, "Y-102") |
500 |
500 |
501 def __check103(self, node): |
501 def __check103(self, node): |
502 """ |
502 """ |
503 Private method to check for calls that wrap a condition to return |
503 Private method to check for calls that wrap a condition to return |
504 a bool. |
504 a bool. |
524 node.orelse[0].value.value is True |
524 node.orelse[0].value.value is True |
525 or node.orelse[0].value.value is False |
525 or node.orelse[0].value.value is False |
526 ) |
526 ) |
527 ): |
527 ): |
528 condition = unparse(node.test) |
528 condition = unparse(node.test) |
529 self.__error(node.lineno - 1, node.col_offset, "Y-103", condition) |
529 self.__error(node, "Y-103", condition) |
530 |
530 |
531 def __check104(self, node): |
531 def __check104(self, node): |
532 """ |
532 """ |
533 Private method to check for "iterate and yield" patterns. |
533 Private method to check for "iterate and yield" patterns. |
534 |
534 |
555 ): |
555 ): |
556 parent = getattr(parent, "parent", None) |
556 parent = getattr(parent, "parent", None) |
557 |
557 |
558 if not isinstance(parent, ast.AsyncFunctionDef): |
558 if not isinstance(parent, ast.AsyncFunctionDef): |
559 iterable = unparse(node.iter) |
559 iterable = unparse(node.iter) |
560 self.__error(node.lineno - 1, node.col_offset, "Y-104", iterable) |
560 self.__error(node, "Y-104", iterable) |
561 |
561 |
562 def __check105(self, node): |
562 def __check105(self, node): |
563 """ |
563 """ |
564 Private method to check for "try-except-pass" patterns. |
564 Private method to check for "try-except-pass" patterns. |
565 |
565 |
581 exception = "Exception" |
581 exception = "Exception" |
582 elif isinstance(node.handlers[0].type, ast.Tuple): |
582 elif isinstance(node.handlers[0].type, ast.Tuple): |
583 exception = ", ".join([unparse(n) for n in node.handlers[0].type.elts]) |
583 exception = ", ".join([unparse(n) for n in node.handlers[0].type.elts]) |
584 else: |
584 else: |
585 exception = unparse(node.handlers[0].type) |
585 exception = unparse(node.handlers[0].type) |
586 self.__error(node.lineno - 1, node.col_offset, "Y-105", exception) |
586 self.__error(node, "Y-105", exception) |
587 |
587 |
588 def __check106(self, node): |
588 def __check106(self, node): |
589 """ |
589 """ |
590 Private method to check for calls where an exception is raised in else. |
590 Private method to check for calls where an exception is raised in else. |
591 |
591 |
607 and len(node.orelse) >= 1 |
607 and len(node.orelse) >= 1 |
608 and isinstance(node.orelse[-1], ast.Raise) |
608 and isinstance(node.orelse[-1], ast.Raise) |
609 and not isinstance(node.body[-1], ast.Raise) |
609 and not isinstance(node.body[-1], ast.Raise) |
610 ) |
610 ) |
611 if just_one or many: |
611 if just_one or many: |
612 self.__error(node.lineno - 1, node.col_offset, "Y-106") |
612 self.__error(node, "Y-106") |
613 |
613 |
614 def __check107(self, node): |
614 def __check107(self, node): |
615 """ |
615 """ |
616 Private method to check for calls where try/except and finally have |
616 Private method to check for calls where try/except and finally have |
617 'return'. |
617 'return'. |
646 finallyHasReturn = True |
646 finallyHasReturn = True |
647 finallyReturn = stmt |
647 finallyReturn = stmt |
648 break |
648 break |
649 |
649 |
650 if (tryHasReturn or exceptHasReturn) and finallyHasReturn: |
650 if (tryHasReturn or exceptHasReturn) and finallyHasReturn: |
651 self.__error(finallyReturn.lineno - 1, finallyReturn.col_offset, "Y-107") |
651 self.__error(finallyReturn, "Y-107") |
652 |
652 |
653 def __check108(self, node): |
653 def __check108(self, node): |
654 """ |
654 """ |
655 Private method to check for if-elses which could be a ternary |
655 Private method to check for if-elses which could be a ternary |
656 operator assignment. |
656 operator assignment. |
697 |
697 |
698 body = unparse(node.body[0].value) |
698 body = unparse(node.body[0].value) |
699 cond = unparse(node.test) |
699 cond = unparse(node.test) |
700 orelse = unparse(node.orelse[0].value) |
700 orelse = unparse(node.orelse[0].value) |
701 |
701 |
702 self.__error( |
702 self.__error(node, "Y-108", assign, body, cond, orelse) |
703 node.lineno - 1, node.col_offset, "Y-108", assign, body, cond, orelse |
|
704 ) |
|
705 |
703 |
706 def __check109(self, node): |
704 def __check109(self, node): |
707 """ |
705 """ |
708 Private method to check for multiple equalities with the same value |
706 Private method to check for multiple equalities with the same value |
709 are combined via "or". |
707 are combined via "or". |
736 for value, values in id2count.items(): |
734 for value, values in id2count.items(): |
737 if len(values) == 1: |
735 if len(values) == 1: |
738 continue |
736 continue |
739 |
737 |
740 self.__error( |
738 self.__error( |
741 node.lineno - 1, |
739 node, "Y-109", value, unparse(ast.Tuple(elts=values)), unparse(node) |
742 node.col_offset, |
|
743 "Y-109", |
|
744 value, |
|
745 unparse(ast.Tuple(elts=values)), |
|
746 unparse(node), |
|
747 ) |
740 ) |
748 |
741 |
749 def __check110_111(self, node): |
742 def __check110_111(self, node): |
750 """ |
743 """ |
751 Private method to check if any / all could be used. |
744 Private method to check if any / all could be used. |
773 ): |
766 ): |
774 check = unparse(node.body[0].test) |
767 check = unparse(node.body[0].test) |
775 target = unparse(node.target) |
768 target = unparse(node.target) |
776 iterable = unparse(node.iter) |
769 iterable = unparse(node.iter) |
777 if node.body[0].body[0].value.value is True: |
770 if node.body[0].body[0].value.value is True: |
778 self.__error( |
771 self.__error(node, "Y-110", check, target, iterable) |
779 node.lineno - 1, node.col_offset, "Y-110", check, target, iterable |
|
780 ) |
|
781 elif node.body[0].body[0].value.value is False: |
772 elif node.body[0].body[0].value.value is False: |
782 isCompoundExpression = " and " in check or " or " in check |
773 isCompoundExpression = " and " in check or " or " in check |
783 |
774 |
784 if isCompoundExpression: |
775 if isCompoundExpression: |
785 check = f"not ({check})" |
776 check = f"not ({check})" |
786 else: |
777 else: |
787 if check.startswith("not "): |
778 if check.startswith("not "): |
788 check = check[len("not ") :] |
779 check = check[len("not ") :] |
789 else: |
780 else: |
790 check = f"not {check}" |
781 check = f"not {check}" |
791 self.__error( |
782 self.__error(node, "Y-111", check, target, iterable) |
792 node.lineno - 1, node.col_offset, "Y-111", check, target, iterable |
|
793 ) |
|
794 |
783 |
795 def __check112(self, node): |
784 def __check112(self, node): |
796 """ |
785 """ |
797 Private method to check for non-capitalized calls to environment |
786 Private method to check for non-capitalized calls to environment |
798 variables. |
787 variables. |
860 defaultValue = unparse(node.value.args[1]) |
849 defaultValue = unparse(node.value.args[1]) |
861 expected = f"os.environ.get('{envName.upper()}', '{defaultValue}')" |
850 expected = f"os.environ.get('{envName.upper()}', '{defaultValue}')" |
862 else: |
851 else: |
863 return |
852 return |
864 |
853 |
865 self.__error(node.lineno - 1, node.col_offset, "Y-112", expected, original) |
854 self.__error(node, "Y-112", expected, original) |
866 |
855 |
867 def __check113(self, node): |
856 def __check113(self, node): |
868 """ |
857 """ |
869 Private method to check for loops in which "enumerate" should be |
858 Private method to check for loops in which "enumerate" should be |
870 used. |
859 used. |
909 while sibling is not None: |
898 while sibling is not None: |
910 sibling = sibling.previous_sibling |
899 sibling = sibling.previous_sibling |
911 |
900 |
912 for match in matches: |
901 for match in matches: |
913 variable = unparse(match) |
902 variable = unparse(match) |
914 self.__error(match.lineno - 1, match.col_offset, "Y-113", variable) |
903 self.__error(match, "Y-113", variable) |
915 |
904 |
916 def __check114(self, node): |
905 def __check114(self, node): |
917 """ |
906 """ |
918 Private method to check for alternative if clauses with identical |
907 Private method to check for alternative if clauses with identical |
919 bodies. |
908 bodies. |
932 ifbody1 = ifBodyPairs[i] |
921 ifbody1 = ifBodyPairs[i] |
933 ifbody2 = ifBodyPairs[i + 1] |
922 ifbody2 = ifBodyPairs[i + 1] |
934 if self.__isSameBody(ifbody1[1], ifbody2[1]): |
923 if self.__isSameBody(ifbody1[1], ifbody2[1]): |
935 errorPairs.append((ifbody1, ifbody2)) |
924 errorPairs.append((ifbody1, ifbody2)) |
936 for ifbody1, ifbody2 in errorPairs: |
925 for ifbody1, ifbody2 in errorPairs: |
937 self.__error( |
926 self.__error(ifbody1[0], "Y-114", unparse(ifbody1[0]), unparse(ifbody2[0])) |
938 ifbody1[0].lineno - 1, |
|
939 ifbody1[0].col_offset, |
|
940 "Y-114", |
|
941 unparse(ifbody1[0]), |
|
942 unparse(ifbody2[0]), |
|
943 ) |
|
944 |
927 |
945 def __check115(self, node): |
928 def __check115(self, node): |
946 """ |
929 """ |
947 Private method to to check for places where open() is called without |
930 Private method to to check for places where open() is called without |
948 a context handler. |
931 a context handler. |
956 if ( |
939 if ( |
957 isinstance(node.func, ast.Name) |
940 isinstance(node.func, ast.Name) |
958 and node.func.id == "open" |
941 and node.func.id == "open" |
959 and not isinstance(node.parent, ast.withitem) |
942 and not isinstance(node.parent, ast.withitem) |
960 ): |
943 ): |
961 self.__error(node.lineno - 1, node.col_offset, "Y-115") |
944 self.__error(node, "Y-115") |
962 |
945 |
963 def __check116(self, node): |
946 def __check116(self, node): |
964 """ |
947 """ |
965 Private method to check for places with 3 or more consecutive |
948 Private method to check for places with 3 or more consecutive |
966 if-statements with direct returns. |
949 if-statements with direct returns. |
1052 if elseValue: |
1035 if elseValue: |
1053 ret = f"{keyValuePairs}.get({variable.id}, {elseValue})" |
1036 ret = f"{keyValuePairs}.get({variable.id}, {elseValue})" |
1054 else: |
1037 else: |
1055 ret = f"{keyValuePairs}.get({variable.id})" |
1038 ret = f"{keyValuePairs}.get({variable.id})" |
1056 |
1039 |
1057 self.__error(node.lineno - 1, node.col_offset, "Y-116", ret) |
1040 self.__error(node, "Y-116", ret) |
1058 |
1041 |
1059 def __check117(self, node): |
1042 def __check117(self, node): |
1060 """ |
1043 """ |
1061 Private method to check for multiple with-statements with same scope. |
1044 Private method to check for multiple with-statements with same scope. |
1062 |
1045 |
1069 if len(node.body) == 1 and isinstance(node.body[0], ast.With): |
1052 if len(node.body) == 1 and isinstance(node.body[0], ast.With): |
1070 withItems = [] |
1053 withItems = [] |
1071 for withitem in node.items + node.body[0].items: |
1054 for withitem in node.items + node.body[0].items: |
1072 withItems.append(f"{unparse(withitem)}") |
1055 withItems.append(f"{unparse(withitem)}") |
1073 mergedWith = f"with {', '.join(withItems)}:" |
1056 mergedWith = f"with {', '.join(withItems)}:" |
1074 self.__error(node.lineno - 1, node.col_offset, "Y-117", mergedWith) |
1057 self.__error(node, "Y-117", mergedWith) |
1075 |
1058 |
1076 def __check118(self, node): |
1059 def __check118(self, node): |
1077 """ |
1060 """ |
1078 Private method to check for usages of "key in dict.keys()". |
1061 Private method to check for usages of "key in dict.keys()". |
1079 |
1062 |
1113 if isinstance(node, ast.Compare): |
1096 if isinstance(node, ast.Compare): |
1114 keyStr = unparse(node.left) |
1097 keyStr = unparse(node.left) |
1115 else: |
1098 else: |
1116 keyStr = unparse(node.target) |
1099 keyStr = unparse(node.target) |
1117 dictStr = unparse(attrNode.value) |
1100 dictStr = unparse(attrNode.value) |
1118 self.__error(node.lineno - 1, node.col_offset, "Y-118", keyStr, dictStr) |
1101 self.__error(node, "Y-118", keyStr, dictStr) |
1119 |
1102 |
1120 def __check119(self, node): |
1103 def __check119(self, node): |
1121 """ |
1104 """ |
1122 Private method to check for classes that should be "dataclasses". |
1105 Private method to check for classes that should be "dataclasses". |
1123 |
1106 |
1143 |
1126 |
1144 if ( |
1127 if ( |
1145 hasOnlyConstructorMethod |
1128 hasOnlyConstructorMethod |
1146 and sum(1 for el in node.body if isinstance(el, ast.FunctionDef)) > 0 |
1129 and sum(1 for el in node.body if isinstance(el, ast.FunctionDef)) > 0 |
1147 ): |
1130 ): |
1148 self.__error(node.lineno - 1, node.col_offset, "Y-119", node.name) |
1131 self.__error(node, "Y-119", node.name) |
1149 |
1132 |
1150 def __check120_121(self, node): |
1133 def __check120_121(self, node): |
1151 """ |
1134 """ |
1152 Private method to check for classes that inherit from object. |
1135 Private method to check for classes that inherit from object. |
1153 |
1136 |
1159 if ( |
1142 if ( |
1160 len(node.bases) == 1 |
1143 len(node.bases) == 1 |
1161 and isinstance(node.bases[0], ast.Name) |
1144 and isinstance(node.bases[0], ast.Name) |
1162 and node.bases[0].id == "object" |
1145 and node.bases[0].id == "object" |
1163 ): |
1146 ): |
1164 self.__error(node.lineno - 1, node.col_offset, "Y-120", node.name) |
1147 self.__error(node, "Y-120", node.name) |
1165 |
1148 |
1166 elif ( |
1149 elif ( |
1167 len(node.bases) > 1 |
1150 len(node.bases) > 1 |
1168 and isinstance(node.bases[-1], ast.Name) |
1151 and isinstance(node.bases[-1], ast.Name) |
1169 and node.bases[-1].id == "object" |
1152 and node.bases[-1].id == "object" |
1170 ): |
1153 ): |
1171 self.__error( |
1154 self.__error( |
1172 node.lineno - 1, |
1155 node, "Y-121", node.name, ", ".join(b.id for b in node.bases[:-1]) |
1173 node.col_offset, |
|
1174 "Y-121", |
|
1175 node.name, |
|
1176 ", ".join(b.id for b in node.bases[:-1]), |
|
1177 ) |
1156 ) |
1178 |
1157 |
1179 def __check122(self, node): |
1158 def __check122(self, node): |
1180 """ |
1159 """ |
1181 Private method to check for all if-blocks which only check if a key |
1160 Private method to check for all if-blocks which only check if a key |
1202 and isinstance(node.test.comparators[0], ast.Name) |
1181 and isinstance(node.test.comparators[0], ast.Name) |
1203 and node.body[0].value.value.id == node.test.comparators[0].id |
1182 and node.body[0].value.value.id == node.test.comparators[0].id |
1204 ): |
1183 ): |
1205 key = unparse(node.test.left) |
1184 key = unparse(node.test.left) |
1206 dictname = unparse(node.test.comparators[0]) |
1185 dictname = unparse(node.test.comparators[0]) |
1207 self.__error(node.lineno - 1, node.col_offset, "Y-122", dictname, key) |
1186 self.__error(node, "Y-122", dictname, key) |
1208 |
1187 |
1209 def __check123(self, node): |
1188 def __check123(self, node): |
1210 """ |
1189 """ |
1211 Private method to check for complicated dictionary access with default value. |
1190 Private method to check for complicated dictionary access with default value. |
1212 |
1191 |
1264 dictStr = unparse(dictName) |
1243 dictStr = unparse(dictName) |
1265 defaultStr = unparse(defaultValue) |
1244 defaultStr = unparse(defaultValue) |
1266 valueStr = unparse(valueNode) |
1245 valueStr = unparse(valueNode) |
1267 else: |
1246 else: |
1268 return |
1247 return |
1269 self.__error( |
1248 self.__error(node, "Y-123", valueStr, dictStr, keyStr, defaultStr) |
1270 node.lineno - 1, |
|
1271 node.col_offset, |
|
1272 "Y-123", |
|
1273 valueStr, |
|
1274 dictStr, |
|
1275 keyStr, |
|
1276 defaultStr, |
|
1277 ) |
|
1278 |
1249 |
1279 def __check181(self, node): |
1250 def __check181(self, node): |
1280 """ |
1251 """ |
1281 Private method to check for assignments that could be converted into |
1252 Private method to check for assignments that could be converted into |
1282 an augmented assignment. |
1253 an augmented assignment. |
1292 and isinstance(node.value.left, ast.Name) |
1263 and isinstance(node.value.left, ast.Name) |
1293 and node.value.left.id == node.targets[0].id |
1264 and node.value.left.id == node.targets[0].id |
1294 and not isinstance(node.value.right, ast.Tuple) |
1265 and not isinstance(node.value.right, ast.Tuple) |
1295 ): |
1266 ): |
1296 newNode = ast.AugAssign(node.targets[0], node.value.op, node.value.right) |
1267 newNode = ast.AugAssign(node.targets[0], node.value.op, node.value.right) |
1297 self.__error( |
1268 self.__error(node, "Y-181", unparse(newNode), unparse(node)) |
1298 node.lineno - 1, |
|
1299 node.col_offset, |
|
1300 "Y-181", |
|
1301 unparse(newNode), |
|
1302 unparse(node), |
|
1303 ) |
|
1304 |
1269 |
1305 def __check182(self, node): |
1270 def __check182(self, node): |
1306 """ |
1271 """ |
1307 Private method to check for calls of type 'super()' that could |
1272 Private method to check for calls of type 'super()' that could |
1308 be shortened to 'super()'. |
1273 be shortened to 'super()'. |
1318 and len(node.args) == 2 |
1283 and len(node.args) == 2 |
1319 and all(isinstance(arg, ast.Name) for arg in node.args) |
1284 and all(isinstance(arg, ast.Name) for arg in node.args) |
1320 and node.args[0].id == self.__classDefinitionStack[-1] |
1285 and node.args[0].id == self.__classDefinitionStack[-1] |
1321 and node.args[1].id == "self" |
1286 and node.args[1].id == "self" |
1322 ): |
1287 ): |
1323 self.__error(node.lineno - 1, node.col_offset, "Y-182", unparse(node)) |
1288 self.__error(node, "Y-182", unparse(node)) |
1324 |
1289 |
1325 def __check201(self, node): |
1290 def __check201(self, node): |
1326 """ |
1291 """ |
1327 Private method to check for calls where an unary 'not' is used for |
1292 Private method to check for calls where an unary 'not' is used for |
1328 an unequality. |
1293 an unequality. |
1342 and self.__isExceptionCheck(node.parent) |
1307 and self.__isExceptionCheck(node.parent) |
1343 ): |
1308 ): |
1344 comparison = node.operand |
1309 comparison = node.operand |
1345 left = unparse(comparison.left) |
1310 left = unparse(comparison.left) |
1346 right = unparse(comparison.comparators[0]) |
1311 right = unparse(comparison.comparators[0]) |
1347 self.__error(node.lineno - 1, node.col_offset, "Y-201", left, right) |
1312 self.__error(node, "Y-201", left, right) |
1348 |
1313 |
1349 def __check202(self, node): |
1314 def __check202(self, node): |
1350 """ |
1315 """ |
1351 Private method to check for calls where an unary 'not' is used for |
1316 Private method to check for calls where an unary 'not' is used for |
1352 an equality. |
1317 an equality. |
1366 and self.__isExceptionCheck(node.parent) |
1331 and self.__isExceptionCheck(node.parent) |
1367 ): |
1332 ): |
1368 comparison = node.operand |
1333 comparison = node.operand |
1369 left = unparse(comparison.left) |
1334 left = unparse(comparison.left) |
1370 right = unparse(comparison.comparators[0]) |
1335 right = unparse(comparison.comparators[0]) |
1371 self.__error(node.lineno - 1, node.col_offset, "Y-202", left, right) |
1336 self.__error(node, "Y-202", left, right) |
1372 |
1337 |
1373 def __check203(self, node): |
1338 def __check203(self, node): |
1374 """ |
1339 """ |
1375 Private method to check for calls where an unary 'not' is used for |
1340 Private method to check for calls where an unary 'not' is used for |
1376 an in-check. |
1341 an in-check. |
1390 and self.__isExceptionCheck(node.parent) |
1355 and self.__isExceptionCheck(node.parent) |
1391 ): |
1356 ): |
1392 comparison = node.operand |
1357 comparison = node.operand |
1393 left = unparse(comparison.left) |
1358 left = unparse(comparison.left) |
1394 right = unparse(comparison.comparators[0]) |
1359 right = unparse(comparison.comparators[0]) |
1395 self.__error(node.lineno - 1, node.col_offset, "Y-203", left, right) |
1360 self.__error(node, "Y-203", left, right) |
1396 |
1361 |
1397 def __check204(self, node): |
1362 def __check204(self, node): |
1398 """ |
1363 """ |
1399 Private method to check for calls of the type "not (a < b)". |
1364 Private method to check for calls of the type "not (a < b)". |
1400 |
1365 |
1413 and self.__isExceptionCheck(node.parent) |
1378 and self.__isExceptionCheck(node.parent) |
1414 ): |
1379 ): |
1415 comparison = node.operand |
1380 comparison = node.operand |
1416 left = unparse(comparison.left) |
1381 left = unparse(comparison.left) |
1417 right = unparse(comparison.comparators[0]) |
1382 right = unparse(comparison.comparators[0]) |
1418 self.__error(node.lineno - 1, node.col_offset, "Y-204", left, right) |
1383 self.__error(node, "Y-204", left, right) |
1419 |
1384 |
1420 def __check205(self, node): |
1385 def __check205(self, node): |
1421 """ |
1386 """ |
1422 Private method to check for calls of the type "not (a <= b)". |
1387 Private method to check for calls of the type "not (a <= b)". |
1423 |
1388 |
1436 and self.__isExceptionCheck(node.parent) |
1401 and self.__isExceptionCheck(node.parent) |
1437 ): |
1402 ): |
1438 comparison = node.operand |
1403 comparison = node.operand |
1439 left = unparse(comparison.left) |
1404 left = unparse(comparison.left) |
1440 right = unparse(comparison.comparators[0]) |
1405 right = unparse(comparison.comparators[0]) |
1441 self.__error(node.lineno - 1, node.col_offset, "Y-205", left, right) |
1406 self.__error(node, "Y-205", left, right) |
1442 |
1407 |
1443 def __check206(self, node): |
1408 def __check206(self, node): |
1444 """ |
1409 """ |
1445 Private method to check for calls of the type "not (a > b)". |
1410 Private method to check for calls of the type "not (a > b)". |
1446 |
1411 |
1459 and self.__isExceptionCheck(node.parent) |
1424 and self.__isExceptionCheck(node.parent) |
1460 ): |
1425 ): |
1461 comparison = node.operand |
1426 comparison = node.operand |
1462 left = unparse(comparison.left) |
1427 left = unparse(comparison.left) |
1463 right = unparse(comparison.comparators[0]) |
1428 right = unparse(comparison.comparators[0]) |
1464 self.__error(node.lineno - 1, node.col_offset, "Y-206", left, right) |
1429 self.__error(node, "Y-206", left, right) |
1465 |
1430 |
1466 def __check207(self, node): |
1431 def __check207(self, node): |
1467 """ |
1432 """ |
1468 Private method to check for calls of the type "not (a >= b)". |
1433 Private method to check for calls of the type "not (a >= b)". |
1469 |
1434 |
1482 and self.__isExceptionCheck(node.parent) |
1447 and self.__isExceptionCheck(node.parent) |
1483 ): |
1448 ): |
1484 comparison = node.operand |
1449 comparison = node.operand |
1485 left = unparse(comparison.left) |
1450 left = unparse(comparison.left) |
1486 right = unparse(comparison.comparators[0]) |
1451 right = unparse(comparison.comparators[0]) |
1487 self.__error(node.lineno - 1, node.col_offset, "Y-207", left, right) |
1452 self.__error(node, "Y-207", left, right) |
1488 |
1453 |
1489 def __check208(self, node): |
1454 def __check208(self, node): |
1490 """ |
1455 """ |
1491 Private method to check for calls of the type "not (not a)". |
1456 Private method to check for calls of the type "not (not a)". |
1492 |
1457 |
1498 isinstance(node.op, ast.Not) |
1463 isinstance(node.op, ast.Not) |
1499 and isinstance(node.operand, ast.UnaryOp) |
1464 and isinstance(node.operand, ast.UnaryOp) |
1500 and isinstance(node.operand.op, ast.Not) |
1465 and isinstance(node.operand.op, ast.Not) |
1501 ): |
1466 ): |
1502 var = unparse(node.operand.operand) |
1467 var = unparse(node.operand.operand) |
1503 self.__error(node.lineno - 1, node.col_offset, "Y-208", var) |
1468 self.__error(node, "Y-208", var) |
1504 |
1469 |
1505 def __check211(self, node): |
1470 def __check211(self, node): |
1506 """ |
1471 """ |
1507 Private method to check for calls of the type "True if a else False". |
1472 Private method to check for calls of the type "True if a else False". |
1508 |
1473 |
1519 cond = unparse(node.test) |
1484 cond = unparse(node.test) |
1520 if isinstance(node.test, ast.Name): |
1485 if isinstance(node.test, ast.Name): |
1521 newCond = "bool({0})".format(cond) |
1486 newCond = "bool({0})".format(cond) |
1522 else: |
1487 else: |
1523 newCond = cond |
1488 newCond = cond |
1524 self.__error(node.lineno - 1, node.col_offset, "Y-211", cond, newCond) |
1489 self.__error(node, "Y-211", cond, newCond) |
1525 |
1490 |
1526 def __check212(self, node): |
1491 def __check212(self, node): |
1527 """ |
1492 """ |
1528 Private method to check for calls of the type "False if a else True". |
1493 Private method to check for calls of the type "False if a else True". |
1529 |
1494 |
1543 else: |
1508 else: |
1544 if len(node.test.ops) == 1: |
1509 if len(node.test.ops) == 1: |
1545 newCond = unparse(self.__negateTest(node.test)) |
1510 newCond = unparse(self.__negateTest(node.test)) |
1546 else: |
1511 else: |
1547 newCond = "not ({0})".format(cond) |
1512 newCond = "not ({0})".format(cond) |
1548 self.__error(node.lineno - 1, node.col_offset, "Y-212", cond, newCond) |
1513 self.__error(node, "Y-212", cond, newCond) |
1549 |
1514 |
1550 def __check213(self, node): |
1515 def __check213(self, node): |
1551 """ |
1516 """ |
1552 Private method to check for calls of the type "b if not a else a". |
1517 Private method to check for calls of the type "b if not a else a". |
1553 |
1518 |
1560 and isinstance(node.test.op, ast.Not) |
1525 and isinstance(node.test.op, ast.Not) |
1561 and self.__isSameExpression(node.test.operand, node.orelse) |
1526 and self.__isSameExpression(node.test.operand, node.orelse) |
1562 ): |
1527 ): |
1563 a = unparse(node.test.operand) |
1528 a = unparse(node.test.operand) |
1564 b = unparse(node.body) |
1529 b = unparse(node.body) |
1565 self.__error(node.lineno - 1, node.col_offset, "Y-213", a, b) |
1530 self.__error(node, "Y-213", a, b) |
1566 |
1531 |
1567 def __check221(self, node): |
1532 def __check221(self, node): |
1568 """ |
1533 """ |
1569 Private method to check for calls of the type "a and not a". |
1534 Private method to check for calls of the type "a and not a". |
1570 |
1535 |
1584 nonNegatedExpressions.append(exp) |
1549 nonNegatedExpressions.append(exp) |
1585 for negatedExpression in negatedExpressions: |
1550 for negatedExpression in negatedExpressions: |
1586 for nonNegatedExpression in nonNegatedExpressions: |
1551 for nonNegatedExpression in nonNegatedExpressions: |
1587 if self.__isSameExpression(negatedExpression, nonNegatedExpression): |
1552 if self.__isSameExpression(negatedExpression, nonNegatedExpression): |
1588 negExp = unparse(negatedExpression) |
1553 negExp = unparse(negatedExpression) |
1589 self.__error(node.lineno - 1, node.col_offset, "Y-221", negExp) |
1554 self.__error(node, "Y-221", negExp) |
1590 |
1555 |
1591 def __check222(self, node): |
1556 def __check222(self, node): |
1592 """ |
1557 """ |
1593 Private method to check for calls of the type "a or not a". |
1558 Private method to check for calls of the type "a or not a". |
1594 |
1559 |
1608 nonNegatedExpressions.append(exp) |
1573 nonNegatedExpressions.append(exp) |
1609 for negatedExpression in negatedExpressions: |
1574 for negatedExpression in negatedExpressions: |
1610 for nonNegatedExpression in nonNegatedExpressions: |
1575 for nonNegatedExpression in nonNegatedExpressions: |
1611 if self.__isSameExpression(negatedExpression, nonNegatedExpression): |
1576 if self.__isSameExpression(negatedExpression, nonNegatedExpression): |
1612 negExp = unparse(negatedExpression) |
1577 negExp = unparse(negatedExpression) |
1613 self.__error(node.lineno - 1, node.col_offset, "Y-222", negExp) |
1578 self.__error(node, "Y-222", negExp) |
1614 |
1579 |
1615 def __check223(self, node): |
1580 def __check223(self, node): |
1616 """ |
1581 """ |
1617 Private method to check for calls of the type "... or True". |
1582 Private method to check for calls of the type "... or True". |
1618 |
1583 |
1621 """ |
1586 """ |
1622 # a or True |
1587 # a or True |
1623 if isinstance(node.op, ast.Or): |
1588 if isinstance(node.op, ast.Or): |
1624 for exp in node.values: |
1589 for exp in node.values: |
1625 if isinstance(exp, ast.Constant) and exp.value is True: |
1590 if isinstance(exp, ast.Constant) and exp.value is True: |
1626 self.__error(node.lineno - 1, node.col_offset, "Y-223") |
1591 self.__error(node, "Y-223") |
1627 |
1592 |
1628 def __check224(self, node): |
1593 def __check224(self, node): |
1629 """ |
1594 """ |
1630 Private method to check for calls of the type "... and False". |
1595 Private method to check for calls of the type "... and False". |
1631 |
1596 |
1634 """ |
1599 """ |
1635 # a and False |
1600 # a and False |
1636 if isinstance(node.op, ast.And): |
1601 if isinstance(node.op, ast.And): |
1637 for exp in node.values: |
1602 for exp in node.values: |
1638 if isinstance(exp, ast.Constant) and exp.value is False: |
1603 if isinstance(exp, ast.Constant) and exp.value is False: |
1639 self.__error(node.lineno - 1, node.col_offset, "Y-224") |
1604 self.__error(node, "Y-224") |
1640 |
1605 |
1641 def __check301(self, node): |
1606 def __check301(self, node): |
1642 """ |
1607 """ |
1643 Private method to check for Yoda conditions. |
1608 Private method to check for Yoda conditions. |
1644 |
1609 |
1656 node.left.value, str |
1621 node.left.value, str |
1657 ) |
1622 ) |
1658 if isStr: |
1623 if isStr: |
1659 left = f"'{left}'" |
1624 left = f"'{left}'" |
1660 right = unparse(node.comparators[0]) |
1625 right = unparse(node.comparators[0]) |
1661 self.__error(node.lineno - 1, node.col_offset, "Y-301", left, right) |
1626 self.__error(node, "Y-301", left, right) |
1662 |
1627 |
1663 def __check401(self, node): |
1628 def __check401(self, node): |
1664 """ |
1629 """ |
1665 Private method to check for bare boolean function arguments. |
1630 Private method to check for bare boolean function arguments. |
1666 |
1631 |
1675 ) |
1640 ) |
1676 |
1641 |
1677 isException = isinstance(node.func, ast.Attribute) and node.func.attr in ["get"] |
1642 isException = isinstance(node.func, ast.Attribute) and node.func.attr in ["get"] |
1678 |
1643 |
1679 if hasBareBool and not isException: |
1644 if hasBareBool and not isException: |
1680 self.__error(node.lineno - 1, node.col_offset, "Y-401") |
1645 self.__error(node, "Y-401") |
1681 |
1646 |
1682 def __check402(self, node): |
1647 def __check402(self, node): |
1683 """ |
1648 """ |
1684 Private method to check for bare numeric function arguments. |
1649 Private method to check for bare numeric function arguments. |
1685 |
1650 |
1696 isException = isException or ( |
1661 isException = isException or ( |
1697 isinstance(node.func, ast.Attribute) and node.func.attr in ("get", "insert") |
1662 isinstance(node.func, ast.Attribute) and node.func.attr in ("get", "insert") |
1698 ) |
1663 ) |
1699 |
1664 |
1700 if hasBareNumeric and not isException: |
1665 if hasBareNumeric and not isException: |
1701 self.__error(node.lineno - 1, node.col_offset, "Y-402") |
1666 self.__error(node, "Y-402") |
1702 |
1667 |
1703 def __check411(self, node): |
1668 def __check411(self, node): |
1704 """ |
1669 """ |
1705 Private method to check for nested f-strings. |
1670 Private method to check for nested f-strings. |
1706 |
1671 |
1713 if fieldName == "values": |
1678 if fieldName == "values": |
1714 for innerNode in value: |
1679 for innerNode in value: |
1715 self.__check411(innerNode) |
1680 self.__check411(innerNode) |
1716 |
1681 |
1717 if fieldName == "value" and isinstance(value, ast.JoinedStr): |
1682 if fieldName == "value" and isinstance(value, ast.JoinedStr): |
1718 self.__error(node.lineno - 1, node.col_offset, "Y-411") |
1683 self.__error(node, "Y-411") |
1719 |
1684 |
1720 def __check901(self, node): |
1685 def __check901(self, node): |
1721 """ |
1686 """ |
1722 Private method to check for unnecessary bool conversion. |
1687 Private method to check for unnecessary bool conversion. |
1723 |
1688 |
1730 and len(node.args) == 1 |
1695 and len(node.args) == 1 |
1731 and isinstance(node.args[0], ast.Compare) |
1696 and isinstance(node.args[0], ast.Compare) |
1732 ): |
1697 ): |
1733 actual = unparse(node) |
1698 actual = unparse(node) |
1734 expected = unparse(node.args[0]) |
1699 expected = unparse(node.args[0]) |
1735 self.__error(node.lineno - 1, node.col_offset, "Y-901", expected, actual) |
1700 self.__error(node, "Y-901", expected, actual) |
1736 |
1701 |
1737 def __check904(self, node): |
1702 def __check904(self, node): |
1738 """ |
1703 """ |
1739 Private method to check for dictionary initialization. |
1704 Private method to check for dictionary initialization. |
1740 |
1705 |
1753 and isinstance(node.targets[0], ast.Name) |
1718 and isinstance(node.targets[0], ast.Name) |
1754 and n2.targets[0].value.id == node.targets[0].id |
1719 and n2.targets[0].value.id == node.targets[0].id |
1755 ): |
1720 ): |
1756 dictName = unparse(node.targets[0]) |
1721 dictName = unparse(node.targets[0]) |
1757 if not self.__expressionUsesVariable(n2.value, dictName): |
1722 if not self.__expressionUsesVariable(n2.value, dictName): |
1758 self.__error(node.lineno - 1, node.col_offset, "Y-904", dictName) |
1723 self.__error(node, "Y-904", dictName) |
1759 |
1724 |
1760 def __check905(self, node): |
1725 def __check905(self, node): |
1761 """ |
1726 """ |
1762 Private method to check for list initialization by splitting a string. |
1727 Private method to check for list initialization by splitting a string. |
1763 |
1728 |
1771 ): |
1736 ): |
1772 value = node.func.value.value |
1737 value = node.func.value.value |
1773 |
1738 |
1774 expected = json.dumps(value.split()) |
1739 expected = json.dumps(value.split()) |
1775 actual = unparse(node.func.value) + ".split()" |
1740 actual = unparse(node.func.value) + ".split()" |
1776 self.__error(node.lineno - 1, node.col_offset, "Y-905", expected, actual) |
1741 self.__error(node, "Y-905", expected, actual) |
1777 |
1742 |
1778 def __check906(self, node): |
1743 def __check906(self, node): |
1779 """ |
1744 """ |
1780 Private method to check for unnecessary nesting of os.path.join(). |
1745 Private method to check for unnecessary nesting of os.path.join(). |
1781 |
1746 |
1825 ): |
1790 ): |
1826 names = getOsPathJoinArgs(node) |
1791 names = getOsPathJoinArgs(node) |
1827 |
1792 |
1828 actual = unparse(node) |
1793 actual = unparse(node) |
1829 expected = "os.path.join({0})".format(", ".join(names)) |
1794 expected = "os.path.join({0})".format(", ".join(names)) |
1830 self.__error(node.lineno - 1, node.col_offset, "Y-906", expected, actual) |
1795 self.__error(node, "Y-906", expected, actual) |
1831 |
1796 |
1832 def __check907(self, node): |
1797 def __check907(self, node): |
1833 """ |
1798 """ |
1834 Private method to check for Union type annotation with None. |
1799 Private method to check for Union type annotation with None. |
1835 |
1800 |
1856 else: |
1821 else: |
1857 others.append(elt) |
1822 others.append(elt) |
1858 |
1823 |
1859 if len(others) == 1 and hasNone: |
1824 if len(others) == 1 and hasNone: |
1860 type_ = unparse(others[0]) |
1825 type_ = unparse(others[0]) |
1861 self.__error( |
1826 self.__error(node, "Y-907", type_, unparse(node)) |
1862 node.lineno - 1, node.col_offset, "Y-907", type_, unparse(node) |
|
1863 ) |
|
1864 |
1827 |
1865 def __check909(self, node): |
1828 def __check909(self, node): |
1866 """ |
1829 """ |
1867 Private method to check for reflexive assignments. |
1830 Private method to check for reflexive assignments. |
1868 |
1831 |
1875 for target in node.targets: |
1838 for target in node.targets: |
1876 names.append(unparse(target)) |
1839 names.append(unparse(target)) |
1877 |
1840 |
1878 if len(names) != len(set(names)) and not isinstance(node.parent, ast.ClassDef): |
1841 if len(names) != len(set(names)) and not isinstance(node.parent, ast.ClassDef): |
1879 srccode = unparse(node) |
1842 srccode = unparse(node) |
1880 self.__error(node.lineno - 1, node.col_offset, "Y-909", srccode) |
1843 self.__error(node, "Y-909", srccode) |
1881 |
1844 |
1882 def __check910(self, node): |
1845 def __check910(self, node): |
1883 """ |
1846 """ |
1884 Private method to check for uses of 'dict.get(key, None)'. |
1847 Private method to check for uses of 'dict.get(key, None)'. |
1885 |
1848 |
1903 |
1866 |
1904 actual = unparse(node) |
1867 actual = unparse(node) |
1905 func = unparse(node.func) |
1868 func = unparse(node.func) |
1906 key = unparse(node.args[0]) |
1869 key = unparse(node.args[0]) |
1907 expected = f"{func}({key})" |
1870 expected = f"{func}({key})" |
1908 self.__error(node.lineno - 1, node.col_offset, "Y-910", expected, actual) |
1871 self.__error(node, "Y-910", expected, actual) |
1909 |
1872 |
1910 def __check911(self, node): |
1873 def __check911(self, node): |
1911 """ |
1874 """ |
1912 Private method to check for the expression "zip(_.keys(), _.values())". |
1875 Private method to check for the expression "zip(_.keys(), _.values())". |
1913 |
1876 |
1929 and isinstance(secondArg.func, ast.Attribute) |
1892 and isinstance(secondArg.func, ast.Attribute) |
1930 and isinstance(secondArg.func.value, ast.Name) |
1893 and isinstance(secondArg.func.value, ast.Name) |
1931 and secondArg.func.attr == "values" |
1894 and secondArg.func.attr == "values" |
1932 and firstArg.func.value.id == secondArg.func.value.id |
1895 and firstArg.func.value.id == secondArg.func.value.id |
1933 ): |
1896 ): |
1934 self.__error( |
1897 self.__error(node, "Y-911", firstArg.func.value.id) |
1935 node.lineno - 1, node.col_offset, "Y-911", firstArg.func.value.id |
|
1936 ) |
|
1937 |
1898 |
1938 |
1899 |
1939 # |
1900 # |
1940 # eflag: noqa = M-891 |
1901 # eflag: noqa = M-891 |