Esempio n. 1
0
    def transform(self, node, results):
        exc = results["exc"].clone()
        val = results["val"].clone()
        tb = results["tb"].clone()

        exc.prefix = u""
        val.prefix = tb.prefix = u" "

        touch_import(None, u'six', node)
        return Call(Name(u"six.reraise"),
                    [exc, Comma(), val, Comma(), tb],
                    prefix=node.prefix)
    def add_provide_context_to_python_operator(node: LN, capture: Capture, filename: Filename) -> None:
        fn_args = capture['function_arguments'][0]
        fn_args.append_child(Comma())

        provide_context_arg = KeywordArg(Name('provide_context'), Name('True'))
        provide_context_arg.prefix = fn_args.children[0].prefix
        fn_args.append_child(provide_context_arg)
Esempio n. 3
0
def join_comma(entries: List[LN]) -> List[LN]:
    """Join a list with a comma token"""
    out = [entries[0]]
    if len(entries) > 1:
        for entry in entries[1:]:
            out.append(Comma())
            out.append(entry)
    return out
Esempio n. 4
0
def join_comma(entries):
    """Return a copy of a list with comma tokens between items"""
    out = [entries[0]]
    if len(entries) > 1:
        for entry in entries[1:]:
            out.append(Comma())
            out.append(entry)
    return out
Esempio n. 5
0
 def _Call(self, name, args=None, prefix=None):
     """Help the next test"""
     children = []
     if isinstance(args, list):
         for arg in args:
             children.append(arg)
             children.append(Comma())
         children.pop()
     return Call(Name(name), children, prefix)
Esempio n. 6
0
        def add_provide_context_to_python_operator(node: LN, capture: Capture, filename: Filename) -> None:
            fn_args = capture['function_arguments'][0]
            if len(fn_args.children) > 0 and (not isinstance(fn_args.children[-1], Leaf)
                                              or fn_args.children[-1].type != token.COMMA):
                fn_args.append_child(Comma())

            provide_context_arg = KeywordArg(Name('provide_context'), Name('True'))
            provide_context_arg.prefix = fn_args.children[0].prefix
            fn_args.append_child(provide_context_arg)
Esempio n. 7
0
def process_format_format(
        node: LN,
        capture: Capture,
        filename: Filename  # noqa: U100
) -> Optional[LN]:

    formatstring = capture["formatstr"]
    if formatstring.type != token.STRING:
        print(
            "Not formatting {filename}:{node.get_lineno()} because indirect format"
        )
        return None
    num_specifiers = len(RE_FORMAT_SPECIFIER.findall(formatstring.value))
    understood = RE_UNDERSTOOD_FORMAT.findall(formatstring.value)

    if len(understood) != num_specifiers:
        print(
            f"Not formatting {filename}:{node.get_lineno()} because complex format specifiers:\n    {formatstring.value.strip()}"
        )
        return None

    # Basic {}
    formatstring.value = re.sub(r"{}", "%s", formatstring.value)
    # {:.3f} and friends
    formatstring.value = re.sub(r"(?<!{){:(\d*\.\d+f)}", r"%\1",
                                formatstring.value)
    # {:>12}
    formatstring.value = re.sub(r"(?<!{){:>(\d+)}", r"%\1s",
                                formatstring.value)
    # if RE_NONPLAIN_FORMAT.search(formatstring.value):
    #     return None

    # print_node(node, capture=capture)
    # breakpoint()
    if isinstance(capture["arglist"], Leaf):
        arguments = [capture["arglist"]]
    else:
        arguments = list(capture["arglist"].children)

    # Clear the parents of moved nodes
    for child in arguments:
        child.remove()
    formatstring.remove()

    # Rewrite the format-string specifier
    formatstring.value = formatstring.value.replace("{}", "%s")
    # breakpoint()
    # Build the arglist
    capture["formatblock"].replace(
        Node(python_symbols.arglist, [formatstring, Comma()] + arguments))

    # RE_NONPLAIN_FORMAT
    # print_node(node, capture=capture)
    # breakpoint()
    return None
Esempio n. 8
0
def ListNode(*args):
    parts = []
    for arg in args:
        if parts:
            parts.append(Space())
        arg = arg.clone()
        arg.prefix = arg.prefix.lstrip()
        parts.append(arg)
        parts.append(Comma())
    parts.pop()
    return Node(SYMBOL.atom, [LBrace(), *parts, RBrace()])
Esempio n. 9
0
def modify_attr(node: LN, capture: Capture,
                filename: Filename) -> Optional[LN]:
    node.replace(
        Call(
            Name("getattr"),
            args=[
                capture["obj"].clone(),
                Comma(),
                Space(),
                String('"' + capture["attr"].value + '"'),
            ],
        ))
Esempio n. 10
0
def TupleNode(*args):
    parts = []
    for arg in args:
        if parts:
            parts.append(Space())
        arg = arg.clone()
        arg.prefix = arg.prefix.lstrip()
        parts.append(arg)
        parts.append(Comma())
    if len(parts) != 2:
        parts.pop()
    return Node(SYMBOL.atom, [LParen(), *parts, RParen()])
Esempio n. 11
0
def process_percent_format(
        node: LN,
        capture: Capture,
        filename: Filename  # noqa: U100
) -> Optional[LN]:

    # if capture["formatstr"] has more than one format point, don't
    # expand it for now
    # if capture["formatstr"]:
    # print_node(node, capture=capture)
    specifiers = None
    if capture["formatstr"].type == token.STRING:
        if RE_MAPPINGKEY.search(capture["formatstr"].value):
            print(
                f"Not formatting {filename}:{node.get_lineno()} as appears to have mapping key"
            )
            return None
        specifiers = RE_SPECIFIERS.findall(capture["formatstr"].value)

    try:
        # Access precise chain of lookups for the inline-tuple case
        if capture["vars"].children[0].value == "(":
            inner = capture["vars"].children[1]
            if isinstance(inner, Node):
                format_args = inner.children
            elif isinstance(inner, Leaf):
                format_args = [inner]
            else:
                raise RuntimeError("Unknown type")
        else:
            # It's not this specific case, treat it as one item
            raise IndexError
    except IndexError:
        # Not a tuple, if we have more than one specifier then we can't
        # reliably rewrite this.
        if specifiers and len(specifiers) > 1:
            print(
                f"Not formatting {filename}:{node.get_lineno()} because unsafe rewriting indirect tuple"
            )
            return None
        # We aren't something with a sub-tuple, assume single-argument
        format_args = [capture["vars"]]

    # Don't rewrite if
    # Prepare these node for transplant
    for child in format_args:
        child.parent = None
    capture["formatstr"].parent = None

    capture["call"].children[1] = Node(
        python_symbols.arglist,
        [capture["formatstr"], Comma()] + format_args)
    return None
Esempio n. 12
0
    def transform_import(self, node, results):
        """Transform for the basic import case. Replaces the old
        import name with a comma separated list of its
        replacements.
        """
        import_mod = results.get("module")
        pref = import_mod.prefix

        names = []

        # create a Node list of the replacement modules
        for name in MAPPING[import_mod.value][:-1]:
            names.extend([Name(name[0], prefix=pref), Comma()])
        names.append(Name(MAPPING[import_mod.value][-1][0], prefix=pref))
        import_mod.replace(names)
Esempio n. 13
0
def on_delete_modifier(node, capture, filename) -> None:
    if not capture:
        return
    args: Node = capture.get("function_arguments")[0]
    has_on_delete = False
    for node in args.children:
        if isinstance(node, Node) and node.type == 261:
            if node.children[0].value == "on_delete":
                has_on_delete = True
    if not has_on_delete:
        if args.children[-1].value != ",":
            args.append_child(Comma())
        args.append_child(
            KeywordArg(Name("on_delete", prefix=" "), Name("models.CASCADE"))
        )
Esempio n. 14
0
def Assert(test, message=None, **kwargs):
    """Build an assertion statement"""
    if not isinstance(test, list):
        test = [test]
    test[0].prefix = " "
    if message is not None:
        if not isinstance(message, list):
            message = [message]
        message.insert(0, Comma())
        message[1].prefix = " "

    return Node(
        syms.assert_stmt,
        [Leaf(TOKEN.NAME, "assert")] + test + (message or []),
        **kwargs,
    )
Esempio n. 15
0
def handle_assert_regex(node, capture, arguments):
    """
    self.assertRegex(text, pattern, msg)
    --> assert re.search(pattern, text), msg

    self.assertNotRegex(text, pattern, msg)
    --> assert not re.search(pattern, text), msg

    """
    function_name = capture["function_name"].value
    invert = function_name in INVERT_FUNCTIONS
    function_name = SYNONYMS.get(function_name, function_name)
    num_arguments = ARGUMENTS[function_name]

    if len(arguments) not in (num_arguments, num_arguments + 1):
        # Not sure what this is. Leave it alone.
        return None

    if len(arguments) == num_arguments:
        message = None
    else:
        message = arguments.pop()
        if message.type == syms.argument:
            # keyword argument (e.g. `msg=abc`)
            message = message.children[2].clone()

    arguments[0].prefix = " "
    arguments[1].prefix = ""

    # Adds a 'import re' if there wasn't one already
    touch_import(None, "re", node)

    op_tokens = []
    if invert:
        op_tokens.append(keyword("not"))

    assert_test_nodes = [
        Node(
            syms.power,
            op_tokens + Attr(keyword("re"), keyword("search", prefix="")) +
            [ArgList([arguments[1], Comma(), arguments[0]])],
        )
    ]
    return Assert(assert_test_nodes,
                  message.clone() if message else None,
                  prefix=node.prefix)
Esempio n. 16
0
def pytest_approx(node, capture, filename):
    target_value = listify(capture['target_value'])[0].clone()
    target_value.prefix = ''
    abs_tolerance = capture['abs_tolerance'].clone()
    abs_tolerance.prefix = ''
    op_value = listify(capture['op'])[0].value

    # Adds a 'import pytest' if there wasn't one already
    touch_import(None, "pytest", node)

    if op_value in ('<', '<='):
        # as you'd expect in an assert statement
        operator = Leaf(TOKEN.EQEQUAL, '==', prefix=' ')
    else:
        # probably in an if statement
        operator = Leaf(TOKEN.NOTEQUAL, '!=', prefix=' ')

    node.replace(
        Node(
            syms.comparison,
            [
                capture['lhs'].clone(),
                operator,
                Node(
                    syms.power,
                    [
                        kw('pytest'),
                        Node(
                            syms.trailer,
                            [Leaf(TOKEN.DOT, ".", prefix=''), kw('approx', prefix='')],
                            prefix='',
                        ),
                        ArgList(
                            [
                                target_value,
                                Comma(),
                                KeywordArg(kw('abs'), abs_tolerance),
                            ]
                        ),
                    ],
                ),
            ],
            prefix=node.prefix,
        )
    )
Esempio n. 17
0
def add_argument(filename, trailer_node, key, value):
    """
    add "key=value" to arglist in trailer_node,
    if arglist already contains key, reassign key to value
    """
    if trailer_node.type != python_symbols.trailer and len(
            trailer_node.children) != 3:
        log_warning(
            filename, trailer_node.get_lineno(),
            "node type is not trailer or len(children) != 3. you may need to call norm_arglist first."
        )
        return
    arglist_node = trailer_node.children[1]
    if arglist_node.type != python_symbols.arglist:
        log_warning(filename, trailer_node.get_lineno(),
                    "trailer_node.children[1] is not arglist.")
        return
    found_key = False
    for node in arglist_node.children:
        if node.type != python_symbols.argument:
            continue
        _key_node = node.children[0]
        if _key_node.value == key:
            found_key = True
            _value_node = node.children[2]
            if _value_node.value != value:
                _value_node_copy = _value_node.clone()
                _value_node_copy.type = token.NAME
                _value_node_copy.value = value
                _value_node.replace(_value_node_copy)
                log_warning(
                    filename, arglist_node.get_lineno(),
                    'argument "{}" is reassigned to "{}"'.format(key, value))
            break
    if not found_key:
        key_node = Name(key)
        value_node = Name(value)
        if arglist_node.children:
            arglist_node.append_child(Comma())
            key_node.prefix = " "
        arg_node = KeywordArg(key_node, value_node)
        arglist_node.append_child(arg_node)
        log_warning(filename, arglist_node.get_lineno(),
                    'add argument "{}={}"'.format(key, value))
Esempio n. 18
0
def rewrite_print(node, capture, filename):
    """Given a print node, rewrite to a logger.debug"""

    params = capture["function_parameters"]
    # Args is either a Leaf or an arglist Node here
    arglist = params.children[1]

    # Extract the arguments from this list
    if isinstance(arglist, Node) and arglist.type == syms.arglist:
        args = [x for x in arglist.children if not x.type == token.COMMA]
        # Remove kwargs for now
        non_kwargs = [x for x in args if not x.type == syms.argument]
        # Read out things like sep here
        sep = " "

        if not len(non_kwargs) == len(args):
            first_leaf = next(node.leaves())
            print(
                "Warning: {}:{} Not handling keyword argument loggers".format(
                    filename, first_leaf.lineno))
            return None

        # If more than one child, we need to construct a new joiner string
        if len(non_kwargs) > 1:
            # Instead of placing a new, modify the first if it's a string
            if arglist.children[0].type == token.STRING:
                value = arglist.children[0].value
                last_char = value[-1]
                new_end = sep + sep.join(["%s"] * (len(non_kwargs) - 1))
                arglist.children[0].value = value[:-1] + new_end + last_char
            else:
                arglist.insert_child(
                    0, String('"' + sep.join(["%s"] * len(non_kwargs)) + '"'))
                arglist.insert_child(1, Comma())
                arglist.children[2].prefix = " " + arglist.children[2].prefix

    # Use the possibly rewritten parameters in the new call
    new_node = Attr(Name("logger"), Name("debug"))
    new_node[0].prefix = node.children[0].prefix
    node.children = new_node + [params]
Esempio n. 19
0
def convert_regex_to_path_modifier(node: Node, capture: Capture,
                                   filename: Filename) -> None:
    # Replace the import
    if is_import(node):
        name_leafs = [
            Name("path", prefix=" "),
            Comma(),
            Name("re_path", prefix=" "),
        ]
        node.replace([FromImport("django.url", name_leafs=name_leafs)])
    # And function calls from url to path, re_path
    if capture and "function_arguments" in capture:
        function_node: Node = next(node.leaves())
        args = capture.get("function_arguments")
        regex_leaf: Leaf = next(args[0].leaves())
        converted = update_regex_to_path(regex_leaf.value)

        if converted == regex_leaf.value:
            function_node.replace(Name("re_path", prefix=function_node.prefix))
        else:
            function_node.replace(Name("path", prefix=function_node.prefix))
            regex_leaf.value = update_regex_to_path(regex_leaf.value)
Esempio n. 20
0
    def transform(self, node, results):
        # First, find the sys import. We'll just hope it's global scope.
        if "sys_import" in results:
            if self.sys_import is None:
                self.sys_import = results["sys_import"]
            return

        func = results["func"].clone()
        func.prefix = ""
        register = pytree.Node(syms.power, Attr(Name("atexit"), Name("register")))
        call = Call(register, [func], node.prefix)
        node.replace(call)

        if self.sys_import is None:
            # That's interesting.
            self.warning(
                node,
                "Can't find sys import; Please add an atexit "
                "import at the top of your file.",
            )
            return

        # Now add an atexit import after the sys import.
        names = self.sys_import.children[1]
        if names.type == syms.dotted_as_names:
            names.append_child(Comma())
            names.append_child(Name("atexit", " "))
        else:
            containing_stmt = self.sys_import.parent
            position = containing_stmt.children.index(self.sys_import)
            stmt_container = containing_stmt.parent
            new_import = pytree.Node(
                syms.import_name, [Name("import"), Name("atexit", " ")]
            )
            new = pytree.Node(syms.simple_stmt, [new_import])
            containing_stmt.insert_child(position + 1, Newline())
            containing_stmt.insert_child(position + 2, new)
Esempio n. 21
0
    def transform_member(self, node, results):
        """Transform for imports of specific module elements. Replaces
        the module to be imported from with the appropriate new
        module.
        """
        mod_member = results.get("mod_member")
        pref = mod_member.prefix
        member = results.get("member")

        # Simple case with only a single member being imported
        if member:
            # this may be a list of length one, or just a node
            if isinstance(member, list):
                member = member[0]
            new_name = None
            for change in MAPPING[mod_member.value]:
                if member.value in change[1]:
                    new_name = change[0]
                    break
            if new_name:
                mod_member.replace(Name(new_name, prefix=pref))
            else:
                self.cannot_convert(node, "This is an invalid module element")

        # Multiple members being imported
        else:
            # a dictionary for replacements, order matters
            modules = []
            mod_dict = {}
            members = results["members"]
            for member in members:
                # we only care about the actual members
                if member.type == syms.import_as_name:
                    as_name = member.children[2].value
                    member_name = member.children[0].value
                else:
                    member_name = member.value
                    as_name = None
                if member_name != ",":
                    for change in MAPPING[mod_member.value]:
                        if member_name in change[1]:
                            if change[0] not in mod_dict:
                                modules.append(change[0])
                            mod_dict.setdefault(change[0], []).append(member)

            new_nodes = []
            indentation = find_indentation(node)
            first = True

            def handle_name(name, prefix):
                if name.type == syms.import_as_name:
                    kids = [
                        Name(name.children[0].value, prefix=prefix),
                        name.children[1].clone(),
                        name.children[2].clone(),
                    ]
                    return [Node(syms.import_as_name, kids)]
                return [Name(name.value, prefix=prefix)]

            for module in modules:
                elts = mod_dict[module]
                names = []
                for elt in elts[:-1]:
                    names.extend(handle_name(elt, pref))
                    names.append(Comma())
                names.extend(handle_name(elts[-1], pref))
                new = FromImport(module, names)
                if not first or node.parent.prefix.endswith(indentation):
                    new.prefix = indentation
                new_nodes.append(new)
                first = False
            if new_nodes:
                nodes = []
                for new_node in new_nodes[:-1]:
                    nodes.extend([new_node, Newline()])
                nodes.append(new_nodes[-1])
                node.replace(nodes)
            else:
                self.cannot_convert(node, "All module elements are invalid")
Esempio n. 22
0
def make_pytest_raises_blocks(node, capture, filename):
    """
    Turns this:

        try:
            ...
            pytest.fail(...)
        except:
            pass

    Into:
        with pytest.raises(Exception):
            ...

    Not only is this prettier, but the former is a bug since
    pytest.fail() raises an exception.
    """

    exc_class = capture.get('exc_class', None)

    if exc_class:
        exc_class = exc_class.clone()
        exc_class.prefix = ''
        raises_args = [exc_class]
    else:
        raises_args = [kw('Exception', prefix='')]

    reason = capture.get('reason')
    if reason:
        assert len(reason) == 1
        reason = KeywordArg(kw('message'), reason[0].clone())
        raises_args = [Node(syms.arglist, raises_args + [Comma(), reason])]

    raises_args = [LParen()] + raises_args + [RParen()]

    capture['fail_stmt'].remove()

    try_suite = capture['try_suite'].clone()

    with_stmt = Node(
        syms.with_stmt,
        [
            kw('with', prefix=''),
            Node(
                syms.power,
                [
                    kw('pytest'),
                    Node(syms.trailer, [Dot(), kw('raises', prefix='')]),
                    Node(syms.trailer, raises_args),
                ],
            ),
            Leaf(TOKEN.COLON, ':'),
            try_suite,
        ],
        prefix=node.prefix,
    )

    # Trailing whitespace and any comments after the if statement are captured
    # in the prefix for the dedent node. Copy it to the following node.
    dedent = capture["dedent"]
    next_node = node.next_sibling

    # This extra newline avoids syntax errors in some cases (where the try
    # statement is at the end of another suite)
    # I don't really know why those occur.
    # Should clean this stuff up with `black` later.
    node.replace([with_stmt, Newline()])
    next_node.prefix = dedent.prefix
Esempio n. 23
0
def assertalmostequal_to_assert(node, capture, arguments):
    function_name = capture["function_name"].value
    invert = function_name in INVERT_FUNCTIONS
    function_name = SYNONYMS.get(function_name, function_name)

    nargs = len(arguments)
    if nargs < 2 or nargs > 5:
        return None

    def get_kwarg_value(index, name):
        idx = 0
        for arg in arguments:
            if arg.type == syms.argument:
                if arg.children[0].value == name:
                    return arg.children[2].clone()
            else:
                if idx == index:
                    return arg.clone()
                idx += 1
        return None

    first = get_kwarg_value(0, "first")
    second = get_kwarg_value(1, "second")

    if first is None or second is None:
        # Not sure what this is, leave it alone
        return

    places = get_kwarg_value(2, "places")
    msg = get_kwarg_value(3, "msg")
    delta = get_kwarg_value(4, "delta")

    if delta is not None:
        try:
            abs_delta = float(delta.value)
        except ValueError:
            # this should be a number, give up.
            return
    else:
        if places is None:
            places = 7
        else:
            try:
                places = int(places.value)
            except (ValueError, AttributeError):
                # this should be an int, give up.
                return
        abs_delta = "1e-%d" % places

    arguments[1].prefix = ""
    if invert:
        op_token = Leaf(TOKEN.NOTEQUAL, "!=", prefix=" ")
    else:
        op_token = Leaf(TOKEN.EQEQUAL, "==", prefix=" ")
    assert_test_nodes = [
        Node(
            syms.comparison,
            [
                arguments[0],
                op_token,
                Node(
                    syms.power,
                    Attr(keyword("pytest"), keyword("approx", prefix="")) + [
                        ArgList([
                            arguments[1],
                            Comma(),
                            KeywordArg(keyword("abs"),
                                       Leaf(TOKEN.NUMBER, abs_delta)),
                        ])
                    ],
                ),
            ],
        )
    ]
    # Adds a 'import pytest' if there wasn't one already
    touch_import(None, "pytest", node)

    return Assert(assert_test_nodes,
                  msg.clone() if msg else None,
                  prefix=node.prefix)
Esempio n. 24
0
def assertmethod_to_assert(node, capture, arguments):
    """
    self.assertEqual(foo, bar, msg)
    --> assert foo == bar, msg

    self.assertTrue(foo, msg)
    --> assert foo, msg

    self.assertIsNotNone(foo, msg)
    --> assert foo is not None, msg

    .. etc
    """
    function_name = capture["function_name"].value
    invert = function_name in INVERT_FUNCTIONS
    function_name = SYNONYMS.get(function_name, function_name)
    num_arguments = ARGUMENTS[function_name]

    if len(arguments) not in (num_arguments, num_arguments + 1):
        # Not sure what this is. Leave it alone.
        return None

    if len(arguments) == num_arguments:
        message = None
    else:
        message = arguments.pop()
        if message.type == syms.argument:
            # keyword argument (e.g. `msg=abc`)
            message = message.children[2].clone()

    if function_name == "assertIsInstance":
        arguments[0].prefix = ""
        assert_test_nodes = [
            Call(keyword("isinstance"),
                 [arguments[0], Comma(), arguments[1]])
        ]
        if invert:
            assert_test_nodes.insert(0, keyword("not"))
    elif function_name == "assertAlmostEqual":
        arguments[1].prefix = ""
        # TODO: insert the `import pytest` at the top of the file
        if invert:
            op_token = Leaf(TOKEN.NOTEQUAL, "!=", prefix=" ")
        else:
            op_token = Leaf(TOKEN.EQEQUAL, "==", prefix=" ")
        assert_test_nodes = [
            Node(
                syms.comparison,
                [
                    arguments[0],
                    op_token,
                    Node(
                        syms.power,
                        Attr(keyword("pytest"), keyword("approx", prefix="")) +
                        [
                            ArgList([
                                arguments[1],
                                Comma(),
                                KeywordArg(keyword("abs"),
                                           Leaf(TOKEN.NUMBER, "1e-7")),
                            ])
                        ],
                    ),
                ],
            )
        ]
        # Adds a 'import pytest' if there wasn't one already
        touch_import(None, "pytest", node)

    else:
        op_tokens = OPERATORS[function_name]
        if not isinstance(op_tokens, list):
            op_tokens = [op_tokens]
        op_tokens = [o.clone() for o in op_tokens]

        if invert:
            if not op_tokens:
                op_tokens.append(keyword("not"))
            elif op_tokens[0].type == TOKEN.NAME and op_tokens[0].value == "is":
                op_tokens[0] = Node(
                    syms.comp_op,
                    [keyword("is"), keyword("not")], prefix=" ")
            elif op_tokens[0].type == TOKEN.NAME and op_tokens[0].value == "in":
                op_tokens[0] = Node(
                    syms.comp_op,
                    [keyword("not"), keyword("in")], prefix=" ")
            elif op_tokens[0].type == TOKEN.EQEQUAL:
                op_tokens[0] = Leaf(TOKEN.NOTEQUAL, "!=", prefix=" ")

        if num_arguments == 2:
            # a != b, etc.
            assert_test_nodes = [arguments[0]] + op_tokens + [arguments[1]]
        elif function_name == "assertTrue":
            assert_test_nodes = op_tokens + [arguments[0]]
            # not a
        elif function_name == "assertIsNone":
            # a is not None
            assert_test_nodes = [arguments[0]] + op_tokens
    return Assert(assert_test_nodes,
                  message.clone() if message else None,
                  prefix=node.prefix)
Esempio n. 25
0
        def encapsulate_transform(
            node: LN, capture: Capture, filename: Filename
        ) -> None:
            if "attr_assignment" in capture:
                leaf = capture["attr_name"]
                leaf.replace(Name(new_name, prefix=leaf.prefix))

                if make_property:
                    # TODO: capture and use type annotation from original assignment

                    class_node = get_class(node)
                    suite = find_first(class_node, SYMBOL.suite)
                    assert isinstance(suite, Node)
                    indent_node = find_first(suite, TOKEN.INDENT)
                    assert isinstance(indent_node, Leaf)
                    indent = indent_node.value

                    getter = Node(
                        SYMBOL.decorated,
                        [
                            Node(
                                SYMBOL.decorator,
                                [
                                    Leaf(TOKEN.AT, "@"),
                                    Name("property"),
                                    Leaf(TOKEN.NEWLINE, "\n"),
                                ],
                            ),
                            Node(
                                SYMBOL.funcdef,
                                [
                                    Name("def", indent),
                                    Name(old_name, prefix=" "),
                                    Node(
                                        SYMBOL.parameters,
                                        [LParen(), Name("self"), RParen()],
                                    ),
                                    Leaf(TOKEN.COLON, ":"),
                                    Node(
                                        SYMBOL.suite,
                                        [
                                            Newline(),
                                            Leaf(TOKEN.INDENT, indent.value + "    "),
                                            Node(
                                                SYMBOL.simple_stmt,
                                                [
                                                    Node(
                                                        SYMBOL.return_stmt,
                                                        [
                                                            Name("return"),
                                                            Node(
                                                                SYMBOL.power,
                                                                Attr(
                                                                    Name("self"),
                                                                    Name(new_name),
                                                                ),
                                                                prefix=" ",
                                                            ),
                                                        ],
                                                    ),
                                                    Newline(),
                                                ],
                                            ),
                                            Leaf(TOKEN.DEDENT, "\n" + indent),
                                        ],
                                    ),
                                ],
                                prefix=indent,
                            ),
                        ],
                    )

                    setter = Node(
                        SYMBOL.decorated,
                        [
                            Node(
                                SYMBOL.decorator,
                                [
                                    Leaf(TOKEN.AT, "@"),
                                    Node(
                                        SYMBOL.dotted_name,
                                        [Name(old_name), Dot(), Name("setter")],
                                    ),
                                    Leaf(TOKEN.NEWLINE, "\n"),
                                ],
                            ),
                            Node(
                                SYMBOL.funcdef,
                                [
                                    Name("def", indent),
                                    Name(old_name, prefix=" "),
                                    Node(
                                        SYMBOL.parameters,
                                        [
                                            LParen(),
                                            Node(
                                                SYMBOL.typedargslist,
                                                [
                                                    Name("self"),
                                                    Comma(),
                                                    Name("value", prefix=" "),
                                                ],
                                            ),
                                            RParen(),
                                        ],
                                    ),
                                    Leaf(TOKEN.COLON, ":"),
                                    Node(
                                        SYMBOL.suite,
                                        [
                                            Newline(),
                                            Leaf(TOKEN.INDENT, indent + "    "),
                                            Node(
                                                SYMBOL.simple_stmt,
                                                [
                                                    Node(
                                                        SYMBOL.expr_stmt,
                                                        [
                                                            Node(
                                                                SYMBOL.power,
                                                                Attr(
                                                                    Name("self"),
                                                                    Name(new_name),
                                                                ),
                                                            ),
                                                            Leaf(
                                                                TOKEN.EQUAL,
                                                                "=",
                                                                prefix=" ",
                                                            ),
                                                            Name("value", prefix=" "),
                                                        ],
                                                    ),
                                                    Newline(),
                                                ],
                                            ),
                                            Leaf(TOKEN.DEDENT, "\n" + indent),
                                        ],
                                    ),
                                ],
                                prefix=indent,
                            ),
                        ],
                    )

                    suite.insert_child(-1, getter)
                    suite.insert_child(-1, setter)

                    prev = find_previous(getter, TOKEN.DEDENT, recursive=True)
                    curr = find_last(setter, TOKEN.DEDENT, recursive=True)
                    assert isinstance(prev, Leaf) and isinstance(curr, Leaf)
                    prev.prefix, curr.prefix = curr.prefix, prev.prefix
                    prev.value, curr.value = curr.value, prev.value
Esempio n. 26
0
    def transform(self, node, results):
        if not has_metaclass(node):
            return  # pragma: no cover

        fixup_parse_tree(node)

        # find metaclasses, keep the last one
        last_metaclass = None
        for suite, i, stmt in find_metas(node):
            last_metaclass = stmt
            stmt.remove()

        text_type = node.children[0].type  # always Leaf(nnn, 'class')

        # figure out what kind of classdef we have
        if len(node.children) == 7:
            # Node(classdef, ['class', 'name', '(', arglist, ')', ':', suite])
            #                 0        1       2    3        4    5    6
            if node.children[3].type == syms.arglist:
                arglist = node.children[3]
            # Node(classdef, ['class', 'name', '(', 'Parent', ')', ':', suite])
            else:
                parent = node.children[3].clone()
                arglist = Node(syms.arglist, [parent])
                node.set_child(3, arglist)
        elif len(node.children) == 6:
            # Node(classdef, ['class', 'name', '(',  ')', ':', suite])
            #                 0        1       2     3    4    5
            arglist = Node(syms.arglist, [])
            node.insert_child(3, arglist)
        elif len(node.children) == 4:
            # Node(classdef, ['class', 'name', ':', suite])
            #                 0        1       2    3
            arglist = Node(syms.arglist, [])
            node.insert_child(2, Leaf(token.RPAR, u')'))
            node.insert_child(2, arglist)
            node.insert_child(2, Leaf(token.LPAR, u'('))
        else:
            raise ValueError("Unexpected class definition")  # pragma: no cover

        touch_import(None, u'six', node)

        metaclass = last_metaclass.children[0].children[2].clone()
        metaclass.prefix = u''

        arguments = [metaclass]

        if arglist.children:
            bases = arglist.clone()
            bases.prefix = u' '
            arguments.extend([Comma(), bases])

        arglist.replace(
            Call(Name(u'six.with_metaclass', prefix=arglist.prefix),
                 arguments))

        fixup_indent(suite)

        # check for empty suite
        if not suite.children:
            # one-liner that was just __metaclass__
            suite.remove()
            pass_leaf = Leaf(text_type, u'pass')
            pass_leaf.prefix = last_metaclass.prefix
            node.append_child(pass_leaf)
            node.append_child(Leaf(token.NEWLINE, u'\n'))

        elif len(suite.children) > 1 and \
                 (suite.children[-2].type == token.INDENT and
                  suite.children[-1].type == token.DEDENT):
            # there was only one line in the class body and it was __metaclass__
            pass_leaf = Leaf(text_type, u'pass')
            suite.insert_child(-1, pass_leaf)
            suite.insert_child(-1, Leaf(token.NEWLINE, u'\n'))
def default_transformer(node: LN, capture: Capture, filename: Filename):
    fp = capture.get("function_parameters")
    if fp and fp.children[1].type == SYMBOL.arglist:
        arg_node = KeywordArg(Name("trans_arg"), Number("1"))
        fp.children[1].append_child(Comma())
        fp.children[1].append_child(arg_node)