示例#1
0
    def leave_Call(self, original: cst.Call, updated: cst.Call) -> cst.CSTNode:
        try:
            key = original.func.attr.value
            kword_params = self.METHOD_TO_PARAMS[key]
        except (AttributeError, KeyError):
            # Either not a method from the API or too convoluted to be sure.
            return updated

        # If the existing code is valid, keyword args come after positional args.
        # Therefore, all positional args must map to the first parameters.
        args, kwargs = partition(lambda a: not bool(a.keyword), updated.args)
        if any(k.keyword.value == "request" for k in kwargs):
            # We've already fixed this file, don't fix it again.
            return updated

        kwargs, ctrl_kwargs = partition(
            lambda a: not a.keyword.value in self.CTRL_PARAMS, kwargs)

        args, ctrl_args = args[:len(kword_params)], args[len(kword_params):]
        ctrl_kwargs.extend(
            cst.Arg(value=a.value, keyword=cst.Name(value=ctrl))
            for a, ctrl in zip(ctrl_args, self.CTRL_PARAMS))

        request_arg = cst.Arg(
            value=cst.Dict([
                cst.DictElement(cst.SimpleString("'{}'".format(name)),
                                cst.Element(value=arg.value))
                # Note: the args + kwargs looks silly, but keep in mind that
                # the control parameters had to be stripped out, and that
                # those could have been passed positionally or by keyword.
                for name, arg in zip(kword_params, args + kwargs)
            ]),
            keyword=cst.Name("request"))

        return updated.with_changes(args=[request_arg] + ctrl_kwargs)
示例#2
0
    def leave_Call(self, original_node: Call,
                   updated_node: Call) -> BaseExpression:
        """
        Remove the `weak` argument if present in the call.

        This is only changing calls with keyword arguments.
        """
        if self.disconnect_call_matchers and m.matches(
                updated_node, m.OneOf(*self.disconnect_call_matchers)):
            updated_args = []
            should_change = False
            last_comma = MaybeSentinel.DEFAULT
            # Keep all arguments except the one with the keyword `weak` (if present)
            for index, arg in enumerate(updated_node.args):
                if m.matches(arg, m.Arg(keyword=m.Name("weak"))):
                    # An argument with the keyword `weak` was found
                    # -> we need to rewrite the statement
                    should_change = True
                else:
                    updated_args.append(arg)
                last_comma = arg.comma  # type: ignore
            if should_change:
                # Make sure the end of line is formatted as initially
                updated_args[-1] = updated_args[-1].with_changes(
                    comma=last_comma)
                return updated_node.with_changes(args=updated_args)
        return super().leave_Call(original_node, updated_node)
    def visit_Call(self, node: cst.Call) -> None:
        if m.matches(
            node,
            m.Call(
                func=m.Name("list") | m.Name("set") | m.Name("dict"),
                args=[m.Arg(value=m.GeneratorExp() | m.ListComp())],
            ),
        ):
            call_name = cst.ensure_type(node.func, cst.Name).value

            if m.matches(node.args[0].value, m.GeneratorExp()):
                exp = cst.ensure_type(node.args[0].value, cst.GeneratorExp)
                message_formatter = UNNECESSARY_GENERATOR
            else:
                exp = cst.ensure_type(node.args[0].value, cst.ListComp)
                message_formatter = UNNECESSARY_LIST_COMPREHENSION

            replacement = None
            if call_name == "list":
                replacement = node.deep_replace(node, cst.ListComp(elt=exp.elt, for_in=exp.for_in))
            elif call_name == "set":
                replacement = node.deep_replace(node, cst.SetComp(elt=exp.elt, for_in=exp.for_in))
            elif call_name == "dict":
                elt = exp.elt
                key = None
                value = None
                if m.matches(elt, m.Tuple(m.DoNotCare(), m.DoNotCare())):
                    elt = cst.ensure_type(elt, cst.Tuple)
                    key = elt.elements[0].value
                    value = elt.elements[1].value
                elif m.matches(elt, m.List(m.DoNotCare(), m.DoNotCare())):
                    elt = cst.ensure_type(elt, cst.List)
                    key = elt.elements[0].value
                    value = elt.elements[1].value
                else:
                    # Unrecoginized form
                    return

                replacement = node.deep_replace(
                    node,
                    # pyre-fixme[6]: Expected `BaseAssignTargetExpression` for 1st
                    #  param but got `BaseExpression`.
                    cst.DictComp(key=key, value=value, for_in=exp.for_in),
                )

            self.report(node, message_formatter.format(func=call_name), replacement=replacement)
示例#4
0
    def leave_Call(self, original_node: cst.Call,
                   updated_node: cst.Call) -> cst.Call:
        if matchers.matches(updated_node, self.matcher):
            return updated_node.with_changes(
                func=updated_node.func.with_changes(attr=cst.Name(
                    value="InsertColumn")))

        return updated_node
示例#5
0
 def _get_async_call_replacement(self,
                                 node: cst.Call) -> Optional[cst.CSTNode]:
     func = node.func
     if m.matches(func, m.Attribute()):
         func = cast(cst.Attribute, func)
         attr_func_replacement = self._get_async_attr_replacement(func)
         if attr_func_replacement is not None:
             return node.with_changes(func=attr_func_replacement)
     return self._get_awaitable_replacement(node)
示例#6
0
 def leave_Call(self, original_node: Call,
                updated_node: Call) -> BaseExpression:
     if m.matches(updated_node, m.Call(func=m.Name("print"))):
         AddImportsVisitor.add_needed_import(
             self.context,
             "pprint",
             "pprint",
         )
         return updated_node.with_changes(func=Name("pprint"))
     return super().leave_Call(original_node, updated_node)
示例#7
0
 def _gen_builtin_call(self, node: cst.Call) -> cst.Call:
     if not node.args:
         return node
     value = node.args[0].value
     if isinstance(value, cst.ListComp):
         pars: dict = {"lpar": [], "rpar": []} if len(node.args) == 1 else {}
         arg0 = node.args[0].with_changes(
             value=cst.GeneratorExp(elt=value.elt, for_in=value.for_in, **pars)
         )
         return node.with_changes(args=(arg0, *node.args[1:]))
     if isinstance(value, cst.GeneratorExp):
         if len(node.args) == 1 and value.lpar:
             arg0 = node.args[0].with_changes(
                 value=cst.GeneratorExp(
                     elt=value.elt, for_in=value.for_in, lpar=[], rpar=[]
                 )
             )
             return node.with_changes(args=(arg0, *node.args[1:]))
     return node
示例#8
0
 def visit_Call(self, node: cst.Call) -> None:
     if m.matches(
         node,
         m.Call(func=m.Attribute(value=m.Name("self"), attr=m.Name("assertEquals"))),
     ):
         new_call = node.with_deep_changes(
             old_node=cst.ensure_type(node.func, cst.Attribute).attr,
             value="assertEqual",
         )
         self.report(node, replacement=new_call)
示例#9
0
	def datetime_replace(
			self, original_node: cst.Call, updated_node: cst.Call
	) -> cst.Call:
		self._update_imports()
		
		return updated_node.with_changes(
				func=cst.Attribute(
						value=cst.Name(value="datetime"), attr=cst.Name("now")
				),
				args=[cst.Arg(value=cst.Name(value="UTC"))],
		)
示例#10
0
    def leave_Call(self, original_node: cst.Call,
                   updated_node: cst.Call) -> cst.Call:
        if matchers.matches(updated_node, self.call_matcher):
            # Update method's call
            updated_node = updated_node.with_changes(
                func=updated_node.func.with_changes(attr=cst.Name(
                    value="AddTool")))

            # Transform keywords
            updated_node_args = list(updated_node.args)

            for arg_matcher, renamed in self.args_matchers_map.items():
                for i, node_arg in enumerate(updated_node.args):
                    if matchers.matches(node_arg, arg_matcher):
                        updated_node_args[i] = node_arg.with_changes(
                            keyword=cst.Name(value=renamed))

                updated_node = updated_node.with_changes(
                    args=updated_node_args)

        return updated_node
示例#11
0
 def _set_call(self, node: cst.Call) -> Union[cst.Call, cst.Set, cst.SetComp]:
     if len(node.args) != 1:
         return node
     value = node.args[0].value
     if isinstance(value, (cst.List, cst.Tuple)):
         if value.elements:
             return cst.Set(elements=value.elements)
         else:
             return node.with_changes(args=[])
     if isinstance(value, (cst.ListComp, cst.SetComp, cst.GeneratorExp)):
         return cst.SetComp(elt=value.elt, for_in=value.for_in)
     return node
 def leave_Call(self, original_node: cst.Call) -> None:
     if self.current_classes and m.matches(
         original_node,
         m.Call(
             func=m.Name("super"),
             args=[
                 m.Arg(value=self._build_arg_class_matcher()),
                 m.Arg(),
             ],
         ),
     ):
         self.report(original_node, replacement=original_node.with_changes(args=()))
示例#13
0
    def leave_Call(self, original_node: cst.Call,
                   updated_node: cst.Call) -> cst.Call:
        # Migrate form deprecated method AppendItem()
        if matchers.matches(updated_node, self.deprecated_call_matcher):
            updated_node = updated_node.with_changes(
                func=updated_node.func.with_changes(attr=cst.Name(
                    value="Append")))

        # Update keywords
        if matchers.matches(updated_node, self.call_matcher):
            updated_node_args = list(updated_node.args)

            for arg_matcher, renamed in self.args_matchers_map.items():
                for i, node_arg in enumerate(updated_node.args):
                    if matchers.matches(node_arg, arg_matcher):
                        updated_node_args[i] = node_arg.with_changes(
                            keyword=cst.Name(value=renamed))

                updated_node = updated_node.with_changes(
                    args=updated_node_args)

        return updated_node
示例#14
0
 def leave_Call(
     self,
     original_node: cst.Call,
     updated_node: cst.Call,
 ) -> cst.Call:
     if len(updated_node.args) < self.argument_count:
         return updated_node
     else:
         last_arg = updated_node.args[-1]
         return updated_node.with_changes(args=(
             *updated_node.args[:-1],
             last_arg.with_changes(comma=cst.Comma()),
         ), )
示例#15
0
 def leave_Call(self, original_node: Call,
                updated_node: Call) -> BaseExpression:
     if (self.is_visiting_subclass and m.matches(
             updated_node,
             m.Call(func=m.Attribute(
                 attr=m.Name("has_add_permission"),
                 value=m.Call(func=m.Name("super")),
             )),
     ) and len(updated_node.args) < 2):
         updated_args = (
             *updated_node.args,
             parse_arg("obj=obj"),
         )
         return updated_node.with_changes(args=updated_args)
     return super().leave_Call(original_node, updated_node)
示例#16
0
 def leave_Call(self, original_node: Call,
                updated_node: Call) -> BaseExpression:
     if (is_one_to_one_field(original_node) or is_foreign_key(original_node)
         ) and not has_on_delete(original_node):
         AddImportsVisitor.add_needed_import(
             context=self.context,
             module="django.db",
             obj="models",
         )
         updated_args = (
             *updated_node.args,
             parse_arg("on_delete=models.CASCADE"),
         )
         return updated_node.with_changes(args=updated_args)
     return super().leave_Call(original_node, updated_node)
示例#17
0
 def leave_Return(
     self, original_node: Return, updated_node: Return
 ) -> Union[BaseSmallStatement, RemovalSentinel]:
     if self.visiting_permalink_method and m.matches(updated_node.value, m.Tuple()):
         elem_0 = updated_node.value.elements[0]
         elem_1_3 = updated_node.value.elements[1:3]
         args = (
             Arg(elem_0.value),
             Arg(Name("None")),
             *[Arg(el.value) for el in elem_1_3],
         )
         return updated_node.with_changes(
             value=Call(func=Name("reverse"), args=args)
         )
     return super().leave_Return(original_node, updated_node)
示例#18
0
    def leave_Call(self, original_node: cst.Call,
                   updated_node: cst.Call) -> cst.BaseExpression:
        if original_node == self.call_node:
            new_args = []
            for arg in updated_node.args:
                if isinstance(arg.keyword, cst.Name):
                    if arg.keyword.value in self.keywords_to_change:
                        value = self.keywords_to_change[arg.keyword.value]
                        if value is not None:
                            new_args.append(arg.with_changes(value=value))
                        # else don't append
                    else:
                        new_args.append(arg)
                else:
                    new_args.append(arg)
            return updated_node.with_changes(args=new_args)

        return updated_node
示例#19
0
 def visit_Call(self, node: cst.Call) -> None:
     # This set excludes frozenset, max, min, sorted, sum, and tuple, which C407 would warn
     # about, because none of those functions short-circuit.
     if m.matches(
             node,
             m.Call(func=m.Name("all") | m.Name("any"),
                    args=[m.Arg(value=m.ListComp())]),
     ):
         list_comp = cst.ensure_type(node.args[0].value, cst.ListComp)
         self.report(
             node,
             UNNECESSARY_LIST_COMPREHENSION.format(
                 func=cst.ensure_type(node.func, cst.Name).value),
             replacement=node.deep_replace(
                 list_comp,
                 cst.GeneratorExp(elt=list_comp.elt,
                                  for_in=list_comp.for_in,
                                  lpar=[],
                                  rpar=[]),
             ),
         )
 def leave_Call(self, original_node: libcst.Call,
                updated_node: libcst.Call) -> libcst.Call:
     check_types = False
     uses_pyre = True
     updated_fields = []
     for field in original_node.args:
         name = field.keyword
         value = field.value
         if not name:
             continue
         name = name.value
         if name == "check_types":
             if isinstance(value, libcst.Name):
                 check_types = check_types or value.value.lower() == "true"
         elif name == "check_types_options":
             if isinstance(value, libcst.SimpleString):
                 uses_pyre = uses_pyre and "mypy" not in value.value.lower()
         elif name not in ["typing", "typing_options"]:
             updated_fields.append(field)
     if check_types and uses_pyre:
         return updated_node.with_changes(args=updated_fields)
     return updated_node
示例#21
0
 def build_path_call(self, pattern, other_args):
     """Build the `Call` node using Django 2.0's `path()` function."""
     route = self.build_route(pattern)
     updated_args = (Arg(value=SimpleString(f"'{route}'")), *other_args)
     return Call(args=updated_args, func=Name("path"))
示例#22
0
    def visit_Call(self, node: cst.Call) -> None:
        if m.matches(
                node,
                m.Call(
                    func=m.Name("tuple") | m.Name("list") | m.Name("set")
                    | m.Name("dict"),
                    args=[m.Arg(value=m.List() | m.Tuple())],
                ),
        ) or m.matches(
                node,
                m.Call(func=m.Name("tuple") | m.Name("list") | m.Name("dict"),
                       args=[]),
        ):

            pairs_matcher = m.ZeroOrMore(
                m.Element(m.Tuple(
                    elements=[m.DoNotCare(), m.DoNotCare()]))
                | m.Element(m.List(
                    elements=[m.DoNotCare(), m.DoNotCare()])))

            exp = cst.ensure_type(node, cst.Call)
            call_name = cst.ensure_type(exp.func, cst.Name).value

            # If this is a empty call, it's an Unnecessary Call where we rewrite the call
            # to literal, except set().
            if not exp.args:
                elements = []
                message_formatter = UNNCESSARY_CALL
            else:
                arg = exp.args[0].value
                elements = cst.ensure_type(
                    arg, cst.List
                    if isinstance(arg, cst.List) else cst.Tuple).elements
                message_formatter = UNNECESSARY_LITERAL

            if call_name == "tuple":
                new_node = cst.Tuple(elements=elements)
            elif call_name == "list":
                new_node = cst.List(elements=elements)
            elif call_name == "set":
                # set() doesn't have an equivelant literal call. If it was
                # matched here, it's an unnecessary literal suggestion.
                if len(elements) == 0:
                    self.report(
                        node,
                        UNNECESSARY_LITERAL.format(func=call_name),
                        replacement=node.deep_replace(
                            node, cst.Call(func=cst.Name("set"))),
                    )
                    return
                new_node = cst.Set(elements=elements)
            elif len(elements) == 0 or m.matches(
                    exp.args[0].value,
                    m.Tuple(elements=[pairs_matcher])
                    | m.List(elements=[pairs_matcher]),
            ):
                new_node = cst.Dict(elements=[(
                    lambda val: cst.DictElement(val.elements[
                        0].value, val.elements[1].value))(cst.ensure_type(
                            ele.value,
                            cst.Tuple if isinstance(ele.value, cst.Tuple
                                                    ) else cst.List,
                        )) for ele in elements])
            else:
                # Unrecoginized form
                return

            self.report(
                node,
                message_formatter.format(func=call_name),
                replacement=node.deep_replace(node, new_node),
            )
示例#23
0
 def leave_Call(self, original_node: Call,
                updated_node: Call) -> BaseExpression:
     if m.matches(updated_node, m.Call(func=m.Name("url"))):
         return Call(args=updated_node.args, func=Name("re_path"))
     return super().leave_Call(original_node, updated_node)
示例#24
0
 def fix_not_iter(self, original_node: Call, updated_node: Call) -> BaseExpression:
     updated_node = Call(func=Name("list"), args=[Arg(updated_node)])
     return updated_node
示例#25
0
 def fix_iter(self, original_node: Call, updated_node: Call) -> BaseExpression:
     attribute = ensure_type(updated_node.func, Attribute)
     func_name = attribute.attr
     dict_name = attribute.value
     return updated_node.with_changes(func=func_name, args=[Arg(dict_name)])
示例#26
0
 def fix_xrange(self, original_node: Call, updated_node: Call) -> BaseExpression:
     orig_func_name = ensure_type(updated_node.func, Name).value
     func_name = "range" if orig_func_name == "xrange" else "input"
     return updated_node.with_changes(func=Name(func_name))
示例#27
0
    def leave_Call(self, original: cst.Call, updated: cst.Call) -> cst.CSTNode:
        try:
            key = original.func.attr.value
            kword_params = self.METHOD_TO_PARAMS[key]
        except (AttributeError, KeyError):
            # Either not a method from the API or too convoluted to be sure.
            return updated

        # If the existing code is valid, keyword args come after positional args.
        # Therefore, all positional args must map to the first parameters.
        args, kwargs = partition(lambda a: not bool(a.keyword), updated.args)
        if any(k.keyword.value == "request" for k in kwargs):
            # We've already fixed this file, don't fix it again.
            return updated

        kwargs, ctrl_kwargs = partition(
            lambda a: not a.keyword.value in self.CTRL_PARAMS, kwargs)

        args, ctrl_args = args[:len(kword_params)], args[len(kword_params):]
        ctrl_kwargs.extend(
            cst.Arg(
                value=a.value,
                keyword=cst.Name(value=ctrl),
                equal=cst.AssignEqual(
                    whitespace_before=cst.SimpleWhitespace(""),
                    whitespace_after=cst.SimpleWhitespace(""),
                ),
            ) for a, ctrl in zip(ctrl_args, self.CTRL_PARAMS))

        if self._use_keywords:
            new_kwargs = [
                cst.Arg(
                    value=arg.value,
                    keyword=cst.Name(value=name),
                    equal=cst.AssignEqual(
                        whitespace_before=cst.SimpleWhitespace(""),
                        whitespace_after=cst.SimpleWhitespace(""),
                    ),
                ) for name, arg in zip(kword_params, args + kwargs)
            ]
            new_kwargs.extend([
                cst.Arg(
                    value=arg.value,
                    keyword=cst.Name(value=arg.keyword.value),
                    equal=cst.AssignEqual(
                        whitespace_before=cst.SimpleWhitespace(""),
                        whitespace_after=cst.SimpleWhitespace(""),
                    ),
                ) for arg in ctrl_kwargs
            ])
            return updated.with_changes(args=new_kwargs)
        else:
            request_arg = cst.Arg(
                value=cst.Dict([
                    cst.DictElement(
                        cst.SimpleString('"{}"'.format(name)),
                        cst.Element(value=arg.value),
                    ) for name, arg in zip(kword_params, args + kwargs)
                ] + [
                    cst.DictElement(
                        cst.SimpleString('"{}"'.format(arg.keyword.value)),
                        cst.Element(value=arg.value),
                    ) for arg in ctrl_kwargs
                ]),
                keyword=cst.Name("request"),
                equal=cst.AssignEqual(
                    whitespace_before=cst.SimpleWhitespace(""),
                    whitespace_after=cst.SimpleWhitespace(""),
                ),
            )

            return updated.with_changes(args=[request_arg])