[Zope-Checkins] SVN: Zope/branches/publication-refactor/lib/python/
Refactor some of the Zope2 traversal. This includes using
Michael Kerrin
michael.kerrin at openapp.biz
Fri Apr 21 10:20:06 EDT 2006
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
More information about the Zope-Checkins
mailing list