Show More
@@ -0,0 +1,31 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
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 | |
|
4 | # the Free Software Foundation, either version 3 of the License, or | |
|
5 | # (at your option) any later version. | |
|
6 | # | |
|
7 | # This program is distributed in the hope that it will be useful, | |
|
8 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
|
9 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
|
10 | # GNU General Public License for more details. | |
|
11 | # | |
|
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/>. | |
|
14 | from tgext.routes import RoutedController | |
|
15 | from kallithea.lib.base import BaseController | |
|
16 | from kallithea.controllers.error import ErrorController | |
|
17 | ||
|
18 | ||
|
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. | |
|
28 | class RootController(RoutedController, BaseController): | |
|
29 | ||
|
30 | # the following assignment hooks in error handling | |
|
31 | error = ErrorController() |
@@ -512,7 +512,7 b' script_location = kallithea:alembic' | |||
|
512 | 512 | ################################ |
|
513 | 513 | |
|
514 | 514 | [loggers] |
|
515 | keys = root, routes, kallithea, sqlalchemy, gearbox, beaker, templates, whoosh_indexer | |
|
515 | keys = root, routes, kallithea, sqlalchemy, tg, gearbox, beaker, templates, whoosh_indexer | |
|
516 | 516 | |
|
517 | 517 | [handlers] |
|
518 | 518 | keys = console, console_sql |
@@ -553,6 +553,12 b' handlers =' | |||
|
553 | 553 | qualname = kallithea |
|
554 | 554 | propagate = 1 |
|
555 | 555 | |
|
556 | [logger_tg] | |
|
557 | level = DEBUG | |
|
558 | handlers = | |
|
559 | qualname = tg | |
|
560 | propagate = 1 | |
|
561 | ||
|
556 | 562 | [logger_gearbox] |
|
557 | 563 | level = DEBUG |
|
558 | 564 | handlers = |
@@ -30,10 +30,6 b' Original author and date, and relevant c' | |||
|
30 | 30 | import sys |
|
31 | 31 | import platform |
|
32 | 32 | |
|
33 | # temporary aliasing to allow early introduction of imports like 'from tg import request' | |
|
34 | import pylons | |
|
35 | sys.modules['tg'] = pylons | |
|
36 | ||
|
37 | 33 | VERSION = (0, 3, 99) |
|
38 | 34 | BACKENDS = { |
|
39 | 35 | 'hg': 'Mercurial repository', |
@@ -11,76 +11,112 b'' | |||
|
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 | """ | |
|
15 | Global configuration file for TurboGears2 specific settings in Kallithea. | |
|
14 | 16 |
|
|
15 | import os | |
|
16 | import kallithea | |
|
17 | This file complements the .ini file. | |
|
18 | """ | |
|
19 | ||
|
17 | 20 | import platform |
|
18 | ||
|
19 | import pylons | |
|
20 | import mako.lookup | |
|
21 | import formencode | |
|
21 | import os, sys | |
|
22 | 22 | |
|
23 | import kallithea.lib.app_globals as app_globals | |
|
24 | ||
|
25 |
from |
|
|
23 | import tg | |
|
24 | from tg import hooks | |
|
25 | from tg.configuration import AppConfig | |
|
26 | from tg.support.converters import asbool | |
|
26 | 27 | |
|
27 |
from kallithea.lib import |
|
|
28 | from kallithea.lib.middleware.https_fixup import HttpsFixup | |
|
29 | from kallithea.lib.middleware.simplegit import SimpleGit | |
|
30 | from kallithea.lib.middleware.simplehg import SimpleHg | |
|
31 | from kallithea.config.routing import make_map | |
|
28 | 32 | from kallithea.lib.auth import set_available_permissions |
|
29 | from kallithea.lib.utils import repo2db_mapper, make_ui, set_app_settings, \ | |
|
30 | load_rcextensions, check_git_version, set_vcs_config, set_indexer_config | |
|
31 | from kallithea.lib.utils2 import engine_from_config, str2bool | |
|
32 |
from kallithea. |
|
|
33 | from kallithea.lib.db_manage import DbManage | |
|
34 | from kallithea.lib.utils import load_rcextensions, make_ui, set_app_settings, set_vcs_config, \ | |
|
35 | set_indexer_config, check_git_version, repo2db_mapper | |
|
36 | from kallithea.lib.utils2 import str2bool | |
|
33 | 37 | from kallithea.model.scm import ScmModel |
|
34 | 38 | |
|
35 | from routes.middleware import RoutesMiddleware | |
|
36 | from paste.cascade import Cascade | |
|
37 | from paste.registry import RegistryManager | |
|
38 | from paste.urlparser import StaticURLParser | |
|
39 | from paste.deploy.converters import asbool | |
|
39 | import formencode | |
|
40 | import kallithea | |
|
41 | ||
|
42 | ||
|
43 | class KallitheaAppConfig(AppConfig): | |
|
44 | # Note: AppConfig has a misleading name, as it's not the application | |
|
45 | # configuration, but the application configurator. The AppConfig values are | |
|
46 | # used as a template to create the actual configuration, which might | |
|
47 | # overwrite or extend the one provided by the configurator template. | |
|
48 | ||
|
49 | # 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 | |
|
51 | # 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 | |
|
53 | # might depend on options provided by configuration files. | |
|
54 | ||
|
55 | def __init__(self): | |
|
56 | super(KallitheaAppConfig, self).__init__() | |
|
57 | ||
|
58 | self['package'] = kallithea | |
|
59 | ||
|
60 | self['prefer_toscawidgets2'] = False | |
|
61 | self['use_toscawidgets'] = False | |
|
62 | ||
|
63 | self['renderers'] = [] | |
|
64 | ||
|
65 | # Enable json in expose | |
|
66 | self['renderers'].append('json') | |
|
40 | 67 | |
|
41 | from pylons.middleware import ErrorHandler, StatusCodeRedirect | |
|
42 | from pylons.wsgiapp import PylonsApp | |
|
68 | # Configure template rendering | |
|
69 | self['renderers'].append('mako') | |
|
70 | self['default_renderer'] = 'mako' | |
|
71 | self['use_dotted_templatenames'] = False | |
|
72 | ||
|
73 | # Configure Sessions, store data as JSON to avoid pickle security issues | |
|
74 | self['session.enabled'] = True | |
|
75 | self['session.data_serializer'] = 'json' | |
|
76 | ||
|
77 | # Configure the base SQLALchemy Setup | |
|
78 | self['use_sqlalchemy'] = True | |
|
79 | self['model'] = kallithea.model.base | |
|
80 | self['DBSession'] = kallithea.model.meta.Session | |
|
81 | ||
|
82 | # Configure App without an authentication backend. | |
|
83 | self['auth_backend'] = None | |
|
43 | 84 | |
|
44 | from kallithea.lib.middleware.simplehg import SimpleHg | |
|
45 | from kallithea.lib.middleware.simplegit import SimpleGit | |
|
46 | from kallithea.lib.middleware.https_fixup import HttpsFixup | |
|
47 | from kallithea.lib.middleware.sessionmiddleware import SecureSessionMiddleware | |
|
48 | from kallithea.lib.middleware.wrapper import RequestWrapper | |
|
85 | # Use custom error page for these errors. By default, Turbogears2 does not add | |
|
86 | # 400 in this list. | |
|
87 | # Explicitly listing all is considered more robust than appending to defaults, | |
|
88 | # in light of possible future framework changes. | |
|
89 | self['errorpage.status_codes'] = [400, 401, 403, 404] | |
|
49 | 90 | |
|
50 | def setup_configuration(config, paths, app_conf, test_env, test_index): | |
|
91 | # Disable transaction manager -- currently Kallithea takes care of transactions itself | |
|
92 | self['tm.enabled'] = False | |
|
93 | ||
|
94 | base_config = KallitheaAppConfig() | |
|
95 | ||
|
96 | # TODO still needed as long as we use pylonslib | |
|
97 | sys.modules['pylons'] = tg | |
|
98 | ||
|
99 | def setup_configuration(app): | |
|
100 | config = app.config | |
|
51 | 101 | |
|
52 | 102 | # store some globals into kallithea |
|
53 | 103 | kallithea.CELERY_ON = str2bool(config['app_conf'].get('use_celery')) |
|
54 | 104 | kallithea.CELERY_EAGER = str2bool(config['app_conf'].get('celery.always.eager')) |
|
105 | kallithea.CONFIG = config | |
|
55 | 106 | |
|
56 | config['routes.map'] = make_map(config) | |
|
57 | config['pylons.app_globals'] = app_globals.Globals(config) | |
|
58 | config['pylons.h'] = helpers | |
|
59 | kallithea.CONFIG = config | |
|
107 | # Provide routes mapper to the RoutedController | |
|
108 | root_controller = app.find_controller('root') | |
|
109 | root_controller.mapper = config['routes.map'] = make_map(config) | |
|
60 | 110 | |
|
61 | 111 | load_rcextensions(root_path=config['here']) |
|
62 | 112 | |
|
63 | # Setup cache object as early as possible | |
|
64 | pylons.cache._push_object(config['pylons.app_globals'].cache) | |
|
65 | ||
|
66 | # Create the Mako TemplateLookup, with the default auto-escaping | |
|
67 | config['pylons.app_globals'].mako_lookup = mako.lookup.TemplateLookup( | |
|
68 | directories=paths['templates'], | |
|
69 | strict_undefined=True, | |
|
70 | module_directory=os.path.join(app_conf['cache_dir'], 'templates'), | |
|
71 | input_encoding='utf-8', default_filters=['escape'], | |
|
72 | imports=['from webhelpers.html import escape']) | |
|
73 | ||
|
74 | # sets the c attribute access when don't existing attribute are accessed | |
|
75 | config['pylons.strict_tmpl_context'] = True | |
|
113 | # FIXME move test setup code out of here | |
|
76 | 114 | test = os.path.split(config['__file__'])[-1] == 'test.ini' |
|
77 | 115 | if test: |
|
78 | if test_env is None: | |
|
79 |
|
|
|
80 | if test_index is None: | |
|
81 | test_index = not int(os.environ.get('KALLITHEA_WHOOSH_TEST_DISABLE', 0)) | |
|
116 | test_env = not int(os.environ.get('KALLITHEA_NO_TMP_PATH', 0)) | |
|
117 | test_index = not int(os.environ.get('KALLITHEA_WHOOSH_TEST_DISABLE', 0)) | |
|
82 | 118 | if os.environ.get('TEST_DB'): |
|
83 | # swap config if we pass enviroment variable | |
|
119 | # swap config if we pass environment variable | |
|
84 | 120 | config['sqlalchemy.url'] = os.environ.get('TEST_DB') |
|
85 | 121 | |
|
86 | 122 | from kallithea.tests.fixture import create_test_env, create_test_index |
@@ -93,11 +129,6 b' def setup_configuration(config, paths, a' | |||
|
93 | 129 | if test_index: |
|
94 | 130 | create_test_index(TESTS_TMP_PATH, config, True) |
|
95 | 131 | |
|
96 | # MULTIPLE DB configs | |
|
97 | # Setup the SQLAlchemy database engine | |
|
98 | sa_engine = engine_from_config(config, 'sqlalchemy.') | |
|
99 | init_model(sa_engine) | |
|
100 | ||
|
101 | 132 | set_available_permissions(config) |
|
102 | 133 | repos_path = make_ui('db').configitems('paths')[0][1] |
|
103 | 134 | config['base_path'] = repos_path |
@@ -108,78 +139,37 b' def setup_configuration(config, paths, a' | |||
|
108 | 139 | instance_id = '%s-%s' % (platform.uname()[1], os.getpid()) |
|
109 | 140 | kallithea.CONFIG['instance_id'] = instance_id |
|
110 | 141 | |
|
111 | # CONFIGURATION OPTIONS HERE (note: all config options will override | |
|
112 | # any Pylons config options) | |
|
142 | # update kallithea.CONFIG with the meanwhile changed 'config' | |
|
143 | kallithea.CONFIG.update(config) | |
|
113 | 144 | |
|
114 | # store config reference into our module to skip import magic of | |
|
115 | # pylons | |
|
116 |
kallithea.CONFIG. |
|
|
145 | # configure vcs and indexer libraries (they are supposed to be independent | |
|
146 | # as much as possible and thus avoid importing tg.config or | |
|
147 | # kallithea.CONFIG). | |
|
117 | 148 | set_vcs_config(kallithea.CONFIG) |
|
118 | 149 | set_indexer_config(kallithea.CONFIG) |
|
119 | 150 | |
|
120 | #check git version | |
|
121 | 151 | check_git_version() |
|
122 | 152 | |
|
123 | 153 | if str2bool(config.get('initial_repo_scan', True)): |
|
124 | 154 | repo2db_mapper(ScmModel().repo_scan(repos_path), |
|
125 | 155 | remove_obsolete=False, install_git_hooks=False) |
|
156 | ||
|
126 | 157 | formencode.api.set_stdtranslation(languages=[config.get('lang')]) |
|
127 | 158 | |
|
128 | return config | |
|
129 | ||
|
130 | def setup_application(config, global_conf, full_stack, static_files): | |
|
159 | hooks.register('configure_new_app', setup_configuration) | |
|
131 | 160 | |
|
132 | # The Pylons WSGI app | |
|
133 | app = PylonsApp(config=config) | |
|
134 | ||
|
135 | # Routing/Session/Cache Middleware | |
|
136 | app = RoutesMiddleware(app, config['routes.map'], use_method_override=False) | |
|
137 | app = SecureSessionMiddleware(app, config) | |
|
138 | 161 | |
|
139 | # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) | |
|
140 | if asbool(config['pdebug']): | |
|
141 | from kallithea.lib.profiler import ProfilingMiddleware | |
|
142 | app = ProfilingMiddleware(app) | |
|
143 | ||
|
144 | if asbool(full_stack): | |
|
145 | ||
|
146 | from kallithea.lib.middleware.sentry import Sentry | |
|
147 | from kallithea.lib.middleware.appenlight import AppEnlight | |
|
148 | if AppEnlight and asbool(config['app_conf'].get('appenlight')): | |
|
149 | app = AppEnlight(app, config) | |
|
150 | elif Sentry: | |
|
151 | app = Sentry(app, config) | |
|
152 | ||
|
153 | # Handle Python exceptions | |
|
154 | app = ErrorHandler(app, global_conf, **config['pylons.errorware']) | |
|
162 | def setup_application(app): | |
|
163 | config = app.config | |
|
155 | 164 | |
|
156 | # Display error documents for 401, 403, 404 status codes (and | |
|
157 | # 500 when debug is disabled) | |
|
158 | # Note: will buffer the output in memory! | |
|
159 | if asbool(config['debug']): | |
|
160 | app = StatusCodeRedirect(app) | |
|
161 | else: | |
|
162 | app = StatusCodeRedirect(app, [400, 401, 403, 404, 500]) | |
|
163 | ||
|
164 | # we want our low level middleware to get to the request ASAP. We don't | |
|
165 | # need any pylons stack middleware in them - especially no StatusCodeRedirect buffering | |
|
166 | app = SimpleHg(app, config) | |
|
167 | app = SimpleGit(app, config) | |
|
165 | # we want our low level middleware to get to the request ASAP. We don't | |
|
166 | # need any stack middleware in them - especially no StatusCodeRedirect buffering | |
|
167 | app = SimpleHg(app, config) | |
|
168 | app = SimpleGit(app, config) | |
|
168 | 169 | |
|
169 |
|
|
|
170 |
|
|
|
171 |
|
|
|
172 | ||
|
173 | app = RequestWrapper(app, config) # logging | |
|
174 | ||
|
175 | # Establish the Registry for this application | |
|
176 | app = RegistryManager(app) # thread / request-local module globals / variables | |
|
170 | # Enable https redirects based on HTTP_X_URL_SCHEME set by proxy | |
|
171 | if any(asbool(config.get(x)) for x in ['https_fixup', 'force_https', 'use_htsts']): | |
|
172 | app = HttpsFixup(app, config) | |
|
173 | return app | |
|
177 | 174 | |
|
178 | if asbool(static_files): | |
|
179 | # Serve static files | |
|
180 | static_app = StaticURLParser(config['pylons.paths']['static_files']) | |
|
181 | app = Cascade([static_app, app]) | |
|
182 | ||
|
183 | app.config = config | |
|
184 | ||
|
185 | return app | |
|
175 | hooks.register('before_config', setup_application) |
@@ -11,34 +11,11 b'' | |||
|
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 | """ | |
|
15 | Pylons environment configuration | |
|
16 | """ | |
|
14 | """WSGI environment setup for Kallithea.""" | |
|
17 | 15 | |
|
18 | import os | |
|
19 | import kallithea | |
|
20 | import pylons | |
|
21 | ||
|
22 | from kallithea.config.app_cfg import setup_configuration | |
|
16 | from kallithea.config.app_cfg import base_config | |
|
23 | 17 | |
|
24 | def load_environment(global_conf, app_conf, | |
|
25 | test_env=None, test_index=None): | |
|
26 | """ | |
|
27 | Configure the Pylons environment via the ``pylons.config`` | |
|
28 | object | |
|
29 | """ | |
|
30 | config = pylons.configuration.PylonsConfig() | |
|
18 | __all__ = ['load_environment'] | |
|
31 | 19 | |
|
32 | # Pylons paths | |
|
33 | root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | |
|
34 | paths = dict( | |
|
35 | root=root, | |
|
36 | controllers=os.path.join(root, 'controllers'), | |
|
37 | static_files=os.path.join(root, 'public'), | |
|
38 | templates=[os.path.join(root, 'templates')] | |
|
39 | ) | |
|
40 | ||
|
41 | # Initialize config with the basic options | |
|
42 | config.init_app(global_conf, app_conf, package='kallithea', paths=paths) | |
|
43 | ||
|
44 | return setup_configuration(config, paths, app_conf, test_env, test_index) | |
|
20 | # Use base_config to setup the environment loader function | |
|
21 | load_environment = base_config.make_load_environment() |
@@ -11,33 +11,35 b'' | |||
|
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 | """ | |
|
15 | Pylons middleware initialization | |
|
16 | """ | |
|
14 | """WSGI middleware initialization for the Kallithea application.""" | |
|
17 | 15 | |
|
18 |
from kallithea.config.app_cfg import se |
|
|
16 | from kallithea.config.app_cfg import base_config | |
|
19 | 17 | from kallithea.config.environment import load_environment |
|
20 | 18 | |
|
21 | def make_app(global_conf, full_stack=True, static_files=True, **app_conf): | |
|
22 | """Create a Pylons WSGI application and return it | |
|
19 | __all__ = ['make_app'] | |
|
20 | ||
|
21 | # Use base_config to setup the necessary PasteDeploy application factory. | |
|
22 | # make_base_app will wrap the TurboGears2 app with all the middleware it needs. | |
|
23 | make_base_app = base_config.setup_tg_wsgi_app(load_environment) | |
|
23 | 24 | |
|
24 | ``global_conf`` | |
|
25 | The inherited configuration for this application. Normally from | |
|
26 | the [DEFAULT] section of the Paste ini file. | |
|
25 | ||
|
26 | def make_app(global_conf, full_stack=True, **app_conf): | |
|
27 | """ | |
|
28 | Set up Kallithea with the settings found in the PasteDeploy configuration | |
|
29 | file used. | |
|
27 | 30 | |
|
28 | ``full_stack`` | |
|
29 | Whether or not this application provides a full WSGI stack (by | |
|
30 | default, meaning it handles its own exceptions and errors). | |
|
31 | Disable full_stack when this application is "managed" by | |
|
32 | another WSGI middleware. | |
|
31 | :param global_conf: The global settings for Kallithea (those | |
|
32 | defined under the ``[DEFAULT]`` section). | |
|
33 | :type global_conf: dict | |
|
34 | :param full_stack: Should the whole TurboGears2 stack be set up? | |
|
35 | :type full_stack: str or bool | |
|
36 | :return: The Kallithea application with all the relevant middleware | |
|
37 | loaded. | |
|
33 | 38 | |
|
34 | ``app_conf`` | |
|
35 | The application's local configuration. Normally specified in | |
|
36 | the [app:<name>] section of the Paste ini file (where <name> | |
|
37 | defaults to main). | |
|
39 | This is the PasteDeploy factory for the Kallithea application. | |
|
38 | 40 | |
|
41 | ``app_conf`` contains all the application-specific settings (those defined | |
|
42 | under ``[app:main]``. | |
|
39 | 43 | """ |
|
40 | # Configure the Pylons environment | |
|
41 | config = load_environment(global_conf, app_conf) | |
|
42 | ||
|
43 | return setup_application(config, global_conf, full_stack, static_files) | |
|
44 | app = make_base_app(global_conf, full_stack=full_stack, **app_conf) | |
|
45 | return app |
@@ -28,7 +28,7 b" ADMIN_PREFIX = '/_admin'" | |||
|
28 | 28 | |
|
29 | 29 | def make_map(config): |
|
30 | 30 | """Create, configure and return the routes Mapper""" |
|
31 |
rmap = Mapper(directory=config[' |
|
|
31 | rmap = Mapper(directory=config['paths']['controllers'], | |
|
32 | 32 | always_scan=config['debug']) |
|
33 | 33 | rmap.minimization = False |
|
34 | 34 | rmap.explicit = False |
@@ -46,7 +46,7 b' def make_map(config):' | |||
|
46 | 46 | repo_name = match_dict.get('repo_name') |
|
47 | 47 | |
|
48 | 48 | if match_dict.get('f_path'): |
|
49 | #fix for multiple initial slashes that causes errors | |
|
49 | # fix for multiple initial slashes that causes errors | |
|
50 | 50 | match_dict['f_path'] = match_dict['f_path'].lstrip('/') |
|
51 | 51 | |
|
52 | 52 | by_id_match = get_repo_by_id(repo_name) |
@@ -90,11 +90,6 b' def make_map(config):' | |||
|
90 | 90 | def check_int(environ, match_dict): |
|
91 | 91 | return match_dict.get('id').isdigit() |
|
92 | 92 | |
|
93 | # The ErrorController route (handles 404/500 error pages); it should | |
|
94 | # likely stay at the top, ensuring it can always be resolved | |
|
95 | rmap.connect('/error/{action}', controller='error') | |
|
96 | rmap.connect('/error/{action}/{id}', controller='error') | |
|
97 | ||
|
98 | 93 | #========================================================================== |
|
99 | 94 | # CUSTOM ROUTES HERE |
|
100 | 95 | #========================================================================== |
@@ -426,8 +421,8 b' def make_map(config):' | |||
|
426 | 421 | #========================================================================== |
|
427 | 422 | # API V2 |
|
428 | 423 | #========================================================================== |
|
429 | with rmap.submapper(path_prefix=ADMIN_PREFIX, | |
|
430 |
|
|
|
424 | with rmap.submapper(path_prefix=ADMIN_PREFIX, controller='api/api', | |
|
425 | action='_dispatch') as m: | |
|
431 | 426 | m.connect('api', '/api') |
|
432 | 427 | |
|
433 | 428 | #USER JOURNAL |
@@ -32,7 +32,7 b' import itertools' | |||
|
32 | 32 | |
|
33 | 33 | from formencode import htmlfill |
|
34 | 34 | |
|
35 | from tg import request, tmpl_context as c | |
|
35 | from tg import request, tmpl_context as c, app_globals | |
|
36 | 36 | from tg.i18n import ugettext as _, ungettext |
|
37 | 37 | from webob.exc import HTTPFound, HTTPForbidden, HTTPNotFound, HTTPInternalServerError |
|
38 | 38 | |
@@ -112,7 +112,7 b' class RepoGroupsController(BaseControlle' | |||
|
112 | 112 | group_iter = RepoGroupList(_list, perm_level='admin') |
|
113 | 113 | repo_groups_data = [] |
|
114 | 114 | total_records = len(group_iter) |
|
115 |
_tmpl_lookup = |
|
|
115 | _tmpl_lookup = app_globals.mako_lookup | |
|
116 | 116 | template = _tmpl_lookup.get_template('data_table/_dt_elements.html') |
|
117 | 117 | |
|
118 | 118 | repo_group_name = lambda repo_group_name, children_groups: ( |
@@ -30,7 +30,7 b' import traceback' | |||
|
30 | 30 | import formencode |
|
31 | 31 | |
|
32 | 32 | from formencode import htmlfill |
|
33 | from tg import request, tmpl_context as c, config | |
|
33 | from tg import request, tmpl_context as c, config, app_globals | |
|
34 | 34 | from tg.i18n import ugettext as _ |
|
35 | 35 | from webob.exc import HTTPFound |
|
36 | 36 | |
@@ -94,7 +94,7 b' class UserGroupsController(BaseControlle' | |||
|
94 | 94 | group_iter = UserGroupList(_list, perm_level='admin') |
|
95 | 95 | user_groups_data = [] |
|
96 | 96 | total_records = len(group_iter) |
|
97 |
_tmpl_lookup = |
|
|
97 | _tmpl_lookup = app_globals.mako_lookup | |
|
98 | 98 | template = _tmpl_lookup.get_template('data_table/_dt_elements.html') |
|
99 | 99 | |
|
100 | 100 | user_group_name = lambda user_group_id, user_group_name: ( |
@@ -30,7 +30,7 b' import traceback' | |||
|
30 | 30 | import formencode |
|
31 | 31 | |
|
32 | 32 | from formencode import htmlfill |
|
33 | from tg import request, tmpl_context as c, config | |
|
33 | from tg import request, tmpl_context as c, config, app_globals | |
|
34 | 34 | from tg.i18n import ugettext as _ |
|
35 | 35 | from sqlalchemy.sql.expression import func |
|
36 | 36 | from webob.exc import HTTPFound, HTTPNotFound |
@@ -73,7 +73,7 b' class UsersController(BaseController):' | |||
|
73 | 73 | |
|
74 | 74 | users_data = [] |
|
75 | 75 | total_records = len(c.users_list) |
|
76 |
_tmpl_lookup = |
|
|
76 | _tmpl_lookup = app_globals.mako_lookup | |
|
77 | 77 | template = _tmpl_lookup.get_template('data_table/_dt_elements.html') |
|
78 | 78 | |
|
79 | 79 | grav_tmpl = '<div class="gravatar">%s</div>' |
@@ -32,12 +32,9 b' import traceback' | |||
|
32 | 32 | import time |
|
33 | 33 | import itertools |
|
34 | 34 | |
|
35 | from paste.response import replace_header | |
|
36 | from pylons.controllers import WSGIController | |
|
37 | from pylons.controllers.util import Response | |
|
38 | from tg import request | |
|
35 | from tg import Response, response, request, TGController | |
|
39 | 36 | |
|
40 | from webob.exc import HTTPError | |
|
37 | from webob.exc import HTTPError, HTTPException, WSGIHTTPException | |
|
41 | 38 | |
|
42 | 39 | from kallithea.model.db import User |
|
43 | 40 | from kallithea.model import meta |
@@ -59,19 +56,20 b' class JSONRPCError(BaseException):' | |||
|
59 | 56 | return safe_str(self.message) |
|
60 | 57 | |
|
61 | 58 | |
|
62 | class JSONRPCErrorResponse(Response, Exception): | |
|
59 | class JSONRPCErrorResponse(Response, HTTPException): | |
|
63 | 60 | """ |
|
64 | 61 | Generate a Response object with a JSON-RPC error body |
|
65 | 62 | """ |
|
66 | 63 | |
|
67 | 64 | def __init__(self, message=None, retid=None, code=None): |
|
65 | HTTPException.__init__(self, message, self) | |
|
68 | 66 | Response.__init__(self, |
|
69 |
body= |
|
|
67 | json_body=dict(id=retid, result=None, error=message), | |
|
70 | 68 | status=code, |
|
71 | 69 | content_type='application/json') |
|
72 | 70 | |
|
73 | 71 | |
|
74 |
class JSONRPCController( |
|
|
72 | class JSONRPCController(TGController): | |
|
75 | 73 | """ |
|
76 | 74 | A WSGI-speaking JSON-RPC controller class |
|
77 | 75 | |
@@ -95,19 +93,15 b' class JSONRPCController(WSGIController):' | |||
|
95 | 93 | """ |
|
96 | 94 | return self._rpc_args |
|
97 | 95 | |
|
98 | def __call__(self, environ, start_response): | |
|
96 | def _dispatch(self, state, remainder=None): | |
|
99 | 97 | """ |
|
100 | 98 | Parse the request body as JSON, look up the method on the |
|
101 | 99 | controller and if it exists, dispatch to it. |
|
102 | 100 | """ |
|
103 | try: | |
|
104 | return self._handle_request(environ, start_response) | |
|
105 | except JSONRPCErrorResponse as e: | |
|
106 | return e | |
|
107 | finally: | |
|
108 | meta.Session.remove() | |
|
101 | # Since we are here we should respond as JSON | |
|
102 | response.content_type = 'application/json' | |
|
109 | 103 | |
|
110 | def _handle_request(self, environ, start_response): | |
|
104 | environ = state.request.environ | |
|
111 | 105 | start = time.time() |
|
112 | 106 | ip_addr = request.ip_addr = self._get_ip_addr(environ) |
|
113 | 107 | self._req_id = None |
@@ -218,39 +212,26 b' class JSONRPCController(WSGIController):' | |||
|
218 | 212 | ) |
|
219 | 213 | |
|
220 | 214 | self._rpc_args = {} |
|
221 | ||
|
222 | 215 | self._rpc_args.update(self._request_params) |
|
223 | ||
|
224 | 216 | self._rpc_args['action'] = self._req_method |
|
225 | 217 | self._rpc_args['environ'] = environ |
|
226 | self._rpc_args['start_response'] = start_response | |
|
227 | 218 | |
|
228 | status = [] | |
|
229 | headers = [] | |
|
230 | exc_info = [] | |
|
231 | ||
|
232 | def change_content(new_status, new_headers, new_exc_info=None): | |
|
233 | status.append(new_status) | |
|
234 | headers.extend(new_headers) | |
|
235 | exc_info.append(new_exc_info) | |
|
236 | ||
|
237 | output = WSGIController.__call__(self, environ, change_content) | |
|
238 | output = list(output) # expand iterator - just to ensure exact timing | |
|
239 | replace_header(headers, 'Content-Type', 'application/json') | |
|
240 | start_response(status[0], headers, exc_info[0]) | |
|
241 | 219 | log.info('IP: %s Request to %s time: %.3fs' % ( |
|
242 | 220 | self._get_ip_addr(environ), |
|
243 | 221 | safe_unicode(_get_access_path(environ)), time.time() - start) |
|
244 | 222 | ) |
|
245 | return output | |
|
246 | 223 | |
|
247 | def _dispatch_call(self): | |
|
224 | state.set_action(self._rpc_call, []) | |
|
225 | state.set_params(self._rpc_args) | |
|
226 | return state | |
|
227 | ||
|
228 | def _rpc_call(self, action, environ, **rpc_args): | |
|
248 | 229 | """ |
|
249 | Implement dispatch interface specified by WSGIController | |
|
230 | Call the specified RPC Method | |
|
250 | 231 | """ |
|
251 | 232 | raw_response = '' |
|
252 | 233 | try: |
|
253 |
raw_response = |
|
|
234 | raw_response = getattr(self, action)(**rpc_args) | |
|
254 | 235 | if isinstance(raw_response, HTTPError): |
|
255 | 236 | self._error = str(raw_response) |
|
256 | 237 | except JSONRPCError as e: |
@@ -29,9 +29,8 b' import os' | |||
|
29 | 29 | import cgi |
|
30 | 30 | import logging |
|
31 | 31 | |
|
32 | from tg import tmpl_context as c, request, config | |
|
32 | from tg import tmpl_context as c, request, config, expose | |
|
33 | 33 | from tg.i18n import ugettext as _ |
|
34 | from pylons.middleware import media_path | |
|
35 | 34 | |
|
36 | 35 | from kallithea.lib.base import BaseController, render |
|
37 | 36 | |
@@ -52,8 +51,9 b' class ErrorController(BaseController):' | |||
|
52 | 51 | # disable all base actions since we don't need them here |
|
53 | 52 | pass |
|
54 | 53 | |
|
55 | def document(self): | |
|
56 | resp = request.environ.get('pylons.original_response') | |
|
54 | @expose('/errors/error_document.html') | |
|
55 | def document(self, *args, **kwargs): | |
|
56 | resp = request.environ.get('tg.original_response') | |
|
57 | 57 | c.site_name = config.get('title') |
|
58 | 58 | |
|
59 | 59 | log.debug('### %s ###', resp and resp.status or 'no response') |
@@ -70,7 +70,7 b' class ErrorController(BaseController):' | |||
|
70 | 70 | c.error_message = _('No response') |
|
71 | 71 | c.error_explanation = _('Unknown error') |
|
72 | 72 | |
|
73 | return render('/errors/error_document.html') | |
|
73 | return dict() | |
|
74 | 74 | |
|
75 | 75 | def get_error_explanation(self, code): |
|
76 | 76 | """ get the error explanations of int codes |
@@ -25,9 +25,8 b' Original author and date, and relevant c' | |||
|
25 | 25 | :copyright: (c) 2013 RhodeCode GmbH, and others. |
|
26 | 26 | :license: GPLv3, see LICENSE.md for more details. |
|
27 | 27 | """ |
|
28 | ||
|
29 | from beaker.cache import CacheManager | |
|
30 | from beaker.util import parse_cache_config_options | |
|
28 | import tg | |
|
29 | from tg import config | |
|
31 | 30 | |
|
32 | 31 | |
|
33 | 32 | class Globals(object): |
@@ -36,11 +35,18 b' class Globals(object):' | |||
|
36 | 35 | life of the application |
|
37 | 36 | """ |
|
38 | 37 | |
|
39 |
def __init__(self |
|
|
38 | def __init__(self): | |
|
40 | 39 | """One instance of Globals is created during application |
|
41 | 40 | initialization and is available during requests via the |
|
42 | 41 | 'app_globals' variable |
|
43 | 42 | |
|
44 | 43 | """ |
|
45 | self.cache = CacheManager(**parse_cache_config_options(config)) | |
|
46 | 44 | self.available_permissions = None # propagated after init_model |
|
45 | ||
|
46 | @property | |
|
47 | def cache(self): | |
|
48 | return tg.cache | |
|
49 | ||
|
50 | @property | |
|
51 | def mako_lookup(self): | |
|
52 | return config['render_functions']['mako'].normal_loader |
@@ -41,9 +41,8 b' import paste.auth.basic' | |||
|
41 | 41 | import paste.httpheaders |
|
42 | 42 | from webhelpers.pylonslib import secure_form |
|
43 | 43 | |
|
44 | from tg import config, tmpl_context as c, request, response, session | |
|
45 |
from |
|
|
46 | from pylons.templating import render_mako as render # don't remove this import | |
|
44 | from tg import config, tmpl_context as c, request, response, session, render_template | |
|
45 | from tg import TGController | |
|
47 | 46 | from tg.i18n import ugettext as _ |
|
48 | 47 | |
|
49 | 48 | from kallithea import __version__, BACKENDS |
@@ -66,6 +65,10 b' from kallithea.model.scm import ScmModel' | |||
|
66 | 65 | log = logging.getLogger(__name__) |
|
67 | 66 | |
|
68 | 67 | |
|
68 | def render(template_path): | |
|
69 | return render_template({'url': url}, 'mako', template_path) | |
|
70 | ||
|
71 | ||
|
69 | 72 | def _filter_proxy(ip): |
|
70 | 73 | """ |
|
71 | 74 | HEADERS can have multiple ips inside the left-most being the original |
@@ -101,7 +104,7 b' def _get_ip_addr(environ):' | |||
|
101 | 104 | |
|
102 | 105 | def _get_access_path(environ): |
|
103 | 106 | path = environ.get('PATH_INFO') |
|
104 |
org_req = environ.get(' |
|
|
107 | org_req = environ.get('tg.original_request') | |
|
105 | 108 | if org_req: |
|
106 | 109 | path = org_req.environ.get('PATH_INFO') |
|
107 | 110 | return path |
@@ -375,14 +378,11 b' class BaseVCSController(object):' | |||
|
375 | 378 | meta.Session.remove() |
|
376 | 379 | |
|
377 | 380 | |
|
378 |
class BaseController( |
|
|
381 | class BaseController(TGController): | |
|
379 | 382 | |
|
380 | 383 | def _before(self, *args, **kwargs): |
|
381 | pass | |
|
382 | ||
|
383 | def __before__(self): | |
|
384 | 384 | """ |
|
385 |
_ |
|
|
385 | _before is called before controller methods and after __call__ | |
|
386 | 386 | """ |
|
387 | 387 | c.kallithea_version = __version__ |
|
388 | 388 | rc_config = Setting.get_app_settings() |
@@ -437,13 +437,6 b' class BaseController(WSGIController):' | |||
|
437 | 437 | |
|
438 | 438 | self.scm_model = ScmModel() |
|
439 | 439 | |
|
440 | # __before__ in Pylons is called _before in TurboGears2. As preparation | |
|
441 | # to the migration to TurboGears2, all __before__ methods were already | |
|
442 | # renamed to _before. We call them from here to keep the behavior. | |
|
443 | # This is a temporary call that will be removed in the real TurboGears2 | |
|
444 | # migration commit. | |
|
445 | self._before() | |
|
446 | ||
|
447 | 440 | @staticmethod |
|
448 | 441 | def _determine_auth_user(api_key, bearer_token, session_authuser): |
|
449 | 442 | """ |
@@ -530,12 +523,7 b' class BaseController(WSGIController):' | |||
|
530 | 523 | log.error('%r request with payload parameters; WebOb should have stopped this', request.method) |
|
531 | 524 | raise webob.exc.HTTPBadRequest() |
|
532 | 525 | |
|
533 |
def __call__(self, environ, |
|
|
534 | """Invoke the Controller""" | |
|
535 | ||
|
536 | # WSGIController.__call__ dispatches to the Controller method | |
|
537 | # the request is routed to. This routing information is | |
|
538 | # available in environ['pylons.routes_dict'] | |
|
526 | def __call__(self, environ, context): | |
|
539 | 527 | try: |
|
540 | 528 | request.ip_addr = _get_ip_addr(environ) |
|
541 | 529 | # make sure that we update permissions each time we call controller |
@@ -564,11 +552,9 b' class BaseController(WSGIController):' | |||
|
564 | 552 | request.ip_addr, request.authuser, |
|
565 | 553 | safe_unicode(_get_access_path(environ)), |
|
566 | 554 | ) |
|
567 |
return |
|
|
555 | return super(BaseController, self).__call__(environ, context) | |
|
568 | 556 | except webob.exc.HTTPException as e: |
|
569 |
return e |
|
|
570 | finally: | |
|
571 | meta.Session.remove() | |
|
557 | return e | |
|
572 | 558 | |
|
573 | 559 | |
|
574 | 560 | class BaseRepoController(BaseController): |
@@ -82,12 +82,12 b' class BasePasterCommand(gearbox.command.' | |||
|
82 | 82 | """ |
|
83 | 83 | Read the config file and initialize logging and the application. |
|
84 | 84 | """ |
|
85 | from tg import config as pylonsconfig | |
|
85 | from kallithea.config.middleware import make_app | |
|
86 | 86 | |
|
87 | 87 | path_to_ini_file = os.path.realpath(config_file) |
|
88 | 88 | conf = paste.deploy.appconfig('config:' + path_to_ini_file) |
|
89 | 89 | logging.config.fileConfig(path_to_ini_file) |
|
90 |
|
|
|
90 | make_app(conf.global_conf, **conf.local_conf) | |
|
91 | 91 | |
|
92 | 92 | def _init_session(self): |
|
93 | 93 | """ |
@@ -40,7 +40,7 b' class Command(BasePasterCommand):' | |||
|
40 | 40 | "Kallithea: Create or update full text search index" |
|
41 | 41 | |
|
42 | 42 | def take_action(self, args): |
|
43 |
from |
|
|
43 | from tg import config | |
|
44 | 44 | index_location = config['index_dir'] |
|
45 | 45 | load_rcextensions(config['here']) |
|
46 | 46 |
@@ -44,7 +44,7 b' class Command(BasePasterCommand):' | |||
|
44 | 44 | takes_config_file = False |
|
45 | 45 | |
|
46 | 46 | def take_action(self, args): |
|
47 |
from |
|
|
47 | from tg import config | |
|
48 | 48 | |
|
49 | 49 | here = config['here'] |
|
50 | 50 | content = pkg_resources.resource_string( |
@@ -516,7 +516,7 b' script_location = kallithea:alembic' | |||
|
516 | 516 | <%text>################################</%text> |
|
517 | 517 | |
|
518 | 518 | [loggers] |
|
519 | keys = root, routes, kallithea, sqlalchemy, gearbox, beaker, templates, whoosh_indexer | |
|
519 | keys = root, routes, kallithea, sqlalchemy, tg, gearbox, beaker, templates, whoosh_indexer | |
|
520 | 520 | |
|
521 | 521 | [handlers] |
|
522 | 522 | keys = console, console_sql |
@@ -557,6 +557,12 b' handlers =' | |||
|
557 | 557 | qualname = kallithea |
|
558 | 558 | propagate = 1 |
|
559 | 559 | |
|
560 | [logger_tg] | |
|
561 | level = DEBUG | |
|
562 | handlers = | |
|
563 | qualname = tg | |
|
564 | propagate = 1 | |
|
565 | ||
|
560 | 566 | [logger_gearbox] |
|
561 | 567 | level = DEBUG |
|
562 | 568 | handlers = |
@@ -32,6 +32,7 b' import datetime' | |||
|
32 | 32 | import traceback |
|
33 | 33 | import beaker |
|
34 | 34 | |
|
35 | from tg import request, response | |
|
35 | 36 | from webhelpers.text import collapse, remove_formatting, strip_tags |
|
36 | 37 | from beaker.cache import _cache_decorate |
|
37 | 38 |
@@ -29,7 +29,7 b' Original author and date, and relevant c' | |||
|
29 | 29 | import logging |
|
30 | 30 | import traceback |
|
31 | 31 | |
|
32 | from tg import tmpl_context as c | |
|
32 | from tg import tmpl_context as c, app_globals | |
|
33 | 33 | from tg.i18n import ugettext as _ |
|
34 | 34 | from sqlalchemy.orm import joinedload, subqueryload |
|
35 | 35 | |
@@ -274,8 +274,8 b' class EmailNotificationModel(object):' | |||
|
274 | 274 | |
|
275 | 275 | def __init__(self): |
|
276 | 276 | super(EmailNotificationModel, self).__init__() |
|
277 |
self._template_root = kallithea.CONFIG[' |
|
|
278 |
self._tmpl_lookup = |
|
|
277 | self._template_root = kallithea.CONFIG['paths']['templates'][0] | |
|
278 | self._tmpl_lookup = app_globals.mako_lookup | |
|
279 | 279 | self.email_types = { |
|
280 | 280 | self.TYPE_CHANGESET_COMMENT: 'changeset_comment', |
|
281 | 281 | self.TYPE_PASSWORD_RESET: 'password_reset', |
@@ -153,10 +153,10 b' class RepoModel(object):' | |||
|
153 | 153 | @classmethod |
|
154 | 154 | def _render_datatable(cls, tmpl, *args, **kwargs): |
|
155 | 155 | import kallithea |
|
156 | from tg import tmpl_context as c, request | |
|
156 | from tg import tmpl_context as c, request, app_globals | |
|
157 | 157 | from tg.i18n import ugettext as _ |
|
158 | 158 | |
|
159 |
_tmpl_lookup = |
|
|
159 | _tmpl_lookup = app_globals.mako_lookup | |
|
160 | 160 | template = _tmpl_lookup.get_template('data_table/_dt_elements.html') |
|
161 | 161 | |
|
162 | 162 | tmpl = template.get_def(tmpl) |
@@ -21,14 +21,9 b' import tempfile' | |||
|
21 | 21 | import time |
|
22 | 22 | |
|
23 | 23 | from tg import config |
|
24 | import pylons | |
|
25 | from pylons import url | |
|
26 | from pylons.i18n.translation import _get_translator | |
|
27 | from pylons.util import ContextObj | |
|
28 | from routes.util import URLGenerator | |
|
29 | 24 | from webtest import TestApp |
|
30 | 25 | |
|
31 | from kallithea import is_windows | |
|
26 | from kallithea import is_windows, model | |
|
32 | 27 | from kallithea.model.db import Notification, User, UserNotification |
|
33 | 28 | from kallithea.model.meta import Session |
|
34 | 29 | from kallithea.lib.utils2 import safe_str |
@@ -42,6 +37,10 b' log = logging.getLogger(__name__)' | |||
|
42 | 37 | skipif = pytest.mark.skipif |
|
43 | 38 | parametrize = pytest.mark.parametrize |
|
44 | 39 | |
|
40 | # Hack: These module global values MUST be set to actual values before running any tests. This is currently done by conftest.py. | |
|
41 | url = None | |
|
42 | testapp = None | |
|
43 | ||
|
45 | 44 | __all__ = [ |
|
46 | 45 | 'skipif', 'parametrize', 'environ', 'url', 'TestController', |
|
47 | 46 | 'ldap_lib_installed', 'pam_lib_installed', 'invalidate_all_caches', |
@@ -147,17 +146,9 b' class TestController(object):' | |||
|
147 | 146 | |
|
148 | 147 | @pytest.fixture(autouse=True) |
|
149 | 148 | def app_fixture(self): |
|
150 | config = pylons.test.pylonsapp.config | |
|
151 | url._push_object(URLGenerator(config['routes.map'], environ)) | |
|
152 | pylons.app_globals._push_object(config['pylons.app_globals']) | |
|
153 | pylons.config._push_object(config) | |
|
154 | pylons.tmpl_context._push_object(ContextObj()) | |
|
155 | # Initialize a translator for tests that utilize i18n | |
|
156 | translator = _get_translator(pylons.config.get('lang')) | |
|
157 | pylons.translator._push_object(translator) | |
|
158 | 149 | h = NullHandler() |
|
159 | 150 | logging.getLogger("kallithea").addHandler(h) |
|
160 |
self.app = TestApp( |
|
|
151 | self.app = TestApp(testapp) | |
|
161 | 152 | return self.app |
|
162 | 153 | |
|
163 | 154 | def remove_all_notifications(self): |
@@ -1,18 +1,20 b'' | |||
|
1 | 1 | import os |
|
2 | 2 | import sys |
|
3 | 3 | import logging |
|
4 | import pkg_resources | |
|
4 | 5 | |
|
5 | import pkg_resources | |
|
6 | 6 | from paste.deploy import loadapp |
|
7 | import pylons.test | |
|
8 | from pylons.i18n.translation import _get_translator | |
|
7 | from routes.util import URLGenerator | |
|
8 | from tg import config | |
|
9 | ||
|
9 | 10 | import pytest |
|
10 | 11 | from kallithea.model.user import UserModel |
|
11 | 12 | from kallithea.model.meta import Session |
|
12 | 13 | from kallithea.model.db import Setting, User, UserIpMap |
|
13 | 14 | from kallithea.tests.base import invalidate_all_caches, TEST_USER_REGULAR_LOGIN |
|
15 | import kallithea.tests.base # FIXME: needed for setting testapp instance!!! | |
|
14 | 16 | |
|
15 |
from |
|
|
17 | from tg.util.webtest import test_context | |
|
16 | 18 | |
|
17 | 19 | def pytest_configure(): |
|
18 | 20 | path = os.getcwd() |
@@ -21,14 +23,10 b' def pytest_configure():' | |||
|
21 | 23 | |
|
22 | 24 | # Disable INFO logging of test database creation, restore with NOTSET |
|
23 | 25 | logging.disable(logging.INFO) |
|
24 |
|
|
|
26 | kallithea.tests.base.testapp = loadapp('config:kallithea/tests/test.ini', relative_to=path) | |
|
25 | 27 | logging.disable(logging.NOTSET) |
|
26 | 28 | |
|
27 | # Initialize a translator for tests that utilize i18n | |
|
28 | translator = _get_translator(pylons.config.get('lang')) | |
|
29 | pylons.translator._push_object(translator) | |
|
30 | ||
|
31 | return pylons.test.pylonsapp | |
|
29 | kallithea.tests.base.url = URLGenerator(config['routes.map'], kallithea.tests.base.environ) | |
|
32 | 30 | |
|
33 | 31 | |
|
34 | 32 | @pytest.fixture |
@@ -6,7 +6,7 b' from kallithea.model.notification import' | |||
|
6 | 6 | from kallithea.model.meta import Session |
|
7 | 7 | from kallithea.lib import helpers as h |
|
8 | 8 | |
|
9 |
from |
|
|
9 | from tg.util.webtest import test_context | |
|
10 | 10 | |
|
11 | 11 | class TestNotificationsController(TestController): |
|
12 | 12 | def setup_method(self, method): |
@@ -5,7 +5,7 b' from kallithea.model.user import UserMod' | |||
|
5 | 5 | from kallithea.model.meta import Session |
|
6 | 6 | from kallithea.tests.base import * |
|
7 | 7 | |
|
8 |
from |
|
|
8 | from tg.util.webtest import test_context | |
|
9 | 9 | |
|
10 | 10 | |
|
11 | 11 | class TestAdminPermissionsController(TestController): |
@@ -17,7 +17,6 b' from sqlalchemy.orm.exc import NoResultF' | |||
|
17 | 17 | import pytest |
|
18 | 18 | from kallithea.tests.base import * |
|
19 | 19 | from kallithea.tests.fixture import Fixture |
|
20 | from kallithea.tests.test_context import test_context | |
|
21 | 20 | from kallithea.controllers.admin.users import UsersController |
|
22 | 21 | from kallithea.model.db import User, Permission, UserIpMap, UserApiKeys |
|
23 | 22 | from kallithea.lib.auth import check_password |
@@ -27,6 +26,8 b' from kallithea.lib import helpers as h' | |||
|
27 | 26 | from kallithea.model.meta import Session |
|
28 | 27 | from webob.exc import HTTPNotFound |
|
29 | 28 | |
|
29 | from tg.util.webtest import test_context | |
|
30 | ||
|
30 | 31 | fixture = Fixture() |
|
31 | 32 | |
|
32 | 33 | @pytest.fixture |
@@ -16,7 +16,7 b' from kallithea.model.db import User, Not' | |||
|
16 | 16 | from kallithea.model.meta import Session |
|
17 | 17 | from kallithea.model.user import UserModel |
|
18 | 18 | |
|
19 |
from |
|
|
19 | from tg.util.webtest import test_context | |
|
20 | 20 | |
|
21 | 21 | fixture = Fixture() |
|
22 | 22 |
@@ -7,7 +7,7 b' from kallithea.lib import helpers as h' | |||
|
7 | 7 | from kallithea.model.user import UserModel |
|
8 | 8 | from kallithea.model.meta import Session |
|
9 | 9 | |
|
10 |
from |
|
|
10 | from tg.util.webtest import test_context | |
|
11 | 11 | |
|
12 | 12 | fixture = Fixture() |
|
13 | 13 |
@@ -1,7 +1,7 b'' | |||
|
1 | 1 | import re |
|
2 | 2 | import pytest |
|
3 | 3 | |
|
4 |
from |
|
|
4 | from tg.util.webtest import test_context | |
|
5 | 5 | |
|
6 | 6 | from kallithea.tests.base import * |
|
7 | 7 | from kallithea.tests.fixture import Fixture |
@@ -14,7 +14,7 b' from kallithea.model.notification import' | |||
|
14 | 14 | import kallithea.lib.celerylib |
|
15 | 15 | import kallithea.lib.celerylib.tasks |
|
16 | 16 | |
|
17 |
from |
|
|
17 | from tg.util.webtest import test_context | |
|
18 | 18 | |
|
19 | 19 | class TestNotifications(TestController): |
|
20 | 20 |
@@ -31,7 +31,7 b' import mock' | |||
|
31 | 31 | from kallithea.tests.base import * |
|
32 | 32 | from kallithea.lib.utils2 import AttributeDict |
|
33 | 33 | from kallithea.model.db import Repository |
|
34 |
from |
|
|
34 | from tg.util.webtest import test_context | |
|
35 | 35 | |
|
36 | 36 | proto = 'http' |
|
37 | 37 | TEST_URLS = [ |
@@ -224,7 +224,7 b' class TestLibs(TestController):' | |||
|
224 | 224 | from kallithea.lib.helpers import gravatar_url |
|
225 | 225 | _md5 = lambda s: hashlib.md5(s).hexdigest() |
|
226 | 226 | |
|
227 |
# |
|
|
227 | # mock tg.tmpl_context | |
|
228 | 228 | def fake_tmpl_context(_url): |
|
229 | 229 | _c = AttributeDict() |
|
230 | 230 | _c.visual = AttributeDict() |
@@ -236,31 +236,31 b' class TestLibs(TestController):' | |||
|
236 | 236 | fake_url = FakeUrlGenerator(current_url='https://example.com') |
|
237 | 237 | with mock.patch('kallithea.config.routing.url', fake_url): |
|
238 | 238 | fake = fake_tmpl_context(_url='http://example.com/{email}') |
|
239 |
with mock.patch(' |
|
|
239 | with mock.patch('tg.tmpl_context', fake): | |
|
240 | 240 | from kallithea.config.routing import url |
|
241 | 241 | assert url.current() == 'https://example.com' |
|
242 | 242 | grav = gravatar_url(email_address='test@example.com', size=24) |
|
243 | 243 | assert grav == 'http://example.com/test@example.com' |
|
244 | 244 | |
|
245 | 245 | fake = fake_tmpl_context(_url='http://example.com/{email}') |
|
246 |
with mock.patch(' |
|
|
246 | with mock.patch('tg.tmpl_context', fake): | |
|
247 | 247 | grav = gravatar_url(email_address='test@example.com', size=24) |
|
248 | 248 | assert grav == 'http://example.com/test@example.com' |
|
249 | 249 | |
|
250 | 250 | fake = fake_tmpl_context(_url='http://example.com/{md5email}') |
|
251 |
with mock.patch(' |
|
|
251 | with mock.patch('tg.tmpl_context', fake): | |
|
252 | 252 | em = 'test@example.com' |
|
253 | 253 | grav = gravatar_url(email_address=em, size=24) |
|
254 | 254 | assert grav == 'http://example.com/%s' % (_md5(em)) |
|
255 | 255 | |
|
256 | 256 | fake = fake_tmpl_context(_url='http://example.com/{md5email}/{size}') |
|
257 |
with mock.patch(' |
|
|
257 | with mock.patch('tg.tmpl_context', fake): | |
|
258 | 258 | em = 'test@example.com' |
|
259 | 259 | grav = gravatar_url(email_address=em, size=24) |
|
260 | 260 | assert grav == 'http://example.com/%s/%s' % (_md5(em), 24) |
|
261 | 261 | |
|
262 | 262 | fake = fake_tmpl_context(_url='{scheme}://{netloc}/{md5email}/{size}') |
|
263 |
with mock.patch(' |
|
|
263 | with mock.patch('tg.tmpl_context', fake): | |
|
264 | 264 | em = 'test@example.com' |
|
265 | 265 | grav = gravatar_url(email_address=em, size=24) |
|
266 | 266 | assert grav == 'https://example.com/%s/%s' % (_md5(em), 24) |
@@ -517,7 +517,7 b' script_location = kallithea:alembic' | |||
|
517 | 517 | ################################ |
|
518 | 518 | |
|
519 | 519 | [loggers] |
|
520 | keys = root, routes, kallithea, sqlalchemy, gearbox, beaker, templates, whoosh_indexer | |
|
520 | keys = root, routes, kallithea, sqlalchemy, tg, gearbox, beaker, templates, whoosh_indexer | |
|
521 | 521 | |
|
522 | 522 | [handlers] |
|
523 | 523 | keys = console, console_sql |
@@ -558,6 +558,12 b' handlers =' | |||
|
558 | 558 | qualname = kallithea |
|
559 | 559 | propagate = 1 |
|
560 | 560 | |
|
561 | [logger_tg] | |
|
562 | level = DEBUG | |
|
563 | handlers = | |
|
564 | qualname = tg | |
|
565 | propagate = 1 | |
|
566 | ||
|
561 | 567 | [logger_gearbox] |
|
562 | 568 | level = DEBUG |
|
563 | 569 | handlers = |
@@ -39,7 +39,9 b' requirements = [' | |||
|
39 | 39 | "GearBox<1", |
|
40 | 40 | "waitress>=0.8.8,<1.0", |
|
41 | 41 | "webob>=1.7,<2", |
|
42 | "Pylons>=1.0.0,<=1.0.2", | |
|
42 | "backlash >= 0.1.1, < 1.0.0", | |
|
43 | "TurboGears2 >= 2.3.10, < 3.0.0", | |
|
44 | "tgext.routes >= 0.2.0, < 1.0.0", | |
|
43 | 45 | "Beaker>=1.7.0,<2", |
|
44 | 46 | "WebHelpers==1.3", |
|
45 | 47 | "formencode>=1.2.4,<=1.2.6", |
@@ -56,6 +58,8 b' requirements = [' | |||
|
56 | 58 | "Routes==1.13", |
|
57 | 59 | "dulwich>=0.14.1", |
|
58 | 60 | "mercurial>=2.9,<4.2", |
|
61 | "decorator >= 3.3.2", | |
|
62 | "Paste >= 2.0.3, < 3.0", | |
|
59 | 63 | ] |
|
60 | 64 | |
|
61 | 65 | if sys.version_info < (2, 7): |
@@ -151,9 +155,6 b' setuptools.setup(' | |||
|
151 | 155 | [paste.app_factory] |
|
152 | 156 | main = kallithea.config.middleware:make_app |
|
153 | 157 | |
|
154 | [paste.app_install] | |
|
155 | main = pylons.util:PylonsInstaller | |
|
156 | ||
|
157 | 158 | [gearbox.commands] |
|
158 | 159 | make-config=kallithea.lib.paster_commands.make_config:Command |
|
159 | 160 | setup-db=kallithea.lib.paster_commands.setup_db:Command |
General Comments 0
You need to be logged in to leave comments.
Login now