[Checkins] SVN: Sandbox/shane/republish/zope/pipeline/ Experiment: the main database will be in the environment as 'zope.database'.

Shane Hathaway shane at hathawaymix.org
Fri Feb 13 00:21:32 EST 2009


Log message for revision 96485:
  Experiment: the main database will be in the environment as 'zope.database'.
  
  Along with the usual sketching and renaming.
  

Changed:
  A   Sandbox/shane/republish/zope/pipeline/__init__.py
  A   Sandbox/shane/republish/zope/pipeline/apps/authenticate.py
  D   Sandbox/shane/republish/zope/pipeline/apps/authenticator.py
  D   Sandbox/shane/republish/zope/pipeline/apps/caller.py
  A   Sandbox/shane/republish/zope/pipeline/apps/event.py
  A   Sandbox/shane/republish/zope/pipeline/apps/mapply.py
  D   Sandbox/shane/republish/zope/pipeline/apps/notify.py
  A   Sandbox/shane/republish/zope/pipeline/apps/openroot.py
  U   Sandbox/shane/republish/zope/pipeline/apps/requestsetup.py
  D   Sandbox/shane/republish/zope/pipeline/apps/rootopen.py
  U   Sandbox/shane/republish/zope/pipeline/apps/switch.py
  A   Sandbox/shane/republish/zope/pipeline/apps/traversal.py
  D   Sandbox/shane/republish/zope/pipeline/apps/traverser.py
  U   Sandbox/shane/republish/zope/pipeline/configure.zcml
  U   Sandbox/shane/republish/zope/pipeline/entry.py
  A   Sandbox/shane/republish/zope/pipeline/interfaces.py
  U   Sandbox/shane/republish/zope/pipeline/zcml.py

-=-
Added: Sandbox/shane/republish/zope/pipeline/__init__.py
===================================================================
--- Sandbox/shane/republish/zope/pipeline/__init__.py	                        (rev 0)
+++ Sandbox/shane/republish/zope/pipeline/__init__.py	2009-02-13 05:21:32 UTC (rev 96485)
@@ -0,0 +1,18 @@
+##############################################################################
+#
+# Copyright (c) 2009 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.
+#
+##############################################################################
+"""Configurable WSGI pipeline for publishing Zope applications.
+
+The zope.pipeline.entry module provides the functions for setting
+up a WSGI application built from a pipeline.
+"""

Copied: Sandbox/shane/republish/zope/pipeline/apps/authenticate.py (from rev 96459, Sandbox/shane/republish/zope/pipeline/apps/authenticator.py)
===================================================================
--- Sandbox/shane/republish/zope/pipeline/apps/authenticate.py	                        (rev 0)
+++ Sandbox/shane/republish/zope/pipeline/apps/authenticate.py	2009-02-13 05:21:32 UTC (rev 96485)
@@ -0,0 +1,86 @@
+##############################################################################
+#
+# Copyright (c) 2009 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.
+#
+##############################################################################
+
+from zope.component import getGlobalSiteManager
+from zope.interface import adapts
+from zope.interface import implements
+from zope.publisher.interfaces import IWSGIApplication
+from zope.security.management import newInteraction
+from zope.security.management import endInteraction
+
+from zope.app.security.interfaces import IAuthentication
+from zope.app.security.interfaces import IFallbackUnauthenticatedPrincipal
+
+
+class Authenticator(object):
+    """WSGI app that hooks into Zope-based authentication.
+
+    The WSGI environment must contain 'zope.request'.
+    """
+    implements(IWSGIApplication)
+    adapts(IWSGIApplication, IRequest)
+
+    def __init__(self, app, marker_request=None):
+        self.app = app
+
+    def __call__(self, environ, start_response):
+        request = environ['zope.request']
+        auth = getGlobalSiteManager().getUtility(IAuthentication)
+        principal = auth.authenticate(request)
+        if principal is None:
+            request.traversal_hooks.append(placeful_auth)
+            principal = auth.unauthenticatedPrincipal()
+            if principal is None:
+                # Get the fallback unauthenticated principal
+                principal = getUtility(IFallbackUnauthenticatedPrincipal)
+        request.principal = principal
+
+        newInteraction(request)
+        try:
+            return self.app(environ, start_response)
+        finally:
+            endInteraction()
+
+    def __repr__(self):
+        return '%s(%s)' % (self.__class__.__name__, repr(self.app))
+
+
+def placeful_auth(request, ob):
+    """Traversal hook that tries to authenticate in a context"""
+
+    if not IUnauthenticatedPrincipal.providedBy(request.principal):
+        # We've already got an authenticated user. There's nothing to do.
+        # Note that beforeTraversal guarentees that user is not None.
+        return
+
+    if not ISite.providedBy(ob):
+        # We won't find an authentication utility here, so give up.
+        return
+
+    sm = removeSecurityProxy(ob).getSiteManager()
+
+    auth = sm.queryUtility(IAuthentication)
+    if auth is None:
+        # No auth utility here
+        return
+
+    # Try to authenticate against the auth utility
+    principal = auth.authenticate(request)
+    if principal is None:
+        principal = auth.unauthenticatedPrincipal()
+        if principal is None:
+            # nothing to do here
+            return
+
+    request.setPrincipal(principal)

Deleted: Sandbox/shane/republish/zope/pipeline/apps/authenticator.py
===================================================================
--- Sandbox/shane/republish/zope/pipeline/apps/authenticator.py	2009-02-13 01:04:24 UTC (rev 96484)
+++ Sandbox/shane/republish/zope/pipeline/apps/authenticator.py	2009-02-13 05:21:32 UTC (rev 96485)
@@ -1,86 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2009 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.
-#
-##############################################################################
-
-from zope.component import getGlobalSiteManager
-from zope.interface import adapts
-from zope.interface import implements
-from zope.publisher.interfaces import IWSGIApplication
-from zope.security.management import newInteraction
-from zope.security.management import endInteraction
-
-from zope.app.security.interfaces import IAuthentication
-from zope.app.security.interfaces import IFallbackUnauthenticatedPrincipal
-
-
-class Authenticator(object):
-    """WSGI app that hooks into Zope-based authentication.
-
-    The WSGI environment must contain 'zope.request'.
-    """
-    implements(IWSGIApplication)
-    adapts(IWSGIApplication, IRequest)
-
-    def __init__(self, app, marker_request=None):
-        self.app = app
-
-    def __call__(self, environ, start_response):
-        request = environ['zope.request']
-        auth = getGlobalSiteManager().getUtility(IAuthentication)
-        principal = auth.authenticate(request)
-        if principal is None:
-            request.traversal_hooks.append(placeful_auth)
-            principal = auth.unauthenticatedPrincipal()
-            if principal is None:
-                # Get the fallback unauthenticated principal
-                principal = getUtility(IFallbackUnauthenticatedPrincipal)
-        request.principal = principal
-
-        newInteraction(request)
-        try:
-            return self.app(environ, start_response)
-        finally:
-            endInteraction()
-
-    def __repr__(self):
-        return '%s(%s)' % (self.__class__.__name__, repr(self.app))
-
-
-def placeful_auth(request, ob):
-    """Traversal hook that tries to authenticate in a context"""
-
-    if not IUnauthenticatedPrincipal.providedBy(request.principal):
-        # We've already got an authenticated user. There's nothing to do.
-        # Note that beforeTraversal guarentees that user is not None.
-        return
-
-    if not ISite.providedBy(ob):
-        # We won't find an authentication utility here, so give up.
-        return
-
-    sm = removeSecurityProxy(ob).getSiteManager()
-
-    auth = sm.queryUtility(IAuthentication)
-    if auth is None:
-        # No auth utility here
-        return
-
-    # Try to authenticate against the auth utility
-    principal = auth.authenticate(request)
-    if principal is None:
-        principal = auth.unauthenticatedPrincipal()
-        if principal is None:
-            # nothing to do here
-            return
-
-    request.setPrincipal(principal)

Deleted: Sandbox/shane/republish/zope/pipeline/apps/caller.py
===================================================================
--- Sandbox/shane/republish/zope/pipeline/apps/caller.py	2009-02-13 01:04:24 UTC (rev 96484)
+++ Sandbox/shane/republish/zope/pipeline/apps/caller.py	2009-02-13 05:21:32 UTC (rev 96485)
@@ -1,131 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2009 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.
-#
-##############################################################################
-
-from zope.interface import implements
-from zope.proxy import removeAllProxies
-from zope.publisher.interfaces import IWSGIApplication
-
-
-class Caller(object):
-    """WSGI app that calls the traversed object.
-
-    Requires 'zope.request', which implements IRequest, in the environment.
-    The 'traversed' attribute of the request must be set.
-    """
-    implements(IWSGIApplication)
-
-    def __call__(self, environ, start_response):
-        request = environ['zope.request']
-        name, ob = request.traversed[-1]
-        result = mapply(ob, request.positional_arguments, request)
-        response = request.response
-        if result is not response:
-            response.setResult(result)
-        start_response(response.getStatusString(), response.getHeaders())
-        return response.consumeBodyIter()
-
-    def __repr__(self):
-        return '%s()' % self.__class__.__name__
-
-
-_marker = object()  # Create a new marker object.
-
-def unwrapMethod(obj):
-    """obj -> (unwrapped, wrapperCount)
-
-    Unwrap 'obj' until we get to a real function, counting the number of
-    unwrappings.
-
-    Bail if we find a class or something we can't identify as callable.
-    """
-    wrapperCount = 0
-    unwrapped = obj
-
-    for i in range(10):
-        bases = getattr(unwrapped, '__bases__', None)
-        if bases is not None:
-            raise TypeError("mapply() can not call class constructors")
-
-        im_func = getattr(unwrapped, 'im_func', None)
-        if im_func is not None:
-            unwrapped = im_func
-            wrapperCount += 1
-        elif getattr(unwrapped, 'func_code', None) is not None:
-            break
-        else:
-            unwrapped = getattr(unwrapped, '__call__' , None)
-            if unwrapped is None:
-                raise TypeError("mapply() can not call %s" % repr(obj))
-    else:
-        raise TypeError("couldn't find callable metadata, mapply() error on %s"
-                        % repr(obj))
-
-    return unwrapped, wrapperCount
-
-
-def mapply(obj, positional=(), request={}):
-    __traceback_info__ = obj
-
-    # we need deep access for introspection. Waaa.
-    unwrapped = removeAllProxies(obj)
-
-    unwrapped, wrapperCount = unwrapMethod(unwrapped)
-
-    code = unwrapped.func_code
-    defaults = unwrapped.func_defaults
-    names = code.co_varnames[wrapperCount:code.co_argcount]
-
-    nargs = len(names)
-    if not positional:
-        args = []
-    else:
-        args = list(positional)
-        if len(args) > nargs:
-            given = len(args)
-            if wrapperCount:
-                given += wrapperCount
-            raise TypeError('%s() takes at most %d argument%s(%d given)' % (
-                getattr(unwrapped, '__name__', repr(obj)),
-                code.co_argcount,
-                (code.co_argcount > 1 and 's ' or ' '),
-                given))
-
-    get = request.get
-    nrequired = len(names)
-    if defaults:
-        nrequired -= len(defaults)
-
-    for index in range(len(args), nargs):
-        name = names[index]
-        v = get(name, _marker)
-        if v is _marker:
-            if name == 'REQUEST':
-                v = request
-            elif index < nrequired:
-                raise TypeError('Missing argument to %s(): %s' % (
-                    getattr(unwrapped, '__name__', repr(obj)), name))
-            else:
-                v = defaults[index - nrequired]
-        args.append(v)
-
-    args = tuple(args)
-
-    if __debug__:
-        return debug_call(obj, args)
-
-    return obj(*args)
-
-def debug_call(obj, args):
-    # The presence of this function allows us to set a pdb breakpoint
-    return obj(*args)

Copied: Sandbox/shane/republish/zope/pipeline/apps/event.py (from rev 96459, Sandbox/shane/republish/zope/pipeline/apps/notify.py)
===================================================================
--- Sandbox/shane/republish/zope/pipeline/apps/event.py	                        (rev 0)
+++ Sandbox/shane/republish/zope/pipeline/apps/event.py	2009-02-13 05:21:32 UTC (rev 96485)
@@ -0,0 +1,48 @@
+##############################################################################
+#
+# Copyright (c) 2009 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.
+#
+##############################################################################
+
+from zope.event import notify
+from zope.interface import adapts
+from zope.interface import implements
+from zope.publisher.interfaces import IWSGIApplication
+from zope.publisher.interfaces.event import BeforeTraverseEvent
+from zope.publisher.interfaces.event import EndRequestEvent
+
+
+class EventNotifier(object):
+    """Fires request-related events.
+
+    Fires BeforeTraverseEvent and EndRequestEvent at the appropriate
+    times.
+    """
+    implements(IWSGIApplication)
+    adapts(IWSGIApplication)
+
+    def __init__(self, app):
+        self.app = app
+
+    def __call__(self, environ, start_response):
+        request = environ['zope.request']
+        request.traversal_hooks.append(fireBeforeTraverse)
+        try:
+            return self.app(environ, start_response)
+        finally:
+            if request.traversed:
+                name, ob = request.traversed[-1]
+            else:
+                ob = None
+            notify(EndRequestEvent(ob, request))
+
+def fireBeforeTraverse(request, ob):
+    notify(BeforeTraverseEvent(ob, request))

Copied: Sandbox/shane/republish/zope/pipeline/apps/mapply.py (from rev 96459, Sandbox/shane/republish/zope/pipeline/apps/caller.py)
===================================================================
--- Sandbox/shane/republish/zope/pipeline/apps/mapply.py	                        (rev 0)
+++ Sandbox/shane/republish/zope/pipeline/apps/mapply.py	2009-02-13 05:21:32 UTC (rev 96485)
@@ -0,0 +1,131 @@
+##############################################################################
+#
+# Copyright (c) 2009 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.
+#
+##############################################################################
+
+from zope.interface import implements
+from zope.proxy import removeAllProxies
+from zope.publisher.interfaces import IWSGIApplication
+
+
+class Caller(object):
+    """WSGI app that calls the traversed object.
+
+    Requires 'zope.request', which implements IRequest, in the environment.
+    The 'traversed' attribute of the request must be set.
+    """
+    implements(IWSGIApplication)
+
+    def __call__(self, environ, start_response):
+        request = environ['zope.request']
+        name, ob = request.traversed[-1]
+        result = mapply(ob, request.positional_arguments, request)
+        response = request.response
+        if result is not response:
+            response.setResult(result)
+        start_response(response.getStatusString(), response.getHeaders())
+        return response.consumeBodyIter()
+
+    def __repr__(self):
+        return '%s()' % self.__class__.__name__
+
+
+_marker = object()  # Create a new marker object.
+
+def unwrapMethod(obj):
+    """obj -> (unwrapped, wrapperCount)
+
+    Unwrap 'obj' until we get to a real function, counting the number of
+    unwrappings.
+
+    Bail if we find a class or something we can't identify as callable.
+    """
+    wrapperCount = 0
+    unwrapped = obj
+
+    for i in range(10):
+        bases = getattr(unwrapped, '__bases__', None)
+        if bases is not None:
+            raise TypeError("mapply() can not call class constructors")
+
+        im_func = getattr(unwrapped, 'im_func', None)
+        if im_func is not None:
+            unwrapped = im_func
+            wrapperCount += 1
+        elif getattr(unwrapped, 'func_code', None) is not None:
+            break
+        else:
+            unwrapped = getattr(unwrapped, '__call__' , None)
+            if unwrapped is None:
+                raise TypeError("mapply() can not call %s" % repr(obj))
+    else:
+        raise TypeError("couldn't find callable metadata, mapply() error on %s"
+                        % repr(obj))
+
+    return unwrapped, wrapperCount
+
+
+def mapply(obj, positional=(), request={}):
+    __traceback_info__ = obj
+
+    # we need deep access for introspection. Waaa.
+    unwrapped = removeAllProxies(obj)
+
+    unwrapped, wrapperCount = unwrapMethod(unwrapped)
+
+    code = unwrapped.func_code
+    defaults = unwrapped.func_defaults
+    names = code.co_varnames[wrapperCount:code.co_argcount]
+
+    nargs = len(names)
+    if not positional:
+        args = []
+    else:
+        args = list(positional)
+        if len(args) > nargs:
+            given = len(args)
+            if wrapperCount:
+                given += wrapperCount
+            raise TypeError('%s() takes at most %d argument%s(%d given)' % (
+                getattr(unwrapped, '__name__', repr(obj)),
+                code.co_argcount,
+                (code.co_argcount > 1 and 's ' or ' '),
+                given))
+
+    get = request.get
+    nrequired = len(names)
+    if defaults:
+        nrequired -= len(defaults)
+
+    for index in range(len(args), nargs):
+        name = names[index]
+        v = get(name, _marker)
+        if v is _marker:
+            if name == 'REQUEST':
+                v = request
+            elif index < nrequired:
+                raise TypeError('Missing argument to %s(): %s' % (
+                    getattr(unwrapped, '__name__', repr(obj)), name))
+            else:
+                v = defaults[index - nrequired]
+        args.append(v)
+
+    args = tuple(args)
+
+    if __debug__:
+        return debug_call(obj, args)
+
+    return obj(*args)
+
+def debug_call(obj, args):
+    # The presence of this function allows us to set a pdb breakpoint
+    return obj(*args)

Deleted: Sandbox/shane/republish/zope/pipeline/apps/notify.py
===================================================================
--- Sandbox/shane/republish/zope/pipeline/apps/notify.py	2009-02-13 01:04:24 UTC (rev 96484)
+++ Sandbox/shane/republish/zope/pipeline/apps/notify.py	2009-02-13 05:21:32 UTC (rev 96485)
@@ -1,48 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2009 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.
-#
-##############################################################################
-
-from zope.event import notify
-from zope.interface import adapts
-from zope.interface import implements
-from zope.publisher.interfaces import IWSGIApplication
-from zope.publisher.interfaces.event import BeforeTraverseEvent
-from zope.publisher.interfaces.event import EndRequestEvent
-
-
-class EventNotifier(object):
-    """Fires request-related events.
-
-    Fires are BeforeTraverseEvent and EndRequestEvent at the appropriate
-    times.
-    """
-    implements(IWSGIApplication)
-    adapts(IWSGIApplication)
-
-    def __init__(self, app):
-        self.app = app
-
-    def __call__(self, environ, start_response):
-        request = environ['zope.request']
-        request.traversal_hooks.append(fireBeforeTraverse)
-        try:
-            return self.app(environ, start_response)
-        finally:
-            if request.traversed:
-                name, ob = request.traversed[-1]
-            else:
-                ob = None
-            notify(EndRequestEvent(ob, request))
-
-def fireBeforeTraverse(request, ob):
-    notify(BeforeTraverseEvent(ob, request))

Copied: Sandbox/shane/republish/zope/pipeline/apps/openroot.py (from rev 96459, Sandbox/shane/republish/zope/pipeline/apps/rootopen.py)
===================================================================
--- Sandbox/shane/republish/zope/pipeline/apps/openroot.py	                        (rev 0)
+++ Sandbox/shane/republish/zope/pipeline/apps/openroot.py	2009-02-13 05:21:32 UTC (rev 96485)
@@ -0,0 +1,69 @@
+##############################################################################
+#
+# Copyright (c) 2009 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.
+#
+##############################################################################
+
+from zope.component import getUtility
+from zope.interface import adapts
+from zope.interface import implements
+from zope.publisher.interfaces import IWSGIApplication
+from zope.security.checker import ProxyFactory
+
+
+class RootOpener(object):
+    """Puts a root object in 'zope.request' of the WSGI environment.
+
+    Requires the environment to contain 'zope.database',
+    which is normally a ZODB.DB.DB object.
+    Sets request.traversed to a list with one element.
+    Also closes the database connection on the way out.
+
+    Special case: if the traversal stack contains "++etc++process",
+    instead of opening the database, this uses the utility by that
+    name as the root object.
+    """
+    implements(IWSGIApplication)
+    adapts(IWSGIApplication)
+
+    root_name = 'Application'
+    app_controller_name = '++etc++process'
+
+    def __init__(self, app):
+        self.app = app
+
+    def __call__(self, environ, start_response):
+        request = environ['zope.request']
+
+        # If the traversal stack contains self.app_controller_name,
+        # then we should get the app controller rather than look
+        # in the database.
+        if self.app_controller_name in request.traversal_stack:
+            root = getUtility(name=self.app_controller_name)
+            request.traversed = [(self.app_controller_name, root)]
+            return self.app(environ, start_response)
+
+        # Open the database.
+        db = environ['zope.database']
+        conn = db.open()
+
+        request.annotations['ZODB.interfaces.IConnection'] = conn
+        root = conn.root()
+        app = root.get(self.root_name, None)
+        if app is None:
+            raise SystemError("Zope Application Not Found")
+
+        request.traversed = [(self.root_name, ProxyFactory(app))]
+
+        try:
+            return self.app(environ, start_response)
+        finally:
+            conn.close()

Modified: Sandbox/shane/republish/zope/pipeline/apps/requestsetup.py
===================================================================
--- Sandbox/shane/republish/zope/pipeline/apps/requestsetup.py	2009-02-13 01:04:24 UTC (rev 96484)
+++ Sandbox/shane/republish/zope/pipeline/apps/requestsetup.py	2009-02-13 05:21:32 UTC (rev 96485)
@@ -16,6 +16,8 @@
 __docformat__ = 'restructuredtext'
 
 from zope.configuration.exceptions import ConfigurationError
+from zope.httpform import FormParser
+from zope.i18n.interfaces import IUserPreferredCharsets
 from zope.interface import adapts
 from zope.interface import implements
 from zope.publisher.interfaces import IWSGIApplication
@@ -54,6 +56,9 @@
 class ProcessForm(object):
     """WSGI middleware that processes HTML form data.
 
+    This step is separate from request creation so that the
+    error handling step can catch form data errors.
+
     Requires the environment to contain a 'zope.request' that
     is an IHTTPRequest, not just an IRequest.
     """
@@ -85,7 +90,6 @@
 
         parser = FormParser(environ, to_unicode=to_unicode)
         request.form = parser.parse()
-
         if parser.action:
             request.traversal_stack.insert(0, parser.action)
 
@@ -93,8 +97,7 @@
 
 
 class RequestFactoryRegistry(object):
-    """The registry implements a four stage lookup for registered factories
-    that have to deal with requests::
+    """This registry implements a four stage lookup for request factories::
 
         {scheme -> {method > { mimetype ->
             [
@@ -141,7 +144,7 @@
                                      'priorities. Please check your ZCML '
                                      'configuration')
 
-    def getFactoriesFor(self, scheme, method, mimetype):
+    def get_factories_for(self, scheme, method, mimetype):
         if ';' in mimetype:
             # `mimetype` might be something like 'text/xml; charset=utf8'. In
             # this case we are only interested in the first part.
@@ -152,7 +155,6 @@
         except KeyError:
             return None
 
-
     def make_request(self, scheme, method, mimetype, environment):
         """Get a factory given scheme+method+mimetype and an environment."""
 
@@ -162,7 +164,7 @@
             (scheme, '*', '*')
             ]
         for s, m, mt in variations:
-            factory_lst = self.getFactoriesFor(s, m, mt)
+            factory_lst = self.get_factories_for(s, m, mt)
             if factory_lst:
                 # Try to call each factory.  If the factory can't or
                 # doesn't want to handle the given environment, it should
@@ -178,4 +180,3 @@
 factoryRegistry = RequestFactoryRegistry()
 
 cleanup.addCleanUp(lambda : factoryRegistry.__init__())
-

Deleted: Sandbox/shane/republish/zope/pipeline/apps/rootopen.py
===================================================================
--- Sandbox/shane/republish/zope/pipeline/apps/rootopen.py	2009-02-13 01:04:24 UTC (rev 96484)
+++ Sandbox/shane/republish/zope/pipeline/apps/rootopen.py	2009-02-13 05:21:32 UTC (rev 96485)
@@ -1,68 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2009 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.
-#
-##############################################################################
-
-from zope.component import getUtility
-from zope.interface import adapts
-from zope.interface import implements
-from zope.publisher.interfaces import IWSGIApplication
-from zope.security.checker import ProxyFactory
-
-
-class RootOpener(object):
-    """Puts a root object in 'zope.request' of the WSGI environment.
-
-    Sets request.traversed to a list with one element.
-    Also closes the database connection on the way out.
-
-    Special case: if the traversal stack contains "++etc++process",
-    instead of opening the database, this uses the utility by that
-    name as the root object.
-    """
-    implements(IWSGIApplication)
-    adapts(IWSGIApplication, IZopeConfiguration)
-
-    database_name = 'main'
-    root_name = 'Application'
-    app_controller_name = '++etc++process'
-
-    def __init__(self, app, zope_conf):
-        self.app = app
-        self.db = zope_conf.databases[self.database_name]
-
-    def __call__(self, environ, start_response):
-        request = environ['zope.request']
-
-        # If the traversal stack contains self.app_controller_name,
-        # then we should get the app controller rather than look
-        # in the database.
-        if self.app_controller_name in request.traversal_stack:
-            root = getUtility(name=self.app_controller_name)
-            request.traversed = [(self.app_controller_name, root)]
-            return self.app(environ, start_response)
-
-        # Open the database.
-        conn = self.db.open()
-
-        request.annotations['ZODB.interfaces.IConnection'] = conn
-        root = conn.root()
-        app = root.get(self.root_name, None)
-        if app is None:
-            raise SystemError("Zope Application Not Found")
-
-        request.traversed = [(self.root_name, ProxyFactory(app))]
-
-        try:
-            return self.app(environ, start_response)
-        finally:
-            conn.close()

Modified: Sandbox/shane/republish/zope/pipeline/apps/switch.py
===================================================================
--- Sandbox/shane/republish/zope/pipeline/apps/switch.py	2009-02-13 01:04:24 UTC (rev 96484)
+++ Sandbox/shane/republish/zope/pipeline/apps/switch.py	2009-02-13 05:21:32 UTC (rev 96485)
@@ -27,7 +27,7 @@
 
     def __call__(self, environ, start_response):
         request = environ['zope.request']
-        app = get_pipeline(request)
+        app = get_pipeline(request=request)
         return app(environ, start_response)
 
     def __repr__(self):

Copied: Sandbox/shane/republish/zope/pipeline/apps/traversal.py (from rev 96459, Sandbox/shane/republish/zope/pipeline/apps/traverser.py)
===================================================================
--- Sandbox/shane/republish/zope/pipeline/apps/traversal.py	                        (rev 0)
+++ Sandbox/shane/republish/zope/pipeline/apps/traversal.py	2009-02-13 05:21:32 UTC (rev 96485)
@@ -0,0 +1,68 @@
+##############################################################################
+#
+# Copyright (c) 2009 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.
+#
+##############################################################################
+
+from zope.interface import adapts
+from zope.interface import implements
+from zope.publisher.interfaces import IWSGIApplication
+
+
+class Traverser(object):
+    """Traverses the object graph based on the traversal stack.
+
+    Requires 'zope.request' in the WSGI environment.
+    """
+    implements(IWSGIApplication)
+    adapts(IWSGIApplication)
+
+    def __init__(self, app):
+        self.app = app
+
+    def __call__(self, environ, start_response):
+        request = environ['zope.request']
+        self.traverse(request)
+        return self.app(environ, start_response)
+
+    def traverse(self, request):
+        traversal_stack = request.traversal_stack
+        traversal_hooks = request.traversal_hooks
+        traversed = request.traversed
+
+        root_name, obj = traversed[-1]
+        prev_object = None
+
+        while True:
+            if obj is not prev_object:
+                # Call hooks (but not more than once).
+                for hook in traversal_hooks:
+                    hook(request, obj)
+
+            if not traversal_stack:
+                break
+
+            prev_object = obj
+
+            # Traverse to the next step.
+            name = traversal_stack.pop()
+            obj = self.traverse_name(obj, name)
+            traversed.append((name, obj))
+
+    def traverse_name(self, obj, name):
+        pass
+
+
+class HTTPTraverser(Traverser):
+    implements(IWSGIApplication)
+    adapts(IWSGIApplication)
+    request_type = IHTTPRequest
+

Deleted: Sandbox/shane/republish/zope/pipeline/apps/traverser.py
===================================================================
--- Sandbox/shane/republish/zope/pipeline/apps/traverser.py	2009-02-13 01:04:24 UTC (rev 96484)
+++ Sandbox/shane/republish/zope/pipeline/apps/traverser.py	2009-02-13 05:21:32 UTC (rev 96485)
@@ -1,68 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2009 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.
-#
-##############################################################################
-
-from zope.interface import adapts
-from zope.interface import implements
-from zope.publisher.interfaces import IWSGIApplication
-
-
-class Traverser(object):
-    """Traverses the object graph based on the traversal stack.
-
-    Requires 'zope.request' in the WSGI environment.
-    """
-    implements(IWSGIApplication)
-    adapts(IWSGIApplication)
-
-    def __init__(self, app):
-        self.app = app
-
-    def __call__(self, environ, start_response):
-        request = environ['zope.request']
-        self.traverse(request)
-        return self.app(environ, start_response)
-
-    def traverse(self, request):
-        traversal_stack = request.traversal_stack
-        traversal_hooks = request.traversal_hooks
-        traversed = request.traversed
-
-        root_name, obj = traversed[-1]
-        prev_object = None
-
-        while True:
-            if obj is not prev_object:
-                # Call hooks (but not more than once).
-                for hook in traversal_hooks:
-                    hook(request, obj)
-
-            if not traversal_stack:
-                break
-
-            prev_object = obj
-
-            # Traverse to the next step.
-            name = traversal_stack.pop()
-            obj = self.traverse_name(obj, name)
-            traversed.append((name, obj))
-
-    def traverse_name(self, obj, name):
-        pass
-
-
-class HTTPTraverser(Traverser):
-    implements(IWSGIApplication)
-    adapts(IWSGIApplication)
-    request_type = IHTTPRequest
-

Modified: Sandbox/shane/republish/zope/pipeline/configure.zcml
===================================================================
--- Sandbox/shane/republish/zope/pipeline/configure.zcml	2009-02-13 01:04:24 UTC (rev 96484)
+++ Sandbox/shane/republish/zope/pipeline/configure.zcml	2009-02-13 05:21:32 UTC (rev 96485)
@@ -39,8 +39,8 @@
     for=".interfaces.INoRequest" />
 
 <wsgi:middleware
-    factory="..."
-    name="request_setup"
+    factory=".apps.requestsetup.CreateRequest"
+    name="create_request"
     for=".interfaces.INoRequest" />
 
 <!-- a wsgi:application directive registers an application for use
@@ -59,39 +59,51 @@
 
 <wsgi:middleware
     factory="..."
-    name="logger" />
+    name="log" />
 
 <wsgi:middleware
-    factory=".apps.rootopen.RootOpener"
-    name="root_opener" />
+    factory=".apps.openroot.RootOpener"
+    name="open_root" />
 
 <wsgi:middleware
     factory=".apps.txnctl.TransactionController"
-    name="transaction_controller" />
+    name="control_transaction" />
 
 <wsgi:middleware
     factory=".apps.notify.EventNotifier"
-    name="notifier" />
+    name="event" />
 
 <wsgi:middleware
     factory="..."
-    name="error_handler" />
+    name="handle_error" />
 
+<!-- no form processing for non-browser requests -->
 <wsgi:middleware
-    factory=".apps.authenticator.Authenticator"
-    name="authenticator" />
+    factory=".apps.passthrough"
+    name="process_form"
+    for="zope.publisher.interfaces.IRequest" />
 
+<!-- process forms for browser requests -->
 <wsgi:middleware
-    factory="..."
-    name="traverser" />
+    factory=".apps.requestsetup.ProcessForm"
+    name="process_form"
+    for="zope.publisher.interfaces.browser.IBrowserRequest" />
 
 <wsgi:middleware
+    factory=".apps.authenticate.Authenticator"
+    name="authenticate" />
+
+<wsgi:middleware
+    factory=".apps.traversal.Traverser"
+    name="traverse" />
+
+<wsgi:middleware
     factory=".apps.txnctl.TransactionAnnotator"
-    name="transaction_annotator" />
+    name="annotate_transaction" />
 
 <wsgi:application
-    factory=".apps.caller.Caller"
-    name="caller" />
+    factory=".apps.mapply.Caller"
+    name="call" />
 
 </configure>
 

Modified: Sandbox/shane/republish/zope/pipeline/entry.py
===================================================================
--- Sandbox/shane/republish/zope/pipeline/entry.py	2009-02-13 01:04:24 UTC (rev 96484)
+++ Sandbox/shane/republish/zope/pipeline/entry.py	2009-02-13 05:21:32 UTC (rev 96485)
@@ -13,24 +13,40 @@
 ##############################################################################
 """The main entry point for the zope.pipeline package.
 
-Use get_pipeline() to get a WSGI application built from a Zope pipeline.
+Use get_database_pipeline() or get_pipeline() to get a WSGI
+application built from a pipeline.
 """
 
+from zope.component import getMultiAdapter
+from zope.interface import directlyProvides
+from zope.interface import providedBy
+from zope.pipeline.interfaces import IPipelineApplicationList
+from zope.pipeline.interfaces import IUndecidedRequest
+from zope.publisher import IWSGIApplication
+from zope.testing import cleanup
+
 # _pipeline_cache: {(interfaces provided by the request) -> WSGI application}
 _pipeline_cache = {}
+cleanup.addCleanUp(_pipeline_cache.clear)
 
-def get_pipeline(request=None):
+def get_database_pipeline(database, global_environ=None):
+    if global_environ is None:
+        global_environ = {}
+    global_environ['zope.database'] = database
+    return get_pipeline(global_environ=global_environ)
+
+def get_pipeline(request=None, global_environ=None):
     if request is None:
         provided = (IUndecidedRequest,)
     else:
         provided = tuple(providedBy(request))
     pipeline = _pipeline_cache.get(provided)
     if pipeline is None:
-        pipeline = make_pipeline(provided)
+        pipeline = make_pipeline(provided, global_environ)
         _pipeline_cache[provided] = pipeline
     return pipeline
 
-def make_pipeline(provided):
+def make_pipeline(provided, global_environ=None):
     marker_req = MarkerRequest(provided)
     app_list = IPipelineApplicationList(marker_req)
     names = list(app_list.names)  # make a copy
@@ -42,7 +58,15 @@
         name = names.pop()
         app = getMultiAdapter(
             (app, marker_req), IWSGIApplication, name=name)
-    return app
+    if global_environ:
+        # augment the WSGI environment with some data
+        def add_global_environ(environ, start_response):
+            environ.update(global_environ)
+            return inner_app(environ, start_response)
+        directlyProvides(add_global_environ, IWSGIApplication)
+        return add_global_environ
+    else:
+        return app
 
 class MarkerRequest(object):
     """A marker object that claims to provide a request type.

Added: Sandbox/shane/republish/zope/pipeline/interfaces.py
===================================================================
--- Sandbox/shane/republish/zope/pipeline/interfaces.py	                        (rev 0)
+++ Sandbox/shane/republish/zope/pipeline/interfaces.py	2009-02-13 05:21:32 UTC (rev 96485)
@@ -0,0 +1,61 @@
+##############################################################################
+#
+# Copyright (c) 2009 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.
+#
+##############################################################################
+"""Interfaces specific to zope.pipeline.
+
+$Id: metadirectives.py 96177 2009-02-06 07:50:13Z shane $
+"""
+
+from zope.interface import Attribute
+from zope.interface import Interface
+
+class IUndecidedRequest(Interface):
+    """Indicates that no request has been created yet.
+
+    Use this interface to register WSGI applications in the
+    pipeline that executes before the request creation step.
+    """
+
+class IPipelineApplicationList(Interface):
+    """Container of a list of pipeline application names.
+
+    The wsgi:pipeline directive creates an object that
+    provides this interface and registers it as an adapter.
+    """
+    names = Attribute("Application names to use in a pipeline")
+
+class IRequestFactoryRegistry(Interface):
+    """A registry of request factories.
+
+    Chooses factories based on the wsgi.url_scheme, the
+    REQUEST_METHOD, and the CONTENT_TYPE.  Multiple factories
+    can be configured schema, method, and content type.
+    The factory itself can introspect the environment to decide
+    if it can handle the request as given by the environment or not.
+    Factories are sorted in descending order of priority, so a
+    factory with priority 10 will be used before a factory with
+    priority 5.
+    """
+
+    def register(scheme, method, mimetype, name, priority, factory):
+        """Registers a factory for scheme + method + mimetype."""
+
+    def get_factories_for(scheme, method, mimetype):
+        """Return the internal datastructure representing the configured
+        factories (basically for testing, not for introspection).
+        """
+
+    def lookup(method, mimetype, environment):
+        """Lookup a factory for a given method+mimetype and a
+        environment.
+        """

Modified: Sandbox/shane/republish/zope/pipeline/zcml.py
===================================================================
--- Sandbox/shane/republish/zope/pipeline/zcml.py	2009-02-13 01:04:24 UTC (rev 96484)
+++ Sandbox/shane/republish/zope/pipeline/zcml.py	2009-02-13 05:21:32 UTC (rev 96485)
@@ -30,15 +30,17 @@
 from zope.schema import Int
 from zope.schema import TextLine
 
+from zope.pipeline.interfaces import IPipelineApplicationList
 from zope.pipeline.apps.requestsetup import factoryRegistry
 
 
 class IPipelineDirective(Interface):
     """Declare a list of application names in a WSGI pipeline"""
 
-    for_ = GlobalObject(
-        title=u'Request type',
-        description=u'The type of request that should use this app list',
+    for_ = Tokens(
+        title=u'Request types',
+        description=u'The request types that should use this pipeline',
+        value_type=GlobalObject(),
         required=True)
 
     names = Tokens(
@@ -54,7 +56,8 @@
 
     factory = GlobalObject(
         title=u"Application factory",
-        description=u"A factory that creates the WSGI application.",
+        description=(u"A factory that creates the WSGI application.  "
+                     u"The factory will be called with no parameters."),
         required=True,
         )
 
@@ -64,23 +67,24 @@
         required=True,
         )
 
-    for_ = GlobalObject(
-        title=u"Request type",
-        description=u"The request type that triggers use of this application",
-        required=False,
-        )
+    for_ = Tokens(
+        title=u'Request types',
+        description=u'The request types that should use this application',
+        value_type=GlobalObject(),
+        required=False)
 
 
 class IMiddlewareDirective(IApplicationDirective):
     """Declare a middleware WSGI application for use in a pipeline"""
-    # same schema as IApplicationDirective
-    pass
+    factory = GlobalObject(
+        title=u"Application factory",
+        description=(u"A factory that creates the WSGI application.  "
+                     u"The factory will be called with one parameter: "
+                     u"the next application in the pipeline."),
+        required=True,
+        )
 
 
-class IPipelineApplicationList(Interface):
-    names = Attribute("Application names to use in a pipeline")
-
-
 class PipelineApplicationList(object):
     implements(IPipelineApplicationList)
 
@@ -96,12 +100,12 @@
     """Register a pipeline application list"""
     obj = PipelineApplicationList(names)
     adapter(_context, factory=obj.adapt,
-        provides=[IPipelineApplicationList], for_=[for_])
+        provides=[IPipelineApplicationList], for_=for_)
 
-def application(_context, factory, name, for_=None):
+def application(_context, factory, name, for_=()):
     """Register a simple WSGI app for use at the end of pipeline"""
-    if for_ is None:
-        for_ = getattr(factory, 'request_type', IRequest)
+    if not for_:
+        for_ = [getattr(factory, 'request_type', IRequest)]
 
     def app_factory(marker_request):
         res = factory()
@@ -110,12 +114,13 @@
         return res
 
     adapter(_context, factory=[app_factory], provides=[IWSGIApplication],
-        for_=[for_], name=name)
+        for_=for_, name=name)
 
-def middleware(_context, factory, name, for_=None):
+def middleware(_context, factory, name, for_=()):
     """Register a middleware WSGI app for use in a pipeline"""
-    if for_ is None:
-        for_ = getattr(factory, 'request_type', IRequest)
+    if not for_:
+        for_ = [getattr(factory, 'request_type', IRequest)]
+    for_ = [IWSGIApplication] + list(for_)
 
     def app_factory(app, marker_request):
         res = factory(app)
@@ -124,7 +129,7 @@
         return res
 
     adapter(_context, factory=[app_factory], provides=[IWSGIApplication],
-        for_=[IWSGIApplication, for_], name=name)
+        for_=for_, name=name)
 
 
 class IRequestFactoryDirective(Interface):
@@ -139,8 +144,8 @@
         description=(u'The request factory, which is a callable '
                      u'that accepts one parameter, the WSGI environment, '
                      u'and returns a request object. '
-                     u'The factory can return None to defer to the '
-                     u'next registered factory.'),
+                     u'The factory can return None if it decides it can '
+                     u'not handle the given environment.'),
         required=True)
 
     schemes = Tokens(
@@ -167,8 +172,9 @@
 
     priority = Int(
         title=u'Priority',
-        description=(u'A priority key used to decide between coexistent'
-                     ' request factories.'),
+        description=(u'A priority number used to decide between coexistent '
+                     u'request factories.  A higher priority number '
+                     u'is chosen before a lower priority number.'),
         required=False)
 
 def request_factory(_context, name, factory,



More information about the Checkins mailing list