# Django 1.8.18.dev20170123152445 documentation

# Source code for django.utils.decorators

    "Functions that help with dynamically creating decorators for views."

    try:
        from contextlib import ContextDecorator
    except ImportError:
        ContextDecorator = None

    from functools import WRAPPER_ASSIGNMENTS, update_wrapper, wraps

    from django.utils import six

    class classonlymethod(classmethod):
        def __get__(self, instance, owner):
            if instance is not None:
                raise AttributeError("This method is available only on the class, not on instances.")
            return super(classonlymethod, self).__get__(instance, owner)

    def method_decorator(decorator):
        """
        Converts a function decorator into a method decorator
        """
        # 'func' is a function at the time it is passed to _dec, but will eventually
        # be a method of the class it is defined on.
        def _dec(func):
            def _wrapper(self, *args, **kwargs):
                @decorator
                def bound_func(*args2, **kwargs2):
                    return func.__get__(self, type(self))(*args2, **kwargs2)
                # bound_func has the signature that 'decorator' expects i.e.  no
                # 'self' argument, but it is a closure over self so it can call
                # 'func' correctly.
                return bound_func(*args, **kwargs)
            # In case 'decorator' adds attributes to the function it decorates, we
            # want to copy those. We don't have access to bound_func in this scope,
            # but we can cheat by using it on a dummy function.

            @decorator
            def dummy(*args, **kwargs):
                pass
            update_wrapper(_wrapper, dummy)
            # Need to preserve any existing attributes of 'func', including the name.
            update_wrapper(_wrapper, func)

            return _wrapper

        update_wrapper(_dec, decorator, assigned=available_attrs(decorator))
        # Change the name to aid debugging.
        if hasattr(decorator, '__name__'):
            _dec.__name__ = 'method_decorator(%s)' % decorator.__name__
        else:
            _dec.__name__ = 'method_decorator(%s)' % decorator.__class__.__name__
        return _dec

    def decorator_from_middleware_with_args(middleware_class):
        """
        Like decorator_from_middleware, but returns a function
        that accepts the arguments to be passed to the middleware_class.
        Use like::

             cache_page = decorator_from_middleware_with_args(CacheMiddleware)
             # ...

             @cache_page(3600)
             def my_view(request):
                 # ...
        """
        return make_middleware_decorator(middleware_class)

    def decorator_from_middleware(middleware_class):
        """
        Given a middleware class (not an instance), returns a view decorator. This
        lets you use middleware functionality on a per-view basis. The middleware
        is created with no params passed.
        """
        return make_middleware_decorator(middleware_class)()

    def available_attrs(fn):
        """
        Return the list of functools-wrappable attributes on a callable.
        This is required as a workaround for http://bugs.python.org/issue3445
        under Python 2.
        """
        if six.PY3:
            return WRAPPER_ASSIGNMENTS
        else:
            return tuple(a for a in WRAPPER_ASSIGNMENTS if hasattr(fn, a))

    def make_middleware_decorator(middleware_class):
        def _make_decorator(*m_args, **m_kwargs):
            middleware = middleware_class(*m_args, **m_kwargs)

            def _decorator(view_func):
                @wraps(view_func, assigned=available_attrs(view_func))
                def _wrapped_view(request, *args, **kwargs):
                    if hasattr(middleware, 'process_request'):
                        result = middleware.process_request(request)
                        if result is not None:
                            return result
                    if hasattr(middleware, 'process_view'):
                        result = middleware.process_view(request, view_func, args, kwargs)
                        if result is not None:
                            return result
                    try:
                        response = view_func(request, *args, **kwargs)
                    except Exception as e:
                        if hasattr(middleware, 'process_exception'):
                            result = middleware.process_exception(request, e)
                            if result is not None:
                                return result
                        raise
                    if hasattr(response, 'render') and callable(response.render):
                        if hasattr(middleware, 'process_template_response'):
                            response = middleware.process_template_response(request, response)
                        # Defer running of process_response until after the template
                        # has been rendered:
                        if hasattr(middleware, 'process_response'):
                            callback = lambda response: middleware.process_response(request, response)
                            response.add_post_render_callback(callback)
                    else:
                        if hasattr(middleware, 'process_response'):
                            return middleware.process_response(request, response)
                    return response
                return _wrapped_view
            return _decorator
        return _make_decorator

    if ContextDecorator is None:
        # ContextDecorator was introduced in Python 3.2
        # See https://docs.python.org/3/library/contextlib.html#contextlib.ContextDecorator
        class ContextDecorator(object):
            """
            A base class that enables a context manager to also be used as a decorator.
            """
            def __call__(self, func):
                @wraps(func, assigned=available_attrs(func))
                def inner(*args, **kwargs):
                    with self:
                        return func(*args, **kwargs)
                return inner