##// END OF EJS Templates
configuration: Allows to use format style "{ENV_NAME}" placeholders in the configuration.
marcink -
r2818:4e04a411 default
parent child Browse files
Show More
@@ -1,440 +1,460 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2018 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import os
21 import logging
22 import logging
22 import traceback
23 import traceback
23 import collections
24 import collections
24
25
25 from paste.gzipper import make_gzip_middleware
26 from paste.gzipper import make_gzip_middleware
26 from pyramid.wsgi import wsgiapp
27 from pyramid.wsgi import wsgiapp
27 from pyramid.authorization import ACLAuthorizationPolicy
28 from pyramid.authorization import ACLAuthorizationPolicy
28 from pyramid.config import Configurator
29 from pyramid.config import Configurator
29 from pyramid.settings import asbool, aslist
30 from pyramid.settings import asbool, aslist
30 from pyramid.httpexceptions import (
31 from pyramid.httpexceptions import (
31 HTTPException, HTTPError, HTTPInternalServerError, HTTPFound, HTTPNotFound)
32 HTTPException, HTTPError, HTTPInternalServerError, HTTPFound, HTTPNotFound)
32 from pyramid.events import ApplicationCreated
33 from pyramid.events import ApplicationCreated
33 from pyramid.renderers import render_to_response
34 from pyramid.renderers import render_to_response
34
35
35 from rhodecode.model import meta
36 from rhodecode.model import meta
36 from rhodecode.config import patches
37 from rhodecode.config import patches
37 from rhodecode.config import utils as config_utils
38 from rhodecode.config import utils as config_utils
38 from rhodecode.config.environment import load_pyramid_environment
39 from rhodecode.config.environment import load_pyramid_environment
39
40
40 from rhodecode.lib.middleware.vcs import VCSMiddleware
41 from rhodecode.lib.middleware.vcs import VCSMiddleware
41 from rhodecode.lib.request import Request
42 from rhodecode.lib.request import Request
42 from rhodecode.lib.vcs import VCSCommunicationError
43 from rhodecode.lib.vcs import VCSCommunicationError
43 from rhodecode.lib.exceptions import VCSServerUnavailable
44 from rhodecode.lib.exceptions import VCSServerUnavailable
44 from rhodecode.lib.middleware.appenlight import wrap_in_appenlight_if_enabled
45 from rhodecode.lib.middleware.appenlight import wrap_in_appenlight_if_enabled
45 from rhodecode.lib.middleware.https_fixup import HttpsFixup
46 from rhodecode.lib.middleware.https_fixup import HttpsFixup
46 from rhodecode.lib.celerylib.loader import configure_celery
47 from rhodecode.lib.celerylib.loader import configure_celery
47 from rhodecode.lib.plugins.utils import register_rhodecode_plugin
48 from rhodecode.lib.plugins.utils import register_rhodecode_plugin
48 from rhodecode.lib.utils2 import aslist as rhodecode_aslist, AttributeDict
49 from rhodecode.lib.utils2 import aslist as rhodecode_aslist, AttributeDict
49 from rhodecode.subscribers import (
50 from rhodecode.subscribers import (
50 scan_repositories_if_enabled, write_js_routes_if_enabled,
51 scan_repositories_if_enabled, write_js_routes_if_enabled,
51 write_metadata_if_needed, inject_app_settings)
52 write_metadata_if_needed, inject_app_settings)
52
53
53
54
54 log = logging.getLogger(__name__)
55 log = logging.getLogger(__name__)
55
56
56
57
57 def is_http_error(response):
58 def is_http_error(response):
58 # error which should have traceback
59 # error which should have traceback
59 return response.status_code > 499
60 return response.status_code > 499
60
61
61
62
62 def make_pyramid_app(global_config, **settings):
63 def make_pyramid_app(global_config, **settings):
63 """
64 """
64 Constructs the WSGI application based on Pyramid.
65 Constructs the WSGI application based on Pyramid.
65
66
66 Specials:
67 Specials:
67
68
68 * The application can also be integrated like a plugin via the call to
69 * The application can also be integrated like a plugin via the call to
69 `includeme`. This is accompanied with the other utility functions which
70 `includeme`. This is accompanied with the other utility functions which
70 are called. Changing this should be done with great care to not break
71 are called. Changing this should be done with great care to not break
71 cases when these fragments are assembled from another place.
72 cases when these fragments are assembled from another place.
72
73
73 """
74 """
75
76 # Allows to use format style "{ENV_NAME}" placeholders in the configuration. It
77 # will be replaced by the value of the environment variable "NAME" in this case.
78 environ = {
79 'ENV_{}'.format(key): value for key, value in os.environ.items()}
80
81 global_config = _substitute_values(global_config, environ)
82 settings = _substitute_values(settings, environ)
83
74 sanitize_settings_and_apply_defaults(settings)
84 sanitize_settings_and_apply_defaults(settings)
75
85
76 config = Configurator(settings=settings)
86 config = Configurator(settings=settings)
77
87
78 # Apply compatibility patches
88 # Apply compatibility patches
79 patches.inspect_getargspec()
89 patches.inspect_getargspec()
80
90
81 load_pyramid_environment(global_config, settings)
91 load_pyramid_environment(global_config, settings)
82
92
83 # Static file view comes first
93 # Static file view comes first
84 includeme_first(config)
94 includeme_first(config)
85
95
86 includeme(config)
96 includeme(config)
87
97
88 pyramid_app = config.make_wsgi_app()
98 pyramid_app = config.make_wsgi_app()
89 pyramid_app = wrap_app_in_wsgi_middlewares(pyramid_app, config)
99 pyramid_app = wrap_app_in_wsgi_middlewares(pyramid_app, config)
90 pyramid_app.config = config
100 pyramid_app.config = config
91
101
92 config.configure_celery(global_config['__file__'])
102 config.configure_celery(global_config['__file__'])
93 # creating the app uses a connection - return it after we are done
103 # creating the app uses a connection - return it after we are done
94 meta.Session.remove()
104 meta.Session.remove()
95
105
96 log.info('Pyramid app %s created and configured.', pyramid_app)
106 log.info('Pyramid app %s created and configured.', pyramid_app)
97 return pyramid_app
107 return pyramid_app
98
108
99
109
100 def not_found_view(request):
110 def not_found_view(request):
101 """
111 """
102 This creates the view which should be registered as not-found-view to
112 This creates the view which should be registered as not-found-view to
103 pyramid.
113 pyramid.
104 """
114 """
105
115
106 if not getattr(request, 'vcs_call', None):
116 if not getattr(request, 'vcs_call', None):
107 # handle like regular case with our error_handler
117 # handle like regular case with our error_handler
108 return error_handler(HTTPNotFound(), request)
118 return error_handler(HTTPNotFound(), request)
109
119
110 # handle not found view as a vcs call
120 # handle not found view as a vcs call
111 settings = request.registry.settings
121 settings = request.registry.settings
112 ae_client = getattr(request, 'ae_client', None)
122 ae_client = getattr(request, 'ae_client', None)
113 vcs_app = VCSMiddleware(
123 vcs_app = VCSMiddleware(
114 HTTPNotFound(), request.registry, settings,
124 HTTPNotFound(), request.registry, settings,
115 appenlight_client=ae_client)
125 appenlight_client=ae_client)
116
126
117 return wsgiapp(vcs_app)(None, request)
127 return wsgiapp(vcs_app)(None, request)
118
128
119
129
120 def error_handler(exception, request):
130 def error_handler(exception, request):
121 import rhodecode
131 import rhodecode
122 from rhodecode.lib import helpers
132 from rhodecode.lib import helpers
123
133
124 rhodecode_title = rhodecode.CONFIG.get('rhodecode_title') or 'RhodeCode'
134 rhodecode_title = rhodecode.CONFIG.get('rhodecode_title') or 'RhodeCode'
125
135
126 base_response = HTTPInternalServerError()
136 base_response = HTTPInternalServerError()
127 # prefer original exception for the response since it may have headers set
137 # prefer original exception for the response since it may have headers set
128 if isinstance(exception, HTTPException):
138 if isinstance(exception, HTTPException):
129 base_response = exception
139 base_response = exception
130 elif isinstance(exception, VCSCommunicationError):
140 elif isinstance(exception, VCSCommunicationError):
131 base_response = VCSServerUnavailable()
141 base_response = VCSServerUnavailable()
132
142
133 if is_http_error(base_response):
143 if is_http_error(base_response):
134 log.exception(
144 log.exception(
135 'error occurred handling this request for path: %s', request.path)
145 'error occurred handling this request for path: %s', request.path)
136
146
137 error_explanation = base_response.explanation or str(base_response)
147 error_explanation = base_response.explanation or str(base_response)
138 if base_response.status_code == 404:
148 if base_response.status_code == 404:
139 error_explanation += " Or you don't have permission to access it."
149 error_explanation += " Or you don't have permission to access it."
140 c = AttributeDict()
150 c = AttributeDict()
141 c.error_message = base_response.status
151 c.error_message = base_response.status
142 c.error_explanation = error_explanation
152 c.error_explanation = error_explanation
143 c.visual = AttributeDict()
153 c.visual = AttributeDict()
144
154
145 c.visual.rhodecode_support_url = (
155 c.visual.rhodecode_support_url = (
146 request.registry.settings.get('rhodecode_support_url') or
156 request.registry.settings.get('rhodecode_support_url') or
147 request.route_url('rhodecode_support')
157 request.route_url('rhodecode_support')
148 )
158 )
149 c.redirect_time = 0
159 c.redirect_time = 0
150 c.rhodecode_name = rhodecode_title
160 c.rhodecode_name = rhodecode_title
151 if not c.rhodecode_name:
161 if not c.rhodecode_name:
152 c.rhodecode_name = 'Rhodecode'
162 c.rhodecode_name = 'Rhodecode'
153
163
154 c.causes = []
164 c.causes = []
155 if is_http_error(base_response):
165 if is_http_error(base_response):
156 c.causes.append('Server is overloaded.')
166 c.causes.append('Server is overloaded.')
157 c.causes.append('Server database connection is lost.')
167 c.causes.append('Server database connection is lost.')
158 c.causes.append('Server expected unhandled error.')
168 c.causes.append('Server expected unhandled error.')
159
169
160 if hasattr(base_response, 'causes'):
170 if hasattr(base_response, 'causes'):
161 c.causes = base_response.causes
171 c.causes = base_response.causes
162
172
163 c.messages = helpers.flash.pop_messages(request=request)
173 c.messages = helpers.flash.pop_messages(request=request)
164 c.traceback = traceback.format_exc()
174 c.traceback = traceback.format_exc()
165 response = render_to_response(
175 response = render_to_response(
166 '/errors/error_document.mako', {'c': c, 'h': helpers}, request=request,
176 '/errors/error_document.mako', {'c': c, 'h': helpers}, request=request,
167 response=base_response)
177 response=base_response)
168
178
169 return response
179 return response
170
180
171
181
172 def includeme_first(config):
182 def includeme_first(config):
173 # redirect automatic browser favicon.ico requests to correct place
183 # redirect automatic browser favicon.ico requests to correct place
174 def favicon_redirect(context, request):
184 def favicon_redirect(context, request):
175 return HTTPFound(
185 return HTTPFound(
176 request.static_path('rhodecode:public/images/favicon.ico'))
186 request.static_path('rhodecode:public/images/favicon.ico'))
177
187
178 config.add_view(favicon_redirect, route_name='favicon')
188 config.add_view(favicon_redirect, route_name='favicon')
179 config.add_route('favicon', '/favicon.ico')
189 config.add_route('favicon', '/favicon.ico')
180
190
181 def robots_redirect(context, request):
191 def robots_redirect(context, request):
182 return HTTPFound(
192 return HTTPFound(
183 request.static_path('rhodecode:public/robots.txt'))
193 request.static_path('rhodecode:public/robots.txt'))
184
194
185 config.add_view(robots_redirect, route_name='robots')
195 config.add_view(robots_redirect, route_name='robots')
186 config.add_route('robots', '/robots.txt')
196 config.add_route('robots', '/robots.txt')
187
197
188 config.add_static_view(
198 config.add_static_view(
189 '_static/deform', 'deform:static')
199 '_static/deform', 'deform:static')
190 config.add_static_view(
200 config.add_static_view(
191 '_static/rhodecode', path='rhodecode:public', cache_max_age=3600 * 24)
201 '_static/rhodecode', path='rhodecode:public', cache_max_age=3600 * 24)
192
202
193
203
194 def includeme(config):
204 def includeme(config):
195 settings = config.registry.settings
205 settings = config.registry.settings
196 config.set_request_factory(Request)
206 config.set_request_factory(Request)
197
207
198 # plugin information
208 # plugin information
199 config.registry.rhodecode_plugins = collections.OrderedDict()
209 config.registry.rhodecode_plugins = collections.OrderedDict()
200
210
201 config.add_directive(
211 config.add_directive(
202 'register_rhodecode_plugin', register_rhodecode_plugin)
212 'register_rhodecode_plugin', register_rhodecode_plugin)
203
213
204 config.add_directive('configure_celery', configure_celery)
214 config.add_directive('configure_celery', configure_celery)
205
215
206 if asbool(settings.get('appenlight', 'false')):
216 if asbool(settings.get('appenlight', 'false')):
207 config.include('appenlight_client.ext.pyramid_tween')
217 config.include('appenlight_client.ext.pyramid_tween')
208
218
209 # Includes which are required. The application would fail without them.
219 # Includes which are required. The application would fail without them.
210 config.include('pyramid_mako')
220 config.include('pyramid_mako')
211 config.include('pyramid_beaker')
221 config.include('pyramid_beaker')
212 config.include('rhodecode.lib.caches')
222 config.include('rhodecode.lib.caches')
213
223
214 config.include('rhodecode.authentication')
224 config.include('rhodecode.authentication')
215 config.include('rhodecode.integrations')
225 config.include('rhodecode.integrations')
216
226
217 # apps
227 # apps
218 config.include('rhodecode.apps._base')
228 config.include('rhodecode.apps._base')
219 config.include('rhodecode.apps.ops')
229 config.include('rhodecode.apps.ops')
220
230
221 config.include('rhodecode.apps.admin')
231 config.include('rhodecode.apps.admin')
222 config.include('rhodecode.apps.channelstream')
232 config.include('rhodecode.apps.channelstream')
223 config.include('rhodecode.apps.login')
233 config.include('rhodecode.apps.login')
224 config.include('rhodecode.apps.home')
234 config.include('rhodecode.apps.home')
225 config.include('rhodecode.apps.journal')
235 config.include('rhodecode.apps.journal')
226 config.include('rhodecode.apps.repository')
236 config.include('rhodecode.apps.repository')
227 config.include('rhodecode.apps.repo_group')
237 config.include('rhodecode.apps.repo_group')
228 config.include('rhodecode.apps.user_group')
238 config.include('rhodecode.apps.user_group')
229 config.include('rhodecode.apps.search')
239 config.include('rhodecode.apps.search')
230 config.include('rhodecode.apps.user_profile')
240 config.include('rhodecode.apps.user_profile')
231 config.include('rhodecode.apps.user_group_profile')
241 config.include('rhodecode.apps.user_group_profile')
232 config.include('rhodecode.apps.my_account')
242 config.include('rhodecode.apps.my_account')
233 config.include('rhodecode.apps.svn_support')
243 config.include('rhodecode.apps.svn_support')
234 config.include('rhodecode.apps.ssh_support')
244 config.include('rhodecode.apps.ssh_support')
235 config.include('rhodecode.apps.gist')
245 config.include('rhodecode.apps.gist')
236
246
237 config.include('rhodecode.apps.debug_style')
247 config.include('rhodecode.apps.debug_style')
238 config.include('rhodecode.tweens')
248 config.include('rhodecode.tweens')
239 config.include('rhodecode.api')
249 config.include('rhodecode.api')
240
250
241 config.add_route(
251 config.add_route(
242 'rhodecode_support', 'https://rhodecode.com/help/', static=True)
252 'rhodecode_support', 'https://rhodecode.com/help/', static=True)
243
253
244 config.add_translation_dirs('rhodecode:i18n/')
254 config.add_translation_dirs('rhodecode:i18n/')
245 settings['default_locale_name'] = settings.get('lang', 'en')
255 settings['default_locale_name'] = settings.get('lang', 'en')
246
256
247 # Add subscribers.
257 # Add subscribers.
248 config.add_subscriber(inject_app_settings, ApplicationCreated)
258 config.add_subscriber(inject_app_settings, ApplicationCreated)
249 config.add_subscriber(scan_repositories_if_enabled, ApplicationCreated)
259 config.add_subscriber(scan_repositories_if_enabled, ApplicationCreated)
250 config.add_subscriber(write_metadata_if_needed, ApplicationCreated)
260 config.add_subscriber(write_metadata_if_needed, ApplicationCreated)
251 config.add_subscriber(write_js_routes_if_enabled, ApplicationCreated)
261 config.add_subscriber(write_js_routes_if_enabled, ApplicationCreated)
252
262
253 # events
263 # events
254 # TODO(marcink): this should be done when pyramid migration is finished
264 # TODO(marcink): this should be done when pyramid migration is finished
255 # config.add_subscriber(
265 # config.add_subscriber(
256 # 'rhodecode.integrations.integrations_event_handler',
266 # 'rhodecode.integrations.integrations_event_handler',
257 # 'rhodecode.events.RhodecodeEvent')
267 # 'rhodecode.events.RhodecodeEvent')
258
268
259 # request custom methods
269 # request custom methods
260 config.add_request_method(
270 config.add_request_method(
261 'rhodecode.lib.partial_renderer.get_partial_renderer',
271 'rhodecode.lib.partial_renderer.get_partial_renderer',
262 'get_partial_renderer')
272 'get_partial_renderer')
263
273
264 # Set the authorization policy.
274 # Set the authorization policy.
265 authz_policy = ACLAuthorizationPolicy()
275 authz_policy = ACLAuthorizationPolicy()
266 config.set_authorization_policy(authz_policy)
276 config.set_authorization_policy(authz_policy)
267
277
268 # Set the default renderer for HTML templates to mako.
278 # Set the default renderer for HTML templates to mako.
269 config.add_mako_renderer('.html')
279 config.add_mako_renderer('.html')
270
280
271 config.add_renderer(
281 config.add_renderer(
272 name='json_ext',
282 name='json_ext',
273 factory='rhodecode.lib.ext_json_renderer.pyramid_ext_json')
283 factory='rhodecode.lib.ext_json_renderer.pyramid_ext_json')
274
284
275 # include RhodeCode plugins
285 # include RhodeCode plugins
276 includes = aslist(settings.get('rhodecode.includes', []))
286 includes = aslist(settings.get('rhodecode.includes', []))
277 for inc in includes:
287 for inc in includes:
278 config.include(inc)
288 config.include(inc)
279
289
280 # custom not found view, if our pyramid app doesn't know how to handle
290 # custom not found view, if our pyramid app doesn't know how to handle
281 # the request pass it to potential VCS handling ap
291 # the request pass it to potential VCS handling ap
282 config.add_notfound_view(not_found_view)
292 config.add_notfound_view(not_found_view)
283 if not settings.get('debugtoolbar.enabled', False):
293 if not settings.get('debugtoolbar.enabled', False):
284 # disabled debugtoolbar handle all exceptions via the error_handlers
294 # disabled debugtoolbar handle all exceptions via the error_handlers
285 config.add_view(error_handler, context=Exception)
295 config.add_view(error_handler, context=Exception)
286
296
287 # all errors including 403/404/50X
297 # all errors including 403/404/50X
288 config.add_view(error_handler, context=HTTPError)
298 config.add_view(error_handler, context=HTTPError)
289
299
290
300
291 def wrap_app_in_wsgi_middlewares(pyramid_app, config):
301 def wrap_app_in_wsgi_middlewares(pyramid_app, config):
292 """
302 """
293 Apply outer WSGI middlewares around the application.
303 Apply outer WSGI middlewares around the application.
294 """
304 """
295 settings = config.registry.settings
305 settings = config.registry.settings
296
306
297 # enable https redirects based on HTTP_X_URL_SCHEME set by proxy
307 # enable https redirects based on HTTP_X_URL_SCHEME set by proxy
298 pyramid_app = HttpsFixup(pyramid_app, settings)
308 pyramid_app = HttpsFixup(pyramid_app, settings)
299
309
300 pyramid_app, _ae_client = wrap_in_appenlight_if_enabled(
310 pyramid_app, _ae_client = wrap_in_appenlight_if_enabled(
301 pyramid_app, settings)
311 pyramid_app, settings)
302 config.registry.ae_client = _ae_client
312 config.registry.ae_client = _ae_client
303
313
304 if settings['gzip_responses']:
314 if settings['gzip_responses']:
305 pyramid_app = make_gzip_middleware(
315 pyramid_app = make_gzip_middleware(
306 pyramid_app, settings, compress_level=1)
316 pyramid_app, settings, compress_level=1)
307
317
308 # this should be the outer most middleware in the wsgi stack since
318 # this should be the outer most middleware in the wsgi stack since
309 # middleware like Routes make database calls
319 # middleware like Routes make database calls
310 def pyramid_app_with_cleanup(environ, start_response):
320 def pyramid_app_with_cleanup(environ, start_response):
311 try:
321 try:
312 return pyramid_app(environ, start_response)
322 return pyramid_app(environ, start_response)
313 finally:
323 finally:
314 # Dispose current database session and rollback uncommitted
324 # Dispose current database session and rollback uncommitted
315 # transactions.
325 # transactions.
316 meta.Session.remove()
326 meta.Session.remove()
317
327
318 # In a single threaded mode server, on non sqlite db we should have
328 # In a single threaded mode server, on non sqlite db we should have
319 # '0 Current Checked out connections' at the end of a request,
329 # '0 Current Checked out connections' at the end of a request,
320 # if not, then something, somewhere is leaving a connection open
330 # if not, then something, somewhere is leaving a connection open
321 pool = meta.Base.metadata.bind.engine.pool
331 pool = meta.Base.metadata.bind.engine.pool
322 log.debug('sa pool status: %s', pool.status())
332 log.debug('sa pool status: %s', pool.status())
323
333
324 return pyramid_app_with_cleanup
334 return pyramid_app_with_cleanup
325
335
326
336
327 def sanitize_settings_and_apply_defaults(settings):
337 def sanitize_settings_and_apply_defaults(settings):
328 """
338 """
329 Applies settings defaults and does all type conversion.
339 Applies settings defaults and does all type conversion.
330
340
331 We would move all settings parsing and preparation into this place, so that
341 We would move all settings parsing and preparation into this place, so that
332 we have only one place left which deals with this part. The remaining parts
342 we have only one place left which deals with this part. The remaining parts
333 of the application would start to rely fully on well prepared settings.
343 of the application would start to rely fully on well prepared settings.
334
344
335 This piece would later be split up per topic to avoid a big fat monster
345 This piece would later be split up per topic to avoid a big fat monster
336 function.
346 function.
337 """
347 """
338
348
339 settings.setdefault('rhodecode.edition', 'Community Edition')
349 settings.setdefault('rhodecode.edition', 'Community Edition')
340
350
341 if 'mako.default_filters' not in settings:
351 if 'mako.default_filters' not in settings:
342 # set custom default filters if we don't have it defined
352 # set custom default filters if we don't have it defined
343 settings['mako.imports'] = 'from rhodecode.lib.base import h_filter'
353 settings['mako.imports'] = 'from rhodecode.lib.base import h_filter'
344 settings['mako.default_filters'] = 'h_filter'
354 settings['mako.default_filters'] = 'h_filter'
345
355
346 if 'mako.directories' not in settings:
356 if 'mako.directories' not in settings:
347 mako_directories = settings.setdefault('mako.directories', [
357 mako_directories = settings.setdefault('mako.directories', [
348 # Base templates of the original application
358 # Base templates of the original application
349 'rhodecode:templates',
359 'rhodecode:templates',
350 ])
360 ])
351 log.debug(
361 log.debug(
352 "Using the following Mako template directories: %s",
362 "Using the following Mako template directories: %s",
353 mako_directories)
363 mako_directories)
354
364
355 # Default includes, possible to change as a user
365 # Default includes, possible to change as a user
356 pyramid_includes = settings.setdefault('pyramid.includes', [
366 pyramid_includes = settings.setdefault('pyramid.includes', [
357 'rhodecode.lib.middleware.request_wrapper',
367 'rhodecode.lib.middleware.request_wrapper',
358 ])
368 ])
359 log.debug(
369 log.debug(
360 "Using the following pyramid.includes: %s",
370 "Using the following pyramid.includes: %s",
361 pyramid_includes)
371 pyramid_includes)
362
372
363 # TODO: johbo: Re-think this, usually the call to config.include
373 # TODO: johbo: Re-think this, usually the call to config.include
364 # should allow to pass in a prefix.
374 # should allow to pass in a prefix.
365 settings.setdefault('rhodecode.api.url', '/_admin/api')
375 settings.setdefault('rhodecode.api.url', '/_admin/api')
366
376
367 # Sanitize generic settings.
377 # Sanitize generic settings.
368 _list_setting(settings, 'default_encoding', 'UTF-8')
378 _list_setting(settings, 'default_encoding', 'UTF-8')
369 _bool_setting(settings, 'is_test', 'false')
379 _bool_setting(settings, 'is_test', 'false')
370 _bool_setting(settings, 'gzip_responses', 'false')
380 _bool_setting(settings, 'gzip_responses', 'false')
371
381
372 # Call split out functions that sanitize settings for each topic.
382 # Call split out functions that sanitize settings for each topic.
373 _sanitize_appenlight_settings(settings)
383 _sanitize_appenlight_settings(settings)
374 _sanitize_vcs_settings(settings)
384 _sanitize_vcs_settings(settings)
375
385
376 # configure instance id
386 # configure instance id
377 config_utils.set_instance_id(settings)
387 config_utils.set_instance_id(settings)
378
388
379 return settings
389 return settings
380
390
381
391
382 def _sanitize_appenlight_settings(settings):
392 def _sanitize_appenlight_settings(settings):
383 _bool_setting(settings, 'appenlight', 'false')
393 _bool_setting(settings, 'appenlight', 'false')
384
394
385
395
386 def _sanitize_vcs_settings(settings):
396 def _sanitize_vcs_settings(settings):
387 """
397 """
388 Applies settings defaults and does type conversion for all VCS related
398 Applies settings defaults and does type conversion for all VCS related
389 settings.
399 settings.
390 """
400 """
391 _string_setting(settings, 'vcs.svn.compatible_version', '')
401 _string_setting(settings, 'vcs.svn.compatible_version', '')
392 _string_setting(settings, 'git_rev_filter', '--all')
402 _string_setting(settings, 'git_rev_filter', '--all')
393 _string_setting(settings, 'vcs.hooks.protocol', 'http')
403 _string_setting(settings, 'vcs.hooks.protocol', 'http')
394 _string_setting(settings, 'vcs.scm_app_implementation', 'http')
404 _string_setting(settings, 'vcs.scm_app_implementation', 'http')
395 _string_setting(settings, 'vcs.server', '')
405 _string_setting(settings, 'vcs.server', '')
396 _string_setting(settings, 'vcs.server.log_level', 'debug')
406 _string_setting(settings, 'vcs.server.log_level', 'debug')
397 _string_setting(settings, 'vcs.server.protocol', 'http')
407 _string_setting(settings, 'vcs.server.protocol', 'http')
398 _bool_setting(settings, 'startup.import_repos', 'false')
408 _bool_setting(settings, 'startup.import_repos', 'false')
399 _bool_setting(settings, 'vcs.hooks.direct_calls', 'false')
409 _bool_setting(settings, 'vcs.hooks.direct_calls', 'false')
400 _bool_setting(settings, 'vcs.server.enable', 'true')
410 _bool_setting(settings, 'vcs.server.enable', 'true')
401 _bool_setting(settings, 'vcs.start_server', 'false')
411 _bool_setting(settings, 'vcs.start_server', 'false')
402 _list_setting(settings, 'vcs.backends', 'hg, git, svn')
412 _list_setting(settings, 'vcs.backends', 'hg, git, svn')
403 _int_setting(settings, 'vcs.connection_timeout', 3600)
413 _int_setting(settings, 'vcs.connection_timeout', 3600)
404
414
405 # Support legacy values of vcs.scm_app_implementation. Legacy
415 # Support legacy values of vcs.scm_app_implementation. Legacy
406 # configurations may use 'rhodecode.lib.middleware.utils.scm_app_http'
416 # configurations may use 'rhodecode.lib.middleware.utils.scm_app_http'
407 # which is now mapped to 'http'.
417 # which is now mapped to 'http'.
408 scm_app_impl = settings['vcs.scm_app_implementation']
418 scm_app_impl = settings['vcs.scm_app_implementation']
409 if scm_app_impl == 'rhodecode.lib.middleware.utils.scm_app_http':
419 if scm_app_impl == 'rhodecode.lib.middleware.utils.scm_app_http':
410 settings['vcs.scm_app_implementation'] = 'http'
420 settings['vcs.scm_app_implementation'] = 'http'
411
421
412
422
413 def _int_setting(settings, name, default):
423 def _int_setting(settings, name, default):
414 settings[name] = int(settings.get(name, default))
424 settings[name] = int(settings.get(name, default))
415
425
416
426
417 def _bool_setting(settings, name, default):
427 def _bool_setting(settings, name, default):
418 input_val = settings.get(name, default)
428 input_val = settings.get(name, default)
419 if isinstance(input_val, unicode):
429 if isinstance(input_val, unicode):
420 input_val = input_val.encode('utf8')
430 input_val = input_val.encode('utf8')
421 settings[name] = asbool(input_val)
431 settings[name] = asbool(input_val)
422
432
423
433
424 def _list_setting(settings, name, default):
434 def _list_setting(settings, name, default):
425 raw_value = settings.get(name, default)
435 raw_value = settings.get(name, default)
426
436
427 old_separator = ','
437 old_separator = ','
428 if old_separator in raw_value:
438 if old_separator in raw_value:
429 # If we get a comma separated list, pass it to our own function.
439 # If we get a comma separated list, pass it to our own function.
430 settings[name] = rhodecode_aslist(raw_value, sep=old_separator)
440 settings[name] = rhodecode_aslist(raw_value, sep=old_separator)
431 else:
441 else:
432 # Otherwise we assume it uses pyramids space/newline separation.
442 # Otherwise we assume it uses pyramids space/newline separation.
433 settings[name] = aslist(raw_value)
443 settings[name] = aslist(raw_value)
434
444
435
445
436 def _string_setting(settings, name, default, lower=True):
446 def _string_setting(settings, name, default, lower=True):
437 value = settings.get(name, default)
447 value = settings.get(name, default)
438 if lower:
448 if lower:
439 value = value.lower()
449 value = value.lower()
440 settings[name] = value
450 settings[name] = value
451
452
453 def _substitute_values(mapping, substitutions):
454 result = {
455 # Note: Cannot use regular replacements, since they would clash
456 # with the implementation of ConfigParser. Using "format" instead.
457 key: value.format(**substitutions)
458 for key, value in mapping.items()
459 }
460 return result
General Comments 0
You need to be logged in to leave comments. Login now