[Checkins] SVN: grokcore.chameleon/trunk/src/grokcore/chameleon/ ressurect the PageTemplateFile behaviour where a relative path could be given as the first argument. This behaviour got lost when the z3.pt base class for page template files was no longer used.

Jan Wijbrand Kolman cvs-admin at zope.org
Mon May 7 14:57:21 UTC 2012


Log message for revision 125684:
  ressurect the PageTemplateFile behaviour where a relative path could be given as the first argument. This behaviour got lost when the z3.pt base class for page template files was no longer used.

Changed:
  U   grokcore.chameleon/trunk/src/grokcore/chameleon/components.py
  A   grokcore.chameleon/trunk/src/grokcore/chameleon/tests/templatefile.py
  A   grokcore.chameleon/trunk/src/grokcore/chameleon/tests/templates/
  A   grokcore.chameleon/trunk/src/grokcore/chameleon/tests/templates/foo.cpt
  U   grokcore.chameleon/trunk/src/grokcore/chameleon/tests/test_megrok_chameleon.py

-=-
Modified: grokcore.chameleon/trunk/src/grokcore/chameleon/components.py
===================================================================
--- grokcore.chameleon/trunk/src/grokcore/chameleon/components.py	2012-05-07 14:41:58 UTC (rev 125683)
+++ grokcore.chameleon/trunk/src/grokcore/chameleon/components.py	2012-05-07 14:57:17 UTC (rev 125684)
@@ -31,20 +31,12 @@
 from z3c.pt.expressions import PathExpr, ProviderExpr
 
 
-#
-# Chameleon Zope Page Templates...
-#
 class PageTemplate(PageTemplate, GrokTemplate):
-    """A `z3c.pt` page template suitable for use with views.
+    """A Chameleon page template suitable for use with views.
 
-    This page template implementation is different from `z3c.pt`
-    implementation in two respects:
-
-    - It sets ``python`` as default mode (instead of ``path``)
-    - It injects any views ``static`` variable in template namespace.
+    It defines the path and provider expression types to the template in
+    addition to the "standard" expressions types.
     """
-    default_expression = 'python'  # Use the chameleon default
-
     expression_types = {
         'python': PythonExpr,
         'string': StringExpr,
@@ -56,21 +48,47 @@
         'structure': StructureExpr,
         }
 
+def _module_relative_to_abs(ctx, filename):
+    # Taken and adapted from z3c.pth.pagetemplate.
+    if os.path.isabs(filename):
+        return filename
+    for depth in (2, 3):
+        frame = sys._getframe(depth)
+        package_name = frame.f_globals.get('__name__', None)
+        if package_name is not None and \
+               package_name != ctx:
+            module = sys.modules[package_name]
+            try:
+                path = module.__path__[0]
+            except AttributeError:
+                path = module.__file__
+                path = path[:path.rfind(os.sep)]
+            break
+        else:
+            package_path = frame.f_globals.get('__file__', None)
+            if package_path is not None:
+                path = os.path.dirname(package_path)
+                break
+    return os.path.join(path, filename)
 
+
 class PageTemplateFile(PageTemplate, PageTemplateFile):
-    """A `z3c.pt` page template file suitable for use with views.
+    """A Chameleon page template file suitable for use with views.
 
-    This implementation is different from `z3c.pt` implementation in
-    two respects:
-
-    - It sets ``python`` as default mode (instead of ``path``)
-    - It injects any views ``static`` variable in template namespace.
+    Takes an absolute path to the template file as the first argument.
     """
-    default_expression = 'python'
+    def __init__(self, filename):
+        filename = _module_relative_to_abs(self, filename)
+        super(PageTemplateFile, self).__init__(filename)
 
 
 class ChameleonPageTemplate(GrokTemplate):
+    """Encapsulates a Chameleon-based template as a GrokTemplate
+    implementation.
 
+    Used for Grok View components by way of the grok.template() directive.
+    """
+
     def setFromString(self, string):
         self._filename = None
         self._template = PageTemplate(string)
@@ -87,18 +105,25 @@
 
     def render(self, view):
         context = self.getNamespace(view)
-
         if 'target_language' not in context:
             try:
                 target_language = zope.i18n.negotiate(context['request'])
             except:
                 target_language = None
             context['target_language'] = target_language
-
         return self._template(**context)
 
+
 class ChameleonPageTemplateFile(ChameleonPageTemplate):
+    """Encapsulates a Chameleon-based template file as a GrokTemplate
+    implementation.
 
+    Used for Grok View components by way of the grok.template() directive.
+
+    The filename will be relative to the module in which the Grok View
+    component is defined.
+    """
+
     def __init__(self, filename, _prefix=None):
         self.__grok_module__ = martian.util.caller_module()
         if _prefix is None:

Added: grokcore.chameleon/trunk/src/grokcore/chameleon/tests/templatefile.py
===================================================================
--- grokcore.chameleon/trunk/src/grokcore/chameleon/tests/templatefile.py	                        (rev 0)
+++ grokcore.chameleon/trunk/src/grokcore/chameleon/tests/templatefile.py	2012-05-07 14:57:17 UTC (rev 125684)
@@ -0,0 +1,56 @@
+"""
+  >>> from zope.publisher.browser import TestRequest
+  >>> context = FooContext()
+  >>> request = TestRequest()
+  >>> view = WithFooTemplate(context, request)
+  >>> print view()
+  Foo Template.
+
+  >>> view = WithFooTemplateNoExists(context, request)
+  >>> view()
+  Traceback (most recent call last):
+    ...
+  IOError: [Errno 2] No such file or directory: '...templates/nothere.cpt'
+
+  >>> view = NonGrokViewWithTemplate(context, request)
+  >>> print view()
+  Foo Template.
+
+  >>> view = NonGrokViewWithTemplateNoExists(context, request)
+  >>> view()
+  Traceback (most recent call last):
+    ...
+  IOError: [Errno 2] No such file or directory: '...templates/nothere.cpt'
+
+"""
+import zope.interface
+import grokcore.component.interfaces
+import grokcore.component
+import grokcore.view
+
+from grokcore.chameleon.components import ChameleonPageTemplateFile
+from grokcore.chameleon.components import PageTemplateFile
+
+class FooContext(object):
+    zope.interface.implements(grokcore.component.interfaces.IContext)
+
+class WithFooTemplate(grokcore.view.View):
+    grokcore.component.context(zope.interface.Interface)
+
+    template = ChameleonPageTemplateFile('templates/foo.cpt')
+
+class WithFooTemplateNoExists(WithFooTemplate):
+    template = ChameleonPageTemplateFile('templates/nothere.cpt')
+
+class NonGrokViewWithTemplate(object):
+    template = PageTemplateFile('templates/foo.cpt')
+
+    def __init__(self, context, request):
+        self.context = context
+        self.request = request
+
+    def __call__(self):
+        return self.template()
+
+class NonGrokViewWithTemplateNoExists(NonGrokViewWithTemplate):
+    template = PageTemplateFile('templates/nothere.cpt')

Added: grokcore.chameleon/trunk/src/grokcore/chameleon/tests/templates/foo.cpt
===================================================================
--- grokcore.chameleon/trunk/src/grokcore/chameleon/tests/templates/foo.cpt	                        (rev 0)
+++ grokcore.chameleon/trunk/src/grokcore/chameleon/tests/templates/foo.cpt	2012-05-07 14:57:17 UTC (rev 125684)
@@ -0,0 +1 @@
+Foo Template.

Modified: grokcore.chameleon/trunk/src/grokcore/chameleon/tests/test_megrok_chameleon.py
===================================================================
--- grokcore.chameleon/trunk/src/grokcore/chameleon/tests/test_megrok_chameleon.py	2012-05-07 14:41:58 UTC (rev 125683)
+++ grokcore.chameleon/trunk/src/grokcore/chameleon/tests/test_megrok_chameleon.py	2012-05-07 14:57:17 UTC (rev 125684)
@@ -43,7 +43,7 @@
     """Get a testsuite of all doctests.
     """
     suite = unittest.TestSuite()
-    test = doctest.DocFileSuite(
+    readme = doctest.DocFileSuite(
         'README.txt',
         setUp=setUpStatic,
         package=grokcore.chameleon,
@@ -52,6 +52,13 @@
             ),
         optionflags=FLAGS,
         )
-    test.layer = FunctionalLayer
-    suite.addTest(test)
+    readme.layer = FunctionalLayer
+    suite.addTest(readme)
+    suite.addTest(
+        doctest.DocTestSuite(
+            'grokcore.chameleon.tests.templatefile',
+            setUp=setUpStatic,
+            optionflags=FLAGS,
+            )
+        )
     return suite



More information about the checkins mailing list