<commit_before>#!/usr/bin/env python
#-*- coding: utf-8 -*-

"""
    flask.ext.paginate
    ~~~~~~~~~~~~~~

    Adds pagination support to your application.

    :copyright: (c) 2013 by <NAME>.
    :license: BSD, see LICENSE for more details
"""

from __future__ import unicode_literals
import sys
import urllib
from flask import request, url_for, Markup
from werkzeug.datastructures import MultiDict

__version__ = '0.2.8'

PY2 = sys.version_info[0] == 2

_bs_prev_page = '<li class="previous"><a href="{0}">{1}</a></li>'
PREV_PAGES = dict(bootstrap=_bs_prev_page,
                  bootstrap2=_bs_prev_page,
                  bootstrap3=_bs_prev_page,
                  foundation='<li class="arrow"><a href="{0}">{1}</a></li>',
                  )

_bs_next_page = '<li class="next"><a href="{0}">{1}</a></li>'
NEXT_PAGES = dict(bootstrap=_bs_next_page,
                  bootstrap2=_bs_next_page,
                  bootstrap3=_bs_next_page,
                  foundation='<li class="arrow"><a href="{0}">{1}</a></li>',
                  )

CURRENT_PAGES = dict(bootstrap='<li class="active"><a href="#">{0}</a></li>',
                     bootstrap3='<li class="active"><a href="#">{0}</a></li>',
                     foundation='<li class="current"><a href="#">{0}</a></li>',
                     )
CURRENT_PAGES.update(bootstrap2=CURRENT_PAGES['bootstrap'])

LINK = '<li><a href="{0}">{1}</a></li>'
FA_LINK = '<li class="unavailable"><a href="#">{0}</a></li>'

GAP_MARKERS = dict(bootstrap='<li class="disabled"><a href="#">...</a></li>',
                   foundation='<li class="unavailable">\
                   <a href="#">...</a></li>',
                   )
GAP_MARKERS.update(bootstrap2=GAP_MARKERS['bootstrap'],
                   bootstrap3=GAP_MARKERS['bootstrap'],
                   )

_bs_prev_disabled_page = '<li class="previous disabled unavailable">\
<a href="#"> {0} </a></li>'
PREV_DISABLED_PAGES = dict(bootstrap=_bs_prev_disabled_page,
                           bootstrap2=_bs_prev_disabled_page,
                           bootstrap3=_bs_prev_disabled_page,
                           foundation=FA_LINK,
                           )

_bs_next_disabled_page = '<li class="next disabled">\
<a href="#"> {0} </a></li>'
NEXT_DISABLED_PAGES = dict(bootstrap=_bs_next_disabled_page,
                           bootstrap2=_bs_next_disabled_page,
                           bootstrap3=_bs_next_disabled_page,
                           foundation=FA_LINK,
                           )

PREV_LABEL = '&laquo;'
NEXT_LABEL = '&raquo;'
RECORD_NAME = 'records'

DISPLAY_MSG = '''displaying <b>{start} - {end}</b> {record_name} in
total <b>{total}</b>'''

SEARCH_MSG = '''found <b>{found}</b> {record_name},
displaying <b>{start} - {end}</b>'''

CSS_LINKS = dict(bootstrap='<div class="pagination{0}{1}"><ul>',
                 bootstrap2='<div class="pagination{0}{1}"><ul>',
                 bootstrap3='<ul class="pagination{0}{1}">',
                 foundation='<ul class="pagination{0}{1}">',
                 )
CSS_LINKS_END = dict(bootstrap='</ul></div>',
                     bootstrap2='</ul></div>',
                     bootstrap3='</ul>',
                     foundation='</ul>',
                     )

# foundation aligment
F_ALIGNMENT = '<div class="pagination-{0}">'


class Pagination(object):
    '''A simple pagination extension for flask
    '''
    def __init__(self, found=0, **kwargs):
        '''provides the params:

            **found**: used when searching

            **page**: current page

            **per_page**: how many records displayed on one page

            **inner_window**: how many links arround current page

            **outer_window**: how many links near first/last link

            **prev_label**: text for previous page, default is **&laquo;**

            **next_label**: text for next page, default is **&raquo;**

            **search**: search or not?

            **total**: total records for pagination

            **display_msg**: text for pagation information

            **search_msg**: text for search information

            **record_name**: record name showed in pagination information

            **link_size**: font size of page links

            **alignment**: the alignment of pagination links

            **href**: Add custom href for links - this supports forms with post method

            **show_single_page**: decide whether or not a single page returns pagination

            **bs_version**: the version of bootstrap, default is **2**

            **css_framework**: the css framework, default is **bootstrap**

            **href**: <a> href parameter, MUST contain {0} to format page number
        '''
        self.found = found
        self.page = kwargs.get('page', 1)
        self.per_page = kwargs.get('per_page', 10)
        self.inner_window = kwargs.get('inner_window', 2)
        self.outer_window = kwargs.get('outer_window', 1)
        self.prev_label = kwargs.get('prev_label') or PREV_LABEL
        self.next_label = kwargs.get('next_label') or NEXT_LABEL
        self.search = kwargs.get('search', False)
        self.total = kwargs.get('total', 0)
        self.display_msg = kwargs.get('display_msg') or DISPLAY_MSG
        self.search_msg = kwargs.get('search_msg') or SEARCH_MSG
        self.record_name = kwargs.get('record_name') or RECORD_NAME
        self.css_framework = kwargs.get('css_framework', 'bootstrap').lower()
        if self.css_framework not in CURRENT_PAGES:
            self.css_framework = 'bootstrap'

        self.bs_version = kwargs.get('bs_version') or 2
        if self.css_framework.startswith('bootstrap'):
            if self.bs_version in (3, '3'):
                self.css_framework = 'bootstrap3'

        self.link_size = kwargs.get('link_size', '')
        if self.link_size:
            if self.css_framework == 'foundation':
                self.link_size = ''
            else:
                self.link_size = ' pagination-{0}'.format(self.link_size)

        self.alignment = kwargs.get('alignment', '')
        if self.alignment and self.css_framework.startswith('bootstrap'):
            self.alignment = ' pagination-{0}'.format(self.alignment)

        self.href = kwargs.get('href', None)
        self.show_single_page = kwargs.get('show_single_page', False)

        self.current_page_fmt = CURRENT_PAGES[self.css_framework]
        self.link_css_fmt = CSS_LINKS[self.css_framework]
        self.gap_marker_fmt = GAP_MARKERS[self.css_framework]
        self.prev_disabled_page_fmt = PREV_DISABLED_PAGES[self.css_framework]
        self.next_disabled_page_fmt = NEXT_DISABLED_PAGES[self.css_framework]
        self.prev_page_fmt = PREV_PAGES[self.css_framework]
        self.next_page_fmt = NEXT_PAGES[self.css_framework]
        self.css_end_fmt = CSS_LINKS_END[self.css_framework]

    def page_href(self, page):
        if self.href:
            page = 1 if page is None else page
            return self.href.format(page)

        return self.get_link(url_for(self.endpoint, page=page, **self.args))

    @property
    def total_pages(self):
        current_total = self.found if self.search else self.total
        pages = divmod(current_total, self.per_page)
        return pages[0] + 1 if pages[1] else pages[0]

    @property
    def has_prev(self):
        return self.page > 1

    @property
    def has_next(self):
        return self.page < self.total_pages

    @property
    def endpoint(self):
        return request.endpoint

    def get_link(self, url):
        if PY2:
            return urllib.unquote(url)

        return urllib.parse.unquote(url)

    @property
    def args(self):
        if PY2:
            args_items = request.args.iteritems(multi=True)
        else:<commit_msg>UnicodeDecodeError when unicode chars in url<commit_after>#!/usr/bin/env python
#-*- coding: utf-8 -*-

"""
    flask.ext.paginate
    ~~~~~~~~~~~~~~

    Adds pagination support to your application.

    :copyright: (c) 2013 by <NAME>.
    :license: BSD, see LICENSE for more details
"""

from __future__ import unicode_literals
import sys
import urllib
from flask import request, url_for, Markup
from werkzeug.datastructures import MultiDict

__version__ = '0.2.8'

PY2 = sys.version_info[0] == 2

_bs_prev_page = '<li class="previous"><a href="{0}">{1}</a></li>'
PREV_PAGES = dict(bootstrap=_bs_prev_page,
                  bootstrap2=_bs_prev_page,
                  bootstrap3=_bs_prev_page,
                  foundation='<li class="arrow"><a href="{0}">{1}</a></li>',
                  )

_bs_next_page = '<li class="next"><a href="{0}">{1}</a></li>'
NEXT_PAGES = dict(bootstrap=_bs_next_page,
                  bootstrap2=_bs_next_page,
                  bootstrap3=_bs_next_page,
                  foundation='<li class="arrow"><a href="{0}">{1}</a></li>',
                  )

CURRENT_PAGES = dict(bootstrap='<li class="active"><a href="#">{0}</a></li>',
                     bootstrap3='<li class="active"><a href="#">{0}</a></li>',
                     foundation='<li class="current"><a href="#">{0}</a></li>',
                     )
CURRENT_PAGES.update(bootstrap2=CURRENT_PAGES['bootstrap'])

LINK = '<li><a href="{0}">{1}</a></li>'
FA_LINK = '<li class="unavailable"><a href="#">{0}</a></li>'

GAP_MARKERS = dict(bootstrap='<li class="disabled"><a href="#">...</a></li>',
                   foundation='<li class="unavailable">\
                   <a href="#">...</a></li>',
                   )
GAP_MARKERS.update(bootstrap2=GAP_MARKERS['bootstrap'],
                   bootstrap3=GAP_MARKERS['bootstrap'],
                   )

_bs_prev_disabled_page = '<li class="previous disabled unavailable">\
<a href="#"> {0} </a></li>'
PREV_DISABLED_PAGES = dict(bootstrap=_bs_prev_disabled_page,
                           bootstrap2=_bs_prev_disabled_page,
                           bootstrap3=_bs_prev_disabled_page,
                           foundation=FA_LINK,
                           )

_bs_next_disabled_page = '<li class="next disabled">\
<a href="#"> {0} </a></li>'
NEXT_DISABLED_PAGES = dict(bootstrap=_bs_next_disabled_page,
                           bootstrap2=_bs_next_disabled_page,
                           bootstrap3=_bs_next_disabled_page,
                           foundation=FA_LINK,
                           )

PREV_LABEL = '&laquo;'
NEXT_LABEL = '&raquo;'
RECORD_NAME = 'records'

DISPLAY_MSG = '''displaying <b>{start} - {end}</b> {record_name} in
total <b>{total}</b>'''

SEARCH_MSG = '''found <b>{found}</b> {record_name},
displaying <b>{start} - {end}</b>'''

CSS_LINKS = dict(bootstrap='<div class="pagination{0}{1}"><ul>',
                 bootstrap2='<div class="pagination{0}{1}"><ul>',
                 bootstrap3='<ul class="pagination{0}{1}">',
                 foundation='<ul class="pagination{0}{1}">',
                 )
CSS_LINKS_END = dict(bootstrap='</ul></div>',
                     bootstrap2='</ul></div>',
                     bootstrap3='</ul>',
                     foundation='</ul>',
                     )

# foundation aligment
F_ALIGNMENT = '<div class="pagination-{0}">'


class Pagination(object):
    '''A simple pagination extension for flask
    '''
    def __init__(self, found=0, **kwargs):
        '''provides the params:

            **found**: used when searching

            **page**: current page

            **per_page**: how many records displayed on one page

            **inner_window**: how many links arround current page

            **outer_window**: how many links near first/last link

            **prev_label**: text for previous page, default is **&laquo;**

            **next_label**: text for next page, default is **&raquo;**

            **search**: search or not?

            **total**: total records for pagination

            **display_msg**: text for pagation information

            **search_msg**: text for search information

            **record_name**: record name showed in pagination information

            **link_size**: font size of page links

            **alignment**: the alignment of pagination links

            **href**: Add custom href for links - this supports forms with post method

            **show_single_page**: decide whether or not a single page returns pagination

            **bs_version**: the version of bootstrap, default is **2**

            **css_framework**: the css framework, default is **bootstrap**

            **href**: <a> href parameter, MUST contain {0} to format page number
        '''
        self.found = found
        self.page = kwargs.get('page', 1)
        self.per_page = kwargs.get('per_page', 10)
        self.inner_window = kwargs.get('inner_window', 2)
        self.outer_window = kwargs.get('outer_window', 1)
        self.prev_label = kwargs.get('prev_label') or PREV_LABEL
        self.next_label = kwargs.get('next_label') or NEXT_LABEL
        self.search = kwargs.get('search', False)
        self.total = kwargs.get('total', 0)
        self.display_msg = kwargs.get('display_msg') or DISPLAY_MSG
        self.search_msg = kwargs.get('search_msg') or SEARCH_MSG
        self.record_name = kwargs.get('record_name') or RECORD_NAME
        self.css_framework = kwargs.get('css_framework', 'bootstrap').lower()
        if self.css_framework not in CURRENT_PAGES:
            self.css_framework = 'bootstrap'

        self.bs_version = kwargs.get('bs_version') or 2
        if self.css_framework.startswith('bootstrap'):
            if self.bs_version in (3, '3'):
                self.css_framework = 'bootstrap3'

        self.link_size = kwargs.get('link_size', '')
        if self.link_size:
            if self.css_framework == 'foundation':
                self.link_size = ''
            else:
                self.link_size = ' pagination-{0}'.format(self.link_size)

        self.alignment = kwargs.get('alignment', '')
        if self.alignment and self.css_framework.startswith('bootstrap'):
            self.alignment = ' pagination-{0}'.format(self.alignment)

        self.href = kwargs.get('href', None)
        self.show_single_page = kwargs.get('show_single_page', False)

        self.current_page_fmt = CURRENT_PAGES[self.css_framework]
        self.link_css_fmt = CSS_LINKS[self.css_framework]
        self.gap_marker_fmt = GAP_MARKERS[self.css_framework]
        self.prev_disabled_page_fmt = PREV_DISABLED_PAGES[self.css_framework]
        self.next_disabled_page_fmt = NEXT_DISABLED_PAGES[self.css_framework]
        self.prev_page_fmt = PREV_PAGES[self.css_framework]
        self.next_page_fmt = NEXT_PAGES[self.css_framework]
        self.css_end_fmt = CSS_LINKS_END[self.css_framework]

    def page_href(self, page):
        if self.href:
            page = 1 if page is None else page
            url = self.href.format(page)
        else:
            url = self.get_link(url_for(self.endpoint, page=page, **self.args))
        
        # Need to return a unicode object
        return url.decode('utf8')

    @property
    def total_pages(self):
        current_total = self.found if self.search else self.total
        pages = divmod(current_total, self.per_page)
        return pages[0] + 1 if pages[1] else pages[0]

    @property
    def has_prev(self):
        return self.page > 1

    @property
    def has_next(self):
        return self.page < self.total_pages

    @property
    def endpoint(self):
        return request.endpoint

    def get_link(self, url):
        if PY2:
            return urllib.unquote(url)

        return urllib.parse.unquote(url)

    @property
    def args(self):
        if PY2:
            args_items = request.args.iteritems(multi=True)
        else:
{'fraction_non_alphanumeric': 0.1399195350916406, 'fraction_numerical': 0.009643016795453095, 'mean_word_length': 2.4095362508164597, 'pattern_counts': {'":': 0, '<': 155, '<?xml version=': 0, '>': 155, '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': '5078746', 'n_tokens_mistral': 4839, 'n_tokens_neox': 4675, 'n_words': 983}