118 self.__check103(node) |
118 self.__check103(node) |
119 self.__check106(node) |
119 self.__check106(node) |
120 self.__check108(node) |
120 self.__check108(node) |
121 self.__check114(node) |
121 self.__check114(node) |
122 self.__check116(node) |
122 self.__check116(node) |
|
123 self.__check122(node) |
123 |
124 |
124 self.generic_visit(node) |
125 self.generic_visit(node) |
125 |
126 |
126 def visit_IfExp(self, node): |
127 def visit_IfExp(self, node): |
127 """ |
128 """ |
169 @param node reference to the Call node |
170 @param node reference to the Call node |
170 @type ast.Call |
171 @type ast.Call |
171 """ |
172 """ |
172 self.__check115(node) |
173 self.__check115(node) |
173 self.__check182(node) |
174 self.__check182(node) |
|
175 self.__check401(node) |
|
176 self.__check402(node) |
174 |
177 |
175 self.generic_visit(node) |
178 self.generic_visit(node) |
176 |
179 |
177 def visit_With(self, node): |
180 def visit_With(self, node): |
178 """ |
181 """ |
206 """ |
209 """ |
207 # register the name of the class being defined |
210 # register the name of the class being defined |
208 self.__classDefinitionStack.append(node.name) |
211 self.__classDefinitionStack.append(node.name) |
209 |
212 |
210 self.__check119(node) |
213 self.__check119(node) |
211 self.__check120(node) |
214 self.__check120_121(node) |
212 |
215 |
213 self.generic_visit(node) |
216 self.generic_visit(node) |
214 |
217 |
215 self.__classDefinitionStack.pop() |
218 self.__classDefinitionStack.pop() |
216 |
219 |
431 Private method to check for nested if statements without else blocks. |
434 Private method to check for nested if statements without else blocks. |
432 |
435 |
433 @param node reference to the AST node to be checked |
436 @param node reference to the AST node to be checked |
434 @type ast.If |
437 @type ast.If |
435 """ |
438 """ |
|
439 # Don't treat 'if __name__ == "__main__":' as an issue. |
|
440 if ( |
|
441 isinstance(node.test, ast.Compare) and |
|
442 isinstance(node.test.left, ast.Name) and |
|
443 node.test.left.id == "__name__" and |
|
444 isinstance(node.test.ops[0], ast.Eq) and |
|
445 isinstance(node.test.comparators[0], ast.Constant) and |
|
446 node.test.comparators[0].value == "__main__" |
|
447 ): |
|
448 return |
|
449 |
436 # ## Pattern 1 |
450 # ## Pattern 1 |
437 # if a: <--- |
451 # if a: <--- |
438 # if b: <--- |
452 # if b: <--- |
439 # c |
453 # c |
440 isPattern1 = ( |
454 isPattern1 = ( |
442 len(node.body) == 1 and |
456 len(node.body) == 1 and |
443 isinstance(node.body[0], ast.If) and |
457 isinstance(node.body[0], ast.If) and |
444 node.body[0].orelse == [] |
458 node.body[0].orelse == [] |
445 ) |
459 ) |
446 # ## Pattern 2 |
460 # ## Pattern 2 |
447 # if a: < irrelvant for here |
461 # if a: < irrelevant for here |
448 # pass |
462 # pass |
449 # elif b: <--- this is treated like a nested block |
463 # elif b: <--- this is treated like a nested block |
450 # if c: <--- |
464 # if c: <--- |
451 # d |
465 # d |
452 if isPattern1: |
466 if isPattern1: |
710 if node.body[0].body[0].value.value is True: |
724 if node.body[0].body[0].value.value is True: |
711 self.__error(node.lineno - 1, node.col_offset, "Y110", |
725 self.__error(node.lineno - 1, node.col_offset, "Y110", |
712 check, target, iterable) |
726 check, target, iterable) |
713 elif node.body[0].body[0].value.value is False: |
727 elif node.body[0].body[0].value.value is False: |
714 check = "not " + check |
728 check = "not " + check |
715 if check.startswith("not not"): |
729 if check.startswith("not not "): |
716 check = check[len("not not "):] |
730 check = check[len("not not "):] |
717 self.__error(node.lineno - 1, node.col_offset, "Y111", |
731 self.__error(node.lineno - 1, node.col_offset, "Y111", |
718 check, target, iterable) |
732 check, target, iterable) |
719 |
733 |
720 def __check112(self, node): |
734 def __check112(self, node): |
1057 if isinstance(el, ast.FunctionDef)) > 0 |
1071 if isinstance(el, ast.FunctionDef)) > 0 |
1058 ): |
1072 ): |
1059 self.__error(node.lineno - 1, node.col_offset, "Y119", |
1073 self.__error(node.lineno - 1, node.col_offset, "Y119", |
1060 node.name) |
1074 node.name) |
1061 |
1075 |
1062 def __check120(self, node): |
1076 def __check120_121(self, node): |
1063 """ |
1077 """ |
1064 Private method to check for classes that inherit from object. |
1078 Private method to check for classes that inherit from object. |
1065 |
1079 |
1066 @param node reference to the AST node to be checked |
1080 @param node reference to the AST node to be checked |
1067 @type ast.ClassDef |
1081 @type ast.ClassDef |
1081 isinstance(node.bases[-1], ast.Name) and |
1095 isinstance(node.bases[-1], ast.Name) and |
1082 node.bases[-1].id == "object" |
1096 node.bases[-1].id == "object" |
1083 ): |
1097 ): |
1084 self.__error(node.lineno - 1, node.col_offset, "Y121", |
1098 self.__error(node.lineno - 1, node.col_offset, "Y121", |
1085 node.name, ", ".join(b.id for b in node.bases[:-1])) |
1099 node.name, ", ".join(b.id for b in node.bases[:-1])) |
|
1100 |
|
1101 def __check122(self, node): |
|
1102 """ |
|
1103 Private method to check for all if-blocks which only check if a key |
|
1104 is in a dictionary. |
|
1105 |
|
1106 @param node reference to the AST node to be checked |
|
1107 @type ast.If |
|
1108 """ |
|
1109 if ( |
|
1110 isinstance(node.test, ast.Compare) and |
|
1111 len(node.test.ops) == 1 and |
|
1112 isinstance(node.test.ops[0], ast.In) and |
|
1113 len(node.body) == 1 and |
|
1114 len(node.orelse) == 0 |
|
1115 ) and ( |
|
1116 # We might still be left with a check if a value is in a list or |
|
1117 # in the body the developer might remove the element from the list. |
|
1118 # We need to have a look at the body. |
|
1119 isinstance(node.body[0], ast.Assign) and |
|
1120 isinstance(node.body[0].value, ast.Subscript) and |
|
1121 len(node.body[0].targets) == 1 and |
|
1122 isinstance(node.body[0].targets[0], ast.Name) |
|
1123 ): |
|
1124 key = unparse(node.test.left) |
|
1125 dictname = unparse(node.test.comparators[0]) |
|
1126 self.__error(node.lineno - 1, node.col_offset, "Y122", |
|
1127 dictname, key) |
1086 |
1128 |
1087 def __check181(self, node): |
1129 def __check181(self, node): |
1088 """ |
1130 """ |
1089 Private method to check for assignments that could be converted into |
1131 Private method to check for assignments that could be converted into |
1090 an augmented assignment. |
1132 an augmented assignment. |
1492 if isPy37Str or isPy38Str: |
1534 if isPy37Str or isPy38Str: |
1493 left = f"'{left}'" |
1535 left = f"'{left}'" |
1494 right = unparse(node.comparators[0]) |
1536 right = unparse(node.comparators[0]) |
1495 self.__error(node.lineno - 1, node.col_offset, "Y301", |
1537 self.__error(node.lineno - 1, node.col_offset, "Y301", |
1496 left, right) |
1538 left, right) |
|
1539 |
|
1540 def __check401(self, node): |
|
1541 """ |
|
1542 Private method to check for bare boolean function arguments. |
|
1543 |
|
1544 @param node reference to the AST node to be checked |
|
1545 @type ast.Call |
|
1546 """ |
|
1547 # foo(a, b, True) |
|
1548 hasBareBool = any( |
|
1549 isinstance(callArg, ast.Constant) and |
|
1550 (callArg.value is True or callArg.value is False) |
|
1551 for callArg in node.args |
|
1552 ) |
|
1553 |
|
1554 isException = ( |
|
1555 isinstance(node.func, ast.Attribute) and |
|
1556 node.func.attr in ["get"] |
|
1557 ) |
|
1558 |
|
1559 if hasBareBool and not isException: |
|
1560 self.__error(node.lineno - 1, node.col_offset, "Y401") |
|
1561 |
|
1562 def __check402(self, node): |
|
1563 """ |
|
1564 Private method to check for bare numeric function arguments. |
|
1565 |
|
1566 @param node reference to the AST node to be checked |
|
1567 @type ast.Call |
|
1568 """ |
|
1569 # foo(a, b, 123123) |
|
1570 hasBareNumeric = any( |
|
1571 isinstance(callArg, ast.Constant) and |
|
1572 type(callArg.value) in (float, int) |
|
1573 for callArg in node.args |
|
1574 ) |
|
1575 |
|
1576 isException = ( |
|
1577 isinstance(node.func, ast.Name) and |
|
1578 node.func.id == "range" |
|
1579 ) |
|
1580 isException = isException or ( |
|
1581 isinstance(node.func, ast.Attribute) and |
|
1582 node.func.attr in ["get", "insert",] |
|
1583 ) |
|
1584 |
|
1585 if hasBareNumeric and not isException: |
|
1586 self.__error(node.lineno - 1, node.col_offset, "Y402") |
1497 |
1587 |
1498 # |
1588 # |
1499 # eflag: noqa = M891 |
1589 # eflag: noqa = M891 |