# 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
        cls.events_in_order = []
        cls.counter = 0

    def __init__(self, fail_in_method=None):
        self.counter = type(self).counter
        type(self).counter += 1
        self.before_call_count = 0
        self.after_call_count = 0
        self.fail_in_method = fail_in_method

    def __enter__(self):
        self.before_call_count += 1
        self.handle_method_was_called('__enter__')
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.after_call_count += 1
        self.handle_method_was_called('__exit__')

    def handle_method_was_called(self, current_method_name):
        self.events_in_order.append((self, current_method_name))
        if self.fail_in_method == current_method_name:
            raise self.TestException('as requested, failing')

    def __repr__(self):
        return str(self.counter)


def wrap_via_cls_methods(cls_to_wrap, method_to_wrap_name,
                         context_manager, is_cls_method):

# 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

        cls.events_in_order = []
        cls.counter = 0

    def __init__(self, fail_in_method=None):
        self.counter = type(self).counter
        type(self).counter += 1
        self.before_call_count = 0
        self.after_call_count = 0
        self.fail_in_method = fail_in_method

    def __enter__(self):
        self.before_call_count += 1
        self.handle_method_was_called('__enter__')
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.after_call_count += 1
        self.handle_method_was_called('__exit__')

    def handle_method_was_called(self, current_method_name):
        self.events_in_order.append((self, current_method_name))
        if self.fail_in_method == current_method_name:
            raise self.TestException('as requested, failing')

    def __repr__(self):
        return str(self.counter)


def wrap_via_cls_methods(cls_to_wrap, method_to_wrap_name,
                         context_manager, is_cls_method):

    wrap_cls_method_in_ctx_manager(