Completed
Push — master ( abd5fe...1e5f43 )
by Bart
14s
created

validate_params()   A

Complexity

Conditions 3

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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