<commit_before>""" A mini API framework.
"""

import re
from urllib import urlencode

from django.contrib.gis.measure import D
from django.core.exceptions import ObjectDoesNotExist
from django.http import HttpResponse, Http404, HttpResponseForbidden, HttpResponseBadRequest
from django.template import loader, RequestContext
from django.template.defaultfilters import escapejs
from django.utils import simplejson as json
from django.views.generic import View

from tastypie.paginator import Paginator

from boundaries import kml
from boundaries.models import app_settings

class RawJSONResponse(object):
    """APIView subclasses can return these if they have
    already-serialized JSON to return"""
    def __init__(self, content):
        self.content = content

class APIView(View):
    """Base view class that serializes subclass responses to JSON.

    Subclasses should define get/post/etc. methods."""

    allow_jsonp = True
    content_type = 'application/json; charset=utf-8'

    def dispatch(self, request, *args, **kwargs):
        result = super(APIView, self).dispatch(request, *args, **kwargs)
        if isinstance(result, HttpResponse):
            return result
        if request.GET.get('format') == 'apibrowser':
            return self.apibrowser_response(request, result)
        resp = HttpResponse(content_type=self.content_type)
        callback = ''
        if self.allow_jsonp and 'callback' in request.GET:
            callback = re.sub(r'[^a-zA-Z0-9_]', '', request.GET['callback'])
            resp.write(callback + '(')
        if isinstance(result, RawJSONResponse):
            resp.write(result.content)
        else:
            json.dump(result, resp, indent=(4 if request.GET.get('pretty') else None))
        if callback:
            resp.write(');')
        return resp

    def apibrowser_response(self, request, result):
        """If format=apibrowser, return a prettified HTML reponse."""
        if isinstance(result, RawJSONResponse):
            result = json.loads(result.content)
        jsonresult = json.dumps(result, indent=4)
        t = loader.get_template('boundaries/apibrowser.html')
        json_url = request.path
        params = dict(request.GET.items())
        params.pop('format')
        if params:
            json_url += '?' + urlencode(params)
        ctx = {
            'json': jsonresult,
            'resource_name': self.model.__name__,
            'is_list': isinstance(self, ModelListView),
            'json_url': json_url
        }
        if ctx['is_list']:
            ctx['title'] = self.model._meta.verbose_name_plural
        else:
            ctx['title'] = self.model._meta.verbose_name
        c = RequestContext(request, ctx)
        return HttpResponse(t.render(c))

class ModelListView(APIView):
    """Base API class for a list of resources.

    Subclasses should set the 'model' attribute to the appropriate model class.
    Set the filterable_fields attribute to a list of field names users should
    be able to filter on.

    Compatible model classes should define a static method called get_dicts that,
    given a list of objects, returns a list of dicts suitable for serialization.
    By default, those will be model objects, but the model can also define a static
    method called 'prepare_queryset_for_get_dicts' that accepts a queryset and returns
    a sliceable iterable of objects that will later be passed to get_dicts."""

    filter_types = ['exact', 'iexact', 'contains', 'icontains',
                    'startswith', 'istartswith', 'endswith', 'iendswith', 'isnull']

    def get_qs(self, request):
        return self.model.objects.all()

    def filter(self, request, qs):
        for (f, val) in request.GET.items():
            if '__' in f:
                (filter_field, filter_type) = f.split('__')
            else:
                (filter_field, filter_type) = (f, 'exact')
            if filter_field in getattr(self, 'filterable_fields', []) and filter_type in self.filter_types:
                if val in ['true', 'True']:
                    val = True
                elif val in ['false', 'False']:
                    val = False
                qs = qs.filter(**{filter_field + '__' + filter_type: val})
        return qs

    def get_related_resources(self, request, qs, meta):
        return {}

    def get(self, request, **kwargs):
        qs = self.get_qs(request, **kwargs)
        qs = self.filter(request, qs)
        if hasattr(self.model, 'prepare_queryset_for_get_dicts'):
            qs = self.model.prepare_queryset_for_get_dicts(qs)
        paginator = Paginator(request.GET, qs, resource_uri=request.path)
        result = paginator.page()
        result['objects'] = self.model.get_dicts(result['objects'])
        related = self.get_related_resources(request, qs, result['meta'])
        if related:<commit_msg>probably not the django way, but I can't stand error emails<commit_after>""" A mini API framework.
"""

import re
from urllib import urlencode

from django.contrib.gis.measure import D
from django.core.exceptions import ObjectDoesNotExist
from django.http import HttpResponse, Http404, HttpResponseForbidden, HttpResponseBadRequest
from django.template import loader, RequestContext
from django.template.defaultfilters import escapejs
from django.utils import simplejson as json
from django.views.generic import View

from tastypie.paginator import Paginator

from boundaries import kml
from boundaries.models import app_settings

class RawJSONResponse(object):
    """APIView subclasses can return these if they have
    already-serialized JSON to return"""
    def __init__(self, content):
        self.content = content

class APIView(View):
    """Base view class that serializes subclass responses to JSON.

    Subclasses should define get/post/etc. methods."""

    allow_jsonp = True
    content_type = 'application/json; charset=utf-8'

    def dispatch(self, request, *args, **kwargs):
        result = super(APIView, self).dispatch(request, *args, **kwargs)
        if isinstance(result, HttpResponse):
            return result
        if request.GET.get('format') == 'apibrowser':
            return self.apibrowser_response(request, result)
        resp = HttpResponse(content_type=self.content_type)
        callback = ''
        if self.allow_jsonp and 'callback' in request.GET:
            callback = re.sub(r'[^a-zA-Z0-9_]', '', request.GET['callback'])
            resp.write(callback + '(')
        if isinstance(result, RawJSONResponse):
            resp.write(result.content)
        else:
            json.dump(result, resp, indent=(4 if request.GET.get('pretty') else None))
        if callback:
            resp.write(');')
        return resp

    def apibrowser_response(self, request, result):
        """If format=apibrowser, return a prettified HTML reponse."""
        if isinstance(result, RawJSONResponse):
            result = json.loads(result.content)
        jsonresult = json.dumps(result, indent=4)
        t = loader.get_template('boundaries/apibrowser.html')
        json_url = request.path
        params = dict(request.GET.items())
        params.pop('format')
        if params:
            json_url += '?' + urlencode(params)
        ctx = {
            'json': jsonresult,
            'resource_name': self.model.__name__,
            'is_list': isinstance(self, ModelListView),
            'json_url': json_url
        }
        if ctx['is_list']:
            ctx['title'] = self.model._meta.verbose_name_plural
        else:
            ctx['title'] = self.model._meta.verbose_name
        c = RequestContext(request, ctx)
        return HttpResponse(t.render(c))

class ModelListView(APIView):
    """Base API class for a list of resources.

    Subclasses should set the 'model' attribute to the appropriate model class.
    Set the filterable_fields attribute to a list of field names users should
    be able to filter on.

    Compatible model classes should define a static method called get_dicts that,
    given a list of objects, returns a list of dicts suitable for serialization.
    By default, those will be model objects, but the model can also define a static
    method called 'prepare_queryset_for_get_dicts' that accepts a queryset and returns
    a sliceable iterable of objects that will later be passed to get_dicts."""

    filter_types = ['exact', 'iexact', 'contains', 'icontains',
                    'startswith', 'istartswith', 'endswith', 'iendswith', 'isnull']

    def get_qs(self, request):
        return self.model.objects.all()

    def filter(self, request, qs):
        for (f, val) in request.GET.items():
            if '__' in f:
                (filter_field, filter_type) = f.split('__')
            else:
                (filter_field, filter_type) = (f, 'exact')
            if filter_field in getattr(self, 'filterable_fields', []) and filter_type in self.filter_types:
                if val in ['true', 'True']:
                    val = True
                elif val in ['false', 'False']:
                    val = False
                qs = qs.filter(**{filter_field + '__' + filter_type: val})
        return qs

    def get_related_resources(self, request, qs, meta):
        return {}

    def get(self, request, **kwargs):
        for parameter in ['point', 'contains']:
            if parameter in request.GET:
                lat, lon = re.sub(r'[^\d.,-]', '', request.GET[parameter]).split(',')
                if not lat and not lon:
                    return HttpResponseBadRequest()

        qs = self.get_qs(request, **kwargs)
        qs = self.filter(request, qs)
        if hasattr(self.model, 'prepare_queryset_for_get_dicts'):
            qs = self.model.prepare_queryset_for_get_dicts(qs)
        paginator = Paginator(request.GET, qs, resource_uri=request.path)
        result = paginator.page()
        result['objects'] = self.model.get_dicts(result['objects'])
        related = self.get_related_resources(request, qs, result['meta'])
        if related:
{'fraction_non_alphanumeric': 0.10446570972886762, 'fraction_numerical': 0.001594896331738437, 'mean_word_length': 2.6886029411764705, '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': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1273479', 'n_tokens_mistral': 2839, 'n_tokens_neox': 2758, 'n_words': 824}