[Checkins] SVN: Zope/branches/publication-refactor/lib/python/ZPublisher/ Replace the ZPublisher.Publish.publish method with the

Michael Kerrin michael.kerrin at openapp.biz
Thu Apr 20 12:18:17 EDT 2006


Log message for revision 67177:
  Replace the ZPublisher.Publish.publish method with the
  Zope3 equivalent zope.publisher.publish. This way the
  publish_module_standard and similar are just wrappers
  around the Zope3 method that sets up the request correctly
  and performs some other stuff I don't quite follow.
  
  There is still a lot of work left, for example 11 tests are
  still failing but we can get back to these later.
  

Changed:
  U   Zope/branches/publication-refactor/lib/python/ZPublisher/BaseRequest.py
  U   Zope/branches/publication-refactor/lib/python/ZPublisher/BaseResponse.py
  U   Zope/branches/publication-refactor/lib/python/ZPublisher/HTTPResponse.py
  U   Zope/branches/publication-refactor/lib/python/ZPublisher/Publication.py
  U   Zope/branches/publication-refactor/lib/python/ZPublisher/Publish.py
  U   Zope/branches/publication-refactor/lib/python/ZPublisher/Test.py
  U   Zope/branches/publication-refactor/lib/python/ZPublisher/tests/testPublish.py

-=-
Modified: Zope/branches/publication-refactor/lib/python/ZPublisher/BaseRequest.py
===================================================================
--- Zope/branches/publication-refactor/lib/python/ZPublisher/BaseRequest.py	2006-04-20 15:19:17 UTC (rev 67176)
+++ Zope/branches/publication-refactor/lib/python/ZPublisher/BaseRequest.py	2006-04-20 16:18:16 UTC (rev 67177)
@@ -249,10 +249,6 @@
         if not path and not method:
             return response.forbiddenError(self['URL'])
 
-        if self.publication.root is not object:
-            self.publication.root = object
-
-        object = self.publication.getApplication(self)
         roles = getRoles(None, None, object, UNSPECIFIED_ROLES)
         parents.append(object)
 

Modified: Zope/branches/publication-refactor/lib/python/ZPublisher/BaseResponse.py
===================================================================
--- Zope/branches/publication-refactor/lib/python/ZPublisher/BaseResponse.py	2006-04-20 15:19:17 UTC (rev 67176)
+++ Zope/branches/publication-refactor/lib/python/ZPublisher/BaseResponse.py	2006-04-20 16:18:16 UTC (rev 67177)
@@ -54,6 +54,10 @@
         """Output the response body"""
         self.stdout.write(str(self))
 
+    def setResult(self, result):
+        """IResponse"""
+        self.setBody(result)
+
     def setBody(self, body):
         self.body = body
 

Modified: Zope/branches/publication-refactor/lib/python/ZPublisher/HTTPResponse.py
===================================================================
--- Zope/branches/publication-refactor/lib/python/ZPublisher/HTTPResponse.py	2006-04-20 15:19:17 UTC (rev 67176)
+++ Zope/branches/publication-refactor/lib/python/ZPublisher/HTTPResponse.py	2006-04-20 16:18:16 UTC (rev 67177)
@@ -180,6 +180,10 @@
         self.stdout = stdout
         self.stderr = stderr
 
+    def internalError(self):
+        'See IPublisherResponse'
+        self.setStatus(500, u"The engines can't take any more, Jim!")
+
     def retry(self):
         """Return a response object to be used in a retry attempt
         """

Modified: Zope/branches/publication-refactor/lib/python/ZPublisher/Publication.py
===================================================================
--- Zope/branches/publication-refactor/lib/python/ZPublisher/Publication.py	2006-04-20 15:19:17 UTC (rev 67176)
+++ Zope/branches/publication-refactor/lib/python/ZPublisher/Publication.py	2006-04-20 16:18:16 UTC (rev 67177)
@@ -15,12 +15,14 @@
 import re
 import sys
 import transaction
+import types
 
 from zope.event import notify
 from zope.component import queryUtility
 from zope.interface import implements
 from zope.publisher.interfaces import IRequest, IPublication
 from zope.publisher.interfaces import NotFound, IPublicationRequest
+import zope.publisher.interfaces
 from zope.publisher.browser import BrowserRequest
 from zope.publisher.browser import BrowserResponse
 from zope.publisher.http import StrResult
@@ -35,14 +37,42 @@
 from ZPublisher.mapply import mapply
 from ZPublisher.BaseRequest import RequestContainer
 
+from ZPublisher.HTTPRequest import HTTPRequest
+from ZPublisher.HTTPResponse import HTTPResponse
+from cStringIO import StringIO
+import traceback
+from zope.publisher.http import status_reasons, DirectResult
+from zope.publisher.interfaces import IPublisherRequest
+from zope import component
+
+
 _marker = object()
 
+class Zope3HTTPRequestTraverser(object):
+    implements(IPublisherRequest)
+
+    def __init__(self, request):
+        self.request = request
+
+    def traverse(self, object):
+        path = self.request.get('PATH_INFO')
+        self.request['PARENTS'] = [object]
+
+        return self.request.traverse(path, self.request.response,
+                                     self.request.publication.validated_hook)
+
+## XXX - Five declares that HTTPRequest implements IPublisherRequest
+## but in fact it doesn't, the traverse method API is all wrong.
+## component.provideAdapter(Zope3HTTPRequestTraverser, (HTTPRequest,),
+##                          IPublisherRequest)
+
+
 class ZopePublication(object):
     """Base Zope2 publication specification.
     """
     implements(IPublication)
 
-    def __init__(self, db=None, module_name="Zope2"):
+    def __init__(self, db = None, module_name = "Zope2"):
         # db is a ZODB.DB.DB object.
         # XXX We don't use this yet.
         self.db = db
@@ -58,6 +88,18 @@
          self.transactions_manager) = get_module_info(self.module_name)
 
     def beforeTraversal(self, request):
+        # First check for "cancel" redirect:
+        if request.get('SUBMIT','').strip().lower()=='cancel':
+            # XXX Deprecate this, the Zope 2+3 publication won't support it.
+            cancel = request.get('CANCEL_ACTION','')
+            if cancel:
+                raise Redirect, cancel
+
+        if self.debug_mode:
+            request.response.debug_mode = self.debug_mode
+        if self.realm and not request.get('REMOTE_USER', None):
+            request.response.realm = self.realm
+
         # First part of old ZPublisher.Publish.publish. Call
         # 'bobo_before' hooks and start a new transaction using the
         # 'transaction_manager'.
@@ -121,8 +163,9 @@
         result = mapply(ob, args,
                         request, call_object, 1, missing_name,
                         dont_publish_class, request, bind=1)
-        if isinstance(request, Zope2BrowserRequest):
-            return StrResult(str(result))
+        ## XXX - what the hell is this.
+        ## if isinstance(request, Zope2BrowserRequest):
+        ##     return StrResult(str(result))
         return result
 
     def afterCall(self, request, ob):
@@ -152,6 +195,18 @@
             self.transactions_manager.abort()
 
     def handleException(self, object, request, exc_info, retry_allowed=True):
+        if isinstance(object, types.ListType):
+            object = object[0]
+
+        # DM: provide nicer error message for FTP
+        sm = getattr(request.response, "setMessage", None)
+        if sm is not None:
+            from asyncore import compact_traceback
+            cl,val= sys.exc_info()[:2]
+            sm('%s: %s %s' % (
+                getattr(cl,'__name__',cl), val,
+                debug_mode and compact_traceback()[-1] or ''))
+
         # Some exception handling from ZPublisher.Publish.publish().
         if self.err_hook is None:
             self._abort()
@@ -165,9 +220,9 @@
                                      exc_info[1],
                                      exc_info[2],
                                      )
-            except Retry:
+            except Retry, retry_exception:
                 if retry_allowed:
-                    raise
+                    raise zope.publisher.interfaces.Retry(sys.exc_info)
                 return self.err_hook(object, request,
                                      sys.exc_info()[0],
                                      sys.exc_info()[1],
@@ -244,168 +299,7 @@
                                                      module_name=module_name)
     return _publications[module_name]
 
-tr = {'environ': '_environ',
-      'TraversalRequestNameStack': '_traversal_stack',
-      'RESPONSE': 'response'}
 
-class Zope2BrowserResponse(BrowserResponse):
-
-    def badRequestError(self, name):
-        raise KeyError, name
-
-    def _headers(self):
-        return dict(self.getHeaders())
-
-    headers = property(_headers)
-
-class Zope2BrowserRequest(BrowserRequest):
-
-    # Zope 2 compatibility XXX Deprecate!
-    def get_header(self, name, default=None):
-        return self.getHeader(name, default)
-
-    def __init__(self, *args, **kw):
-        self.other = {'PARENTS':[]}
-        self._lazies = {}
-        self._file = None
-        self._urls = []
-        BrowserRequest.__init__(self, *args, **kw)
-
-    def _createResponse(self):
-        return Zope2BrowserResponse()
-
-    def set_lazy(self, name, func):
-        self._lazies[name] = func
-
-    _hold = BrowserRequest.hold
-
-    def __getitem__(self, key, default=_marker):
-        v = self.get(key, default)
-        if v is _marker:
-            raise KeyError, key
-        return v
-
-    def __getattr__(self, key, default=_marker):
-        v = self.get(key, default)
-        if v is _marker:
-            raise AttributeError, key
-        return v
-
-    def traverse(self, object):
-        ob = super(Zope2BrowserRequest, self).traverse(object)
-        self.other['PARENTS'].append(ob)
-        return ob
-
-    def set(self, key, value):
-        self.other[key] = value
-
-    def get(self, key, default=None, returnTaints=0,
-            URLmatch=re.compile('URL(PATH)?([0-9]+)$').match,
-            BASEmatch=re.compile('BASE(PATH)?([0-9]+)$').match,
-            ):
-        """Get a variable value
-
-        Return a value for the required variable name.
-        The value will be looked up from one of the request data
-        categories. The search order is environment variables,
-        other variables, form data, and then cookies.
-
-        """
-        from ZPublisher.HTTPRequest import isCGI_NAME, hide_key
-
-        if (key in ('other', '_file',
-                    '_lazies', '_urls') or tr.has_key(key)):
-            key = tr.get(key, key)
-            return object.__getattribute__(self, key)
-
-        if key == 'REQUEST': return self
-
-        other = self.other
-        if other.has_key(key):
-            return other[key]
-
-        if key[:1]=='U':
-            match = URLmatch(key)
-            if match is not None:
-                pathonly, n = match.groups()
-                path = self._traversed_names
-                n = len(path) - int(n)
-                if n < 0:
-                    raise KeyError, key
-                if pathonly:
-                    path = [''] + path[:n]
-                else:
-                    path = [self['SERVER_URL']] + path[:n]
-                URL = '/'.join(path)
-                if other.has_key('PUBLISHED'):
-                    # Don't cache URLs until publishing traversal is done.
-                    other[key] = URL
-                    self._urls = self._urls + (key,)
-                return URL
-
-        if isCGI_NAME(key) or key[:5] == 'HTTP_':
-            environ = self.environ
-            if environ.has_key(key) and (not hide_key(key)):
-                return environ[key]
-            return ''
-
-        if key[:1]=='B':
-            match = BASEmatch(key)
-            if match is not None:
-                pathonly, n = match.groups()
-                path = self._traversed_names
-                n = int(n)
-                if n:
-                    n = n - 1
-                    if len(path) < n:
-                        raise KeyError, key
-
-                    v = path[:n]
-                else:
-                    v = ['']
-                if pathonly:
-                    v.insert(0, '')
-                else:
-                    v.insert(0, other['SERVER_URL'])
-                URL = '/'.join(v)
-                if other.has_key('PUBLISHED'):
-                    # Don't cache URLs until publishing traversal is done.
-                    other[key] = URL
-                    self._urls = self._urls + (key,)
-                return URL
-
-            if key=='BODY' and self._file is not None:
-                p=self._file.tell()
-                self._file.seek(0)
-                v=self._file.read()
-                self._file.seek(p)
-                self.other[key]=v
-                return v
-
-            if key=='BODYFILE' and self._file is not None:
-                v=self._file
-                self.other[key]=v
-                return v
-
-        if self._lazies:
-            v = self._lazies.get(key, _marker)
-            if v is not _marker:
-                if callable(v): v = v()
-                self[key] = v                   # Promote lazy value
-                del self._lazies[key]
-                return v
-
-        v = super(Zope2BrowserRequest, self).get(key, _marker)
-        if v is not _marker: return v
-
-        return default
-    
-from ZPublisher.HTTPRequest import HTTPRequest
-from ZPublisher.HTTPResponse import HTTPResponse
-from cStringIO import StringIO
-import traceback
-from zope.publisher.http import status_reasons, DirectResult
-
 class Zope2HTTPResponse(HTTPResponse):
     
     def setResult(self, result):
@@ -429,20 +323,6 @@
         'See IPublisherResponse'
         self.setStatus(500, u"The engines can't take any more, Jim!")
 
-    def reset(self):
-        """Reset the output result.
-
-        Reset the response by nullifying already set variables.
-        """
-        raise Exception
-
-    def retry(self):
-        """Returns a retry response
-
-        Returns a response suitable for repeating the publication attempt.
-        """
-        raise Exception
-
     def getStatusString(self):
         'See IHTTPResponse'
         return '%i %s' % (self.status, status_reasons[self.status])
@@ -455,19 +335,20 @@
     
 
 class Zope2HTTPRequest(HTTPRequest):
-    
+
     def supportsRetry(self):
         return False
-    
+
     def traverse(self, object):
         path = self.get('PATH_INFO')
         self['PARENTS'] = [self.publication.root]
+
         return HTTPRequest.traverse(self, path)
 
 
 def Zope2RequestFactory(sin, env):
     response=Zope2HTTPResponse() 
-    return Zope2HTTPRequest(sin, env, response)
+    return HTTPRequest(sin, env, response)
 
 class Zope2HTTPFactory(object):
 
@@ -477,5 +358,4 @@
         return True
 
     def __call__(self):
-
         return Zope2RequestFactory, ZopePublication

Modified: Zope/branches/publication-refactor/lib/python/ZPublisher/Publish.py
===================================================================
--- Zope/branches/publication-refactor/lib/python/ZPublisher/Publish.py	2006-04-20 15:19:17 UTC (rev 67176)
+++ Zope/branches/publication-refactor/lib/python/ZPublisher/Publish.py	2006-04-20 16:18:16 UTC (rev 67177)
@@ -164,42 +164,50 @@
     status=200
     after_list=[None]
     try:
-        try:
-            if response is None:
-                response=Response(stdout=stdout, stderr=stderr)
-            else:
-                stdout=response.stdout
+        if response is None:
+            response=Response(stdout=stdout, stderr=stderr)
+        else:
+            stdout=response.stdout
 
-            if request is None:
-                request=Request(stdin, environ, response)
+        if request is None:
+            request=Request(stdin, environ, response)
 
-            response = publish(request, module_name, after_list, debug=debug)
-        except SystemExit, v:
+        # We assume the publication object returned is the one in
+        # ZPublisher.Publication here so we don't bother using accessors
+        # and poke directly into the variables.
+        from ZPublisher.Publication import get_publication
+        publication = get_publication(module_name)
+        request.setPublication(publication)
+
+        from zope.publisher.publish import publish as publish3
+        publish3(request)
+    except SystemExit, v:
+        must_die=sys.exc_info()
+        request.response.exception(must_die)
+    except ImportError, v:
+        if isinstance(v, tuple) and len(v) == 3:
+            must_die=v
+        elif hasattr(sys, 'exc_info'):
             must_die=sys.exc_info()
-            request.response.exception(must_die)
-        except ImportError, v:
-            if isinstance(v, tuple) and len(v)==3: must_die=v
-            elif hasattr(sys, 'exc_info'): must_die=sys.exc_info()
-            else: must_die = SystemExit, v, sys.exc_info()[2]
-            request.response.exception(1, v)
-        except:
-            request.response.exception()
-            status=response.getStatus()
+        else:
+            must_die = SystemExit, v, sys.exc_info()[2]
+        request.response.exception(1, v)
+    except:
+        request.response.exception()
+        status=response.getStatus()
 
-        if response:
-            outputBody=getattr(response, 'outputBody', None)
-            if outputBody is not None:
-                outputBody()
-            else:
-                response=str(response)
-                if response: stdout.write(response)
+    if request.response:
+        outputBody=getattr(request.response, 'outputBody', None)
+        if outputBody is not None:
+            outputBody()
+        else:
+            response=str(request.response)
+            if response:
+                stdout.write(response)
 
         # The module defined a post-access function, call it
         if after_list[0] is not None: after_list[0]()
 
-    finally:
-        if request is not None: request.close()
-
     if must_die:
         # Try to turn exception value into an exit code.
         try:

Modified: Zope/branches/publication-refactor/lib/python/ZPublisher/Test.py
===================================================================
--- Zope/branches/publication-refactor/lib/python/ZPublisher/Test.py	2006-04-20 15:19:17 UTC (rev 67176)
+++ Zope/branches/publication-refactor/lib/python/ZPublisher/Test.py	2006-04-20 16:18:16 UTC (rev 67177)
@@ -180,39 +180,39 @@
     after_list=[None]
     from Response import Response
     from Request import Request
-    from Publish import publish
+    from Publication import get_publication
+    # from Publish import publish
+    from zope.publisher.publish import publish
     try:
-        try:
-            if response is None:
-                response=Response(stdout=stdout, stderr=stderr)
-            else:
-                stdout=response.stdout
-            if request is None:
-                request=Request(stdin, environ, response)
-            for k, v in extra.items(): request[k]=v
-            response = publish(request, module_name, after_list, debug=debug)
-        except SystemExit, v:
-            must_die=sys.exc_info()
-            response.exception(must_die)
-        except ImportError, v:
-            if isinstance(v, TupleType) and len(v)==3: must_die=v
-            else: must_die=sys.exc_info()
-            response.exception(1, v)
-        except:
-            if debug:
-                raise
-            response.exception()
-            status=response.getStatus()
-        if response:
-            response=str(response)
-        if response: stdout.write(response)
+        if response is None:
+            response=Response(stdout=stdout, stderr=stderr)
+        else:
+            stdout=response.stdout
+        if request is None:
+            request=Request(stdin, environ, response)
+        request.setPublication(get_publication())
+        for k, v in extra.items(): request[k]=v
+        response = request.response
+        publish(request) #, module_name, after_list, debug=debug)
+    except SystemExit, v:
+        must_die=sys.exc_info()
+        response.exception(must_die)
+    except ImportError, v:
+        if isinstance(v, TupleType) and len(v)==3: must_die=v
+        else: must_die=sys.exc_info()
+        response.exception(1, v)
+    except:
+        if debug:
+            raise
+        response.exception()
+        status=response.getStatus()
+    if response:
+        response=str(response)
+    if response: stdout.write(response)
 
-        # The module defined a post-access function, call it
-        if after_list[0] is not None: after_list[0]()
+    # The module defined a post-access function, call it
+    if after_list[0] is not None: after_list[0]()
 
-    finally:
-        if request is not None: request.close()
-
     if must_die:
         try: raise must_die[0], must_die[1], must_die[2]
         finally: must_die=None

Modified: Zope/branches/publication-refactor/lib/python/ZPublisher/tests/testPublish.py
===================================================================
--- Zope/branches/publication-refactor/lib/python/ZPublisher/tests/testPublish.py	2006-04-20 15:19:17 UTC (rev 67176)
+++ Zope/branches/publication-refactor/lib/python/ZPublisher/tests/testPublish.py	2006-04-20 16:18:16 UTC (rev 67177)
@@ -79,9 +79,21 @@
     """Mock Response to replace ZPublisher.HTTPResponse.HTTPResponse.
     """
 
+    def internalError(self):
+        'See IPublisherResponse'
+        self.setStatus(500, u"The engines can't take any more, Jim!")
+
+    def setStatus(self, status, reason):
+        self.status = status
+
     def setBody(self, a):
         pass
 
+    def exception(self, fatal = 0, info = None):
+        pass
+
+    setResult = setBody
+
 class Request:
     """Mock Request to replace ZPublisher.HTTPRequest.HTTPRequest.
     """
@@ -90,6 +102,8 @@
 
     def __init__(self):
         self.response = Response()
+        from ZPublisher.Publication import get_publication
+        self.publication = get_publication('ZPublisher.tests.testPublish')
 
     def setPublication(self, publication):
         self.publication = publication
@@ -103,7 +117,7 @@
     def __setitem__(self, name, value):
         pass
 
-    def traverse(self, path, validated_hook):
+    def traverse(self, path, response = None, validated_hook = None):
         return Object()
 
     def close(self):
@@ -115,6 +129,8 @@
     def supports_retry(self):
         return self.retry_count < self.retry_max_count
 
+    supportsRetry = supports_retry
+
     def retry(self):
         self.retry_count += 1
         r = self.__class__()
@@ -130,14 +146,14 @@
     Tests to ensure that the ZPublisher correctly manages the ZODB
     transaction boundaries.
 
-    >>> from ZPublisher.Publish import publish
+    >>> from zope.publisher.publish import publish
 
     ZPublisher will commit the transaction after it has made a
     rendering of the object.
 
     >>> tracer.reset()
     >>> request = Request()
-    >>> response = publish(request, module_name, after_list)
+    >>> response = publish(request)
     >>> tracer.showTracedPath()
     begin
     __call__
@@ -153,7 +169,7 @@
     >>> tracer.reset()
     >>> tracer.exceptions['__call__'] = [ValueError]
     >>> request = Request()
-    >>> response = publish(request, module_name, after_list)
+    >>> response = publish(request)
     >>> tracer.showTracedPath()
     begin
     __call__
@@ -169,7 +185,7 @@
     >>> tracer.exceptions['__call__'] = [ValueError]
     >>> tracer.exceptions['zpublisher_exception_hook'] = [ValueError]
     >>> request = Request()
-    >>> response = publish(request, module_name, after_list)
+    >>> response = publish(request, False)
     Traceback (most recent call last):
     ...
     ValueError
@@ -190,7 +206,7 @@
     >>> tracer.reset()
     >>> tracer.exceptions['__call__'] = [ConflictError]
     >>> request = Request()
-    >>> response = publish(request, module_name, after_list)
+    >>> response = publish(request)
     >>> tracer.showTracedPath()
     begin
     __call__
@@ -207,7 +223,7 @@
     >>> tracer.reset()
     >>> tracer.exceptions['commit'] = [ConflictError]
     >>> request = Request()
-    >>> response = publish(request, module_name, after_list)
+    >>> response = publish(request)
     >>> tracer.showTracedPath()
     begin
     __call__
@@ -225,7 +241,7 @@
     >>> tracer.exceptions['__call__'] = [ConflictError, ConflictError,
     ...                                  ConflictError, ConflictError]
     >>> request = Request()
-    >>> response = publish(request, module_name, after_list)
+    >>> response = publish(request, False)
     Traceback (most recent call last):
     ...
     ConflictError: database conflict error
@@ -254,7 +270,7 @@
     >>> tracer.exceptions['__call__'] = [ValueError]
     >>> tracer.exceptions['zpublisher_exception_hook'] = [ConflictError]
     >>> request = Request()
-    >>> response = publish(request, module_name, after_list)
+    >>> response = publish(request, False)
     Traceback (most recent call last):
     ...
     ConflictError: database conflict error



More information about the Checkins mailing list