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)
        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)
Beispiel #3
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"))
        )
Beispiel #4
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,
        )
    )
Beispiel #5
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))
Beispiel #6
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)
Beispiel #7
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)
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)
Beispiel #9
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