Log message for revision 67219: Refactor some of the Zope2 traversal. This includes using IPublishTraverse to do the traversal, and using Zope3 to find the views.
Changed: U Zope/branches/publication-refactor/lib/python/Products/Five/configure.zcml U Zope/branches/publication-refactor/lib/python/ZPublisher/BaseRequest.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 -=- Modified: Zope/branches/publication-refactor/lib/python/Products/Five/configure.zcml =================================================================== --- Zope/branches/publication-refactor/lib/python/Products/Five/configure.zcml 2006-04-21 14:18:10 UTC (rev 67218) +++ Zope/branches/publication-refactor/lib/python/Products/Five/configure.zcml 2006-04-21 14:20:05 UTC (rev 67219) @@ -60,4 +60,11 @@ provides="zope.publisher.interfaces.ITraversingRequest" /> + <adapter + for="* + .interfaces.IZope2Request" + provides="zope.publisher.interfaces.IPublishTraverse" + factory="ZPublisher.Publication.Zope2PublishTraverseAdapter" + /> + </configure> Modified: Zope/branches/publication-refactor/lib/python/ZPublisher/BaseRequest.py =================================================================== --- Zope/branches/publication-refactor/lib/python/ZPublisher/BaseRequest.py 2006-04-21 14:18:10 UTC (rev 67218) +++ Zope/branches/publication-refactor/lib/python/ZPublisher/BaseRequest.py 2006-04-21 14:20:05 UTC (rev 67219) @@ -230,16 +230,9 @@ if method=='GET' or method=='POST' and not isinstance(response, xmlrpc.Response): - # Probably a browser - no_acquire_flag=0 # index_html is still the default method, only any object can # override it by implementing its own __browser_default__ method method = 'index_html' - elif self.maybe_webdav_client: - # Probably a WebDAV client. - no_acquire_flag=1 - else: - no_acquire_flag=0 URL=request['URL'] parents = request['PARENTS'] @@ -315,7 +308,7 @@ try: subobject = self.publication.traverseName( - self, object, entry_name, no_acquire_flag) + self, object, entry_name) except NotFound: if debug_mode: return response.debugError( @@ -323,30 +316,6 @@ else: return response.notFoundError(URL) - # Ensure that the object has a docstring, or that the parent - # object has a pseudo-docstring for the object. Objects that - # have an empty or missing docstring are not published. - doc = getattr(subobject, '__doc__', None) - if doc is None: - doc = getattr(object, '%s__doc__' % entry_name, None) - if not doc: - return response.debugError( - "The object at %s has an empty or missing " \ - "docstring. Objects must have a docstring to be " \ - "published." % URL - ) - - # Hack for security: in Python 2.2.2, most built-in types - # gained docstrings that they didn't have before. That caused - # certain mutable types (dicts, lists) to become publishable - # when they shouldn't be. The following check makes sure that - # the right thing happens in both 2.2.2+ and earlier versions. - - if not typeCheck(subobject): - return response.debugError( - "The object at %s is not publishable." % URL - ) - roles = getRoles( object, (not got) and entry_name or None, subobject, roles) Modified: Zope/branches/publication-refactor/lib/python/ZPublisher/Publication.py =================================================================== --- Zope/branches/publication-refactor/lib/python/ZPublisher/Publication.py 2006-04-21 14:18:10 UTC (rev 67218) +++ Zope/branches/publication-refactor/lib/python/ZPublisher/Publication.py 2006-04-21 14:20:05 UTC (rev 67219) @@ -16,9 +16,10 @@ import sys import transaction import types +import xmlrpc from zope.event import notify -from zope.component import queryUtility +from zope.component import queryUtility, queryMultiAdapter from zope.interface import implements from zope.publisher.interfaces import IRequest, IPublication from zope.publisher.interfaces import NotFound, IPublicationRequest @@ -30,12 +31,16 @@ from zope.app.publication.interfaces import BeforeTraverseEvent from zope.app.publication.interfaces import IBrowserRequestFactory from zope.app.publication.interfaces import IRequestPublicationFactory +from zope.app.traversing.namespace import nsParse +from zope.app.traversing.namespace import namespaceLookup +from zope.app.traversing.interfaces import TraversalError from ZPublisher.Publish import Retry from ZPublisher.Publish import get_module_info, call_object from ZPublisher.Publish import missing_name, dont_publish_class from ZPublisher.mapply import mapply from ZPublisher.BaseRequest import RequestContainer +from ZPublisher.BaseRequest import typeCheck from ZPublisher.HTTPRequest import HTTPRequest from ZPublisher.HTTPResponse import HTTPResponse @@ -234,7 +239,76 @@ # request supports retry. It's not clear how this will be # handled by Zope 3. - def traverseName(self, request, ob, name, acquire=True): + def traverseName(self, request, ob, name): + nm = name # the name to look up the object with + + if name and name[:1] in '@+': + # Process URI segment parameters. + ns, nm = nsParse(name) + if ns: + try: + ob2 = namespaceLookup(ns, nm, ob, request) + except TraversalError: + raise NotFound(ob, name) + + return ob2 + + if nm == '.': + return ob + + if zope.publisher.interfaces.IPublishTraverse.providedBy(ob): + ob2 = ob.publishTraverse(request, nm) + else: + # self is marker + adapter = queryMultiAdapter((ob, request), + zope.publisher.interfaces.IPublishTraverse, + default = self) + if adapter is self: + ## Zope2 doesn't set up its own adapters in a lot of cases + ## so we will just use a default adapter. + adapter = Zope2PublishTraverseAdapter(ob, request) + + ob2 = adapter.publishTraverse(request, nm) + + return ob2 + + def getDefaultTraversal(self, request, ob): + if hasattr(ob, '__browser_default__'): + return object.__browser_default__(request) + if getattr(ob, 'index_html', None): + return ob, ['index_html'] + return ob, [] + +_publications = {} +def get_publication(module_name=None): + if module_name is None: + module_name = "Zope2" + if not _publications.has_key(module_name): + _publications[module_name] = ZopePublication(db=None, + module_name=module_name) + return _publications[module_name] + + +class Zope2PublishTraverseAdapter(object): + implements(zope.publisher.interfaces.IPublishTraverse) + + def __init__(self, context, request): + self.context = context + + def subObject(self, request, ob, name): + # How did this request come in? (HTTP GET, PUT, POST, etc.) + method = request.get('REQUEST_METHOD', 'GET').upper() + + if method == 'GET' or method == 'POST' and \ + not isinstance(request.response, xmlrpc.Response): + # Probably a browser + no_acquire_flag=0 + elif request.maybe_webdav_client: + # Probably a WebDAV client. + no_acquire_flag=1 + else: + no_acquire_flag=0 + if hasattr(ob, '__bobo_traverse__'): try: subob = ob.__bobo_traverse__(request, name) @@ -264,7 +338,7 @@ # an object 'test' existed above it in the # heirarchy -- you'd always get the # existing object :( - if (acquire and hasattr(ob, 'aq_base')): + if (no_acquire_flag and hasattr(ob, 'aq_base')): if hasattr(ob.aq_base, name): return getattr(ob, name) else: @@ -272,30 +346,41 @@ else: return getattr(ob, name) except AttributeError: - got = 1 try: return ob[name] except (KeyError, IndexError, TypeError, AttributeError): raise NotFound(ob, name) + + def publishTraverse(self, request, name): + subobject = self.subObject(request, self.context, name) - def getDefaultTraversal(self, request, ob): - if hasattr(ob, '__browser_default__'): - return object.__browser_default__(request) - if getattr(ob, 'index_html', None): - return ob, ['index_html'] - return ob, [] + # Ensure that the object has a docstring, or that the parent + # object has a pseudo-docstring for the object. Objects that + # have an empty or missing docstring are not published. + doc = getattr(subobject, '__doc__', None) + if doc is None: + doc = getattr(object, '%s__doc__' % entry_name, None) + if not doc: + return request.response.debugError( + "The object at %s has an empty or missing " \ + "docstring. Objects must have a docstring to be " \ + "published." % URL + ) -_publications = {} -def get_publication(module_name=None): - if module_name is None: - module_name = "Zope2" - if not _publications.has_key(module_name): - _publications[module_name] = ZopePublication(db=None, - module_name=module_name) - return _publications[module_name] + # Hack for security: in Python 2.2.2, most built-in types + # gained docstrings that they didn't have before. That caused + # certain mutable types (dicts, lists) to become publishable + # when they shouldn't be. The following check makes sure that + # the right thing happens in both 2.2.2+ and earlier versions. + if not typeCheck(subobject): + return request.response.debugError( + "The object at %s is not publishable." % URL + ) + return subobject + class Zope2HTTPResponse(HTTPResponse): def setResult(self, result): Modified: Zope/branches/publication-refactor/lib/python/ZPublisher/Publish.py =================================================================== --- Zope/branches/publication-refactor/lib/python/ZPublisher/Publish.py 2006-04-21 14:18:10 UTC (rev 67218) +++ Zope/branches/publication-refactor/lib/python/ZPublisher/Publish.py 2006-04-21 14:20:05 UTC (rev 67219) @@ -21,6 +21,7 @@ from maybe_lock import allocate_lock from mapply import mapply from zExceptions import Redirect +from zope.app.publication.browser import setDefaultSkin class Retry(Exception): """Raise this to retry a request @@ -179,6 +180,11 @@ publication = get_publication(module_name) request.setPublication(publication) + # make sure that the request we hand over has the + # default layer/skin set on it; subsequent code that + # wants to look up views will likely depend on it + setDefaultSkin(request) + from zope.publisher.publish import publish as publish3 publish3(request) except SystemExit, v: Modified: Zope/branches/publication-refactor/lib/python/ZPublisher/Test.py =================================================================== --- Zope/branches/publication-refactor/lib/python/ZPublisher/Test.py 2006-04-21 14:18:10 UTC (rev 67218) +++ Zope/branches/publication-refactor/lib/python/ZPublisher/Test.py 2006-04-21 14:20:05 UTC (rev 67219) @@ -190,6 +190,11 @@ stdout=response.stdout if request is None: request=Request(stdin, environ, response) + # make sure that the request we hand over has the + # default layer/skin set on it; subsequent code that + # wants to look up views will likely depend on it + from zope.app.publication.browser import setDefaultSkin + setDefaultSkin(request) request.setPublication(get_publication()) for k, v in extra.items(): request[k]=v response = request.response _______________________________________________ Zope-Checkins maillist - Zope-Checkins@zope.org http://mail.zope.org/mailman/listinfo/zope-checkins