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