[Checkins] SVN: zope.app.session/trunk/src/zope/app/session/ Make progress with moving core components

Roger Ineichen roger at projekt01.ch
Tue Sep 25 17:28:40 EDT 2007


Log message for revision 80054:
  Make progress with moving core components 
  from zope.app.session to zope.session

Changed:
  D   zope.app.session/trunk/src/zope/app/session/DEPENDENCIES.cfg
  D   zope.app.session/trunk/src/zope/app/session/bootstrap.py
  U   zope.app.session/trunk/src/zope/app/session/browser.zcml
  U   zope.app.session/trunk/src/zope/app/session/configure.zcml
  D   zope.app.session/trunk/src/zope/app/session/design.txt
  U   zope.app.session/trunk/src/zope/app/session/ftesting.zcml
  U   zope.app.session/trunk/src/zope/app/session/http.py
  U   zope.app.session/trunk/src/zope/app/session/interfaces.py
  U   zope.app.session/trunk/src/zope/app/session/session.py
  U   zope.app.session/trunk/src/zope/app/session/tests.py

-=-
Deleted: zope.app.session/trunk/src/zope/app/session/DEPENDENCIES.cfg
===================================================================
--- zope.app.session/trunk/src/zope/app/session/DEPENDENCIES.cfg	2007-09-25 21:28:25 UTC (rev 80053)
+++ zope.app.session/trunk/src/zope/app/session/DEPENDENCIES.cfg	2007-09-25 21:28:40 UTC (rev 80054)
@@ -1,12 +0,0 @@
-BTrees
-ZODB
-persistent
-zope.component
-zope.interface
-zope.minmax
-zope.publisher
-zope.schema
-
-# TODO This dependency is bad.  It reflects use of a utility function
-# that should be copied elsewhere:
-zope.server

Deleted: zope.app.session/trunk/src/zope/app/session/bootstrap.py
===================================================================
--- zope.app.session/trunk/src/zope/app/session/bootstrap.py	2007-09-25 21:28:25 UTC (rev 80053)
+++ zope.app.session/trunk/src/zope/app/session/bootstrap.py	2007-09-25 21:28:40 UTC (rev 80054)
@@ -1,54 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2002, 2004 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Bootstrap code.
-
-This module contains code to bootstrap a Zope3 instance.  For example
-it makes sure a root folder exists and creates and configures some
-essential utilities.
-
-$Id$
-"""
-
-import transaction
-
-from zope.app.appsetup.bootstrap import ensureUtility, getInformationFromEvent
-
-from zope.app.session.interfaces import \
-     IClientIdManager, ISessionDataContainer
-from zope.app.session.http import CookieClientIdManager
-from zope.app.session.session import PersistentSessionDataContainer
-
-def bootStrapSubscriber(event):
-    """Subscriber to the IDataBaseOpenedEvent
-
-    Create utility at that time if not yet present
-    """
-
-    db, connection, root, root_folder = getInformationFromEvent(event)
-
-    ensureUtility(
-        root_folder,
-        IClientIdManager, 'CookieClientIdManager',
-        CookieClientIdManager,
-        asObject=True,
-        )
-    ensureUtility(
-        root_folder,
-        ISessionDataContainer, 'PersistentSessionDataContainer',
-        PersistentSessionDataContainer,
-        asObject=True,
-        )
-
-    transaction.commit()
-    connection.close()

Modified: zope.app.session/trunk/src/zope/app/session/browser.zcml
===================================================================
--- zope.app.session/trunk/src/zope/app/session/browser.zcml	2007-09-25 21:28:25 UTC (rev 80053)
+++ zope.app.session/trunk/src/zope/app/session/browser.zcml	2007-09-25 21:28:40 UTC (rev 80054)
@@ -9,11 +9,11 @@
     title="Cookie Client Id Manager"
     description="Uses a cookie to uniquely identify a client, allowing 
       state to be maintained between requests"
-    class=".http.CookieClientIdManager"
+    class="zope.session.http.CookieClientIdManager"
     permission="zope.ManageServices" />
 
   <editform
-    schema=".http.ICookieClientIdManager"
+    schema="zope.session.http.ICookieClientIdManager"
     label="Cookie Client Id Manager Properties"
     name="edit.html" menu="zmi_views" title="Edit"
     permission="zope.ManageServices" />
@@ -23,7 +23,7 @@
   <addMenuItem
     title="Persistent Session Data Container"
     description="Stores session data persistently in the ZODB"
-    class=".session.PersistentSessionDataContainer"
+    class="zope.session.session.PersistentSessionDataContainer"
     permission="zope.ManageServices" />
 
   <!-- RAMSessionDataContainer -->
@@ -31,12 +31,12 @@
   <addMenuItem
     title="RAM Session Data Container"
     description="Stores session data in RAM"
-    class=".session.RAMSessionDataContainer"
+    class="zope.session.session.RAMSessionDataContainer"
     permission="zope.ManageServices" />
 
   <!-- ISessionDataContainer -->
   <editform
-    schema=".interfaces.ISessionDataContainer"
+    schema="zope.session.interfaces.ISessionDataContainer"
     label="Session Data Container Properties"
     name="edit.html" menu="zmi_views" title="Edit"
     permission="zope.ManageServices" />

Modified: zope.app.session/trunk/src/zope/app/session/configure.zcml
===================================================================
--- zope.app.session/trunk/src/zope/app/session/configure.zcml	2007-09-25 21:28:25 UTC (rev 80053)
+++ zope.app.session/trunk/src/zope/app/session/configure.zcml	2007-09-25 21:28:40 UTC (rev 80054)
@@ -1,114 +1,9 @@
 <configure 
     xmlns="http://namespaces.zope.org/zope"
     xmlns:browser="http://namespaces.zope.org/browser"
-    i18n_domain="zope"
-    >
-    
-  <adapter
-      factory=".session.ClientId"
-      permission="zope.Public" 
-      />
+    i18n_domain="zope">
 
-  <adapter
-      factory=".session.Session"
-      provides="zope.app.session.interfaces.ISession"
-      permission="zope.Public"
-      />
-
-  <adapter
-      factory=".session.Session"
-      provides="zope.traversing.interfaces.IPathAdapter"
-      name="session"
-      />
-
-  <class class=".session.Session">
-    <allow interface=".interfaces.ISession" />
-    <implements interface="zope.traversing.interfaces.IPathAdapter" />
-  </class>
-
-  <class class=".http.CookieClientIdManager">
-    <require
-        interface=".http.ICookieClientIdManager"
-        permission="zope.Public" />
-    <require
-        set_schema=".http.ICookieClientIdManager"
-        permission="zope.ManageServices" />
-    <require
-        interface="zope.location.ILocation"
-        permission="zope.Public" />
-    <require
-        set_schema="zope.location.ILocation"
-        permission="zope.ManageServices" />
-  </class>
-
-  <class class=".session.PersistentSessionDataContainer">
-    <require
-        interface=".interfaces.ISessionDataContainer"
-        permission="zope.Public" />
-    <require
-        set_schema=".interfaces.ISessionDataContainer"
-        permission="zope.ManageServices" />
-    <require
-        interface="zope.location.ILocation"
-        permission="zope.Public" />
-    <require
-        set_schema="zope.location.ILocation"
-        permission="zope.ManageServices" />
-  </class>
-
-  <class class=".session.RAMSessionDataContainer">
-    <require
-        interface=".interfaces.ISessionDataContainer"
-        permission="zope.Public" />
-    <require
-        set_schema=".interfaces.ISessionDataContainer"
-        permission="zope.ManageServices" />
-    <require
-        interface="zope.location.ILocation"
-        permission="zope.Public" />
-    <require
-        set_schema="zope.location.ILocation"
-        permission="zope.ManageServices" />
-  </class>
-
-  <class class=".session.SessionData">
-    <allow interface=".interfaces.ISessionData" />
-  </class>
-
-  <class class=".session.SessionPkgData">
-    <allow interface=".interfaces.ISessionPkgData" />
-  </class>
-
-  <subscriber
-      for="zope.app.appsetup.IDatabaseOpenedEvent"
-      handler=".bootstrap.bootStrapSubscriber"
-      />
-      
-  <subscriber
-      for="zope.publisher.interfaces.http.IHTTPVirtualHostChangedEvent"
-      handler=".http.notifyVirtualHostChanged"
-      />
-
+  <include package="zope.session" />
   <include file="browser.zcml" />
 
-  <!-- Registering documentation with API doc -->
-  <configure
-      xmlns:apidoc="http://namespaces.zope.org/apidoc"
-      xmlns:zcml="http://namespaces.zope.org/zcml"
-      zcml:condition="have apidoc">
-
-    <apidoc:bookchapter
-        id="session"
-        title="Sessions"
-        doc_path="design.txt"
-        />
-    <apidoc:bookchapter
-        id="api"
-        title="API"
-        doc_path="api.txt"
-        parent="session"
-        />
-
-  </configure>
-
 </configure>

Deleted: zope.app.session/trunk/src/zope/app/session/design.txt
===================================================================
--- zope.app.session/trunk/src/zope/app/session/design.txt	2007-09-25 21:28:25 UTC (rev 80053)
+++ zope.app.session/trunk/src/zope/app/session/design.txt	2007-09-25 21:28:40 UTC (rev 80054)
@@ -1,146 +0,0 @@
-Sessions
-========
-
-Sessions provide a way to temporarily associate information with a
-client without requiring the authentication of a principal.  We
-associate an identifier with a particular client. Whenever we get a
-request from that client, we compute the identifier and use the
-identifier to look up associated information, which is stored on the
-server.
-
-A major disadvantage of sessions is that they require management of
-information on the server. This can have major implications for
-scalability.  It is possible for a framework to make use of session
-data very easy for the developer.  This is great if scalability is not
-an issue, otherwise, it is a booby trap.
-
-Design Issues
--------------
-
-Sessions introduce a number of issues to be considered:
-
-- Clients have to be identified. A number of approaches are possible,
-  including:
-
-  o Using HTTP cookies. The application assigns a client identifier,
-    which is stored in a cookie.  This technique is the most
-    straightforward, but can be defeated if the client does not
-    support HTTP cookies (usually because the feature has been
-    disabled).
-
-  o Using URLs.  The application assigns a client identifier, which is
-    stored in the URL.  This makes URLs a bit uglier and requires some
-    care. If people copy URLs and send them to others, then you could
-    end up with multiple clients with the same session
-    identifier. There are a number of ways to reduce the risk of
-    accidental reuse of session identifiers:
-
-    - Embed the client IP address in the identifier
-
-    - Expire the identifier
-
-  o Use hidden form variables.  This complicates applications. It
-    requires all requests to be POST requests and requires the
-    maintenance of the hidden variables.
-
-  o Use the client IP address
-
-    This doesn't work very well, because an IP address may be shared by
-    many clients.
-
-- Data storage
-
-  Data can be simply stored in the object database. This provides lots
-  of flexibility. You can store pretty much anything you want as long
-  as it is persistent. You get the full benefit of the object database,
-  such as transactions, transparency, clustering, and so on.  Using
-  the object database is especially useful when:
-
-  - Writes are infrequent
-
-  - Data are complex
-
-  If writes are frequent, then the object database introduces
-  scalability problems.  Really, any transactional database is likely
-  to introduce problems with frequent writes. If you are tempted to
-  update session data on every request, think very hard about it.  You
-  are creating a scalability problem.
-
-  If you know that scalability is not (and never will be) an issue,
-  you can just use the object database.
-
-  If you have client data that needs to be updated often (as in every
-  request), consider storing the data on the client.  (Like all data
-  received from a client, it may be tainted and, in most instances,
-  should not be trusted. Sensitive information that the user should
-  not see should likewise not be stored on the client, unless
-  encrypted with a key the client has no access to.)  If you can't
-  store it on the client, then consider some other storage mechanism,
-  like a fast database, possibly without transaction support.
-
-  You may be tempted to store session data in memory for speed.  This
-  doesn't turn out to work very well.  If you need scalability, then
-  you need to be able to use an application-server cluster and storage
-  of session data in memory defeats that.  You can use
-  "server-affinity" to assure that requests from a client always go
-  back to the same server, but not all load balancers support server
-  affinity, and, for those that do, enabling server affinity tends to
-  defeat load balancing.
-
-- Session expiration
-
-  You may wish to ensure that sessions terminate after some period of
-  time. This may be for security reasons, or to avoid accidental
-  sharing of a session among multiple clients.  The policy might be
-  expressed in terms of total session time, or maximum inactive time,
-  or some combination.
-
-  There are a number of ways to approach this.  You can expire client
-  ids. You can expire session data.
-
-- Data expiration
-
-  Because HTTP is a stateless protocol, you can't tell whether a user
-  is thinking about a task or has simply stopped working on it.  Some
-  means is needed to free server session storage that is no-longer needed.
-
-  The simplest strategy is to never remove data. This strategy has
-  some obvious disadvantages.  Other strategies can be viewed as
-  optimizations of the basic strategy.  It is important to realize that
-  a data expiration strategy can be informed by, but need not be
-  constrained by a session-expiration strategy.
-
-Application programming interface
----------------------------------
-
-Application code will merely adapt request objects to a session data
-interface.  Initially, we will define the session data interface
-``ISession``.  It provides a mapping interface. Keys in the mapping
-are application identifiers. Values are persistent mapping objects.
-
-Application code that wants to get object session data for a request
-adapts the request to ``ISession``::
-
-  appkey = "mycorp.actionplan"
-  data = ISession(request)[appkey]
-
-where ``appkey`` is a dotted name that identifies the application.
-Given the session data, the application can then store data in it::
-
-  data['original'] = original_actions
-  data['new'] = new_actions
-
-From ZPT, you can access session data using adapter syntax::
-
-  request/session:key
-
-So, for example, to access the ``old`` key for the session data for
-the sample key above:
-
-  request/session:mycorp.actionplan/old
-
-In this example, the data for an aplication key was a mapping object.
-The semantics of a session data for a particular application key are
-determined by the session data type interface.  ``ISession`` defines
-the application data to be a mapping object by default.  Other data
-interfaces could specify different bahavior.

Modified: zope.app.session/trunk/src/zope/app/session/ftesting.zcml
===================================================================
--- zope.app.session/trunk/src/zope/app/session/ftesting.zcml	2007-09-25 21:28:25 UTC (rev 80053)
+++ zope.app.session/trunk/src/zope/app/session/ftesting.zcml	2007-09-25 21:28:40 UTC (rev 80054)
@@ -11,6 +11,9 @@
   <include package="zope.app.securitypolicy" file="meta.zcml" />
 
   <include package="zope.app.zcmlfiles" />
+
+  <include package="zope.session" />
+
   <include package="zope.app.authentication" />
   <include package="zope.app.zptpage"/>
   <include package="zope.app.securitypolicy" />

Modified: zope.app.session/trunk/src/zope/app/session/http.py
===================================================================
--- zope.app.session/trunk/src/zope/app/session/http.py	2007-09-25 21:28:25 UTC (rev 80053)
+++ zope.app.session/trunk/src/zope/app/session/http.py	2007-09-25 21:28:40 UTC (rev 80054)
@@ -15,401 +15,15 @@
 
 $Id$
 """
-import hmac
-import logging
-import random
-import re
-import sha
-import string
-import time
-from cStringIO import StringIO
 
-import zope.location
-from persistent import Persistent
-from zope import schema, component
-from zope.interface import implements
-from zope.publisher.interfaces.http import IHTTPRequest
-from zope.publisher.interfaces.http import IHTTPApplicationRequest
-from zope.annotation.interfaces import IAttributeAnnotatable
-from zope.i18nmessageid import ZopeMessageFactory as _
+import zope.deferredimport
 
-from zope.app.session.interfaces import IClientIdManager
-from zope.schema.fieldproperty import FieldProperty
-from zope.app.http.httpdate import build_http_date
-
-__docformat__ = 'restructuredtext'
-
-cookieSafeTrans = string.maketrans("+/", "-.")
-
-logger = logging.getLogger()
-
-def digestEncode(s):
-    """Encode SHA digest for cookie."""
-    return s.encode("base64")[:-2].translate(cookieSafeTrans)
-
-class MissingClientIdException(Exception):
-    """No ClientId found in Request"""
-
-class ICookieClientIdManager(IClientIdManager):
-    """Manages sessions using a cookie"""
-
-    namespace = schema.TextLine(
-            title=_('Cookie Name'),
-            description=_(
-                "Name of cookie used to maintain state. "
-                "Must be unique to the site domain name, and only contain "
-                "ASCII letters, digits and '_'"
-                ),
-            required=True,
-            min_length=1,
-            max_length=30,
-            constraint=re.compile("^[\d\w_]+$").search,
-            )
-
-    cookieLifetime = schema.Int(
-            title=_('Cookie Lifetime'),
-            description=_(
-                "Number of seconds until the browser expires the cookie. "
-                "Leave blank expire the cookie when the browser is quit. "
-                "Set to 0 to never expire. "
-                ),
-            min=0,
-            required=False,
-            default=None,
-            missing_value=None,
-            )
-
-    thirdparty = schema.Bool(
-            title=_('Third party cookie'),
-            description=_(
-                "Is a third party issuing the identification cookie? "
-                "Servers like Apache or Nginx have capabilities to issue "
-                "identification cookies too. If Third party cookies are "
-                "beeing used, Zope will never send a cookie back, just check "
-                "for them."
-                ),
-            required=False,
-            default=False,
-            )
-
-
-class CookieClientIdManager(zope.location.Location, Persistent):
-    """Session utility implemented using cookies."""
-
-    implements(IClientIdManager, ICookieClientIdManager, IAttributeAnnotatable)
-
-    thirdparty = FieldProperty(ICookieClientIdManager['thirdparty'])
-    cookieLifetime = FieldProperty(ICookieClientIdManager['cookieLifetime'])
-
-    def __init__(self):
-        self.namespace = "zope3_cs_%x" % (int(time.time()) - 1000000000)
-        self.secret = "%.20f" % random.random()
-
-    def getClientId(self, request):
-        """Get the client id
-
-        This creates one if necessary:
-
-          >>> from zope.publisher.http import HTTPRequest
-          >>> request = HTTPRequest(StringIO(''), {}, None)
-          >>> bim = CookieClientIdManager()
-          >>> id = bim.getClientId(request)
-          >>> id == bim.getClientId(request)
-          True
-
-        The id is retained accross requests:
-
-          >>> request2 = HTTPRequest(StringIO(''), {}, None)
-          >>> request2._cookies = dict(
-          ...   [(name, cookie['value'])
-          ...    for (name, cookie) in request.response._cookies.items()
-          ...   ])
-          >>> id == bim.getClientId(request2)
-          True
-          >>> bool(id)
-          True
-
-        Note that the return value of this function is a string, not
-        an IClientId. This is because this method is used to implement
-        the IClientId Adapter.
-
-          >>> type(id) == type('')
-          True
-
-        It's also possible to use third-party cookies. E.g. Apache `mod_uid`
-        or Nginx `ngx_http_userid_module` are able to issue user tracking
-        cookies in front of Zope. In case thirdparty is activated Zope may
-        not set a cookie.
-        
-          >>> bim.thirdparty = True
-          >>> request3 = HTTPRequest(StringIO(''), {}, None)
-          >>> bim.getClientId(request3)
-          Traceback (most recent call last):
-          ...
-          MissingClientIdException          
-          >>> cookie = request3.response.getCookie(bim.namespace)
-          >>> cookie is None
-          True
-          
-        """
-        sid = self.getRequestId(request)
-        if sid is None:
-            if self.thirdparty:
-                raise MissingClientIdException
-            else:
-                sid = self.generateUniqueId()
-                
-        if not self.thirdparty:
-            self.setRequestId(request, sid)
-
-        return sid
-
-    def generateUniqueId(self):
-        """Generate a new, random, unique id.
-
-          >>> bim = CookieClientIdManager()
-          >>> id1 = bim.generateUniqueId()
-          >>> id2 = bim.generateUniqueId()
-          >>> id1 != id2
-          True
-
-        """
-        data = "%.20f%.20f%.20f" % (random.random(), time.time(), time.clock())
-        digest = sha.sha(data).digest()
-        s = digestEncode(digest)
-        # we store a HMAC of the random value together with it, which makes
-        # our session ids unforgeable.
-        mac = hmac.new(s, self.secret, digestmod=sha).digest()
-        return s + digestEncode(mac)
-
-    def getRequestId(self, request):
-        """Return the browser id encoded in request as a string
-
-        Return None if an id is not set.
-
-        For example:
-
-          >>> from zope.publisher.http import HTTPRequest
-          >>> request = HTTPRequest(StringIO(''), {}, None)
-          >>> bim = CookieClientIdManager()
-
-        Because no cookie has been set, we get no id:
-
-          >>> bim.getRequestId(request) is None
-          True
-
-        We can set an id:
-
-          >>> id1 = bim.generateUniqueId()
-          >>> bim.setRequestId(request, id1)
-
-        And get it back:
-
-          >>> bim.getRequestId(request) == id1
-          True
-
-        When we set the request id, we also set a response cookie.  We
-        can simulate getting this cookie back in a subsequent request:
-
-          >>> request2 = HTTPRequest(StringIO(''), {}, None)
-          >>> request2._cookies = dict(
-          ...   [(name, cookie['value'])
-          ...    for (name, cookie) in request.response._cookies.items()
-          ...   ])
-
-        And we get the same id back from the new request:
-
-          >>> bim.getRequestId(request) == bim.getRequestId(request2)
-          True
-
-        If another server is managing the ClientId cookies (Apache, Nginx)
-        we're returning their value without checking:
-        
-          >>> bim.namespace = 'uid'
-          >>> bim.thirdparty = True
-          >>> request3 = HTTPRequest(StringIO(''), {}, None)
-          >>> request3._cookies = {'uid': 'AQAAf0Y4gjgAAAQ3AwMEAg=='}
-          >>> bim.getRequestId(request3)
-          'AQAAf0Y4gjgAAAQ3AwMEAg=='
-          
-        """
-        response_cookie = request.response.getCookie(self.namespace)
-        if response_cookie:
-            sid = response_cookie['value']
-        else:
-            request = IHTTPApplicationRequest(request)
-            sid = request.getCookies().get(self.namespace, None)
-        if self.thirdparty:
-            return sid
-        else:
-            # If there is an id set on the response, use that but don't trust it.
-            # We need to check the response in case there has already been a new
-            # session created during the course of this request.
-            if sid is None or len(sid) != 54:
-                return None
-            s, mac = sid[:27], sid[27:]
-            if (digestEncode(hmac.new(s, self.secret, digestmod=sha).digest())
-                != mac):
-                return None
-            else:
-                return sid
-
-    def setRequestId(self, request, id):
-        """Set cookie with id on request.
-
-        This sets the response cookie:
-
-        See the examples in getRequestId.
-
-        Note that the id is checkec for validity. Setting an
-        invalid value is silently ignored:
-
-            >>> from zope.publisher.http import HTTPRequest
-            >>> request = HTTPRequest(StringIO(''), {}, None)
-            >>> bim = CookieClientIdManager()
-            >>> bim.getRequestId(request)
-            >>> bim.setRequestId(request, 'invalid id')
-            >>> bim.getRequestId(request)
-
-        For now, the cookie path is the application URL:
-
-            >>> cookie = request.response.getCookie(bim.namespace)
-            >>> cookie['path'] == request.getApplicationURL(path_only=True)
-            True
-
-        In the future, it should be the site containing the
-        CookieClientIdManager
-
-        By default, session cookies don't expire:
-
-            >>> cookie.has_key('expires')
-            False
-
-        Expiry time of 0 means never (well - close enough)
-
-            >>> bim.cookieLifetime = 0
-            >>> request = HTTPRequest(StringIO(''), {}, None)
-            >>> bid = bim.getClientId(request)
-            >>> cookie = request.response.getCookie(bim.namespace)
-            >>> cookie['expires']
-            'Tue, 19 Jan 2038 00:00:00 GMT'
-
-        A non-zero value means to expire after than number of seconds:
-
-            >>> bim.cookieLifetime = 3600
-            >>> request = HTTPRequest(StringIO(''), {}, None)
-            >>> bid = bim.getClientId(request)
-            >>> cookie = request.response.getCookie(bim.namespace)
-            >>> import rfc822
-            >>> expires = time.mktime(rfc822.parsedate(cookie['expires']))
-            >>> expires > time.mktime(time.gmtime()) + 55*60
-            True
-                        
-        If another server in front of Zope (Apache, Nginx) is managing the
-        cookies we won't set any ClientId cookies:
-        
-          >>> request = HTTPRequest(StringIO(''), {}, None)
-          >>> bim.thirdparty = True
-          >>> bim.setRequestId(request, '1234')
-          >>> cookie = request.response.getCookie(bim.namespace)
-          >>> cookie
-        """
-        # TODO: Currently, the path is the ApplicationURL. This is reasonable,
-        #     and will be adequate for most purposes.
-        #     A better path to use would be that of the folder that contains
-        #     the site manager this service is registered within. However,
-        #     that would be expensive to look up on each request, and would
-        #     have to be altered to take virtual hosting into account.
-        #     Seeing as this utility instance has a unique namespace for its
-        #     cookie, using ApplicationURL shouldn't be a problem.
-
-        if self.thirdparty:
-            logger.warning('ClientIdManager is using thirdparty cookies, '
-                'ignoring setIdRequest call')            
-        else:
-            if self.cookieLifetime is not None:
-                if self.cookieLifetime:
-                    expires = build_http_date(time.time() + self.cookieLifetime)
-                else:
-                    expires = 'Tue, 19 Jan 2038 00:00:00 GMT'
-                request.response.setCookie(
-                        self.namespace, id, expires=expires,
-                        path=request.getApplicationURL(path_only=True)
-                        )
-            else:
-                request.response.setCookie(
-                        self.namespace, id,
-                        path=request.getApplicationURL(path_only=True)
-                        )
-
-def notifyVirtualHostChanged(event):
-    """Adjust cookie paths when IVirtualHostRequest information changes.
-    
-    Given a event, this method should call a CookieClientIdManager's 
-    setRequestId if a cookie is present in the response for that manager. To
-    demonstrate we create a dummy manager object and event:
-    
-        >>> class DummyManager(object):
-        ...     implements(ICookieClientIdManager)
-        ...     namespace = 'foo'
-        ...     thirdparty = False
-        ...     request_id = None
-        ...     def setRequestId(self, request, id):
-        ...         self.request_id = id
-        ...
-        >>> manager = DummyManager()
-        >>> component.provideUtility(manager, IClientIdManager)
-        >>> from zope.publisher.http import HTTPRequest
-        >>> class DummyEvent (object):
-        ...     request = HTTPRequest(StringIO(''), {}, None)
-        >>> event = DummyEvent()
-        
-    With no cookies present, the manager should not be called:
-    
-        >>> notifyVirtualHostChanged(event)
-        >>> manager.request_id is None
-        True
-        
-    However, when a cookie *has* been set, the manager is called so it can
-    update the cookie if need be:
-    
-        >>> event.request.response.setCookie('foo', 'bar')
-        >>> notifyVirtualHostChanged(event)
-        >>> manager.request_id
-        'bar'
-    
-    If a server in front of Zope manages the ClientIds (Apache, Nginx), we
-    don't need to take care about the cookies
-
-        >>> manager2 = DummyManager()
-        >>> manager2.thirdparty = True
-        >>> event2 = DummyEvent()
-        
-    However, when a cookie *has* been set, the manager is called so it can
-    update the cookie if need be:
-    
-        >>> event2.request.response.setCookie('foo2', 'bar2')
-        >>> notifyVirtualHostChanged(event2)
-        >>> id = manager2.request_id
-        >>> id is None
-        True
-
-    Cleanup of the utility registration:
-    
-        >>> import zope.component.testing
-        >>> zope.component.testing.tearDown()
-        
-    """
-    # the event sends us a IHTTPApplicationRequest, but we need a
-    # IHTTPRequest for the response attribute, and so does the cookie-
-    # manager.
-    request = IHTTPRequest(event.request, None)
-    if event.request is None:
-        return 
-    for name, manager in component.getUtilitiesFor(IClientIdManager):
-        if manager and ICookieClientIdManager.providedBy(manager):
-            # Third party ClientId Managers need no modification at all 
-            if not manager.thirdparty:
-                cookie = request.response.getCookie(manager.namespace)
-                if cookie:
-                    manager.setRequestId(request, cookie['value'])
\ No newline at end of file
+zope.deferredimport.deprecated(
+    "It has moved to zope.session.http  This reference will be gone sometimes.",
+    ICookieClientIdManager = 'zope.session.http:ICookieClientIdManager',
+    MissingClientIdException = 'zope.session.http:MissingClientIdException',
+    notifyVirtualHostChanged = 'zope.session.http:notifyVirtualHostChanged',
+    CookieClientIdManager = 'zope.session.http:CookieClientIdManager',
+    digestEncode = 'zope.session.http:digestEncode',
+    cookieSafeTrans = 'zope.session.http:cookieSafeTrans',
+    )

Modified: zope.app.session/trunk/src/zope/app/session/interfaces.py
===================================================================
--- zope.app.session/trunk/src/zope/app/session/interfaces.py	2007-09-25 21:28:25 UTC (rev 80053)
+++ zope.app.session/trunk/src/zope/app/session/interfaces.py	2007-09-25 21:28:40 UTC (rev 80054)
@@ -15,140 +15,15 @@
 
 $Id$
 """
-from zope.interface import Interface
-from zope.interface.common.mapping import IMapping, IReadMapping, IWriteMapping
-from zope import schema
-from zope.i18nmessageid import ZopeMessageFactory as _
 
-__docformat__ = 'restructuredtext'
+import zope.deferredimport
 
-class IClientIdManager(Interface):
-    """Manages sessions - fake state over multiple client requests."""
-
-    def getClientId(request):
-        """Return the client id for the given request as a string.
-        
-        If the request doesn't have an attached sessionId a new one will be
-        generated.
-
-        This will do whatever is possible to do the HTTP request to ensure the
-        session id will be preserved. Depending on the specific method,
-        further action might be necessary on the part of the user.  See the
-        documentation for the specific implementation and its interfaces.
-
-        """
-
-
-class IClientId(Interface):
-    """A unique id representing a session"""
-
-    def __str__():
-        """As a unique ASCII string"""
-
-
-class ISessionDataContainer(IReadMapping, IWriteMapping):
-    """Stores data objects for sessions.
-
-    The object implementing this interface is responsible for expiring data as
-    it feels appropriate.
-
-    Usage::
-
-      session_data_container[client_id][product_id][key] = value
-
-    Note that this interface does not support the full mapping interface -
-    the keys need to remain secret so we can't give access to keys(), 
-    values() etc.
-
-    """
-    timeout = schema.Int(
-            title=_(u"Timeout"),
-            description=_(
-                "Number of seconds before data becomes stale and may "
-                "be removed. A value of '0' means no expiration."),
-            default=3600,
-            required=True,
-            min=0,
-            )
-    resolution = schema.Int(
-            title=_("Timeout resolution (in seconds)"),
-            description=_(
-                "Defines what the 'resolution' of item timeout is. "
-                "Setting this higher allows the transience machinery to "
-                "do fewer 'writes' at the expense of  causing items to time "
-                "out later than the 'Data object timeout value' by  a factor "
-                "of (at most) this many seconds."
-                ),
-            default=5*60,
-            required=True,
-            min=0,
-            )
-
-    def __getitem__(self, product_id):
-        """Return an ISessionPkgData"""
-
-    def __setitem__(self, product_id, value):
-        """Store an ISessionPkgData"""
-
-
-class ISession(Interface):
-    """This object allows retrieval of the correct ISessionData
-    for a particular product id
-    
-        >>> session = ISession(request)[product_id]
-        >>> session['color'] = 'red'
-        True
-
-        >>> ISessionData.providedBy(session)
-        True
-
-    """
-
-    def __getitem__(product_id):
-        """Return the relevant ISessionPkgData
-        
-        This involves locating the correct ISessionDataContainer for the 
-        given product id, determining the client id, and returning the
-        relevant ISessionPkgData.
-        
-        """
-
-    def get(product_id, default=None):
-        """Return the relevant ISessionPkgData or default if not
-        available"""
-
-
-class ISessionData(IReadMapping, IMapping):
-    """Storage for a particular product id's session data
-    
-    Contains 0 or more ISessionPkgData instances
-    
-    """
-
-    lastAccessTime = schema.Int(
-            title=_("Last Access Time"),
-            description=_(
-                "Approximate epoch time this ISessionData was last retrieved "
-                "from its ISessionDataContainer"
-                ),
-            default=0,
-            required=True,
-            )
-
-    # Note that only IReadMapping and IWriteMaping are implemented.
-    # We cannot give access to the keys, as they need to remain secret.
-
-    def __getitem__(self, client_id):
-        """Return an ISessionPkgData"""
-
-    def __setitem__(self, client_id, session_pkg_data):
-        """Store an ISessionPkgData"""
-
-
-class ISessionPkgData(IMapping):
-    """Storage for a particular product id and browser id's session data
-
-    Data is stored persistently and transactionally. Data stored must
-    be persistent or picklable.
-
-    """
+zope.deferredimport.deprecated(
+    "It has moved to zope.session.interfaces  This reference will be gone sometimes.",
+    IClientIdManager = 'zope.session.interfaces:IClientIdManager',
+    IClientId = 'zope.session.interfaces:IClientId',
+    ISessionDataContainer = 'zope.session.interfaces:ISessionDataContainer',
+    ISession = 'zope.session.interfaces:ISession',
+    ISessionData = 'zope.session.interfaces:ISessionData',
+    ISessionPkgData = 'zope.session.interfaces:ISessionPkgData',
+    )

Modified: zope.app.session/trunk/src/zope/app/session/session.py
===================================================================
--- zope.app.session/trunk/src/zope/app/session/session.py	2007-09-25 21:28:25 UTC (rev 80053)
+++ zope.app.session/trunk/src/zope/app/session/session.py	2007-09-25 21:28:40 UTC (rev 80054)
@@ -15,512 +15,17 @@
 
 $Id$
 """
-from cStringIO import StringIO
-import time, string, random, thread
-from UserDict import IterableUserDict
-from heapq import heapify, heappop
 
-import ZODB
-import ZODB.MappingStorage
-import zope.location
-import zope.minmax
-from persistent import Persistent
-from BTrees.OOBTree import OOBTree
+import zope.deferredimport
 
-from zope.interface import implements
-from zope.component import getUtility, adapts
-from zope.component.interfaces import ComponentLookupError
-from zope.publisher.interfaces import IRequest
-from zope.annotation.interfaces import IAttributeAnnotatable
-
-from interfaces import \
-        IClientIdManager, IClientId, ISession, ISessionDataContainer, \
-        ISessionPkgData, ISessionData
-
-__docformat__ = 'restructuredtext'
-
-cookieSafeTrans = string.maketrans("+/", "-.")
-
-def digestEncode(s):
-    """Encode SHA digest for cookie."""
-    return s.encode("base64")[:-2].translate(cookieSafeTrans)
-
-
-class ClientId(str):
-    """See zope.app.interfaces.utilities.session.IClientId
-
-        >>> import tests
-        >>> request = tests.setUp()
-
-        >>> id1 = ClientId(request)
-        >>> id2 = ClientId(request)
-        >>> id1 == id2
-        True
-
-        >>> tests.tearDown()
-
-    """
-    implements(IClientId)
-    adapts(IRequest)
-
-    def __new__(cls, request):
-        return str.__new__(
-                cls, getUtility(IClientIdManager).getClientId(request)
-                )
-
-
-class PersistentSessionDataContainer(zope.location.Location, Persistent, 
-    IterableUserDict):
-    """A SessionDataContainer that stores data in the ZODB"""
-
-    implements(ISessionDataContainer, IAttributeAnnotatable)
-
-    _v_last_sweep = 0 # Epoch time sweep last run
-
-    def __init__(self):
-        self.data = OOBTree()
-        self.timeout = 1 * 60 * 60
-        self.resolution = 50*60
-
-    def __getitem__(self, pkg_id):
-        """Retrieve an ISessionData
-
-            >>> sdc = PersistentSessionDataContainer()
-
-            >>> sdc.timeout = 60
-            >>> sdc.resolution = 3
-            >>> sdc['clientid'] = sd = SessionData()
-
-        To ensure stale data is removed, we can wind
-        back the clock using undocumented means...
-
-            >>> sd.lastAccessTime = sd.lastAccessTime - 64
-            >>> sdc._v_last_sweep = sdc._v_last_sweep - 4
-
-        Now the data should be garbage collected
-
-            >>> sdc['clientid']
-            Traceback (most recent call last):
-                [...]
-            KeyError: 'clientid'
-
-        Ensure lastAccessTime on the ISessionData is being updated
-        occasionally. The ISessionDataContainer maintains this whenever
-        the ISessionData is set or retrieved.
-
-        lastAccessTime on the ISessionData is set when it is added
-        to the ISessionDataContainer
-
-            >>> sdc['client_id'] = sd = SessionData()
-            >>> sd.lastAccessTime > 0
-            True
-
-        lastAccessTime is also updated whenever the ISessionData
-        is retrieved through the ISessionDataContainer, at most
-        once every 'resolution' seconds.
-
-            >>> then = sd.lastAccessTime = sd.lastAccessTime - 4
-            >>> now = sdc['client_id'].lastAccessTime
-            >>> now > then
-            True
-            >>> time.sleep(1)
-            >>> now == sdc['client_id'].lastAccessTime
-            True
-
-        Ensure lastAccessTime is not modified and no garbage collection
-        occurs when timeout == 0. We test this by faking a stale
-        ISessionData object.
-
-            >>> sdc.timeout = 0
-            >>> sd.lastAccessTime = sd.lastAccessTime - 5000
-            >>> lastAccessTime = sd.lastAccessTime
-            >>> sdc['client_id'].lastAccessTime == lastAccessTime
-            True
-
-        Next, we test session expiration functionality beyond transactions.
-
-            >>> import transaction
-            >>> from ZODB.DB import DB
-            >>> from ZODB.DemoStorage import DemoStorage
-            >>> sdc = PersistentSessionDataContainer()
-            >>> sdc.timeout = 60
-            >>> sdc.resolution = 3
-            >>> db = DB(DemoStorage('test_storage'))
-            >>> c = db.open()
-            >>> c.root()['sdc'] = sdc
-            >>> sdc['pkg_id'] = sd = SessionData()
-            >>> sd['name'] = 'bob'
-            >>> transaction.commit()
-
-        Access immediately. the data should be accessible.
-
-            >>> c.root()['sdc']['pkg_id']['name']
-            'bob'
-
-        Change the clock time and stale the session data.
-
-            >>> sdc = c.root()['sdc']
-            >>> sd = sdc['pkg_id']
-            >>> sd.lastAccessTime = sd.lastAccessTime - 64
-            >>> sdc._v_last_sweep = sdc._v_last_sweep - 4
-            >>> transaction.commit()
-
-        The data should be garbage collected.
-
-            >>> c.root()['sdc']['pkg_id']['name']
-            Traceback (most recent call last):
-                [...]
-            KeyError: 'pkg_id'
-
-        Then abort transaction and access the same data again.
-        The previous GC was cancelled, but deadline is over.
-        The data should be garbage collected again.
-
-            >>> transaction.abort()
-            >>> c.root()['sdc']['pkg_id']['name']
-            Traceback (most recent call last):
-                [...]
-            KeyError: 'pkg_id'
-
-        """
-        if self.timeout == 0:
-            return IterableUserDict.__getitem__(self, pkg_id)
-
-        now = time.time()
-
-        # TODO: When scheduler exists, sweeping should be done by
-        # a scheduled job since we are currently busy handling a
-        # request and may end up doing simultaneous sweeps
-
-        # If transaction is aborted after sweep. _v_last_sweep keep
-        # incorrect sweep time. So when self.data is ghost, revert the time
-        # to the previous _v_last_sweep time(_v_old_sweep).
-        if self.data._p_state < 0:
-            try:
-                self._v_last_sweep = self._v_old_sweep
-                del self._v_old_sweep
-            except AttributeError:
-                pass
-
-        if self._v_last_sweep + self.resolution < now:
-            self.sweep()
-            if getattr(self, '_v_old_sweep', None) is None:
-                self._v_old_sweep = self._v_last_sweep
-            self._v_last_sweep = now
-
-        rv = IterableUserDict.__getitem__(self, pkg_id)
-        # Only update lastAccessTime once every few minutes, rather than
-        # every hit, to avoid ZODB bloat and conflicts
-        if rv.lastAccessTime + self.resolution < now:
-            rv.lastAccessTime = int(now)
-        return rv
-
-    def __setitem__(self, pkg_id, session_data):
-        """Set an ISessionPkgData
-
-            >>> sdc = PersistentSessionDataContainer()
-            >>> sad = SessionData()
-
-        __setitem__ sets the ISessionData's lastAccessTime
-
-            >>> sad.lastAccessTime
-            0
-            >>> sdc['1'] = sad
-            >>> 0 < sad.lastAccessTime <= time.time()
-            True
-
-        We can retrieve the same object we put in
-
-            >>> sdc['1'] is sad
-            True
-
-        """
-        session_data.lastAccessTime = int(time.time())
-        return IterableUserDict.__setitem__(self, pkg_id, session_data)
-
-    def sweep(self):
-        """Clean out stale data
-
-            >>> sdc = PersistentSessionDataContainer()
-            >>> sdc['1'] = SessionData()
-            >>> sdc['2'] = SessionData()
-
-        Wind back the clock on one of the ISessionData's
-        so it gets garbage collected
-
-            >>> sdc['2'].lastAccessTime -= sdc.timeout * 2
-
-        Sweep should leave '1' and remove '2'
-
-            >>> sdc.sweep()
-            >>> sd1 = sdc['1']
-            >>> sd2 = sdc['2']
-            Traceback (most recent call last):
-                [...]
-            KeyError: '2'
-
-        """
-        # We only update the lastAccessTime every 'resolution' seconds.
-        # To compensate for this, we factor in the resolution when
-        # calculating the expiry time to ensure that we never remove
-        # data that has been accessed within timeout seconds.
-        expire_time = time.time() - self.timeout - self.resolution
-        heap = [(v.lastAccessTime, k) for k,v in self.data.items()]
-        heapify(heap)
-        while heap:
-            lastAccessTime, key = heappop(heap)
-            if lastAccessTime < expire_time:
-                del self.data[key]
-            else:
-                return
-
-
-class RAMSessionDataContainer(PersistentSessionDataContainer):
-    """A SessionDataContainer that stores data in RAM.
-
-    Currently session data is not shared between Zope clients, so
-    server affinity will need to be maintained to use this in a ZEO cluster.
-
-        >>> sdc = RAMSessionDataContainer()
-        >>> sdc['1'] = SessionData()
-        >>> sdc['1'] is sdc['1']
-        True
-        >>> ISessionData.providedBy(sdc['1'])
-        True
-
-    """
-    def __init__(self):
-        self.resolution = 5*60
-        self.timeout = 1 * 60 * 60
-        # Something unique
-        self.key = '%s.%s.%s' % (time.time(), random.random(), id(self))
-
-    _ram_storage = ZODB.MappingStorage.MappingStorage()
-    _ram_db = ZODB.DB(_ram_storage)
-    _conns = {}
-
-    def _getData(self):
-
-        # Open a connection to _ram_storage per thread
-        tid = thread.get_ident()
-        if not self._conns.has_key(tid):
-            self._conns[tid] = self._ram_db.open()
-
-        root = self._conns[tid].root()
-        if not root.has_key(self.key):
-            root[self.key] = OOBTree()
-        return root[self.key]
-
-    data = property(_getData, None)
-
-    def sweep(self):
-        super(RAMSessionDataContainer, self).sweep()
-        self._ram_db.pack(time.time())
-
-
-class Session(object):
-    """See zope.app.session.interfaces.ISession"""
-    implements(ISession)
-    adapts(IRequest)
-
-    def __init__(self, request):
-        self.client_id = str(IClientId(request))
-
-    def _sdc(self, pkg_id):
-        # Locate the ISessionDataContainer by looking up the named
-        # Utility, and falling back to the unnamed one.
-        try:
-            return getUtility(ISessionDataContainer, pkg_id)
-        except ComponentLookupError:
-            return getUtility(ISessionDataContainer)
-
-    def get(self, pkg_id, default=None):
-
-        """See zope.app.session.interfaces.ISession
-
-            >>> import tests
-            >>> request = tests.setUp(PersistentSessionDataContainer)
-
-           If we use get we get None or default returned if the pkg_id
-           is not there.
-           
-            >>> session = Session(request).get('not.there', 'default')
-            >>> session
-            'default'
-            
-           This method is lazy and does not create the session data.
-            >>> session = Session(request).get('not.there')
-            >>> session is None
-            True
-
-           The __getitem__ method instead creates the data.
-            >>> session = Session(request)['not.there']
-            >>> session is None
-            False
-            >>> session = Session(request).get('not.there')
-            >>> session is None
-            False
-            >>> tests.tearDown()
-
-        """
-
-
-        # The ISessionDataContainer contains two levels:
-        # ISessionDataContainer[client_id] == ISessionData
-        # ISessionDataContainer[client_id][pkg_id] == ISessionPkgData
-        sdc = self._sdc(pkg_id)
-        try:
-            sd = sdc[self.client_id]
-        except KeyError:
-            return default
-        try:
-            return sd[pkg_id]
-        except KeyError:
-            return default
-        
-
-    def __getitem__(self, pkg_id):
-        """See zope.app.session.interfaces.ISession
-
-            >>> import tests
-            >>> request = tests.setUp(PersistentSessionDataContainer)
-            >>> request2 = tests.HTTPRequest(StringIO(''), {}, None)
-
-            >>> ISession.providedBy(Session(request))
-            True
-
-        Setup some sessions, each with a distinct namespace
-
-            >>> session1 = Session(request)['products.foo']
-            >>> session2 = Session(request)['products.bar']
-            >>> session3 = Session(request2)['products.bar']
-
-        If we use the same parameters, we should retrieve the
-        same object
-
-            >>> session1 is Session(request)['products.foo']
-            True
-
-        Make sure it returned sane values
-
-            >>> ISessionPkgData.providedBy(session1)
-            True
-
-        Make sure that pkg_ids don't share a namespace.
-
-            >>> session1['color'] = 'red'
-            >>> session2['color'] = 'blue'
-            >>> session3['color'] = 'vomit'
-            >>> session1['color']
-            'red'
-            >>> session2['color']
-            'blue'
-            >>> session3['color']
-            'vomit'
-
-            >>> tests.tearDown()
-
-        """
-        sdc = self._sdc(pkg_id)
-
-        # The ISessionDataContainer contains two levels:
-        # ISessionDataContainer[client_id] == ISessionData
-        # ISessionDataContainer[client_id][pkg_id] == ISessionPkgData
-        try:
-            sd = sdc[self.client_id]
-        except KeyError:
-            sd = sdc[self.client_id] = SessionData()
-
-        try:
-            return sd[pkg_id]
-        except KeyError:
-            spd = sd[pkg_id] = SessionPkgData()
-            return spd
-
-
-class SessionData(Persistent, IterableUserDict):
-    """See zope.app.session.interfaces.ISessionData
-
-        >>> session = SessionData()
-        >>> ISessionData.providedBy(session)
-        True
-        >>> session.lastAccessTime
-        0
-
-    Before the zope.minmax package this class used to have an attribute
-    lastAccessTime initialized in the class itself to zero.
-    To avoid changing the interface, that attribute has been turned into a
-    property.  This part tests the behavior of a legacy session which would
-    have the lastAccessTime attribute loaded from the database.
-    The implementation should work for that case as well as with the new
-    session where lastAccessTime is a property.  These tests will
-    be removed in a later release (see the comments in the code below).
-
-    First, create an instance of SessionData and remove a protected attribute
-    _lastAcessTime from it to make it more like the legacy SessionData.  The
-    subsequent attempt to get lastAccessTime will return a 0, because the
-    lastAccessTime is not there and the dictionary returns the default value
-    zero supplied to its get() method.
-
-        >>> legacy_session = SessionData()
-        >>> del legacy_session._lastAccessTime
-        >>> legacy_session.lastAccessTime
-        0
-
-    Now, artificially add lastAccessTime to the instance's dictionary.
-    This should make it exactly like the legacy SessionData().
-
-        >>> legacy_session.__dict__['lastAccessTime'] = 42
-        >>> legacy_session.lastAccessTime
-        42
-
-    Finally, assign to lastAccessTime.  Since the instance now looks like a
-    legacy instance, this will trigger, through the property mechanism, a
-    creation of a zope.minmax.Maximum() object which will take over the
-    handling of this value and its conflict resolution from now on.
-
-        >>> legacy_session.lastAccessTime = 13
-        >>> legacy_session._lastAccessTime.value
-        13
-
-    """
-    implements(ISessionData)
-
-    # this is for support of legacy sessions; this comment and
-    # the next line will be removed in a later release
-    _lastAccessTime = None
-
-    def __init__(self):
-        self.data = OOBTree()
-        self._lastAccessTime = zope.minmax.Maximum(0)
-
-    def _getLastAccessTime(self):
-        # this conditional is for legacy sessions; this comment and
-        # the next two lines will be removed in a later release
-        if self._lastAccessTime is None:
-            return self.__dict__.get('lastAccessTime', 0)
-        return self._lastAccessTime.value
-
-    def _setLastAccessTime(self, value):
-        # this conditional is for legacy sessions; this comment and
-        # the next two lines will be removed in a later release
-        if self._lastAccessTime is None:
-            self._lastAccessTime = zope.minmax.Maximum(0)
-        self._lastAccessTime.value = value
-
-    lastAccessTime = property(fget=_getLastAccessTime,
-                              fset=_setLastAccessTime,
-                              doc='integer value of the last access time')
-
-
-class SessionPkgData(Persistent, IterableUserDict):
-    """See zope.app.session.interfaces.ISessionData
-
-        >>> session = SessionPkgData()
-        >>> ISessionPkgData.providedBy(session)
-        True
-    """
-    implements(ISessionPkgData)
-    def __init__(self):
-        self.data = OOBTree()
-
+zope.deferredimport.deprecated(
+    "It has moved to zope.session.session  This reference will be gone sometimes.",
+    SessionData = 'zope.session.session:SessionData',
+    SessionPkgData = 'zope.session.session:SessionPkgData',
+    Session = 'zope.session.session:Session',
+    RAMSessionDataContainer = 'zope.session.session:RAMSessionDataContainer',
+    PersistentSessionDataContainer = 'zope.session.session:PersistentSessionDataContainer',
+    ClientId = 'zope.session.session:ClientId',
+    digestEncode = 'zope.session.session:digestEncode',
+    cookieSafeTrans = 'zope.session.session:cookieSafeTrans',
+    )

Modified: zope.app.session/trunk/src/zope/app/session/tests.py
===================================================================
--- zope.app.session/trunk/src/zope/app/session/tests.py	2007-09-25 21:28:25 UTC (rev 80053)
+++ zope.app.session/trunk/src/zope/app/session/tests.py	2007-09-25 21:28:40 UTC (rev 80054)
@@ -22,30 +22,24 @@
 from zope.app.testing import ztapi, placelesssetup
 import transaction
 
-from zope.app.session.interfaces import IClientId, IClientIdManager, ISession
-from zope.app.session.interfaces import ISessionDataContainer
-from zope.app.session.interfaces import ISessionPkgData, ISessionData
+import zope.component
+from zope.session.interfaces import IClientId, IClientIdManager, ISession
+from zope.session.interfaces import ISessionDataContainer
+from zope.session.interfaces import ISessionPkgData, ISessionData
+from zope.session.session import ClientId, Session
+from zope.session.session import PersistentSessionDataContainer
+from zope.session.session import RAMSessionDataContainer
+from zope.session.http import CookieClientIdManager
 
-from zope.app.session.session import ClientId, Session
-from zope.app.session.session import PersistentSessionDataContainer
-from zope.app.session.session import RAMSessionDataContainer
-
-from zope.app.session.http import CookieClientIdManager
-
 from zope.publisher.interfaces import IRequest
 from zope.publisher.http import HTTPRequest
 
-from zope.app.appsetup.tests import TestBootstrapSubscriber, EventStub
-from zope.app.appsetup.bootstrap import bootStrapSubscriber
-from zope.app.session.bootstrap import bootStrapSubscriber as \
-     sessionBootstrapSubscriber
-
-from zope.component import provideHandler, getGlobalSiteManager
 from zope.app.folder import Folder
 from zope.app.folder.interfaces import IRootFolder
 from zope.app.publication.interfaces import IBeforeTraverseEvent
 from zope.app.testing.functional import BrowserTestCase
 from zope.app.zptpage.zptpage import ZPTPage
+
 from zope.app.session.testing import SessionLayer
 
 
@@ -63,28 +57,7 @@
 def tearDown():
     placelesssetup.tearDown()
 
-class TestBootstrap(TestBootstrapSubscriber):
 
-    def test_bootstrapSusbcriber(self):
-        bootStrapSubscriber(EventStub(self.db))
-
-        sessionBootstrapSubscriber(EventStub(self.db))
-
-        from zope.app.publication.zopepublication import ZopePublication
-        from zope.app.component.hooks import setSite
-        from zope.app import zapi
-
-        cx = self.db.open()
-        root = cx.root()
-        root_folder = root[ZopePublication.root_name]
-        setSite(root_folder)
-
-        zapi.getUtility(IClientIdManager)
-        zapi.getUtility(ISessionDataContainer)
-
-
-        cx.close()
-
 # Test the code in our API documentation is correct
 def test_documentation():
     pass
@@ -102,10 +75,6 @@
     transaction.abort()
 
 
-
-
-from interfaces import ISession
-
 class ZPTSessionTest(BrowserTestCase):
     content = u'''
         <div tal:define="
@@ -145,6 +114,7 @@
         response3 = self.fetch()
         self.failUnlessEqual(response3, u'3')
 
+
 class VirtualHostSessionTest(BrowserTestCase):
     def setUp(self):
         super(VirtualHostSessionTest, self).setUp()
@@ -156,11 +126,11 @@
         root['folder']['page'] = page
         self.commit()
         
-        provideHandler(self.accessSessionOnRootTraverse, 
+        zope.component.provideHandler(self.accessSessionOnRootTraverse, 
                        (IBeforeTraverseEvent,))
         
     def tearDown(self):
-        getGlobalSiteManager().unregisterHandler(
+        zope.component.getGlobalSiteManager().unregisterHandler(
             self.accessSessionOnRootTraverse, (IBeforeTraverseEvent,))
         
     def accessSessionOnRootTraverse(self, event):
@@ -191,13 +161,7 @@
     ZPTSessionTest.layer = SessionLayer
     VirtualHostSessionTest.layer = SessionLayer
     suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(TestBootstrap))
     suite.addTest(doctest.DocTestSuite())
-    suite.addTest(doctest.DocTestSuite('zope.app.session.session',
-        tearDown=tearDownTransaction))
-    suite.addTest(doctest.DocTestSuite('zope.app.session.http',
-        optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,)
-        )
     suite.addTest(unittest.makeSuite(ZPTSessionTest))
     suite.addTest(unittest.makeSuite(VirtualHostSessionTest))
     return suite



More information about the Checkins mailing list