# Path: doubles/exceptions.py
# class VerifyingDoubleArgumentError(AssertionError):
#     """
#     An exception raised when attempting to double a method with arguments that do not match the
#     signature of the real method.
#     """
# 
#     pass
# 
# class VerifyingBuiltinDoubleArgumentError(VerifyingDoubleArgumentError):
#     """
#     An exception raised when attempting to validate arguments of a builtin.
#     """
# 
#     pass
# 
# class VerifyingDoubleError(AssertionError):
#     """
#     An exception raised when attempting to double a method that does not exist on the real object.
#     """
# 
#     def __init__(self, method_name, doubled_obj):
#         """
#         :param str method_name: The name of the method to double.
#         :param object doubled_obj: The real object being doubled.
#         """
# 
#         self._method_name = method_name
#         self._doubled_obj = doubled_obj
#         self.args = (method_name, doubled_obj)
#         self.message = "Cannot double method '{}' of '{}'."
# 
#     def no_matching_method(self):
#         self.message = "Cannot double method '{}' because {} does not implement it."
# 
#         return self
# 
#     def not_callable(self):
#         self.message = "Cannot double method '{}' because it is not a callable attribute on {}."
# 
#         return self
# 
#     def requires_instance(self):
#         self.message = "Cannot double method '{}' because it is not callable directly on {}."
# 
#         return self
# 
#     def __str__(self):
#         return self.message.format(self._method_name, self._doubled_obj)


import sys
from inspect import isbuiltin, getcallargs, isfunction, ismethod
from doubles.exceptions import (
    VerifyingDoubleArgumentError,
    VerifyingBuiltinDoubleArgumentError,
    VerifyingDoubleError,
)
        ['self'] + list(args),
        kwargs,
    )


def _raise_doubles_error_from_index_error(method_name):
    # Work Around for http://bugs.python.org/issue20817
    raise VerifyingDoubleArgumentError(
        "{method}() missing 3 or more arguments.".format(method=method_name)
    )


def verify_method(target, method_name, class_level=False):
    """Verifies that the provided method exists on the target object.

    :param Target target: A ``Target`` object containing the object with the method to double.
    :param str method_name: The name of the method to double.
    :raise: ``VerifyingDoubleError`` if the attribute doesn't exist, if it's not a callable object,
        and in the case where the target is a class, that the attribute isn't an instance method.
    """

    attr = target.get_attr(method_name)

    if not attr:
        raise VerifyingDoubleError(method_name, target.doubled_obj).no_matching_method()

    if attr.kind == 'data' and not isbuiltin(attr.object) and not is_callable(attr.object):
        raise VerifyingDoubleError(method_name, target.doubled_obj).not_callable()

    if class_level and attr.kind == 'method' and method_name != '__new__':

# Path: doubles/exceptions.py
# class VerifyingDoubleArgumentError(AssertionError):
#     """
#     An exception raised when attempting to double a method with arguments that do not match the
#     signature of the real method.
#     """
# 
#     pass
# 
# class VerifyingBuiltinDoubleArgumentError(VerifyingDoubleArgumentError):
#     """
#     An exception raised when attempting to validate arguments of a builtin.
#     """
# 
#     pass
# 
# class VerifyingDoubleError(AssertionError):
#     """
#     An exception raised when attempting to double a method that does not exist on the real object.
#     """
# 
#     def __init__(self, method_name, doubled_obj):
#         """
#         :param str method_name: The name of the method to double.
#         :param object doubled_obj: The real object being doubled.
#         """
# 
#         self._method_name = method_name
#         self._doubled_obj = doubled_obj
#         self.args = (method_name, doubled_obj)
#         self.message = "Cannot double method '{}' of '{}'."
# 
#     def no_matching_method(self):
#         self.message = "Cannot double method '{}' because {} does not implement it."
# 
#         return self
# 
#     def not_callable(self):
#         self.message = "Cannot double method '{}' because it is not a callable attribute on {}."
# 
#         return self
# 
#     def requires_instance(self):
#         self.message = "Cannot double method '{}' because it is not callable directly on {}."
# 
#         return self
# 
#     def __str__(self):
#         return self.message.format(self._method_name, self._doubled_obj)


# Path: doubles/verification.py
import sys
from inspect import isbuiltin, getcallargs, isfunction, ismethod
from doubles.exceptions import (
    VerifyingDoubleArgumentError,
    VerifyingBuiltinDoubleArgumentError,
    VerifyingDoubleError,
)

        ['self'] + list(args),
        kwargs,
    )


def _raise_doubles_error_from_index_error(method_name):
    # Work Around for http://bugs.python.org/issue20817
    raise VerifyingDoubleArgumentError(
        "{method}() missing 3 or more arguments.".format(method=method_name)
    )


def verify_method(target, method_name, class_level=False):
    """Verifies that the provided method exists on the target object.

    :param Target target: A ``Target`` object containing the object with the method to double.
    :param str method_name: The name of the method to double.
    :raise: ``VerifyingDoubleError`` if the attribute doesn't exist, if it's not a callable object,
        and in the case where the target is a class, that the attribute isn't an instance method.
    """

    attr = target.get_attr(method_name)

    if not attr:
        raise VerifyingDoubleError(method_name, target.doubled_obj).no_matching_method()

    if attr.kind == 'data' and not isbuiltin(attr.object) and not is_callable(attr.object):
        raise VerifyingDoubleError(method_name, target.doubled_obj).not_callable()

    if class_level and attr.kind == 'method' and method_name != '__new__':

        raise VerifyingDoubleError(method_name, target.doubled_obj).requires_instance()