GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 8b35b9...c5c1a6 )
by Dmitry
01:05
created

Imagine.handle_request()   C

Complexity

Conditions 7

Size

Total Lines 34

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 7
dl 0
loc 34
rs 5.5
1
"""
2
Flask Imagine extension.
3
"""
4
import logging
5
6
from StringIO import StringIO
7
from flask import current_app, abort, redirect
8
9
from .adapters import ImagineFilesystemAdapter
10
from .filters import *
11
from .helpers.regex_route import RegexConverter
12
13
LOGGER = logging.getLogger(__file__)
14
15
16
class Imagine(object):
17
    """
18
    Flask Imagine extension
19
    """
20
    adapters = {
21
        'fs': ImagineFilesystemAdapter
22
    }
23
    filters = {
24
        'autorotate': AutorotateFilter,
25
        'crop': CropFilter,
26
        'downscale': DownscaleFilter,
27
        'relative_resize': RelativeResizeFilter,
28
        'rotate': RotateFilter,
29
        'thumbnail': ThumbnailFilter,
30
        'upscale': UpscaleFilter,
31
        'watermark': WatermarkFilter
32
    }
33
34
    filter_sets = {}
35
    adapter = None
36
    redirect_code = 302
37
38
    def __init__(self, app=None):
39
        """
40
        :param app: Flask application
41
        """
42
        if app is not None:
43
            self.init_app(app)
44
45
    def init_app(self, app):
46
        """
47
        :param app: Flask application
48
        """
49
        if not hasattr(app, 'extensions'):  # pragma: no cover
50
            app.extensions = {}
51
        app.extensions['imagine'] = self
52
53
        self._set_defaults(app)
54
55
        self.redirect_code = app.config['IMAGINE_CACHE_REDIRECT_CODE']
56
57
        if isinstance(app.config['IMAGINE_ADAPTERS'], dict):
58
            self.adapters.update(app.config['IMAGINE_ADAPTERS'])
59
        if isinstance(app.config['IMAGINE_FILTERS'], dict):
60
            self.filters.update(app.config['IMAGINE_FILTERS'])
61
62
        self._handle_adapter(app)
63
        self._handle_filter_sets(app)
64
65
        self._add_url_rule(app)
66
67
    @classmethod
68
    def _set_defaults(cls, app):
69
        """
70
        Set default configuration parameters
71
        :param app: Flask application
72
        :return: Flask application
73
        """
74
        app.config.setdefault('IMAGINE_URL', '/media/cache/resolve')
75
        app.config.setdefault('IMAGINE_NAME', 'imagine')
76
        app.config.setdefault('IMAGINE_CACHE_ENABLED', True)
77
        app.config.setdefault('IMAGINE_CACHE_REDIRECT_CODE', 302)
78
79
        app.config.setdefault('IMAGINE_ADAPTERS', {})
80
        app.config.setdefault('IMAGINE_FILTERS', {})
81
82
        app.config.setdefault('IMAGINE_ADAPTER', {
83
            'name': 'fs',
84
        })
85
86
        app.config.setdefault('IMAGINE_FILTER_SETS', {})
87
88
        return app
89
90
    def _handle_adapter(self, app):
91
        """
92
        Handle storage adapter configuration
93
        :param app: Flask application
94
        """
95
        if 'IMAGINE_ADAPTER' in app.config \
96
                and 'name' in app.config['IMAGINE_ADAPTER'] \
97
                and app.config['IMAGINE_ADAPTER']['name'] in self.adapters.keys():
98
            self.adapter = self.adapters[app.config['IMAGINE_ADAPTER']['name']](
99
                **app.config['IMAGINE_ADAPTER']
100
            )
101
        else:
102
            raise ValueError('Unknown adapter: %s' % unicode(app.config['IMAGINE_ADAPTER']))
103
104
    def _handle_filter_sets(self, app):
105
        """
106
        Handle filter sets
107
        :param app: Flask application
108
        """
109
        if 'IMAGINE_FILTER_SETS' in app.config and isinstance(app.config['IMAGINE_FILTER_SETS'], dict):
110
            for filter_name, filters_settings in app.config['IMAGINE_FILTER_SETS'].iteritems():
111
                filter_set = []
112
                if isinstance(filters_settings, dict) and 'filters' in filters_settings:
113
                    for filter_type, filter_settings in filters_settings['filters'].iteritems():
114
                        if filter_type in self.filters:
115
                            filter_item = self.filters[filter_type](**filter_settings)
116
                            if isinstance(filter_item, ImagineFilterInterface):
117
                                filter_set.append(filter_item)
118
                            else:
119
                                raise ValueError('Filter must be implement ImagineFilterInterface')
120
                        else:
121
                            raise ValueError('Unknown filter type: %s' % filter_type)
122
123
                    filter_config = {'filters': filter_set}
124
                    if 'cached' in filters_settings:
125
                        filter_config['cached'] = filters_settings['cached']
126
                    else:
127
                        filter_config['cached'] = app.config['IMAGINE_CACHE_ENABLED']
128
129
                    self.filter_sets.update({filter_name: filter_config})
130
                else:
131
                    raise ValueError('Wrong settings for filter: %s' % filter_name)
132
        else:
133
            raise ValueError('Filters configuration does not present')
134
135
    def _add_url_rule(self, app):
136
        """
137
        Add url rule for get filtered images
138
        :param app: Flask application
139
        :return: Flask application
140
        """
141
        app.url_map.converters['regex'] = RegexConverter
142
        app.add_url_rule(
143
            app.config['IMAGINE_URL'] + '/<regex("[^\/]+"):filter_name>/<path:path>',
144
            app.config['IMAGINE_NAME'],
145
            self.handle_request
146
        )
147
148
        return app
149
150
    def handle_request(self, filter_name, path):
151
        """
152
        Handle image request
153
        :param filter_name: filter_name
154
        :param path: image_path
155
        :return:
156
        """
157
        if filter_name in self.filter_sets:
158
            if self.filter_sets[filter_name]['cached']:
159
                cached_item_path = self.adapter.check_cached_item('%s/%s' % (filter_name, path))
160
                if cached_item_path:
161
                    return redirect(cached_item_path, self.redirect_code)
162
163
            resource = self.adapter.get_item(path)
164
165
            if resource:
166
                for filter_item in self.filter_sets[filter_name]['filters']:
167
                    resource = filter_item.apply(resource)
168
169
                if self.filter_sets[filter_name]['cached']:
170
                    return redirect(
171
                        self.adapter.create_cached_item('%s/%s' % (filter_name, path), resource),
172
                        self.redirect_code
173
                    )
174
                else:
175
                    output = StringIO()
176
                    resource.save(output, format=resource.format)
177
                    return output.getvalue()
178
            else:
179
                LOGGER.warning('File "%s" not found.' % path)
180
                abort(404)
181
        else:
182
            LOGGER.warning('Filter "%s" not found.' % filter_name)
183
            abort(404)
184
185
    def clear_cache(self, path, filter_name=None):
186
        """
187
        Clear cache for resource path.
188
        :param path: str
189
        :param filter_name: str or None
190
        """
191
        if filter_name:
192
            self.adapter.remove_cached_item('%s/%s' % (filter_name, path))
193
        else:
194
            for filter_name in self.filter_sets.iterkeys():
195
                self.adapter.remove_cached_item('%s/%s' % (filter_name, path))
196
197
198
def imagine_cache_clear(path, filter_name=None):
199
    """
200
    Clear cache for resource path.
201
    :param path: str
202
    :param filter_name: str or None
203
    """
204
    self = current_app.extensions['imagine']
205
    self.clear_cache(path, filter_name)
206