[Checkins] SVN: megrok.quarry/trunk/ add ContentProvider support with ITALNamespaceData

Kevin Smith kevin at mcweekly.com
Thu May 3 15:24:14 EDT 2007


Log message for revision 75071:
  add ContentProvider support with ITALNamespaceData

Changed:
  U   megrok.quarry/trunk/README.txt
  U   megrok.quarry/trunk/src/megrok/quarry/__init__.py
  U   megrok.quarry/trunk/src/megrok/quarry/components.py
  U   megrok.quarry/trunk/src/megrok/quarry/directive.py
  U   megrok.quarry/trunk/src/megrok/quarry/meta.py

-=-
Modified: megrok.quarry/trunk/README.txt
===================================================================
--- megrok.quarry/trunk/README.txt	2007-05-03 19:20:37 UTC (rev 75070)
+++ megrok.quarry/trunk/README.txt	2007-05-03 19:24:13 UTC (rev 75071)
@@ -197,6 +197,7 @@
 The Grok team lead by Martijn and Philipp and Zope3 community for making web programming
 entirely too much fun.  :)
 
+>>>>>>> MERGE-SOURCE
 
 
 

Modified: megrok.quarry/trunk/src/megrok/quarry/__init__.py
===================================================================
--- megrok.quarry/trunk/src/megrok/quarry/__init__.py	2007-05-03 19:20:37 UTC (rev 75070)
+++ megrok.quarry/trunk/src/megrok/quarry/__init__.py	2007-05-03 19:24:13 UTC (rev 75071)
@@ -1,5 +1,5 @@
 # this directory is a package
 
 
-from directive import layer, template, viewletmanager
-from components import Layer, Skin, View, Viewlet, ViewletManager
+from directive import layer, template, viewletmanager, talnamespace
+from components import Layer, Skin, View, Viewlet, ViewletManager, ContentProvider

Modified: megrok.quarry/trunk/src/megrok/quarry/components.py
===================================================================
--- megrok.quarry/trunk/src/megrok/quarry/components.py	2007-05-03 19:20:37 UTC (rev 75070)
+++ megrok.quarry/trunk/src/megrok/quarry/components.py	2007-05-03 19:24:13 UTC (rev 75071)
@@ -16,58 +16,24 @@
     pass
 
 
-class View(BrowserPage):
-    interface.implements(interfaces.IGrokView)
+class ViewBase(object):
 
-    def __init__(self, context, request):
-        super(View, self).__init__(context, request)
-        self.static = component.queryAdapter(
-            self.request,
-            interface.Interface,
-            name=self.module_info.package_dotted_name
-            )
-
-        
-    @property
-    def response(self):
-        return self.request.response
-
-    def __call__(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()
-        return mapply(self.render, (), self.request)
-    
     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 application_obj(self):
+    def application_url(self):
         obj = self.context
-        while obj:
+        while obj is not None:
             if isinstance(obj, grok.Application):
-                return obj
+                return self.url(obj)
             obj = obj.__parent__
         raise ValueErrror("No application found.")
 
-    def application_url(self):
-        return self.url(self.application_obj())
-    
     def url(self, obj=None, name=None):
         # if the first argument is a string, that's the name. There should
         # be no second argument
@@ -90,11 +56,59 @@
     def redirect(self, url):
         return self.request.response.redirect(url)
         
+    @property
+    def response(self):
+        return self.request.response
+
+    
+
+
+class View(BrowserPage, ViewBase):
+    interface.implements(interfaces.IGrokView)
+
+    def __init__(self, context, request):
+        super(View, self).__init__(context, request)
+        self.static = component.queryAdapter(
+            self.request,
+            interface.Interface,
+            name=self.module_info.package_dotted_name
+            )
+
+
+    def __call__(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()
+        return mapply(self.render, (), self.request)
+    
     def update(self):
         pass
+
+    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 __getitem__(self, key):
+        # XXX give nice error message if template is None
+        return self.template.macros[key]
 
-class ViewletManager(ViewletManagerBase):
+    
+
+class ViewletManager(ViewletManagerBase, ViewBase):
     """  A grok.View-like ViewletManager
     """
     
@@ -107,7 +121,11 @@
             interface.Interface,
             name=self.module_info.package_dotted_name
             )
-        
+
+    def update(self):
+        super(ViewletManager, self).update()
+
+
     def render(self):
         """See zope.contentprovider.interfaces.IContentProvider"""
         # Now render the view
@@ -116,49 +134,14 @@
             return self._render_template()
         else:
             return u'\n'.join([viewlet.render() for viewlet in self.viewlets])
-                                                
-    @property
-    def response(self):
-        return self.request.response
 
-    def _render_template(self):
-        namespace = self.template.pt_getContext()
-        namespace['request'] = self.request
-        namespace['view'] = self
-        namespace['viewlets'] = self.viewlets
-        namespace['static'] = self.static
-        namespace['context'] = self.context
-        # XXX need to check whether we really want to put None here if missing
-        return self.template.pt_render(namespace)
-
     def sort(self, viewlets):
         # sort by viewlet class name as default
         return sorted(viewlets, lambda x,y: cmp(x[0], y[0]))
 
-    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):
+class Viewlet(ViewletBase, ViewBase):
     """ A grok.View-like viewlet
     """
 
@@ -171,12 +154,9 @@
             name=self.module_info.package_dotted_name
             )
 
+    def update(self):
+        pass
 
-    @property
-    def response(self):
-        return self.request.response
-
-
     def render(self):
         mapply(self.update, (), self.request)
         if self.request.response.getStatus() in (302, 303):
@@ -188,42 +168,34 @@
         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
+class ContentProvider(ViewBase):
 
-        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 __init__(self, context, request, view):
+        self.__parent__ = view
+        self.context = context
+        self.request = request
+        self.static = component.queryAdapter(
+            self.request,
+            interface.Interface,
+            name=self.module_info.package_dotted_name
+            )        
+        return self.request.response
 
-    def redirect(self, url):
-        return self.request.response.redirect(url)
-
     def update(self):
         pass
 
+    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()
+
+
+        

Modified: megrok.quarry/trunk/src/megrok/quarry/directive.py
===================================================================
--- megrok.quarry/trunk/src/megrok/quarry/directive.py	2007-05-03 19:20:37 UTC (rev 75070)
+++ megrok.quarry/trunk/src/megrok/quarry/directive.py	2007-05-03 19:24:13 UTC (rev 75071)
@@ -1,4 +1,4 @@
-from grok.directive import InterfaceOrClassDirective, ClassOrModuleDirectiveContext
+from grok.directive import InterfaceOrClassDirective, ClassOrModuleDirectiveContext, InterfaceDirective
 from grok.directive import SingleTextDirective, ClassDirectiveContext
 
 layer = InterfaceOrClassDirective('quarry.layer',
@@ -9,3 +9,5 @@
 
 viewletmanager = InterfaceOrClassDirective('quarry.viewletmanager',
                                            ClassDirectiveContext())
+talnamespace = InterfaceDirective('quarry.talnamespace',
+                               ClassDirectiveContext())

Modified: megrok.quarry/trunk/src/megrok/quarry/meta.py
===================================================================
--- megrok.quarry/trunk/src/megrok/quarry/meta.py	2007-05-03 19:20:37 UTC (rev 75070)
+++ megrok.quarry/trunk/src/megrok/quarry/meta.py	2007-05-03 19:24:13 UTC (rev 75071)
@@ -14,7 +14,11 @@
 from zope.dottedname.resolve import resolve
 from zope import interface, component
 import zope.component.interface
+import zope.interface
+from zope.contentprovider.interfaces import IContentProvider
+from zope.contentprovider.interfaces import ITALNamespaceData
 
+
 class LayerGrokker(grok.ClassGrokker):
     component_class = quarry.Layer
 
@@ -141,6 +145,114 @@
                                 % (method.__name__, factory), factory)
 
 
+class ContentProviderGrokker(grok.ClassGrokker):
+    component_class = quarry.ContentProvider
+
+
+    def register(self, context, name, factory, module_info, templates):
+
+
+        # transfer namespace data
+        namespace = util.class_annotation(factory, 'quarry.talnamespace',
+                                          None)
+
+        if namespace:
+            interface.classImplements(factory, namespace)
+            interface.directlyProvides(namespace, ITALNamespaceData)
+            
+        layer = util.class_annotation(factory, 'quarry.layer',
+                                                    None) or module_info.getAnnotation('quarry.layer',
+                                                     None) or IDefaultBrowserLayer
+        factory_name = factory.__name__.lower()
+        view_name = util.class_annotation(factory, 'grok.name',
+                                          factory_name)
+        view_context = util.determine_class_context(factory, context) #grok.context        
+
+        factory.module_info = module_info
+        factory_name = factory.__name__.lower()
+
+        if util.check_subclass(factory, components.GrokForm):
+            # setup form_fields from context class if we've encountered a form
+            if getattr(factory, 'form_fields', None) is None:
+                factory.form_fields = formlib.get_auto_fields(view_context)
+
+            if not getattr(factory.render, 'base_method', False):
+                raise GrokError(
+                    "It is not allowed to specify a custom 'render' "
+                    "method for form %r. Forms either use the default "
+                    "template or a custom-supplied one." % factory,
+                    factory)
+
+        # can't use grok.template
+        if util.class_annotation(factory, 'grok.template',
+                                 None):
+            raise GrokError(
+                "%s may not use grok.template, use quarry.template instead."
+                % factory.__name__, factory)
+
+        template_name = util.class_annotation(factory, 'quarry.template',
+                                              None)
+        if template_name is None:
+            template_name = factory_name
+            
+        template = templates.get(template_name)
+
+            
+        if factory_name != template_name:
+            # quarry.template is being used
+            if templates.get(factory_name):
+                raise GrokError("Multiple possible templates for view %r. It "
+                                "uses quarry.template('%s'), but there is also "
+                                "a template called '%s'."
+                                % (factory, template_name, factory_name),
+                                factory)
+            # no conflicts, lets try and load the template
+            # using quarry.template('with.dotted.name')
+            try:
+                factory.template = resolve(template_name)
+                # accept string and unicode objects, useful if .__doc__ is referenced
+                if isinstance(factory.template, (str, unicode)):
+                    factory.template = grok.PageTemplate(factory.template)
+            except ImportError:
+                # verify this is a dotted name
+                if template_name.find('.') >=0:
+                    raise GrokError(
+                        "'%s' is not importable. Check the path and"
+                        "be sure it's a grok.PageTemplate,"
+                        "grok.PageTemplateFile, string, or unicode object"
+                        % template_name, factory)
+
+        # support in-class imports template = grok.PageTemplateFile
+        factory_template =  getattr(factory, 'template', None)
+
+        if template:
+            if (getattr(factory, 'render', None) and not
+                util.check_subclass(factory, components.GrokForm)):
+                # we do not accept render and template both for a view
+                # (unless it's a form, they happen to have render.
+                raise GrokError(
+                    "Multiple possible ways to render view %r. "
+                    "It has both a 'render' method as well as "
+                    "an associated template." % factory, factory)
+
+            templates.markAssociated(template_name)
+            factory.template = template
+        elif factory_template:
+            pass
+        else:
+            if not getattr(factory, 'render', None):
+                # we do not accept a view without any way to render it
+                raise GrokError("View %r has no associated template or "
+                                "'render' method." % factory, factory)
+
+
+        component.provideAdapter(factory,
+                                 adapts=(zope.interface.Interface, # TODO: Make configurable
+                                         layer, # TODO: Make configurable
+                                         view_context),
+                                 provides=IContentProvider,
+                                 name=view_name)        
+
 class ViewletManagerGrokker(grok.ClassGrokker):
     component_class = quarry.ViewletManager
 
@@ -148,6 +260,15 @@
 
         factory.module_info = module_info # to make /static available
         factory_name = factory.__name__.lower()
+
+        # transfer namespace data
+        namespace = util.class_annotation(factory, 'quarry.talnamespace',
+                                          None)
+
+        if namespace:
+            interface.classImplements(factory, namespace)
+            interface.directlyProvides(namespace, ITALNamespaceData)
+
         
         permissions = grok.util.class_annotation(factory, 'grok.require', [])
         if not permissions:



More information about the Checkins mailing list