# Buggy code
def evaluate_call(call, parent, ignore_nodes=None):
    secure = False
    evaluate = False
    if isinstance(call, ast.Call) and isinstance(call.func, ast.Attribute):
        if isinstance(call.func.value, ast.Str) and call.func.attr == "format":
            evaluate = True
            if call.keywords or call.kwargs:
                evaluate = False  # TODO(??) get support for this

    if evaluate:
        args = list(call.args)
        if call.starargs and isinstance(call.starargs, (ast.List, ast.Tuple)):
            args.extend(call.starargs.elts)

        num_secure = 0
        for arg in args:
            if isinstance(arg, ast.Str):
                num_secure += 1
            elif isinstance(arg, ast.Name):
                if evaluate_var(arg, parent, call.lineno, ignore_nodes):
                    num_secure += 1
                else:
                    break
            elif isinstance(arg, ast.Call):
                if evaluate_call(arg, parent, ignore_nodes):
                    num_secure += 1
                else:
                    break
            else:
                break
        secure = num_secure == len(args)

    return secure


# Traceback (AttributeError)
Bandit internal error running: django_mark_safe on file /home/travis/build/PyCQA/bandit/examples/mark_safe_secure.py at line 33: 'Call' object has no attribute 'kwargs'Traceback (most recent call last):
File "/home/travis/build/PyCQA/bandit/bandit/core/tester.py", line 64, in run_tests
result = test(context)
File "/home/travis/build/PyCQA/bandit/bandit/plugins/django_xss.py", line 279, in django_mark_safe
return check_risk(context.node)
File "/home/travis/build/PyCQA/bandit/bandit/plugins/django_xss.py", line 232, in check_risk
secure = evaluate_call(xss_var, parent)
File "/home/travis/build/PyCQA/bandit/bandit/plugins/django_xss.py", line 154, in evaluate_call
if call.keywords or call.kwargs:
AttributeError: 'Call' object has no attribute 'kwargs'

# Fixed code
def evaluate_call(call, parent, ignore_nodes=None):
    secure = False
    evaluate = False
    if isinstance(call, ast.Call) and isinstance(call.func, ast.Attribute):
        if isinstance(call.func.value, ast.Str) and call.func.attr == "format":
            evaluate = True
            if call.keywords or (six.PY2 and call.kwargs):
                evaluate = False  # TODO(??) get support for this

    if evaluate:
        args = list(call.args)
        if (
            six.PY2
            and call.starargs
            and isinstance(call.starargs, (ast.List, ast.Tuple))
        ):
            args.extend(call.starargs.elts)

        num_secure = 0
        for arg in args:
            if isinstance(arg, ast.Str):
                num_secure += 1
            elif isinstance(arg, ast.Name):
                if evaluate_var(arg, parent, call.lineno, ignore_nodes):
                    num_secure += 1
                else:
                    break
            elif isinstance(arg, ast.Call):
                if evaluate_call(arg, parent, ignore_nodes):
                    num_secure += 1
                else:
                    break
            elif (
                not six.PY2
                and isinstance(arg, ast.Starred)
                and isinstance(arg.value, (ast.List, ast.Tuple))
            ):
                args.extend(arg.value.elts)
                num_secure += 1
            else:
                break
        secure = num_secure == len(args)

    return secure