<commit_before>import json
import logging
import opml
import re

from django.contrib import messages
from django.core.exceptions import ValidationError
from django.core.paginator import Paginator, InvalidPage, EmptyPage
from django.core.urlresolvers import reverse, reverse_lazy
from django.db import transaction
from django.db.models import Sum
from django.shortcuts import get_object_or_404, redirect, render
from django.template import loader, RequestContext
from django.template.defaultfilters import slugify
from django.utils.html import format_html
from django.utils.translation import ugettext as _, ungettext
from django.views import generic

from ..decorators import login_required
from ..tasks import enqueue
from .models import Category, Entry, UniqueFeed
from .forms import (CategoryForm, FeedForm, OPMLImportForm, ActionForm,
                    ReadForm, SubscriptionFormSet, UndoReadForm, user_lock)
from .tasks import read_later

"""
Each view displays a list of entries, with a level of filtering:
    - home: all entries
    - category: entries in a specific category
    - feed: entries for a specific feed
    - item: a single entry

Entries are paginated.
"""

logger = logging.getLogger(__name__)

MEDIA_RE = re.compile(r'.*<(img|audio|video)\s+.*', re.UNICODE | re.DOTALL)


class Keyboard(generic.TemplateView):
    template_name = 'feeds/keyboard.html'
keyboard = Keyboard.as_view()


def paginate(object_list, page=1, nb_items=25, force_count=None):
    """
    Simple generic paginator for all the ``Entry`` lists
    """
    if force_count is not None:
        object_list.count = lambda x: force_count

    paginator = Paginator(object_list, nb_items)

    try:
        paginated = paginator.page(page)
    except (EmptyPage, InvalidPage):
        paginated = paginator.page(paginator.num_pages)

    return paginated, paginator._count


@login_required
def entries_list(request, page=1, only_unread=False, category=None, feed=None,
                 starred=False):
    """
    Displays a paginated list of entries.

    ``page``: the page number
    ``only_unread``: filters the list to display only the new entries
    ``category``: (slug) if set, will filter the entries of this category
    ``feed``: (object_id) if set, will filter the entries of this feed

    Note: only set category OR feed. Not both at the same time.
    """
    user = request.user
    categories = user.categories.with_unread_counts()

    if category is not None:
        category = get_object_or_404(user.categories.all(), slug=category)
        entries = user.entries.filter(feed__category=category)
        all_url = reverse('feeds:category', args=[category.slug])
        unread_url = reverse('feeds:unread_category', args=[category.slug])

    if feed is not None:
        feed = get_object_or_404(user.feeds.select_related('category'),
                                 pk=feed)
        entries = feed.entries.all()
        all_url = reverse('feeds:feed', args=[feed.id])
        unread_url = reverse('feeds:unread_feed', args=[feed.id])
        category = feed.category

    if starred is True:
        entries = user.entries.filter(starred=True)
        all_url = reverse('feeds:stars')
        unread_url = None

    if feed is None and category is None and starred is not True:
        entries = user.entries.all()
        all_url = reverse('feeds:home')
        unread_url = reverse('feeds:unread')

    entries = entries.select_related('feed', 'feed__category')
    if user.oldest_first:
        entries = entries.order_by('date', 'id')

    if request.method == 'POST':
        if request.POST['action'] in (ReadForm.READ_ALL, ReadForm.READ_PAGE):
            pages_only = request.POST['action'] == ReadForm.READ_PAGE
            form = ReadForm(entries, feed, category, user,
                            pages_only=pages_only,
                            nb_items=request.user.entries_per_page,
                            data=request.POST)
            if form.is_valid():
                pks = form.save()
                undo_form = loader.render_to_string('feeds/undo_read.html', {
                    'form': UndoReadForm(initial={
                        'pks': json.dumps(pks, separators=(',', ':'))}),
                    'action': request.get_full_path(),
                }, context_instance=RequestContext(request))
                message = ungettext(
                    '1 entry has been marked as read.',
                    '%(value)s entries have been marked as read.',
                    'value') % {'value': len(pks)}
                messages.success(request,
                                 format_html(u"{0} {1}", message, undo_form))

        elif request.POST['action'] == 'undo-read':
            form = UndoReadForm(user, data=request.POST)
            if form.is_valid():
                count = form.save()
                messages.success(
                    request, ungettext(
                        '1 entry has been marked as unread.',
                        '%(value)s entries have been marked as unread.',
                        'value') % {'value': count})

        if only_unread:
            return redirect(unread_url)
        else:
            return redirect(all_url)

    unread_count = entries.filter(read=False).count()

    # base_url is a variable that helps the paginator a lot. The drawback is
    # that the paginator can't use reversed URLs.
    base_url = all_url
    if only_unread:
        total_count = entries.count()
        entries = entries.filter(read=False)
        base_url = unread_url
        entries, foo = paginate(entries, page=page,
                                force_count=unread_count,
                                nb_items=request.user.entries_per_page)
    else:
        entries, total_count = paginate(entries, page=page,
                                        nb_items=request.user.entries_per_page)

    request.session['back_url'] = request.get_full_path()
    context = {
        'categories': categories,
        'category': category,
        'feed': feed,
        'entries': entries,
        'only_unread': only_unread,
        'unread_count': unread_count,
        'total_count': total_count,
        'all_url': all_url,
        'unread_url': unread_url,
        'base_url': base_url,
        'stars': starred,
        'entries_template': 'feeds/entries_include.html',
    }
    if unread_count:
        context['read_all_form'] = ReadForm()
        context['read_page_form'] = ReadForm(pages_only=True, initial={
            'action': ReadForm.READ_PAGE,
            'pages': json.dumps([page]),
        })
        context['action'] = request.get_full_path()
    if entries.paginator.count == 0 and request.user.feeds.count() == 0:
        context['noob'] = True

    if request.is_ajax():
        template_name = context['entries_template']
    else:
        template_name = 'feeds/entries_list.html'

    return render(request, template_name, context)


class SuccessMixin(object):
    success_message = None

    def get_success_message(self):
        return self.success_message

    def form_valid(self, form):
        response = super(SuccessMixin, self).form_valid(form)
        msg = self.get_success_message()
        if msg is not None:
            messages.success(self.request, msg)
        return response<commit_msg>Make sure the initial passed page number is an interger.<commit_after>import json
import logging
import opml
import re

from django.contrib import messages
from django.core.exceptions import ValidationError
from django.core.paginator import Paginator, InvalidPage, EmptyPage
from django.core.urlresolvers import reverse, reverse_lazy
from django.db import transaction
from django.db.models import Sum
from django.shortcuts import get_object_or_404, redirect, render
from django.template import loader, RequestContext
from django.template.defaultfilters import slugify
from django.utils.html import format_html
from django.utils.translation import ugettext as _, ungettext
from django.views import generic

from ..decorators import login_required
from ..tasks import enqueue
from .models import Category, Entry, UniqueFeed
from .forms import (CategoryForm, FeedForm, OPMLImportForm, ActionForm,
                    ReadForm, SubscriptionFormSet, UndoReadForm, user_lock)
from .tasks import read_later

"""
Each view displays a list of entries, with a level of filtering:
    - home: all entries
    - category: entries in a specific category
    - feed: entries for a specific feed
    - item: a single entry

Entries are paginated.
"""

logger = logging.getLogger(__name__)

MEDIA_RE = re.compile(r'.*<(img|audio|video)\s+.*', re.UNICODE | re.DOTALL)


class Keyboard(generic.TemplateView):
    template_name = 'feeds/keyboard.html'
keyboard = Keyboard.as_view()


def paginate(object_list, page=1, nb_items=25, force_count=None):
    """
    Simple generic paginator for all the ``Entry`` lists
    """
    if force_count is not None:
        object_list.count = lambda x: force_count

    paginator = Paginator(object_list, nb_items)

    try:
        paginated = paginator.page(page)
    except (EmptyPage, InvalidPage):
        paginated = paginator.page(paginator.num_pages)

    return paginated, paginator._count


@login_required
def entries_list(request, page=1, only_unread=False, category=None, feed=None,
                 starred=False):
    """
    Displays a paginated list of entries.

    ``page``: the page number
    ``only_unread``: filters the list to display only the new entries
    ``category``: (slug) if set, will filter the entries of this category
    ``feed``: (object_id) if set, will filter the entries of this feed

    Note: only set category OR feed. Not both at the same time.
    """
    user = request.user
    categories = user.categories.with_unread_counts()

    if category is not None:
        category = get_object_or_404(user.categories.all(), slug=category)
        entries = user.entries.filter(feed__category=category)
        all_url = reverse('feeds:category', args=[category.slug])
        unread_url = reverse('feeds:unread_category', args=[category.slug])

    if feed is not None:
        feed = get_object_or_404(user.feeds.select_related('category'),
                                 pk=feed)
        entries = feed.entries.all()
        all_url = reverse('feeds:feed', args=[feed.id])
        unread_url = reverse('feeds:unread_feed', args=[feed.id])
        category = feed.category

    if starred is True:
        entries = user.entries.filter(starred=True)
        all_url = reverse('feeds:stars')
        unread_url = None

    if feed is None and category is None and starred is not True:
        entries = user.entries.all()
        all_url = reverse('feeds:home')
        unread_url = reverse('feeds:unread')

    entries = entries.select_related('feed', 'feed__category')
    if user.oldest_first:
        entries = entries.order_by('date', 'id')

    if request.method == 'POST':
        if request.POST['action'] in (ReadForm.READ_ALL, ReadForm.READ_PAGE):
            pages_only = request.POST['action'] == ReadForm.READ_PAGE
            form = ReadForm(entries, feed, category, user,
                            pages_only=pages_only,
                            nb_items=request.user.entries_per_page,
                            data=request.POST)
            if form.is_valid():
                pks = form.save()
                undo_form = loader.render_to_string('feeds/undo_read.html', {
                    'form': UndoReadForm(initial={
                        'pks': json.dumps(pks, separators=(',', ':'))}),
                    'action': request.get_full_path(),
                }, context_instance=RequestContext(request))
                message = ungettext(
                    '1 entry has been marked as read.',
                    '%(value)s entries have been marked as read.',
                    'value') % {'value': len(pks)}
                messages.success(request,
                                 format_html(u"{0} {1}", message, undo_form))

        elif request.POST['action'] == 'undo-read':
            form = UndoReadForm(user, data=request.POST)
            if form.is_valid():
                count = form.save()
                messages.success(
                    request, ungettext(
                        '1 entry has been marked as unread.',
                        '%(value)s entries have been marked as unread.',
                        'value') % {'value': count})

        if only_unread:
            return redirect(unread_url)
        else:
            return redirect(all_url)

    unread_count = entries.filter(read=False).count()

    # base_url is a variable that helps the paginator a lot. The drawback is
    # that the paginator can't use reversed URLs.
    base_url = all_url
    if only_unread:
        total_count = entries.count()
        entries = entries.filter(read=False)
        base_url = unread_url
        entries, foo = paginate(entries, page=page,
                                force_count=unread_count,
                                nb_items=request.user.entries_per_page)
    else:
        entries, total_count = paginate(entries, page=page,
                                        nb_items=request.user.entries_per_page)

    request.session['back_url'] = request.get_full_path()
    context = {
        'categories': categories,
        'category': category,
        'feed': feed,
        'entries': entries,
        'only_unread': only_unread,
        'unread_count': unread_count,
        'total_count': total_count,
        'all_url': all_url,
        'unread_url': unread_url,
        'base_url': base_url,
        'stars': starred,
        'entries_template': 'feeds/entries_include.html',
    }
    if unread_count:
        context['read_all_form'] = ReadForm()
        context['read_page_form'] = ReadForm(pages_only=True, initial={
            'action': ReadForm.READ_PAGE,
            'pages': json.dumps([int(page)]),
        })
        context['action'] = request.get_full_path()
    if entries.paginator.count == 0 and request.user.feeds.count() == 0:
        context['noob'] = True

    if request.is_ajax():
        template_name = context['entries_template']
    else:
        template_name = 'feeds/entries_list.html'

    return render(request, template_name, context)


class SuccessMixin(object):
    success_message = None

    def get_success_message(self):
        return self.success_message

    def form_valid(self, form):
        response = super(SuccessMixin, self).form_valid(form)
        msg = self.get_success_message()
        if msg is not None:
            messages.success(self.request, msg)
        return response
{'fraction_non_alphanumeric': 0.10107249524843877, 'fraction_numerical': 0.002579418951941352, 'mean_word_length': 2.4674040950811955, 'pattern_counts': {'":': 0, '<': 5, '<?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': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1419378', 'n_tokens_mistral': 4238, 'n_tokens_neox': 4085, 'n_words': 1076}