# Path: django_performance_testing/utils.py
# def wrap_cls_method_in_ctx_manager(cls, method_name, ctx_manager,
#                                    is_cls_method):
#     target_method = getattr(cls, method_name)
#     has_been_patched_flag = 'djpt_patched'
#     if hasattr(target_method, has_been_patched_flag):
#         return
#     if is_cls_method:
#         # as classmethod must be outermost decorator
#         target_method = target_method.__func__
#     wrapped_method = with_context_manager(ctx_manager)(target_method)
#     if is_cls_method:
#         # as classmethod must be outermost decorator
#         wrapped_method = classmethod(wrapped_method)
#     setattr(cls, method_name, wrapped_method)
#     target_method = getattr(cls, method_name)
#     assert hasattr(target_method, has_been_patched_flag), (cls, target_method)
# 
# class multi_context_manager(object):
# 
#     def __init__(self, managers, debug=False):
#         if not managers:
#             raise ValueError('Expected at least one manager, got 0 as arg')
#         self.head_manager = managers[0]
#         self.tail_managers = managers[1:]
#         if self.tail_managers:
#             self.next_ = multi_context_manager(self.tail_managers)
#         else:
#             self.next_ = None
#         self.debug = debug
# 
#     def _print(self, action):
#         if self.debug:
#             id_ = getattr(self.head_manager, 'id_', None)
#             print('{} {} {}'.format(action, type(self.head_manager), id_))
# 
#     def __enter__(self):
#         self._print('entering....')
#         self.head_manager.__enter__()
#         if self.next_:
#             try:
#                 self.next_.__enter__()
#             except:  # noqa: E722
#                 self._print('exiting...')
#                 self.head_manager.__exit__(*sys.exc_info())
#                 self._print('... exited')
#                 raise
#         self._print('... entered')
# 
#     def __exit__(self, exc_type, exc_val, exc_tb):
#         try:
#             if self.next_:
#                 self.next_.__exit__(exc_type, exc_val, exc_tb)
#         finally:
#             self._print('exiting...')
#             self.head_manager.__exit__(exc_type, exc_val, exc_tb)
#             self._print('... exited')


from django_performance_testing.utils import \
    wrap_cls_method_in_ctx_manager, multi_context_manager
import pytest
    wrapper(f, 'foo', context_manager=None, is_cls_method=False)
    assert hasattr(f.foo, 'returns')  # after wrapping
    assert 'str' == getattr(f.foo, 'returns')  # after wrapping


def test_wrapper_can_be_applied_to_classmethods(wrapper):

    class Foo(object):
        has_been_called = False

        @classmethod
        def some_classmethod(cls, some_arg):
            assert cls == Foo
            assert some_arg == 'hello'
            cls.has_been_called = True

    ctx = ControllableContextManager()
    wrapper(Foo, 'some_classmethod', context_manager=ctx, is_cls_method=True)
    assert ctx.before_call_count == 0
    assert ctx.after_call_count == 0
    Foo.some_classmethod('hello')
    assert ctx.before_call_count == 1
    assert ctx.after_call_count == 1
    assert Foo.has_been_called


class TestMultiContextManager(object):

    def test_cant_construct_it_without_a_managers(self):
        with pytest.raises(ValueError):

# Path: django_performance_testing/utils.py
# def wrap_cls_method_in_ctx_manager(cls, method_name, ctx_manager,
#                                    is_cls_method):
#     target_method = getattr(cls, method_name)
#     has_been_patched_flag = 'djpt_patched'
#     if hasattr(target_method, has_been_patched_flag):
#         return
#     if is_cls_method:
#         # as classmethod must be outermost decorator
#         target_method = target_method.__func__
#     wrapped_method = with_context_manager(ctx_manager)(target_method)
#     if is_cls_method:
#         # as classmethod must be outermost decorator
#         wrapped_method = classmethod(wrapped_method)
#     setattr(cls, method_name, wrapped_method)
#     target_method = getattr(cls, method_name)
#     assert hasattr(target_method, has_been_patched_flag), (cls, target_method)
# 
# class multi_context_manager(object):
# 
#     def __init__(self, managers, debug=False):
#         if not managers:
#             raise ValueError('Expected at least one manager, got 0 as arg')
#         self.head_manager = managers[0]
#         self.tail_managers = managers[1:]
#         if self.tail_managers:
#             self.next_ = multi_context_manager(self.tail_managers)
#         else:
#             self.next_ = None
#         self.debug = debug
# 
#     def _print(self, action):
#         if self.debug:
#             id_ = getattr(self.head_manager, 'id_', None)
#             print('{} {} {}'.format(action, type(self.head_manager), id_))
# 
#     def __enter__(self):
#         self._print('entering....')
#         self.head_manager.__enter__()
#         if self.next_:
#             try:
#                 self.next_.__enter__()
#             except:  # noqa: E722
#                 self._print('exiting...')
#                 self.head_manager.__exit__(*sys.exc_info())
#                 self._print('... exited')
#                 raise
#         self._print('... entered')
# 
#     def __exit__(self, exc_type, exc_val, exc_tb):
#         try:
#             if self.next_:
#                 self.next_.__exit__(exc_type, exc_val, exc_tb)
#         finally:
#             self._print('exiting...')
#             self.head_manager.__exit__(exc_type, exc_val, exc_tb)
#             self._print('... exited')


# Path: tests/testapp/tests/test_wrapper.py
from django_performance_testing.utils import \
    wrap_cls_method_in_ctx_manager, multi_context_manager
import pytest

    wrapper(f, 'foo', context_manager=None, is_cls_method=False)
    assert hasattr(f.foo, 'returns')  # after wrapping
    assert 'str' == getattr(f.foo, 'returns')  # after wrapping


def test_wrapper_can_be_applied_to_classmethods(wrapper):

    class Foo(object):
        has_been_called = False

        @classmethod
        def some_classmethod(cls, some_arg):
            assert cls == Foo
            assert some_arg == 'hello'
            cls.has_been_called = True

    ctx = ControllableContextManager()
    wrapper(Foo, 'some_classmethod', context_manager=ctx, is_cls_method=True)
    assert ctx.before_call_count == 0
    assert ctx.after_call_count == 0
    Foo.some_classmethod('hello')
    assert ctx.before_call_count == 1
    assert ctx.after_call_count == 1
    assert Foo.has_been_called


class TestMultiContextManager(object):

    def test_cant_construct_it_without_a_managers(self):
        with pytest.raises(ValueError):

            multi_context_manager([])