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 _______________________________________________ Zope-Checkins maillist - Zope-Checkins@zope.org http://mail.zope.org/mailman/listinfo/zope-checkins