[Zope3-checkins] SVN: Zope3/trunk/ Templates now allow
metal:define-macro and metal:use-macro in the same tag.
Shane Hathaway
shane at zope.com
Mon Nov 22 11:38:57 EST 2004
Log message for revision 28489:
Templates now allow metal:define-macro and metal:use-macro in the same tag.
This allows a macro to extend another macro, which is particularly
useful for writing a skin that customizes another skin.
Changed:
U Zope3/trunk/doc/CHANGES.txt
U Zope3/trunk/src/zope/tal/taldefs.py
U Zope3/trunk/src/zope/tal/talgenerator.py
U Zope3/trunk/src/zope/tal/talinterpreter.py
A Zope3/trunk/src/zope/tal/tests/input/acme_template.pt
A Zope3/trunk/src/zope/tal/tests/input/document_list.pt
A Zope3/trunk/src/zope/tal/tests/input/pnome_template.pt
U Zope3/trunk/src/zope/tal/tests/input/test_metal7.html
A Zope3/trunk/src/zope/tal/tests/output/acme_template.html
A Zope3/trunk/src/zope/tal/tests/output/acme_template_source.html
A Zope3/trunk/src/zope/tal/tests/output/document_list.html
A Zope3/trunk/src/zope/tal/tests/output/document_list_source.html
U Zope3/trunk/src/zope/tal/tests/output/test_metal1.html
U Zope3/trunk/src/zope/tal/tests/test_talinterpreter.py
-=-
Modified: Zope3/trunk/doc/CHANGES.txt
===================================================================
--- Zope3/trunk/doc/CHANGES.txt 2004-11-22 10:15:51 UTC (rev 28488)
+++ Zope3/trunk/doc/CHANGES.txt 2004-11-22 16:38:56 UTC (rev 28489)
@@ -10,15 +10,20 @@
New features
+ - Page templates now allow metal:define-macro and
+ metal:use-macro in the same tag. This allows a macro to
+ extend another macro, which is particularly useful for writing
+ a skin that customizes another skin.
+
- Added pagelet concept. Pagelets are responsible for a piece
of content in a view. They can be used to render additionaly
provided information into a pagetemplate.
- + Added tal expression 'pagelet'
+ + Added tales expression 'pagelet'
- + Added tal expression 'pagelets'
+ + Added tales expression 'pagelets'
- + Added tal expression 'pagedata'
+ + Added tales expression 'pagedata'
- Added pagelet chooser for store pagelet name in the annotation
of a object.
Modified: Zope3/trunk/src/zope/tal/taldefs.py
===================================================================
--- Zope3/trunk/src/zope/tal/taldefs.py 2004-11-22 10:15:51 UTC (rev 28488)
+++ Zope3/trunk/src/zope/tal/taldefs.py 2004-11-22 16:38:56 UTC (rev 28489)
@@ -19,7 +19,7 @@
from zope.tal.interfaces import ITALExpressionErrorInfo
from zope.interface import implements
-TAL_VERSION = "1.5"
+TAL_VERSION = "1.5.1"
XML_NS = "http://www.w3.org/XML/1998/namespace" # URI for XML namespace
XMLNS_NS = "http://www.w3.org/2000/xmlns/" # URI for XML NS declarations
Modified: Zope3/trunk/src/zope/tal/talgenerator.py
===================================================================
--- Zope3/trunk/src/zope/tal/talgenerator.py 2004-11-22 10:15:51 UTC (rev 28488)
+++ Zope3/trunk/src/zope/tal/talgenerator.py 2004-11-22 16:38:56 UTC (rev 28489)
@@ -387,6 +387,14 @@
self.inMacroUse = 0
self.emit("useMacro", expr, cexpr, self.popSlots(), program)
+ def emitExtendMacro(self, defineName, useExpr):
+ cexpr = self.compileExpression(useExpr)
+ program = self.popProgram()
+ self.inMacroUse = 0
+ self.emit("extendMacro", useExpr, cexpr, self.popSlots(), program,
+ defineName)
+ self.emitDefineMacro(defineName)
+
def emitDefineSlot(self, slotName):
program = self.popProgram()
slotName = slotName.strip()
@@ -538,10 +546,12 @@
raise I18NError("i18n:data must be accompanied by i18n:translate",
position)
- if len(metaldict) > 1 and (defineMacro or useMacro):
- raise METALError("define-macro and use-macro cannot be used "
- "together or with define-slot or fill-slot",
- position)
+ if defineMacro or useMacro:
+ if fillSlot or defineSlot:
+ raise METALError(
+ "define-slot and fill-slot cannot be used with "
+ "define-macro or use-macro", position)
+
if replace:
if content:
raise TALError(
@@ -827,10 +837,13 @@
self.emitDefineSlot(defineSlot)
if fillSlot:
self.emitFillSlot(fillSlot)
- if useMacro:
- self.emitUseMacro(useMacro)
- if defineMacro:
- self.emitDefineMacro(defineMacro)
+ if useMacro or defineMacro:
+ if useMacro and defineMacro:
+ self.emitExtendMacro(defineMacro, useMacro)
+ elif useMacro:
+ self.emitUseMacro(useMacro)
+ elif defineMacro:
+ self.emitDefineMacro(defineMacro)
if useMacro or defineSlot:
# generate a source annotation after define-slot or use-macro
# because the source file might have changed
Modified: Zope3/trunk/src/zope/tal/talinterpreter.py
===================================================================
--- Zope3/trunk/src/zope/tal/talinterpreter.py 2004-11-22 10:15:51 UTC (rev 28488)
+++ Zope3/trunk/src/zope/tal/talinterpreter.py 2004-11-22 16:38:56 UTC (rev 28489)
@@ -181,7 +181,10 @@
self.html = 0
self.endsep = "/>"
self.endlen = len(self.endsep)
+ # macroStack contains:
+ # [(macroName, slots, definingName, extending, entering, i18ncontext)]
self.macroStack = []
+ self.inUseDirective = False
self.position = None, None # (lineno, offset)
self.col = 0
self.level = 0
@@ -220,11 +223,12 @@
assert self.level == level
assert self.scopeLevel == scopeLevel
- def pushMacro(self, macroName, slots, entering=1):
+ def pushMacro(self, macroName, slots, definingName, extending, entering=1):
if len(self.macroStack) >= self.stackLimit:
raise METALError("macro nesting limit (%d) exceeded "
"by %s" % (self.stackLimit, `macroName`))
- self.macroStack.append([macroName, slots, entering, self.i18nContext])
+ self.macroStack.append([macroName, slots, definingName, extending,
+ entering, self.i18nContext])
def popMacro(self):
return self.macroStack.pop()
@@ -361,28 +365,29 @@
try:
for item in attrList:
if _len(item) == 2:
- name, s = item
+ rendered = item[1:]
else:
# item[2] is the 'action' field:
if item[2] in ('metal', 'tal', 'xmlns', 'i18n'):
if not self.showtal:
continue
- ok, name, s = self.attrAction(item)
+ rendered = self.attrAction(item)
else:
- ok, name, s = attrAction(self, item)
- if not ok:
+ rendered = attrAction(self, item)
+ if not rendered:
continue
- slen = _len(s)
- if (wrap and
- col >= align and
- col + 1 + slen > wrap):
- append("\n")
- append(" "*align)
- col = align + slen
- else:
- append(" ")
- col = col + 1 + slen
- append(s)
+ for s in rendered:
+ slen = _len(s)
+ if (wrap and
+ col >= align and
+ col + 1 + slen > wrap):
+ append("\n")
+ append(" "*align)
+ col = align + slen
+ else:
+ append(" ")
+ col = col + 1 + slen
+ append(s)
append(end)
col = col + endlen
finally:
@@ -393,33 +398,47 @@
def attrAction(self, item):
name, value, action = item[:3]
if action == 'insert':
- return 0, name, value
+ return ()
macs = self.macroStack
if action == 'metal' and self.metal and macs:
- if len(macs) > 1 or not macs[-1][2]:
- # Drop all METAL attributes at a use-depth above one.
- return 0, name, value
+ # Drop all METAL attributes at a use-depth beyond the first
+ # use-macro and its extensions
+ if len(macs) > 1:
+ for macro in macs[1:]:
+ if macro is None:
+ return ()
+ extending = macro[3]
+ if not extending:
+ return ()
+ if not macs[-1][4]:
+ return ()
# Clear 'entering' flag
- macs[-1][2] = 0
+ macs[-1][4] = 0
# Convert or drop depth-one METAL attributes.
i = name.rfind(":") + 1
prefix, suffix = name[:i], name[i:]
if suffix == "define-macro":
# Convert define-macro as we enter depth one.
- name = prefix + "use-macro"
- value = macs[-1][0] # Macro name
+ useName = macs[0][0]
+ defName = macs[0][2]
+ res = []
+ if defName:
+ res.append('%sdefine-macro=%s' % (prefix, quote(defName)))
+ if useName:
+ res.append('%suse-macro=%s' % (prefix, quote(useName)))
+ return res
elif suffix == "define-slot":
name = prefix + "fill-slot"
elif suffix == "fill-slot":
pass
else:
- return 0, name, value
+ return ()
if value is None:
value = name
else:
value = "%s=%s" % (name, quote(value))
- return 1, name, value
+ return [value]
def attrAction_tal(self, item):
name, value, action = item[:3]
@@ -451,8 +470,9 @@
value = translated
if value is None:
value = name
- value = "%s=%s" % (name, quote(value))
- return ok, name, value
+ return ["%s=%s" % (name, quote(value))]
+ else:
+ return ()
bytecode_handlers["<attrAction>"] = attrAction
def no_tag(self, start, program):
@@ -751,8 +771,10 @@
def do_defineMacro(self, (macroName, macro)):
macs = self.macroStack
+ wasInUse = self.inUseDirective
+ self.inUseDirective = False
if len(macs) == 1:
- entering = macs[-1][2]
+ entering = macs[-1][4]
if not entering:
macs.append(None)
self.interpret(macro)
@@ -760,9 +782,11 @@
macs.pop()
return
self.interpret(macro)
+ self.inUseDirective = wasInUse
bytecode_handlers["defineMacro"] = do_defineMacro
- def do_useMacro(self, (macroName, macroExpr, compiledSlots, block)):
+ def do_useMacro(self, (macroName, macroExpr, compiledSlots, block),
+ definingName=None, extending=False):
if not self.metal:
self.interpret(block)
return
@@ -778,14 +802,18 @@
if mode != (self.html and "html" or "xml"):
raise METALError("macro %s has incompatible mode %s" %
(`macroName`, `mode`), self.position)
- self.pushMacro(macroName, compiledSlots)
+ self.pushMacro(macroName, compiledSlots, definingName, extending)
# We want 'macroname' name to be always available as a variable
outer = self.engine.getValue('macroname')
self.engine.setLocal('macroname', macroName.split('/')[-1])
prev_source = self.sourceFile
+ wasInUse = self.inUseDirective
+ self.inUseDirective = True
self.interpret(macro)
+ self.inUseDirective = wasInUse
+
if self.sourceFile != prev_source:
self.engine.setSourceFile(prev_source)
self.sourceFile = prev_source
@@ -794,6 +822,19 @@
self.engine.setLocal('macroname', outer)
bytecode_handlers["useMacro"] = do_useMacro
+ def do_extendMacro(self, (macroName, macroExpr, compiledSlots, block,
+ definingName)):
+ # extendMacro results from a combination of define-macro and
+ # use-macro. definingName has the value of the
+ # metal:define-macro attribute.
+ extending = False
+ if self.metal and self.inUseDirective:
+ # extend the calling directive.
+ extending = True
+ self.do_useMacro((macroName, macroExpr, compiledSlots, block),
+ definingName, extending)
+ bytecode_handlers["extendMacro"] = do_extendMacro
+
def do_fillSlot(self, (slotName, block)):
# This is only executed if the enclosing 'use-macro' evaluates
# to 'default'.
@@ -806,17 +847,41 @@
return
macs = self.macroStack
if macs and macs[-1] is not None:
- macroName, slots = self.popMacro()[:2]
- slot = slots.get(slotName)
+ len_macs = len(macs)
+ # Measure the extension depth of this use-macro
+ depth = 1
+ while depth < len_macs:
+ if macs[-depth][3]:
+ depth += 1
+ else:
+ break
+ # Search for a slot filler from the most specific to the
+ # most general macro. The most general is at the top of
+ # the stack.
+ slot = None
+ i = len_macs - depth
+ while i < len_macs:
+ slots = macs[i][1]
+ slot = slots.get(slotName)
+ if slot is not None:
+ break
+ i += 1
if slot is not None:
+ # Found a slot filler. Temporarily chop the macro
+ # stack starting at the macro that filled the slot and
+ # render the slot filler.
+ chopped = macs[i:]
+ del macs[i:]
prev_source = self.sourceFile
self.interpret(slot)
if self.sourceFile != prev_source:
self.engine.setSourceFile(prev_source)
self.sourceFile = prev_source
- self.pushMacro(macroName, slots, entering=0)
+ # Restore the stack entries.
+ for mac in chopped:
+ mac[4] = 0 # Not entering
+ macs.extend(chopped)
return
- self.pushMacro(macroName, slots)
# Falling out of the 'if' allows the macro to be interpreted.
self.interpret(block)
bytecode_handlers["defineSlot"] = do_defineSlot
Added: Zope3/trunk/src/zope/tal/tests/input/acme_template.pt
===================================================================
--- Zope3/trunk/src/zope/tal/tests/input/acme_template.pt 2004-11-22 10:15:51 UTC (rev 28488)
+++ Zope3/trunk/src/zope/tal/tests/input/acme_template.pt 2004-11-22 16:38:56 UTC (rev 28489)
@@ -0,0 +1,15 @@
+<!-- This is ACME's generic look and feel, which is based on
+PNOME's look and feel. -->
+<html metal:use-macro="pnome_macros_page" metal:define-macro="page">
+<head>
+<title metal:fill-slot="title">ACME Look and Feel</title>
+</head>
+<body>
+<div metal:fill-slot="page-footer">
+Copyright 2004 Acme Inc.
+<div metal:define-slot="disclaimer">
+Standard disclaimers apply.
+</div>
+</div>
+</body>
+</html>
Added: Zope3/trunk/src/zope/tal/tests/input/document_list.pt
===================================================================
--- Zope3/trunk/src/zope/tal/tests/input/document_list.pt 2004-11-22 10:15:51 UTC (rev 28488)
+++ Zope3/trunk/src/zope/tal/tests/input/document_list.pt 2004-11-22 16:38:56 UTC (rev 28489)
@@ -0,0 +1,21 @@
+<!-- ACME's document_list uses the ACME look and feel -->
+<html metal:use-macro="acme_macros_page">
+<head>
+<title metal:fill-slot="title">Acme Document List</title>
+<style metal:fill-slot="local-styles" type="text/css">
+ body { background-color: white; }
+</style>
+</head>
+<body>
+<div metal:fill-slot="content">
+<h1>Documents</h1>
+<ul>
+<li>Rocket Science for Dummies</li>
+<li>Birds for the Gourmet Chef</li>
+</ul>
+</div>
+<div metal:fill-slot="disclaimer">
+This document list is classified.
+</div>
+</body>
+</html>
Added: Zope3/trunk/src/zope/tal/tests/input/pnome_template.pt
===================================================================
--- Zope3/trunk/src/zope/tal/tests/input/pnome_template.pt 2004-11-22 10:15:51 UTC (rev 28488)
+++ Zope3/trunk/src/zope/tal/tests/input/pnome_template.pt 2004-11-22 16:38:56 UTC (rev 28489)
@@ -0,0 +1,23 @@
+<!-- fakeplone is a fictional user interface created by a large,
+well-focused team of graphics designers -->
+<html metal:define-macro="page">
+<head>
+<title metal:define-slot="title">Title here</title>
+<metal:block define-slot="local-styles">
+</metal:block>
+</head>
+<body>
+<div>
+ <div metal:define-slot="annoying-quote">
+ "The early bird gets the worm, but the second mouse gets the cheese."
+ </div>
+ <a href="#">Preferences...</a>
+</div>
+<div metal:define-slot="content">
+ Content here
+</div>
+<div metal:define-slot="page-footer">
+ page footer
+</div>
+</body>
+</html>
Modified: Zope3/trunk/src/zope/tal/tests/input/test_metal7.html
===================================================================
--- Zope3/trunk/src/zope/tal/tests/input/test_metal7.html 2004-11-22 10:15:51 UTC (rev 28488)
+++ Zope3/trunk/src/zope/tal/tests/input/test_metal7.html 2004-11-22 16:38:56 UTC (rev 28489)
@@ -1,4 +1,6 @@
<html metal:define-macro="page" i18n:domain="zope">
<x metal:define-slot="title" />
</html>
-<html metal:use-macro="page" />
\ No newline at end of file
+<html metal:use-macro="page">
+ <x metal:fill-slot="title" />
+</html>
Added: Zope3/trunk/src/zope/tal/tests/output/acme_template.html
===================================================================
--- Zope3/trunk/src/zope/tal/tests/output/acme_template.html 2004-11-22 10:15:51 UTC (rev 28488)
+++ Zope3/trunk/src/zope/tal/tests/output/acme_template.html 2004-11-22 16:38:56 UTC (rev 28489)
@@ -0,0 +1,26 @@
+<!-- This is ACME's generic look and feel, which is based on
+PNOME's look and feel. -->
+<html>
+<head>
+<title>ACME Look and Feel</title>
+
+
+</head>
+<body>
+<div>
+ <div>
+ "The early bird gets the worm, but the second mouse gets the cheese."
+ </div>
+ <a href="#">Preferences...</a>
+</div>
+<div>
+ Content here
+</div>
+<div>
+Copyright 2004 Acme Inc.
+<div>
+Standard disclaimers apply.
+</div>
+</div>
+</body>
+</html>
Added: Zope3/trunk/src/zope/tal/tests/output/acme_template_source.html
===================================================================
--- Zope3/trunk/src/zope/tal/tests/output/acme_template_source.html 2004-11-22 10:15:51 UTC (rev 28488)
+++ Zope3/trunk/src/zope/tal/tests/output/acme_template_source.html 2004-11-22 16:38:56 UTC (rev 28489)
@@ -0,0 +1,27 @@
+<!-- This is ACME's generic look and feel, which is based on
+PNOME's look and feel. -->
+<html metal:define-macro="page"
+ metal:use-macro="pnome_macros_page">
+<head>
+<title metal:fill-slot="title">ACME Look and Feel</title>
+<metal:block>
+</metal:block>
+</head>
+<body>
+<div>
+ <div>
+ "The early bird gets the worm, but the second mouse gets the cheese."
+ </div>
+ <a href="#">Preferences...</a>
+</div>
+<div>
+ Content here
+</div>
+<div metal:fill-slot="page-footer">
+Copyright 2004 Acme Inc.
+<div metal:define-slot="disclaimer">
+Standard disclaimers apply.
+</div>
+</div>
+</body>
+</html>
Added: Zope3/trunk/src/zope/tal/tests/output/document_list.html
===================================================================
--- Zope3/trunk/src/zope/tal/tests/output/document_list.html 2004-11-22 10:15:51 UTC (rev 28488)
+++ Zope3/trunk/src/zope/tal/tests/output/document_list.html 2004-11-22 16:38:56 UTC (rev 28489)
@@ -0,0 +1,30 @@
+<!-- ACME's document_list uses the ACME look and feel -->
+<html>
+<head>
+<title>Acme Document List</title>
+<style type="text/css">
+ body { background-color: white; }
+</style>
+</head>
+<body>
+<div>
+ <div>
+ "The early bird gets the worm, but the second mouse gets the cheese."
+ </div>
+ <a href="#">Preferences...</a>
+</div>
+<div>
+<h1>Documents</h1>
+<ul>
+<li>Rocket Science for Dummies</li>
+<li>Birds for the Gourmet Chef</li>
+</ul>
+</div>
+<div>
+Copyright 2004 Acme Inc.
+<div>
+This document list is classified.
+</div>
+</div>
+</body>
+</html>
Added: Zope3/trunk/src/zope/tal/tests/output/document_list_source.html
===================================================================
--- Zope3/trunk/src/zope/tal/tests/output/document_list_source.html 2004-11-22 10:15:51 UTC (rev 28488)
+++ Zope3/trunk/src/zope/tal/tests/output/document_list_source.html 2004-11-22 16:38:56 UTC (rev 28489)
@@ -0,0 +1,30 @@
+<!-- ACME's document_list uses the ACME look and feel -->
+<html metal:use-macro="acme_macros_page">
+<head>
+<title metal:fill-slot="title">Acme Document List</title>
+<style metal:fill-slot="local-styles" type="text/css">
+ body { background-color: white; }
+</style>
+</head>
+<body>
+<div>
+ <div>
+ "The early bird gets the worm, but the second mouse gets the cheese."
+ </div>
+ <a href="#">Preferences...</a>
+</div>
+<div metal:fill-slot="content">
+<h1>Documents</h1>
+<ul>
+<li>Rocket Science for Dummies</li>
+<li>Birds for the Gourmet Chef</li>
+</ul>
+</div>
+<div>
+Copyright 2004 Acme Inc.
+<div metal:fill-slot="disclaimer">
+This document list is classified.
+</div>
+</div>
+</body>
+</html>
Modified: Zope3/trunk/src/zope/tal/tests/output/test_metal1.html
===================================================================
--- Zope3/trunk/src/zope/tal/tests/output/test_metal1.html 2004-11-22 10:15:51 UTC (rev 28488)
+++ Zope3/trunk/src/zope/tal/tests/output/test_metal1.html 2004-11-22 16:38:56 UTC (rev 28489)
@@ -22,7 +22,7 @@
<span metal:use-macro="OUTER2">
AAA
- <xxx metal:fill-slot="OUTERSLOT">
+ <xxx>
<span>INNER</span>
</xxx>
BBB
@@ -48,7 +48,7 @@
<span metal:use-macro="OUTER3">
AAA
- <xxx metal:fill-slot="OUTERSLOT">
+ <xxx>
<span>INNER
<xxx>INNERSLOT</xxx>
</span>
@@ -63,7 +63,7 @@
</span>
<span metal:use-macro="INNER3">INNER
- <xxx metal:fill-slot="INNERSLOT">INNERSLOT</xxx>
+ <xxx>INNERSLOT</xxx>
</span>
<span metal:use-macro="INNER3">INNER
Modified: Zope3/trunk/src/zope/tal/tests/test_talinterpreter.py
===================================================================
--- Zope3/trunk/src/zope/tal/tests/test_talinterpreter.py 2004-11-22 10:15:51 UTC (rev 28488)
+++ Zope3/trunk/src/zope/tal/tests/test_talinterpreter.py 2004-11-22 16:38:56 UTC (rev 28489)
@@ -16,12 +16,13 @@
$Id$
"""
+import os
import sys
import unittest
from StringIO import StringIO
-from zope.tal.taldefs import METALError, I18NError
+from zope.tal.taldefs import METALError, I18NError, TAL_VERSION
from zope.tal.htmltalparser import HTMLTALParser
from zope.tal.talinterpreter import TALInterpreter
from zope.tal.dummyengine import DummyEngine, DummyTranslationDomain
@@ -74,6 +75,76 @@
self.assertEqual(output, '<p><div>foo</div></p>')
+class MacroExtendTestCase(TestCaseBase):
+
+ def setUp(self):
+ s = self._read(('input', 'pnome_template.pt'))
+ self.pnome_program, pnome_macros = self._compile(s)
+ s = self._read(('input', 'acme_template.pt'))
+ self.acme_program, acme_macros = self._compile(s)
+ s = self._read(('input', 'document_list.pt'))
+ self.doclist_program, doclist_macros = self._compile(s)
+ macros = {
+ 'pnome_macros_page': pnome_macros['page'],
+ 'acme_macros_page': acme_macros['page'],
+ }
+ self.engine = DummyEngine(macros)
+
+ def _read(self, path):
+ dir = os.path.dirname(__file__)
+ fn = os.path.join(dir, *path)
+ f = open(fn)
+ data = f.read()
+ f.close()
+ return data
+
+ def test_acme_extends_pnome(self):
+ # ACME inc. has a document_list template that uses ACME's
+ # common look and feel. ACME's look and feel is based on the
+ # work of PNOME, Inc., a company that creates Pretty Nice
+ # Object Management Environments for Zope. This test verifies
+ # that document_list works as expected.
+ result = StringIO()
+ interpreter = TALInterpreter(
+ self.doclist_program, {}, self.engine, stream=result)
+ interpreter()
+ actual = result.getvalue().strip()
+ expected = self._read(('output', 'document_list.html')).strip()
+ self.assertEqual(actual, expected)
+
+ def test_acme_extends_pnome_source(self):
+ # Render METAL attributes in document_list
+ result = StringIO()
+ interpreter = TALInterpreter(
+ self.doclist_program, {}, self.engine, stream=result, tal=False)
+ interpreter()
+ actual = result.getvalue().strip()
+ expected = self._read(('output', 'document_list_source.html')).strip()
+ self.assertEqual(actual, expected)
+
+ def test_preview_acme_template(self):
+ # An ACME designer is previewing the ACME design. For the
+ # purposes of this use case, extending a macro should act the
+ # same as using a macro.
+ result = StringIO()
+ interpreter = TALInterpreter(
+ self.acme_program, {}, self.engine, stream=result)
+ interpreter()
+ actual = result.getvalue().strip()
+ expected = self._read(('output', 'acme_template.html')).strip()
+ self.assertEqual(actual, expected)
+
+ def test_preview_acme_template_source(self):
+ # Render METAL attributes in acme_template
+ result = StringIO()
+ interpreter = TALInterpreter(
+ self.acme_program, {}, self.engine, stream=result, tal=False)
+ interpreter()
+ actual = result.getvalue().strip()
+ expected = self._read(('output', 'acme_template_source.html')).strip()
+ self.assertEqual(actual, expected)
+
+
class I18NCornerTestCase(TestCaseBase):
def setUp(self):
@@ -155,7 +226,7 @@
'<div>THIS IS TEXT FOR <span>BARVALUE</span>.</div>\n')
def test_translate_static_text_as_dynamic_from_bytecode(self):
- program = [('version', '1.5'),
+ program = [('version', TAL_VERSION),
('mode', 'html'),
('setPosition', (1, 0)),
('beginScope', {'i18n:translate': ''}),
@@ -441,6 +512,7 @@
def test_suite():
suite = unittest.makeSuite(I18NErrorsTestCase)
suite.addTest(unittest.makeSuite(MacroErrorsTestCase))
+ suite.addTest(unittest.makeSuite(MacroExtendTestCase))
suite.addTest(unittest.makeSuite(OutputPresentationTestCase))
suite.addTest(unittest.makeSuite(ScriptTestCase))
suite.addTest(unittest.makeSuite(I18NCornerTestCase))
More information about the Zope3-Checkins
mailing list