[Checkins] SVN: grok/trunk/ Merge jw-viewlets-fix branch. Fixes #226555.

Jan-Wijbrand Kolman janwijbrand at gmail.com
Thu Jun 19 15:38:51 EDT 2008


Log message for revision 87563:
  Merge jw-viewlets-fix branch. Fixes #226555.
  
  

Changed:
  U   grok/trunk/CHANGES.txt
  U   grok/trunk/src/grok/components.py
  U   grok/trunk/src/grok/ftests/viewlet/viewletmanager_template_templates/cavemanager.pt
  U   grok/trunk/src/grok/interfaces.py
  A   grok/trunk/src/grok/tests/viewlet/viewlet_references.py

-=-
Modified: grok/trunk/CHANGES.txt
===================================================================
--- grok/trunk/CHANGES.txt	2008-06-19 18:43:25 UTC (rev 87562)
+++ grok/trunk/CHANGES.txt	2008-06-19 19:38:50 UTC (rev 87563)
@@ -24,6 +24,11 @@
 Feature changes
 ---------------
 
+* GrokTemplate sets up the namespaces for the template by calling
+  default_namespace() on the view component the template is associated
+  with. As a result, ViewletManagers and Viewlets can now push in the
+  viewletmanager and viewlet namespace into the template.
+
 * Updated tutorial section about grokproject to fit the latest changes.
 
 * Added ``grok.traversable`` directive for easy traversal to attributes and
@@ -76,6 +81,10 @@
 Bug fixes
 ---------
 
+* Fix https://bugs.launchpad.net/grok/+bug/226555: the url() method on
+  ViewletManager and Viewlet has been removed now that there's easy
+  access to the view component the viewlet(manager) is registered for.
+
 * Fix https://bugs.launchpad.net/grok/+bug/231106: Use the
   viewletmanager.sort() method for sorting viewlets by using
   util.sort_components().

Modified: grok/trunk/src/grok/components.py
===================================================================
--- grok/trunk/src/grok/components.py	2008-06-19 18:43:25 UTC (rev 87562)
+++ grok/trunk/src/grok/components.py	2008-06-19 19:38:50 UTC (rev 87563)
@@ -175,6 +175,14 @@
     def _render_template(self):
         return self.template.render(self)
 
+    def default_namespace(self):
+        namespace = {}
+        namespace['context'] = self.context
+        namespace['request'] = self.request
+        namespace['static'] = self.static
+        namespace['view'] = self
+        return namespace
+
     def namespace(self):
         return {}
 
@@ -312,7 +320,8 @@
         self.__grok_module__ = martian.util.caller_module()
 
         if not (string is None) ^ (filename is None):
-            raise AssertionError("You must pass in template or filename, but not both.")
+            raise AssertionError(
+                "You must pass in template or filename, but not both.")
 
         if string:
             self.setFromString(string)
@@ -334,15 +343,10 @@
         pass
 
     def namespace(self, view):
-        namespace = {}
-        namespace['request'] = view.request
-        namespace['view'] = view
-        namespace['context'] = view.context
-        # XXX need to check whether we really want to put None here if missing
-        namespace['static'] = view.static
+        # By default use the namespaces that are defined as the
+        # default by the view implementation.
+        return view.default_namespace()
 
-        return namespace
-
     def getNamespace(self, view):
         namespace = self.namespace(view)
         namespace.update(view.namespace())
@@ -667,6 +671,9 @@
 
     def __init__(self, context, request, view):
         super(ViewletManager, self).__init__(context, request, view)
+        self.context = context
+        self.request = request
+        self.view = view
         self.__name__ = self.__view_name__
         self.static = component.queryAdapter(
             self.request,
@@ -698,6 +705,18 @@
         s_viewlets = util.sort_components(s_viewlets)
         return [(viewlet.__viewlet_name__, viewlet) for viewlet in s_viewlets]
 
+    def default_namespace(self):
+        namespace = {}
+        namespace['context'] = self.context
+        namespace['request'] = self.request
+        namespace['static'] = self.static
+        namespace['view'] = self.view
+        namespace['viewletmanager'] = self
+        return namespace
+
+    def namespace(self):
+        return {}
+
     def render(self):
         """See zope.contentprovider.interfaces.IContentProvider"""
         # Now render the view
@@ -706,41 +725,17 @@
         else:
             return u'\n'.join([viewlet.render() for viewlet in self.viewlets])
 
-    def namespace(self):
-        return {}
 
-    @property
-    def response(self):
-        return self.request.response
-
-    def url(self, obj=None, name=None):
-        # if the first argument is a string, that's the name. There should
-        # be no second argument
-        if isinstance(obj, basestring):
-            if name is not None:
-                raise TypeError(
-                    'url() takes either obj argument, obj, string arguments, '
-                    'or string argument')
-            name = obj
-            obj = None
-
-        if name is None and obj is None:
-            # create URL to view itself
-            obj = self
-        elif name is not None and obj is None:
-            # create URL to view on context
-            obj = self.context
-        return util.url(self.request, obj, name)
-
-    def redirect(self, url):
-        return self.request.response.redirect(url)
-
 class Viewlet(ViewletBase):
-    """ Batteries included viewlet """
+    """Batteries included viewlet.
+    """
 
-
     def __init__(self, context, request, view, manager):
         super(Viewlet, self).__init__(context, request, view, manager)
+        self.context = context
+        self.request = request
+        self.view = view
+        self.viewletmanager = manager
         self.__name__ = self.__view_name__
         self.static = component.queryAdapter(
             self.request,
@@ -748,34 +743,21 @@
             name=self.module_info.package_dotted_name
             )
 
-    @property
-    def response(self):
-        return self.request.response
+    def default_namespace(self):
+        namespace = {}
+        namespace['context'] = self.context
+        namespace['request'] = self.request
+        namespace['static'] = self.static
+        namespace['view'] = self.view
+        namespace['viewlet'] = self
+        namespace['viewletmanager'] = self.manager
+        return namespace
 
-    def render(self):
-        return self.template.render(self)
-
     def namespace(self):
         return {}
 
-    def url(self, obj=None, name=None):
-        # if the first argument is a string, that's the name. There should
-        # be no second argument
-        if isinstance(obj, basestring):
-            if name is not None:
-                raise TypeError(
-                    'url() takes either obj argument, obj, string arguments, '
-                    'or string argument')
-            name = obj
-            obj = None
-
-        if name is None and obj is None:
-            # create URL to view itself
-            obj = self
-        elif name is not None and obj is None:
-            # create URL to view on context
-            obj = self.context
-        return util.url(self.request, obj, name)
-
     def update(self):
         pass
+
+    def render(self):
+        return self.template.render(self)

Modified: grok/trunk/src/grok/ftests/viewlet/viewletmanager_template_templates/cavemanager.pt
===================================================================
--- grok/trunk/src/grok/ftests/viewlet/viewletmanager_template_templates/cavemanager.pt	2008-06-19 18:43:25 UTC (rev 87562)
+++ grok/trunk/src/grok/ftests/viewlet/viewletmanager_template_templates/cavemanager.pt	2008-06-19 19:38:50 UTC (rev 87563)
@@ -1,3 +1,3 @@
-<ul tal:define="v_dict view/viewlet_dict; v_keys view/viewlet_keys_sorted;">
+<ul tal:define="v_dict viewletmanager/viewlet_dict; v_keys viewletmanager/viewlet_keys_sorted;">
  <li tal:repeat="k v_keys" tal:content="python:v_dict[k].render().strip()" />
 </ul>

Modified: grok/trunk/src/grok/interfaces.py
===================================================================
--- grok/trunk/src/grok/interfaces.py	2008-06-19 18:43:25 UTC (rev 87562)
+++ grok/trunk/src/grok/interfaces.py	2008-06-19 19:38:50 UTC (rev 87563)
@@ -320,6 +320,22 @@
         as a cgi query string.
         """
 
+    def default_namespace():
+        """Returns a dictionary of namespaces that the template
+        implementation expects to always be available.
+
+        This method is *not* intended to be overridden by application
+        developers.
+        """
+
+    def namespace():
+        """Returns a dictionary that is injected in the template
+        namespace in addition to the default namespace.
+
+        This method *is* intended to be overridden by the application
+        developer.
+        """
+
     def update(**kw):
         """This method is meant to be implemented by grok.View
         subclasses.  It will be called *before* the view's associated
@@ -507,4 +523,3 @@
 class IViewletManager(IViewletManagerBase):
     """The Grok viewlet manager.
     """
-

Added: grok/trunk/src/grok/tests/viewlet/viewlet_references.py
===================================================================
--- grok/trunk/src/grok/tests/viewlet/viewlet_references.py	                        (rev 0)
+++ grok/trunk/src/grok/tests/viewlet/viewlet_references.py	2008-06-19 19:38:50 UTC (rev 87563)
@@ -0,0 +1,65 @@
+"""
+A grok.ViewletManager instance has references to the components it was
+registered for::
+
+  >>> grok.testing.grok(__name__)
+  >>> from zope import component
+  >>> from zope.contentprovider.interfaces import IContentProvider
+  >>> from zope.publisher.browser import TestRequest
+  >>> ctxt = AContext()
+  >>> request = TestRequest()
+  >>> view = component.getMultiAdapter((ctxt, request), name='with_items')
+  >>> items_mgr = component.getMultiAdapter(
+  ...     (ctxt, request, view), IContentProvider, name='view_items_manager')
+  >>> items_mgr.context is ctxt
+  True
+  >>> items_mgr.view is view
+  True
+  >>> items_mgr.request is request
+  True
+
+Likewise, grok.Viewlet instances have references to the components they're
+registered for::
+
+  >>> items_mgr.update()
+  >>> for viewlet in items_mgr.viewlets:
+  ...     viewlet.context is ctxt
+  ...     viewlet.view is view
+  ...     viewlet.viewletmanager is items_mgr
+  ...     viewlet.request is request
+  True
+  True
+  True
+  True
+  True
+  True
+  True
+  True
+"""
+
+import grok
+from zope import interface
+
+class AContext(grok.Model):
+    pass
+
+class ViewWithItems(grok.View):
+    grok.name('with_items')
+
+    def render(self):
+        return ''
+
+class ViewItemsManager(grok.ViewletManager):
+    grok.name('view_items_manager')
+
+class ItemOneViewlet(grok.Viewlet):
+    grok.name('item_one')
+
+    def render(self):
+        return "Item one reporting, sir!"
+
+class ItemTwoViewlet(grok.Viewlet):
+    grok.name('item_two')
+
+    def render(self):
+        return "Item two reporting, sir!"



More information about the Checkins mailing list