[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