[Checkins] SVN: grok/trunk/src/grok/ Change the approach we define inline templates to support templates

Philipp von Weitershausen philikon at philikon.de
Sun Oct 15 12:42:48 EDT 2006


Log message for revision 70659:
  Change the approach we define inline templates to support templates
  that are not associated with a view class.
  

Changed:
  U   grok/trunk/src/grok/__init__.py
  U   grok/trunk/src/grok/_grok.py
  U   grok/trunk/src/grok/tests/view/inline.py
  U   grok/trunk/src/grok/tests/view/inlinebogus.py

-=-
Modified: grok/trunk/src/grok/__init__.py
===================================================================
--- grok/trunk/src/grok/__init__.py	2006-10-15 15:57:56 UTC (rev 70658)
+++ grok/trunk/src/grok/__init__.py	2006-10-15 16:42:47 UTC (rev 70659)
@@ -15,4 +15,4 @@
 """
 
 from zope.interface import implements
-from _grok import Model, Adapter, View, grok, context, name
+from _grok import Model, Adapter, View, PageTemplate, grok, context, name

Modified: grok/trunk/src/grok/_grok.py
===================================================================
--- grok/trunk/src/grok/_grok.py	2006-10-15 15:57:56 UTC (rev 70658)
+++ grok/trunk/src/grok/_grok.py	2006-10-15 16:42:47 UTC (rev 70659)
@@ -22,7 +22,7 @@
 from zope.interface.interfaces import IInterface
 from zope.publisher.browser import BrowserPage
 from zope.publisher.interfaces.browser import IDefaultBrowserLayer
-from zope.pagetemplate.pagetemplate import PageTemplate
+from zope.pagetemplate import pagetemplate
 from zope.app.pagetemplate.engine import TrustedAppPT
 
 class Model(object):
@@ -46,9 +46,20 @@
         namespace['context'] = self.context
         return template.pt_render(namespace)
 
-class GrokTemplate(TrustedAppPT, PageTemplate):
+class PageTemplate(TrustedAppPT, pagetemplate.PageTemplate):
     expand = 0
 
+    def __init__(self, template):
+        super(PageTemplate, self).__init__()
+        if not_unicode_or_ascii(template):
+            raise GrokError("Invalid page template. Page templates must be "
+                            "unicode or ASCII.")
+        self.write(template)
+
+        # XXX unfortunately using caller_module means that
+        # PageTemplate cannot be subclassed
+        self.__grok_module__ = caller_module()
+
 class GrokError(Exception):
     pass
 
@@ -60,10 +71,11 @@
     context = None
     adapters = []
     views = []
+    templates = TemplateRegistry()
     for name in dir(module):
         obj = getattr(module, name)
 
-        if getattr(obj, '__module__', None) != dotted_name:
+        if not defined_locally(obj, dotted_name):
             continue
 
         if check_subclass(obj, Model):
@@ -75,6 +87,8 @@
             adapters.append(obj)
         elif check_subclass(obj, View):
             views.append(obj)
+        elif isinstance(obj, PageTemplate):
+            templates.register(name, obj)
 
     if getattr(module, '__grok_context__', None):
         context = module.__grok_context__
@@ -90,15 +104,10 @@
         name = getattr(factory, '__grok_name__', name)
 
         # find inline templates
-        template_name = name + '_pt'
-        template = getattr(module, template_name, None)
+        template = templates.get(name)
         if template:
-            if not_unicode_or_ascii(template):
-                raise GrokError("Invalid inline template '%s' for %r. Inline "
-                                "templates must be unicode or ASCII."
-                                % (template_name, factory))
-            factory.template = GrokTemplate()
-            factory.template.write(template)
+            templates.markUsed(name)
+            factory.template = template
         else:
             if not getattr(factory, 'render', None):
                 raise GrokError("View %r has no associated template or "
@@ -109,6 +118,46 @@
                                  provides=interface.Interface,
                                  name=name)
 
+    for name, unused_template in templates.listUnused():
+        source = '<%s template in %s>' % (name, dotted_name)
+        check_context(source, context)
+
+        class TemplateView(View):
+            template = unused_template
+
+        component.provideAdapter(TemplateView,
+                                 adapts=(context, IDefaultBrowserLayer),
+                                 provides=interface.Interface,
+                                 name=name)
+
+class TemplateRegistry(object):
+
+    def __init__(self):
+        self._reg = {}
+
+    def register(self, name, template):
+        self._reg[name] = dict(template=template, used=False)
+
+    def markUsed(self, name):
+        self._reg[name]['used'] = True
+
+    def get(self, name):
+        entry = self._reg.get(name)
+        if entry is None:
+            return None
+        return entry['template']
+
+    def listUnused(self):
+        for name, entry in self._reg.iteritems():
+            if not entry['used']:
+                yield name, entry['template']
+
+def defined_locally(obj, dotted_name):
+    obj_module = getattr(obj, '__grok_module__', None)
+    if obj_module is None:
+        obj_module = getattr(obj, '__module__', None)
+    return obj_module == dotted_name
+
 def isclass(obj):
     """We cannot use ``inspect.isclass`` because it will return True for interfaces"""
     return type(obj) in (types.ClassType, type)
@@ -118,14 +167,17 @@
         return False
     return issubclass(obj, class_)
 
+def check_context(source, context):
+    if context is None:
+        raise GrokError("Cannot determine context for %s, please use "
+                        "grok.context." % source)
+    elif context is AMBIGUOUS_CONTEXT:
+        raise GrokError("Ambiguous contexts for %s, please use "
+                        "grok.context." % source)
+
 def determine_context(factory, module_context):
     context = getattr(factory, '__grok_context__', module_context)
-    if context is None:
-        raise GrokError("Cannot determine context for %r, please use "
-                        "grok.context." % factory)
-    elif context is AMBIGUOUS_CONTEXT:
-        raise GrokError("Ambiguous contexts for %r, please use "
-                        "grok.context." % factory)
+    check_context(repr(factory), context)
     return context
 
 def caller_is_module():
@@ -136,6 +188,9 @@
     frame = sys._getframe(2)
     return '__module__' in frame.f_locals
 
+def caller_module():
+    return sys._getframe(2).f_globals['__name__']
+
 def set_local(name, value, error_message):
     frame = sys._getframe(2)
     name = '__grok_%s__' % name
@@ -151,7 +206,6 @@
     return is_not_ascii(value)
 
 is_not_ascii = re.compile(eval(r'u"[\u0080-\uffff]"')).search
-    
 
 def context(obj):
     if not (IInterface.providedBy(obj) or isclass(obj)):

Modified: grok/trunk/src/grok/tests/view/inline.py
===================================================================
--- grok/trunk/src/grok/tests/view/inline.py	2006-10-15 15:57:56 UTC (rev 70658)
+++ grok/trunk/src/grok/tests/view/inline.py	2006-10-15 16:42:47 UTC (rev 70659)
@@ -21,6 +21,14 @@
   </ul>
   </body>
   </html>
+
+Templates that are not associated with a view class will still be
+registered on the model:
+
+  >>> view = component.getMultiAdapter((manfred, request), name='club')
+  >>> print view()
+  <html><body><h1>GROK CLUB MAMMOTH!</h1></body></html>
+
 """
 import grok
 
@@ -30,7 +38,7 @@
 class CavePainting(grok.View):
     pass
 
-cavepainting_pt = """\
+cavepainting = grok.PageTemplate("""\
 <html>
 <body>
 <h1 tal:content="string:Mammoth Cave Painting"/>
@@ -42,4 +50,8 @@
 </ul>
 </body>
 </html>
-"""
+""")
+
+club = grok.PageTemplate("""\
+<html><body><h1>GROK CLUB MAMMOTH!</h1></body></html>
+""")

Modified: grok/trunk/src/grok/tests/view/inlinebogus.py
===================================================================
--- grok/trunk/src/grok/tests/view/inlinebogus.py	2006-10-15 15:57:56 UTC (rev 70658)
+++ grok/trunk/src/grok/tests/view/inlinebogus.py	2006-10-15 16:42:47 UTC (rev 70659)
@@ -4,24 +4,13 @@
 encoded strings:
 
   >>> import grok
-  >>> grok.grok(__name__)
+  >>> grok.PageTemplate('''
+  ... <html>
+  ... <body><h1 tal:content="string:Mammoth Cave Painting"/>
+  ... <p>ööö</p>
+  ... </body>
+  ... </html>''')
   Traceback (most recent call last):
     ...
-  GrokError: Invalid inline template 'cavepainting_pt' for <class 'grok.tests.view.inlinebogus.CavePainting'>. Inline templates must be unicode or ASCII.
-
+  GrokError: Invalid page template. Page templates must be unicode or ASCII.
 """
-import grok
-
-class Mammoth(grok.Model):
-    pass
-
-class CavePainting(grok.View):
-    pass
-
-cavepainting_pt = """\
-<html>
-<body><h1 tal:content="string:Mammoth Cave Painting"/>
-<p>ööö</p>
-</body>
-</html>
-"""



More information about the Checkins mailing list