<commit_before>import json
import logging
import traceback
from functools import wraps

from django import http
from django.conf import settings
from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse as _reverse
from django.utils.http import urlencode

from dimagi.utils.web import get_url_base

from corehq.util import global_request

JSON = 'application/json'
logger = logging.getLogger('django.request')


def set_file_download(response, filename):
    response["Content-Disposition"] = 'attachment; filename="%s"' % filename


class BadRequest(Exception):
    """Error to be used with @json_error to signal a bad request

    Inspired by https://github.com/jsocol/django-jsonview ::

    HTTP does not have a great status code for "you submitted a form that didn't
    validate," and so Django doesn't support it very well. Most examples just
    return 200 OK.

    Normally, this is fine. But if you're submitting a form via Ajax, it's nice
    to have a distinct status for "OK" and "Nope." The HTTP 400 Bad Request
    response is the fallback for issues with a request not-otherwise-specified,
    so let's do that.

    To cause @json_error to return a 400, just raise this exception with
    whatever appropriate error message.
    """


def json_error(f):
    """A decorator for request handlers that returns structured error responses

    Inspired by (and some parts shamelessly copied from)
    https://github.com/jsocol/django-jsonview
    """
    @wraps(f)
    def inner(request, *args, **kwargs):
        try:
            response = f(request, *args, **kwargs)

            # Some errors are not exceptions. :\
            if isinstance(response, http.HttpResponseNotAllowed):
                blob = json.dumps({
                    'error': 405,
                    'message': 'HTTP method not allowed.'
                })
                return http.HttpResponse(blob, status=405, content_type=JSON)

            return response

        except http.Http404 as e:
            return _get_json_exception_response(404, request, e, log_message='Not found: %s')
        except PermissionDenied as e:
            return _get_json_exception_response(403, request, e, log_message='Forbidden (Permission denied): %s')
        except BadRequest as e:
            return _get_json_exception_response(400, request, e)
        except Exception as e:
            return _get_json_exception_response(500, request, e)
    return inner


def _get_json_exception_response(code, request, exception, log_message=None):
    if log_message:
        logger.warning(
            log_message, request.path,<commit_msg>Notify when exception occurs in JSON response<commit_after>import json
import logging
import traceback
from functools import wraps

from django import http
from django.conf import settings
from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse as _reverse
from django.utils.http import urlencode

from dimagi.utils.logging import notify_exception
from dimagi.utils.web import get_url_base

from corehq.util import global_request

JSON = 'application/json'
logger = logging.getLogger('django.request')


def set_file_download(response, filename):
    response["Content-Disposition"] = 'attachment; filename="%s"' % filename


class BadRequest(Exception):
    """Error to be used with @json_error to signal a bad request

    Inspired by https://github.com/jsocol/django-jsonview ::

    HTTP does not have a great status code for "you submitted a form that didn't
    validate," and so Django doesn't support it very well. Most examples just
    return 200 OK.

    Normally, this is fine. But if you're submitting a form via Ajax, it's nice
    to have a distinct status for "OK" and "Nope." The HTTP 400 Bad Request
    response is the fallback for issues with a request not-otherwise-specified,
    so let's do that.

    To cause @json_error to return a 400, just raise this exception with
    whatever appropriate error message.
    """


def json_error(f):
    """A decorator for request handlers that returns structured error responses

    Inspired by (and some parts shamelessly copied from)
    https://github.com/jsocol/django-jsonview
    """
    @wraps(f)
    def inner(request, *args, **kwargs):
        try:
            response = f(request, *args, **kwargs)

            # Some errors are not exceptions. :\
            if isinstance(response, http.HttpResponseNotAllowed):
                blob = json.dumps({
                    'error': 405,
                    'message': 'HTTP method not allowed.'
                })
                return http.HttpResponse(blob, status=405, content_type=JSON)

            return response

        except http.Http404 as e:
            return _get_json_exception_response(404, request, e, log_message='Not found: %s')
        except PermissionDenied as e:
            return _get_json_exception_response(403, request, e, log_message='Forbidden (Permission denied): %s')
        except BadRequest as e:
            return _get_json_exception_response(400, request, e)
        except Exception as e:
            notify_exception(request, 'JSON exception response: {}'.format(e))
            return _get_json_exception_response(500, request, e)
    return inner


def _get_json_exception_response(code, request, exception, log_message=None):
    if log_message:
        logger.warning(
            log_message, request.path,
{'fraction_non_alphanumeric': 0.07692307692307693, 'fraction_numerical': 0.010962908825141605, 'mean_word_length': 3.039852398523985, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3482901', 'n_tokens_mistral': 1536, 'n_tokens_neox': 1431, 'n_words': 534}