##// END OF EJS Templates
core: use proper event to bootstrap pylons env....
marcink -
r1309:8a946991 default
parent child Browse files
Show More
@@ -1,166 +1,213 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21
22 22 import logging
23 23 import pylons
24 24 import Queue
25 25 import subprocess32
26 26
27 27 from pyramid.i18n import get_localizer
28 28 from pyramid.threadlocal import get_current_request
29 29 from threading import Thread
30 30
31 31 from rhodecode.translation import _ as tsf
32 32
33 import rhodecode
34
35 from pylons.i18n.translation import _get_translator
36 from pylons.util import ContextObj
37 from routes.util import URLGenerator
38
39 from rhodecode.lib.base import attach_context_attributes, get_auth_user
40
33 41 log = logging.getLogger(__name__)
34 42
35 43
36 44 def add_renderer_globals(event):
37 45 # Put pylons stuff into the context. This will be removed as soon as
38 46 # migration to pyramid is finished.
39 47 conf = pylons.config._current_obj()
40 48 event['h'] = conf.get('pylons.h')
41 49 event['c'] = pylons.tmpl_context
42 50 event['url'] = pylons.url
43 51
44 52 # TODO: When executed in pyramid view context the request is not available
45 53 # in the event. Find a better solution to get the request.
46 54 request = event['request'] or get_current_request()
47 55
48 56 # Add Pyramid translation as '_' to context
49 57 event['_'] = request.translate
50 58 event['_ungettext'] = request.plularize
51 59
52 60
53 61 def add_localizer(event):
54 62 request = event.request
55 63 localizer = get_localizer(request)
56 64
57 65 def auto_translate(*args, **kwargs):
58 66 return localizer.translate(tsf(*args, **kwargs))
59 67
60 68 request.localizer = localizer
61 69 request.translate = auto_translate
62 70 request.plularize = localizer.pluralize
63 71
64 72
65 73 def set_user_lang(event):
66 cur_user = getattr(event.request, 'user', None)
74 request = event.request
75 cur_user = getattr(request, 'user', None)
67 76
68 77 if cur_user:
69 78 user_lang = cur_user.get_instance().user_data.get('language')
70 79 if user_lang:
71 80 log.debug('lang: setting current user:%s language to: %s', cur_user, user_lang)
72 81 event.request._LOCALE_ = user_lang
73 82
74 83
84 def add_pylons_context(event):
85 request = event.request
86
87 config = rhodecode.CONFIG
88 environ = request.environ
89 session = request.session
90
91 if hasattr(request, 'vcs_call'):
92 # skip vcs calls
93 return
94
95 # Setup pylons globals.
96 pylons.config._push_object(config)
97 pylons.request._push_object(request)
98 pylons.session._push_object(session)
99 pylons.translator._push_object(_get_translator(config.get('lang')))
100
101 pylons.url._push_object(URLGenerator(config['routes.map'], environ))
102 session_key = (
103 config['pylons.environ_config'].get('session', 'beaker.session'))
104 environ[session_key] = session
105
106 if hasattr(request, 'rpc_method'):
107 # skip api calls
108 return
109
110 # Get the rhodecode auth user object and make it available.
111 auth_user = get_auth_user(environ)
112 request.user = auth_user
113 environ['rc_auth_user'] = auth_user
114
115 # Setup the pylons context object ('c')
116 context = ContextObj()
117 context.rhodecode_user = auth_user
118 attach_context_attributes(context, request)
119 pylons.tmpl_context._push_object(context)
120
121
75 122 def scan_repositories_if_enabled(event):
76 123 """
77 124 This is subscribed to the `pyramid.events.ApplicationCreated` event. It
78 125 does a repository scan if enabled in the settings.
79 126 """
80 127 from rhodecode.model.scm import ScmModel
81 128 from rhodecode.lib.utils import repo2db_mapper, get_rhodecode_base_path
82 129 settings = event.app.registry.settings
83 130 vcs_server_enabled = settings['vcs.server.enable']
84 131 import_on_startup = settings['startup.import_repos']
85 132 if vcs_server_enabled and import_on_startup:
86 133 repositories = ScmModel().repo_scan(get_rhodecode_base_path())
87 134 repo2db_mapper(repositories, remove_obsolete=False)
88 135
89 136
90 137 class Subscriber(object):
91 138 """
92 139 Base class for subscribers to the pyramid event system.
93 140 """
94 141 def __call__(self, event):
95 142 self.run(event)
96 143
97 144 def run(self, event):
98 145 raise NotImplementedError('Subclass has to implement this.')
99 146
100 147
101 148 class AsyncSubscriber(Subscriber):
102 149 """
103 150 Subscriber that handles the execution of events in a separate task to not
104 151 block the execution of the code which triggers the event. It puts the
105 152 received events into a queue from which the worker process takes them in
106 153 order.
107 154 """
108 155 def __init__(self):
109 156 self._stop = False
110 157 self._eventq = Queue.Queue()
111 158 self._worker = self.create_worker()
112 159 self._worker.start()
113 160
114 161 def __call__(self, event):
115 162 self._eventq.put(event)
116 163
117 164 def create_worker(self):
118 165 worker = Thread(target=self.do_work)
119 166 worker.daemon = True
120 167 return worker
121 168
122 169 def stop_worker(self):
123 170 self._stop = False
124 171 self._eventq.put(None)
125 172 self._worker.join()
126 173
127 174 def do_work(self):
128 175 while not self._stop:
129 176 event = self._eventq.get()
130 177 if event is not None:
131 178 self.run(event)
132 179
133 180
134 181 class AsyncSubprocessSubscriber(AsyncSubscriber):
135 182 """
136 183 Subscriber that uses the subprocess32 module to execute a command if an
137 184 event is received. Events are handled asynchronously.
138 185 """
139 186
140 187 def __init__(self, cmd, timeout=None):
141 188 super(AsyncSubprocessSubscriber, self).__init__()
142 189 self._cmd = cmd
143 190 self._timeout = timeout
144 191
145 192 def run(self, event):
146 193 cmd = self._cmd
147 194 timeout = self._timeout
148 195 log.debug('Executing command %s.', cmd)
149 196
150 197 try:
151 198 output = subprocess32.check_output(
152 199 cmd, timeout=timeout, stderr=subprocess32.STDOUT)
153 200 log.debug('Command finished %s', cmd)
154 201 if output:
155 202 log.debug('Command output: %s', output)
156 203 except subprocess32.TimeoutExpired as e:
157 204 log.exception('Timeout while executing command.')
158 205 if e.output:
159 206 log.error('Command output: %s', e.output)
160 207 except subprocess32.CalledProcessError as e:
161 208 log.exception('Error while executing command.')
162 209 if e.output:
163 210 log.error('Command output: %s', e.output)
164 211 except:
165 212 log.exception(
166 213 'Exception while executing command %s.', cmd)
@@ -1,98 +1,66 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21
22 22 import logging
23 import pylons
24 import rhodecode
25 23
26 from pylons.i18n.translation import _get_translator
27 from pylons.util import ContextObj
28 from routes.util import URLGenerator
29
30 from rhodecode.lib.base import attach_context_attributes, get_auth_user
31 24 from rhodecode.lib.middleware.vcs import (
32 25 detect_vcs_request, VCS_TYPE_KEY, VCS_TYPE_SKIP)
33 from rhodecode.model import meta
34 26
35 27
36 28 log = logging.getLogger(__name__)
37 29
38 30
39 def pylons_compatibility_tween_factory(handler, registry):
31 def vcs_detection_tween_factory(handler, registry):
40 32
41 def pylons_compatibility_tween(request):
33 def vcs_detection_tween(request):
42 34 """
43 While migrating from pylons to pyramid we need to call some pylons code
44 from pyramid. For example while rendering an old template that uses the
45 'c' or 'h' objects. This tween sets up the needed pylons globals.
35 Do detection of vcs type, and save results for other layers to re-use
36 this information
46 37 """
47 config = rhodecode.CONFIG
48 environ = request.environ
49 session = request.session
50 38
51 39 vcs_handler = detect_vcs_request(
52 40 request.environ, request.registry.settings.get('vcs.backends'))
53 41
54 42 if vcs_handler:
55 43 # save detected VCS type for later re-use
56 44 request.environ[VCS_TYPE_KEY] = vcs_handler.SCM
45 request.vcs_call = vcs_handler.SCM
57 46 return handler(request)
58 47
59 48 # mark that we didn't detect an VCS, and we can skip detection later on
60 49 request.environ[VCS_TYPE_KEY] = VCS_TYPE_SKIP
61 50
62 # Setup pylons globals.
63 pylons.config._push_object(config)
64 pylons.request._push_object(request)
65 pylons.session._push_object(session)
66
67 session_key = (
68 config['pylons.environ_config'].get('session', 'beaker.session'))
69 environ[session_key] = session
70 pylons.url._push_object(URLGenerator(config['routes.map'], environ))
71
72 # TODO: Maybe we should use the language from pyramid.
73 translator = _get_translator(config.get('lang'))
74 pylons.translator._push_object(translator)
75
76 # Get the rhodecode auth user object and make it available.
77 auth_user = get_auth_user(environ)
78 request.user = auth_user
79 environ['rc_auth_user'] = auth_user
80
81 # Setup the pylons context object ('c')
82 context = ContextObj()
83 context.rhodecode_user = auth_user
84 attach_context_attributes(context, request)
85 pylons.tmpl_context._push_object(context)
86 51 return handler(request)
87 52
88 return pylons_compatibility_tween
53 return vcs_detection_tween
89 54
90 55
91 56 def includeme(config):
92 57 config.add_subscriber('rhodecode.subscribers.add_renderer_globals',
93 58 'pyramid.events.BeforeRender')
94 59 config.add_subscriber('rhodecode.subscribers.set_user_lang',
95 60 'pyramid.events.NewRequest')
96 61 config.add_subscriber('rhodecode.subscribers.add_localizer',
97 62 'pyramid.events.NewRequest')
98 config.add_tween('rhodecode.tweens.pylons_compatibility_tween_factory')
63 config.add_subscriber('rhodecode.subscribers.add_pylons_context',
64 'pyramid.events.ContextFound')
65
66 config.add_tween('rhodecode.tweens.vcs_detection_tween_factory')
General Comments 0
You need to be logged in to leave comments. Login now