[Checkins] SVN: grok/trunk/src/grok/ Fix https://bugs.launchpad.net/grok/+bug/125735:

Philipp von Weitershausen philikon at philikon.de
Sat Jul 14 09:00:42 EDT 2007


Log message for revision 77924:
  Fix https://bugs.launchpad.net/grok/+bug/125735:
  When a custom traverser returns an object that doesn't have a __parent__ (and
  __name__) attribute yet, it should be set automatically.
  

Changed:
  U   grok/trunk/src/grok/components.py
  U   grok/trunk/src/grok/ftests/traversal/modeltraverse.py
  U   grok/trunk/src/grok/ftests/traversal/traverser.py
  A   grok/trunk/src/grok/ftests/traversal/traverser_sets_parent.py
  U   grok/trunk/src/grok/util.py

-=-
Modified: grok/trunk/src/grok/components.py
===================================================================
--- grok/trunk/src/grok/components.py	2007-07-14 12:31:54 UTC (rev 77923)
+++ grok/trunk/src/grok/components.py	2007-07-14 13:00:42 UTC (rev 77924)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2006−2007 Zope Corporation and Contributors.
+# Copyright (c) 2006-2007 Zope Corporation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -49,12 +49,10 @@
 from zope.app.container.interfaces import IReadContainer
 from zope.app.component.site import SiteManagerContainer
 
-from martian import util
+import martian.util
+from grok import interfaces, formlib, util
 
-from grok import interfaces, formlib
-from grok.util import url
 
-
 class Model(Contained, persistent.Persistent):
     # XXX Inheritance order is important here. If we reverse this,
     # then containers can't be models anymore because no unambigous MRO
@@ -154,7 +152,7 @@
         elif name is not None and obj is None:
             # create URL to view on context
             obj = self.context
-        return url(self.request, obj, name)
+        return util.url(self.request, obj, name)
 
     def application_url(self, name=None):
         obj = self.context
@@ -208,7 +206,7 @@
 
     def __init__(self, template):
         super(PageTemplate, self).__init__()
-        if util.not_unicode_or_ascii(template):
+        if martian.util.not_unicode_or_ascii(template):
             raise ValueError("Invalid page template. Page templates must be "
                              "unicode or ASCII.")
         self.write(template)
@@ -217,7 +215,7 @@
         # inline templates
         # XXX unfortunately using caller_module means that
         # PageTemplate cannot be subclassed
-        self.__grok_module__ = util.caller_module()
+        self.__grok_module__ = martian.util.caller_module()
 
 
 class PageTemplateFile(GrokPageTemplate, TrustedAppPT,
@@ -231,7 +229,7 @@
         # inline templates
         # XXX unfortunately using caller_module means that
         # PageTemplateFile cannot be subclassed
-        self.__grok_module__ = util.caller_module()
+        self.__grok_module__ = martian.util.caller_module()
 
 
 class DirectoryResource(directoryresource.DirectoryResource):
@@ -277,7 +275,7 @@
     def publishTraverse(self, request, name):
         subob = self.traverse(name)
         if subob is not None:
-            return subob
+            return util.safely_locate_maybe(subob, self.context, name)
 
         # XXX Special logic here to deal with containers.  It would be
         # good if we wouldn't have to do this here. One solution is to
@@ -471,6 +469,6 @@
         self.__grok_indexes__ = indexes
         # __grok_module__ is needed to make defined_locally() return True for
         # inline templates
-        self.__grok_module__ = util.caller_module()
+        self.__grok_module__ = martian.util.caller_module()
 
 Indexes = IndexesClass('Indexes')

Modified: grok/trunk/src/grok/ftests/traversal/modeltraverse.py
===================================================================
--- grok/trunk/src/grok/ftests/traversal/modeltraverse.py	2007-07-14 12:31:54 UTC (rev 77923)
+++ grok/trunk/src/grok/ftests/traversal/modeltraverse.py	2007-07-14 13:00:42 UTC (rev 77924)
@@ -5,7 +5,7 @@
   >>> import grok
   >>> from grok.ftests.traversal.modeltraverse import Herd
   >>> grok.grok('grok.ftests.traversal.modeltraverse')
-  >>> getRootFolder()["herd"] = Herd()
+  >>> getRootFolder()["herd"] = Herd('The Big Mammoth Herd')
 
   >>> from zope.testbrowser.testing import Browser
   >>> browser = Browser()
@@ -15,6 +15,7 @@
   <html>
   <body>
   <h1>Hello, Manfred!</h1>
+  <p>Manfred is part of The Big Mammoth Herd.</p>
   </body>
   </html>
 
@@ -23,6 +24,7 @@
   <html>
   <body>
   <h1>Hello, Ellie!</h1>
+  <p>Ellie is part of The Big Mammoth Herd.</p>
   </body>
   </html>
 
@@ -31,6 +33,9 @@
 
 class Herd(grok.Model):
 
+    def __init__(self, name):
+        self.name = name
+
     def getMammoth(self, name):
         return Mammoth(name)
 
@@ -51,6 +56,7 @@
 <html>
 <body>
 <h1>Hello, <span tal:replace="context/name/title" />!</h1>
+<p><span tal:replace="context/name/title" /> is part of <span tal:replace="context/__parent__/name" />.</p>
 </body>
 </html>
 """)

Modified: grok/trunk/src/grok/ftests/traversal/traverser.py
===================================================================
--- grok/trunk/src/grok/ftests/traversal/traverser.py	2007-07-14 12:31:54 UTC (rev 77923)
+++ grok/trunk/src/grok/ftests/traversal/traverser.py	2007-07-14 13:00:42 UTC (rev 77924)
@@ -5,7 +5,7 @@
   >>> import grok
   >>> from grok.ftests.traversal.traverser import Herd
   >>> grok.grok('grok.ftests.traversal.traverser')
-  >>> getRootFolder()["herd"] = Herd()
+  >>> getRootFolder()["herd"] = Herd('The Big Mammoth Herd')
 
   >>> from zope.testbrowser.testing import Browser
   >>> browser = Browser()
@@ -15,6 +15,7 @@
   <html>
   <body>
   <h1>Hello, Manfred!</h1>
+  <p>Manfred is part of The Big Mammoth Herd.</p>
   </body>
   </html>
 
@@ -23,6 +24,7 @@
   <html>
   <body>
   <h1>Hello, Ellie!</h1>
+  <p>Ellie is part of The Big Mammoth Herd.</p>
   </body>
   </html>
 
@@ -30,8 +32,10 @@
 import grok
 
 class Herd(grok.Model):
-    pass
 
+    def __init__(self, name):
+        self.name = name
+
 class HerdTraverser(grok.Traverser):
     grok.context(Herd)
 
@@ -52,6 +56,7 @@
 <html>
 <body>
 <h1>Hello, <span tal:replace="context/name/title" />!</h1>
+<p><span tal:replace="context/name/title" /> is part of <span tal:replace="context/__parent__/name" />.</p>
 </body>
 </html>
 """)

Added: grok/trunk/src/grok/ftests/traversal/traverser_sets_parent.py
===================================================================
--- grok/trunk/src/grok/ftests/traversal/traverser_sets_parent.py	                        (rev 0)
+++ grok/trunk/src/grok/ftests/traversal/traverser_sets_parent.py	2007-07-14 13:00:42 UTC (rev 77924)
@@ -0,0 +1,66 @@
+"""
+A traverser can set the __parent__ (and __name__) attributes itself,
+in which case Grok's traverser won't interfere:
+
+  >>> import grok
+  >>> from grok.ftests.traversal.traverser_sets_parent import Herd
+  >>> grok.grok('grok.ftests.traversal.traverser_sets_parent')
+  >>> getRootFolder()["herd"] = Herd('The Big Mammoth Herd')
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+  >>> browser.open("http://localhost/herd/manfred")
+  >>> print browser.contents
+  <html>
+  <body>
+  <h1>Hello, Manfred!</h1>
+  <p>Manfred is part of The Three Stooges.</p>
+  </body>
+  </html>
+
+  >>> browser.open("http://localhost/herd/ellie")
+  >>> print browser.contents
+  <html>
+  <body>
+  <h1>Hello, Ellie!</h1>
+  <p>Ellie is part of The Three Stooges.</p>
+  </body>
+  </html>
+
+"""
+import grok
+
+class Herd(grok.Model):
+
+    def __init__(self, name):
+        self.name = name
+
+class HerdTraverser(grok.Traverser):
+    grok.context(Herd)
+
+    def traverse(self, name):
+        mammoth = Mammoth(name)
+        # We pretend the mammoth is the child object of some competely
+        # differnt Herd object.
+        mammoth.__parent__ = Herd('The Three Stooges')
+        return mammoth
+
+class Mammoth(grok.Model):
+
+    def __init__(self, name):
+        self.name = name
+
+grok.context(Mammoth)
+
+class Index(grok.View):
+    pass
+
+index = grok.PageTemplate("""\
+<html>
+<body>
+<h1>Hello, <span tal:replace="context/name/title" />!</h1>
+<p><span tal:replace="context/name/title" /> is part of <span tal:replace="context/__parent__/name" />.</p>
+</body>
+</html>
+""")


Property changes on: grok/trunk/src/grok/ftests/traversal/traverser_sets_parent.py
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: grok/trunk/src/grok/util.py
===================================================================
--- grok/trunk/src/grok/util.py	2007-07-14 12:31:54 UTC (rev 77923)
+++ grok/trunk/src/grok/util.py	2007-07-14 13:00:42 UTC (rev 77924)
@@ -16,6 +16,7 @@
 
 import urllib
 
+import zope.location.interfaces
 from zope import component
 from zope.traversing.browser.interfaces import IAbsoluteURL
 from zope.traversing.browser.absoluteurl import _safe as SAFE_URL_CHARACTERS
@@ -84,3 +85,17 @@
         return url
     return url + '/' + urllib.quote(name.encode('utf-8'),
                                     SAFE_URL_CHARACTERS)
+
+def safely_locate_maybe(obj, parent, name):
+    """Set an object's __parent__ (and __name__) if the object's
+    __parent__ attribute doesn't exist yet or is None.
+
+    If the object provides ILocation, __parent__ and __name__ will be
+    set directly.  A location proxy will be returned otherwise.
+    """
+    if getattr(obj, '__parent__', None) is not None:
+        return obj
+    if zope.location.interfaces.ILocation.providedBy(obj):
+        zope.location.locate(obj, parent, name)
+        return obj
+    return zope.location.LocationProxy(obj, parent, name)



More information about the Checkins mailing list