# Path: doubles/exceptions.py
# class UnallowedMethodCallError(AssertionError):
#     """An exception raised when an unallowed method call is made on a double."""
# 
#     pass
# 
# class MockExpectationError(AssertionError):
#     """An exception raised when a mock fails verification."""
# 
#     pass
# 
# 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
# 
# Path: doubles/instance_double.py
# class InstanceDouble(ObjectDouble):
#     """A pure double representing an instance of the target class.
# 
#     Any kwargs supplied will be set as attributes on the instance that is
#     created.
# 
#     ::
# 
#         user = InstanceDouble('myapp.User', name='Bob Barker')
# 
#     :param str path: The absolute module path to the class.
#     """
# 
#     def __init__(self, path, **kwargs):
#         module_path, class_name = get_path_components(path)
#         module = get_module(module_path, path)
#         self._doubles_target = _get_doubles_target(module, class_name, path)
#         for k, v in kwargs.items():
#             setattr(self, k, v)
# 
# Path: doubles/lifecycle.py
# @contextmanager
# def no_builtin_verification():
#     """Turn off validation for builtin methods
# 
#     While inside this context we will ignore errors raised while verifying the
#     arguments of builtins.
# 
#     Note: It is impossible to verify the expected arguments of built in functions
#     """
#     current_space().skip_builtin_verification = True
#     yield
#     current_space().skip_builtin_verification = False
# 
# Path: doubles/targets/allowance_target.py
# def allow(target):
#     """
#     Prepares a target object for a method call allowance (stub). The name of the method to allow
#     should be called as a method on the return value of this function::
# 
#         allow(foo).bar
# 
#     Accessing the ``bar`` attribute will return an ``Allowance`` which provides additional methods
#     to configure the stub.
# 
#     :param object target: The object that will be stubbed.
#     :return: An ``AllowanceTarget`` for the target object.
#     """
# 
#     return AllowanceTarget(target)
# 
# Path: doubles/lifecycle.py
# def teardown():
#     """Tears down the current Doubles environment. Must be called after each test case."""
#     if hasattr(_thread_local_data, 'current_space'):
#         _thread_local_data.current_space.teardown()
#         del _thread_local_data.current_space
# 
# Path: doubles/testing.py
# class AlwaysEquals(object):
#     def __eq__(self, other):
#         return True
# 
# class NeverEquals(object):
#     def __eq__(self, other):
#         return False


import inspect
import re
import sys
import pytest
from pytest import raises
from doubles.exceptions import (
    UnallowedMethodCallError,
    MockExpectationError,
    VerifyingDoubleArgumentError
)
from doubles.instance_double import InstanceDouble
from doubles import allow, no_builtin_verification
from doubles.lifecycle import teardown
from doubles.testing import AlwaysEquals, NeverEquals
class UserDefinedException(Exception):
    pass


class TestBasicAllowance(object):
    def test_allows_method_calls_on_doubles(self):
        subject = InstanceDouble('doubles.testing.User')

        allow(subject).instance_method

        assert subject.instance_method() is None

    def test_raises_on_undefined_attribute_access(self):
        subject = InstanceDouble('doubles.testing.User')

        with raises(AttributeError):
            subject.instance_method

    def test_raises_if_called_with_args_that_do_not_match_signature(self):
        subject = InstanceDouble('doubles.testing.User')
        allow(subject).instance_method

        with raises(VerifyingDoubleArgumentError):
            subject.instance_method('bar')

    def test_skip_builtin_verification_does_not_affect_non_builtins(self):
        with no_builtin_verification():
            subject = InstanceDouble('doubles.testing.User')
            allow(subject).instance_method


# Path: doubles/exceptions.py
# class UnallowedMethodCallError(AssertionError):
#     """An exception raised when an unallowed method call is made on a double."""
# 
#     pass
# 
# class MockExpectationError(AssertionError):
#     """An exception raised when a mock fails verification."""
# 
#     pass
# 
# 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
# 
# Path: doubles/instance_double.py
# class InstanceDouble(ObjectDouble):
#     """A pure double representing an instance of the target class.
# 
#     Any kwargs supplied will be set as attributes on the instance that is
#     created.
# 
#     ::
# 
#         user = InstanceDouble('myapp.User', name='Bob Barker')
# 
#     :param str path: The absolute module path to the class.
#     """
# 
#     def __init__(self, path, **kwargs):
#         module_path, class_name = get_path_components(path)
#         module = get_module(module_path, path)
#         self._doubles_target = _get_doubles_target(module, class_name, path)
#         for k, v in kwargs.items():
#             setattr(self, k, v)
# 
# Path: doubles/lifecycle.py
# @contextmanager
# def no_builtin_verification():
#     """Turn off validation for builtin methods
# 
#     While inside this context we will ignore errors raised while verifying the
#     arguments of builtins.
# 
#     Note: It is impossible to verify the expected arguments of built in functions
#     """
#     current_space().skip_builtin_verification = True
#     yield
#     current_space().skip_builtin_verification = False
# 
# Path: doubles/targets/allowance_target.py
# def allow(target):
#     """
#     Prepares a target object for a method call allowance (stub). The name of the method to allow
#     should be called as a method on the return value of this function::
# 
#         allow(foo).bar
# 
#     Accessing the ``bar`` attribute will return an ``Allowance`` which provides additional methods
#     to configure the stub.
# 
#     :param object target: The object that will be stubbed.
#     :return: An ``AllowanceTarget`` for the target object.
#     """
# 
#     return AllowanceTarget(target)
# 
# Path: doubles/lifecycle.py
# def teardown():
#     """Tears down the current Doubles environment. Must be called after each test case."""
#     if hasattr(_thread_local_data, 'current_space'):
#         _thread_local_data.current_space.teardown()
#         del _thread_local_data.current_space
# 
# Path: doubles/testing.py
# class AlwaysEquals(object):
#     def __eq__(self, other):
#         return True
# 
# class NeverEquals(object):
#     def __eq__(self, other):
#         return False


# Path: test/allow_test.py
import inspect
import re
import sys
import pytest
from pytest import raises
from doubles.exceptions import (
    UnallowedMethodCallError,
    MockExpectationError,
    VerifyingDoubleArgumentError
)
from doubles.instance_double import InstanceDouble
from doubles import allow, no_builtin_verification
from doubles.lifecycle import teardown
from doubles.testing import AlwaysEquals, NeverEquals

class UserDefinedException(Exception):
    pass


class TestBasicAllowance(object):
    def test_allows_method_calls_on_doubles(self):
        subject = InstanceDouble('doubles.testing.User')

        allow(subject).instance_method

        assert subject.instance_method() is None

    def test_raises_on_undefined_attribute_access(self):
        subject = InstanceDouble('doubles.testing.User')

        with raises(AttributeError):
            subject.instance_method

    def test_raises_if_called_with_args_that_do_not_match_signature(self):
        subject = InstanceDouble('doubles.testing.User')
        allow(subject).instance_method

        with raises(VerifyingDoubleArgumentError):
            subject.instance_method('bar')

    def test_skip_builtin_verification_does_not_affect_non_builtins(self):
        with no_builtin_verification():
            subject = InstanceDouble('doubles.testing.User')
            allow(subject).instance_method


            with raises(VerifyingDoubleArgumentError):