Commit 4ba39f69 authored by Chris McDonough's avatar Chris McDonough

Browser Id Manager is no longer __replaceable__ = UNIQUE, meaning

that other things named browser_id_manager can be created in subfolders.

Wrap transient data objects only in session data manager upon return.
Previously, they had been wrapped also in session data container.

Took out clever traversal error logging code in fear that it would
bloat the ZODB.

Added SessionDataManagerErr and BrowserIdManagerErr to API docs and
made them importable within a PythonScript.

Extended test suite with request-autopopulate tests.
parent 35a3c9ba
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
# #
############################################################################ ############################################################################
__version__='$Revision: 1.5 $'[11:-2] __version__='$Revision: 1.6 $'[11:-2]
import Globals import Globals
from Persistence import Persistent from Persistence import Persistent
from ZODB import TimeStamp from ZODB import TimeStamp
...@@ -138,8 +138,6 @@ class BrowserIdManager(Item, Persistent, Implicit, RoleManager, Owned, Tabs): ...@@ -138,8 +138,6 @@ class BrowserIdManager(Item, Persistent, Implicit, RoleManager, Owned, Tabs):
security.setPermissionDefault(ACCESS_CONTENTS_PERM,['Manager','Anonymous']) security.setPermissionDefault(ACCESS_CONTENTS_PERM,['Manager','Anonymous'])
security.setPermissionDefault(CHANGE_IDMGR_PERM, ['Manager']) security.setPermissionDefault(CHANGE_IDMGR_PERM, ['Manager'])
__replaceable__ = UNIQUE # singleton for now
__implements__ = (SessionInterfaces.BrowserIdManagerInterface, ) __implements__ = (SessionInterfaces.BrowserIdManagerInterface, )
icon = 'misc_/Sessions/idmgr.gif' icon = 'misc_/Sessions/idmgr.gif'
......
...@@ -83,7 +83,7 @@ from Persistence import Persistent ...@@ -83,7 +83,7 @@ from Persistence import Persistent
from AccessControl.Owned import Owned from AccessControl.Owned import Owned
from AccessControl.Role import RoleManager from AccessControl.Role import RoleManager
from App.Management import Tabs from App.Management import Tabs
from zLOG import LOG, WARNING from zLOG import LOG, WARNING, BLATHER
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
import SessionInterfaces import SessionInterfaces
from SessionPermissions import * from SessionPermissions import *
...@@ -234,13 +234,13 @@ class SessionDataManager(Item, Implicit, Persistent, RoleManager, Owned, Tabs): ...@@ -234,13 +234,13 @@ class SessionDataManager(Item, Implicit, Persistent, RoleManager, Owned, Tabs):
def _getSessionDataObject(self, key): def _getSessionDataObject(self, key):
""" returns new or existing session data object """ """ returns new or existing session data object """
container = self._getSessionDataContainer() container = self._getSessionDataContainer()
ob = container.new_or_existing(key) ob = aq_base(container.new_or_existing(key))
return ob.__of__(self) return ob.__of__(self)
def _getSessionDataObjectByKey(self, key): def _getSessionDataObjectByKey(self, key):
""" returns new or existing session data object """ """ returns new or existing session data object """
container = self._getSessionDataContainer() container = self._getSessionDataContainer()
ob = container.get(key) ob = aq_base(container.get(key))
if ob is not None: if ob is not None:
return ob.__of__(self) return ob.__of__(self)
...@@ -249,10 +249,8 @@ class SessionDataManager(Item, Implicit, Persistent, RoleManager, Owned, Tabs): ...@@ -249,10 +249,8 @@ class SessionDataManager(Item, Implicit, Persistent, RoleManager, Owned, Tabs):
transactions for mounted storages. """ transactions for mounted storages. """
if self.obpath is None: if self.obpath is None:
err = 'Session data container is unspecified in %s' % self.getId() err = 'Session data container is unspecified in %s' % self.getId()
if DEBUG: LOG('Session Tracking', WARNING, err)
LOG('Session Tracking', 0, err)
raise SessionIdManagerErr, err raise SessionIdManagerErr, err
# return an external data container
try: try:
# This should arguably use restrictedTraverse, but it # This should arguably use restrictedTraverse, but it
# currently fails for mounted storages. This might # currently fails for mounted storages. This might
...@@ -260,7 +258,7 @@ class SessionDataManager(Item, Implicit, Persistent, RoleManager, Owned, Tabs): ...@@ -260,7 +258,7 @@ class SessionDataManager(Item, Implicit, Persistent, RoleManager, Owned, Tabs):
# unrestrictedTraverse is also much faster. # unrestrictedTraverse is also much faster.
if DEBUG and not hasattr(self, '_v_wrote_dc_type'): if DEBUG and not hasattr(self, '_v_wrote_dc_type'):
args = string.join(self.obpath, '/') args = string.join(self.obpath, '/')
LOG('Session Tracking', 0, LOG('Session Tracking', BLATHER,
'External data container at %s in use' % args) 'External data container at %s in use' % args)
self._v_wrote_dc_type = 1 self._v_wrote_dc_type = 1
return self.unrestrictedTraverse(self.obpath) return self.unrestrictedTraverse(self.obpath)
...@@ -303,24 +301,15 @@ class SessionDataManagerTraverser: ...@@ -303,24 +301,15 @@ class SessionDataManagerTraverser:
def __init__(self, requestSessionName, sdm): def __init__(self, requestSessionName, sdm):
self._requestSessionName = requestSessionName self._requestSessionName = requestSessionName
self._sessionDataManager = sdm self._sessionDataManager = sdm
self._v_errors=0
def __call__(self, container, request): def __call__(self, container, request):
sdm = self._sessionDataManager.__of__(container)
# Yank our session & stuff into request
try: try:
sdm = self._sessionDataManager.__of__(container)
session = sdm.getSessionData session = sdm.getSessionData
self._v_errors = 0
except: except:
errors = getattr(self,"_v_errors", 0) msg = 'Session automatic traversal failed to get session data'
if errors < 4: LOG('Session Tracking', WARNING, msg, error=sys.exc_info())
LOG('Session Tracking', WARNING,'Session automatic traversal ' return
'failed to get session data', error=sys.exc_info())
if errors == 3:
LOG('Session Tracking', WARNING, 'Suppressing further '
'automatic session failure error messages on this thread')
self._v_errors = errors + 1
return # Throw our hands up but dont fail
if self._requestSessionName is not None: if self._requestSessionName is not None:
request.set_lazy(self._requestSessionName, session) request.set_lazy(self._requestSessionName, session)
...@@ -243,4 +243,3 @@ class SessionDataManagerInterface( ...@@ -243,4 +243,3 @@ class SessionDataManagerInterface(
Permission required: Access arbitrary user session data Permission required: Access arbitrary user session data
""" """
...@@ -85,11 +85,14 @@ ...@@ -85,11 +85,14 @@
""" """
Session initialization routines Session initialization routines
$Id: __init__.py,v 1.4 2001/11/05 21:15:47 matt Exp $ $Id: __init__.py,v 1.5 2001/11/21 22:36:21 chrism Exp $
""" """
import ZODB # this is for testrunner to be happy
import BrowserIdManager import BrowserIdManager
import SessionDataManager import SessionDataManager
from BrowserIdManager import BrowserIdManagerErr
from SessionDataManager import SessionDataManagerErr
def initialize(context): def initialize(context):
context.registerClass( context.registerClass(
...@@ -108,6 +111,20 @@ def initialize(context): ...@@ -108,6 +111,20 @@ def initialize(context):
SessionDataManager.constructSessionDataManager) SessionDataManager.constructSessionDataManager)
) )
context.registerHelp() context.registerHelp()
context.registerHelpTitle("Zope Help") context.registerHelpTitle("Zope Help")
# do module security declarations so folks can use some of the
# module-level stuff in PythonScripts
#
# declare on behalf of Transience too, since ModuleSecurityInfo is too
# stupid for me to declare in two places without overwriting one set
# with the other. :-(
from AccessControl import ModuleSecurityInfo
security = ModuleSecurityInfo('Products')
security.declarePublic('Sessions')
security.declarePublic('Transience')
security = ModuleSecurityInfo('Products.Sessions')
security.declarePublic('BrowserIdManagerErr')
security.declarePublic('SessionDataManagerErr')
security = ModuleSecurityInfo('Products.Transience')
security.declarePublic('MaxTransientObjectsExceeded')
...@@ -82,11 +82,7 @@ Session API ...@@ -82,11 +82,7 @@ Session API
- "Transient Object API":../../Transience/Help/TransienceInterfaces.py - "Transient Object API":../../Transience/Help/TransienceInterfaces.py
""" """
import Interface class BrowserIdManagerInterface:
class BrowserIdManagerInterface(
Interface.Base
):
""" """
Zope Browser Id Manager interface. Zope Browser Id Manager interface.
...@@ -128,7 +124,7 @@ class BrowserIdManagerInterface( ...@@ -128,7 +124,7 @@ class BrowserIdManagerInterface(
Permission required: Access contents information Permission required: Access contents information
Raises: BrowserIdManagerErr. If ill-formed browser id Raises: BrowserIdManagerErr if ill-formed browser id
is found in REQUEST. is found in REQUEST.
""" """
...@@ -192,9 +188,7 @@ class BrowserIdManagerInterface( ...@@ -192,9 +188,7 @@ class BrowserIdManagerInterface(
a browser id namespace at the time of the call. a browser id namespace at the time of the call.
""" """
class SessionDataManagerInterface( class SessionDataManagerInterface:
Interface.Base
):
""" """
Zope Session Data Manager interface. Zope Session Data Manager interface.
...@@ -239,4 +233,26 @@ class SessionDataManagerInterface( ...@@ -239,4 +233,26 @@ class SessionDataManagerInterface(
Permission required: Access arbitrary user session data Permission required: Access arbitrary user session data
""" """
class SessionDataManagerErr:
"""
Error raised during some session data manager operations, as
explained in the API documentation of the Session Data Manager.
This exception may be caught in PythonScripts. A successful
import of the exception for PythonScript use would need to be::
from Products.Sessions import SessionDataManagerErr
"""
class BrowserIdManagerErr:
"""
Error raised during some browser id manager operations, as
explained in the API documentation of the Browser Id Manager.
This exception may be caught in PythonScripts. A successful
import of the exception for PythonScript use would need to be::
from Products.Sessions import BrowserIdManagerErr
"""
...@@ -85,9 +85,9 @@ ...@@ -85,9 +85,9 @@
""" """
Test suite for session id manager. Test suite for session id manager.
$Id: testBrowserIdManager.py,v 1.4 2001/11/20 16:08:10 chrism Exp $ $Id: testBrowserIdManager.py,v 1.5 2001/11/21 22:36:21 chrism Exp $
""" """
__version__ = "$Revision: 1.4 $"[11:-2] __version__ = "$Revision: 1.5 $"[11:-2]
import sys import sys
if __name__ == "__main__": if __name__ == "__main__":
...@@ -351,5 +351,5 @@ def test_suite(): ...@@ -351,5 +351,5 @@ def test_suite():
return testsuite return testsuite
if __name__ == '__main__': if __name__ == '__main__':
runner = TextTestRunner() runner = TextTestRunner(verbosity=9)
runner.run(test_suite()) runner.run(test_suite())
...@@ -85,14 +85,15 @@ ...@@ -85,14 +85,15 @@
import sys, os, time import sys, os, time
if __name__ == "__main__": if __name__ == "__main__":
sys.path.insert(0, '../../..') sys.path.insert(0, '../../..')
#os.chdir('../../..')
from Testing import makerequest from Testing import makerequest
import ZODB # in order to get Persistence.Persistent working import ZODB # in order to get Persistence.Persistent working
from OFS.DTMLMethod import DTMLMethod
import Acquisition import Acquisition
from Acquisition import aq_base from Acquisition import aq_base
from Products.Sessions.BrowserIdManager import BrowserIdManager from Products.Sessions.BrowserIdManager import BrowserIdManager
from Products.Sessions.SessionDataManager import \ from Products.Sessions.SessionDataManager import \
SessionDataManager, SessionDataManagerErr SessionDataManager, SessionDataManagerErr, SessionDataManagerTraverser
from Products.Transience.Transience import \ from Products.Transience.Transience import \
TransientObjectContainer, TransientObject TransientObjectContainer, TransientObject
from Products.TemporaryFolder.TemporaryFolder import MountedTemporaryFolder from Products.TemporaryFolder.TemporaryFolder import MountedTemporaryFolder
...@@ -103,8 +104,9 @@ import time, threading, whrandom ...@@ -103,8 +104,9 @@ import time, threading, whrandom
from cPickle import UnpickleableError from cPickle import UnpickleableError
from ZODB.DemoStorage import DemoStorage from ZODB.DemoStorage import DemoStorage
from OFS.Application import Application from OFS.Application import Application
from ZPublisher.BeforeTraverse import registerBeforeTraverse, \
unregisterBeforeTraverse
import sys import sys
sys.setcheckinterval(200)
tf_name = 'temp_folder' tf_name = 'temp_folder'
idmgr_name = 'browser_id_manager' idmgr_name = 'browser_id_manager'
...@@ -139,7 +141,8 @@ def _populate(app): ...@@ -139,7 +141,8 @@ def _populate(app):
toc = TransientObjectContainer(toc_name, title='Temporary ' toc = TransientObjectContainer(toc_name, title='Temporary '
'Transient Object Container', timeout_mins=20) 'Transient Object Container', timeout_mins=20)
session_data_manager=SessionDataManager(id='session_data_manager', session_data_manager=SessionDataManager(id='session_data_manager',
path='/'+tf_name+'/'+toc_name, title='Session Data Manager') path='/'+tf_name+'/'+toc_name, title='Session Data Manager',
requestName='TESTOFSESSION')
try: app._delObject(idmgr_name) try: app._delObject(idmgr_name)
except AttributeError: pass except AttributeError: pass
...@@ -150,6 +153,9 @@ def _populate(app): ...@@ -150,6 +153,9 @@ def _populate(app):
try: app._delObject('session_data_manager') try: app._delObject('session_data_manager')
except AttributeError: pass except AttributeError: pass
try: app._delObject('index_html')
except AttributeError: pass
app._setObject(idmgr_name, bidmgr) app._setObject(idmgr_name, bidmgr)
app._setObject('session_data_manager', session_data_manager) app._setObject('session_data_manager', session_data_manager)
...@@ -159,7 +165,11 @@ def _populate(app): ...@@ -159,7 +165,11 @@ def _populate(app):
app.temp_folder._setObject(toc_name, toc) app.temp_folder._setObject(toc_name, toc)
get_transaction().commit() get_transaction().commit()
# index_html necessary for publishing emulation for testAutoReqPopulate
app._setObject('index_html', DTMLMethod('', __name__='foo'))
get_transaction().commit()
class TestBase(TestCase): class TestBase(TestCase):
def setUp(self): def setUp(self):
db = _getDB() db = _getDB()
...@@ -191,6 +201,11 @@ class TestSessionManager(TestBase): ...@@ -191,6 +201,11 @@ class TestSessionManager(TestBase):
sd = self.app.session_data_manager.getSessionData() sd = self.app.session_data_manager.getSessionData()
assert self.app.session_data_manager.hasSessionData() assert self.app.session_data_manager.hasSessionData()
def testSessionDataWrappedInSDM(self):
sd = self.app.session_data_manager.getSessionData(1)
assert aq_base(sd.aq_parent) is \
aq_base(self.app.session_data_manager), sd.aq_parent
def testNewSessionDataObjectIsValid(self): def testNewSessionDataObjectIsValid(self):
sdType = type(TransientObject(1)) sdType = type(TransientObject(1))
sd = self.app.session_data_manager.getSessionData() sd = self.app.session_data_manager.getSessionData()
...@@ -201,6 +216,7 @@ class TestSessionManager(TestBase): ...@@ -201,6 +216,7 @@ class TestSessionManager(TestBase):
sd = self.app.session_data_manager.getSessionData() sd = self.app.session_data_manager.getSessionData()
sd.invalidate() sd.invalidate()
assert hasattr(sd, '_invalid') assert hasattr(sd, '_invalid')
assert not sd.isValid()
def testBrowserIdIsSet(self): def testBrowserIdIsSet(self):
sd = self.app.session_data_manager.getSessionData() sd = self.app.session_data_manager.getSessionData()
...@@ -215,29 +231,30 @@ class TestSessionManager(TestBase): ...@@ -215,29 +231,30 @@ class TestSessionManager(TestBase):
assert sd == bykeysd, (sd, bykeysd, token) assert sd == bykeysd, (sd, bykeysd, token)
def testBadExternalSDCPath(self): def testBadExternalSDCPath(self):
sdm = self.app.session_data_manager
# fake out webdav # fake out webdav
self.app.session_data_manager.REQUEST['REQUEST_METHOD'] = 'GET' sdm.REQUEST['REQUEST_METHOD'] = 'GET'
self.app.session_data_manager.setContainerPath('/fudgeffoloo') sdm.setContainerPath('/fudgeffoloo')
try: self.assertRaises(SessionDataManagerErr, self._testbadsdcpath)
self.app.session_data_manager.getSessionData()
except SessionDataManagerErr: def _testbadsdcpath(self):
pass self.app.session_data_manager.getSessionData()
else:
assert 1 == 2, self.app.session_data_manager.getSessionDataContainerPath()
def testInvalidateSessionDataObject(self): def testInvalidateSessionDataObject(self):
sd = self.app.session_data_manager.getSessionData() sdm = self.app.session_data_manager
sd = sdm.getSessionData()
sd['test'] = 'Its alive! Alive!' sd['test'] = 'Its alive! Alive!'
sd.invalidate() sd.invalidate()
assert not self.app.session_data_manager.getSessionData().has_key('test') assert not sdm.getSessionData().has_key('test')
def testGhostUnghostSessionManager(self): def testGhostUnghostSessionManager(self):
sdm = self.app.session_data_manager
get_transaction().commit() get_transaction().commit()
sd = self.app.session_data_manager.getSessionData() sd = sdm.getSessionData()
sd.set('foo', 'bar') sd.set('foo', 'bar')
self.app.session_data_manager._p_changed = None sdm._p_changed = None
get_transaction().commit() get_transaction().commit()
assert self.app.session_data_manager.getSessionData().get('foo') == 'bar' assert sdm.getSessionData().get('foo') == 'bar'
def testSubcommit(self): def testSubcommit(self):
sd = self.app.session_data_manager.getSessionData() sd = self.app.session_data_manager.getSessionData()
...@@ -261,6 +278,20 @@ class TestSessionManager(TestBase): ...@@ -261,6 +278,20 @@ class TestSessionManager(TestBase):
sd.set('foo', aq_wrapped) sd.set('foo', aq_wrapped)
self.assertRaises(UnpickleableError, get_transaction().commit) self.assertRaises(UnpickleableError, get_transaction().commit)
def testAutoReqPopulate(self):
self.app.REQUEST['PARENTS'] = [self.app]
self.app.REQUEST['URL'] = 'a'
self.app.REQUEST.traverse('/')
assert self.app.REQUEST.has_key('TESTOFSESSION')
def testUnlazifyAutoPopulated(self):
self.app.REQUEST['PARENTS'] = [self.app]
self.app.REQUEST['URL'] = 'a'
self.app.REQUEST.traverse('/')
sess = self.app.REQUEST['TESTOFSESSION']
sdType = type(TransientObject(1))
assert type(aq_base(sess)) is sdType, type(aq_base(sess))
def test_suite(): def test_suite():
test_datamgr = makeSuite(TestSessionManager, 'test') test_datamgr = makeSuite(TestSessionManager, 'test')
suite = TestSuite((test_datamgr,)) suite = TestSuite((test_datamgr,))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment