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