171 checkersWithCodes = [ |
170 checkersWithCodes = [ |
172 (self.__checkCoding, ("M101", "M102")), |
171 (self.__checkCoding, ("M101", "M102")), |
173 (self.__checkCopyright, ("M111", "M112")), |
172 (self.__checkCopyright, ("M111", "M112")), |
174 (self.__checkBuiltins, ("M131", "M132")), |
173 (self.__checkBuiltins, ("M131", "M132")), |
175 (self.__checkComprehensions, ("M181", "M182", "M183", "M184", |
174 (self.__checkComprehensions, ("M181", "M182", "M183", "M184", |
176 "M185", "M186", "M187", |
175 "M185", "M186", "M187", "M188", |
|
176 "M189", |
177 "M191", "M192", "M193", |
177 "M191", "M192", "M193", |
178 "M195", "M196", "M197", "M198")), |
178 "M195", "M196", "M197", "M198")), |
179 (self.__checkDictWithSortedKeys, ("M201",)), |
179 (self.__checkDictWithSortedKeys, ("M201",)), |
180 (self.__checkDateTime, ("M301", "M302", "M303", "M304", "M305", |
180 (self.__checkDateTime, ("M301", "M302", "M303", "M304", "M305", |
181 "M306", "M307", "M308", "M311", "M312", |
181 "M306", "M307", "M308", "M311", "M312", |
694 }[node.func.id] |
695 }[node.func.id] |
695 self.__error(node.lineno - 1, node.col_offset, errorCode) |
696 self.__error(node.lineno - 1, node.col_offset, errorCode) |
696 |
697 |
697 elif ( |
698 elif ( |
698 nArgs == 1 and |
699 nArgs == 1 and |
699 isinstance(node.args[0], ast.GeneratorExp) and |
700 isinstance(node.args[0], |
|
701 (ast.GeneratorExp, ast.ListComp)) and |
700 isinstance(node.args[0].elt, ast.Tuple) and |
702 isinstance(node.args[0].elt, ast.Tuple) and |
701 len(node.args[0].elt.elts) == 2 and |
703 len(node.args[0].elt.elts) == 2 and |
702 node.func.id == "dict" |
704 node.func.id == "dict" |
703 ): |
705 ): |
704 self.__error(node.lineno - 1, node.col_offset, "M183") |
706 if isinstance(node.args[0], ast.GeneratorExp): |
|
707 errorCode = "M183" |
|
708 else: |
|
709 errorCode = "M185" |
|
710 self.__error(node.lineno - 1, node.col_offset, errorCode) |
705 |
711 |
706 elif ( |
712 elif ( |
707 nArgs == 1 and |
713 nArgs == 1 and |
708 isinstance(node.args[0], ast.ListComp) and |
714 isinstance(node.args[0], ast.ListComp) and |
709 node.func.id in ('list', 'set', 'dict') |
715 node.func.id in ('list', 'set') |
710 ): |
716 ): |
711 errorCode = { |
717 errorCode = { |
712 'list': 'M195', |
718 'list': 'M195', |
713 'dict': 'M185', |
|
714 'set': 'M184', |
719 'set': 'M184', |
715 }[node.func.id] |
720 }[node.func.id] |
716 self.__error(node.lineno - 1, node.col_offset, errorCode) |
721 self.__error(node.lineno - 1, node.col_offset, errorCode) |
717 |
722 |
718 elif nArgs == 1 and ( |
723 elif nArgs == 1 and ( |
741 "dict": "M191", |
746 "dict": "M191", |
742 }[node.func.id] |
747 }[node.func.id] |
743 self.__error(node.lineno - 1, node.col_offset, errorCode, |
748 self.__error(node.lineno - 1, node.col_offset, errorCode, |
744 type(node.args[0]).__name__.lower(), |
749 type(node.args[0]).__name__.lower(), |
745 node.func.id) |
750 node.func.id) |
746 |
|
747 elif ( |
|
748 nArgs == 1 and |
|
749 isinstance(node.args[0], ast.ListComp) and |
|
750 node.func.id in ('all', 'any', 'enumerate', 'frozenset', |
|
751 'max', 'min', 'sorted', 'sum', 'tuple',) |
|
752 ): |
|
753 self.__error(node.lineno - 1, node.col_offset, "M187", |
|
754 node.func.id) |
|
755 |
751 |
756 elif ( |
752 elif ( |
757 nArgs == 0 and |
753 nArgs == 0 and |
758 not any(isinstance(a, ast.Starred) for a in node.args) and |
754 not any(isinstance(a, ast.Starred) for a in node.args) and |
759 not any(k.arg is None for k in node.keywords) and |
755 not any(k.arg is None for k in node.keywords) and |
760 node.func.id in ("tuple", "list", "dict") |
756 node.func.id == "dict" |
|
757 ) or ( |
|
758 nArgs == 0 and |
|
759 nKwArgs == 0 and |
|
760 node.func.id in ("tuple", "list") |
761 ): |
761 ): |
762 self.__error(node.lineno - 1, node.col_offset, "M186", |
762 self.__error(node.lineno - 1, node.col_offset, "M186", |
763 node.func.id) |
763 node.func.id) |
764 |
764 |
765 elif isinstance(node, ast.Compare) and ( |
765 elif ( |
766 len(node.ops) == 1 and |
766 node.func.id in {"list", "reversed"} and |
767 isinstance(node.ops[0], ast.In) and |
767 nArgs > 0 and |
768 len(node.comparators) == 1 and |
768 isinstance(node.args[0], ast.Call) and |
769 isinstance(node.comparators[0], ast.ListComp) |
769 isinstance(node.args[0].func, ast.Name) and |
|
770 node.args[0].func.id == "sorted" |
770 ): |
771 ): |
771 self.__error(node.lineno - 1, node.col_offset, "M196") |
772 if node.func.id == "reversed": |
|
773 reverseFlagValue = False |
|
774 for kw in node.args[0].keywords: |
|
775 if kw.arg != "reverse": |
|
776 continue |
|
777 if isinstance(kw.value, ast.NameConstant): |
|
778 reverseFlagValue = kw.value.value |
|
779 elif isinstance(kw.value, ast.Num): |
|
780 reverseFlagValue = bool(kw.value.n) |
|
781 else: |
|
782 # Complex value |
|
783 reverseFlagValue = None |
|
784 |
|
785 if reverseFlagValue is None: |
|
786 self.__error(node.lineno - 1, node.col_offset, |
|
787 "M187a", node.func.id, |
|
788 node.args[0].func.id) |
|
789 else: |
|
790 self.__error(node.lineno - 1, node.col_offset, |
|
791 "M187b", node.func.id, |
|
792 node.args[0].func.id, |
|
793 not reverseFlagValue) |
|
794 else: |
|
795 self.__error(node.lineno - 1, node.col_offset, |
|
796 "M187c", node.func.id, |
|
797 node.args[0].func.id) |
|
798 |
|
799 elif ( |
|
800 nArgs > 0 and |
|
801 isinstance(node.args[0], ast.Call) and |
|
802 isinstance(node.args[0].func, ast.Name) and |
|
803 ( |
|
804 ( |
|
805 node.func.id in {"set", "sorted"} and |
|
806 node.args[0].func.id in { |
|
807 "list", "reversed", "sorted", "tuple"} |
|
808 ) or ( |
|
809 node.func.id in {"list", "tuple"} and |
|
810 node.args[0].func.id in {"list", "tuple"} |
|
811 ) or ( |
|
812 node.func.id == "set" and |
|
813 node.args[0].func.id == "set" |
|
814 ) |
|
815 ) |
|
816 ): |
|
817 self.__error(node.lineno - 1, node.col_offset, "M188", |
|
818 node.args[0].func.id, node.func.id) |
|
819 |
|
820 elif ( |
|
821 node.func.id in {"reversed", "set", "sorted"} and |
|
822 nArgs > 0 and |
|
823 isinstance(node.args[0], ast.Subscript) and |
|
824 isinstance(node.args[0].slice, ast.Slice) and |
|
825 node.args[0].slice.lower is None and |
|
826 node.args[0].slice.upper is None and |
|
827 isinstance(node.args[0].slice.step, ast.UnaryOp) and |
|
828 isinstance(node.args[0].slice.step.op, ast.USub) and |
|
829 isinstance(node.args[0].slice.step.operand, ast.Num) and |
|
830 node.args[0].slice.step.operand.n == 1 |
|
831 ): |
|
832 self.__error(node.lineno - 1, node.col_offset, |
|
833 "M189", node.func.id) |
|
834 |
|
835 elif ( |
|
836 isinstance(node, (ast.ListComp, ast.SetComp)) and ( |
|
837 len(node.generators) == 1 and |
|
838 not node.generators[0].ifs and |
|
839 not node.generators[0].is_async and ( |
|
840 isinstance(node.elt, ast.Name) and |
|
841 isinstance(node.generators[0].target, ast.Name) and |
|
842 node.elt.id == node.generators[0].target.id |
|
843 ) |
|
844 ) |
|
845 ): |
|
846 compType = { |
|
847 ast.DictComp: "dict", |
|
848 ast.ListComp: "list", |
|
849 ast.SetComp: "set", |
|
850 }[node.__class__] |
|
851 |
|
852 self.__error(node.lineno - 1, node.col_offset, |
|
853 "M196", compType) |
772 |
854 |
773 def __checkMutableDefault(self): |
855 def __checkMutableDefault(self): |
774 """ |
856 """ |
775 Private method to check for use of mutable types as default arguments. |
857 Private method to check for use of mutable types as default arguments. |
776 """ |
858 """ |