예제 #1
0
 def leave_Name(
         self, original_node: cst.Name,
         updated_node: cst.Name) -> Union[cst.Name, cst.SimpleString]:
     value = updated_node.value
     if value == "NoneType":
         # This is special-cased in typing, un-special case it.
         return updated_node.with_changes(value="None")
     if value in CST_DIR and not value.endswith("Sentinel"):
         # If this isn't a typing define and it isn't a builtin, convert it to
         # a forward ref string.
         return cst.SimpleString(repr(value))
     return updated_node
예제 #2
0
 def leave_Decorator(
     self, original_node: Decorator, updated_node: Decorator
 ) -> Union[Decorator, FlattenSentinel[Decorator], RemovalSentinel]:
     """Update decorator call if all conditions are met."""
     if self.decorators_matcher and m.matches(updated_node, self.decorators_matcher):
         # If we have a decorator matcher, and it matches,
         # then update the node with new name
         updated_decorator = updated_node.decorator.with_changes(
             attr=Name("simple_tag")
         )
         return updated_node.with_changes(decorator=updated_decorator)
     return super().leave_Decorator(original_node, updated_node)
예제 #3
0
 def visit_Name(self, node: libcst.Name) -> None:
     if self.annotation_counter > 0 and node.value in BUILTINS_TO_REPLACE:
         correct_type = node.value.title()
         scope = self.get_metadata(ScopeProvider, node)
         replacement = None
         if scope is not None and correct_type in scope:
             replacement = node.with_changes(value=correct_type)
         self.report(
             node,
             REPLACE_BUILTIN_TYPE_ANNOTATION.format(
                 builtin_type=node.value, correct_type=correct_type
             ),
             replacement=replacement,
         )
예제 #4
0
 def visit_Name(self, node: cst.Name) -> Optional[bool]:
     if (len(self.imports) > 0 or len(self.attributes) > 0
             or len(self.annotations) > 0):
         return
     pos = self.get_metadata(PositionProvider, node)
     start = pos.start
     end = pos.end
     tup = (start.line, start.column, end.line, end.column)
     # remove this if condition when the type issues are fixed.
     if not any(
             node.deep_equals(name) and tup == _tup for (name, _tup) in {
                 (cst.Name("i"), (17, 21, 17, 22)),
             }):
         self.test.assertIn(
             tup,
             self.lookup,
             f"Name node {node.value} at {tup} found without inferred type.",
         )
예제 #5
0
 def leave_ImportFrom(
     self, original_node: ImportFrom, updated_node: ImportFrom
 ) -> Union[BaseSmallStatement, RemovalSentinel]:
     if self._test_import_from(updated_node):
         new_names = []
         new_import_missing = True
         new_import_alias = None
         for import_alias in original_node.names:
             if import_alias.evaluated_name == self.old_name:
                 new_import_alias = ImportAlias(name=Name(self.new_name))
             else:
                 if import_alias.evaluated_name == self.new_name:
                     new_import_missing = False
                 new_names.append(import_alias)
         if new_import_missing and new_import_alias is not None:
             new_names.append(new_import_alias)
         new_names = list(sorted(new_names, key=lambda n: n.evaluated_name))
         return ImportFrom(module=updated_node.module, names=new_names)
     return super().leave_ImportFrom(original_node, updated_node)
예제 #6
0
    def _check_import_from_exact(
        self, original_node: ImportFrom, updated_node: ImportFrom
    ) -> Optional[Union[BaseSmallStatement, RemovalSentinel]]:
        """
        Check for when the thing to replace is imported exactly.

        When `parent.module.the_thing` is transformed, detect such import:

            from parent.module import the_thing
        """
        # First, exit early if 'import *' is used
        if isinstance(updated_node.names, ImportStar):
            return None
        # Check whether the exact symbol is imported
        if not import_from_matches(updated_node, self.old_module_parts):
            return None
        # Match, update the node an return it
        new_import_aliases = []
        for import_alias in updated_node.names:
            if not self.old_name or import_alias.evaluated_name == self.old_name:
                if import_alias.evaluated_alias is None:
                    self.save_import_scope(original_node)
                    self.context.scratch[self.ctx_key_name_matcher] = m.Name(
                        self.old_name)
                    if self.new_name:
                        self.context.scratch[self.ctx_key_new_func] = Name(
                            self.new_name)
                if self.rename_from != self.rename_to:
                    if self.simple_rename:
                        AddImportsVisitor.add_needed_import(
                            context=self.context,
                            module=".".join(self.new_module_parts),
                            obj=self.new_name or import_alias.evaluated_name,
                            asname=import_alias.evaluated_alias,
                        )
                    continue
            new_import_aliases.append(import_alias)
        if not new_import_aliases:
            # Nothing left in the import statement: remove it
            return RemoveFromParent()
        # Some imports are left, update the statement
        new_import_aliases = clean_new_import_aliases(new_import_aliases)
        return updated_node.with_changes(names=new_import_aliases)
예제 #7
0
    def visit_Name(self, node: libcst.Name) -> None:
        # Avoid a false-positive in this scenario:
        #
        # ```
        # from typing import List as list
        # from graphene import List
        # ```
        qualified_names = self.get_metadata(QualifiedNameProvider, node, set())

        is_builtin_type = node.value in BUILTINS_TO_REPLACE and all(qualified_name.name in QUALIFIED_BUILTINS_TO_REPLACE for qualified_name in qualified_names)

        if self.annotation_counter > 0 and is_builtin_type:
            correct_type = node.value.title()
            scope = self.get_metadata(ScopeProvider, node)
            replacement = None
            if scope is not None and correct_type in scope:
                replacement = node.with_changes(value=correct_type)
            self.report(
                node,
                REPLACE_BUILTIN_TYPE_ANNOTATION.format(builtin_type=node.value, correct_type=correct_type),
                replacement=replacement,
            )
예제 #8
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))
예제 #9
0
 def leave_Call(self, original_node: Call,
                updated_node: Call) -> BaseExpression:
     if self.is_entity_imported and m.matches(
             updated_node, m.Call(func=m.Name(self.old_name))):
         return Name(self.new_name)
     return super().leave_Call(original_node, updated_node)
예제 #10
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"))
예제 #11
0
    def leave_Module(self, original_node: "Module",
                     updated_node: "Module") -> "Module":
        if not self.names:
            return original_node

        modified_body = list(original_node.body)

        indented_space = ParenthesizedWhitespace(
            first_line=TrailingWhitespace(
                whitespace=SimpleWhitespace(value=""),
                comment=None,
                newline=Newline(value=None),
            ),
            empty_lines=[],
            indent=True,
            last_line=SimpleWhitespace(value="    "),
        )

        indented_comma = Comma(
            whitespace_before=SimpleWhitespace(value=""),
            whitespace_after=indented_space,
        )
        line_break = ParenthesizedWhitespace(first_line=TrailingWhitespace(
            whitespace=SimpleWhitespace(value=""),
            comment=None,
            newline=Newline(value=None),
        ))

        list_values = [
            Element(SimpleString(value=f'"{global_name}"'),
                    comma=indented_comma) for global_name in self.names[:-1]
        ]
        list_values.append(
            Element(
                SimpleString(value=f'"{self.names[-1]}"'),
                comma=Comma(
                    whitespace_before=SimpleWhitespace(value=""),
                    whitespace_after=line_break,
                ),
            ))

        all_names = Assign(
            targets=(AssignTarget(target=Name(value="__all__")), ),
            value=List(
                list_values,
                lbracket=LeftSquareBracket(
                    whitespace_after=ParenthesizedWhitespace(
                        first_line=TrailingWhitespace(
                            whitespace=SimpleWhitespace(value=""),
                            comment=None,
                            newline=Newline(value=None),
                        ),
                        empty_lines=[],
                        indent=True,
                        last_line=SimpleWhitespace(value="    "),
                    )),
                rbracket=RightSquareBracket(whitespace_before=SimpleWhitespace(
                    value="")),
            ),
        )

        modified_body.append(Newline())
        modified_body.append(all_names)
        return updated_node.with_changes(body=modified_body)
예제 #12
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)
예제 #13
0
 def update_call_args(self, node: Call) -> Sequence[Arg]:
     return (Arg(value=Name("None")), *node.args)
예제 #14
0
 def update_call(self, updated_node: Call) -> BaseExpression:
     updated_args = self.update_call_args(updated_node)
     return Call(args=updated_args, func=Name(self.new_name))
예제 #15
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
예제 #16
0
 def fix_unicode(self, original_node: Name, updated_node: Name) -> BaseExpression:
     value = "text_type"
     if value not in self.future_utils_imports:
         self.future_utils_new_imports.add(value)
     return updated_node.with_changes(value=value)
예제 #17
0
 def leave_Name(self, original_node: cst.Name, updated_node: cst.Name):
     if re.match(r"^\$.+\$$", original_node.value):
         return updated_node.with_changes(
             value=original_node.value.replace(" ", ""))
     else:
         return original_node
예제 #18
0
 def leave_Call(self, original_node: Call,
                updated_node: Call) -> BaseExpression:
     matcher = self.name_matcher
     if m.matches(updated_node, m.Call(func=matcher)):
         return Name(self.new_name)
     return super().leave_Call(original_node, updated_node)
예제 #19
0
 def leave_Call(self, original_node: Call, updated_node: Call) -> BaseExpression:
     if m.matches(updated_node, m.Call(func=m.Name(self.old_name))):
         updated_args = self.update_call_args(updated_node)
         return Call(args=updated_args, func=Name(self.new_name))
     return super().leave_Call(original_node, updated_node)