# 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,
)
    :param dict kwargs: The keyword arguments the method should be called with.
    :raise: ``VerifyingDoubleError`` if the provided arguments do not match the signature.
    """

    if method_name == '_doubles__new__':
        return _verify_arguments_of_doubles__new__(target, args, kwargs)

    attr = target.get_attr(method_name)
    method = attr.object

    if attr.kind in ('data', 'attribute', 'toplevel', 'class method', 'static method'):
        try:
            method = method.__get__(None, attr.defining_class)
        except AttributeError:
            method = method.__call__
    elif attr.kind == 'property':
        if args or kwargs:
            raise VerifyingDoubleArgumentError("Properties do not accept arguments.")
        return
    else:
        args = ['self_or_cls'] + list(args)

    _verify_arguments(method, method_name, args, kwargs)


def _verify_arguments(method, method_name, args, kwargs):
    try:
        getcallargs(method, *args, **kwargs)
    except TypeError as e:
        if not _is_python_function(method):

# 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,
)

    :param dict kwargs: The keyword arguments the method should be called with.
    :raise: ``VerifyingDoubleError`` if the provided arguments do not match the signature.
    """

    if method_name == '_doubles__new__':
        return _verify_arguments_of_doubles__new__(target, args, kwargs)

    attr = target.get_attr(method_name)
    method = attr.object

    if attr.kind in ('data', 'attribute', 'toplevel', 'class method', 'static method'):
        try:
            method = method.__get__(None, attr.defining_class)
        except AttributeError:
            method = method.__call__
    elif attr.kind == 'property':
        if args or kwargs:
            raise VerifyingDoubleArgumentError("Properties do not accept arguments.")
        return
    else:
        args = ['self_or_cls'] + list(args)

    _verify_arguments(method, method_name, args, kwargs)


def _verify_arguments(method, method_name, args, kwargs):
    try:
        getcallargs(method, *args, **kwargs)
    except TypeError as e:
        if not _is_python_function(method):

            raise VerifyingBuiltinDoubleArgumentError(str(e))