[Checkins] SVN: Sandbox/shane/republish/zope/pipeline/ Sketched the wsgi:* directives.

Shane Hathaway shane at hathawaymix.org
Wed Feb 11 13:01:31 EST 2009


Log message for revision 96450:
  Sketched the wsgi:* directives.
  

Changed:
  U   Sandbox/shane/republish/zope/pipeline/caller.py
  U   Sandbox/shane/republish/zope/pipeline/configure.zcml
  D   Sandbox/shane/republish/zope/pipeline/main.py
  A   Sandbox/shane/republish/zope/pipeline/meta.zcml
  U   Sandbox/shane/republish/zope/pipeline/txnctl.py
  A   Sandbox/shane/republish/zope/pipeline/zcml.py

-=-
Modified: Sandbox/shane/republish/zope/pipeline/caller.py
===================================================================
--- Sandbox/shane/republish/zope/pipeline/caller.py	2009-02-11 15:14:48 UTC (rev 96449)
+++ Sandbox/shane/republish/zope/pipeline/caller.py	2009-02-11 18:01:30 UTC (rev 96450)
@@ -2,7 +2,6 @@
 from zope.interface import implements
 from zope.proxy import removeAllProxies
 from zope.publisher.interfaces import IWSGIApplication
-from zope.publisher.interfaces import IRequest
 
 
 class Caller(object):
@@ -12,11 +11,7 @@
     The 'traversed' attribute of the request must be set.
     """
     implements(IWSGIApplication)
-    adapts(IRequest)
 
-    def __init__(self, marker_request=None):
-        pass
-
     def __call__(self, environ, start_response):
         request = environ['zope.request']
         name, ob = request.traversed[-1]

Modified: Sandbox/shane/republish/zope/pipeline/configure.zcml
===================================================================
--- Sandbox/shane/republish/zope/pipeline/configure.zcml	2009-02-11 15:14:48 UTC (rev 96449)
+++ Sandbox/shane/republish/zope/pipeline/configure.zcml	2009-02-11 18:01:30 UTC (rev 96450)
@@ -3,13 +3,13 @@
 <!-- a wsgi:stage-list directive registers a bound StageList.adapt() method
      as an unnamed adapter from the request type to IStageList. -->
 
-<wsgi:stage-list require=".interfaces.IUndecidedRequest" names="
+<wsgi:app-list for=".interfaces.IUndecidedRequest" names="
     retry
     request_factory
-    select_pipeline
+    pipeline_pivot
     " />
 
-<wsgi:stage-list require="zope.publisher.interfaces.IRequest" names="
+<wsgi:app-list for="zope.publisher.interfaces.IRequest" names="
     logger
     root_opener
     transaction_controller
@@ -25,14 +25,15 @@
      an adapter from the request type to IWSGIApplication with name
      "pipeline". -->
 
-<wsgi:pipeline require=".interfaces.IUndecidedRequest" />
-<wsgi:pipeline require="zope.publisher.interfaces.IRequest" />
-<wsgi:pipeline require="zope.publisher.interfaces.http.IHTTPRequest" />
-<wsgi:pipeline require="zope.publisher.interfaces.browser.IBrowserRequest" />
+<wsgi:pipeline for=".interfaces.IUndecidedRequest" />
+<wsgi:pipeline for="zope.publisher.interfaces.IRequest" />
+<wsgi:pipeline for="zope.publisher.interfaces.http.IHTTPRequest" />
+<wsgi:pipeline for="zope.publisher.interfaces.browser.IBrowserRequest" />
 
-<!-- a wsgi:middleware directive is just like an adapter directive,
-     except that the adapter is always registered as requiring
-     two parameters, 'app' and 'request'; the factory may be wrapped
+<!-- a wsgi:middleware directive is like an adapter directive,
+     except that the adapter is registered as requiring
+     two parameters, 'app' and 'request', while only the app is
+     provided to the application factory; the factory is wrapped
      to make that happen.  If neither the directive nor the factory
      says what kind of request is required, assume IRequest. -->
 
@@ -40,58 +41,58 @@
     factory=".retry.Retry"
     name="retry" />
 
-<!-- a wsgi:app directive is just like an adapter directive,
-     except that the adapter is always registered as requiring
-     one parameter, 'request'; the factory may be wrapped
+<!-- a wsgi:application directive is like an adapter directive,
+     except that the adapter is registered as requiring
+     one parameter, 'request', while no parameters are passed to the
+     application factory; the factory is wrapped
      to make that happen.  If neither the directive nor the factory
      says what kind of request is required, assume IRequest. -->
 
-<wsgi:app
+<wsgi:application
     factory=".caller.Caller"
     name="caller" />
 
-
-<adapter
+<wsgi:middleware
     factory=".retry.Retry"
     name="retry" />
 
-<adapter
+<wsgi:middleware
     factory="..."
     name="request_factory" />
 
-<adapter
+<wsgi:application
     factory="..."
-    name="select_pipeline" />
+    name="pipeline_pivot" />
 
-<adapter
+<wsgi:middleware
     factory="..."
     name="logger" />
 
-<adapter
+<wsgi:middleware
     factory=".rootopen.RootOpener"
     name="root_opener" />
 
-<adapter
+<wsgi:middleware
     factory=".txnctl.TransactionController"
     name="transaction_controller" />
 
-<adapter
+<wsgi:middleware
     factory=".event.EventNotifier"
     name="notifier" />
 
-<adapter
+<wsgi:middleware
     factory="..."
     name="error_handler" />
 
-<adapter
+<wsgi:middleware
     factory=".authenticator.Authenticator"
     name="authenticator" />
 
-<adapter
+<wsgi:middleware
     factory="..."
     name="traverser" />
 
-<adapter
+<wsgi:middleware
     factory=".txnctl.TransactionAnnotator"
     name="transaction_annotator" />
 

Deleted: Sandbox/shane/republish/zope/pipeline/main.py
===================================================================
--- Sandbox/shane/republish/zope/pipeline/main.py	2009-02-11 15:14:48 UTC (rev 96449)
+++ Sandbox/shane/republish/zope/pipeline/main.py	2009-02-11 18:01:30 UTC (rev 96450)
@@ -1,52 +0,0 @@
-
-
-class StageList(object):
-    implements(IStageList)
-
-    def __init__(self, names):
-        self.names = names
-
-    def adapt(self, request):
-        """Called by adapter lookup"""
-        return self
-
-
-class MarkerRequest(object):
-    """A marker object that claims to provide a request type.
-
-    This is used for adapter lookup.
-    """
-
-    __slots__ = ('__provides__',)
-
-    def __init__(self, request_type):
-        request_type.directlyProvidedBy(self)
-
-
-class Pipeline(object):
-    implements(IWSGIApplication)
-
-    def __init__(self, request_type):
-        self.app = None
-        self.request_type = request_type
-
-    def adapt(self, request):
-        """Called by adapter lookup"""
-        app = self.app
-        if app is None:
-            self.app = app = self.make_app()
-        return app
-
-    def make_app(self):
-        marker_req = MarkerRequest(self.request_type)
-        stage_list = IStageList(marker_req)
-        names = list(stage_list.names)  # make a copy
-        # The last name in the list is an application.
-        name = names.pop()
-        app = IWSGIApplication(marker_req, name=name)
-        while names:
-            # The rest of the names are middleware.
-            name = names.pop()
-            app = getMultiAdapter(
-                (app, marker_req), IWSGIApplication, name=name)
-        return app

Added: Sandbox/shane/republish/zope/pipeline/meta.zcml
===================================================================
--- Sandbox/shane/republish/zope/pipeline/meta.zcml	                        (rev 0)
+++ Sandbox/shane/republish/zope/pipeline/meta.zcml	2009-02-11 18:01:30 UTC (rev 96450)
@@ -0,0 +1,31 @@
+<configure xmlns:meta="http://namespaces.zope.org/meta">
+
+<meta:directive
+    namespace="http://namespaces.zope.org/wsgi"
+    name="application-list"
+    schema=".zcml.IApplicationListDirective"
+    handler=".zcml.application_list"
+    />
+
+<meta:directive
+    namespace="http://namespaces.zope.org/wsgi"
+    name="pipeline"
+    schema=".zcml.IPipelineDirective"
+    handler=".zcml.pipeline"
+    />
+
+<meta:directive
+    namespace="http://namespaces.zope.org/wsgi"
+    name="application"
+    schema=".zcml.IApplicationDirective"
+    handler=".zcml.application"
+    />
+
+<meta:directive
+    namespace="http://namespaces.zope.org/wsgi"
+    name="middleware"
+    schema=".zcml.IMiddlewareDirective"
+    handler=".zcml.middleware"
+    />
+
+</configure>

Modified: Sandbox/shane/republish/zope/pipeline/txnctl.py
===================================================================
--- Sandbox/shane/republish/zope/pipeline/txnctl.py	2009-02-11 15:14:48 UTC (rev 96449)
+++ Sandbox/shane/republish/zope/pipeline/txnctl.py	2009-02-11 18:01:30 UTC (rev 96450)
@@ -87,6 +87,6 @@
         for iface in providedBy(request):
             if iface.extends(IRequest):
                 break
-        iface_dotted = iface.__module__ + '.' + iface.getName()
+        iface_dotted = '%s.%s' % (iface.__module__, iface.getName())
         txn.setExtendedInfo('request_type', iface_dotted)
         return txn

Added: Sandbox/shane/republish/zope/pipeline/zcml.py
===================================================================
--- Sandbox/shane/republish/zope/pipeline/zcml.py	                        (rev 0)
+++ Sandbox/shane/republish/zope/pipeline/zcml.py	2009-02-11 18:01:30 UTC (rev 96450)
@@ -0,0 +1,171 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Schema and implementation of WSGI pipeline directives
+
+$Id: metadirectives.py 96177 2009-02-06 07:50:13Z shane $
+"""
+__docformat__ = 'restructuredtext'
+
+from zope.component import getMultiAdapter
+from zope.component.zcml import adapter
+from zope.configuration.fields import GlobalObject
+from zope.configuration.fields import Tokens
+from zope.interface import alsoProvides
+from zope.interface import Attribute
+from zope.interface import directlyProvides
+from zope.interface import Interface
+from zope.schema import TextLine
+
+from zope.publisher.interfaces import IWSGIApplication
+from zope.publisher.interfaces import IRequest
+
+class IApplicationListDirective(Interface):
+    """Declare a list of application names in a WSGI pipeline"""
+
+    for_ = GlobalObject(
+        title=_('Request type'),
+        description=_('The type of request that should use this app list'),
+        required=True)
+
+    names = Tokens(
+        title=_('Application names'),
+        description=_('The list of WSGI application names to use.  '
+            'The last name in the list declares a simple application; '
+            'the rest declare a middleware application.'),
+        required=True)
+
+class IPipelineDirective(Interface):
+    """Declare a WSGI pipeline"""
+
+    for_ = GlobalObject(
+        title=_('Request type'),
+        description=_('The type of request that should use this pipeline'),
+        required=True)
+
+class IApplicationDirective(Interface):
+    """Declare a simple WSGI application for use at the end of a pipeline"""
+
+    factory = GlobalObject(
+        title=_("Application factory"),
+        description=_("A factory that creates the WSGI application."),
+        required=True,
+        )
+
+    name = TextLine(
+        title=_("Name"),
+        description=_("The name of the application"),
+        required=True,
+        )
+
+    for_ = GlobalObject(
+        title=_("Request type"),
+        description=_("The type of request this application expects"),
+        required=False,
+        )
+
+class IMiddlewareDirective(IApplicationDirective):
+    """Declare a middleware WSGI application for use in a pipeline"""
+    # same schema as IApplicationDirective
+    pass
+
+class IApplicationList(Interface):
+    names = Attribute("Application names to use in a pipeline")
+
+class ApplicationList(object):
+    implements(IApplicationList)
+
+    def __init__(self, names):
+        self.names = names
+
+    def adapt(self, request):
+        """Called by adapter lookup"""
+        return self
+
+class MarkerRequest(object):
+    """A marker object that claims to provide a request type.
+
+    This is used for adapter lookup.
+    """
+    __slots__ = ('__provides__',)
+
+    def __init__(self, request_type):
+        directlyProvides(self, request_type)
+
+class Pipeline(object):
+    implements(IWSGIApplication)
+
+    def __init__(self, request_type):
+        self.app = None
+        self.request_type = request_type
+
+    def adapt(self, request):
+        """Called by adapter lookup"""
+        app = self.app
+        if app is None:
+            # cache the pipeline for future use
+            self.app = app = self.make_app()
+        return app
+
+    def make_app(self):
+        marker_req = MarkerRequest(self.request_type)
+        app_list = IApplicationList(marker_req)
+        names = list(app_list.names)  # make a copy
+        # The last name in the list is an application.
+        name = names.pop()
+        app = IWSGIApplication(marker_req, name=name)
+        while names:
+            # The rest of the names are middleware.
+            name = names.pop()
+            app = getMultiAdapter(
+                (app, marker_req), IWSGIApplication, name=name)
+        return app
+
+def application_list(_context, for_, names):
+    """Register an application list"""
+    obj = ApplicationList(names)
+    adapter(_context, factory=obj.adapt, provides=[IAppList], for_=[for_])
+
+def pipeline(_context, for_):
+    """Register a pipeline"""
+    obj = Pipeline(for_)
+    adapter(_context, factory=obj.adapt, provides=[IWSGIApplication],
+        for_=[for_], name='pipeline')
+
+def application(_context, factory, name, for_=None):
+    """Register a simple WSGI app for use at the end of pipeline"""
+    if for_ is None:
+        for_ = getattr(factory, 'request_type', IRequest)
+
+    def app_factory(marker_request):
+        res = factory()
+        if not IWSGIApplication.providedBy(res):
+            alsoProvides(res, IWSGIApplication)
+        return res
+
+    adapter(_context, factory=[app_factory], provides=[IWSGIApplication],
+        for_=[for_], name=name)
+
+def middleware(_context, factory, name, for_=None):
+    """Register a middleware WSGI app for use in a pipeline"""
+    if for_ is None:
+        for_ = getattr(factory, 'request_type', IRequest)
+
+    def app_factory(app, marker_request):
+        res = factory(app)
+        if not IWSGIApplication.providedBy(res):
+            alsoProvides(res, IWSGIApplication)
+        return res
+
+    adapter(_context, factory=[app_factory], provides=[IWSGIApplication],
+        for_=[IWSGIApplication, for_], name=name)



More information about the Checkins mailing list