[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