##// END OF EJS Templates
added latest changes
added latest changes

File last commit:

r5148:5ce7d4ae default
r5658:a109f5ac merge default
Show More
rc_beaker.py
171 lines | 5.6 KiB | text/x-python | PythonLexer
session: moved pyramid_beaker internally to apply some patches required for better session handling
r3748 # Copyright (c) 2010 Agendaless Consulting and Contributors.
# (http://www.agendaless.com), All Rights Reserved
# License: BSD-derived (http://www.repoze.org/LICENSE.txt)
# With Patches from RhodeCode GmBH
import os
from beaker import cache
sessions: fixed regression in handlin sqlalchemy params for beaker DB based sessions
r5132 from beaker.session import SessionObject, Session
session: moved pyramid_beaker internally to apply some patches required for better session handling
r3748 from beaker.util import coerce_cache_params
from beaker.util import coerce_session_params
from pyramid.interfaces import ISession
from pyramid.settings import asbool
from zope.interface import implementer
from binascii import hexlify
sessions: fixed regression in handlin sqlalchemy params for beaker DB based sessions
r5132 class CustomSession(Session):
pass
session: moved pyramid_beaker internally to apply some patches required for better session handling
r3748 def BeakerSessionFactoryConfig(**options):
""" Return a Pyramid session factory using Beaker session settings
supplied directly as ``**options``"""
class PyramidBeakerSessionObject(SessionObject):
_options = options
_cookie_on_exception = _options.pop('cookie_on_exception', True)
_constant_csrf_token = _options.pop('constant_csrf_token', False)
sessions: fixed regression in handlin sqlalchemy params for beaker DB based sessions
r5132 _sa_opts = _options.pop('sa_opts', {})
session: moved pyramid_beaker internally to apply some patches required for better session handling
r3748
def __init__(self, request):
sessions: fixed regression in handlin sqlalchemy params for beaker DB based sessions
r5132 self._options['session_class'] = CustomSession
self._options['sa_opts'] = self._sa_opts
session: moved pyramid_beaker internally to apply some patches required for better session handling
r3748 SessionObject.__init__(self, request.environ, **self._options)
sessions: improve the code so it doesn't access cookies/sessions when not needed, e.g for API calls
r5027 def session_callback(_request, _response):
exception = getattr(_request, 'exception', None)
file_response = getattr(_request, '_file_response', None)
api_call = getattr(_request, 'rpc_method', None)
file-store: don't response with cookies on file-store download.
r4236
sessions: improve the code so it doesn't access cookies/sessions when not needed, e.g for API calls
r5027 if file_response is not None:
return
if api_call is not None:
return
if exception is not None and not self._cookie_on_exception:
return
if self.accessed():
session: moved pyramid_beaker internally to apply some patches required for better session handling
r3748 self.persist()
headers = self.__dict__['_headers']
file-store: don't response with cookies on file-store download.
r4236 if headers.get('set_cookie') and headers.get('cookie_out'):
sessions: improve the code so it doesn't access cookies/sessions when not needed, e.g for API calls
r5027 _response.headerlist.append(('Set-Cookie', headers['cookie_out']))
session: moved pyramid_beaker internally to apply some patches required for better session handling
r3748 request.add_response_callback(session_callback)
# ISession API
@property
def id(self):
# this is as inspected in SessionObject.__init__
if self.__dict__['_params'].get('type') != 'cookie':
return self._session().id
return None
@property
def new(self):
return self.last_accessed is None
changed = SessionObject.save
# modifying dictionary methods
@call_save
def clear(self):
return self._session().clear()
@call_save
def update(self, d, **kw):
return self._session().update(d, **kw)
@call_save
def setdefault(self, k, d=None):
return self._session().setdefault(k, d)
@call_save
def pop(self, k, d=None):
return self._session().pop(k, d)
@call_save
def popitem(self):
return self._session().popitem()
__setitem__ = call_save(SessionObject.__setitem__)
__delitem__ = call_save(SessionObject.__delitem__)
# Flash API methods
def flash(self, msg, queue='', allow_duplicate=True):
sessions: fixed regression in handlin sqlalchemy params for beaker DB based sessions
r5132 storage = self.setdefault(f'_f_{queue}', [])
session: moved pyramid_beaker internally to apply some patches required for better session handling
r3748 if allow_duplicate or (msg not in storage):
storage.append(msg)
def pop_flash(self, queue=''):
sessions: fixed regression in handlin sqlalchemy params for beaker DB based sessions
r5132 storage = self.pop(f'_f_{queue}', [])
session: moved pyramid_beaker internally to apply some patches required for better session handling
r3748 return storage
def peek_flash(self, queue=''):
prompts: fixed input() calls for python3
r5148 storage = self.get(f'_f_{queue}', [])
session: moved pyramid_beaker internally to apply some patches required for better session handling
r3748 return storage
# CSRF API methods
def new_csrf_token(self):
token = (self._constant_csrf_token
or hexlify(os.urandom(20)).decode('ascii'))
self['_csrft_'] = token
return token
def get_csrf_token(self):
token = self.get('_csrft_', None)
if token is None:
token = self.new_csrf_token()
return token
return implementer(ISession)(PyramidBeakerSessionObject)
def call_save(wrapped):
""" By default, in non-auto-mode beaker badly wants people to
call save even though it should know something has changed when
a mutating method is called. This hack should be removed if
Beaker ever starts to do this by default. """
def save(session, *arg, **kw):
value = wrapped(session, *arg, **kw)
session.save()
return value
save.__doc__ = wrapped.__doc__
return save
def session_factory_from_settings(settings):
""" Return a Pyramid session factory using Beaker session settings
supplied from a Paste configuration file"""
prefixes = ('session.', 'beaker.session.')
options = {}
sessions: fixed regression in handlin sqlalchemy params for beaker DB based sessions
r5132 # custom gather of our specific sqlalchemy session db configuration we need to translate this into a single entry
# dict because this is how beaker expects that.
sa_opts = {}
session: moved pyramid_beaker internally to apply some patches required for better session handling
r3748 # Pull out any config args meant for beaker session. if there are any
for k, v in settings.items():
for prefix in prefixes:
if k.startswith(prefix):
option_name = k[len(prefix):]
if option_name == 'cookie_on_exception':
v = asbool(v)
sessions: fixed regression in handlin sqlalchemy params for beaker DB based sessions
r5132 if option_name.startswith('sa.'):
sa_opts[option_name] = v
session: moved pyramid_beaker internally to apply some patches required for better session handling
r3748 options[option_name] = v
options = coerce_session_params(options)
sessions: fixed regression in handlin sqlalchemy params for beaker DB based sessions
r5132 options['sa_opts'] = sa_opts
session: moved pyramid_beaker internally to apply some patches required for better session handling
r3748 return BeakerSessionFactoryConfig(**options)
def includeme(config):
session_factory = session_factory_from_settings(config.registry.settings)
config.set_session_factory(session_factory)