Completed
Push — master ( ddc962...ab2a47 )
by
unknown
49s queued 25s
created

get_valid_params()   A

Complexity

Conditions 1

Size

Total Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
c 0
b 0
f 0
dl 0
loc 2
rs 10
1
# -*- coding: utf-8 -*-
2
from math import ceil
3
4
from pyramid.httpexceptions import HTTPBadRequest
5
from webob.multidict import MultiDict
6
7
8
def validate_params(params, valid_keys, fail_on_invalid_key=True):
9
    p = MultiDict()
10
    for k, v in params.items():
11
        if k in valid_keys:
12
            p.add(k, v)
13
        elif fail_on_invalid_key:
14
            raise HTTPBadRequest('invalid search parameter')
15
    return p
16
17
18
def get_valid_params(params, valid_keys):
19
    return validate_params(params, valid_keys, fail_on_invalid_key=False)
20
21
22
def parse_sort_string(sort):
23
    """
24
    Parse a sort string for use with elasticsearch
25
26
    :param: sort: the sort string
27
    """
28
    if sort is None:
29
        return ['_score']
30
    l = sort.rsplit(',')
31
    sortlist = []
32
    for se in l:
33
        se = se.strip()
34
        order = 'desc' if se[0:1] == '-' else 'asc'
35
        field = se[1:] if se[0:1] in ['-', '+'] else se
36
        field = field.strip()
37
        sortlist.append({field: {"order": order, "unmapped_type": "string", "missing": "_last"}})
38
    sortlist.append('_score')
39
    return sortlist
40
41
42
def parse_filter_params(query_params, filterable):
43
    """
44
    Parse query_params to a filter params dict. Merge multiple values for one key to a list.
45
    Filter out keys that aren't filterable.
46
47
    :param query_params: query params
48
    :param filterable: list of filterable keys
49
    :return: dict of filter values
50
    """
51
    if query_params is not None:
52
        filter_params = {}
53
        for fq in query_params.mixed():
54
            if fq in filterable:
55
                filter_params[fq] = query_params.mixed().get(fq)
56
        return filter_params
57
    else:
58
        return {}
59
60
61
class SearchResultPager(object):
62
    """based on http://atlas-core.readthedocs.org/en/latest/_modules/flask_sqlalchemy.html Pagination"""
63
64
    def __init__(self, page, per_page, total_count):
65
        self.page = page
66
        self.per_page = per_page
67
        self.total_count = total_count
68
69
    @property
70
    def pages(self):
71
        return int(ceil(self.total_count / float(self.per_page)))
72
73
    @property
74
    def has_prev(self):
75
        return self.page > 1
76
77
    @property
78
    def prev(self):
79
        return self.page - 1 if self.has_prev else None
80
81
    @property
82
    def has_next(self):
83
        return self.page < self.pages
84
85
    @property
86
    def next(self):
87
        return self.page + 1 if self.has_next else None
88
89
    def iter_pages(
90
            self, left_edge=2, left_current=2,
91
            right_current=5, right_edge=2
92
    ):
93
        """Iterates over the page numbers in the pagination.  The four
94
        parameters control the thresholds how many numbers should be produced
95
        from the sides.  Skipped page numbers are represented as `None`.
96
        """
97
        last = 0
98
        try:
99
            xrange
100
        except NameError:
101
            xrange = range
102
        for num in xrange(1, self.pages + 1):
103
            if (
104
                                num <= left_edge or
105
                            (self.page - left_current - 1 < num < self.page + right_current)
106
                    or num > self.pages - right_edge
107
            ):
108
                if last + 1 != num:
109
                    yield None
110
                yield num
111
                last = num
112