Completed
Push — master ( 78cb2b...87b508 )
by
unknown
01:41
created

Range.parse()   B

Complexity

Conditions 6

Size

Total Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 6
c 1
b 0
f 1
dl 0
loc 30
rs 7.5384
1
# -*- coding: utf-8 -*-
2
3
import re
4
5
6
class RangeParseException(Exception):
7
    '''
8
    Used for handling errors during range parsing
9
    '''
10
    pass
11
12
13
class Range(object):
14
    def __init__(self, start, end, page=1):
15
        self.start = start
16
        self.end = end
17
        self.page = page
18
19
    def get_page_size(self):
20
        '''
21
22
        :return: the size of a page
23
        '''
24
        return self.end - self.start + 1
25
26
    def content_range(self, length):
27
        '''
28
29
        :param length: the total number of results
30
        :return: range header string
31
        '''
32
        end = self.end if self.end <= length else length - 1
33
        return 'items %d-%d/%d' % (self.start, end, length)
34
35
    @classmethod
36
    def parse(cls, request, default_start=0, default_end=11):
37
        '''
38
        Parse the range headers into a range object. When there are no range headers,
39
        check for a page 'pagina' parameter, otherwise use the defaults defaults
40
41
        :param request: a request object
42
        :param default_start: default start for  paging (optional, default is 0)
43
        :param default_end: default end for paging (optional, default is 11)
44
        :return: :class: 'oe_utils.range_parser.Range'
45
        '''
46
        if 'Range' in request.headers and request.headers['Range'] is not '':
47
            match = re.match('^items=([0-9]+)-([0-9]+)$', request.headers['Range'])
48
49
            if match:
50
                start = int(match.group(1))
51
                end = int(match.group(2))
52
53
                if end < start:
54
                    end = start
55
                return cls(start, end)
56
            else:
57
                raise RangeParseException('range header does not match expected format')
58
        elif 'pagina' in request.params:
59
            page = int(request.params.get('pagina'))
60
            start = default_start + (default_end + 1) * (page - 1)
61
            end = default_end * page + page - 1
62
            return cls(start, end, page)
63
        else:
64
            return cls(default_start, default_end)
65
66
    def set_response_headers(self, response, total_count):
67
        '''
68
        Set the correct range headers on the response
69
70
        :param response: a response object
71
        :param total_count: the total number of results
72
        '''
73
        response.headerlist.append(('Access-Control-Expose-Headers', 'Content-Range, X-Content-Range'))
74
        response.accept_ranges = 'items'
75
        if total_count is None:
76
            raise RangeParseException('Provided length value is null')
77
        if total_count > 0:
78
            response.content_range = self.content_range(total_count)
79