middleware that is deliberately neither sync or async synccapable false asynccapable false def callself request return self getresponserequest middleware that is deliberately neither sync or async
from asgiref.sync import iscoroutinefunction, markcoroutinefunction

from django.http import Http404, HttpResponse
from django.template import engines
from django.template.response import TemplateResponse
from django.utils.decorators import (
    async_only_middleware,
    sync_and_async_middleware,
    sync_only_middleware,
)

log = []


class BaseMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        if iscoroutinefunction(self.get_response):
            markcoroutinefunction(self)

    def __call__(self, request):
        return self.get_response(request)


class ProcessExceptionMiddleware(BaseMiddleware):
    def process_exception(self, request, exception):
        return HttpResponse("Exception caught")


@async_only_middleware
class AsyncProcessExceptionMiddleware(BaseMiddleware):
    async def process_exception(self, request, exception):
        return HttpResponse("Exception caught")


class ProcessExceptionLogMiddleware(BaseMiddleware):
    def process_exception(self, request, exception):
        log.append("process-exception")


class ProcessExceptionExcMiddleware(BaseMiddleware):
    def process_exception(self, request, exception):
        raise Exception("from process-exception")


class ProcessViewMiddleware(BaseMiddleware):
    def process_view(self, request, view_func, view_args, view_kwargs):
        return HttpResponse("Processed view %s" % view_func.__name__)


@async_only_middleware
class AsyncProcessViewMiddleware(BaseMiddleware):
    async def process_view(self, request, view_func, view_args, view_kwargs):
        return HttpResponse("Processed view %s" % view_func.__name__)


class ProcessViewNoneMiddleware(BaseMiddleware):
    def process_view(self, request, view_func, view_args, view_kwargs):
        log.append("processed view %s" % view_func.__name__)
        return None


class ProcessViewTemplateResponseMiddleware(BaseMiddleware):
    def process_view(self, request, view_func, view_args, view_kwargs):
        template = engines["django"].from_string(
            "Processed view {{ view }}{% for m in mw %}\n{{ m }}{% endfor %}"
        )
        return TemplateResponse(
            request,
            template,
            {"mw": [self.__class__.__name__], "view": view_func.__name__},
        )


class TemplateResponseMiddleware(BaseMiddleware):
    def process_template_response(self, request, response):
        response.context_data["mw"].append(self.__class__.__name__)
        return response


@async_only_middleware
class AsyncTemplateResponseMiddleware(BaseMiddleware):
    async def process_template_response(self, request, response):
        response.context_data["mw"].append(self.__class__.__name__)
        return response


class LogMiddleware(BaseMiddleware):
    def __call__(self, request):
        response = self.get_response(request)
        log.append((response.status_code, response.content))
        return response


class NoTemplateResponseMiddleware(BaseMiddleware):
    def process_template_response(self, request, response):
        return None


@async_only_middleware
class AsyncNoTemplateResponseMiddleware(BaseMiddleware):
    async def process_template_response(self, request, response):
        return None


class NotFoundMiddleware(BaseMiddleware):
    def __call__(self, request):
        raise Http404("not found")


class PaymentMiddleware(BaseMiddleware):
    def __call__(self, request):
        response = self.get_response(request)
        response.status_code = 402
        return response


@async_only_middleware
def async_payment_middleware(get_response):
    async def middleware(request):
        response = await get_response(request)
        response.status_code = 402
        return response

    return middleware


@sync_and_async_middleware
class SyncAndAsyncMiddleware(BaseMiddleware):
    pass


@sync_only_middleware
class DecoratedPaymentMiddleware(PaymentMiddleware):
    pass


class NotSyncOrAsyncMiddleware(BaseMiddleware):
    

    sync_capable = False
    async_capable = False

    def __call__(self, request):
        return self.get_response(request)