##// END OF EJS Templates
core: expose pyraid specific partialRenderer request attribute....
marcink -
r1894:43ece55e default
parent child Browse files
Show More
@@ -0,0 +1,97 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 #
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
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
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/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21
22 import logging
23 from mako import exceptions
24 from pyramid.renderers import get_renderer
25
26 log = logging.getLogger(__name__)
27
28
29 def get_partial_renderer(request, tmpl_name):
30 return PyramidPartialRenderer(request, tmpl_name=tmpl_name)
31
32
33 class PyramidPartialRenderer(object):
34
35 """
36 Partial renderer used to render chunks of html used in datagrids
37 use like::
38
39 _renderer = request.get_partial_renderer('_dt/template_base.mako')
40 _render('quick_menu', args, kwargs)
41
42 :param tmpl_name: template path relate to /templates/ dir
43 """
44
45 def __init__(self, request, tmpl_name):
46 self.tmpl_name = tmpl_name
47 self.request = request
48
49 def _mako_lookup(self):
50 _tmpl_lookup = get_renderer('root.mako').lookup
51 return _tmpl_lookup.get_template(self.tmpl_name)
52
53 def get_call_context(self):
54 return self.request.call_context
55
56 def get_helpers(self):
57 from rhodecode.lib import helpers
58 return helpers
59
60 def _update_kwargs_for_render(self, kwargs):
61 """
62 Inject params required for Mako rendering
63 """
64
65 _kwargs = {
66 '_': self.request.translate,
67 'ungettext': self.request.plularize,
68 'h': self.get_helpers(),
69 'c': self.get_call_context(),
70
71 'request': self.request,
72 }
73 _kwargs.update(kwargs)
74 return _kwargs
75
76 def _render_with_exc(self, render_func, args, kwargs):
77 try:
78 return render_func.render(*args, **kwargs)
79 except:
80 log.error(exceptions.text_error_template().render())
81 raise
82
83 def _get_template(self, template_obj, def_name):
84 if def_name:
85 tmpl = template_obj.get_def(def_name)
86 else:
87 tmpl = template_obj
88 return tmpl
89
90 def render(self, def_name, *args, **kwargs):
91 lookup_obj = self._mako_lookup()
92 tmpl = self._get_template(lookup_obj, def_name=def_name)
93 kwargs = self._update_kwargs_for_render(kwargs)
94 return self._render_with_exc(tmpl, args, kwargs)
95
96 def __call__(self, tmpl, *args, **kwargs):
97 return self.render(tmpl, *args, **kwargs)
@@ -1,528 +1,532 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 """
22 22 Pylons middleware initialization
23 23 """
24 24 import logging
25 25 from collections import OrderedDict
26 26
27 27 from paste.registry import RegistryManager
28 28 from paste.gzipper import make_gzip_middleware
29 29 from pylons.wsgiapp import PylonsApp
30 30 from pyramid.authorization import ACLAuthorizationPolicy
31 31 from pyramid.config import Configurator
32 32 from pyramid.settings import asbool, aslist
33 33 from pyramid.wsgi import wsgiapp
34 34 from pyramid.httpexceptions import (
35 35 HTTPException, HTTPError, HTTPInternalServerError, HTTPFound)
36 36 from pyramid.events import ApplicationCreated
37 37 from pyramid.renderers import render_to_response
38 38 from routes.middleware import RoutesMiddleware
39 39 import routes.util
40 40
41 41 import rhodecode
42 42
43 43 from rhodecode.model import meta
44 44 from rhodecode.config import patches
45 45 from rhodecode.config.routing import STATIC_FILE_PREFIX
46 46 from rhodecode.config.environment import (
47 47 load_environment, load_pyramid_environment)
48 48
49 49 from rhodecode.lib.vcs import VCSCommunicationError
50 50 from rhodecode.lib.exceptions import VCSServerUnavailable
51 51 from rhodecode.lib.middleware import csrf
52 52 from rhodecode.lib.middleware.appenlight import wrap_in_appenlight_if_enabled
53 53 from rhodecode.lib.middleware.error_handling import (
54 54 PylonsErrorHandlingMiddleware)
55 55 from rhodecode.lib.middleware.https_fixup import HttpsFixup
56 56 from rhodecode.lib.middleware.vcs import VCSMiddleware
57 57 from rhodecode.lib.plugins.utils import register_rhodecode_plugin
58 58 from rhodecode.lib.utils2 import aslist as rhodecode_aslist, AttributeDict
59 59 from rhodecode.subscribers import (
60 60 scan_repositories_if_enabled, write_js_routes_if_enabled,
61 61 write_metadata_if_needed)
62 62
63 63
64 64 log = logging.getLogger(__name__)
65 65
66 66
67 67 # this is used to avoid avoid the route lookup overhead in routesmiddleware
68 68 # for certain routes which won't go to pylons to - eg. static files, debugger
69 69 # it is only needed for the pylons migration and can be removed once complete
70 70 class SkippableRoutesMiddleware(RoutesMiddleware):
71 71 """ Routes middleware that allows you to skip prefixes """
72 72
73 73 def __init__(self, *args, **kw):
74 74 self.skip_prefixes = kw.pop('skip_prefixes', [])
75 75 super(SkippableRoutesMiddleware, self).__init__(*args, **kw)
76 76
77 77 def __call__(self, environ, start_response):
78 78 for prefix in self.skip_prefixes:
79 79 if environ['PATH_INFO'].startswith(prefix):
80 80 # added to avoid the case when a missing /_static route falls
81 81 # through to pylons and causes an exception as pylons is
82 82 # expecting wsgiorg.routingargs to be set in the environ
83 83 # by RoutesMiddleware.
84 84 if 'wsgiorg.routing_args' not in environ:
85 85 environ['wsgiorg.routing_args'] = (None, {})
86 86 return self.app(environ, start_response)
87 87
88 88 return super(SkippableRoutesMiddleware, self).__call__(
89 89 environ, start_response)
90 90
91 91
92 92 def make_app(global_conf, static_files=True, **app_conf):
93 93 """Create a Pylons WSGI application and return it
94 94
95 95 ``global_conf``
96 96 The inherited configuration for this application. Normally from
97 97 the [DEFAULT] section of the Paste ini file.
98 98
99 99 ``app_conf``
100 100 The application's local configuration. Normally specified in
101 101 the [app:<name>] section of the Paste ini file (where <name>
102 102 defaults to main).
103 103
104 104 """
105 105 # Apply compatibility patches
106 106 patches.kombu_1_5_1_python_2_7_11()
107 107 patches.inspect_getargspec()
108 108
109 109 # Configure the Pylons environment
110 110 config = load_environment(global_conf, app_conf)
111 111
112 112 # The Pylons WSGI app
113 113 app = PylonsApp(config=config)
114 114 if rhodecode.is_test:
115 115 app = csrf.CSRFDetector(app)
116 116
117 117 expected_origin = config.get('expected_origin')
118 118 if expected_origin:
119 119 # The API can be accessed from other Origins.
120 120 app = csrf.OriginChecker(app, expected_origin,
121 121 skip_urls=[routes.util.url_for('api')])
122 122
123 123 # Establish the Registry for this application
124 124 app = RegistryManager(app)
125 125
126 126 app.config = config
127 127
128 128 return app
129 129
130 130
131 131 def make_pyramid_app(global_config, **settings):
132 132 """
133 133 Constructs the WSGI application based on Pyramid and wraps the Pylons based
134 134 application.
135 135
136 136 Specials:
137 137
138 138 * We migrate from Pylons to Pyramid. While doing this, we keep both
139 139 frameworks functional. This involves moving some WSGI middlewares around
140 140 and providing access to some data internals, so that the old code is
141 141 still functional.
142 142
143 143 * The application can also be integrated like a plugin via the call to
144 144 `includeme`. This is accompanied with the other utility functions which
145 145 are called. Changing this should be done with great care to not break
146 146 cases when these fragments are assembled from another place.
147 147
148 148 """
149 149 # The edition string should be available in pylons too, so we add it here
150 150 # before copying the settings.
151 151 settings.setdefault('rhodecode.edition', 'Community Edition')
152 152
153 153 # As long as our Pylons application does expect "unprepared" settings, make
154 154 # sure that we keep an unmodified copy. This avoids unintentional change of
155 155 # behavior in the old application.
156 156 settings_pylons = settings.copy()
157 157
158 158 sanitize_settings_and_apply_defaults(settings)
159 159 config = Configurator(settings=settings)
160 160 add_pylons_compat_data(config.registry, global_config, settings_pylons)
161 161
162 162 load_pyramid_environment(global_config, settings)
163 163
164 164 includeme_first(config)
165 165 includeme(config)
166 166 pyramid_app = config.make_wsgi_app()
167 167 pyramid_app = wrap_app_in_wsgi_middlewares(pyramid_app, config)
168 168 pyramid_app.config = config
169 169
170 170 # creating the app uses a connection - return it after we are done
171 171 meta.Session.remove()
172 172
173 173 return pyramid_app
174 174
175 175
176 176 def make_not_found_view(config):
177 177 """
178 178 This creates the view which should be registered as not-found-view to
179 179 pyramid. Basically it contains of the old pylons app, converted to a view.
180 180 Additionally it is wrapped by some other middlewares.
181 181 """
182 182 settings = config.registry.settings
183 183 vcs_server_enabled = settings['vcs.server.enable']
184 184
185 185 # Make pylons app from unprepared settings.
186 186 pylons_app = make_app(
187 187 config.registry._pylons_compat_global_config,
188 188 **config.registry._pylons_compat_settings)
189 189 config.registry._pylons_compat_config = pylons_app.config
190 190
191 191 # Appenlight monitoring.
192 192 pylons_app, appenlight_client = wrap_in_appenlight_if_enabled(
193 193 pylons_app, settings)
194 194
195 195 # The pylons app is executed inside of the pyramid 404 exception handler.
196 196 # Exceptions which are raised inside of it are not handled by pyramid
197 197 # again. Therefore we add a middleware that invokes the error handler in
198 198 # case of an exception or error response. This way we return proper error
199 199 # HTML pages in case of an error.
200 200 reraise = (settings.get('debugtoolbar.enabled', False) or
201 201 rhodecode.disable_error_handler)
202 202 pylons_app = PylonsErrorHandlingMiddleware(
203 203 pylons_app, error_handler, reraise)
204 204
205 205 # The VCSMiddleware shall operate like a fallback if pyramid doesn't find a
206 206 # view to handle the request. Therefore it is wrapped around the pylons
207 207 # app. It has to be outside of the error handling otherwise error responses
208 208 # from the vcsserver are converted to HTML error pages. This confuses the
209 209 # command line tools and the user won't get a meaningful error message.
210 210 if vcs_server_enabled:
211 211 pylons_app = VCSMiddleware(
212 212 pylons_app, settings, appenlight_client, registry=config.registry)
213 213
214 214 # Convert WSGI app to pyramid view and return it.
215 215 return wsgiapp(pylons_app)
216 216
217 217
218 218 def add_pylons_compat_data(registry, global_config, settings):
219 219 """
220 220 Attach data to the registry to support the Pylons integration.
221 221 """
222 222 registry._pylons_compat_global_config = global_config
223 223 registry._pylons_compat_settings = settings
224 224
225 225
226 226 def error_handler(exception, request):
227 227 import rhodecode
228 228 from rhodecode.lib import helpers
229 229
230 230 rhodecode_title = rhodecode.CONFIG.get('rhodecode_title') or 'RhodeCode'
231 231
232 232 base_response = HTTPInternalServerError()
233 233 # prefer original exception for the response since it may have headers set
234 234 if isinstance(exception, HTTPException):
235 235 base_response = exception
236 236 elif isinstance(exception, VCSCommunicationError):
237 237 base_response = VCSServerUnavailable()
238 238
239 239 def is_http_error(response):
240 240 # error which should have traceback
241 241 return response.status_code > 499
242 242
243 243 if is_http_error(base_response):
244 244 log.exception(
245 245 'error occurred handling this request for path: %s', request.path)
246 246
247 247 c = AttributeDict()
248 248 c.error_message = base_response.status
249 249 c.error_explanation = base_response.explanation or str(base_response)
250 250 c.visual = AttributeDict()
251 251
252 252 c.visual.rhodecode_support_url = (
253 253 request.registry.settings.get('rhodecode_support_url') or
254 254 request.route_url('rhodecode_support')
255 255 )
256 256 c.redirect_time = 0
257 257 c.rhodecode_name = rhodecode_title
258 258 if not c.rhodecode_name:
259 259 c.rhodecode_name = 'Rhodecode'
260 260
261 261 c.causes = []
262 262 if hasattr(base_response, 'causes'):
263 263 c.causes = base_response.causes
264 264 c.messages = helpers.flash.pop_messages()
265 265
266 266 response = render_to_response(
267 267 '/errors/error_document.mako', {'c': c, 'h': helpers}, request=request,
268 268 response=base_response)
269 269
270 270 return response
271 271
272 272
273 273 def includeme(config):
274 274 settings = config.registry.settings
275 275
276 276 # plugin information
277 277 config.registry.rhodecode_plugins = OrderedDict()
278 278
279 279 config.add_directive(
280 280 'register_rhodecode_plugin', register_rhodecode_plugin)
281 281
282 282 if asbool(settings.get('appenlight', 'false')):
283 283 config.include('appenlight_client.ext.pyramid_tween')
284 284
285 285 # Includes which are required. The application would fail without them.
286 286 config.include('pyramid_mako')
287 287 config.include('pyramid_beaker')
288 288
289 289 config.include('rhodecode.authentication')
290 290 config.include('rhodecode.integrations')
291 291
292 292 # apps
293 293 config.include('rhodecode.apps._base')
294 294 config.include('rhodecode.apps.ops')
295 295
296 296 config.include('rhodecode.apps.admin')
297 297 config.include('rhodecode.apps.channelstream')
298 298 config.include('rhodecode.apps.login')
299 299 config.include('rhodecode.apps.home')
300 300 config.include('rhodecode.apps.repository')
301 301 config.include('rhodecode.apps.repo_group')
302 302 config.include('rhodecode.apps.search')
303 303 config.include('rhodecode.apps.user_profile')
304 304 config.include('rhodecode.apps.my_account')
305 305 config.include('rhodecode.apps.svn_support')
306 306 config.include('rhodecode.apps.gist')
307 307
308 308 config.include('rhodecode.tweens')
309 309 config.include('rhodecode.api')
310 310
311 311 config.add_route(
312 312 'rhodecode_support', 'https://rhodecode.com/help/', static=True)
313 313
314 314 config.add_translation_dirs('rhodecode:i18n/')
315 315 settings['default_locale_name'] = settings.get('lang', 'en')
316 316
317 317 # Add subscribers.
318 318 config.add_subscriber(scan_repositories_if_enabled, ApplicationCreated)
319 319 config.add_subscriber(write_metadata_if_needed, ApplicationCreated)
320 320 config.add_subscriber(write_js_routes_if_enabled, ApplicationCreated)
321 321
322 config.add_request_method(
323 'rhodecode.lib.partial_renderer.get_partial_renderer',
324 'get_partial_renderer')
325
322 326 # events
323 327 # TODO(marcink): this should be done when pyramid migration is finished
324 328 # config.add_subscriber(
325 329 # 'rhodecode.integrations.integrations_event_handler',
326 330 # 'rhodecode.events.RhodecodeEvent')
327 331
328 332 # Set the authorization policy.
329 333 authz_policy = ACLAuthorizationPolicy()
330 334 config.set_authorization_policy(authz_policy)
331 335
332 336 # Set the default renderer for HTML templates to mako.
333 337 config.add_mako_renderer('.html')
334 338
335 339 config.add_renderer(
336 340 name='json_ext',
337 341 factory='rhodecode.lib.ext_json_renderer.pyramid_ext_json')
338 342
339 343 # include RhodeCode plugins
340 344 includes = aslist(settings.get('rhodecode.includes', []))
341 345 for inc in includes:
342 346 config.include(inc)
343 347
344 348 # This is the glue which allows us to migrate in chunks. By registering the
345 349 # pylons based application as the "Not Found" view in Pyramid, we will
346 350 # fallback to the old application each time the new one does not yet know
347 351 # how to handle a request.
348 352 config.add_notfound_view(make_not_found_view(config))
349 353
350 354 if not settings.get('debugtoolbar.enabled', False):
351 355 # if no toolbar, then any exception gets caught and rendered
352 356 config.add_view(error_handler, context=Exception)
353 357
354 358 config.add_view(error_handler, context=HTTPError)
355 359
356 360
357 361 def includeme_first(config):
358 362 # redirect automatic browser favicon.ico requests to correct place
359 363 def favicon_redirect(context, request):
360 364 return HTTPFound(
361 365 request.static_path('rhodecode:public/images/favicon.ico'))
362 366
363 367 config.add_view(favicon_redirect, route_name='favicon')
364 368 config.add_route('favicon', '/favicon.ico')
365 369
366 370 def robots_redirect(context, request):
367 371 return HTTPFound(
368 372 request.static_path('rhodecode:public/robots.txt'))
369 373
370 374 config.add_view(robots_redirect, route_name='robots')
371 375 config.add_route('robots', '/robots.txt')
372 376
373 377 config.add_static_view(
374 378 '_static/deform', 'deform:static')
375 379 config.add_static_view(
376 380 '_static/rhodecode', path='rhodecode:public', cache_max_age=3600 * 24)
377 381
378 382
379 383 def wrap_app_in_wsgi_middlewares(pyramid_app, config):
380 384 """
381 385 Apply outer WSGI middlewares around the application.
382 386
383 387 Part of this has been moved up from the Pylons layer, so that the
384 388 data is also available if old Pylons code is hit through an already ported
385 389 view.
386 390 """
387 391 settings = config.registry.settings
388 392
389 393 # enable https redirects based on HTTP_X_URL_SCHEME set by proxy
390 394 pyramid_app = HttpsFixup(pyramid_app, settings)
391 395
392 396 # Add RoutesMiddleware to support the pylons compatibility tween during
393 397 # migration to pyramid.
394 398 pyramid_app = SkippableRoutesMiddleware(
395 399 pyramid_app, config.registry._pylons_compat_config['routes.map'],
396 400 skip_prefixes=(STATIC_FILE_PREFIX, '/_debug_toolbar'))
397 401
398 402 pyramid_app, _ = wrap_in_appenlight_if_enabled(pyramid_app, settings)
399 403
400 404 if settings['gzip_responses']:
401 405 pyramid_app = make_gzip_middleware(
402 406 pyramid_app, settings, compress_level=1)
403 407
404 408 # this should be the outer most middleware in the wsgi stack since
405 409 # middleware like Routes make database calls
406 410 def pyramid_app_with_cleanup(environ, start_response):
407 411 try:
408 412 return pyramid_app(environ, start_response)
409 413 finally:
410 414 # Dispose current database session and rollback uncommitted
411 415 # transactions.
412 416 meta.Session.remove()
413 417
414 418 # In a single threaded mode server, on non sqlite db we should have
415 419 # '0 Current Checked out connections' at the end of a request,
416 420 # if not, then something, somewhere is leaving a connection open
417 421 pool = meta.Base.metadata.bind.engine.pool
418 422 log.debug('sa pool status: %s', pool.status())
419 423
420 424 return pyramid_app_with_cleanup
421 425
422 426
423 427 def sanitize_settings_and_apply_defaults(settings):
424 428 """
425 429 Applies settings defaults and does all type conversion.
426 430
427 431 We would move all settings parsing and preparation into this place, so that
428 432 we have only one place left which deals with this part. The remaining parts
429 433 of the application would start to rely fully on well prepared settings.
430 434
431 435 This piece would later be split up per topic to avoid a big fat monster
432 436 function.
433 437 """
434 438
435 439 # Pyramid's mako renderer has to search in the templates folder so that the
436 440 # old templates still work. Ported and new templates are expected to use
437 441 # real asset specifications for the includes.
438 442 mako_directories = settings.setdefault('mako.directories', [
439 443 # Base templates of the original Pylons application
440 444 'rhodecode:templates',
441 445 ])
442 446 log.debug(
443 447 "Using the following Mako template directories: %s",
444 448 mako_directories)
445 449
446 450 # Default includes, possible to change as a user
447 451 pyramid_includes = settings.setdefault('pyramid.includes', [
448 452 'rhodecode.lib.middleware.request_wrapper',
449 453 ])
450 454 log.debug(
451 455 "Using the following pyramid.includes: %s",
452 456 pyramid_includes)
453 457
454 458 # TODO: johbo: Re-think this, usually the call to config.include
455 459 # should allow to pass in a prefix.
456 460 settings.setdefault('rhodecode.api.url', '/_admin/api')
457 461
458 462 # Sanitize generic settings.
459 463 _list_setting(settings, 'default_encoding', 'UTF-8')
460 464 _bool_setting(settings, 'is_test', 'false')
461 465 _bool_setting(settings, 'gzip_responses', 'false')
462 466
463 467 # Call split out functions that sanitize settings for each topic.
464 468 _sanitize_appenlight_settings(settings)
465 469 _sanitize_vcs_settings(settings)
466 470
467 471 return settings
468 472
469 473
470 474 def _sanitize_appenlight_settings(settings):
471 475 _bool_setting(settings, 'appenlight', 'false')
472 476
473 477
474 478 def _sanitize_vcs_settings(settings):
475 479 """
476 480 Applies settings defaults and does type conversion for all VCS related
477 481 settings.
478 482 """
479 483 _string_setting(settings, 'vcs.svn.compatible_version', '')
480 484 _string_setting(settings, 'git_rev_filter', '--all')
481 485 _string_setting(settings, 'vcs.hooks.protocol', 'http')
482 486 _string_setting(settings, 'vcs.scm_app_implementation', 'http')
483 487 _string_setting(settings, 'vcs.server', '')
484 488 _string_setting(settings, 'vcs.server.log_level', 'debug')
485 489 _string_setting(settings, 'vcs.server.protocol', 'http')
486 490 _bool_setting(settings, 'startup.import_repos', 'false')
487 491 _bool_setting(settings, 'vcs.hooks.direct_calls', 'false')
488 492 _bool_setting(settings, 'vcs.server.enable', 'true')
489 493 _bool_setting(settings, 'vcs.start_server', 'false')
490 494 _list_setting(settings, 'vcs.backends', 'hg, git, svn')
491 495 _int_setting(settings, 'vcs.connection_timeout', 3600)
492 496
493 497 # Support legacy values of vcs.scm_app_implementation. Legacy
494 498 # configurations may use 'rhodecode.lib.middleware.utils.scm_app_http'
495 499 # which is now mapped to 'http'.
496 500 scm_app_impl = settings['vcs.scm_app_implementation']
497 501 if scm_app_impl == 'rhodecode.lib.middleware.utils.scm_app_http':
498 502 settings['vcs.scm_app_implementation'] = 'http'
499 503
500 504
501 505 def _int_setting(settings, name, default):
502 506 settings[name] = int(settings.get(name, default))
503 507
504 508
505 509 def _bool_setting(settings, name, default):
506 510 input = settings.get(name, default)
507 511 if isinstance(input, unicode):
508 512 input = input.encode('utf8')
509 513 settings[name] = asbool(input)
510 514
511 515
512 516 def _list_setting(settings, name, default):
513 517 raw_value = settings.get(name, default)
514 518
515 519 old_separator = ','
516 520 if old_separator in raw_value:
517 521 # If we get a comma separated list, pass it to our own function.
518 522 settings[name] = rhodecode_aslist(raw_value, sep=old_separator)
519 523 else:
520 524 # Otherwise we assume it uses pyramids space/newline separation.
521 525 settings[name] = aslist(raw_value)
522 526
523 527
524 528 def _string_setting(settings, name, default, lower=True):
525 529 value = settings.get(name, default)
526 530 if lower:
527 531 value = value.lower()
528 532 settings[name] = value
General Comments 0
You need to be logged in to leave comments. Login now