<commit_before>from datetime import datetime, timedelta

from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.core.paginator import Paginator
from django.db import models
from django.http import Http404
from django.shortcuts import redirect, render
from django.template.defaultfilters import slugify
from django.template.response import TemplateResponse
from django.utils.translation import ugettext_lazy as _
from django.views.generic.list import ListView

from ella.core.models import Listing, Category, Publishable, Author
from ella.core.cache import get_cached_object_or_404, cache_this, get_cached_object
from ella.core import custom_urls
from ella.core.conf import core_settings
from ella.core.managers import ListingHandler
from ella.core.signals import object_rendering, object_rendered
from ella.api.conf import api_settings
from ella.api import object_serializer, response_serializer, FULL
from ella.utils.timezone import now, utc_localize

__docformat__ = "restructuredtext en"

# local cache for get_content_type()
CONTENT_TYPE_MAPPING = {}


class AuthorView(ListView):
    model = Publishable
    context_object_name = 'listings'
    allow_empty = True
    paginate_by = core_settings.CATEGORY_LISTINGS_PAGINATE_BY
    template_name = 'page/author.html'

    def get(self, request, *args, **kwargs):
        if 'slug' not in kwargs:
            raise Http404

        # Compatibility with `paginator` tag.
        if 'p' in request.GET:
            self.kwargs.update({'page': request.GET['p']})

        self.author = get_cached_object(Author, slug=kwargs['slug'])

        return super(AuthorView, self).get(request, *args, **kwargs)

    def get_queryset(self):
        return self.author.recently_published()

    def get_context_data(self, **kwargs):
        base = super(AuthorView, self).get_context_data(**kwargs)
        base.update({'object': self.author})

        # Compatibility with `paginator` tag.
        if base['page_obj']:
            base.update({'page': base['page_obj']})

        return base


class EllaCoreView(object):
    ' Base class for class-based views used in ella.core.views. '

    # name of the template to be passed into get_templates
    template_name = 'TEMPLATE'

    def get_context(self, request, **kwargs):
        """
        Return a dictionary that will be then passed into the template as context.

        :Parameters:
            - `request`: current request

        :Returns:
            Dictionary with all the data
        """
        raise NotImplementedError()

    def get_templates(self, context, template_name=None):
        " Extract parameters for `get_templates` from the context. "
        if not template_name:
            template_name = self.template_name

        kw = {}
        if 'object' in context:
            o = context['object']
            kw['slug'] = o.slug

        if context.get('content_type', False):
            ct = context['content_type']
            kw['app_label'] = ct.app_label
            kw['model_label'] = ct.model

        return get_templates(template_name, category=context['category'], **kw)

    def render(self, request, context, template):
        return TemplateResponse(request, template, context)

    def __call__(self, request, **kwargs):
        context = self.get_context(request, **kwargs)
        return self.render(request, context, self.get_templates(context))


class ObjectDetail(EllaCoreView):
    """
    Renders a page for publishable.  If ``url_remainder`` is specified, tries to
    locate custom view via :meth:`DetailDispatcher.call_view`. If
    :meth:`DetailDispatcher.has_custom_detail` returns ``True``, calls
    :meth:`DetailDispatcher.call_custom_detail`. Otherwise renders a template
    with context containing:

    * object: ``Publishable`` instance representing the URL accessed
    * category: ``Category`` of the ``object``
    * content_type_name: slugified plural verbose name of the publishable's content type
    * content_type: ``ContentType`` of the publishable

    The template is chosen based on the object in question (the first one that matches is used):

    * ``page/category/<tree_path>/content_type/<app>.<model>/<slug>/object.html``
    * ``page/category/<tree_path>/content_type/<app>.<model>/object.html``
    * ``page/category/<tree_path>/object.html``
    * ``page/content_type/<app>.<model>/object.html``
    * ``page/object.html``

    :param request: ``HttpRequest`` from Django
    :param category: ``Category.tree_path`` (empty if home category)
    :param year month day: date matching the `publish_from` field of the `Publishable` object
    :param slug: slug of the `Publishable`
    :param url_remainder: url after the object's url, used to locate custom views in `custom_urls.resolver`

    :raises Http404: if the URL is not valid and/or doesn't correspond to any valid `Publishable`
    """
    template_name = 'object.html'

    class WrongUrl(Http404): pass

    def __call__(self, request, category, slug, year=None, month=None, day=None, id=None, url_remainder=None):
        try:
            context = self.get_context(request, category, slug, year, month, day, id)
        except self.WrongUrl, e:
            message, obj = e.args
            url = obj.get_absolute_url()
            if url_remainder:
                url += url_remainder
            return redirect(url, permanent=True)

        obj = context['object']

        object_rendering.send(sender=context['object'].__class__, request=request, category=context['category'], publishable=context['object'])

        # check for custom actions
        if url_remainder:
            return custom_urls.resolver.call_custom_view(request, obj, url_remainder, context)
        elif custom_urls.resolver.has_custom_detail(obj):
            return custom_urls.resolver.call_custom_detail(request, context)

        object_rendered.send(sender=context['object'].__class__, request=request, category=context['category'], publishable=context['object'])

        if api_settings.ENABLED:
            for mimetype in (a.split(';')[0] for a in request.META.get('HTTP_ACCEPT', '').split(',')):
                if response_serializer.serializable(mimetype):
                    return response_serializer.serialize(object_serializer.serialize(obj, FULL), mimetype)

        return self.render(request, context, self.get_templates(context))

    def get_context(self, request, category, slug, year, month, day, id):

        try:
            cat = Category.objects.get_by_tree_path(category)
        except Category.DoesNotExist:
            # non-static url, no way to recover
            if year:
                raise Http404("Category with tree_path '%s' doesn't exist." % category)
            else:
                cat = None

        if year:
            publishable = get_cached_object_or_404(Publishable,
                        publish_from__year=year,
                        publish_from__month=month,
                        publish_from__day=day,
                        category=cat,
                        slug=slug,
                        static=False
                    )
        else:
            publishable = get_cached_object_or_404(Publishable, pk=id)
            if cat is None:
                raise self.WrongUrl('Category with tree_path %r does not exist.' % category, publishable)<commit_msg>process api before possibly dispatching to custom detail view<commit_after>from datetime import datetime, timedelta

from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.core.paginator import Paginator
from django.db import models
from django.http import Http404
from django.shortcuts import redirect, render
from django.template.defaultfilters import slugify
from django.template.response import TemplateResponse
from django.utils.translation import ugettext_lazy as _
from django.views.generic.list import ListView

from ella.core.models import Listing, Category, Publishable, Author
from ella.core.cache import get_cached_object_or_404, cache_this, get_cached_object
from ella.core import custom_urls
from ella.core.conf import core_settings
from ella.core.managers import ListingHandler
from ella.core.signals import object_rendering, object_rendered
from ella.api.conf import api_settings
from ella.api import object_serializer, response_serializer, FULL
from ella.utils.timezone import now, utc_localize

__docformat__ = "restructuredtext en"

# local cache for get_content_type()
CONTENT_TYPE_MAPPING = {}


class AuthorView(ListView):
    model = Publishable
    context_object_name = 'listings'
    allow_empty = True
    paginate_by = core_settings.CATEGORY_LISTINGS_PAGINATE_BY
    template_name = 'page/author.html'

    def get(self, request, *args, **kwargs):
        if 'slug' not in kwargs:
            raise Http404

        # Compatibility with `paginator` tag.
        if 'p' in request.GET:
            self.kwargs.update({'page': request.GET['p']})

        self.author = get_cached_object(Author, slug=kwargs['slug'])

        return super(AuthorView, self).get(request, *args, **kwargs)

    def get_queryset(self):
        return self.author.recently_published()

    def get_context_data(self, **kwargs):
        base = super(AuthorView, self).get_context_data(**kwargs)
        base.update({'object': self.author})

        # Compatibility with `paginator` tag.
        if base['page_obj']:
            base.update({'page': base['page_obj']})

        return base


class EllaCoreView(object):
    ' Base class for class-based views used in ella.core.views. '

    # name of the template to be passed into get_templates
    template_name = 'TEMPLATE'

    def get_context(self, request, **kwargs):
        """
        Return a dictionary that will be then passed into the template as context.

        :Parameters:
            - `request`: current request

        :Returns:
            Dictionary with all the data
        """
        raise NotImplementedError()

    def get_templates(self, context, template_name=None):
        " Extract parameters for `get_templates` from the context. "
        if not template_name:
            template_name = self.template_name

        kw = {}
        if 'object' in context:
            o = context['object']
            kw['slug'] = o.slug

        if context.get('content_type', False):
            ct = context['content_type']
            kw['app_label'] = ct.app_label
            kw['model_label'] = ct.model

        return get_templates(template_name, category=context['category'], **kw)

    def render(self, request, context, template):
        return TemplateResponse(request, template, context)

    def __call__(self, request, **kwargs):
        context = self.get_context(request, **kwargs)
        return self.render(request, context, self.get_templates(context))


class ObjectDetail(EllaCoreView):
    """
    Renders a page for publishable.  If ``url_remainder`` is specified, tries to
    locate custom view via :meth:`DetailDispatcher.call_view`. If
    :meth:`DetailDispatcher.has_custom_detail` returns ``True``, calls
    :meth:`DetailDispatcher.call_custom_detail`. Otherwise renders a template
    with context containing:

    * object: ``Publishable`` instance representing the URL accessed
    * category: ``Category`` of the ``object``
    * content_type_name: slugified plural verbose name of the publishable's content type
    * content_type: ``ContentType`` of the publishable

    The template is chosen based on the object in question (the first one that matches is used):

    * ``page/category/<tree_path>/content_type/<app>.<model>/<slug>/object.html``
    * ``page/category/<tree_path>/content_type/<app>.<model>/object.html``
    * ``page/category/<tree_path>/object.html``
    * ``page/content_type/<app>.<model>/object.html``
    * ``page/object.html``

    :param request: ``HttpRequest`` from Django
    :param category: ``Category.tree_path`` (empty if home category)
    :param year month day: date matching the `publish_from` field of the `Publishable` object
    :param slug: slug of the `Publishable`
    :param url_remainder: url after the object's url, used to locate custom views in `custom_urls.resolver`

    :raises Http404: if the URL is not valid and/or doesn't correspond to any valid `Publishable`
    """
    template_name = 'object.html'

    class WrongUrl(Http404): pass

    def __call__(self, request, category, slug, year=None, month=None, day=None, id=None, url_remainder=None):
        try:
            context = self.get_context(request, category, slug, year, month, day, id)
        except self.WrongUrl, e:
            message, obj = e.args
            url = obj.get_absolute_url()
            if url_remainder:
                url += url_remainder
            return redirect(url, permanent=True)

        obj = context['object']

        object_rendering.send(sender=context['object'].__class__, request=request, category=context['category'], publishable=context['object'])

        # check for custom actions
        if url_remainder:
            return custom_urls.resolver.call_custom_view(request, obj, url_remainder, context)
        elif api_settings.ENABLED:
            for mimetype in (a.split(';')[0] for a in request.META.get('HTTP_ACCEPT', '').split(',')):
                if response_serializer.serializable(mimetype):
                    return response_serializer.serialize(object_serializer.serialize(obj, FULL), mimetype)

        if custom_urls.resolver.has_custom_detail(obj):
            return custom_urls.resolver.call_custom_detail(request, context)

        object_rendered.send(sender=context['object'].__class__, request=request, category=context['category'], publishable=context['object'])

        return self.render(request, context, self.get_templates(context))

    def get_context(self, request, category, slug, year, month, day, id):

        try:
            cat = Category.objects.get_by_tree_path(category)
        except Category.DoesNotExist:
            # non-static url, no way to recover
            if year:
                raise Http404("Category with tree_path '%s' doesn't exist." % category)
            else:
                cat = None

        if year:
            publishable = get_cached_object_or_404(Publishable,
                        publish_from__year=year,
                        publish_from__month=month,
                        publish_from__day=day,
                        category=cat,
                        slug=slug,
                        static=False
                    )
        else:
            publishable = get_cached_object_or_404(Publishable, pk=id)
            if cat is None:
                raise self.WrongUrl('Category with tree_path %r does not exist.' % category, publishable)
{'fraction_non_alphanumeric': 0.09745591600484588, 'fraction_numerical': 0.0033651904697805895, 'mean_word_length': 2.988993288590604, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 23, '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': '4694817', 'n_tokens_mistral': 4234, 'n_tokens_neox': 4058, 'n_words': 1125}