485 """ |
486 """ |
486 # if a: |
487 # if a: |
487 # b = c |
488 # b = c |
488 # else: |
489 # else: |
489 # b = d |
490 # b = d |
|
491 # |
|
492 # but not: |
|
493 # if a: |
|
494 # b = c |
|
495 # elif c: |
|
496 # b = e |
|
497 # else: |
|
498 # b = d |
490 if ( |
499 if ( |
491 len(node.body) == 1 and |
500 len(node.body) == 1 and |
492 len(node.orelse) == 1 and |
501 len(node.orelse) == 1 and |
493 isinstance(node.body[0], ast.Assign) and |
502 isinstance(node.body[0], ast.Assign) and |
494 isinstance(node.orelse[0], ast.Assign) and |
503 isinstance(node.orelse[0], ast.Assign) and |
495 len(node.body[0].targets) == 1 and |
504 len(node.body[0].targets) == 1 and |
496 len(node.orelse[0].targets) == 1 and |
505 len(node.orelse[0].targets) == 1 and |
497 isinstance(node.body[0].targets[0], ast.Name) and |
506 isinstance(node.body[0].targets[0], ast.Name) and |
498 isinstance(node.orelse[0].targets[0], ast.Name) and |
507 isinstance(node.orelse[0].targets[0], ast.Name) and |
499 node.body[0].targets[0].id == node.orelse[0].targets[0].id |
508 node.body[0].targets[0].id == node.orelse[0].targets[0].id and |
|
509 not isinstance(node.parent, ast.If) |
500 ): |
510 ): |
501 assign = unparse(node.body[0].targets[0]) |
511 assign = unparse(node.body[0].targets[0]) |
502 body = unparse(node.body[0].value) |
512 body = unparse(node.body[0].value) |
503 cond = unparse(node.test) |
513 cond = unparse(node.test) |
504 orelse = unparse(node.orelse[0].value) |
514 orelse = unparse(node.orelse[0].value) |
505 if len( |
515 if len( |
506 "{0} = {1} if {2} else {3}".format(assign, body, cond, orelse) |
516 "{0} = {1} if {2} else {3}".format(assign, body, cond, orelse) |
507 ) > 79: |
517 ) < 79: |
508 self.__error(node.lineno - 1, node.col_offset, "Y108a") |
518 # don't flag an issue, if the ternary would get too complicated |
509 else: |
519 self.__error(node.lineno - 1, node.col_offset, "Y108", |
510 self.__error(node.lineno - 1, node.col_offset, "Y108b", |
|
511 assign, body, cond, orelse) |
520 assign, body, cond, orelse) |
512 |
521 |
513 def __check109(self, node): |
522 def __check109(self, node): |
514 """ |
523 """ |
515 Private method to check for multiple equalities with the same value |
524 Private method to check for multiple equalities with the same value |
846 for withitem in node.items + node.body[0].items: |
855 for withitem in node.items + node.body[0].items: |
847 withItems.append(f"{unparse(withitem)}") |
856 withItems.append(f"{unparse(withitem)}") |
848 mergedWith = f"with {', '.join(withItems)}:" |
857 mergedWith = f"with {', '.join(withItems)}:" |
849 self.__error(node.lineno - 1, node.col_offset, "Y117", mergedWith) |
858 self.__error(node.lineno - 1, node.col_offset, "Y117", mergedWith) |
850 |
859 |
851 def __check118a(self, node): |
860 def __check118(self, node): |
852 """ |
861 """ |
853 Private method to check for usages of "key in dict.keys()". |
862 Private method to check for usages of "key in dict.keys()". |
854 |
863 |
855 @param node reference to the AST node to be checked |
864 @param node reference to the AST node to be checked |
856 @type ast.Compare |
865 @type ast.Compare or ast.For |
857 """ |
866 """ |
858 # key in dict.keys() |
867 # Pattern 1: |
|
868 # |
|
869 # if key in dict.keys(): |
|
870 # # do something |
|
871 # |
|
872 # Pattern 2: |
|
873 # |
|
874 # for key in dict.keys(): |
|
875 # # do something |
859 if ( |
876 if ( |
|
877 isinstance(node, ast.Compare) and |
860 len(node.ops) == 1 and |
878 len(node.ops) == 1 and |
861 isinstance(node.ops[0], ast.In) and |
879 isinstance(node.ops[0], ast.In) and |
862 len(node.comparators) == 1 |
880 len(node.comparators) == 1 |
863 ): |
881 ): |
864 callNode = node.comparators[0] |
882 callNode = node.comparators[0] |
865 if not isinstance(callNode, ast.Call): |
883 elif ( |
866 return |
884 isinstance(node, ast.For) |
867 |
885 ): |
868 attrNode = callNode.func |
886 callNode = node.iter |
869 if ( |
887 else: |
870 isinstance(callNode.func, ast.Attribute) and |
888 callNode = None |
871 callNode.func.attr == "keys" and |
889 |
872 isinstance(callNode.func.ctx, ast.Load) |
|
873 ): |
|
874 keyStr = unparse(node.left) |
|
875 dictStr = unparse(attrNode.value) |
|
876 self.__error(node.lineno - 1, node.col_offset, "Y118", |
|
877 keyStr, dictStr) |
|
878 |
|
879 def __check118b(self, node): |
|
880 """ |
|
881 Private method to check for usages of "key in dict.keys()". |
|
882 |
|
883 @param node reference to the AST node to be checked |
|
884 @type ast.For |
|
885 """ |
|
886 # for key in dict.keys(): |
|
887 # # do something |
|
888 callNode = node.iter |
|
889 if not isinstance(callNode, ast.Call): |
890 if not isinstance(callNode, ast.Call): |
890 return |
891 return |
891 |
892 |
892 attrNode = callNode.func |
893 attrNode = callNode.func |
893 if ( |
894 if ( |
894 isinstance(callNode.func, ast.Attribute) and |
895 isinstance(callNode.func, ast.Attribute) and |
895 callNode.func.attr == "keys" and |
896 callNode.func.attr == "keys" and |
896 isinstance(callNode.func.ctx, ast.Load) |
897 isinstance(callNode.func.ctx, ast.Load) |
897 ): |
898 ): |
898 keyStr = unparse(node.target) |
899 if isinstance(node, ast.Compare): |
|
900 keyStr = unparse(node.left) |
|
901 else: |
|
902 keyStr = unparse(node.target) |
899 dictStr = unparse(attrNode.value) |
903 dictStr = unparse(attrNode.value) |
900 self.__error(node.lineno - 1, node.col_offset, "Y118", |
904 self.__error(node.lineno - 1, node.col_offset, "Y118", |
901 keyStr, dictStr) |
905 keyStr, dictStr) |
902 |
906 |
903 def __check119(self, node): |
907 def __check119(self, node): |
904 """ |
908 """ |
905 Public method to check for classes that should be "dataclasses". |
909 Private method to check for classes that should be "dataclasses". |
906 |
910 |
907 @param node reference to the AST node to be checked |
911 @param node reference to the AST node to be checked |
908 @type ast.ClassDef |
912 @type ast.ClassDef |
909 """ |
913 """ |
910 if ( |
914 if ( |
932 sum(1 for el in node.body |
936 sum(1 for el in node.body |
933 if isinstance(el, ast.FunctionDef)) > 0 |
937 if isinstance(el, ast.FunctionDef)) > 0 |
934 ): |
938 ): |
935 self.__error(node.lineno - 1, node.col_offset, "Y119", |
939 self.__error(node.lineno - 1, node.col_offset, "Y119", |
936 node.name) |
940 node.name) |
|
941 |
|
942 def __check120(self, node): |
|
943 """ |
|
944 Private method to check for classes that inherit from object. |
|
945 |
|
946 @param node reference to the AST node to be checked |
|
947 @type ast.ClassDef |
|
948 """ |
|
949 # class FooBar(object): |
|
950 # ... |
|
951 if ( |
|
952 len(node.bases) == 1 and |
|
953 isinstance(node.bases[0], ast.Name) and |
|
954 node.bases[0].id == "object" |
|
955 ): |
|
956 self.__error(node.lineno - 1, node.col_offset, "Y120", |
|
957 node.name) |
937 |
958 |
938 # |
959 # |
939 # eflag: noqa = M891 |
960 # eflag: noqa = M891 |