[Checkins] SVN: Sandbox/shane/republish/zope.p Added more meat to traversal and mapply. Some of the interesting

Shane Hathaway shane at hathawaymix.org
Sun Feb 22 05:54:14 EST 2009


Log message for revision 97011:
  Added more meat to traversal and mapply.  Some of the interesting
  pipeline variations are now visible.
  

Changed:
  U   Sandbox/shane/republish/zope.pipeline/setup.py
  U   Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/apps/fixrel.py
  U   Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/apps/mapply.py
  U   Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/apps/tests/requestsetup.txt
  U   Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/apps/traversal.py
  U   Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/configure.zcml
  U   Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/envkeys.py
  U   Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/request.py
  A   Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/response.py
  U   Sandbox/shane/republish/zope.publisher/src/zope/publisher/browser.py
  U   Sandbox/shane/republish/zope.publisher/src/zope/publisher/interfaces/base.py
  U   Sandbox/shane/republish/zope.publisher/src/zope/publisher/interfaces/http.py

-=-
Modified: Sandbox/shane/republish/zope.pipeline/setup.py
===================================================================
--- Sandbox/shane/republish/zope.pipeline/setup.py	2009-02-22 09:35:24 UTC (rev 97010)
+++ Sandbox/shane/republish/zope.pipeline/setup.py	2009-02-22 10:54:13 UTC (rev 97011)
@@ -49,6 +49,7 @@
         'zope.i18n',
         'zope.interface',
         'zope.publisher',
+        'zope.traversing', # for namespace traversal
         'zope.security',
         ],
     extras_require=dict(

Modified: Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/apps/fixrel.py
===================================================================
--- Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/apps/fixrel.py	2009-02-22 09:35:24 UTC (rev 97010)
+++ Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/apps/fixrel.py	2009-02-22 10:54:13 UTC (rev 97011)
@@ -13,7 +13,7 @@
 ##############################################################################
 
 from zope.interface import implements
-from zope.pipeline.envkeys import IMPLICIT_TRAVERSAL_STEPS_KEY
+from zope.pipeline.envkeys import DEFAULT_TRAVERSAL_STEPS_KEY
 from zope.pipeline.envkeys import REQUEST_KEY
 from zope.pipeline.envkeys import STRING_RESULT_HOOKS_KEY
 from zope.publisher.interfaces import IWSGIApplication
@@ -47,8 +47,6 @@
             need_fix = True
 
         else:
-            actual_steps = environ[IMPLICIT_TRAVERSAL_STEPS_KEY]
-
             # If the URL ends with a slash, the URL specified one
             # default traversal step, otherwise the URL specified zero.
             if environ['PATH_INFO'].endswith('/'):
@@ -60,6 +58,7 @@
             # by the URL with the number of default traversal steps
             # actually performed. Set need_fix to True if the specified
             # number does not match the actual.
+            actual_steps = environ[DEFAULT_TRAVERSAL_STEPS_KEY]
             if actual_steps != specified_steps:
                 need_fix = True
                 allow_redirect = (

Modified: Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/apps/mapply.py
===================================================================
--- Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/apps/mapply.py	2009-02-22 09:35:24 UTC (rev 97010)
+++ Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/apps/mapply.py	2009-02-22 10:54:13 UTC (rev 97011)
@@ -14,6 +14,7 @@
 
 from zope.interface import implements
 from zope.proxy import removeAllProxies
+from zope.publisher.interfaces.http import MethodNotAllowed
 from zope.publisher.interfaces import IWSGIApplication
 
 from zope.pipeline.envkeys import REQUEST_KEY
@@ -28,11 +29,16 @@
     """
     implements(IWSGIApplication)
 
+    def get_target(self, environ):
+        """Returns the object to call."""
+        traversed = environ[TRAVERSED_KEY]
+        name, ob = traversed[-1]
+        return ob
+
     def __call__(self, environ, start_response):
-        traversed = environ[TRAVERSED_KEY]
+        ob = self.get_target(environ)
         request = environ[REQUEST_KEY]
         positional = request.getPositionalArguments()
-        name, ob = traversed[-1]
         result = mapply(ob, positional, request)
         response = request.response
         if result is not response:
@@ -44,6 +50,54 @@
         return '%s()' % self.__class__.__name__
 
 
+class HTTPCaller(Caller):
+    """Caller for HTTP: Returns an empty body for HEAD requests.
+
+    Other request methods 
+    """
+    implements(IWSGIApplication)
+
+    def __call__(self, environ, start_response):
+        res = super(HTTPCaller, self)(environ, start_response)
+        if request.method == 'HEAD':
+            # Send the headers, but discard the body.
+            # Note that a HEAD request can have a nonzero Content-Length
+            # header, while the body has zero length.  This seems to follow
+            # the HTTP spec.
+            if hasattr(res, 'close'):
+                res.close()
+            res = ('',)
+        return res
+
+
+class HTTPRequestMethodCaller(HTTPCaller):
+    """Caller for HTTP: calls the view and method specified by REQUEST_METHOD.
+
+    This is normally used for non-browser requests such as PUT, DELETE, etc.
+    """
+
+    def get_target(self, environ):
+        """Returns the object to call."""
+        orig = super(HTTPRequestMethodCaller, self).get_target(environ)
+
+        # The commented code below matches the behavior of
+        # zope.app.publication, but that behavior is strange and
+        # undocumented.  If anyone needs this code, please explain
+        # why.
+
+        #if IHTTPException.providedBy(orig):
+        #    return orig
+
+        request = environ[REQUEST_KEY]
+        # Get the view named by the request method
+        ob = queryMultiAdapter((orig, request), name=request.method)
+        # Get the method of that view with the same name
+        ob = getattr(ob, request.method, None)
+        if ob is None:
+            raise MethodNotAllowed(orig, request)
+        return ob
+
+
 _marker = object()  # Create a new marker object.
 
 def unwrapMethod(obj):

Modified: Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/apps/tests/requestsetup.txt
===================================================================
--- Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/apps/tests/requestsetup.txt	2009-02-22 09:35:24 UTC (rev 97010)
+++ Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/apps/tests/requestsetup.txt	2009-02-22 10:54:13 UTC (rev 97011)
@@ -3,8 +3,7 @@
 ----------------
 
 The ``CreateRequest`` application puts a Zope-style request object in the
-WSGI environment.  Zope-style request objects are mainly used for
-object traversal.
+WSGI environment.
 
 Create an app that prints the contents of the created request.
 

Modified: Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/apps/traversal.py
===================================================================
--- Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/apps/traversal.py	2009-02-22 09:35:24 UTC (rev 97010)
+++ Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/apps/traversal.py	2009-02-22 10:54:13 UTC (rev 97011)
@@ -12,39 +12,76 @@
 #
 ##############################################################################
 
+from zope.component import queryMultiAdapter
 from zope.interface import implements
+from zope.publisher.interfaces.browser import IBrowserPublisher
+from zope.publisher.interfaces.exceptions import NotFound
+from zope.publisher.interfaces import IPublishTraverse
 from zope.publisher.interfaces import IWSGIApplication
+from zope.security.checker import ProxyFactory
+from zope.traversing.namespace import namespaceLookup
+from zope.traversing.namespace import nsParse
 
+from zope.pipeline.envkeys import DEFAULT_TRAVERSAL_STEPS_KEY
+from zope.pipeline.envkeys import REQUEST_KEY
 from zope.pipeline.envkeys import TRAVERSAL_HOOKS_KEY
 from zope.pipeline.envkeys import TRAVERSED_KEY
 
 
 class Traverser(object):
-    """Traverses the object graph based on the traversal stack.
+    """WSGI app that traverses the path specified by PATH_INFO.
 
-    Requires 'zope.pipeline.traversed' in the WSGI environment. Calls
-    the hooks listed in 'zope.pipeline.traversal_hooks', if there are
-    any.
+    Requires 'zope.pipeline.request' and 'zope.pipeline.traversed' in
+    the WSGI environment. Calls the hooks listed in
+    'zope.pipeline.traversal_hooks', if there are any. Appends to
+    'zope.pipeline.traversed' and sets
+    'zope.pipeline.default_traversal_steps'.
     """
     implements(IWSGIApplication)
 
     def __init__(self, next_app):
         self.next_app = next_app
+        self.proxy_factory = ProxyFactory
 
     def __call__(self, environ, start_response):
         self.traverse(environ)
         return self.next_app(environ, start_response)
 
-    def get_stack(self, environ):
-        pass
+    def get_steps(self, environ):
+        """Return the list of names to traverse.
 
+        The list of names to traverse comes from environ['PATH_INFO'].
+        """
+        path = environ.get("PATH_INFO", "/")
+        steps = []
+        for item in path.split('/'):
+            if not item or item == '.':
+                continue
+            elif item == '..':
+                try:
+                    del steps[-1]
+                except IndexError:
+                    raise NotFound('..')
+            else:
+                steps.append(item)
+        return steps
+
+
     def traverse(self, environ):
-        stack = self.get_stack(environ)
+        """Traverse the object graph by following URL path segments.
+
+        Updates the traversal variables in the WSGI environment at each step.
+        """
+        stack = self.get_steps(environ)
+        stack.reverse()
+        request = environ[REQUEST_KEY]
         traversed = environ[TRAVERSED_KEY]
         hooks = environ.get(TRAVERSAL_HOOKS_KEY, ())
+        environ[DEFAULT_TRAVERSAL_STEPS_KEY] = 0
 
         root_name, obj = traversed[-1]
         prev_object = None
+        default_traversal = False
 
         while True:
             if obj is not prev_object:
@@ -54,9 +91,14 @@
                 prev_object = obj
 
             if not stack:
-                obj, stack = self.add_steps(environ)
-                if stack:
-                    # call traversal hooks and traverse some more
+                next_obj, add_steps = self.get_default_traversal(request, obj)
+                if add_steps:
+                    stack = list(add_steps)
+                    stack.reverse()
+                    # Now traverse through default traversal steps.
+                    # Call traversal hooks and traverse some more.
+                    default_traversal = True
+                    obj = next_obj
                     continue
                 else:
                     # done traversing
@@ -64,22 +106,87 @@
 
             # Traverse the next step.
             name = stack.pop()
-            obj = self.traverse_name(obj, name)
+            obj = self.traverse_name(request, obj, name)
             traversed.append((name, obj))
+            if default_traversal:
+                environ[DEFAULT_TRAVERSAL_STEPS_KEY] += 1
 
-    def traverse_name(self, obj, name):
-        pass
 
-    def add_steps(self, environ):
-        pass
+    def traverse_name(self, request, ob, name):
+        nm = name # the name to look up the object with
 
+        if name and name[:1] in '@+':
+            # Process URI segment parameters.
+            ns, nm = nsParse(name)
+            if ns:
+                try:
+                    ob2 = namespaceLookup(ns, nm, ob, request)
+                except TraversalError:
+                    raise NotFound(ob, name)
 
-class HTTPTraverser(Traverser):
-    # includes form_action (or should this be in BrowserTraverser?)
-    implements(IWSGIApplication)
+                return self.proxy_factory(ob2)
 
+        if nm == '.':
+            return ob
 
-class BrowserTraverser(HTTPTraverser):
-    # includes browserDefault traversal
+        if IPublishTraverse.providedBy(ob):
+            ob2 = ob.publishTraverse(request, nm)
+        else:
+            # self is marker
+            adapter = queryMultiAdapter((ob, request), IPublishTraverse,
+                                        default=self)
+            if adapter is not self:
+                ob2 = adapter.publishTraverse(request, nm)
+            else:
+                raise NotFound(ob, name, request)
+
+        return self.proxy_factory(ob2)
+
+
+    def get_default_traversal(self, request, ob):
+        """Get the default traversal steps for an object.
+
+        Returns (next_object, steps).  
+        """
+        return ob, None
+
+
+class BrowserTraverser(Traverser):
+    # includes form_action and browserDefault traversal
     implements(IWSGIApplication)
 
+    def get_steps(self, environ):
+        """Return the list of names to traverse.
+
+        This implementation calls super.get_steps(), then if a form
+        action was provided, the action is appended to the steps.
+        """
+        steps = super(BrowserTraverser, self).get_steps(environ)
+        request = environ[REQUEST_KEY]
+        if request.form_action:
+            steps.append(request.form_action)
+        return steps
+
+    def get_default_traversal(self, request, ob):
+        """Get the default traversal steps for an object.
+
+        Returns (next_object, steps).
+        """
+        if request.form_action:
+            # Do not follow default traversal when a form action was
+            # provided.
+            return ob, None
+
+        if IBrowserPublisher.providedBy(ob):
+            # ob is already proxied, so the result of calling a method
+            # will be too.
+            return ob.browserDefault(request)
+
+        adapter = queryMultiAdapter((ob, request), IBrowserPublisher)
+        if adapter is not None:
+            ob, path = adapter.browserDefault(request)
+            ob = self.proxy_factory(ob)
+            return ob, path
+
+        # ob is already proxied
+        return ob, None

Modified: Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/configure.zcml
===================================================================
--- Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/configure.zcml	2009-02-22 09:35:24 UTC (rev 97010)
+++ Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/configure.zcml	2009-02-22 10:54:13 UTC (rev 97011)
@@ -91,18 +91,40 @@
     name="authenticate"
     factory=".apps.authenticate.Authenticator" /-->
 
+<!-- Normal traversal for non-browser requests -->
 <wsgi:application
     name="traverse"
     factory=".apps.traversal.Traverser" />
 
+<!-- Extra traversal for browser requests -->
 <wsgi:application
+    name="traverse"
+    factory=".apps.traversal.BrowserTraverser"
+    for="zope.publisher.interfaces.browser.IBrowserRequest" />
+
+<wsgi:application
     name="annotate_transaction"
     factory=".apps.txnctl.TransactionAnnotator" />
 
+<!-- Just use mapply for non-HTTP requests -->
 <wsgi:application
     name="call"
     factory=".apps.mapply.Caller" />
 
+<!-- For browser requests, treat the HEAD method specially -->
+<wsgi:application
+    name="call"
+    factory=".apps.mapply.HTTPCaller"
+    for="zope.publisher.interfaces.browser.IBrowserRequest"
+    />
+
+<!-- For non-browser HTTP requests, look up method-specific views -->
+<wsgi:application
+    name="call"
+    factory=".apps.mapply.HTTPRequestMethodCaller"
+    for="zope.publisher.interfaces.http.IHTTPRequest"
+    />
+
 </configure>
 
 

Modified: Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/envkeys.py
===================================================================
--- Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/envkeys.py	2009-02-22 09:35:24 UTC (rev 97010)
+++ Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/envkeys.py	2009-02-22 10:54:13 UTC (rev 97011)
@@ -46,9 +46,9 @@
     first element of this list. Used by at least the `traverse` and
     `call` applications.
 
-'zope.pipeline.implicit_traversal_steps'
-    Number of steps that were traversed implicitly. Implicit traversal
-    adds automatic traversal steps to the end of the path; this is
+'zope.pipeline.default_traversal_steps'
+    Number of steps that were traversed implicitly. Default traversal
+    adds implicit traversal steps to the end of the path; this is
     primarily used for default views of folders. Created by the
     `traverse` application and used by the `fix_relative_links`
     application.
@@ -72,7 +72,7 @@
 REQUEST_KEY = "zope.pipeline.request"
 TRAVERSAL_HOOKS_KEY = "zope.pipeline.traversal_hooks"
 TRAVERSED_KEY = "zope.pipeline.traversed"
-IMPLICIT_TRAVERSAL_STEPS_KEY = "zope.pipeline.implicit_traversal_steps"
+DEFAULT_TRAVERSAL_STEPS_KEY = "zope.pipeline.default_traversal_steps"
 STRING_RESULT_HOOKS_KEY = "zope.pipeline.string_result_hooks"
 
 RESETTABLE_KEYS = [

Modified: Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/request.py
===================================================================
--- Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/request.py	2009-02-22 09:35:24 UTC (rev 97010)
+++ Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/request.py	2009-02-22 10:54:13 UTC (rev 97011)
@@ -48,10 +48,6 @@
         '__provides__',      # Allow request to directly provide interfaces
         'environment',       # The request environment (CGI. WSGI, or similar)
         'bodyStream',        # body input stream
-        'traversal_stack',   # Names to be traversed, in reverse order
-        'traversal_hooks',   # list of functions to call during traversal
-        'traversed',         # list of (name, obj) that have been traversed
-        'traversed_default', # number of steps added by default traversal
         'principal',         # authorized principal
         'debug',             # debug flags
         'interaction',       # interaction, set by interaction
@@ -65,10 +61,6 @@
     def __init__(self, environ):
         self.environment = environ
         self.bodyStream = environ.get('wsgi.input')
-        self.traversal_stack = []
-        self.traversal_hooks = []
-        self.traversed = []
-        self.traversed_default = 0
         self.principal = None
         self.debug = DebugFlags()
         self.interaction = None

Added: Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/response.py
===================================================================
--- Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/response.py	                        (rev 0)
+++ Sandbox/shane/republish/zope.pipeline/src/zope/pipeline/response.py	2009-02-22 10:54:13 UTC (rev 97011)
@@ -0,0 +1,46 @@
+##############################################################################
+#
+# 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 queryMultiAdapter
+from zope.publisher.interfaces import IResult
+
+from zope.pipeline.envkeys import STRING_RESULT_HOOKS_KEY
+
+class Response:
+
+    def setResult(self, result):
+        if IResult.providedBy(result):
+            r = result
+        else:
+            r = queryMultiAdapter((result, self._request), IResult)
+            if r is None:
+                if isinstance(result, basestring):
+                    r = result
+                elif result is None:
+                    r = ''
+                else:
+                    raise TypeError(
+                        'The result should be None, a string, or adaptable to '
+                        'IResult.')
+            if isinstance(r, basestring):
+                environ = self._request.environment
+                hooks = environ.get(STRING_RESULT_HOOKS_KEY)
+                if hooks:
+                    for hook in hooks:
+                        r = hook(r, environ)
+                r = (r,)
+
+        self._result = r
+        if not self._status_set:
+            self.setStatus('Ok')

Modified: Sandbox/shane/republish/zope.publisher/src/zope/publisher/browser.py
===================================================================
--- Sandbox/shane/republish/zope.publisher/src/zope/publisher/browser.py	2009-02-22 09:35:24 UTC (rev 97010)
+++ Sandbox/shane/republish/zope.publisher/src/zope/publisher/browser.py	2009-02-22 10:54:13 UTC (rev 97011)
@@ -60,3 +60,6 @@
     def __call__(self, *args, **kw):
         raise NotImplementedError("Subclasses should override __call__ to "
                                   "provide a response body")
+
+def applySkin():
+    pass

Modified: Sandbox/shane/republish/zope.publisher/src/zope/publisher/interfaces/base.py
===================================================================
--- Sandbox/shane/republish/zope.publisher/src/zope/publisher/interfaces/base.py	2009-02-22 09:35:24 UTC (rev 97010)
+++ Sandbox/shane/republish/zope.publisher/src/zope/publisher/interfaces/base.py	2009-02-22 10:54:13 UTC (rev 97011)
@@ -18,9 +18,9 @@
 
 """The base interfaces for request and response objects."""
 
+from zope.interface.common.mapping import IExtendedReadMapping
 from zope.interface import Attribute
 from zope.interface import Interface
-from zope.interface.common.mapping import IExtendedReadMapping
 
 __all__ = (
     'IRequest',
@@ -28,8 +28,8 @@
     'IResult',
     'IHeld',
     'IDebugFlags',
-    'IWSGIApplication',
     'IPublishTraverse',
+    'IWSGIApplication',
     )
 
 
@@ -59,36 +59,6 @@
         possible by other parts of the framework to access the data of the
         request via the ``body`` attribute.""")
 
-    traversal_stack = Attribute(
-        """The list of steps to traverse in reverse order.
-
-        Elements will be removed from this list as they are traversed.
-        It is possible to influence traversal by changing this list
-        during traversal.
-        """)
-
-    traversal_hooks = Attribute(
-        """List of hooks to call before each traversal step.
-
-        Each hook will be called with two parameters, request and ob.
-        The hook does not need to return anything.
-
-        These hooks will be called before traversing an object for the
-        first time.  If the same object is traversed more than
-        once, the hook will still only be called the first time.
-        """)
-
-    traversed = Attribute(
-        """List of (name, obj) steps that have been traversed.
-
-        The first object is the application root and may have an empty name.
-        The last object is the object to call.
-        """)
-
-    traversed_default = Attribute(
-        """The number of steps added by default traversal.
-        """)
-
     principal = Attribute(
         """IPrincipal object associated with the request.
         """)
@@ -118,33 +88,10 @@
     locale = Attribute(
         """The locale object associated with this request.""")
 
-    def getTraversalStack():
-        """Deprecated: use the traversal_stack attribute instead.
-        """
-
-    def setTraversalStack(stack):
-        """Deprecated: use the traversal_stack attribute instead.
-        """
-
     def setPrincipal(principal):
         """Deprecated: use the principal attribute instead.
         """
 
-    def getBasicCredentials():
-        """Return (login, password) if the request contains basic credentials.
-
-        Returns None if no such credentials are in the request or the
-        credentials are of some other type.
-        """
-
-    def _authUserPW():
-        """Deprecated: Use getBasicCredentials() instead.
-        """
-
-    def unauthorized(challenge):
-        """Deprecated: use response.unauthorized() instead.
-        """
-
     def hold(held):
         """Hold a reference to an object until the request is closed.
 
@@ -158,14 +105,15 @@
 
 
 class IResponse(Interface):
-    """Holds a response result."""
+    """Collects information for a response and produces an iterable result."""
 
     def getStatus():
         """Returns the current status code as an integer.
         """
 
     def getStatusString():
-        """Return the status followed by the reason."""
+        """Return the status and status message, joined by a space character.
+        """
 
     def setStatus(status, reason=None):
         """Sets the status code of the response
@@ -288,16 +236,6 @@
     showTAL = Attribute("""Leave TAL markup in rendered page templates""")
 
 
-class IWSGIApplication(Interface):
-    """Implements the WSGI application spec.  See PEP 333:
-
-    http://www.python.org/dev/peps/pep-0333/
-    """
-
-    def __call__(environ, start_response):
-        """Call the application and return a body iterator."""
-
-
 class IPublishTraverse(Interface):
 
     def publishTraverse(request, name):
@@ -312,3 +250,12 @@
         This method should return an object that provides ILocation,
         having the specified name and `self` as parent.
         """
+
+class IWSGIApplication(Interface):
+    """Implements the WSGI application spec.  See PEP 333:
+
+    http://www.python.org/dev/peps/pep-0333/
+    """
+
+    def __call__(environ, start_response):
+        """Call the application and return a body iterator."""

Modified: Sandbox/shane/republish/zope.publisher/src/zope/publisher/interfaces/http.py
===================================================================
--- Sandbox/shane/republish/zope.publisher/src/zope/publisher/interfaces/http.py	2009-02-22 09:35:24 UTC (rev 97010)
+++ Sandbox/shane/republish/zope.publisher/src/zope/publisher/interfaces/http.py	2009-02-22 10:54:13 UTC (rev 97011)
@@ -129,24 +129,7 @@
         If path_only is true, then only a path will be returned.
         """
 
-    def getBasicAuth():
-        """Return (login, password) if there are basic credentials.
 
-        Return None if the request does not contain basic credentials.
-        """
-
-    def _authUserPw():
-        """Deprecated: Use getBasicAuth() instead.
-        """
-
-    def unauthorized(challenge):
-        """Issue a 401 Unauthorized error (asking for login/password).
-
-        Sets the WWW-Authenticate header to the value of the
-        challenge parameter.
-        """
-
-
 class IHTTPResponse(IResponse):
     """An object representation of an HTTP response."""
 



More information about the Checkins mailing list