[Zope-CVS] CVS: Products/CompositePage - macro.py:1.1 composite.py:1.3

Shane Hathaway shane at zope.com
Sat Oct 4 14:10:35 EDT 2003


Update of /cvs-repository/Products/CompositePage
In directory cvs.zope.org:/tmp/cvs-serv22368

Modified Files:
	composite.py 
Added Files:
	macro.py 
Log Message:
Added support for composite templating based on METAL macros.

Now, instead of:

  <div tal:repeat="element here/slots/foo/multiple"
    tal:content="structure element" />

you can use:

  <div metal:define-slot="foo" />

To accomplish this, the composite generates a TAL program and executes 
it using the standard TALIntepreter.



=== Added File Products/CompositePage/macro.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
# 
##############################################################################
"""Support for composites built from ZPT macros.

$Id: macro.py,v 1.1 2003/10/04 18:10:04 shane Exp $
"""

from __future__ import nested_scopes

from StringIO import StringIO

from Acquisition import aq_inner, aq_parent
from TAL.TALInterpreter import TALInterpreter
from Products.PageTemplates.Expressions import getEngine, SecureModuleImporter

from interfaces import ISlot


class MacroSlotGenerator:
    """Generates macro slots on the fly.
    """

    def __init__(self, slots):
        self.slots = slots

    def get(self, name, default=None):
        s = self.slots[name]
        assert ISlot.isImplementedBy(s)
        text = "\n".join(s.multiple())
        return [('rawtextOffset', (text, 0)),]


def makeContext(composite):
    """Creates a TALES context.
    """
    root = composite.getPhysicalRoot()
    parent = aq_parent(composite)
    c = {
        'template': composite,  # Not a mistake :-)
        'here': parent,
        'context': parent,
        'container': aq_parent(aq_inner(composite)),
        'nothing': None,
        'options': {},
        'root': root,
        'request': getattr(root, 'REQUEST', None),
        'modules': SecureModuleImporter,
        }
    return getEngine().getContext(c)
    

def renderMacro(macro, composite):
    """Renders a page template macro, filling slots.
    """
    path = '/'.join(composite.getPhysicalPath())
    expr = lambda engine: macro
    slot_generator = MacroSlotGenerator(composite.slots)
    program = [
        ('version', '1.4'),
        ('mode', 'html'),
        ('setSourceFile', path),
        ('useMacro', ('macro', expr, slot_generator, [])),
        ]

    output = StringIO()
    c = makeContext(composite)
    TALInterpreter(program, {}, c, output, tal=1, strictinsert=0)()
    return output.getvalue()
    



=== Products/CompositePage/composite.py 1.2 => 1.3 ===
--- Products/CompositePage/composite.py:1.2	Wed Oct  1 14:59:31 2003
+++ Products/CompositePage/composite.py	Sat Oct  4 14:10:04 2003
@@ -29,6 +29,7 @@
 
 from interfaces import ISlot, CompositeError
 from slot import Slot
+from macro import renderMacro
 import perm_names
 
 _www = os.path.join(os.path.dirname(__file__), "www")
@@ -71,6 +72,7 @@
         )
 
     template_path = "template"
+    use_macro = ""
     _v_editing = 0
     _v_rendering = 0
     _v_generating = 0
@@ -81,6 +83,8 @@
     _properties = Folder._properties + (
         {"id": "template_path", "mode": "w", "type": "string",
          "label": "Path to template"},
+        {"id": "use_macro", "mode": "w", "type": "string",
+         "label": "METAL macro to use from template"},
         )
 
     def __init__(self):
@@ -111,7 +115,11 @@
         self._v_rendering = 1
         try:
             template = self.getTemplate()
-            return template()
+            if not self.use_macro:
+                return template()
+            else:
+                macro = template.restrictedTraverse(("macros", self.use_macro))
+                return renderMacro(macro, self)
         finally:
             self._v_rendering = 0
 
@@ -177,9 +185,14 @@
         self.parent._setObject(obj.getId(), obj)
 
 
+attributes_for_samples = {
+    "sample_template.zpt": {},
+    "metal_template.zpt": {"use_macro": "page"},
+    }
+
 addCompositeForm = PageTemplateFile("addCompositeForm", _www)
 
-def manage_addComposite(dispatcher, id, title="", create_sample=0,
+def manage_addComposite(dispatcher, id, title="", create_sample="",
                         REQUEST=None):
     """Adds a composite to a folder.
     """
@@ -188,8 +201,12 @@
     ob.title = string(title)
     dispatcher._setObject(ob.getId(), ob)
     if create_sample:
+        attrs = attributes_for_samples.get(create_sample)
+        if attrs is None:
+            raise ValueError("Not allowed: %s" % create_sample)
         ob = dispatcher.this()._getOb(ob.getId())
-        f = open(os.path.join(_www, "sample_template.zpt"), "rt")
+        ob.use_macro = attrs.get("use_macro", "")
+        f = open(os.path.join(_www, create_sample), "rt")
         try:
             text = f.read()
         finally:




More information about the Zope-CVS mailing list