_parse_settings()   C
last analyzed

Complexity

Conditions 9

Size

Total Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 9
c 1
b 0
f 0
dl 0
loc 34
rs 6.6666
1
# -*- coding: utf-8 -*-
2
3
import logging
4
import os
5
from collections import Sequence
6
7
from crabpy.client import crab_factory
8
from crabpy.gateway.capakey import CapakeyRestGateway
9
from crabpy.gateway.crab import CrabGateway
10
from pyramid.config import Configurator
11
from pyramid.settings import asbool
12
from zope.interface import Interface
13
14
from crabpy_pyramid.renderers.capakey import (
15
    json_list_renderer as capakey_json_list_renderer,
16
    json_item_renderer as capakey_json_item_renderer
17
)
18
from crabpy_pyramid.renderers.crab import (
19
    json_list_renderer as crab_json_list_renderer,
20
    json_item_renderer as crab_json_item_renderer
21
)
22
23
log = logging.getLogger(__name__)
24
25
26
class ICapakey(Interface):
27
    pass
28
29
30
class ICrab(Interface):
31
    pass
32
33
34
def _parse_settings(settings):
35
    defaults = {
36
        'capakey.include': False,
37
        'crab.include': True,
38
        'cache.file.root': '/tmp/dogpile_data'
39
    }
40
    args = defaults.copy()
41
42
    # booelean settings
43
    for short_key_name in ('capakey.include', 'crab.include'):
44
        key_name = "crabpy.%s" % short_key_name
45
        if key_name in settings:
46
            args[short_key_name] = asbool(settings.get(
47
                key_name, defaults.get(short_key_name)
48
            ))
49
50
    # string setting
51
    for short_key_name in ('proxy.http', 'proxy.https', 'cache.file.root'):
52
        key_name = "crabpy.%s" % short_key_name
53
        if key_name in settings:
54
            args[short_key_name] = settings.get(key_name)
55
56
    # cache configuration
57
    for short_key_name in ('crab.cache_config', 'capakey.cache_config'):
58
        key_name = "crabpy.%s." % short_key_name
59
        cache_config = {}
60
        for skey in settings.keys():
61
            if skey.startswith(key_name):
62
                cache_config[skey[len(key_name):]] = settings.get(skey)
63
        if cache_config:
64
            args[short_key_name] = cache_config
65
66
    log.debug(args)
67
    return args
68
69
70
def _filter_settings(settings, prefix):
71
    """
72
    Filter all settings to only return settings that start with a certain
73
    prefix.
74
75
    :param dict settings: A settings dictionary.
76
    :param str prefix: A prefix.
77
    """
78
    ret = {}
79
    for skey in settings.keys():
80
        if skey.startswith(prefix):
81
            key = skey[len(prefix):]
82
            ret[key] = settings[skey]
83
    return ret
84
85
86
def _build_capakey(registry, settings):
87
    capakey = registry.queryUtility(ICapakey)
88
    if capakey is not None:
89
        return capakey
90
    if 'cache_config' in settings:
91
        cache_config = settings['cache_config']
92
        del settings['cache_config']
93
    else:
94
        cache_config = {}
95
    gateway = CapakeyRestGateway(cache_config=cache_config)
96
97
    registry.registerUtility(gateway, ICapakey)
98
    return registry.queryUtility(ICapakey)
99
100
101
def _build_crab(registry, settings):
102
    crab = registry.queryUtility(ICrab)
103
    if crab is not None:
104
        return crab
105
    if 'cache_config' in settings:
106
        cache_config = settings['cache_config']
107
        del settings['cache_config']
108
    else:
109
        cache_config = {}
110
    factory = crab_factory(**settings)
111
    gateway = CrabGateway(factory, cache_config=cache_config)
112
113
    registry.registerUtility(gateway, ICrab)
114
    return registry.queryUtility(ICapakey)
115
116
117
def get_capakey(registry):
118
    """
119
    Get the Capakey Gateway
120
121
    :rtype: :class:`crabpy.gateway.capakey.CapakeyRestGateway`
122
    """
123
    # argument might be a config or a request
124
    regis = getattr(registry, 'registry', None)
125
    if regis is None:
126
        regis = registry
127
128
    return regis.queryUtility(ICapakey)
129
130
131
def get_crab(registry):
132
    """
133
    Get the Crab Gateway
134
135
    :rtype: :class:`crabpy.gateway.crab.CrabGateway`
136
    # argument might be a config or a request
137
    """
138
    # argument might be a config or a request
139
    regis = getattr(registry, 'registry', None)
140
    if regis is None:
141
        regis = registry
142
143
    return regis.queryUtility(ICrab)
144
145
146
def _get_proxy_settings(settings):
147
    base_settings = {}
148
    http = settings.get('proxy.http', None)
149
    https = settings.get('proxy.https', None)
150
    if (http or https):
151
        base_settings["proxy"] = {}
152
        if "proxy.http" in settings:
153
            base_settings["proxy"]["http"] = settings["proxy.http"]
154
            log.info('HTTP proxy: %s' % base_settings["proxy"]["http"])
155
        if "proxy.https" in settings:
156
            base_settings["proxy"]["https"] = settings["proxy.https"]
157
            log.info('HTTPS proxy: %s' % base_settings["proxy"]["https"])
158
    return base_settings
159
160
161
def conditional_http_tween_factory(handler, registry):
162
    """
163
    Tween that adds ETag headers and tells Pyramid to enable 
164
    conditional responses where appropriate.
165
    """
166
    settings = registry.settings if hasattr(registry, 'settings') else {}
167
    not_cacheble_list = []
168
    if 'not.cachable.list' in settings:
169
        not_cacheble_list = settings.get('not.cachable.list').split()
170
171
    def conditional_http_tween(request):
172
        response = handler(request)
173
174
        if request.path not in not_cacheble_list:
175
176
            # If the Last-Modified header has been set, we want to enable the
177
            # conditional response processing.
178
            if response.last_modified is not None:
179
                response.conditional_response = True
180
181
            # We want to only enable the conditional machinery if either we
182
            # were given an explicit ETag header by the view or we have a
183
            # buffered response and can generate the ETag header ourself.
184
            if response.etag is not None:
185
                response.conditional_response = True
186
            elif (isinstance(response.app_iter, Sequence) and
187
                          len(response.app_iter) == 1) and response.body is not None:
188
                response.conditional_response = True
189
                response.md5_etag()
190
191
        return response
192
193
    return conditional_http_tween
194
195
196
def includeme(config):
197
    """
198
    Include `crabpy_pyramid` in this `Pyramid` application.
199
200
    :param pyramid.config.Configurator config: A Pyramid configurator.
201
    """
202
203
    settings = _parse_settings(config.registry.settings)
204
    base_settings = _get_proxy_settings(settings)
205
206
    # http caching tween
207
    config.add_tween('crabpy_pyramid.conditional_http_tween_factory')
208
209
    # create cache
210
    root = settings.get('cache.file.root', '/tmp/dogpile_data')
211
    if not os.path.exists(root):
212
        os.makedirs(root)
213
214
    capakey_settings = dict(_filter_settings(settings, 'capakey.'), **base_settings)
215
    if capakey_settings['include']:
216
        log.info('Adding CAPAKEY Gateway.')
217
        del capakey_settings['include']
218
        config.add_renderer('capakey_listjson', capakey_json_list_renderer)
219
        config.add_renderer('capakey_itemjson', capakey_json_item_renderer)
220
        _build_capakey(config.registry, capakey_settings)
221
        config.add_request_method(get_capakey, 'capakey_gateway')
222
        config.add_directive('get_capakey', get_capakey)
223
        config.include('crabpy_pyramid.routes.capakey')
224
        config.scan('crabpy_pyramid.views.capakey')
225
226
    crab_settings = dict(_filter_settings(settings, 'crab.'), **base_settings)
227
    if crab_settings['include']:
228
        log.info('Adding CRAB Gateway.')
229
        del crab_settings['include']
230
        config.add_renderer('crab_listjson', crab_json_list_renderer)
231
        config.add_renderer('crab_itemjson', crab_json_item_renderer)
232
        _build_crab(config.registry, crab_settings)
233
        config.add_directive('get_crab', get_crab)
234
        config.add_request_method(get_crab, 'crab_gateway')
235
        config.include('crabpy_pyramid.routes.crab')
236
        config.scan('crabpy_pyramid.views.crab')
237
238
239
def main(global_config, **settings):
240
    """
241
     This function returns a Pyramid WSGI application.
242
    """
243
    config = Configurator(settings=settings)
244
245
    includeme(config)
246
    return config.make_wsgi_app()
247