<commit_before>from __future__ import unicode_literals

from django.conf import settings
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render
from django.utils.deprecation import MiddlewareMixin
from django.utils.encoding import force_text
from django.utils.text import camel_case_to_spaces
from django.utils.translation import ugettext_lazy as _
from safespace.settings import get_exception_classes


class SafespaceMiddleware(MiddlewareMixin):
    """The main safespace middleware."""

    def process_exception(self, request, exception):
        """
        Possibly process an exception. This is a Django middleware hook.

        :param request: Django request that caused the exception
        :type request: django.http.HttpRequest
        :param exception: The exception that occurred
        :type exception: Exception
        :return: Response, maybe
        :rtype: django.http.HttpResponse|None
        """

        if self.should_handle_exception(request, exception):
            return self.respond_to_exception(request, exception)

    def should_handle_exception(self, request, exception):
        """
        Return true if Safespace should handle the exception.
        :param request: Django request that caused the exception
        :type request: django.http.HttpRequest
        :param exception: The exception that occurred
        :type exception: Exception
        :return:
        """
        return any(isinstance(exception, klass) for klass in get_exception_classes())

    def respond_to_exception(self, request, exception):
        """
        Get a response for the given request and exception.

        :param request: Django request that caused the exception
        :type request: django.http.HttpRequest
        :param exception: The exception that occurred
        :type exception: Exception
        :return: Response
        :rtype: django.http.HttpResponse
        """

        # If the exception has a `response`, return that.
        response = getattr(exception, 'response', None)
        if response and isinstance(response, HttpResponse):
            return response

        context = self.get_context(request, exception)
        response_type = self.determine_response_type(request, exception)
        status = self.get_response_status(request, exception)
        if response_type == 'json':
            response = JsonResponse(
                {
                    'code': context['code'],
                    'error': context['message'],
                    'title': context['title'],
                },
                status=status,
            )
        else:
            response = render(
                request=request,
                template_name=self.get_template_names(request, exception, context),
                context=context,
                status=status,
                using=getattr(settings, 'SAFESPACE_TEMPLATE_ENGINE', None),
            )
        if context['code']:
            response['X-Error-Code'] = context['code']
        return response

    def get_response_status(self, request, exception):
        """
        Get the HTTP status code for the response.

        This could be overridden in a subclass.

        :param request: Django request that caused the exception
        :type request: django.http.HttpRequest
        :param exception: The exception that occurred
        :type exception: Exception
        """

        return getattr(settings, 'SAFESPACE_HTTP_STATUS', 406)

    def get_template_names(self, request, exception, context):
        """
        Get candidate template names for rendering a response.

        This could be overridden in a subclass.

        :param request: Django request that caused the exception
        :type request: django.http.HttpRequest
        :param exception: The exception that occurred
        :type exception: Exception
        :param context: Precalculated dict of template interpolation variables
        :type context: dict
<commit_msg>Make the JSON and HTML responses easier to fully override in subclasses<commit_after>from __future__ import unicode_literals

from django.conf import settings
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render
from django.utils.deprecation import MiddlewareMixin
from django.utils.encoding import force_text
from django.utils.text import camel_case_to_spaces
from django.utils.translation import ugettext_lazy as _
from safespace.settings import get_exception_classes


class SafespaceMiddleware(MiddlewareMixin):
    """The main safespace middleware."""

    def process_exception(self, request, exception):
        """
        Possibly process an exception. This is a Django middleware hook.

        :param request: Django request that caused the exception
        :type request: django.http.HttpRequest
        :param exception: The exception that occurred
        :type exception: Exception
        :return: Response, maybe
        :rtype: django.http.HttpResponse|None
        """

        if self.should_handle_exception(request, exception):
            return self.respond_to_exception(request, exception)

    def should_handle_exception(self, request, exception):
        """
        Return true if Safespace should handle the exception.
        :param request: Django request that caused the exception
        :type request: django.http.HttpRequest
        :param exception: The exception that occurred
        :type exception: Exception
        :return:
        """
        return any(isinstance(exception, klass) for klass in get_exception_classes())

    def respond_to_exception(self, request, exception):
        """
        Get a response for the given request and exception.

        :param request: Django request that caused the exception
        :type request: django.http.HttpRequest
        :param exception: The exception that occurred
        :type exception: Exception
        :return: Response
        :rtype: django.http.HttpResponse
        """

        # If the exception has a `response`, return that.
        response = getattr(exception, 'response', None)
        if response and isinstance(response, HttpResponse):
            return response

        context = self.get_context(request, exception)

        response_type = self.determine_response_type(request, exception)
        response_renderer = getattr(self, 'get_%s_response' % response_type)
        status = self.get_response_status(request, exception)
        response = response_renderer(request, exception, context, status)
        if context['code']:
            response['X-Error-Code'] = context['code']
        return response

    def get_html_response(self, request, exception, context, status):
        return render(
            request=request,
            template_name=self.get_template_names(request, exception, context),
            context=context,
            using=getattr(settings, 'SAFESPACE_TEMPLATE_ENGINE', None),
            status=status,
        )

    def get_json_response(self, request, exception, context, status):
        content = {
            'code': context['code'],
            'error': context['message'],
            'title': context['title'],
        }
        return JsonResponse(content, status=status)

    def get_response_status(self, request, exception):
        """
        Get the HTTP status code for the response.

        This could be overridden in a subclass.

        :param request: Django request that caused the exception
        :type request: django.http.HttpRequest
        :param exception: The exception that occurred
        :type exception: Exception
        """

        return getattr(settings, 'SAFESPACE_HTTP_STATUS', 406)

    def get_template_names(self, request, exception, context):
        """
        Get candidate template names for rendering a response.

        This could be overridden in a subclass.

        :param request: Django request that caused the exception
        :type request: django.http.HttpRequest
        :param exception: The exception that occurred
        :type exception: Exception
        :param context: Precalculated dict of template interpolation variables
        :type context: dict

{'fraction_non_alphanumeric': 0.07246200607902735, 'fraction_numerical': 0.000729483282674772, 'mean_word_length': 2.680536912751678, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '736246', 'n_tokens_mistral': 2004, 'n_tokens_neox': 1923, 'n_words': 665}