##// END OF EJS Templates
session: moved pyramid_beaker internally to apply some patches required for better session handling
marcink -
r3748:9f6c56d4 new-ui
parent child Browse files
Show More
@@ -0,0 +1,200 b''
1 # Copyright (c) 2010 Agendaless Consulting and Contributors.
2 # (http://www.agendaless.com), All Rights Reserved
3 # License: BSD-derived (http://www.repoze.org/LICENSE.txt)
4 # With Patches from RhodeCode GmBH
5
6
7 import os
8
9 from beaker import cache
10 from beaker.session import SessionObject
11 from beaker.util import coerce_cache_params
12 from beaker.util import coerce_session_params
13
14 from pyramid.interfaces import ISession
15 from pyramid.settings import asbool
16 from zope.interface import implementer
17
18 from binascii import hexlify
19
20
21 def BeakerSessionFactoryConfig(**options):
22 """ Return a Pyramid session factory using Beaker session settings
23 supplied directly as ``**options``"""
24
25 class PyramidBeakerSessionObject(SessionObject):
26 _options = options
27 _cookie_on_exception = _options.pop('cookie_on_exception', True)
28 _constant_csrf_token = _options.pop('constant_csrf_token', False)
29
30 def __init__(self, request):
31 SessionObject.__init__(self, request.environ, **self._options)
32
33 def session_callback(request, response):
34 exception = getattr(request, 'exception', None)
35 if (exception is None or self._cookie_on_exception) and self.accessed():
36 self.persist()
37 headers = self.__dict__['_headers']
38 if headers['set_cookie'] and headers['cookie_out']:
39 response.headerlist.append(('Set-Cookie', headers['cookie_out']))
40 request.add_response_callback(session_callback)
41
42 # ISession API
43
44 @property
45 def id(self):
46 # this is as inspected in SessionObject.__init__
47 if self.__dict__['_params'].get('type') != 'cookie':
48 return self._session().id
49 return None
50
51 @property
52 def new(self):
53 return self.last_accessed is None
54
55 changed = SessionObject.save
56
57 # modifying dictionary methods
58
59 @call_save
60 def clear(self):
61 return self._session().clear()
62
63 @call_save
64 def update(self, d, **kw):
65 return self._session().update(d, **kw)
66
67 @call_save
68 def setdefault(self, k, d=None):
69 return self._session().setdefault(k, d)
70
71 @call_save
72 def pop(self, k, d=None):
73 return self._session().pop(k, d)
74
75 @call_save
76 def popitem(self):
77 return self._session().popitem()
78
79 __setitem__ = call_save(SessionObject.__setitem__)
80 __delitem__ = call_save(SessionObject.__delitem__)
81
82 # Flash API methods
83 def flash(self, msg, queue='', allow_duplicate=True):
84 storage = self.setdefault('_f_' + queue, [])
85 if allow_duplicate or (msg not in storage):
86 storage.append(msg)
87
88 def pop_flash(self, queue=''):
89 storage = self.pop('_f_' + queue, [])
90 return storage
91
92 def peek_flash(self, queue=''):
93 storage = self.get('_f_' + queue, [])
94 return storage
95
96 # CSRF API methods
97 def new_csrf_token(self):
98 token = (self._constant_csrf_token
99 or hexlify(os.urandom(20)).decode('ascii'))
100 self['_csrft_'] = token
101 return token
102
103 def get_csrf_token(self):
104 token = self.get('_csrft_', None)
105 if token is None:
106 token = self.new_csrf_token()
107 return token
108
109 return implementer(ISession)(PyramidBeakerSessionObject)
110
111
112 def call_save(wrapped):
113 """ By default, in non-auto-mode beaker badly wants people to
114 call save even though it should know something has changed when
115 a mutating method is called. This hack should be removed if
116 Beaker ever starts to do this by default. """
117 def save(session, *arg, **kw):
118 value = wrapped(session, *arg, **kw)
119 session.save()
120 return value
121 save.__doc__ = wrapped.__doc__
122 return save
123
124
125 def session_factory_from_settings(settings):
126 """ Return a Pyramid session factory using Beaker session settings
127 supplied from a Paste configuration file"""
128 prefixes = ('session.', 'beaker.session.')
129 options = {}
130
131 # Pull out any config args meant for beaker session. if there are any
132 for k, v in settings.items():
133 for prefix in prefixes:
134 if k.startswith(prefix):
135 option_name = k[len(prefix):]
136 if option_name == 'cookie_on_exception':
137 v = asbool(v)
138 options[option_name] = v
139
140 options = coerce_session_params(options)
141 return BeakerSessionFactoryConfig(**options)
142
143
144 def set_cache_regions_from_settings(settings):
145 """ Add cache support to the Pylons application.
146
147 The ``settings`` passed to the configurator are used to setup
148 the cache options. Cache options in the settings should start
149 with either 'beaker.cache.' or 'cache.'.
150
151 """
152 cache_settings = {'regions': []}
153 for key in settings.keys():
154 for prefix in ['beaker.cache.', 'cache.']:
155 if key.startswith(prefix):
156 name = key.split(prefix)[1].strip()
157 cache_settings[name] = settings[key].strip()
158
159 if ('expire' in cache_settings
160 and isinstance(cache_settings['expire'], basestring)
161 and cache_settings['expire'].lower() in ['none', 'no']):
162 cache_settings['expire'] = None
163
164 coerce_cache_params(cache_settings)
165
166 if 'enabled' not in cache_settings:
167 cache_settings['enabled'] = True
168
169 regions = cache_settings['regions']
170 if regions:
171 for region in regions:
172 if not region:
173 continue
174
175 region_settings = {
176 'data_dir': cache_settings.get('data_dir'),
177 'lock_dir': cache_settings.get('lock_dir'),
178 'expire': cache_settings.get('expire', 60),
179 'enabled': cache_settings['enabled'],
180 'key_length': cache_settings.get('key_length', 250),
181 'type': cache_settings.get('type'),
182 'url': cache_settings.get('url'),
183 }
184 region_prefix = '%s.' % region
185 region_len = len(region_prefix)
186 for key in list(cache_settings.keys()):
187 if key.startswith(region_prefix):
188 region_settings[key[region_len:]] = cache_settings.pop(key)
189
190 if (isinstance(region_settings['expire'], basestring)
191 and region_settings['expire'].lower() in ['none', 'no']):
192 region_settings['expire'] = None
193 coerce_cache_params(region_settings)
194 cache.cache_regions[region] = region_settings
195
196
197 def includeme(config):
198 session_factory = session_factory_from_settings(config.registry.settings)
199 config.set_session_factory(session_factory)
200 set_cache_regions_from_settings(config.registry.settings)
@@ -1395,21 +1395,6 b' self: super: {'
1395 license = [ { fullName = "Repoze Public License"; } { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
1395 license = [ { fullName = "Repoze Public License"; } { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
1396 };
1396 };
1397 };
1397 };
1398 "pyramid-beaker" = super.buildPythonPackage {
1399 name = "pyramid-beaker-0.8";
1400 doCheck = false;
1401 propagatedBuildInputs = [
1402 self."pyramid"
1403 self."beaker"
1404 ];
1405 src = fetchurl {
1406 url = "https://files.pythonhosted.org/packages/d9/6e/b85426e00fd3d57f4545f74e1c3828552d8700f13ededeef9233f7bca8be/pyramid_beaker-0.8.tar.gz";
1407 sha256 = "0hflx3qkcdml1mwpq53sz46s7jickpfn0zy0ns2c7j445j66bp3p";
1408 };
1409 meta = {
1410 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
1411 };
1412 };
1413 "pyramid-debugtoolbar" = super.buildPythonPackage {
1398 "pyramid-debugtoolbar" = super.buildPythonPackage {
1414 name = "pyramid-debugtoolbar-4.5";
1399 name = "pyramid-debugtoolbar-4.5";
1415 doCheck = false;
1400 doCheck = false;
@@ -1793,7 +1778,6 b' self: super: {'
1793 self."pycrypto"
1778 self."pycrypto"
1794 self."pygments"
1779 self."pygments"
1795 self."pyparsing"
1780 self."pyparsing"
1796 self."pyramid-beaker"
1797 self."pyramid-debugtoolbar"
1781 self."pyramid-debugtoolbar"
1798 self."pyramid-mako"
1782 self."pyramid-mako"
1799 self."pyramid"
1783 self."pyramid"
@@ -44,7 +44,6 b' pycurl==7.43.0.2'
44 pycrypto==2.6.1
44 pycrypto==2.6.1
45 pygments==2.4.2
45 pygments==2.4.2
46 pyparsing==2.3.0
46 pyparsing==2.3.0
47 pyramid-beaker==0.8
48 pyramid-debugtoolbar==4.5.0
47 pyramid-debugtoolbar==4.5.0
49 pyramid-mako==1.0.2
48 pyramid-mako==1.0.2
50 pyramid==1.10.4
49 pyramid==1.10.4
@@ -250,7 +250,7 b' def includeme(config):'
250
250
251 # Includes which are required. The application would fail without them.
251 # Includes which are required. The application would fail without them.
252 config.include('pyramid_mako')
252 config.include('pyramid_mako')
253 config.include('pyramid_beaker')
253 config.include('rhodecode.lib.rc_beaker')
254 config.include('rhodecode.lib.rc_cache')
254 config.include('rhodecode.lib.rc_cache')
255
255
256 config.include('rhodecode.apps._base.navigation')
256 config.include('rhodecode.apps._base.navigation')
@@ -536,7 +536,7 b' def bootstrap_config(request):'
536
536
537 # allow pyramid lookup in testing
537 # allow pyramid lookup in testing
538 config.include('pyramid_mako')
538 config.include('pyramid_mako')
539 config.include('pyramid_beaker')
539 config.include('rhodecode.lib.rc_beaker')
540 config.include('rhodecode.lib.rc_cache')
540 config.include('rhodecode.lib.rc_cache')
541
541
542 add_events_routes(config)
542 add_events_routes(config)
General Comments 0
You need to be logged in to leave comments. Login now