[Zope3-checkins] SVN: Zope3/trunk/src/zope/app/publication/ Removed
all XXX in zopepublication.py by
Stephan Richter
srichter at cosmos.phy.tufts.edu
Thu Jul 8 14:23:56 EDT 2004
Log message for revision 26209:
Removed all XXX in zopepublication.py by
1. Fixing the handleException method to have a sane algorithm to
determine its location.
2. Creating a local error service, if none exists when reporting an
error.
Added a functional test for the second change.
-=-
Added: Zope3/trunk/src/zope/app/publication/ftests.py
===================================================================
--- Zope3/trunk/src/zope/app/publication/ftests.py 2004-07-08 18:21:18 UTC (rev 26208)
+++ Zope3/trunk/src/zope/app/publication/ftests.py 2004-07-08 18:23:56 UTC (rev 26209)
@@ -0,0 +1,72 @@
+##############################################################################
+#
+# Copyright (c) 2004 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.
+#
+##############################################################################
+"""Functional tests for Zope Publication
+
+$Id: ftests.py 25177 2004-06-02 13:17:31Z jim $
+"""
+import unittest
+from zope.app import zapi
+from zope.app.tests.functional import BrowserTestCase
+
+class TestErrorReportingService(BrowserTestCase):
+
+ def testAddMissingErrorReportingService(self):
+ # Unregister and remove the existing error reporting service
+ self.publish(
+ '/++etc++site/default/RegistrationManager/ServiceRegistration/',
+ basic='mgr:mgrpw',
+ form={'field.permission': '',
+ 'field.status': 'Unregistered',
+ 'UPDATE_SUBMIT': 'Change'})
+ self.publish(
+ '/++etc++site/default/RegistrationManager/',
+ basic='mgr:mgrpw',
+ form={'keys': ['ServiceRegistration'],
+ 'remove_submit': 'Remove'})
+ self.publish(
+ '/++etc++site/default/@@contents.html',
+ basic='mgr:mgrpw',
+ form={'ids': ['ErrorLogging'],
+ 'container_delete_button': 'Delete'})
+
+ root = self.getRootFolder()
+ default = zapi.traverse(root, '++etc++site/default')
+ self.assert_('ErrorLogging' not in default.keys())
+
+ # Force a NotFoundError, so that the error reporting service is
+ # created again.
+ response = self.publish('/foobar', basic='mgr:mgrpw',
+ handle_errors=True)
+ self.assertEqual(response.getStatus(), 404)
+ body = response.getBody()
+ self.assert_(
+ 'The page that you are trying to access is not available' in body)
+
+ # Now make sure that we have a new error reporting service with the
+ # right entry.
+ root = self.getRootFolder()
+ default = zapi.traverse(root, '++etc++site/default')
+ self.assert_('ErrorLogging' in default.keys())
+ entry = default['ErrorLogging'].getLogEntries()[0]
+ self.assertEqual(entry['type'], 'NotFound')
+ self.assert_('foobar' in entry['tb_text'])
+
+
+def test_suite():
+ return unittest.TestSuite((
+ unittest.makeSuite(TestErrorReportingService),
+ ))
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='test_suite')
Modified: Zope3/trunk/src/zope/app/publication/zopepublication.py
===================================================================
--- Zope3/trunk/src/zope/app/publication/zopepublication.py 2004-07-08 18:21:18 UTC (rev 26208)
+++ Zope3/trunk/src/zope/app/publication/zopepublication.py 2004-07-08 18:23:56 UTC (rev 26209)
@@ -21,34 +21,31 @@
from ZODB.POSException import ConflictError
+from zope.event import notify
+from zope.exceptions import Unauthorized
+from zope.component.exceptions import ComponentLookupError
from zope.interface import implements, providedBy
-from zope.component import getService
-from zope.app.servicenames import ErrorLogging
-from zope.component.exceptions import ComponentLookupError
+from zope.proxy import removeAllProxies
from zope.publisher.publish import mapply
from zope.publisher.interfaces import Retry, IExceptionSideEffects
from zope.publisher.interfaces import IRequest, IPublication
-
from zope.security.management import newInteraction, endInteraction
from zope.security.checker import ProxyFactory
from zope.security.proxy import trustedRemoveSecurityProxy
-from zope.proxy import removeAllProxies
-from zope.exceptions import Unauthorized
from zope.app import zapi
-from zope.app.site.interfaces import ISite
from zope.app.applicationcontrol.applicationcontrol \
import applicationControllerRoot
-
-from zope.app.servicenames import ErrorLogging, Authentication
+from zope.app.component.hooks import getSite
+from zope.app.errorservice import RootErrorReportingService
+from zope.app.location import LocationProxy
+from zope.app.publication.interfaces import BeforeTraverseEvent
+from zope.app.publication.interfaces import EndRequestEvent
+from zope.app.publication.publicationtraverse import PublicationTraverse
from zope.app.security.principalregistry import principalRegistry as prin_reg
from zope.app.security.interfaces import IUnauthenticatedPrincipal
-from zope.app.publication.publicationtraverse import PublicationTraverse
+from zope.app.site.interfaces import ISite
from zope.app.traversing.interfaces import IPhysicallyLocatable
-from zope.app.location import LocationProxy
-from zope.event import notify
-from zope.app.publication.interfaces import BeforeTraverseEvent
-from zope.app.publication.interfaces import EndRequestEvent
class Cleanup(object):
@@ -94,7 +91,7 @@
sm = removeAllProxies(ob).getSiteManager()
try:
- auth_service = sm.getService(Authentication)
+ auth_service = sm.getService(zapi.servicenames.Authentication)
except ComponentLookupError:
# No auth service here
return
@@ -208,12 +205,38 @@
'error reporting service')
try:
try:
- errService = getService(ErrorLogging)
- errService.raising(exc_info, request)
+ errService = zapi.getService(zapi.servicenames.ErrorLogging)
+ # We only want to get the global error reporting service, if
+ # we are not in a site. If we are, we want a local error
+ # reporting service.
+ # The global error reporting service does not have a
+ # __parent__
+ if getSite() is not None and \
+ getattr(errService, '__parent__', None) is None:
+ raise ComponentLookupError
+
except ComponentLookupError:
- # There is no local error reporting service.
- # XXX We need to build a local error reporting service.
- pass
+ # There is no error reporting service. This is extremely
+ # unlikely, since such a service is created when the ZODB is
+ # first generated. So someone must have deliberately deleted
+ # it.
+ #
+ # We need to go to the root folder and add a root error
+ # reporting service there. And just in case the object passed
+ # is not a contained object or a method, we use the local site
+ # to find the root folder.
+
+ # Import here to avoid circular imports. This is okay, since
+ # this is a very special case.
+ # This is the same code used in the bootstrap mechanism.
+ from zope.app.appsetup.bootstrap import addConfigureService
+ addConfigureService(zapi.getRoot(getSite()),
+ zapi.servicenames.ErrorLogging,
+ RootErrorReportingService,
+ copy_to_zlog=True)
+
+ errService = zapi.getService(zapi.servicenames.ErrorLogging)
+
# It is important that an error in errService.raising
# does not propagate outside of here. Otherwise, nothing
# meaningful will be returned to the user.
@@ -227,11 +250,12 @@
# the ErrorReportingService, and that it will be in
# the zope log.
+ errService.raising(exc_info, request)
get_transaction().commit()
except:
tryToLogException(
'Error while reporting an error to the %s service' %
- ErrorLogging)
+ zapi.servicenames.ErrorLogging)
get_transaction().abort()
def handleException(self, object, request, exc_info, retry_allowed=True):
@@ -276,22 +300,26 @@
request, object, 'application error-handling')
view = None
try:
- # XXX we need to get a location. The object might not
- # have one, because it might be a method. If we don't
- # have a parent attr but have an im_self or an
- # __self__, use that:
-
- # XXX The following block of code is silly.
+ # We need to get a location, because some template content of
+ # the exception view might require one.
+ #
+ # The object might not have a parent, because it might be a
+ # method. If we don't have a `__parent__` attribute but have
+ # an im_self or a __self__, use it.
loc = object
- if hasattr(object, '__parent__'):
- loc = object # XXX That was done two lines above.
- else:
+ if not hasattr(object, '__parent__'):
loc = removeAllProxies(object)
+ # Try to get an object, since we apparently have a method
+ # Note: We are guaranteed that an object has a location,
+ # so just getting the instance the method belongs to is
+ # sufficient.
loc = getattr(loc, 'im_self', loc)
- if loc is loc: # XXX if True:
- loc = getattr(loc, '__self__', loc)
+ loc = getattr(loc, '__self__', loc)
+ # Protect the location with a security proxy
loc = ProxyFactory(loc)
+ # Give the exception instance its location and look up the
+ # view.
exception = LocationProxy(exc_info[1], loc, '')
name = zapi.queryDefaultViewName(exception, request)
if name is not None:
More information about the Zope3-Checkins
mailing list