[Zope3-checkins] CVS: Zope3/src/zope/app/publication - httpfactory.py:1.1.2.1 browser.py:1.4.2.1 http.py:1.2.4.1 xmlrpc.py:1.3.2.1 zopepublication.py:1.10.2.1 configure.zcml:NONE
Sidnei da Silva
sidnei@x3ng.com.br
Tue, 11 Feb 2003 09:41:54 -0500
Update of /cvs-repository/Zope3/src/zope/app/publication
In directory cvs.zope.org:/tmp/cvs-serv18615/src/zope/app/publication
Modified Files:
Tag: paris-copypasterename-branch
browser.py http.py xmlrpc.py zopepublication.py
Added Files:
Tag: paris-copypasterename-branch
httpfactory.py
Removed Files:
Tag: paris-copypasterename-branch
configure.zcml
Log Message:
Updating from HEAD to make sure everything still works before merging
=== Added File Zope3/src/zope/app/publication/httpfactory.py ===
##############################################################################
#
# 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: httpfactory.py,v 1.1.2.1 2003/02/11 14:41:22 sidnei Exp $
"""
from zope.publisher.http import HTTPRequest
from zope.publisher.browser import BrowserRequest
from zope.publisher.xmlrpc import XMLRPCRequest
from zope.app.interfaces.startup import IPublicationRequestFactoryFactory
from zope.app.interfaces.startup import IPublicationRequestFactory
from zope.app.publication.http import HTTPPublication
from zope.app.publication.browser import BrowserPublication
from zope.app.publication.xmlrpc import XMLRPCPublication
__implements__ = IPublicationRequestFactoryFactory
__metaclass__ = type
_browser_methods = 'GET', 'POST', 'HEAD'
class HTTPPublicationRequestFactory:
__implements__ = IPublicationRequestFactory
def __init__(self, db):
'See IRequestFactory'
self._http = HTTPPublication(db)
self._brower = BrowserPublication(db)
self._xmlrpc = XMLRPCPublication(db)
def __call__(self, input_stream, output_steam, env):
'See IRequestFactory'
method = env.get('REQUEST_METHOD', 'GET').upper()
if method in _browser_methods:
if (method == 'POST' and
env.get('CONTENT_TYPE', '').startswith('text/xml')
):
request = XMLRPCRequest(input_stream, output_steam, env)
request.setPublication(self._xmlrpc)
else:
request = BrowserRequest(input_stream, output_steam, env)
request.setPublication(self._brower)
else:
request = HTTPRequest(input_stream, output_steam, env)
request.setPublication(self._http)
return request
realize = HTTPPublicationRequestFactory
=== Zope3/src/zope/app/publication/browser.py 1.4 => 1.4.2.1 ===
--- Zope3/src/zope/app/publication/browser.py:1.4 Tue Dec 31 13:26:57 2002
+++ Zope3/src/zope/app/publication/browser.py Tue Feb 11 09:41:22 2003
@@ -19,7 +19,7 @@
from zope.app.publication.publicationtraverse \
import PublicationTraverser as PublicationTraverser_
-from zope.app.publication.http import ZopeHTTPPublication
+from zope.app.publication.zopepublication import ZopePublication
from zope.component import queryAdapter, queryView
from zope.proxy.context import ContextWrapper
from zope.proxy.introspection import removeAllProxies
@@ -43,7 +43,7 @@
ob = self.traversePath(request, ob, path)
-class BrowserPublication(ZopeHTTPPublication):
+class BrowserPublication(ZopePublication):
"""Web browser publication handling."""
def getDefaultTraversal(self, request, ob):
@@ -64,6 +64,11 @@
wrapped = ContextWrapper(ProxyFactory(r[0]), ob, name=None)
return (wrapped, r[1])
+
+ def afterCall(self, request):
+ super(BrowserPublication, self).afterCall(request)
+ if request.method == 'HEAD':
+ request.response.setBody('')
# For now, have a factory that returns a singleton
class PublicationFactory:
=== Zope3/src/zope/app/publication/http.py 1.2 => 1.2.4.1 ===
--- Zope3/src/zope/app/publication/http.py:1.2 Wed Dec 25 09:13:08 2002
+++ Zope3/src/zope/app/publication/http.py Tue Feb 11 09:41:22 2003
@@ -17,7 +17,13 @@
"""
from zope.app.publication.zopepublication import ZopePublication
+from zope.component import getView
+from zope.publisher.publish import mapply
-class ZopeHTTPPublication(ZopePublication):
+class HTTPPublication(ZopePublication):
"HTTP-specific support"
- # XXX do we need this?
+
+ def callObject(self, request, ob):
+ ob = getView(ob, request.method, request)
+ ob = getattr(ob, request.method)
+ return mapply(ob, request.getPositionalArguments(), request)
=== Zope3/src/zope/app/publication/xmlrpc.py 1.3 => 1.3.2.1 ===
--- Zope3/src/zope/app/publication/xmlrpc.py:1.3 Tue Jan 14 15:26:05 2003
+++ Zope3/src/zope/app/publication/xmlrpc.py Tue Feb 11 09:41:22 2003
@@ -15,11 +15,12 @@
$Id$
"""
+
from zope.proxy.introspection import removeAllProxies
-from zope.app.publication.http import ZopeHTTPPublication
+from zope.app.publication.zopepublication import ZopePublication
from zope.component import queryView
-class XMLRPCPublication(ZopeHTTPPublication):
+class XMLRPCPublication(ZopePublication):
"""XML-RPC publication handling.
There is nothing special here right now.
=== Zope3/src/zope/app/publication/zopepublication.py 1.10 => 1.10.2.1 ===
--- Zope3/src/zope/app/publication/zopepublication.py:1.10 Mon Feb 3 12:20:24 2003
+++ Zope3/src/zope/app/publication/zopepublication.py Tue Feb 11 09:41:22 2003
@@ -14,12 +14,14 @@
import sys
import logging
-from zope.component import getService
+from zope.component import getService, getView, getDefaultViewName
+from zope.component import queryService, getAdapter
from zope.component.exceptions import ComponentLookupError
+from zope.component.servicenames import ErrorReports, Authentication
from zodb.interfaces import ConflictError
from zope.publisher.publish import mapply
-from zope.publisher.interfaces import Retry
+from zope.publisher.interfaces import Retry, IExceptionSideEffects
from zope.publisher.interfaces.http import IHTTPRequest
from zope.security.management import getSecurityManager, newSecurityManager
@@ -70,7 +72,8 @@
raise Unauthorized # If there's no default principal
newSecurityManager(p.getId())
- request.user = p
+ # XXX add a test to check that request.user is context wrapped
+ request.user = ContextWrapper(p, prin_reg)
get_transaction().begin()
def _maybePlacefullyAuthenticate(self, request, ob):
@@ -90,7 +93,7 @@
sm = ContextWrapper(sm, ob, name="++etc++Services")
- auth_service = sm.get('Authentication')
+ auth_service = sm.get(Authentication)
if auth_service is None:
# No auth service here
return
@@ -104,7 +107,8 @@
return
newSecurityManager(principal.getId())
- request.user = principal
+ # XXX add test that request.user is context-wrapped
+ request.user = ContextWrapper(principal, auth_service)
def callTraversalHooks(self, request, ob):
@@ -160,16 +164,66 @@
txn.setUser(request.user.getId())
get_transaction().commit()
- def handleException(self, object, request, exc_info, retry_allowed=1):
- # Abort the transaction.
- get_transaction().abort()
-
- try:
- errService = getService(object, 'ErrorReportingService')
- except ComponentLookupError:
- pass
+ def handleException(self, object, request, exc_info, retry_allowed=True):
+ # Convert ConflictErrors to Retry exceptions.
+ if retry_allowed and isinstance(exc_info[1], ConflictError):
+ get_transaction().abort()
+ tryToLogWarning('ZopePublication',
+ 'Competing writes/reads at %s' %
+ request.get('PATH_INFO', '???'),
+ exc_info=True)
+ raise Retry
+ # Are there any reasons why we'd want to let application-level error
+ # handling determine whether a retry is allowed or not?
+ # Assume not for now.
+
+ response = request.response
+ exception = None
+ legacy_exception = not isinstance(exc_info[1], Exception)
+ if legacy_exception:
+ response.handleException(exc_info)
+ get_transaction().abort()
+ if isinstance(exc_info[1], str):
+ tryToLogWarning(
+ 'Publisher received a legacy string exception: %s.'
+ ' This will be handled by the request.' %
+ exc_info[1])
+ else:
+ tryToLogWarning(
+ 'Publisher received a legacy classic class exception: %s.'
+ ' This will be handled by the request.' %
+ exc_info[1].__class__)
else:
+ # We definitely have an Exception
try:
+ # Set the request body, and abort the current transaction.
+ try:
+ exception = ContextWrapper(exc_info[1], object)
+ name = getDefaultViewName(exception, request)
+ view = getView(exception, name, request)
+ response.setBody(self.callObject(request, view))
+ except ComponentLookupError:
+ # No view available for this exception, so let the
+ # response handle it.
+ response.handleException(exc_info)
+ except:
+ # Problem getting a view for this exception. Log an error.
+ tryToLogException(
+ 'Exception while getting view on exception')
+ # So, let the response handle it.
+ response.handleException(exc_info)
+ finally:
+ # Definitely abort the transaction that raised the exception.
+ get_transaction().abort()
+
+ # New transaction for side-effects
+ beginErrorHandlingTransaction(request)
+ transaction_ok = False
+
+ # Record the error with the ErrorReportingService
+ try:
+ errService = queryService(object, ErrorReports)
+ if errService is not None:
errService.raising(exc_info, request)
# It is important that an error in errService.raising
# does not propagate outside of here. Otherwise, nothing
@@ -183,64 +237,71 @@
# error handling that this error occurred while using
# the ErrorReportingService, and that it will be in
# the zope log.
- except:
- logging.getLogger('SiteError').exception(
- 'Error while reporting an error to the '
- 'ErrorReportingService')
-
- # Delegate Unauthorized errors to the authentication service
- # XXX Is this the right way to handle Unauthorized? We need
- # to understand this better.
- if isinstance(exc_info[1], Unauthorized):
- sm = getSecurityManager()
- id = sm.getPrincipal()
- prin_reg.unauthorized(id, request) # May issue challenge
- request.response.handleException(exc_info)
- return
-
- # XXX This is wrong. Should use getRequstView:
- #
- #
- # # Look for a component to handle the exception.
- # traversed = request.traversed
- # if traversed:
- # context = traversed[-1]
- # #handler = getExceptionHandler(context, t, IBrowserPublisher)
- # handler = None # no getExceptionHandler() exists yet.
- # if handler is not None:
- # handler(request, exc_info)
- # return
- # Convert ConflictErrors to Retry exceptions.
- if retry_allowed and isinstance(exc_info[1], ConflictError):
- #XXX this code path needs a unit test
- logging.getLogger('ZopePublication').warn(
- 'Competing writes/reads at %s',
- request.get('PATH_INFO', '???'),
- exc_info=True)
- raise Retry
+ except:
+ tryToLogException(
+ 'Error while reporting an error to the %s service' %
+ ErrorReports)
+ get_transaction().abort()
+ beginErrorHandlingTransaction(request)
+
+ if legacy_exception:
+ # There should be nothing of consequence done in this transaction,
+ # but this allows the error reporting service to save things
+ # persistently when we get a legacy exception.
+ get_transaction().commit()
+ else:
+ # See if there's an IExceptionSideEffects adapter for the
+ # exception
+ try:
+ adapter = getAdapter(exception, IExceptionSideEffects)
+ # view_presented is None if no view was presented, or the name
+ # of the view, if it was.
+ # Although request is passed in here, it should be considered
+ # read-only.
+ adapter(object, request, exc_info)
+ get_transaction().commit()
+ except:
+ get_transaction().abort()
- # Let the response handle it as best it can.
- # XXX Is this what we want in the long term?
- request.response.handleException(exc_info)
return
def _parameterSetskin(self, pname, pval, request):
request.setViewSkin(pval)
-class DebugPublication(object):
-
- class call_wrapper:
-
- def __init__(self, ob):
- self.__ob = ob
-
- def __getattr__(self, name):
- return getattr(self.__ob, name)
+def tryToLogException(arg1, arg2=None):
+ if arg2 is None:
+ subsystem = 'SiteError'
+ message = arg1
+ else:
+ subsystem = arg1
+ message = arg2
+ try:
+ logging.getLogger(subsystem).exception(message)
+ # Bare except, because we want to swallow any exception raised while
+ # logging an exception.
+ except:
+ pass
- def __call__(self, *args, **kw):
- self.__ob(*args, **kw)
+def tryToLogWarning(arg1, arg2=None, exc_info=False):
+ if arg2 is None:
+ subsystem = 'SiteError'
+ message = arg1
+ else:
+ subsystem = arg1
+ message = arg2
+ try:
+ logging.getLogger(subsystem).warn(message, exc_info=exc_info)
+ # Bare except, because we want to swallow any exception raised while
+ # logging a warning.
+ except:
+ pass
- def callObject(self, request, ob):
- return mapply(self.call_wrapper(ob),
- request.getPositionalArguments(), request)
+def beginErrorHandlingTransaction(request):
+ get_transaction().begin()
+ if IHTTPRequest.isImplementedBy(request):
+ pathnote = '%s ' % request["PATH_INFO"]
+ else:
+ pathnote = ''
+ get_transaction().note(
+ '%s(application error handling)' % pathnote)
=== Removed File Zope3/src/zope/app/publication/configure.zcml ===