[Zope-Checkins] CVS: Zope3/lib/python/Zope/Publisher - BaseRequest.py:1.2 BaseResponse.py:1.2 Converters.py:1.2 DefaultPublication.py:1.2 Exceptions.py:1.2 IApplicationRequest.py:1.2 IApplicationResponse.py:1.2 IPublication.py:1.2 IPublicationRequest.py:1.2 IPublishTraverse.py:1.2 IPublisher.py:1.2 IPublisherRequest.py:1.2 IPublisherResponse.py:1.2 Publish.py:1.2 RequestDataProperty.py:1.2 __init__.py:1.2 mapply.py:1.2 maybe_lock.py:1.2 minitest.py:1.2 normal.clb:1.2 publisher-meta.zcml:1.2 publisher.zcml:1.2
Jim Fulton
jim@zope.com
Mon, 10 Jun 2002 19:30:04 -0400
Update of /cvs-repository/Zope3/lib/python/Zope/Publisher
In directory cvs.zope.org:/tmp/cvs-serv20468/lib/python/Zope/Publisher
Added Files:
BaseRequest.py BaseResponse.py Converters.py
DefaultPublication.py Exceptions.py IApplicationRequest.py
IApplicationResponse.py IPublication.py IPublicationRequest.py
IPublishTraverse.py IPublisher.py IPublisherRequest.py
IPublisherResponse.py Publish.py RequestDataProperty.py
__init__.py mapply.py maybe_lock.py minitest.py normal.clb
publisher-meta.zcml publisher.zcml
Log Message:
Merged Zope-3x-branch into newly forked Zope3 CVS Tree.
=== Zope3/lib/python/Zope/Publisher/BaseRequest.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""
+
+$Id$
+"""
+
+from cgi import escape
+from types import StringType
+from BaseResponse import BaseResponse
+from IApplicationRequest import IApplicationRequest
+from IPublisherRequest import IPublisherRequest
+from IPublicationRequest import IPublicationRequest
+from RequestDataProperty import RequestDataProperty, RequestDataMapper
+
+class IRequest(IPublisherRequest, IPublicationRequest, IApplicationRequest):
+ """The basic request contract
+ """
+
+_marker = object()
+
+class RequestEnvironment(RequestDataMapper):
+ _mapname = '_environ'
+
+class BaseRequest(object):
+ """Represents a publishing request.
+
+ This object provides access to request data. Request data may
+ vary depending on the protocol used.
+
+ Request objects are created by the object publisher and will be
+ passed to published objects through the argument name, REQUEST.
+
+ The request object is a mapping object that represents a
+ collection of variable to value mappings.
+ """
+
+ __implements__ = IRequest
+
+ __slots__ = (
+ '_held', # Objects held until the request is closed
+ '_traversed_names', # The names that have been traversed
+ '_traversal_stack', # Names to be traversed, in reverse order
+ '_environ', # The request environment variables
+ '_response', # The response
+ '_args', # positional arguments
+ '_body_instream', # input stream
+ '_body', # The request body as a string
+ '_publication', # publication object
+ '_presentation_skin', # View skin
+ )
+
+ environment = RequestDataProperty(RequestEnvironment)
+
+ def __init__(self, body_instream, outstream, environ, response=None,
+ positional=()):
+ self._traversal_stack = []
+ self._traversed_names = []
+ self._environ = environ
+
+ self._args = positional
+ if response is None:
+ self._response = self._createResponse(outstream)
+ else:
+ self._response = response
+ self._body_instream = body_instream
+ self._held = ()
+
+
+ ############################################################
+ # Implementation methods for interface
+ # Zope.Publisher.BaseRequest.IRequest
+
+ ######################################
+ # from: Zope.Publisher.IPublisherRequest.IPublisherRequest
+
+ def getPublication(self):
+ 'See Zope.Publisher.IPublisherRequest.IPublisherRequest'
+ return getattr(self, '_publication', None)
+
+ def processInputs(self):
+ 'See Zope.Publisher.IPublisherRequest.IPublisherRequest'
+ # Nothing to do here
+
+ def retry(self):
+ 'See Zope.Publisher.IPublisherRequest.IPublisherRequest'
+ raise TypeError('Retry is not supported')
+
+ def setPublication(self, pub):
+ 'See Zope.Publisher.IPublisherRequest.IPublisherRequest'
+ self._publication = pub
+
+ def supportsRetry(self):
+ 'See Zope.Publisher.IPublisherRequest.IPublisherRequest'
+ return 0
+
+ def traverse(self, object):
+ 'See Zope.Publisher.IPublisherRequest.IPublisherRequest'
+
+ publication = self.getPublication()
+
+ traversal_stack = self._traversal_stack
+ traversed_names = self._traversed_names
+
+ prev_object = None
+ while 1:
+ if object is not prev_object:
+ # Invoke hooks (but not more than once).
+ publication.callTraversalHooks(self, object)
+
+ prev_object = object
+
+ if traversal_stack:
+ # Traverse to the next step.
+ entry_name = traversal_stack.pop()
+ subobject = publication.traverseName(
+ self, object, entry_name)
+ traversed_names.append(entry_name)
+ object = subobject
+ else:
+ # Finished traversal.
+ break
+
+ return object
+
+ ######################################
+ # from: Zope.Publisher.IPublicationRequest.IPublicationRequest
+
+ def close(self):
+ 'See Zope.Publisher.IPublicationRequest.IPublicationRequest'
+ self._held = None
+ self._response = None
+ self._body_instream = None
+ self._publication = None
+
+ def getPositionalArguments(self):
+ 'See Zope.Publisher.IPublicationRequest.IPublicationRequest'
+ return self._args
+
+ def getResponse(self):
+ 'See Zope.Publisher.IPublicationRequest.IPublicationRequest'
+ return self._response
+
+ def getTraversalStack(self):
+ 'See Zope.Publisher.IPublicationRequest.IPublicationRequest'
+ return list(self._traversal_stack) # Return a copy
+
+ def hold(self, object):
+ 'See Zope.Publisher.IPublicationRequest.IPublicationRequest'
+ self._held = self._held + (object,)
+
+ def setTraversalStack(self, stack):
+ 'See Zope.Publisher.IPublicationRequest.IPublicationRequest'
+ self._traversal_stack[:] = list(stack)
+
+ def setViewSkin(self, skin):
+ 'See Zope.Publisher.IPublicationRequest.IPublicationRequest'
+ self._presentation_skin = skin
+
+ ######################################
+ # from:
+ # Zope.ComponentArchitecture.IPresentationService.IPresentationRequest
+
+ def getPresentationSkin(self):
+ 'See Zope.ComponentArchitecture.IViewService.IPresentationRequest'
+ return getattr(self, '_presentation_skin', '')
+
+ def getPresentationType(self):
+ 'See Zope.ComponentArchitecture.IViewService.IPresentationRequest'
+ return getattr(self, '_presentation_type', None)
+
+ # This is not part of the interface:
+ def setViewType(self, viewtype):
+ '''Set the view type.
+
+ This method will normally only be called in tests, which will allow
+ us to use a simpler Request set-up.'''
+
+ # XXX This will probably go away
+
+ self._presentation_type = viewtype
+
+
+ ######################################
+ # from: Zope.Publisher.IApplicationRequest.IApplicationRequest
+
+ def getBody(self):
+ 'See Zope.Publisher.IApplicationRequest.IApplicationRequest'
+ body = getattr(self, '_body', None)
+ if body is None:
+ s = self._body_instream
+ if s is None:
+ return default
+ p = s.tell()
+ s.seek(0)
+ body = s.read()
+ s.seek(p)
+ self._body = body
+ return body
+
+ def getBodyFile(self):
+ 'See Zope.Publisher.IApplicationRequest.IApplicationRequest'
+ return self._body_instream
+
+ ######################################
+ # from: Interface.Common.Mapping.IEnumerableMapping
+
+ def __len__(self):
+ 'See Interface.Common.Mapping.IEnumerableMapping'
+ return len(self.keys())
+
+ def items(self):
+ 'See Interface.Common.Mapping.IEnumerableMapping'
+ result = []
+ get = self.get
+ for k in self.keys():
+ result.append((k, get(k)))
+ return result
+
+ def keys(self):
+ 'See Interface.Common.Mapping.IEnumerableMapping'
+ return self._environ.keys()
+
+ def values(self):
+ 'See Interface.Common.Mapping.IEnumerableMapping'
+ result = []
+ get = self.get
+ for k in self.keys():
+ result.append(get(k))
+ return result
+
+ ######################################
+ # from: Interface.Common.Mapping.IReadMapping
+
+ def __getitem__(self, key):
+ 'See Interface.Common.Mapping.IReadMapping'
+ result = self.get(key, _marker)
+ if result is _marker:
+ raise KeyError, key
+ else:
+ return result
+
+ def get(self, key, default=None):
+ 'See Interface.Common.Mapping.IReadMapping'
+
+ result = self._environ.get(key, self)
+ if result is not self: return result
+
+ return default
+
+ def __contains__(self, key):
+ 'See Interface.Common.Mapping.IReadMapping'
+ lookup = self.get(key, self)
+ return lookup is not self
+
+ has_key = __contains__
+
+ #
+ ############################################################
+
+ def _createResponse(self, outstream):
+ # Should be overridden by subclasses
+ return BaseResponse(outstream)
+
+ def __nonzero__(self):
+ # This is here to avoid calling __len__ for boolean tests
+ return 1
+
+ def __str__(self):
+ L1 = self.items()
+ L1.sort()
+ return "\n".join(map(lambda item: "%s:\t%s" % item, L1))
+
+ def __repr__(self):
+ # Returns a *short* string.
+ return '<%s instance at 0x%x, URL=%s>' % (
+ str(self.__class__), id(self), `self.URL`)
+
+
+
+
+
+
+
+
+
+
+
=== Zope3/lib/python/Zope/Publisher/BaseResponse.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+'''Response Output formatter
+
+$Id$
+'''
+
+
+import traceback
+from IPublisherResponse import IPublisherResponse
+from IApplicationResponse import IApplicationResponse
+
+
+class IResponse(IPublisherResponse, IApplicationResponse):
+ """The basic response contract
+ """
+
+
+class BaseResponse(object):
+ """Base Response Class
+ """
+
+ __slots__ = (
+ '_body', # The response body
+ '_outstream', # The output stream
+ )
+
+ __implements__ = IResponse
+
+
+ def __init__(self, outstream):
+ self._body = ''
+ self._outstream = outstream
+
+ ############################################################
+ # Implementation methods for interface
+ # Zope.Publisher.BaseResponse.IResponse
+
+ ######################################
+ # from: Zope.Publisher.IPublisherResponse.IPublisherResponse
+
+ def outputBody(self):
+ 'See Zope.Publisher.IPublisherResponse.IPublisherResponse'
+ self._outstream.write(self._getBody())
+
+ def setBody(self, body):
+ 'See Zope.Publisher.IPublisherResponse.IPublisherResponse'
+ self._body = body
+
+ # This method is not part of this interface
+ def _getBody(self):
+ 'Returns a string representing the currently set body.'
+ return self._body
+
+ def handleException(self, exc_info):
+ 'See Zope.Publisher.IPublisherResponse.IPublisherResponse'
+ traceback.print_exception(
+ exc_info[0], exc_info[1], exc_info[2], 100, self)
+
+ def internalError(self):
+ 'See Zope.Publisher.IPublisherResponse.IPublisherResponse'
+ pass
+
+ def retry(self):
+ 'See Zope.Publisher.IPublisherResponse.IPublisherResponse'
+ return self.__class__(self.outstream)
+
+ ######################################
+ # from: Zope.Publisher.IApplicationResponse.IApplicationResponse
+
+ def write(self, string):
+ 'See Zope.Publisher.IApplicationResponse.IApplicationResponse'
+ self._body += string
+
+ #
+ ############################################################
=== Zope3/lib/python/Zope/Publisher/Converters.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+__version__='$Revision$'[11:-2]
+
+import re
+from types import ListType, TupleType
+
+__ArrayTypes = (ListType, TupleType)
+
+def field2string(v):
+ if hasattr(v,'read'): v=v.read()
+ else: v=str(v)
+ return v
+
+def field2text(v, nl=re.compile('\r\n|\n\r').search):
+ if hasattr(v,'read'): v=v.read()
+ else: v=str(v)
+ mo = nl(v)
+ if mo is None: return v
+ l = mo.start(0)
+ r=[]
+ s=0
+ while l >= s:
+ r.append(v[s:l])
+ s=l+2
+ mo=nl(v,s)
+ if mo is None: l=-1
+ else: l=mo.start(0)
+
+ r.append(v[s:])
+
+ return '\n'.join(r)
+
+def field2required(v):
+ if hasattr(v,'read'): v=v.read()
+ else: v=str(v)
+ if v.strip(): return v
+ raise ValueError, 'No input for required field<p>'
+
+def field2int(v):
+ if isinstance(v, __ArrayTypes):
+ return map(field2int, v)
+ if hasattr(v,'read'): v=v.read()
+ else: v=str(v)
+ if v:
+ try: return int(v)
+ except ValueError:
+ raise ValueError, (
+ "An integer was expected in the value '%s'" % v
+ )
+ raise ValueError, 'Empty entry when <strong>integer</strong> expected'
+
+def field2float(v):
+ if isinstance(v, __ArrayTypes):
+ return map(field2float, v)
+ if hasattr(v,'read'): v=v.read()
+ else: v=str(v)
+ if v:
+ try: return float(v)
+ except ValueError:
+ raise ValueError, (
+ "A floating-point number was expected in the value '%s'" % v
+ )
+ raise ValueError, (
+ 'Empty entry when <strong>floating-point number</strong> expected')
+
+def field2long(v):
+ if isinstance(v, __ArrayTypes):
+ return map(field2long, v)
+ if hasattr(v,'read'): v=v.read()
+ else: v=str(v)
+
+ # handle trailing 'L' if present.
+ if v.lower().endswith('l'):
+ v = v[:-1]
+ if v:
+ try: return long(v)
+ except ValueError:
+ raise ValueError, (
+ "A long integer was expected in the value '%s'" % v
+ )
+ raise ValueError, 'Empty entry when <strong>integer</strong> expected'
+
+def field2tokens(v):
+ if hasattr(v,'read'): v=v.read()
+ else: v=str(v)
+ return v.split()
+
+def field2lines(v):
+ if isinstance(v, __ArrayTypes):
+ result=[]
+ for item in v:
+ result.append(str(item))
+ return result
+ return field2text(v).split('\n')
+
+def field2date(v):
+ from DateTime import DateTime
+ if hasattr(v,'read'): v=v.read()
+ else: v=str(v)
+ return DateTime(v)
+
+def field2boolean(v):
+ return v
+
+type_converters = {
+ 'float': field2float,
+ 'int': field2int,
+ 'long': field2long,
+ 'string': field2string,
+ 'date': field2date,
+ 'required': field2required,
+ 'tokens': field2tokens,
+ 'lines': field2lines,
+ 'text': field2text,
+ 'boolean': field2boolean,
+ }
+
+get_converter=type_converters.get
=== Zope3/lib/python/Zope/Publisher/DefaultPublication.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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 IPublication import IPublication
+from Exceptions import NotFound, DebugError, Unauthorized
+from mapply import mapply
+
+class DefaultPublication:
+
+ __implements__ = IPublication
+
+ require_docstrings = 1
+
+ def __init__(self, app):
+ self.app = app
+
+ def beforeTraversal(self, request):
+ # Lop off leading and trailing empty names
+ stack = request.getTraversalStack()
+ while stack and not stack[-1]:
+ stack.pop() # toss a trailing empty name
+ while stack and not stack[0]:
+ stack.pop(0) # toss a leading empty name
+ request.setTraversalStack(stack)
+
+ def getApplication(self, request):
+ return self.app
+
+ def callTraversalHooks(self, request, ob):
+ pass
+
+ def traverseName(self, request, ob, name, check_auth=1):
+ if name.startswith('_'):
+ raise Unauthorized("Name %s begins with an underscore" % `name`)
+ if hasattr(ob, name):
+ subob = getattr(ob, name)
+ else:
+ try:
+ subob = ob[name]
+ except (KeyError, IndexError,
+ TypeError, AttributeError):
+ raise NotFound(ob, name, request)
+ if self.require_docstrings and not getattr(subob, '__doc__', None):
+ raise DebugError(subob, 'Missing or empty doc string')
+ return subob
+
+ def getDefaultTraversal(self, request, ob):
+ return ob, ()
+
+ def afterTraversal(self, request, ob):
+ pass
+
+ def callObject(self, request, ob):
+ return mapply(ob, request.getPositionalArguments(), request)
+
+ def afterCall(self, request):
+ pass
+
+ def handleException(self, request, exc_info, retry_allowed=1):
+ # Let the response handle it as best it can.
+ response = request.getResponse()
+ response.handleException(exc_info)
+
+
+class TestPublication(DefaultPublication):
+
+ def traverseName(self, request, ob, name, check_auth=1):
+ if hasattr(ob, name):
+ subob = getattr(ob, name)
+ else:
+ try:
+ subob = ob[name]
+ except (KeyError, IndexError,
+ TypeError, AttributeError):
+ raise NotFound(ob, name, request)
+ return subob
=== Zope3/lib/python/Zope/Publisher/Exceptions.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.Exceptions import Unauthorized
+from Zope.Exceptions import NotFoundError
+
+
+class PublishingException (Exception):
+ """
+ """
+
+
+class TraversalException (PublishingException):
+ """
+ """
+
+
+class NotFound (NotFoundError, TraversalException):
+ """
+ """
+ def __init__(self, ob, name, request=None):
+ self.ob = ob
+ self.name = name
+
+ def getObject(self):
+ return self.ob
+
+ def getName(self):
+ return self.name
+
+ def __str__(self):
+ try: ob = `self.ob`
+ except: ob = 'unprintable object'
+ return 'Object: %s, name: %s' % (ob, `self.name`)
+
+
+class DebugError (TraversalException):
+ """
+ """
+ def __init__(self, ob, message):
+ self.ob = ob
+ self.message = message
+
+ def getObject(self):
+ return self.ob
+
+ def getMessage(self):
+ return self.message
+
+ def __str__(self):
+ return self.message
+
+
+class BadRequest (PublishingException):
+
+ def __init__(self, message):
+ self.message = message
+
+ def __str__(self):
+ return self.message
+
+
+class Redirect (PublishingException):
+
+ def __init__(self, location):
+ self.location = location
+
+ def getLocation(self):
+ return self.location
+
+ def __str__(self):
+ return 'Location: %s' % self.location
+
+
+class Retry (PublishingException):
+ """
+ Raise this to retry a request.
+ """
+
+ def __init__(self, orig_exc=None):
+ self.orig_exc = orig_exc
+
+ def getOriginalException(self):
+ return self.orig_exc
+
+ def __str__(self):
+ return repr(self.orig_exc)
=== Zope3/lib/python/Zope/Publisher/IApplicationRequest.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""
+
+Revision information:
+$Id$
+"""
+
+from Interface.Common.Mapping import IEnumerableMapping
+from Interface.Attribute import Attribute
+
+class IApplicationRequest(IEnumerableMapping):
+ """Features that support application logic
+ """
+
+ def getBody():
+ """Return the body of the request as a string
+ """
+
+
+ def getBodyFile():
+ """Return the body of the request as a file
+ """
+
+ def __getitem__(key):
+ """Return request data
+
+ The only request data are envirnment variables.
+ """
+
+ environment = Attribute(
+ """Request environment data
+
+ This is a read-only mapping from variable name to value.
+ """)
+
+
=== Zope3/lib/python/Zope/Publisher/IApplicationResponse.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""
+
+Revision information:
+$Id$
+"""
+
+from Interface import Interface
+
+class IApplicationResponse(Interface):
+ """Features that support application logic
+ """
+
+ def write(string):
+ """Output a string to the response body.
+ """
=== Zope3/lib/python/Zope/Publisher/IPublication.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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 Interface import Interface
+
+class IPublication (Interface):
+ """Object publication framework.
+
+ The responsibility of publication objects is to provide
+ application hooks for the publishing process. This allows
+ application-specific tasks, such as connecting to databases,
+ managing transactions, and setting security contexts to be invoked
+ during the publishing process.
+
+ """
+ # The order of the hooks mostly corresponds with the order in which
+ # they are invoked.
+
+ def beforeTraversal(request):
+ """
+ Pre-traversal hook.
+ """
+
+ def getApplication(request):
+ """
+ Returns the object where traversal should commence.
+ """
+
+ def callTraversalHooks(request, ob):
+ """
+ Invokes any traversal hooks associated with the object.
+ """
+
+ def traverseName(request, ob, name, check_auth=1):
+ """
+ Traverses to the next object. If check_auth is set,
+ performs idenitification, authentication, and authorization.
+ Returns the subobject.
+ """
+
+ def afterTraversal(request, ob):
+ """Post-traversal hook.
+ """
+
+ def callObject(request, ob):
+ """Call the object, returning the result.
+
+ For GET/POST this means calling it, but for other methods
+ (including those of WebDAV and FTP) this might mean invoking
+ a method of an adapter.
+ """
+
+ def afterCall(request):
+ """Post-callObject hook (if it was successful).
+ """
+
+ def handleException(request, exc_info, retry_allowed=1):
+ """Handle an exception
+
+ Either:
+ - sets the body of the response, request.getResponse(), or
+ - raises a Retry exception, or
+ - throws another exception, which is a Bad Thing.
+
+ Note that this method should not leak, which means that
+ exc_info must be set to some other value before exiting the method.
+ """
+
=== Zope3/lib/python/Zope/Publisher/IPublicationRequest.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""
+
+Revision information:
+$Id$
+"""
+
+from Zope.ComponentArchitecture.IPresentationRequest \
+ import IPresentationRequest
+
+class IPublicationRequest(IPresentationRequest):
+ """Interface provided by requests to IPublication objects
+ """
+
+ def getResponse():
+ """Return the request's response object
+
+ Return an IPublisherResponse for the request.
+ """
+
+ def close():
+ """Release resources held by the request.
+ """
+
+ def hold(object):
+ """Hold a reference to an object until the request is closed
+ """
+
+ def getTraversalStack():
+ """Return the request traversal stack
+
+ This is a sequence of steps to traverse in reverse order. They
+ will be traversed from last to first.
+ """
+
+ def setTraversalStack(stack):
+ """Change the traversal stack.
+
+ See getTraversalStack.
+ """
+
+ def getPositionalArguments():
+ """Return the positional arguments given to the request.
+ """
+
+ def setViewSkin(skin):
+ """Set the skin to be used for the request.
+
+ It's up to the publication object to decide this.
+ """
+
+
=== Zope3/lib/python/Zope/Publisher/IPublishTraverse.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""
+
+$Id$
+"""
+
+from Interface import Interface
+
+class IPublishTraverse(Interface):
+
+ def publishTraverse(request, name):
+ """Lookup a name
+
+ The request argument is the publisher request object.
+ """
+
=== Zope3/lib/python/Zope/Publisher/IPublisher.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""
+
+Revision information:
+$Id$
+"""
+
+from Interface import Interface
+
+def IPublisher(Interface):
+
+ def publish(request):
+ """Publish a request
+
+ The request must be an IPublisherRequest.
+ """
+
+
=== Zope3/lib/python/Zope/Publisher/IPublisherRequest.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""
+
+Revision information:
+$Id$
+"""
+
+from IPublicationRequest import IPublicationRequest
+
+class IPublisherRequest(IPublicationRequest):
+ """Request interface use by the publisher
+
+ The responsibility of requests is to encapsulate protocol
+ specific details, especially wrt request inputs.
+
+ Request objects also serve as "context" objectsm providing
+ construction of and access to responses and storage of publication
+ objects.
+
+ """
+
+ def supportsRetry():
+ """Check whether the request supports retry
+
+ Return a boolean value indicating whether the request can be retried.
+ """
+
+ def retry():
+ """Return a retry request
+
+ Return a request suitable for repeating the publication attempt.
+ """
+
+ def getPublication():
+ """Return the request's publication object
+
+ The publication object, an IRequestPublication provides
+ application-specific functionality hooks.
+ """
+
+ def setPublication(publication):
+ """Set the request's publication object
+ """
+
+ def traverse(object):
+ """Traverse from the given object to the published object
+
+ The published object is returned.
+
+ The following hook methods on the publication will be called:
+
+ - callTraversalHooks is called before each step and after
+ the last step.
+
+ - traverseName to actually do a single traversal
+
+ """
+
+ def processInputs():
+ """Do any input processing that needs to bve done before traversing
+
+ This is done after construction to allow the publisher to
+ handle errors that arise.
+ """
=== Zope3/lib/python/Zope/Publisher/IPublisherResponse.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""
+
+Revision information:
+$Id$
+"""
+
+from Interface import Interface
+
+class IPublisherResponse(Interface):
+ """Interface used by the publsher
+ """
+
+ def setBody(result):
+ """Sets the response result value.
+ """
+
+ def handleException(exc_info):
+ """Handles an otherwise unhandled exception.
+
+ The publication object gets the first chance to handle an exception,
+ and if it doesn't have a good way to do it, it defers to the
+ response. Implementations should set the reponse body.
+ """
+
+ def internalError():
+ """Called when the exception handler bombs.
+
+ Should report back to the client that an internal error occurred.
+ """
+
+ def outputBody():
+ """Outputs the response to the client
+ """
+
+ def retry():
+ """Returns a retry response
+
+ Returns a response suitable for repeating the publication attempt.
+ """
=== Zope3/lib/python/Zope/Publisher/Publish.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""
+Python Object Publisher -- Publish Python objects on web servers
+
+$Id$
+"""
+
+
+import sys, os
+from Exceptions import Retry
+
+def publish(request, handle_errors=1):
+ try: # finally to clean up to_raise and close request
+ to_raise = None
+ while 1:
+ publication = request.getPublication()
+ try:
+ try:
+ try:
+ request.processInputs()
+ publication.beforeTraversal(request)
+
+ root_object = publication.getApplication(request)
+ object = request.traverse(root_object)
+ publication.afterTraversal(request, object)
+
+ result = publication.callObject(request, object)
+ response = request.getResponse()
+ if result is not response:
+ response.setBody(result)
+
+ publication.afterCall(request)
+
+ except:
+ publication.handleException(request, sys.exc_info(), 1)
+ if not handle_errors:
+ raise
+
+ break # Successful.
+
+ except Retry, retryException:
+ if request.supportsRetry():
+ # Create a copy of the request and use it.
+ newrequest = request.retry()
+ request.close()
+ request = newrequest
+ elif handle_errors:
+ # Output the original exception.
+ publication = request.getPublication()
+ publication.handleException(
+ request, retryException.getOriginalException(), 0)
+ break
+ else:
+ raise
+
+ except:
+ # Bad exception handler or retry method.
+ # Re-raise after outputting the response.
+ if handle_errors:
+ request.getResponse().internalError()
+ to_raise = sys.exc_info()
+ break
+ else:
+ raise
+
+ response = request.getResponse()
+ response.outputBody()
+ if to_raise is not None:
+ raise to_raise[0], to_raise[1], to_raise[2]
+
+ finally:
+ to_raise = None # Avoid circ. ref.
+ request.close() # Close database connections, etc.
+
+
+
+
=== Zope3/lib/python/Zope/Publisher/RequestDataProperty.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""
+
+Revision information:
+$Id$
+"""
+
+from Interface.Common.Mapping import IReadMapping, IEnumerableMapping
+
+class RequestDataGetter(object):
+
+ __implements__ = IReadMapping
+
+ def __init__(self, request):
+ self.__get = getattr(request, self._gettrname)
+
+ def __getitem__(self, name):
+ return self.__get(name)
+
+ def get(self, name, default=None):
+ return self.__get(name, default)
+
+ def __contains__(self, key):
+ lookup = self.get(key, self)
+ return lookup is not self
+
+ has_key = __contains__
+
+class RequestDataMapper(object):
+
+ __implements__ = IEnumerableMapping
+
+ def __init__(self, request):
+ self.__map = getattr(request, self._mapname)
+
+ def __getitem__(self, name):
+ return self.__map[name]
+
+ def get(self, name, default=None):
+ return self.__map.get(name, default)
+
+ def __contains__(self, key):
+ lookup = self.get(key, self)
+ return lookup is not self
+
+ has_key = __contains__
+
+ def keys(self): return self.__map.keys()
+ def items(self): return self.__map.items()
+ def values(self): return self.__map.values()
+ def __len__(self): return len(self.__map)
+
+class RequestDataProperty(object):
+
+ def __init__(self, gettr_class):
+ self.__gettr_class = gettr_class
+
+ def __get__(self, request, rclass=None):
+ if request is not None:
+ return self.__gettr_class(request)
+
+ def __set__(*args):
+ raise AttributeError, 'Unassignable attribute'
=== Zope3/lib/python/Zope/Publisher/__init__.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""
+Notes:
+
+provideExceptionHandler(BrowserPublish, Redirect, HTTPRedirector)
+"""
+
=== Zope3/lib/python/Zope/Publisher/mapply.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""Provide an apply-like facility that works with any mapping object
+"""
+
+from Zope.Proxy.ProxyIntrospection import removeAllProxies
+
+_marker = [] # Create a new marker object.
+
+
+def unwrapMethod(object):
+ """ object -> ( unwrapped, wrapperCount )
+
+ Unwrap 'object' until we get to a real function, counting the
+ number of unwrappings.
+
+ Bail if we find a class or something we can't
+ idendify as callable.
+ """
+ wrapperCount = 0
+ unwrapped = object
+ 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
+ continue
+
+ func_code = getattr(unwrapped, 'func_code', None)
+ if func_code is not None:
+ break
+
+ __call__ = getattr(unwrapped, '__call__' , None)
+ if __call__ is not None:
+ unwrapped = unwrapped.__call__
+ else:
+ raise TypeError, "mapply() can not call %s" % `object`
+
+ else:
+ raise TypeError(
+ "couldn't find callable metadata, mapply() error on %s"%`object`
+ )
+
+ return unwrapped, wrapperCount
+
+def mapply(object, positional=(), request={}, call=apply):
+ __traceback_info__ = object
+
+ # we need deep access for intrspection. Waaa.
+ unwrapped = removeAllProxies(object)
+
+ unwrapped, wrapperCount = unwrapMethod(unwrapped)
+
+ code = unwrapped.func_code
+ defaults = unwrapped.func_defaults
+ names = code.co_varnames[wrapperCount:code.co_argcount]
+
+ nargs = len(names)
+ if positional:
+ args = list(positional)
+ if len(args) > nargs:
+ given = len(args)
+ if wrapperCount:
+ given = given + wrapperCount
+ raise TypeError, (
+ '%s() takes at most %d argument%s(%d given)' % (
+ getattr(unwrapped, '__name__', repr(object)), code.co_argcount,
+ (code.co_argcount > 1 and 's ' or ' '), given))
+ else:
+ args = []
+
+ get = request.get
+ if defaults:
+ nrequired = len(names) - (len(defaults))
+ else:
+ nrequired = len(names)
+ 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(object)), name)
+ else:
+ v = defaults[index-nrequired]
+ args.append(v)
+
+ args = tuple(args)
+ return call(object, args)
=== Zope3/lib/python/Zope/Publisher/maybe_lock.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+__version__='$Revision$'[11:-2]
+
+# Waaaa, I wish I didn't have to work this hard.
+try: from thread import allocate_lock
+except:
+ class allocate_lock:
+ def acquire(*args): pass
+ def release(*args): pass
=== Zope3/lib/python/Zope/Publisher/minitest.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+import sys
+
+from Zope.Publisher.Publish import publish
+from Zope.Publisher.DefaultPublication import DefaultPublication
+from Zope.Publisher.HTTP.HTTPRequest import HTTPRequest
+from Zope.Publisher.HTTP.HTTPResponse import HTTPResponse
+from Zope.Publisher.HTTP.BrowserPayload import BrowserRequestPayload, \
+ BrowserResponsePayload
+
+class c:
+ " "
+ def __call__(self, URL):
+ return 'You invoked URL %s\n' % URL
+
+ob = c()
+ob.x = c()
+ob.x.y = c()
+
+publication = DefaultPublication(ob)
+req_p = BrowserRequestPayload(publication)
+resp_p = BrowserResponsePayload()
+
+response = HTTPResponse(resp_p, sys.stdout)
+environ = {
+ 'SERVER_NAME': 'test',
+ 'PATH_INFO': sys.argv[1]
+ }
+request = HTTPRequest(req_p, response, sys.stdin, environ)
+
+publish(request)
+
+# bogus speed test ;-)
+
+class DevNull:
+ def write(self, s):
+ pass
+devnull = DevNull()
+
+from time import clock
+count = 1000
+start = clock()
+for n in range(count):
+ response = HTTPResponse(resp_p, devnull)
+ environ = {
+ 'SERVER_NAME': 'test',
+ 'PATH_INFO': sys.argv[1]
+ }
+ request = HTTPRequest(req_p, response, sys.stdin, environ)
+ publish(request)
+end = clock()
+print '%d requests/sec' % (count / (end - start))
+
=== Zope3/lib/python/Zope/Publisher/normal.clb 1.1 => 1.2 ===
+
+ Participants:
+
+ publisher:IPublisher
+
+ request:IPublisherRequest
+
+ response:IPublicationResponse = request.getResponse()
+
+ publication:IPublication = request.getPublication()
+
+
+ Values:
+
+ root
+ "the top-level object"
+
+ foo
+ "an object obtaines by traversing the root with 'foo'"
+
+ bar
+ "an object obtaines by traversing the root with 'bar'"
+
+ result
+ "The result of calling bar"
+
+
+ Scenario: Normal, path = foo/bar
+ "Show normal publishing of a simple path without errors"
+
+ publisher.publish(request)
+
+ request.processInputs()
+
+ publication.beforeTraversal(request)
+
+ publication.getApplication(request)
+ "Get the root object to be traversed"
+
+ request.traverse(root)
+
+ publication.callTraversalHooks(request, root)
+ '''Call any "before traversal step" hooks. These hooks
+ should 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.
+
+ The last constraint is probably important to get
+ virtual host semantics rigfht. :)
+ '''
+
+ publication.traverseName(request, root, 'foo')
+
+ publication.callTraversalHooks(request, foo)
+
+ publication.traverseName(request, foo, 'bar')
+
+ return bar
+
+ publication.afterTraversal(request, bar)
+
+ publication.callObject(request, bar)
+
+ return result
+
+ response.setBody(result)
+
+ publication.afterCall(request)
+
+ response.outputBody()
+
+ request.close()
+
+
+ Scenario: Error during application call, path = foo
+ "Show what heppens when the main application code raises an error"
+
+ publisher.publish(request)
+
+ request.processInputs()
+
+ publication.beforeTraversal(request)
+
+ publication.getApplication(request)
+
+ request.traverse(root)
+
+ publication.callTraversalHooks(request, root)
+
+ publication.traverseName(request, root, 'foo')
+
+ return foo
+
+ publication.afterTraversal(request, foo)
+
+ publication.callObject(request, foo)
+
+ raise AttributeError, 'spam'
+
+
+ publication.handleException()
+
+ response.outputBody()
+
+ request.close()
+
=== Zope3/lib/python/Zope/Publisher/publisher-meta.zcml 1.1 => 1.2 ===
+ xmlns='http://namespaces.zope.org/zope'
+ xmlns:security='http://namespaces.zope.org/security'
+ xmlns:zmi='http://namespaces.zope.org/zmi'
+ xmlns:browser='http://namespaces.zope.org/browser'
+>
+
+ <include package=".XMLRPC" file="xmlrpc-meta.zcml" />
+ <include package=".VFS" file="vfs-meta.zcml" />
+
+</zopeConfigure>
=== Zope3/lib/python/Zope/Publisher/publisher.zcml 1.1 => 1.2 ===
+ xmlns='http://namespaces.zope.org/zope'
+>
+ <include package=".HTTP" file="http.zcml" />
+
+</zopeConfigure>