##// END OF EJS Templates
config: initialize routes directly from RootController...
Thomas De Schampheleire -
r6530:69cd0c05 default
parent child Browse files
Show More
@@ -1,190 +1,185 b''
1 1 # -*- coding: utf-8 -*-
2 2 # This program is free software: you can redistribute it and/or modify
3 3 # it under the terms of the GNU General Public License as published by
4 4 # the Free Software Foundation, either version 3 of the License, or
5 5 # (at your option) any later version.
6 6 #
7 7 # This program is distributed in the hope that it will be useful,
8 8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 10 # GNU General Public License for more details.
11 11 #
12 12 # You should have received a copy of the GNU General Public License
13 13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 14 """
15 15 Global configuration file for TurboGears2 specific settings in Kallithea.
16 16
17 17 This file complements the .ini file.
18 18 """
19 19
20 20 import platform
21 21 import os, sys
22 22
23 23 import tg
24 24 from tg import hooks
25 25 from tg.configuration import AppConfig
26 26 from tg.support.converters import asbool
27 27
28 28 from kallithea.lib.middleware.https_fixup import HttpsFixup
29 29 from kallithea.lib.middleware.simplegit import SimpleGit
30 30 from kallithea.lib.middleware.simplehg import SimpleHg
31 from kallithea.config.routing import make_map
32 31 from kallithea.lib.auth import set_available_permissions
33 32 from kallithea.lib.db_manage import DbManage
34 33 from kallithea.lib.utils import load_rcextensions, make_ui, set_app_settings, set_vcs_config, \
35 34 set_indexer_config, check_git_version, repo2db_mapper
36 35 from kallithea.lib.utils2 import str2bool
37 36 from kallithea.model.scm import ScmModel
38 37
39 38 import formencode
40 39 import kallithea
41 40
42 41
43 42 class KallitheaAppConfig(AppConfig):
44 43 # Note: AppConfig has a misleading name, as it's not the application
45 44 # configuration, but the application configurator. The AppConfig values are
46 45 # used as a template to create the actual configuration, which might
47 46 # overwrite or extend the one provided by the configurator template.
48 47
49 48 # To make it clear, AppConfig creates the config and sets into it the same
50 49 # values that AppConfig itself has. Then the values from the config file and
51 50 # gearbox options are loaded and merged into the configuration. Then an
52 51 # after_init_config(conf) method of AppConfig is called for any change that
53 52 # might depend on options provided by configuration files.
54 53
55 54 def __init__(self):
56 55 super(KallitheaAppConfig, self).__init__()
57 56
58 57 self['package'] = kallithea
59 58
60 59 self['prefer_toscawidgets2'] = False
61 60 self['use_toscawidgets'] = False
62 61
63 62 self['renderers'] = []
64 63
65 64 # Enable json in expose
66 65 self['renderers'].append('json')
67 66
68 67 # Configure template rendering
69 68 self['renderers'].append('mako')
70 69 self['default_renderer'] = 'mako'
71 70 self['use_dotted_templatenames'] = False
72 71
73 72 # Configure Sessions, store data as JSON to avoid pickle security issues
74 73 self['session.enabled'] = True
75 74 self['session.data_serializer'] = 'json'
76 75
77 76 # Configure the base SQLALchemy Setup
78 77 self['use_sqlalchemy'] = True
79 78 self['model'] = kallithea.model.base
80 79 self['DBSession'] = kallithea.model.meta.Session
81 80
82 81 # Configure App without an authentication backend.
83 82 self['auth_backend'] = None
84 83
85 84 # Use custom error page for these errors. By default, Turbogears2 does not add
86 85 # 400 in this list.
87 86 # Explicitly listing all is considered more robust than appending to defaults,
88 87 # in light of possible future framework changes.
89 88 self['errorpage.status_codes'] = [400, 401, 403, 404]
90 89
91 90 # Disable transaction manager -- currently Kallithea takes care of transactions itself
92 91 self['tm.enabled'] = False
93 92
94 93 base_config = KallitheaAppConfig()
95 94
96 95 # TODO still needed as long as we use pylonslib
97 96 sys.modules['pylons'] = tg
98 97
99 98 # DebugBar, a debug toolbar for TurboGears2.
100 99 # (https://github.com/TurboGears/tgext.debugbar)
101 100 # To enable it, install 'tgext.debugbar' and 'kajiki', and run Kallithea with
102 101 # 'debug = true' (not in production!)
103 102 # See the Kallithea documentation for more information.
104 103 try:
105 104 from tgext.debugbar import enable_debugbar
106 105 import kajiki # only to check its existence
107 106 except ImportError:
108 107 pass
109 108 else:
110 109 base_config['renderers'].append('kajiki')
111 110 enable_debugbar(base_config)
112 111
113 112
114 113 def setup_configuration(app):
115 114 config = app.config
116 115
117 116 # store some globals into kallithea
118 117 kallithea.CELERY_ON = str2bool(config['app_conf'].get('use_celery'))
119 118 kallithea.CELERY_EAGER = str2bool(config['app_conf'].get('celery.always.eager'))
120 119 kallithea.CONFIG = config
121 120
122 # Provide routes mapper to the RoutedController
123 root_controller = app.find_controller('root')
124 root_controller.mapper = config['routes.map'] = make_map(config)
125
126 121 load_rcextensions(root_path=config['here'])
127 122
128 123 # FIXME move test setup code out of here
129 124 test = os.path.split(config['__file__'])[-1] == 'test.ini'
130 125 if test:
131 126 test_env = not int(os.environ.get('KALLITHEA_NO_TMP_PATH', 0))
132 127 test_index = not int(os.environ.get('KALLITHEA_WHOOSH_TEST_DISABLE', 0))
133 128 if os.environ.get('TEST_DB'):
134 129 # swap config if we pass environment variable
135 130 config['sqlalchemy.url'] = os.environ.get('TEST_DB')
136 131
137 132 from kallithea.tests.fixture import create_test_env, create_test_index
138 133 from kallithea.tests.base import TESTS_TMP_PATH
139 134 #set KALLITHEA_NO_TMP_PATH=1 to disable re-creating the database and
140 135 #test repos
141 136 if test_env:
142 137 create_test_env(TESTS_TMP_PATH, config)
143 138 #set KALLITHEA_WHOOSH_TEST_DISABLE=1 to disable whoosh index during tests
144 139 if test_index:
145 140 create_test_index(TESTS_TMP_PATH, config, True)
146 141
147 142 set_available_permissions(config)
148 143 repos_path = make_ui('db').configitems('paths')[0][1]
149 144 config['base_path'] = repos_path
150 145 set_app_settings(config)
151 146
152 147 instance_id = kallithea.CONFIG.get('instance_id', '*')
153 148 if instance_id == '*':
154 149 instance_id = '%s-%s' % (platform.uname()[1], os.getpid())
155 150 kallithea.CONFIG['instance_id'] = instance_id
156 151
157 152 # update kallithea.CONFIG with the meanwhile changed 'config'
158 153 kallithea.CONFIG.update(config)
159 154
160 155 # configure vcs and indexer libraries (they are supposed to be independent
161 156 # as much as possible and thus avoid importing tg.config or
162 157 # kallithea.CONFIG).
163 158 set_vcs_config(kallithea.CONFIG)
164 159 set_indexer_config(kallithea.CONFIG)
165 160
166 161 check_git_version()
167 162
168 163 if str2bool(config.get('initial_repo_scan', True)):
169 164 repo2db_mapper(ScmModel().repo_scan(repos_path),
170 165 remove_obsolete=False, install_git_hooks=False)
171 166
172 167 formencode.api.set_stdtranslation(languages=[config.get('lang')])
173 168
174 169 hooks.register('configure_new_app', setup_configuration)
175 170
176 171
177 172 def setup_application(app):
178 173 config = app.config
179 174
180 175 # we want our low level middleware to get to the request ASAP. We don't
181 176 # need any stack middleware in them - especially no StatusCodeRedirect buffering
182 177 app = SimpleHg(app, config)
183 178 app = SimpleGit(app, config)
184 179
185 180 # Enable https redirects based on HTTP_X_URL_SCHEME set by proxy
186 181 if any(asbool(config.get(x)) for x in ['https_fixup', 'force_https', 'use_htsts']):
187 182 app = HttpsFixup(app, config)
188 183 return app
189 184
190 185 hooks.register('before_config', setup_application)
@@ -1,31 +1,32 b''
1 1 # -*- coding: utf-8 -*-
2 2 # This program is free software: you can redistribute it and/or modify
3 3 # it under the terms of the GNU General Public License as published by
4 4 # the Free Software Foundation, either version 3 of the License, or
5 5 # (at your option) any later version.
6 6 #
7 7 # This program is distributed in the hope that it will be useful,
8 8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 10 # GNU General Public License for more details.
11 11 #
12 12 # You should have received a copy of the GNU General Public License
13 13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 14 from tgext.routes import RoutedController
15 from kallithea.config.routing import make_map
15 16 from kallithea.lib.base import BaseController
16 17 from kallithea.controllers.error import ErrorController
17
18 from tg import config
18 19
19 # With TurboGears, the RootController is the controller from which all routing
20 # starts from. It is 'magically' found based on the fact that a controller
21 # 'foo' is expected to have a class name FooController, located in a file
22 # foo.py, inside config['paths']['controllers']. The name 'root' for the root
23 # controller is the default name. The dictionary config['paths'] determines the
24 # directories where templates, static files and controllers are found. It is
25 # set up in tg.AppConfig based on AppConfig['package'] ('kallithea') and the
26 # respective defaults 'templates', 'public' and 'controllers'.
27 # Inherit from RoutedController to allow Kallithea to use regex-based routing.
20 # This is the main Kallithea entry point; TurboGears will forward all requests
21 # to an instance of 'controller.root.RootController' in the configured
22 # 'application' module (set by app_cfg.py). Requests are forwarded to
23 # controllers based on the routing mapper that lives in this root instance.
24 # The mapper is configured using routes defined in routing.py. This use of the
25 # 'mapper' attribute is a feature of tgext.routes, which is activated by
26 # inheriting from its RoutedController class.
28 27 class RootController(RoutedController, BaseController):
29 28
29 mapper = make_map(config)
30
30 31 # the following assignment hooks in error handling
31 32 error = ErrorController()
@@ -1,122 +1,123 b''
1 1 import os
2 2 import sys
3 3 import logging
4 4 import pkg_resources
5 5
6 6 from paste.deploy import loadapp
7 7 from routes.util import URLGenerator
8 8 from tg import config
9 9
10 10 import pytest
11 from kallithea.controllers.root import RootController
11 12 from kallithea.model.user import UserModel
12 13 from kallithea.model.meta import Session
13 14 from kallithea.model.db import Setting, User, UserIpMap
14 15 from kallithea.tests.base import invalidate_all_caches, TEST_USER_REGULAR_LOGIN
15 16 import kallithea.tests.base # FIXME: needed for setting testapp instance!!!
16 17
17 18 from tg.util.webtest import test_context
18 19
19 20 def pytest_configure():
20 21 path = os.getcwd()
21 22 sys.path.insert(0, path)
22 23 pkg_resources.working_set.add_entry(path)
23 24
24 25 # Disable INFO logging of test database creation, restore with NOTSET
25 26 logging.disable(logging.INFO)
26 27 kallithea.tests.base.testapp = loadapp('config:kallithea/tests/test.ini', relative_to=path)
27 28 logging.disable(logging.NOTSET)
28 29
29 kallithea.tests.base.url = URLGenerator(config['routes.map'], kallithea.tests.base.environ)
30 kallithea.tests.base.url = URLGenerator(RootController().mapper, kallithea.tests.base.environ)
30 31
31 32
32 33 @pytest.fixture
33 34 def create_test_user():
34 35 """Provide users that automatically disappear after test is over."""
35 36 test_user_ids = []
36 37 def _create_test_user(user_form):
37 38 user = UserModel().create(user_form)
38 39 test_user_ids.append(user.user_id)
39 40 return user
40 41 yield _create_test_user
41 42 for user_id in test_user_ids:
42 43 UserModel().delete(user_id)
43 44 Session().commit()
44 45
45 46
46 47 def _set_settings(*kvtseq):
47 48 session = Session()
48 49 for kvt in kvtseq:
49 50 assert len(kvt) in (2, 3)
50 51 k = kvt[0]
51 52 v = kvt[1]
52 53 t = kvt[2] if len(kvt) == 3 else 'unicode'
53 54 Setting.create_or_update(k, v, t)
54 55 session.commit()
55 56
56 57
57 58 @pytest.fixture
58 59 def set_test_settings():
59 60 """Restore settings after test is over."""
60 61 # Save settings.
61 62 settings_snapshot = [
62 63 (s.app_settings_name, s.app_settings_value, s.app_settings_type)
63 64 for s in Setting.query().all()]
64 65 yield _set_settings
65 66 # Restore settings.
66 67 session = Session()
67 68 keys = frozenset(k for (k, v, t) in settings_snapshot)
68 69 for s in Setting.query().all():
69 70 if s.app_settings_name not in keys:
70 71 session.delete(s)
71 72 for k, v, t in settings_snapshot:
72 73 if t == 'list' and hasattr(v, '__iter__'):
73 74 v = ','.join(v) # Quirk: must format list value manually.
74 75 Setting.create_or_update(k, v, t)
75 76 session.commit()
76 77
77 78 @pytest.fixture
78 79 def auto_clear_ip_permissions():
79 80 """Fixture that provides nothing but clearing IP permissions upon test
80 81 exit. This clearing is needed to avoid other test failing to make fake http
81 82 accesses."""
82 83 yield
83 84 # cleanup
84 85 user_model = UserModel()
85 86
86 87 user_ids = []
87 88 user_ids.append(User.get_default_user().user_id)
88 89 user_ids.append(User.get_by_username(TEST_USER_REGULAR_LOGIN).user_id)
89 90
90 91 for user_id in user_ids:
91 92 for ip in UserIpMap.query().filter(UserIpMap.user_id == user_id):
92 93 user_model.delete_extra_ip(user_id, ip.ip_id)
93 94
94 95 # IP permissions are cached, need to invalidate this cache explicitly
95 96 invalidate_all_caches()
96 97
97 98 @pytest.fixture
98 99 def test_context_fixture(app_fixture):
99 100 """
100 101 Encompass the entire test using this fixture in a test_context,
101 102 making sure that certain functionality still works even if no call to
102 103 self.app.get/post has been made.
103 104 The typical error message indicating you need a test_context is:
104 105 TypeError: No object (name: context) has been registered for this thread
105 106
106 107 The standard way to fix this is simply using the test_context context
107 108 manager directly inside your test:
108 109 with test_context(self.app):
109 110 <actions>
110 111 but if test setup code (xUnit-style or pytest fixtures) also needs to be
111 112 executed inside the test context, that method is not possible.
112 113 Even if there is no such setup code, the fixture may reduce code complexity
113 114 if the entire test needs to run inside a test context.
114 115
115 116 To apply this fixture (like any other fixture) to all test methods of a
116 117 class, use the following class decorator:
117 118 @pytest.mark.usefixtures("test_context_fixture")
118 119 class TestFoo(TestController):
119 120 ...
120 121 """
121 122 with test_context(app_fixture):
122 123 yield
General Comments 0
You need to be logged in to leave comments. Login now