[Checkins] SVN: grok/branches/ksmith_mcweekly-layers/ * grok.Viewlet behaves more like grok.View this

Kevin Smith kevin at mcweekly.com
Fri Apr 27 14:12:39 EDT 2007


Log message for revision 74866:
  * grok.Viewlet behaves more like grok.View this
    means templates can be used or render overridden
  * add grok.OrderedViewletManager which sorts by
    class name
  

Changed:
  U   grok/branches/ksmith_mcweekly-layers/buildout.cfg
  U   grok/branches/ksmith_mcweekly-layers/src/grok/__init__.py
  U   grok/branches/ksmith_mcweekly-layers/src/grok/components.py
  U   grok/branches/ksmith_mcweekly-layers/src/grok/directive.py
  U   grok/branches/ksmith_mcweekly-layers/src/grok/ftests/url/url_function.py
  U   grok/branches/ksmith_mcweekly-layers/src/grok/interfaces.py
  U   grok/branches/ksmith_mcweekly-layers/src/grok/meta.py
  U   grok/branches/ksmith_mcweekly-layers/src/grok/tests/test_grok.py

-=-
Modified: grok/branches/ksmith_mcweekly-layers/buildout.cfg
===================================================================
--- grok/branches/ksmith_mcweekly-layers/buildout.cfg	2007-04-27 18:10:18 UTC (rev 74865)
+++ grok/branches/ksmith_mcweekly-layers/buildout.cfg	2007-04-27 18:12:36 UTC (rev 74866)
@@ -1,10 +1,11 @@
 [buildout]
 develop = . grokwiki ldapaddressbook
-parts = zope3 data instance testdata testinstance test
+parts = data instance testdata testinstance test
 
 [zope3]
-recipe = zc.recipe.zope3checkout
-url = svn://svn.zope.org/repos/main/Zope3/branches/3.3
+location = /root/Zope-3.3.1
+#recipe = zc.recipe.zope3checkout
+#url = svn://svn.zope.org/repos/main/Zope3/branches/3.3
 
 [data]
 recipe = zc.recipe.filestorage
@@ -54,7 +55,7 @@
 [test]
 recipe = zc.recipe.testrunner
 eggs = grok
-extra-paths = parts/zope3/src
+extra-paths = /root/Zope-3.3.1/lib/python
 working-directory = parts/testinstance
 defaults = ['--tests-pattern', '^f?tests$',
             '-v'

Modified: grok/branches/ksmith_mcweekly-layers/src/grok/__init__.py
===================================================================
--- grok/branches/ksmith_mcweekly-layers/src/grok/__init__.py	2007-04-27 18:10:18 UTC (rev 74865)
+++ grok/branches/ksmith_mcweekly-layers/src/grok/__init__.py	2007-04-27 18:12:36 UTC (rev 74866)
@@ -34,10 +34,11 @@
 from grok.components import PageTemplate, PageTemplateFile, Container, Traverser
 from grok.components import Site, GlobalUtility, LocalUtility, Annotation
 from grok.components import Application, Form, AddForm, EditForm, DisplayForm
-from grok.components import Indexes, Skin, ILayer
+from grok.components import Indexes, Skin, ILayer, ViewletManager, Viewlet
+from grok.components import OrderedViewletManager
 from grok.directive import (context, name, template, templatedir, provides,
                             baseclass, global_utility, local_utility,
-                            define_permission, require, site, layer)
+                            define_permission, require, site, layer, viewletmanager)
 
 from grok._grok import do_grok as grok  # Avoid name clash within _grok
 from grok._grok import SubscribeDecorator as subscribe

Modified: grok/branches/ksmith_mcweekly-layers/src/grok/components.py
===================================================================
--- grok/branches/ksmith_mcweekly-layers/src/grok/components.py	2007-04-27 18:10:18 UTC (rev 74865)
+++ grok/branches/ksmith_mcweekly-layers/src/grok/components.py	2007-04-27 18:12:36 UTC (rev 74866)
@@ -40,6 +40,8 @@
 from zope.traversing.browser.absoluteurl import AbsoluteURL
 from zope.traversing.browser.absoluteurl import _safe as SAFE_URL_CHARACTERS
 from zope.annotation.interfaces import IAttributeAnnotatable
+from zope.viewlet.manager import ViewletManagerBase
+from zope.viewlet.viewlet import ViewletBase
 
 from zope.app.pagetemplate.engine import TrustedAppPT
 from zope.app.publisher.browser import getDefaultViewName
@@ -511,3 +513,83 @@
 
 class Skin(object):
     pass
+
+
+class ViewletManager(ViewletManagerBase):
+    template = None
+
+    
+class OrderedViewletManager(ViewletManager):
+    def sort(self, viewlets):
+        # sort by viewlet class name as default
+        return sorted(viewlets, lambda x,y: cmp(x[0], y[0]))
+
+
+class Viewlet(ViewletBase):
+    """ Batteries included viewlet """
+
+
+    def __init__(self, context, request, view, manager):
+        super(Viewlet, self).__init__(context, request, view, manager)
+        self.static = component.queryAdapter(
+            self.request,
+            interface.Interface,
+            name=self.module_info.package_dotted_name
+            )
+
+
+    @property
+    def response(self):
+        return self.request.response
+
+
+    def render(self):
+        mapply(self.update, (), self.request)
+        if self.request.response.getStatus() in (302, 303):
+            # A redirect was triggered somewhere in update().  Don't
+            # continue rendering the template or doing anything else.
+            return
+
+        template = getattr(self, 'template', None)
+        if template is not None:
+            return self._render_template()
+
+    def _render_template(self):
+        namespace = self.template.pt_getContext()
+        namespace['request'] = self.request
+        namespace['view'] = self
+        namespace['context'] = self.context
+        # XXX need to check whether we really want to put None here if missing
+        namespace['static'] = self.static
+        return self.template.pt_render(namespace)
+
+    def __getitem__(self, key):
+        # XXX give nice error message if template is None
+        return self.template.macros[key]
+
+    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)
+
+    def update(self):
+        pass
+
+

Modified: grok/branches/ksmith_mcweekly-layers/src/grok/directive.py
===================================================================
--- grok/branches/ksmith_mcweekly-layers/src/grok/directive.py	2007-04-27 18:10:18 UTC (rev 74865)
+++ grok/branches/ksmith_mcweekly-layers/src/grok/directive.py	2007-04-27 18:12:36 UTC (rev 74866)
@@ -284,3 +284,5 @@
 layer = InterfaceOrClassDirective('grok.layer',
                            ClassOrModuleDirectiveContext())
 
+viewletmanager = InterfaceOrClassDirective('grok.viewletmanager',
+                                           ClassDirectiveContext())

Modified: grok/branches/ksmith_mcweekly-layers/src/grok/ftests/url/url_function.py
===================================================================
--- grok/branches/ksmith_mcweekly-layers/src/grok/ftests/url/url_function.py	2007-04-27 18:10:18 UTC (rev 74865)
+++ grok/branches/ksmith_mcweekly-layers/src/grok/ftests/url/url_function.py	2007-04-27 18:12:36 UTC (rev 74866)
@@ -6,8 +6,8 @@
   >>> from grok import url
   >>> import grok
   >>> grok.grok('grok.ftests.url.url_function')
-  
-  >>> from grok.ftests.url.url import Herd, Mammoth
+
+  >>> from grok.ftests.url.url_function import Herd, Mammoth
   >>> herd = Herd()
   >>> getRootFolder()['herd'] = herd
   >>> manfred = Mammoth()
@@ -24,7 +24,7 @@
   >>> browser.open("http://localhost/herd/manfred/another")
   >>> print browser.contents
   http://localhost/herd/manfred/another
-  
+
 We get the views manually so we can do a greater variety of url() calls:
 
   >>> from zope import component
@@ -65,6 +65,7 @@
   True
 """
 import grok
+from grok import url
 
 class Herd(grok.Container, grok.Model):
     pass
@@ -77,7 +78,7 @@
 class Index(grok.View):
     def render(self):
         return url(self.request, self)
-    
+
 class Another(grok.View):
     def render(self):
         return url(self.request, self)

Modified: grok/branches/ksmith_mcweekly-layers/src/grok/interfaces.py
===================================================================
--- grok/branches/ksmith_mcweekly-layers/src/grok/interfaces.py	2007-04-27 18:10:18 UTC (rev 74865)
+++ grok/branches/ksmith_mcweekly-layers/src/grok/interfaces.py	2007-04-27 18:12:36 UTC (rev 74866)
@@ -41,8 +41,11 @@
     AddForm = interface.Attribute("Base class for add forms.")
     EditForm = interface.Attribute("Base class for edit forms.")
     DisplayForm = interface.Attribute("Base class for display forms.")
-    Layer = interface.Attribute("Base interface for skin layers.")
-
+    ILayer = interface.Attribute("Base interface for layers.")
+    Skin = interface.Attribute("Base class for skin.")
+    ViewletManager = interface.Attribute("Base class for viewletmanager.")
+    Viewlet = interface.Attribute("Base class for viewlet.")
+    
 class IGrokErrors(interface.Interface):
 
     def GrokError(message, component):

Modified: grok/branches/ksmith_mcweekly-layers/src/grok/meta.py
===================================================================
--- grok/branches/ksmith_mcweekly-layers/src/grok/meta.py	2007-04-27 18:10:18 UTC (rev 74865)
+++ grok/branches/ksmith_mcweekly-layers/src/grok/meta.py	2007-04-27 18:12:36 UTC (rev 74866)
@@ -7,8 +7,11 @@
                                                IBrowserPublisher,
                                                IBrowserSkinType)
 from zope.publisher.interfaces.xmlrpc import IXMLRPCRequest
+from zope.publisher.browser import IBrowserView
+from zope.viewlet.interfaces import IViewletManager, IViewlet
 from zope.security.permission import Permission
 from zope.security.interfaces import IPermission
+from zope.security.checker import NamesChecker, defineChecker
 from zope.annotation.interfaces import IAnnotations
 
 from zope.app.publisher.xmlrpc import MethodPublisher
@@ -28,6 +31,7 @@
 from grok.error import GrokError
 
 
+
 class ModelGrokker(grok.ClassGrokker):
     component_class = grok.Model
 
@@ -110,9 +114,6 @@
             permission = getattr(method, '__grok_require__',
                                  default_permission)
             util.make_checker(factory, method_view, permission)
-    
-class ILayerGrokker(grok.ClassGrokker):
-    component_class = grok.ILayer
 
 
 class ViewGrokker(grok.ClassGrokker):
@@ -298,19 +299,7 @@
             interface.Interface, name=module_info.dotted_name)
 
 
-class RegisterSkinDirectiveGrokker(grok.ModuleGrokker):
 
-    def register(self, context, module_info, templates):
-        infos = module_info.getAnnotation('grok.register_skin',[])
-        if infos:
-            for skin in infos:
-                name = skin.name
-                if not skin.name:
-                    name = skin.layer.__name__
-                zope.component.interface.provideInterface(name, skin.layer,
-                                                          IBrowserSkinType)
-
-
 class GlobalUtilityDirectiveGrokker(grok.ModuleGrokker):
 
     def register(self, context, module_info, templates):
@@ -586,6 +575,10 @@
         return intids
 
 
+class ILayerGrokker(grok.ClassGrokker):
+    component_class = grok.ILayer
+
+
 class SkinGrokker(grok.ClassGrokker):
     component_class = grok.Skin
 
@@ -595,3 +588,65 @@
                                     None) or grok.IDefaultBrowserLayer
         name = grok.util.class_annotation(factory, 'grok.name', factory.__name__.lower())
         zope.component.interface.provideInterface(name, layer, IBrowserSkinType)
+
+
+class ViewletManagerGrokker(grok.ClassGrokker):
+    component_class = (grok.ViewletManager, grok.OrderedViewletManager)
+
+    def register(self, context, name, factory, module_info, templates):
+
+        name = grok.util.class_annotation(factory, 'grok.name', factory.__name__.lower())
+        view_layer = util.class_annotation(factory, 'grok.layer',
+                                                    None) or module_info.getAnnotation('grok.layer',
+                                                     None) or IDefaultBrowserLayer
+        
+        view_context = util.determine_class_context(factory, context)
+        component.provideAdapter(factory,
+                                 adapts=(None, # TODO: Make configurable
+                                         view_layer, # TODO: Make configurable
+                                         view_context),
+                                 provides=IViewletManager,
+                                 name=name)
+
+            
+class ViewletGrokker(grok.ClassGrokker):
+    component_class = grok.Viewlet
+                
+    def register(self, context, name, factory, module_info, templates):
+        # Try to set up permissions (copied from the View grokker)
+
+        factory.module_info = module_info # to make /static available
+        
+        permissions = grok.util.class_annotation(factory, 'grok.require', [])
+        if not permissions:
+            checker = NamesChecker(['update', 'render'])
+        elif len(permissions) > 1:
+            raise GrokError('grok.require was called multiple times in viewlet '
+                            '%r. It may only be called once.' % factory,
+                            factory)
+        elif permissions[0] == 'zope.Public':
+            checker = NamesChecker(['update','render'])
+        else:
+            perm = permissions[0]
+            if component.queryUtility(IPermission, name=perm) is None:
+                raise GrokError('Undefined permission %r in view %r. Use '
+                            'grok.define_permission first.'
+                            % (perm, factory), factory)
+            checker = NamesChecker(['update','render'], permissions[0])
+        
+        defineChecker(factory, checker)
+        
+        # New directive
+        viewletmanager = grok.util.class_annotation(factory, 'grok.viewletmanager', [])
+        layer = util.class_annotation(factory, 'grok.layer',
+                                            None) or module_info.getAnnotation('grok.layer',
+                                             None) or IDefaultBrowserLayer
+       
+        component.provideAdapter(factory,
+                                 adapts=(None, # TODO: Make configurable
+                                         layer,
+                                         IBrowserView,
+                                         viewletmanager),
+                                 provides=IViewlet,
+                                 name=name)
+

Modified: grok/branches/ksmith_mcweekly-layers/src/grok/tests/test_grok.py
===================================================================
--- grok/branches/ksmith_mcweekly-layers/src/grok/tests/test_grok.py	2007-04-27 18:10:18 UTC (rev 74865)
+++ grok/branches/ksmith_mcweekly-layers/src/grok/tests/test_grok.py	2007-04-27 18:12:36 UTC (rev 74866)
@@ -2,9 +2,12 @@
 from pkg_resources import resource_listdir
 from zope.testing import doctest, cleanup
 import zope.component.eventtesting
+import zope.viewlet.tests
 
+
 def setUpZope(test):
     zope.component.eventtesting.setUp(test)
+    zope.viewlet.tests.setUp(test)
 
 def cleanUpZope(test):
     cleanup.cleanUp()



More information about the Checkins mailing list