# Path: doubles/patch.py
# class Patch(object):
#     def __init__(self, target):
#     def _capture_original_object(self):
#     def set_value(self, value):
#     def restore_original_object(self):
# 
# Path: doubles/class_double.py
# class ClassDouble(InstanceDouble):
#     """
#     A pure double representing the target class.
# 
#     ::
# 
#         User = ClassDouble('myapp.User')
# 
#     :param str path: The absolute module path to the class.
#     """
# 
#     is_class = True
# 
#     def __init__(self, path):
#         super(ClassDouble, self).__init__(path)
#         self._doubles_target = patch_class(self._doubles_target)
#         self._target = Target(self._doubles_target)
# 
#     def __call__(self, *args, **kwargs):
#         """Verify arguments and proxy to _doubles__new__
# 
#         :rtype obj:
#         :raises VerifyingDoubleArgumentError: If args/kwargs don't match the expected arguments of
#             __init__ of the underlying class.
#         """
#         verify_arguments(self._target, '_doubles__new__', args, kwargs)
#         return self._doubles__new__(*args, **kwargs)
# 
#     def _doubles__new__(self, *args, **kwargs):
#         """Raises an UnallowedMethodCallError
# 
#         NOTE: This method is here only to raise if it has not been stubbed
#         """
#         raise UnallowedMethodCallError('Cannot call __new__ on a ClassDouble without stubbing it')
# 
# 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/targets/allowance_target.py
# def allow_constructor(target):
#     """
#     Set an allowance on a ``ClassDouble`` constructor
# 
#     This allows the caller to control what a ClassDouble returns when a new instance is created.
# 
#     :param ClassDouble target:  The ClassDouble to set the allowance on.
#     :return: an ``Allowance`` for the __new__ method.
#     :raise: ``ConstructorDoubleError`` if target is not a ClassDouble.
#     """
#     if not isinstance(target, ClassDouble):
#         raise ConstructorDoubleError(
#             'Cannot allow_constructor of {} since it is not a ClassDouble.'.format(target),
#         )
# 
#     return allow(target)._doubles__new__
# 
# Path: doubles/targets/patch_target.py
# def patch_class(target):
#     """
#     Replace the specified class with a ClassDouble
# 
#     :param str target: A string pointing to the target to patch.
#     :param obj values: Values to return when new instances are created.
#     :return: A ``ClassDouble`` object.
#     """
#     class_double = ClassDouble(target)
#     patch(target, class_double)
#     return class_double
# 
# Path: doubles/exceptions.py
# class VerifyingDoubleImportError(AssertionError):
#     """
#     An exception raised when attempting to create a verifying double from an invalid module path.
#     """
# 
# 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/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


import pytest
import doubles.testing
from doubles import (
    patch,
    patch_class,
    InstanceDouble,
    ClassDouble,
    allow_constructor,
)
from doubles.exceptions import (
    VerifyingDoubleImportError,
    VerifyingDoubleError,
)
from doubles.lifecycle import teardown



class TestPatch(object):
    def test_patch_wth_new_object_supplied(self):
        patch('doubles.testing.User', 'Bob Barker')

        assert doubles.testing.User == 'Bob Barker'

    def test_restores_original_value(self):
        original_value = doubles.testing.User
        patch('doubles.testing.User', 'Bob Barker')

        teardown()

        assert original_value == doubles.testing.User

    def test_creating_instance_double_after_patching(self):
        patch('doubles.testing.User', InstanceDouble('doubles.testing.User'))


# Path: doubles/patch.py
# class Patch(object):
#     def __init__(self, target):
#     def _capture_original_object(self):
#     def set_value(self, value):
#     def restore_original_object(self):
# 
# Path: doubles/class_double.py
# class ClassDouble(InstanceDouble):
#     """
#     A pure double representing the target class.
# 
#     ::
# 
#         User = ClassDouble('myapp.User')
# 
#     :param str path: The absolute module path to the class.
#     """
# 
#     is_class = True
# 
#     def __init__(self, path):
#         super(ClassDouble, self).__init__(path)
#         self._doubles_target = patch_class(self._doubles_target)
#         self._target = Target(self._doubles_target)
# 
#     def __call__(self, *args, **kwargs):
#         """Verify arguments and proxy to _doubles__new__
# 
#         :rtype obj:
#         :raises VerifyingDoubleArgumentError: If args/kwargs don't match the expected arguments of
#             __init__ of the underlying class.
#         """
#         verify_arguments(self._target, '_doubles__new__', args, kwargs)
#         return self._doubles__new__(*args, **kwargs)
# 
#     def _doubles__new__(self, *args, **kwargs):
#         """Raises an UnallowedMethodCallError
# 
#         NOTE: This method is here only to raise if it has not been stubbed
#         """
#         raise UnallowedMethodCallError('Cannot call __new__ on a ClassDouble without stubbing it')
# 
# 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/targets/allowance_target.py
# def allow_constructor(target):
#     """
#     Set an allowance on a ``ClassDouble`` constructor
# 
#     This allows the caller to control what a ClassDouble returns when a new instance is created.
# 
#     :param ClassDouble target:  The ClassDouble to set the allowance on.
#     :return: an ``Allowance`` for the __new__ method.
#     :raise: ``ConstructorDoubleError`` if target is not a ClassDouble.
#     """
#     if not isinstance(target, ClassDouble):
#         raise ConstructorDoubleError(
#             'Cannot allow_constructor of {} since it is not a ClassDouble.'.format(target),
#         )
# 
#     return allow(target)._doubles__new__
# 
# Path: doubles/targets/patch_target.py
# def patch_class(target):
#     """
#     Replace the specified class with a ClassDouble
# 
#     :param str target: A string pointing to the target to patch.
#     :param obj values: Values to return when new instances are created.
#     :return: A ``ClassDouble`` object.
#     """
#     class_double = ClassDouble(target)
#     patch(target, class_double)
#     return class_double
# 
# Path: doubles/exceptions.py
# class VerifyingDoubleImportError(AssertionError):
#     """
#     An exception raised when attempting to create a verifying double from an invalid module path.
#     """
# 
# 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/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: test/patch_test.py
import pytest
import doubles.testing
from doubles import (
    patch,
    patch_class,
    InstanceDouble,
    ClassDouble,
    allow_constructor,
)
from doubles.exceptions import (
    VerifyingDoubleImportError,
    VerifyingDoubleError,
)
from doubles.lifecycle import teardown




class TestPatch(object):
    def test_patch_wth_new_object_supplied(self):
        patch('doubles.testing.User', 'Bob Barker')

        assert doubles.testing.User == 'Bob Barker'

    def test_restores_original_value(self):
        original_value = doubles.testing.User
        patch('doubles.testing.User', 'Bob Barker')

        teardown()

        assert original_value == doubles.testing.User

    def test_creating_instance_double_after_patching(self):
        patch('doubles.testing.User', InstanceDouble('doubles.testing.User'))


        assert InstanceDouble('doubles.testing.User')