[Zope-Checkins] CVS: Zope/lib/python/ZPublisher - BaseRequest.py:1.39.20.6

Shane Hathaway shane@digicool.com
Thu, 25 Oct 2001 16:39:35 -0400


Update of /cvs-repository/Zope/lib/python/ZPublisher
In directory cvs.zope.org:/tmp/cvs-serv16082

Modified Files:
      Tag: ComponentArchitecture-branch
	BaseRequest.py 
Log Message:
Added DefaultBrowserPublish and cleaned up traverse() some more.
Also added _browser_renderable() but this will need review.


=== Zope/lib/python/ZPublisher/BaseRequest.py 1.39.20.5 => 1.39.20.6 ===
 from urllib import quote
 from cgi import escape
+from types import StringType
 
 UNSPECIFIED_ROLES=''
 
@@ -277,37 +278,39 @@
         return object, roles
 
     def _finalTraverse(self, object):
+        if hasattr(object, '_browser_renderable'):
+            object = object._browser_renderable()
         roles = UNSPECIFIED_ROLES
         if (hasattr(object, '__call__') and
             hasattr(object.__call__,'__roles__')):
             roles=object.__call__.__roles__
         return object, roles
 
-    def _addDefaultView(self, object, path, m_name='_browser_default'):
+    def _getDefaultView(self, object, m_name='_browser_default'):
         """
-        returns (object, entry_name)
+        returns (object, add_steps)
         """
         psteps = None
-        default = getattr(object, m_name, None)
-        if default is not None:
-            o, add_steps = default(self)
-            if add_steps:
-                if len(add_steps) > 1:
-                    # 2 or more steps added
-                    path.extend(add_steps[1:])
-                # 1 step added
-                return o, add_steps[0]
-            elif o is not object:
-                # no steps added but object changed.
-                return o, ()
+        f = getattr(object, m_name, None)
+        if f is not None:
+            v = f(self)
+            if v is not None:
+                if type(v) is StringType:
+                    # One more traversal step.
+                    return o, (v,)
+                else:
+                    # Arbitrary additional traversal.
+                    o, add_steps = v
+                    if add_steps or o is not object:
+                        return o, add_steps
         m = self._request_method
         if m == 'GET' or m == 'POST':
             default = 'index_html'
         else:
             default = m
         if default and getattr(object, default, None) is not None:
-            return object, default
-        return object, None
+            return object, (default,)
+        return object, ()
 
     def _traverseName(self, object, entry_name, m_name="__bobo_traverse__"):
         """
@@ -450,14 +453,13 @@
         The REQUEST must already have a PARENTS item with at least one
         object in it.  This is typically the root object.
         """
-        request = self
         checked_default = 0
         path = self._splitPath(path_str)
         self._setRequestMethod()
         if not path and not self._request_method:
             return self.response.forbiddenError(self['URL'])
         
-        parents=request['PARENTS']
+        parents=self['PARENTS']
         object=parents[-1]
         del parents[:]
         object, roles = self._initialTraverse(object)
@@ -466,54 +468,62 @@
         steps=self.steps
         self._steps = _steps = map(quote, steps)
         path.reverse()
-        request['TraversalRequestNameStack'] = request.path = path
+        self['TraversalRequestNameStack'] = self.path = path
 
-        entry_name = ''
+        prev_object = None
         try:
             # We build parents in the wrong order, so we
             # need to make sure we reverse it when we're doe.
             while 1:
-                hook = getattr(object, '__before_publishing_traverse__', None)
-                if hook is not None:
-                    hook(object, self)
+                if object is not prev_object:  # Don't call hooks twice
+                    hook = getattr(
+                        object, '__before_publishing_traverse__', None)
+                    if hook is not None:
+                        hook(object, self)
+                prev_object = object
 
-                path = self.path = self['TraversalRequestNameStack']
+                self.path = path = self['TraversalRequestNameStack']
                 if path:
+                    # Traverse to the next step.
                     entry_name = path.pop()
+                    if entry_name:
+                        step = quote(entry_name)
+                        _steps.append(step)
+                        self['URL'] = '%s/%s' % (self['URL'], step)
+                        try:
+                            object, r = self._traverseName(object, entry_name)
+                            if r is not UNSPECIFIED_ROLES:
+                                roles = r
+                        except StopTraversal, v:
+                            return v
+                        parents.append(object)
+                        steps.append(entry_name)
+
+                elif not checked_default:
+                    # Traverse to the default view, if any.
+                    checked_default = 1
+                    object, add_steps = self._getDefaultView(object)
+                    if add_steps:
+                        path.extend(add_steps)
+                        self._hacked_path = 1
+
                 else:
-                    entry_name = None
-                    if not checked_default:
-                        object, entry_name = self._addDefaultView(object, path)
-                        checked_default = 1
-                        if entry_name:
-                            self._hacked_path = 1
-                    if not entry_name:
-                        # Finished traversal.
-                        object, r = self._finalTraverse(object)
-                        if r is not UNSPECIFIED_ROLES:
-                            roles = r
-                        if self._hacked_path:
-                            URL = self['URL']
-                            i=rfind(URL,'/')
-                            if i > 0: self.response.setBase(URL[:i])
-                        break
-                if not entry_name:
-                    continue
-                step = quote(entry_name)
-                _steps.append(step)
-                request['URL'] = '%s/%s' % (request['URL'], step)
-                try:
-                    object, r = self._traverseName(object, entry_name)
-                    if r is not UNSPECIFIED_ROLES:
-                        roles = r
-                except StopTraversal, v:
-                    return v
-                parents.append(object)
-                steps.append(entry_name)
+                    # Finished traversal.
+                    break
+
+            object, r = self._finalTraverse(object)
+            if r is not UNSPECIFIED_ROLES:
+                roles = r
+            if self._hacked_path:
+                URL = self['URL']
+                i = rfind(URL,'/')
+                if i > 0:
+                    self.response.setBase(URL[:i])
+
         finally:
             parents.reverse()
 
-        request['PUBLISHED'] = parents.pop(0)
+        self['PUBLISHED'] = object
 
         # Do authorization checks
         self._checkAuthorization(object, parents, roles, validated_hook)