240 self.__check206(node) |
240 self.__check206(node) |
241 self.__check207(node) |
241 self.__check207(node) |
242 self.__check208(node) |
242 self.__check208(node) |
243 |
243 |
244 self.generic_visit(node) |
244 self.generic_visit(node) |
245 |
245 |
246 def visit_Subscript(self, node): |
246 def visit_Subscript(self, node): |
247 """ |
247 """ |
248 Public method to process a Subscript node. |
248 Public method to process a Subscript node. |
249 |
249 |
250 @param node reference to the Subscript node |
250 @param node reference to the Subscript node |
284 return [name for name, count in counter.items() if count > 1] |
284 return [name for name, count in counter.items() if count > 1] |
285 |
285 |
286 def __isConstantIncrease(self, expr): |
286 def __isConstantIncrease(self, expr): |
287 """ |
287 """ |
288 Private method to check an expression for being a constant increase. |
288 Private method to check an expression for being a constant increase. |
289 |
289 |
290 @param expr reference to the node to be checked |
290 @param expr reference to the node to be checked |
291 @type ast.AugAssign |
291 @type ast.AugAssign |
292 @return flag indicating a constant increase |
292 @return flag indicating a constant increase |
293 @rtype bool |
293 @rtype bool |
294 """ |
294 """ |
295 return isinstance(expr.op, ast.Add) and ( |
295 return isinstance(expr.op, ast.Add) and ( |
296 ( |
296 (isinstance(expr.value, ast.Constant) and expr.value.value == 1) |
297 isinstance(expr.value, ast.Constant) |
|
298 and expr.value.value == 1 |
|
299 ) |
|
300 or (isinstance(expr.value, ast.Num) and expr.value.n == 1) |
297 or (isinstance(expr.value, ast.Num) and expr.value.n == 1) |
301 ) |
298 ) |
302 |
299 |
303 def __getIfBodyPairs(self, node): |
300 def __getIfBodyPairs(self, node): |
304 """ |
301 """ |
432 return newNode |
429 return newNode |
433 |
430 |
434 def __expressionUsesVariable(self, expr, var): |
431 def __expressionUsesVariable(self, expr, var): |
435 """ |
432 """ |
436 Private method to check, if a variable is used by an expression. |
433 Private method to check, if a variable is used by an expression. |
437 |
434 |
438 @param expr expression node to be checked |
435 @param expr expression node to be checked |
439 @type ast.expr |
436 @type ast.expr |
440 @param var variable name to be checked for |
437 @param var variable name to be checked for |
441 @type str |
438 @type str |
442 @return flag indicating the expression uses the variable |
439 @return flag indicating the expression uses the variable |
447 # false-positives. |
444 # false-positives. |
448 |
445 |
449 def __bodyContainsContinue(self, stmts): |
446 def __bodyContainsContinue(self, stmts): |
450 """ |
447 """ |
451 Private method to check, if a list of statements contain a 'continue' statement. |
448 Private method to check, if a list of statements contain a 'continue' statement. |
452 |
449 |
453 @param stmts list of statements |
450 @param stmts list of statements |
454 @type list of ast.stmt |
451 @type list of ast.stmt |
455 @return flag indicating a continue statement |
452 @return flag indicating a continue statement |
456 @rtype bool |
453 @rtype bool |
457 """ |
454 """ |
651 if isinstance(stmt, ast.Return): |
648 if isinstance(stmt, ast.Return): |
652 finallyHasReturn = True |
649 finallyHasReturn = True |
653 finallyReturn = stmt |
650 finallyReturn = stmt |
654 break |
651 break |
655 |
652 |
656 if ( |
653 if (tryHasReturn or exceptHasReturn) and finallyHasReturn: |
657 (tryHasReturn or exceptHasReturn) |
|
658 and finallyHasReturn |
|
659 ): |
|
660 self.__error(finallyReturn.lineno - 1, finallyReturn.col_offset, "Y107") |
654 self.__error(finallyReturn.lineno - 1, finallyReturn.col_offset, "Y107") |
661 |
655 |
662 def __check108(self, node): |
656 def __check108(self, node): |
663 """ |
657 """ |
664 Private method to check for if-elses which could be a ternary |
658 Private method to check for if-elses which could be a ternary |
691 and node.body[0].targets[0].id == node.orelse[0].targets[0].id |
685 and node.body[0].targets[0].id == node.orelse[0].targets[0].id |
692 and not isinstance(node.parent, ast.If) |
686 and not isinstance(node.parent, ast.If) |
693 ): |
687 ): |
694 targetVar = node.body[0].targets[0] |
688 targetVar = node.body[0].targets[0] |
695 assign = unparse(targetVar) |
689 assign = unparse(targetVar) |
696 |
690 |
697 # It's part of a bigger if-elseif block: |
691 # It's part of a bigger if-elseif block: |
698 if isinstance(node.parent, ast.If): |
692 if isinstance(node.parent, ast.If): |
699 for n in node.parent.body: |
693 for n in node.parent.body: |
700 if ( |
694 if ( |
701 isinstance(n, ast.Assign) |
695 isinstance(n, ast.Assign) |
702 and isinstance(n.targets[0], ast.Name) |
696 and isinstance(n.targets[0], ast.Name) |
703 and n.targets[0].id == targetVar.id |
697 and n.targets[0].id == targetVar.id |
704 ): |
698 ): |
705 return |
699 return |
706 |
700 |
707 body = unparse(node.body[0].value) |
701 body = unparse(node.body[0].value) |
708 cond = unparse(node.test) |
702 cond = unparse(node.test) |
709 orelse = unparse(node.orelse[0].value) |
703 orelse = unparse(node.orelse[0].value) |
710 |
704 |
711 self.__error( |
705 self.__error( |
792 |
786 |
793 if isCompoundExpression: |
787 if isCompoundExpression: |
794 check = f"not ({check})" |
788 check = f"not ({check})" |
795 else: |
789 else: |
796 if check.startswith("not "): |
790 if check.startswith("not "): |
797 check = check[len("not "):] |
791 check = check[len("not ") :] |
798 else: |
792 else: |
799 check = f"not {check}" |
793 check = f"not {check}" |
800 self.__error( |
794 self.__error( |
801 node.lineno - 1, node.col_offset, "Y111", check, target, iterable |
795 node.lineno - 1, node.col_offset, "Y111", check, target, iterable |
802 ) |
796 ) |
924 while sibling is not None: |
918 while sibling is not None: |
925 sibling = sibling.previous_sibling |
919 sibling = sibling.previous_sibling |
926 |
920 |
927 for match in matches: |
921 for match in matches: |
928 variable = unparse(match) |
922 variable = unparse(match) |
929 self.__error( |
923 self.__error(match.lineno - 1, match.col_offset, "Y113", variable) |
930 match.lineno - 1, match.col_offset, "Y113", variable |
|
931 ) |
|
932 |
924 |
933 def __check114(self, node): |
925 def __check114(self, node): |
934 """ |
926 """ |
935 Private method to check for alternative if clauses with identical |
927 Private method to check for alternative if clauses with identical |
936 bodies. |
928 bodies. |
1018 else: |
1010 else: |
1019 bodyValueStr = "None" |
1011 bodyValueStr = "None" |
1020 if isinstance(node.test.comparators[0], ast.Str): |
1012 if isinstance(node.test.comparators[0], ast.Str): |
1021 value = ( |
1013 value = ( |
1022 bodyValueStr |
1014 bodyValueStr |
1023 if bodyValueStr[0] == '"' and bodyValueStr[-1] == '"' else |
1015 if bodyValueStr[0] == '"' and bodyValueStr[-1] == '"' |
1024 bodyValueStr[1:-1] |
1016 else bodyValueStr[1:-1] |
1025 ) |
1017 ) |
1026 keyValuePairs = {node.test.comparators[0].s: value} |
1018 keyValuePairs = {node.test.comparators[0].s: value} |
1027 elif isinstance(node.test.comparators[0], ast.Num): |
1019 elif isinstance(node.test.comparators[0], ast.Num): |
1028 keyValuePairs = {node.test.comparators[0].n: bodyValueStr} |
1020 keyValuePairs = {node.test.comparators[0].n: bodyValueStr} |
1029 else: |
1021 else: |
1231 self.__error(node.lineno - 1, node.col_offset, "Y122", dictname, key) |
1223 self.__error(node.lineno - 1, node.col_offset, "Y122", dictname, key) |
1232 |
1224 |
1233 def __check123(self, node): |
1225 def __check123(self, node): |
1234 """ |
1226 """ |
1235 Private method to check for complicated dictionary access with default value. |
1227 Private method to check for complicated dictionary access with default value. |
1236 |
1228 |
1237 @param node reference to the AST node to be checked |
1229 @param node reference to the AST node to be checked |
1238 @type ast.If |
1230 @type ast.If |
1239 """ |
1231 """ |
1240 isPattern1 = ( |
1232 isPattern1 = ( |
1241 len(node.body) == 1 |
1233 len(node.body) == 1 |
1288 dictStr = unparse(dictName) |
1280 dictStr = unparse(dictName) |
1289 defaultStr = unparse(defaultValue) |
1281 defaultStr = unparse(defaultValue) |
1290 valueStr = unparse(valueNode) |
1282 valueStr = unparse(valueNode) |
1291 else: |
1283 else: |
1292 return |
1284 return |
1293 self.__error(node.lineno - 1, node.col_offset, "Y123", valueStr, dictStr, |
1285 self.__error( |
1294 keyStr, defaultStr) |
1286 node.lineno - 1, |
|
1287 node.col_offset, |
|
1288 "Y123", |
|
1289 valueStr, |
|
1290 dictStr, |
|
1291 keyStr, |
|
1292 defaultStr, |
|
1293 ) |
1295 |
1294 |
1296 def __check181(self, node): |
1295 def __check181(self, node): |
1297 """ |
1296 """ |
1298 Private method to check for assignments that could be converted into |
1297 Private method to check for assignments that could be converted into |
1299 an augmented assignment. |
1298 an augmented assignment. |
1719 self.__error(node.lineno - 1, node.col_offset, "Y402") |
1718 self.__error(node.lineno - 1, node.col_offset, "Y402") |
1720 |
1719 |
1721 def __check901(self, node): |
1720 def __check901(self, node): |
1722 """ |
1721 """ |
1723 Private method to check for unnecessary bool conversion. |
1722 Private method to check for unnecessary bool conversion. |
1724 |
1723 |
1725 @param node reference to the AST node to be checked |
1724 @param node reference to the AST node to be checked |
1726 @type ast.Call |
1725 @type ast.Call |
1727 """ |
1726 """ |
1728 if ( |
1727 if ( |
1729 isinstance(node.func, ast.Name) |
1728 isinstance(node.func, ast.Name) |
1736 self.__error(node.lineno - 1, node.col_offset, "Y901", expected, actual) |
1735 self.__error(node.lineno - 1, node.col_offset, "Y901", expected, actual) |
1737 |
1736 |
1738 def __check904(self, node): |
1737 def __check904(self, node): |
1739 """ |
1738 """ |
1740 Private method to check for dictionary initialization. |
1739 Private method to check for dictionary initialization. |
1741 |
1740 |
1742 @param node reference to the AST node to be checked |
1741 @param node reference to the AST node to be checked |
1743 @type ast.Assign |
1742 @type ast.Assign |
1744 """ |
1743 """ |
1745 # a = {}; a['b'] = 'c' |
1744 # a = {}; a['b'] = 'c' |
1746 n2 = node.next_sibling |
1745 n2 = node.next_sibling |
1759 self.__error(node.lineno - 1, node.col_offset, "Y904", dictName) |
1758 self.__error(node.lineno - 1, node.col_offset, "Y904", dictName) |
1760 |
1759 |
1761 def __check905(self, node): |
1760 def __check905(self, node): |
1762 """ |
1761 """ |
1763 Private method to check for list initialization by splitting a string. |
1762 Private method to check for list initialization by splitting a string. |
1764 |
1763 |
1765 @param node reference to the AST node to be checked |
1764 @param node reference to the AST node to be checked |
1766 @type ast.Call |
1765 @type ast.Call |
1767 """ |
1766 """ |
1768 if ( |
1767 if ( |
1769 isinstance(node.func, ast.Attribute) |
1768 isinstance(node.func, ast.Attribute) |
1780 self.__error(node.lineno - 1, node.col_offset, "Y905", expected, actual) |
1779 self.__error(node.lineno - 1, node.col_offset, "Y905", expected, actual) |
1781 |
1780 |
1782 def __check906(self, node): |
1781 def __check906(self, node): |
1783 """ |
1782 """ |
1784 Private method to check for unnecessary nesting of os.path.join(). |
1783 Private method to check for unnecessary nesting of os.path.join(). |
1785 |
1784 |
1786 @param node reference to the AST node to be checked |
1785 @param node reference to the AST node to be checked |
1787 @type ast.Call |
1786 @type ast.Call |
1788 """ |
1787 """ |
1789 # __IGNORE_WARNING_D234r__ |
1788 # __IGNORE_WARNING_D234r__ |
1790 def getOsPathJoinArgs(node): |
1789 def getOsPathJoinArgs(node): |
1828 ) |
1827 ) |
1829 ): |
1828 ): |
1830 names = getOsPathJoinArgs(node) |
1829 names = getOsPathJoinArgs(node) |
1831 |
1830 |
1832 actual = unparse(node) |
1831 actual = unparse(node) |
1833 expected = "os.path.join({0})".format(', '.join(names)) |
1832 expected = "os.path.join({0})".format(", ".join(names)) |
1834 self.__error(node.lineno - 1, node.col_offset, "Y906", expected, actual) |
1833 self.__error(node.lineno - 1, node.col_offset, "Y906", expected, actual) |
1835 |
1834 |
1836 def __check907(self, node): |
1835 def __check907(self, node): |
1837 """ |
1836 """ |
1838 Private method to check for Union type annotation with None. |
1837 Private method to check for Union type annotation with None. |
1839 |
1838 |
1840 @param node reference to the AST node to be checked |
1839 @param node reference to the AST node to be checked |
1841 @type ast.Subscript |
1840 @type ast.Subscript |
1842 """ |
1841 """ |
1843 if (isinstance(node.value, ast.Name) and node.value.id == "Union"): |
1842 if isinstance(node.value, ast.Name) and node.value.id == "Union": |
1844 if ( |
1843 if isinstance(node.slice, ast.Index) and isinstance( |
1845 isinstance(node.slice, ast.Index) |
1844 node.slice.value, ast.Tuple |
1846 and isinstance(node.slice.value, ast.Tuple) |
|
1847 ): |
1845 ): |
1848 # Python 3.8 |
1846 # Python 3.8 |
1849 tupleVar = node.slice.value |
1847 tupleVar = node.slice.value |
1850 elif isinstance(node.slice, ast.Tuple): |
1848 elif isinstance(node.slice, ast.Tuple): |
1851 # Python 3.9+ |
1849 # Python 3.9+ |
1868 ) |
1866 ) |
1869 |
1867 |
1870 def __check909(self, node): |
1868 def __check909(self, node): |
1871 """ |
1869 """ |
1872 Private method to check for reflexive assignments. |
1870 Private method to check for reflexive assignments. |
1873 |
1871 |
1874 @param node reference to the AST node to be checked |
1872 @param node reference to the AST node to be checked |
1875 @type ast.Assign |
1873 @type ast.Assign |
1876 """ |
1874 """ |
1877 names = [] |
1875 names = [] |
1878 if isinstance(node.value, (ast.Name, ast.Subscript, ast.Tuple)): |
1876 if isinstance(node.value, (ast.Name, ast.Subscript, ast.Tuple)): |
1882 |
1880 |
1883 if len(names) != len(set(names)) and not isinstance(node.parent, ast.ClassDef): |
1881 if len(names) != len(set(names)) and not isinstance(node.parent, ast.ClassDef): |
1884 srccode = unparse(node) |
1882 srccode = unparse(node) |
1885 self.__error(node.lineno - 1, node.col_offset, "Y909", srccode) |
1883 self.__error(node.lineno - 1, node.col_offset, "Y909", srccode) |
1886 |
1884 |
|
1885 |
1887 # |
1886 # |
1888 # eflag: noqa = M891 |
1887 # eflag: noqa = M891 |