##// END OF EJS Templates
db: Set `rhodecode.is_test` in `make_pyramid_app` instead of `make_app`...
johbo -
r118:931f58e5 default
parent child Browse files
Show More
@@ -1,177 +1,176 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2016 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 """
21 """
22 Pylons environment configuration
22 Pylons environment configuration
23 """
23 """
24
24
25 import os
25 import os
26 import logging
26 import logging
27 import rhodecode
27 import rhodecode
28 import platform
28 import platform
29 import re
29 import re
30 import io
30 import io
31
31
32 from mako.lookup import TemplateLookup
32 from mako.lookup import TemplateLookup
33 from pylons.configuration import PylonsConfig
33 from pylons.configuration import PylonsConfig
34 from pylons.error import handle_mako_error
34 from pylons.error import handle_mako_error
35 from pyramid.settings import asbool
35 from pyramid.settings import asbool
36
36
37 # don't remove this import it does magic for celery
37 # don't remove this import it does magic for celery
38 from rhodecode.lib import celerypylons # noqa
38 from rhodecode.lib import celerypylons # noqa
39
39
40 import rhodecode.lib.app_globals as app_globals
40 import rhodecode.lib.app_globals as app_globals
41
41
42 from rhodecode.config import utils
42 from rhodecode.config import utils
43 from rhodecode.config.routing import make_map
43 from rhodecode.config.routing import make_map
44 from rhodecode.config.jsroutes import generate_jsroutes_content
44 from rhodecode.config.jsroutes import generate_jsroutes_content
45
45
46 from rhodecode.lib import helpers
46 from rhodecode.lib import helpers
47 from rhodecode.lib.auth import set_available_permissions
47 from rhodecode.lib.auth import set_available_permissions
48 from rhodecode.lib.utils import (
48 from rhodecode.lib.utils import (
49 repo2db_mapper, make_db_config, set_rhodecode_config,
49 repo2db_mapper, make_db_config, set_rhodecode_config,
50 load_rcextensions)
50 load_rcextensions)
51 from rhodecode.lib.utils2 import str2bool, aslist
51 from rhodecode.lib.utils2 import str2bool, aslist
52 from rhodecode.lib.vcs import connect_vcs, start_vcs_server
52 from rhodecode.lib.vcs import connect_vcs, start_vcs_server
53 from rhodecode.model.scm import ScmModel
53 from rhodecode.model.scm import ScmModel
54
54
55 log = logging.getLogger(__name__)
55 log = logging.getLogger(__name__)
56
56
57 def load_environment(global_conf, app_conf, initial=False,
57 def load_environment(global_conf, app_conf, initial=False,
58 test_env=None, test_index=None):
58 test_env=None, test_index=None):
59 """
59 """
60 Configure the Pylons environment via the ``pylons.config``
60 Configure the Pylons environment via the ``pylons.config``
61 object
61 object
62 """
62 """
63 config = PylonsConfig()
63 config = PylonsConfig()
64
64
65 rhodecode.is_test = str2bool(app_conf.get('is_test', 'False'))
66
65
67 # Pylons paths
66 # Pylons paths
68 root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
67 root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
69 paths = {
68 paths = {
70 'root': root,
69 'root': root,
71 'controllers': os.path.join(root, 'controllers'),
70 'controllers': os.path.join(root, 'controllers'),
72 'static_files': os.path.join(root, 'public'),
71 'static_files': os.path.join(root, 'public'),
73 'templates': [os.path.join(root, 'templates')],
72 'templates': [os.path.join(root, 'templates')],
74 }
73 }
75
74
76 # Initialize config with the basic options
75 # Initialize config with the basic options
77 config.init_app(global_conf, app_conf, package='rhodecode', paths=paths)
76 config.init_app(global_conf, app_conf, package='rhodecode', paths=paths)
78
77
79 # store some globals into rhodecode
78 # store some globals into rhodecode
80 rhodecode.CELERY_ENABLED = str2bool(config['app_conf'].get('use_celery'))
79 rhodecode.CELERY_ENABLED = str2bool(config['app_conf'].get('use_celery'))
81 rhodecode.CELERY_EAGER = str2bool(
80 rhodecode.CELERY_EAGER = str2bool(
82 config['app_conf'].get('celery.always.eager'))
81 config['app_conf'].get('celery.always.eager'))
83
82
84 config['routes.map'] = make_map(config)
83 config['routes.map'] = make_map(config)
85
84
86 if asbool(config['debug']):
85 if asbool(config['debug']):
87 jsroutes = config['routes.map'].jsroutes()
86 jsroutes = config['routes.map'].jsroutes()
88 jsroutes_file_content = generate_jsroutes_content(jsroutes)
87 jsroutes_file_content = generate_jsroutes_content(jsroutes)
89 jsroutes_file_path = os.path.join(
88 jsroutes_file_path = os.path.join(
90 paths['static_files'], 'js', 'rhodecode', 'routes.js')
89 paths['static_files'], 'js', 'rhodecode', 'routes.js')
91
90
92 with io.open(jsroutes_file_path, 'w', encoding='utf-8') as f:
91 with io.open(jsroutes_file_path, 'w', encoding='utf-8') as f:
93 f.write(jsroutes_file_content)
92 f.write(jsroutes_file_content)
94
93
95 config['pylons.app_globals'] = app_globals.Globals(config)
94 config['pylons.app_globals'] = app_globals.Globals(config)
96 config['pylons.h'] = helpers
95 config['pylons.h'] = helpers
97 rhodecode.CONFIG = config
96 rhodecode.CONFIG = config
98
97
99 load_rcextensions(root_path=config['here'])
98 load_rcextensions(root_path=config['here'])
100
99
101 # Setup cache object as early as possible
100 # Setup cache object as early as possible
102 import pylons
101 import pylons
103 pylons.cache._push_object(config['pylons.app_globals'].cache)
102 pylons.cache._push_object(config['pylons.app_globals'].cache)
104
103
105 # Create the Mako TemplateLookup, with the default auto-escaping
104 # Create the Mako TemplateLookup, with the default auto-escaping
106 config['pylons.app_globals'].mako_lookup = TemplateLookup(
105 config['pylons.app_globals'].mako_lookup = TemplateLookup(
107 directories=paths['templates'],
106 directories=paths['templates'],
108 error_handler=handle_mako_error,
107 error_handler=handle_mako_error,
109 module_directory=os.path.join(app_conf['cache_dir'], 'templates'),
108 module_directory=os.path.join(app_conf['cache_dir'], 'templates'),
110 input_encoding='utf-8', default_filters=['escape'],
109 input_encoding='utf-8', default_filters=['escape'],
111 imports=['from webhelpers.html import escape'])
110 imports=['from webhelpers.html import escape'])
112
111
113 # sets the c attribute access when don't existing attribute are accessed
112 # sets the c attribute access when don't existing attribute are accessed
114 config['pylons.strict_tmpl_context'] = True
113 config['pylons.strict_tmpl_context'] = True
115
114
116 # Limit backends to "vcs.backends" from configuration
115 # Limit backends to "vcs.backends" from configuration
117 backends = config['vcs.backends'] = aslist(
116 backends = config['vcs.backends'] = aslist(
118 config.get('vcs.backends', 'hg,git'), sep=',')
117 config.get('vcs.backends', 'hg,git'), sep=',')
119 for alias in rhodecode.BACKENDS.keys():
118 for alias in rhodecode.BACKENDS.keys():
120 if alias not in backends:
119 if alias not in backends:
121 del rhodecode.BACKENDS[alias]
120 del rhodecode.BACKENDS[alias]
122 log.info("Enabled backends: %s", backends)
121 log.info("Enabled backends: %s", backends)
123
122
124 # initialize vcs client and optionally run the server if enabled
123 # initialize vcs client and optionally run the server if enabled
125 vcs_server_uri = config.get('vcs.server', '')
124 vcs_server_uri = config.get('vcs.server', '')
126 vcs_server_enabled = str2bool(config.get('vcs.server.enable', 'true'))
125 vcs_server_enabled = str2bool(config.get('vcs.server.enable', 'true'))
127 start_server = (
126 start_server = (
128 str2bool(config.get('vcs.start_server', 'false')) and
127 str2bool(config.get('vcs.start_server', 'false')) and
129 not int(os.environ.get('RC_VCSSERVER_TEST_DISABLE', '0')))
128 not int(os.environ.get('RC_VCSSERVER_TEST_DISABLE', '0')))
130 if vcs_server_enabled and start_server:
129 if vcs_server_enabled and start_server:
131 log.info("Starting vcsserver")
130 log.info("Starting vcsserver")
132 start_vcs_server(server_and_port=vcs_server_uri,
131 start_vcs_server(server_and_port=vcs_server_uri,
133 protocol=utils.get_vcs_server_protocol(config),
132 protocol=utils.get_vcs_server_protocol(config),
134 log_level=config['vcs.server.log_level'])
133 log_level=config['vcs.server.log_level'])
135
134
136 set_available_permissions(config)
135 set_available_permissions(config)
137 db_cfg = make_db_config(clear_session=True)
136 db_cfg = make_db_config(clear_session=True)
138
137
139 repos_path = list(db_cfg.items('paths'))[0][1]
138 repos_path = list(db_cfg.items('paths'))[0][1]
140 config['base_path'] = repos_path
139 config['base_path'] = repos_path
141
140
142 config['vcs.hooks.direct_calls'] = _use_direct_hook_calls(config)
141 config['vcs.hooks.direct_calls'] = _use_direct_hook_calls(config)
143 config['vcs.hooks.protocol'] = _get_vcs_hooks_protocol(config)
142 config['vcs.hooks.protocol'] = _get_vcs_hooks_protocol(config)
144
143
145 # store db config also in main global CONFIG
144 # store db config also in main global CONFIG
146 set_rhodecode_config(config)
145 set_rhodecode_config(config)
147
146
148 # configure instance id
147 # configure instance id
149 utils.set_instance_id(config)
148 utils.set_instance_id(config)
150
149
151 # CONFIGURATION OPTIONS HERE (note: all config options will override
150 # CONFIGURATION OPTIONS HERE (note: all config options will override
152 # any Pylons config options)
151 # any Pylons config options)
153
152
154 # store config reference into our module to skip import magic of pylons
153 # store config reference into our module to skip import magic of pylons
155 rhodecode.CONFIG.update(config)
154 rhodecode.CONFIG.update(config)
156
155
157 utils.configure_pyro4(config)
156 utils.configure_pyro4(config)
158 utils.configure_vcs(config)
157 utils.configure_vcs(config)
159 if vcs_server_enabled:
158 if vcs_server_enabled:
160 connect_vcs(vcs_server_uri, utils.get_vcs_server_protocol(config))
159 connect_vcs(vcs_server_uri, utils.get_vcs_server_protocol(config))
161
160
162 import_on_startup = str2bool(config.get('startup.import_repos', False))
161 import_on_startup = str2bool(config.get('startup.import_repos', False))
163 if vcs_server_enabled and import_on_startup:
162 if vcs_server_enabled and import_on_startup:
164 repo2db_mapper(ScmModel().repo_scan(repos_path), remove_obsolete=False)
163 repo2db_mapper(ScmModel().repo_scan(repos_path), remove_obsolete=False)
165 return config
164 return config
166
165
167
166
168 def _use_direct_hook_calls(config):
167 def _use_direct_hook_calls(config):
169 default_direct_hook_calls = 'false'
168 default_direct_hook_calls = 'false'
170 direct_hook_calls = str2bool(
169 direct_hook_calls = str2bool(
171 config.get('vcs.hooks.direct_calls', default_direct_hook_calls))
170 config.get('vcs.hooks.direct_calls', default_direct_hook_calls))
172 return direct_hook_calls
171 return direct_hook_calls
173
172
174
173
175 def _get_vcs_hooks_protocol(config):
174 def _get_vcs_hooks_protocol(config):
176 protocol = config.get('vcs.hooks.protocol', 'pyro4').lower()
175 protocol = config.get('vcs.hooks.protocol', 'pyro4').lower()
177 return protocol
176 return protocol
@@ -1,324 +1,327 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2016 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 """
21 """
22 Pylons middleware initialization
22 Pylons middleware initialization
23 """
23 """
24 import logging
24 import logging
25
25
26 from paste.registry import RegistryManager
26 from paste.registry import RegistryManager
27 from paste.gzipper import make_gzip_middleware
27 from paste.gzipper import make_gzip_middleware
28 from pylons.middleware import ErrorHandler, StatusCodeRedirect
28 from pylons.middleware import ErrorHandler, StatusCodeRedirect
29 from pylons.wsgiapp import PylonsApp
29 from pylons.wsgiapp import PylonsApp
30 from pyramid.authorization import ACLAuthorizationPolicy
30 from pyramid.authorization import ACLAuthorizationPolicy
31 from pyramid.config import Configurator
31 from pyramid.config import Configurator
32 from pyramid.static import static_view
32 from pyramid.static import static_view
33 from pyramid.settings import asbool, aslist
33 from pyramid.settings import asbool, aslist
34 from pyramid.wsgi import wsgiapp
34 from pyramid.wsgi import wsgiapp
35 from routes.middleware import RoutesMiddleware
35 from routes.middleware import RoutesMiddleware
36 import routes.util
36 import routes.util
37
37
38 import rhodecode
38 import rhodecode
39 from rhodecode.config import patches, utils
39 from rhodecode.config import patches, utils
40 from rhodecode.config.environment import load_environment
40 from rhodecode.config.environment import load_environment
41 from rhodecode.lib.middleware import csrf
41 from rhodecode.lib.middleware import csrf
42 from rhodecode.lib.middleware.appenlight import wrap_in_appenlight_if_enabled
42 from rhodecode.lib.middleware.appenlight import wrap_in_appenlight_if_enabled
43 from rhodecode.lib.middleware.disable_vcs import DisableVCSPagesWrapper
43 from rhodecode.lib.middleware.disable_vcs import DisableVCSPagesWrapper
44 from rhodecode.lib.middleware.https_fixup import HttpsFixup
44 from rhodecode.lib.middleware.https_fixup import HttpsFixup
45 from rhodecode.lib.middleware.vcs import VCSMiddleware
45 from rhodecode.lib.middleware.vcs import VCSMiddleware
46 from rhodecode.lib.plugins.utils import register_rhodecode_plugin
46 from rhodecode.lib.plugins.utils import register_rhodecode_plugin
47
47
48
48
49 log = logging.getLogger(__name__)
49 log = logging.getLogger(__name__)
50
50
51
51
52 def make_app(global_conf, full_stack=True, static_files=True, **app_conf):
52 def make_app(global_conf, full_stack=True, static_files=True, **app_conf):
53 """Create a Pylons WSGI application and return it
53 """Create a Pylons WSGI application and return it
54
54
55 ``global_conf``
55 ``global_conf``
56 The inherited configuration for this application. Normally from
56 The inherited configuration for this application. Normally from
57 the [DEFAULT] section of the Paste ini file.
57 the [DEFAULT] section of the Paste ini file.
58
58
59 ``full_stack``
59 ``full_stack``
60 Whether or not this application provides a full WSGI stack (by
60 Whether or not this application provides a full WSGI stack (by
61 default, meaning it handles its own exceptions and errors).
61 default, meaning it handles its own exceptions and errors).
62 Disable full_stack when this application is "managed" by
62 Disable full_stack when this application is "managed" by
63 another WSGI middleware.
63 another WSGI middleware.
64
64
65 ``app_conf``
65 ``app_conf``
66 The application's local configuration. Normally specified in
66 The application's local configuration. Normally specified in
67 the [app:<name>] section of the Paste ini file (where <name>
67 the [app:<name>] section of the Paste ini file (where <name>
68 defaults to main).
68 defaults to main).
69
69
70 """
70 """
71 # Apply compatibility patches
71 # Apply compatibility patches
72 patches.kombu_1_5_1_python_2_7_11()
72 patches.kombu_1_5_1_python_2_7_11()
73 patches.inspect_getargspec()
73 patches.inspect_getargspec()
74
74
75 # Configure the Pylons environment
75 # Configure the Pylons environment
76 config = load_environment(global_conf, app_conf)
76 config = load_environment(global_conf, app_conf)
77
77
78 # The Pylons WSGI app
78 # The Pylons WSGI app
79 app = PylonsApp(config=config)
79 app = PylonsApp(config=config)
80 if rhodecode.is_test:
80 if rhodecode.is_test:
81 app = csrf.CSRFDetector(app)
81 app = csrf.CSRFDetector(app)
82
82
83 expected_origin = config.get('expected_origin')
83 expected_origin = config.get('expected_origin')
84 if expected_origin:
84 if expected_origin:
85 # The API can be accessed from other Origins.
85 # The API can be accessed from other Origins.
86 app = csrf.OriginChecker(app, expected_origin,
86 app = csrf.OriginChecker(app, expected_origin,
87 skip_urls=[routes.util.url_for('api')])
87 skip_urls=[routes.util.url_for('api')])
88
88
89 # Add RoutesMiddleware. Currently we have two instances in the stack. This
89 # Add RoutesMiddleware. Currently we have two instances in the stack. This
90 # is the lower one to make the StatusCodeRedirect middleware happy.
90 # is the lower one to make the StatusCodeRedirect middleware happy.
91 # TODO: johbo: This is not optimal, search for a better solution.
91 # TODO: johbo: This is not optimal, search for a better solution.
92 app = RoutesMiddleware(app, config['routes.map'])
92 app = RoutesMiddleware(app, config['routes.map'])
93
93
94 # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares)
94 # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares)
95 if asbool(config['pdebug']):
95 if asbool(config['pdebug']):
96 from rhodecode.lib.profiler import ProfilingMiddleware
96 from rhodecode.lib.profiler import ProfilingMiddleware
97 app = ProfilingMiddleware(app)
97 app = ProfilingMiddleware(app)
98
98
99 # Protect from VCS Server error related pages when server is not available
99 # Protect from VCS Server error related pages when server is not available
100 vcs_server_enabled = asbool(config.get('vcs.server.enable', 'true'))
100 vcs_server_enabled = asbool(config.get('vcs.server.enable', 'true'))
101 if not vcs_server_enabled:
101 if not vcs_server_enabled:
102 app = DisableVCSPagesWrapper(app)
102 app = DisableVCSPagesWrapper(app)
103
103
104 if asbool(full_stack):
104 if asbool(full_stack):
105
105
106 # Appenlight monitoring and error handler
106 # Appenlight monitoring and error handler
107 app, appenlight_client = wrap_in_appenlight_if_enabled(app, config)
107 app, appenlight_client = wrap_in_appenlight_if_enabled(app, config)
108
108
109 # Handle Python exceptions
109 # Handle Python exceptions
110 app = ErrorHandler(app, global_conf, **config['pylons.errorware'])
110 app = ErrorHandler(app, global_conf, **config['pylons.errorware'])
111
111
112 # we want our low level middleware to get to the request ASAP. We don't
112 # we want our low level middleware to get to the request ASAP. We don't
113 # need any pylons stack middleware in them
113 # need any pylons stack middleware in them
114 app = VCSMiddleware(app, config, appenlight_client)
114 app = VCSMiddleware(app, config, appenlight_client)
115 # Display error documents for 401, 403, 404 status codes (and
115 # Display error documents for 401, 403, 404 status codes (and
116 # 500 when debug is disabled)
116 # 500 when debug is disabled)
117 if asbool(config['debug']):
117 if asbool(config['debug']):
118 app = StatusCodeRedirect(app)
118 app = StatusCodeRedirect(app)
119 else:
119 else:
120 app = StatusCodeRedirect(app, [400, 401, 403, 404, 500])
120 app = StatusCodeRedirect(app, [400, 401, 403, 404, 500])
121
121
122 # enable https redirects based on HTTP_X_URL_SCHEME set by proxy
122 # enable https redirects based on HTTP_X_URL_SCHEME set by proxy
123 app = HttpsFixup(app, config)
123 app = HttpsFixup(app, config)
124
124
125 # Establish the Registry for this application
125 # Establish the Registry for this application
126 app = RegistryManager(app)
126 app = RegistryManager(app)
127
127
128 app.config = config
128 app.config = config
129
129
130 return app
130 return app
131
131
132
132
133 def make_pyramid_app(global_config, **settings):
133 def make_pyramid_app(global_config, **settings):
134 """
134 """
135 Constructs the WSGI application based on Pyramid and wraps the Pylons based
135 Constructs the WSGI application based on Pyramid and wraps the Pylons based
136 application.
136 application.
137
137
138 Specials:
138 Specials:
139
139
140 * We migrate from Pylons to Pyramid. While doing this, we keep both
140 * We migrate from Pylons to Pyramid. While doing this, we keep both
141 frameworks functional. This involves moving some WSGI middlewares around
141 frameworks functional. This involves moving some WSGI middlewares around
142 and providing access to some data internals, so that the old code is
142 and providing access to some data internals, so that the old code is
143 still functional.
143 still functional.
144
144
145 * The application can also be integrated like a plugin via the call to
145 * The application can also be integrated like a plugin via the call to
146 `includeme`. This is accompanied with the other utility functions which
146 `includeme`. This is accompanied with the other utility functions which
147 are called. Changing this should be done with great care to not break
147 are called. Changing this should be done with great care to not break
148 cases when these fragments are assembled from another place.
148 cases when these fragments are assembled from another place.
149
149
150 """
150 """
151 # The edition string should be available in pylons too, so we add it here
151 # The edition string should be available in pylons too, so we add it here
152 # before copying the settings.
152 # before copying the settings.
153 settings.setdefault('rhodecode.edition', 'Community Edition')
153 settings.setdefault('rhodecode.edition', 'Community Edition')
154
154
155 # As long as our Pylons application does expect "unprepared" settings, make
155 # As long as our Pylons application does expect "unprepared" settings, make
156 # sure that we keep an unmodified copy. This avoids unintentional change of
156 # sure that we keep an unmodified copy. This avoids unintentional change of
157 # behavior in the old application.
157 # behavior in the old application.
158 settings_pylons = settings.copy()
158 settings_pylons = settings.copy()
159
159
160 # Some parts of the code expect a merge of global and app settings.
160 # Some parts of the code expect a merge of global and app settings.
161 settings_merged = global_config.copy()
161 settings_merged = global_config.copy()
162 settings_merged.update(settings)
162 settings_merged.update(settings)
163
163
164 sanitize_settings_and_apply_defaults(settings)
164 sanitize_settings_and_apply_defaults(settings)
165 config = Configurator(settings=settings)
165 config = Configurator(settings=settings)
166 add_pylons_compat_data(config.registry, global_config, settings_pylons)
166 add_pylons_compat_data(config.registry, global_config, settings_pylons)
167
167
168 # If this is a test run we prepare the test environment like
168 # If this is a test run we prepare the test environment like
169 # creating a test database, test search index and test repositories.
169 # creating a test database, test search index and test repositories.
170 # This has to be done before the database connection is initialized.
170 # This has to be done before the database connection is initialized.
171 # if settings['is_test']:
171 if settings['is_test']:
172 if settings['is_test']:
173 rhodecode.is_test = True
172 utils.initialize_test_environment(settings_merged)
174 utils.initialize_test_environment(settings_merged)
173
175
174 # Initialize the database connection.
176 # Initialize the database connection.
175 utils.initialize_database(settings_merged)
177 utils.initialize_database(settings_merged)
176
178
177 includeme(config)
179 includeme(config)
178 includeme_last(config)
180 includeme_last(config)
179 pyramid_app = config.make_wsgi_app()
181 pyramid_app = config.make_wsgi_app()
180 pyramid_app = wrap_app_in_wsgi_middlewares(pyramid_app, config)
182 pyramid_app = wrap_app_in_wsgi_middlewares(pyramid_app, config)
181 return pyramid_app
183 return pyramid_app
182
184
183
185
184 def add_pylons_compat_data(registry, global_config, settings):
186 def add_pylons_compat_data(registry, global_config, settings):
185 """
187 """
186 Attach data to the registry to support the Pylons integration.
188 Attach data to the registry to support the Pylons integration.
187 """
189 """
188 registry._pylons_compat_global_config = global_config
190 registry._pylons_compat_global_config = global_config
189 registry._pylons_compat_settings = settings
191 registry._pylons_compat_settings = settings
190
192
191
193
192 def includeme(config):
194 def includeme(config):
193 settings = config.registry.settings
195 settings = config.registry.settings
194
196
195 # Includes which are required. The application would fail without them.
197 # Includes which are required. The application would fail without them.
196 config.include('pyramid_mako')
198 config.include('pyramid_mako')
197 config.include('pyramid_beaker')
199 config.include('pyramid_beaker')
198 config.include('rhodecode.authentication')
200 config.include('rhodecode.authentication')
199 config.include('rhodecode.login')
201 config.include('rhodecode.login')
200 config.include('rhodecode.tweens')
202 config.include('rhodecode.tweens')
201 config.include('rhodecode.api')
203 config.include('rhodecode.api')
202
204
203 # Set the authorization policy.
205 # Set the authorization policy.
204 authz_policy = ACLAuthorizationPolicy()
206 authz_policy = ACLAuthorizationPolicy()
205 config.set_authorization_policy(authz_policy)
207 config.set_authorization_policy(authz_policy)
206
208
207 # Set the default renderer for HTML templates to mako.
209 # Set the default renderer for HTML templates to mako.
208 config.add_mako_renderer('.html')
210 config.add_mako_renderer('.html')
209
211
210 # plugin information
212 # plugin information
211 config.registry.rhodecode_plugins = {}
213 config.registry.rhodecode_plugins = {}
212
214
213 config.add_directive(
215 config.add_directive(
214 'register_rhodecode_plugin', register_rhodecode_plugin)
216 'register_rhodecode_plugin', register_rhodecode_plugin)
215 # include RhodeCode plugins
217 # include RhodeCode plugins
216 includes = aslist(settings.get('rhodecode.includes', []))
218 includes = aslist(settings.get('rhodecode.includes', []))
217 for inc in includes:
219 for inc in includes:
218 config.include(inc)
220 config.include(inc)
219
221
220 # This is the glue which allows us to migrate in chunks. By registering the
222 # This is the glue which allows us to migrate in chunks. By registering the
221 # pylons based application as the "Not Found" view in Pyramid, we will
223 # pylons based application as the "Not Found" view in Pyramid, we will
222 # fallback to the old application each time the new one does not yet know
224 # fallback to the old application each time the new one does not yet know
223 # how to handle a request.
225 # how to handle a request.
224 pylons_app = make_app(
226 pylons_app = make_app(
225 config.registry._pylons_compat_global_config,
227 config.registry._pylons_compat_global_config,
226 **config.registry._pylons_compat_settings)
228 **config.registry._pylons_compat_settings)
227 config.registry._pylons_compat_config = pylons_app.config
229 config.registry._pylons_compat_config = pylons_app.config
228 pylons_app_as_view = wsgiapp(pylons_app)
230 pylons_app_as_view = wsgiapp(pylons_app)
229 config.add_notfound_view(pylons_app_as_view)
231 config.add_notfound_view(pylons_app_as_view)
230
232
231
233
232 def includeme_last(config):
234 def includeme_last(config):
233 """
235 """
234 The static file catchall needs to be last in the view configuration.
236 The static file catchall needs to be last in the view configuration.
235 """
237 """
236 settings = config.registry.settings
238 settings = config.registry.settings
237
239
238 # Note: johbo: I would prefer to register a prefix for static files at some
240 # Note: johbo: I would prefer to register a prefix for static files at some
239 # point, e.g. move them under '_static/'. This would fully avoid that we
241 # point, e.g. move them under '_static/'. This would fully avoid that we
240 # can have name clashes with a repository name. Imaging someone calling his
242 # can have name clashes with a repository name. Imaging someone calling his
241 # repo "css" ;-) Also having an external web server to serve out the static
243 # repo "css" ;-) Also having an external web server to serve out the static
242 # files seems to be easier to set up if they have a common prefix.
244 # files seems to be easier to set up if they have a common prefix.
243 #
245 #
244 # Example: config.add_static_view('_static', path='rhodecode:public')
246 # Example: config.add_static_view('_static', path='rhodecode:public')
245 #
247 #
246 # It might be an option to register both paths for a while and then migrate
248 # It might be an option to register both paths for a while and then migrate
247 # over to the new location.
249 # over to the new location.
248
250
249 # Serving static files with a catchall.
251 # Serving static files with a catchall.
250 if settings['static_files']:
252 if settings['static_files']:
251 config.add_route('catchall_static', '/*subpath')
253 config.add_route('catchall_static', '/*subpath')
252 config.add_view(
254 config.add_view(
253 static_view('rhodecode:public'), route_name='catchall_static')
255 static_view('rhodecode:public'), route_name='catchall_static')
254
256
255
257
256 def wrap_app_in_wsgi_middlewares(pyramid_app, config):
258 def wrap_app_in_wsgi_middlewares(pyramid_app, config):
257 """
259 """
258 Apply outer WSGI middlewares around the application.
260 Apply outer WSGI middlewares around the application.
259
261
260 Part of this has been moved up from the Pylons layer, so that the
262 Part of this has been moved up from the Pylons layer, so that the
261 data is also available if old Pylons code is hit through an already ported
263 data is also available if old Pylons code is hit through an already ported
262 view.
264 view.
263 """
265 """
264 settings = config.registry.settings
266 settings = config.registry.settings
265
267
266 # Add RoutesMiddleware. Currently we have two instances in the stack. This
268 # Add RoutesMiddleware. Currently we have two instances in the stack. This
267 # is the upper one to support the pylons compatibility tween during
269 # is the upper one to support the pylons compatibility tween during
268 # migration to pyramid.
270 # migration to pyramid.
269 pyramid_app = RoutesMiddleware(
271 pyramid_app = RoutesMiddleware(
270 pyramid_app, config.registry._pylons_compat_config['routes.map'])
272 pyramid_app, config.registry._pylons_compat_config['routes.map'])
271
273
272 # TODO: johbo: Don't really see why we enable the gzip middleware when
274 # TODO: johbo: Don't really see why we enable the gzip middleware when
273 # serving static files, might be something that should have its own setting
275 # serving static files, might be something that should have its own setting
274 # as well?
276 # as well?
275 if settings['static_files']:
277 if settings['static_files']:
276 pyramid_app = make_gzip_middleware(
278 pyramid_app = make_gzip_middleware(
277 pyramid_app, settings, compress_level=1)
279 pyramid_app, settings, compress_level=1)
278
280
279 return pyramid_app
281 return pyramid_app
280
282
281
283
282 def sanitize_settings_and_apply_defaults(settings):
284 def sanitize_settings_and_apply_defaults(settings):
283 """
285 """
284 Applies settings defaults and does all type conversion.
286 Applies settings defaults and does all type conversion.
285
287
286 We would move all settings parsing and preparation into this place, so that
288 We would move all settings parsing and preparation into this place, so that
287 we have only one place left which deals with this part. The remaining parts
289 we have only one place left which deals with this part. The remaining parts
288 of the application would start to rely fully on well prepared settings.
290 of the application would start to rely fully on well prepared settings.
289
291
290 This piece would later be split up per topic to avoid a big fat monster
292 This piece would later be split up per topic to avoid a big fat monster
291 function.
293 function.
292 """
294 """
293
295
294 # Pyramid's mako renderer has to search in the templates folder so that the
296 # Pyramid's mako renderer has to search in the templates folder so that the
295 # old templates still work. Ported and new templates are expected to use
297 # old templates still work. Ported and new templates are expected to use
296 # real asset specifications for the includes.
298 # real asset specifications for the includes.
297 mako_directories = settings.setdefault('mako.directories', [
299 mako_directories = settings.setdefault('mako.directories', [
298 # Base templates of the original Pylons application
300 # Base templates of the original Pylons application
299 'rhodecode:templates',
301 'rhodecode:templates',
300 ])
302 ])
301 log.debug(
303 log.debug(
302 "Using the following Mako template directories: %s",
304 "Using the following Mako template directories: %s",
303 mako_directories)
305 mako_directories)
304
306
305 # Default includes, possible to change as a user
307 # Default includes, possible to change as a user
306 pyramid_includes = settings.setdefault('pyramid.includes', [
308 pyramid_includes = settings.setdefault('pyramid.includes', [
307 'rhodecode.lib.middleware.request_wrapper',
309 'rhodecode.lib.middleware.request_wrapper',
308 ])
310 ])
309 log.debug(
311 log.debug(
310 "Using the following pyramid.includes: %s",
312 "Using the following pyramid.includes: %s",
311 pyramid_includes)
313 pyramid_includes)
312
314
313 # TODO: johbo: Re-think this, usually the call to config.include
315 # TODO: johbo: Re-think this, usually the call to config.include
314 # should allow to pass in a prefix.
316 # should allow to pass in a prefix.
315 settings.setdefault('rhodecode.api.url', '/_admin/api')
317 settings.setdefault('rhodecode.api.url', '/_admin/api')
316
318
317 _bool_setting(settings, 'vcs.server.enable', 'true')
319 _bool_setting(settings, 'vcs.server.enable', 'true')
318 _bool_setting(settings, 'static_files', 'true')
320 _bool_setting(settings, 'static_files', 'true')
321 _bool_setting(settings, 'is_test', 'false')
319
322
320 return settings
323 return settings
321
324
322
325
323 def _bool_setting(settings, name, default):
326 def _bool_setting(settings, name, default):
324 settings[name] = asbool(settings.get(name, default))
327 settings[name] = asbool(settings.get(name, default))
General Comments 0
You need to be logged in to leave comments. Login now