[ZPT] Zope 2 should use Zope 3's ZPT?
Chris Withers
chris at simplistix.co.uk
Tue Nov 23 05:06:22 EST 2004
Yet another good reason why Zope 2 should use Zope 3's ZPT.
I remember someone talking about this. Can they remember who they are?
And if so, how's it going?
cheers,
Chris
Shane Hathaway wrote:
> 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))
>
> _______________________________________________
> Zope3-Checkins mailing list
> Zope3-Checkins at zope.org
> http://mail.zope.org/mailman/listinfo/zope3-checkins
>
--
Simplistix - Content Management, Zope & Python Consulting
- http://www.simplistix.co.uk
More information about the ZPT
mailing list