diff options
Diffstat (limited to 'src/zope')
47 files changed, 2031 insertions, 0 deletions
diff --git a/src/zope/pagetemplate/DEPENDENCIES.cfg b/src/zope/pagetemplate/DEPENDENCIES.cfg new file mode 100644 index 0000000..bcd721a --- /dev/null +++ b/src/zope/pagetemplate/DEPENDENCIES.cfg @@ -0,0 +1,3 @@ +zope.interface +zope.tal +zope.tales diff --git a/src/zope/pagetemplate/__init__.py b/src/zope/pagetemplate/__init__.py new file mode 100644 index 0000000..0824ece --- /dev/null +++ b/src/zope/pagetemplate/__init__.py @@ -0,0 +1,17 @@ +############################################################################## +# +# Copyright (c) 2001, 2002 Zope Corporation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (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. +# +############################################################################## +"""Page Templates + +$Id$ +""" diff --git a/src/zope/pagetemplate/architecture.txt b/src/zope/pagetemplate/architecture.txt new file mode 100644 index 0000000..637b028 --- /dev/null +++ b/src/zope/pagetemplate/architecture.txt @@ -0,0 +1,32 @@ +===================================== +ZPT (Zope Page-Template) Architecture +===================================== + +There are a number of major components that make up the page-template +architecture: + +- The TAL *compiler* and *interpreter*. This is responsible for + compiling source files and for executing compiled templates. See + the `zope.tal` package for more information. + +- An *expression engine* is responsible for compiling expressions and + for creating expression execution contexts. It is common for + applications to override expression engines to provide custom + expression support or to change the way expressions are implemented. + The `zope.app.pagetemplate` package uses this to implement trusted + and untrusted evaluation; a different engine is used for each, with + different implementations of the same type of expressions. + + Expression contexts support execution of expressions and provide + APIs for setting up variable scopes and setting variables. The + expression contexts are passed to the TAL interpreter at execution + time. + + The most commonly used expression implementation is that found in + `zope.tales`. + +- Page templates tie everything together. They assemble an expression + engine with the TAL interpreter and orchestrate management of source + and compiled template data. See `zope.pagetemplate.interfaces`. + + diff --git a/src/zope/pagetemplate/interfaces.py b/src/zope/pagetemplate/interfaces.py new file mode 100644 index 0000000..41f7451 --- /dev/null +++ b/src/zope/pagetemplate/interfaces.py @@ -0,0 +1,114 @@ +############################################################################## +# +# Copyright (c) 2002 Zope Corporation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (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. +# +############################################################################## +"""Interface that describes the 'macros' attribute of a PageTemplate. + +$Id$ +""" +from zope.interface import Interface, Attribute + + +class IPageTemplate(Interface): + """Objects that can render page templates + """ + + def __call__(*args, **kw): + """Render a page template + + The argument handling is specific to particular + implementations. Normally, however, positional arguments are + bound to the top-level `args` variable and keyword arguments + are bound to the top-level `options` variable. + """ + + def pt_edit(source, content_type): + """Set the source and content type + """ + + def pt_errors(namespace): + """Return a sequence of strings that describe errors in the template. + + The errors may occur when the template is compiled or + rendered. + + `namespace` is the set of names passed to the TALES expression + evaluator, similar to what's returned by pt_getContext(). + + This can be used to let a template author know what went wrong + when an attempt was made to render the template. + """ + + def pt_warnings(): + """Return a sequence of warnings from the parser. + + This can be useful to present to the template author to + indication forward compatibility problems with the template. + """ + + def read(): + """Get the template source + """ + + macros = Attribute("An object that implements the __getitem__ " + "protocol, containing page template macros.") + +class IPageTemplateSubclassing(IPageTemplate): + """Behavior that may be overridden or used by subclasses + """ + + + def pt_getContext(**kw): + """Compute a dictionary of top-level template names + + Responsible for returning the set of + top-level names supported in path expressions + + """ + + def pt_getEngine(): + """Returns the TALES expression evaluator. + """ + + def pt_getEngineContext(namespace): + """Return an execution context from the expression engine.""" + + def __call__(*args, **kw): + """Render a page template + + This is sometimes overridden to provide additional argument + binding. + """ + + def pt_source_file(): + """return some text describing where a bit of ZPT code came from. + + This could be a file path, a object path, etc. + """ + + def _cook(): + """Compile the source + + Results are saved in the variables: _v_errors, _v_warnings, + _v_program, and _v_macros, and the flag _v_cooked is set. + """ + def _cook_check(): + """Compiles the source if necessary + + Subclasses might override this to influence the decision about + whether compilation is necessary. + """ + + content_type = Attribute("The content-type of the generated output") + + expand = Attribute( + "Flag indicating whether the read method should expand macros") diff --git a/src/zope/pagetemplate/pagetemplate.py b/src/zope/pagetemplate/pagetemplate.py new file mode 100644 index 0000000..ea26cc1 --- /dev/null +++ b/src/zope/pagetemplate/pagetemplate.py @@ -0,0 +1,212 @@ +############################################################################## +# +# Copyright (c) 2001, 2002 Zope Corporation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (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. +# +############################################################################## +"""Page Template module + +HTML- and XML-based template objects using TAL, TALES, and METAL. + +$Id$ +""" +import sys +from zope.tal.talparser import TALParser +from zope.tal.htmltalparser import HTMLTALParser +from zope.tal.talgenerator import TALGenerator +from zope.tal.talinterpreter import TALInterpreter +from zope.tales.engine import Engine +# Don't use cStringIO here! It's not unicode aware. +from StringIO import StringIO + +from zope.pagetemplate.interfaces import IPageTemplateSubclassing +from zope.interface import implements + + +_default_options = {} +_error_start = '<!-- Page Template Diagnostics' + +class PageTemplate(object): + """Page Templates using TAL, TALES, and METAL. + + Subclassing + ----------- + + The following methods have certain internal responsibilities. + + pt_getContext(**keywords) + Should ignore keyword arguments that it doesn't care about, + and construct the namespace passed to the TALES expression + engine. This method is free to use the keyword arguments it + receives. + + pt_render(namespace, source=False, sourceAnnotations=False, showtal=False) + Responsible the TAL interpreter to perform the rendering. The + namespace argument is a mapping which defines the top-level + namespaces passed to the TALES expression engine. + + __call__(*args, **keywords) + Calls pt_getContext() to construct the top-level namespace + passed to the TALES expression engine, then calls pt_render() + to perform the rendering. + """ + + implements(IPageTemplateSubclassing) + + content_type = 'text/html' + expand = 1 + _v_errors = () + _v_program = None + _v_macros = None + _v_cooked = 0 + _text = '' + + def macros(self): + self._cook_check() + return self._v_macros + + macros = property(macros) + + def pt_edit(self, text, content_type): + if content_type: + self.content_type = str(content_type) + if hasattr(text, 'read'): + text = text.read() + self.write(text) + + def pt_getContext(self, args=(), options=_default_options, **ignored): + rval = {'template': self, + 'options': options, + 'args': args, + 'nothing': None, + } + rval.update(self.pt_getEngine().getBaseNames()) + return rval + + def __call__(self, *args, **kwargs): + return self.pt_render(self.pt_getContext(args, kwargs)) + + def pt_getEngineContext(self, namespace): + return self.pt_getEngine().getContext(namespace) + + def pt_getEngine(self): + return Engine + + def pt_render(self, namespace, source=False, sourceAnnotations=False, + showtal=False): + """Render this Page Template""" + self._cook_check() + __traceback_supplement__ = (PageTemplateTracebackSupplement, + self, namespace) + if self._v_errors: + raise PTRuntimeError(str(self._v_errors)) + + output = StringIO(u'') + context = self.pt_getEngineContext(namespace) + TALInterpreter(self._v_program, self._v_macros, + context, output, tal=not source, showtal=showtal, + strictinsert=0, sourceAnnotations=sourceAnnotations)() + return output.getvalue() + + def pt_errors(self, namespace): + self._cook_check() + err = self._v_errors + if err: + return err + try: + self.pt_render(namespace, source=1) + except: + return ('Macro expansion failed', '%s: %s' % sys.exc_info()[:2]) + + def write(self, text): + # We accept both, since the text can either come from a file (and the + # parser will take care of the encoding) or from a TTW template, in + # which case we already have unicode. + assert isinstance(text, (str, unicode)) + + if text.startswith(_error_start): + errend = text.find('-->') + if errend >= 0: + text = text[errend + 3:] + if text[:1] == "\n": + text = text[1:] + if self._text != text: + self._text = text + + # Always cook on an update, even if the source is the same; + # the content-type might have changed. + self._cook() + + def read(self, request=None): + """Gets the source, sometimes with macros expanded.""" + self._cook_check() + if not self._v_errors: + if not self.expand: + return self._text + try: + # This gets called, if macro expansion is turned on. + # Note that an empty dictionary is fine for the context at + # this point, since we are not evaluating the template. + return self.pt_render(self.pt_getContext(self, request), source=1) + except: + return ('%s\n Macro expansion failed\n %s\n-->\n%s' % + (_error_start, "%s: %s" % sys.exc_info()[:2], + self._text) ) + + return ('%s\n %s\n-->\n%s' % (_error_start, + '\n'.join(self._v_errors), + self._text)) + + def pt_source_file(self): + """To be overridden.""" + return None + + def _cook_check(self): + if not self._v_cooked: + self._cook() + + def _cook(self): + """Compile the TAL and METAL statments. + + Cooking must not fail due to compilation errors in templates. + """ + engine = self.pt_getEngine() + source_file = self.pt_source_file() + if self.content_type == 'text/html': + gen = TALGenerator(engine, xml=0, source_file=source_file) + parser = HTMLTALParser(gen) + else: + gen = TALGenerator(engine, source_file=source_file) + parser = TALParser(gen) + + self._v_errors = () + try: + parser.parseString(self._text) + self._v_program, self._v_macros = parser.getCode() + except: + self._v_errors = ["Compilation failed", + "%s: %s" % sys.exc_info()[:2]] + self._v_cooked = 1 + + +class PTRuntimeError(RuntimeError): + '''The Page Template has template errors that prevent it from rendering.''' + pass + + +class PageTemplateTracebackSupplement(object): + #implements(ITracebackSupplement) + + def __init__(self, pt, namespace): + self.manageable_object = pt + self.warnings = [] + e = pt.pt_errors(namespace) + if e: + self.warnings.extend(e) diff --git a/src/zope/pagetemplate/pagetemplatefile.py b/src/zope/pagetemplate/pagetemplatefile.py new file mode 100644 index 0000000..4fe6f0f --- /dev/null +++ b/src/zope/pagetemplate/pagetemplatefile.py @@ -0,0 +1,134 @@ +############################################################################## +# +# Copyright (c) 2001, 2002 Zope Corporation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (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. +# +############################################################################## +"""Filesystem Page Template module + +Zope object encapsulating a Page Template from the filesystem. + +$Id$ +""" + +__all__ = ("PageTemplateFile",) + +import os +import sys +import re +import logging + +from zope.pagetemplate.pagetemplate import PageTemplate + +DEFAULT_ENCODING = "utf-8" + +meta_pattern = re.compile( + r'\s*<meta\s+http-equiv=["\']?Content-Type["\']?' + r'\s+content=["\']?([^;]+);\s*charset=([^"\']+)["\']?\s*/?\s*>\s*', + re.IGNORECASE) + +def package_home(gdict): + filename = gdict["__file__"] + return os.path.dirname(filename) + +class PageTemplateFile(PageTemplate): + "Zope wrapper for filesystem Page Template using TAL, TALES, and METAL" + + _v_last_read = 0 + + def __init__(self, filename, _prefix=None): + path = self.get_path_from_prefix(_prefix) + self.filename = os.path.join(path, filename) + if not os.path.isfile(self.filename): + raise ValueError("No such file", self.filename) + + def get_path_from_prefix(self, _prefix): + if isinstance(_prefix, str): + path = _prefix + else: + if _prefix is None: + _prefix = sys._getframe(2).f_globals + path = package_home(_prefix) + return path + + def _prepare_html(self, text): + match = meta_pattern.search(text) + if match is not None: + type_, encoding = match.groups() + # TODO: Shouldn't <meta>/<?xml?> stripping + # be in PageTemplate.__call__()? + text = meta_pattern.sub("", text) + else: + type_ = None + encoding = DEFAULT_ENCODING + return unicode(text, encoding), type_ + + def _read_file(self): + __traceback_info__ = self.filename + f = open(self.filename, "rb") + try: + text = f.read(XML_PREFIX_MAX_LENGTH) + except: + f.close() + raise + type_ = sniff_type(text) + if type_ == "text/xml": + text += f.read() + else: + # For HTML, we really want the file read in text mode: + f.close() + f = open(self.filename) + text = f.read() + text, type_ = self._prepare_html(text) + f.close() + return text, type_ + + def _cook_check(self): + if self._v_last_read and not __debug__: + return + __traceback_info__ = self.filename + try: + mtime = os.path.getmtime(self.filename) + except OSError: + mtime = 0 + if self._v_program is not None and mtime == self._v_last_read: + return + text, type_ = self._read_file() + self.pt_edit(text, type_) + self._cook() + if self._v_errors: + logging.error('PageTemplateFile: Error in template %s: %s', + self.filename, '\n'.join(self._v_errors)) + return + self._v_last_read = mtime + + def pt_source_file(self): + return self.filename + + def __getstate__(self): + raise TypeError("non-picklable object") + +XML_PREFIXES = [ + "<?xml", # ascii, utf-8 + "\xef\xbb\xbf<?xml", # utf-8 w/ byte order mark + "\0<\0?\0x\0m\0l", # utf-16 big endian + "<\0?\0x\0m\0l\0", # utf-16 little endian + "\xfe\xff\0<\0?\0x\0m\0l", # utf-16 big endian w/ byte order mark + "\xff\xfe<\0?\0x\0m\0l\0", # utf-16 little endian w/ byte order mark + ] + +XML_PREFIX_MAX_LENGTH = max(map(len, XML_PREFIXES)) + +def sniff_type(text): + """Return 'text/xml' if text appears to be XML, otherwise return None.""" + for prefix in XML_PREFIXES: + if text.startswith(prefix): + return "text/xml" + return None diff --git a/src/zope/pagetemplate/readme.txt b/src/zope/pagetemplate/readme.txt new file mode 100644 index 0000000..e73b916 --- /dev/null +++ b/src/zope/pagetemplate/readme.txt @@ -0,0 +1,67 @@ +============== +Page Templates +============== + +:Author: Kapil Thangavelu <hazmat at objectrealms.net> + +.. contents:: + + +Introduction +------------ + +Page Templates provide an elegant templating mechanism that achieves a +clean separation of presentation and application logic while allowing +for designers to work with templates in their visual editing tools +(FrontPage, Dreamweaver, GoLive, etc.). + +This document focuses on usage of Page Templates outside of a Zope +context, it does *not* explain how to write page templates as there +are several resources on the web which do so. + +Simple Usage +------------ + +Using Page Templates outside of Zope3 is very easy and straight +forward. A quick example:: + + >>> from zope.pagetemplate.pagetemplatefile import PageTemplateFile + >>> my_pt = PageTemplateFile('hello_world.pt') + >>> my_pt() + u'<html><body>Hello World</body></html>' + +Subclassing PageTemplates +------------------------- + +Lets say we want to alter page templates such that keyword arguments +appear as top level items in the namespace. We can subclass +`PageTemplate` and alter the default behavior of `pt_getContext()` to +add them in:: + + from zope.pagetemplate.pagetemplate import PageTemplate + + class mypt(PageTemplate): + def pt_getContext(self, args=(), options={}, **kw): + rval = PageTemplate.pt_getContext(self, args=args) + options.update(rval) + return options + + class foo: + def getContents(self): return 'hi' + +So now we can bind objects in a more arbitrary fashion, like the +following:: + + template = """ + <html> + <body> + <b tal:replace="das_object/getContents">Good Stuff Here</b> + </body> + </html> + """ + + pt = mypt() + pt.write(template) + pt(das_object=foo()) + +See `interfaces.py`. diff --git a/src/zope/pagetemplate/tests/__init__.py b/src/zope/pagetemplate/tests/__init__.py new file mode 100644 index 0000000..b711d36 --- /dev/null +++ b/src/zope/pagetemplate/tests/__init__.py @@ -0,0 +1,2 @@ +# +# This file is necessary to make this directory a package. diff --git a/src/zope/pagetemplate/tests/batch.py b/src/zope/pagetemplate/tests/batch.py new file mode 100644 index 0000000..ec1057c --- /dev/null +++ b/src/zope/pagetemplate/tests/batch.py @@ -0,0 +1,118 @@ +############################################################################## +# +# Copyright (c) 2001, 2002 Zope Corporation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (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. +# +############################################################################## +"""Batching support tests + +$Id$ +""" + +class batch(object): + """Create a sequence batch""" + + def __init__(self, sequence, size, start=0, end=0, + orphan=3, overlap=0): + + start=start+1 + + start,end,sz=opt(start,end,size,orphan,sequence) + + self._last=end-1 + self._first=start-1 + + self._sequence=sequence + self._size=size + self._start=start + self._end=end + self._orphan=orphan + self._overlap=overlap + + def previous_sequence(self): return self._first + + def previous_sequence_end_number(self): + start,end,spam=opt(0, self._start-1+self._overlap, + self._size, self._orphan, self._sequence) + return end + + def previous_sequence_start_number(self): + start,end,spam=opt(0, self._start-1+self._overlap, + self._size, self._orphan, self._sequence) + return start + + def previous_sequence_end_item(self): + start,end,spam=opt(0, self._start-1+self._overlap, + self._size, self._orphan, self._sequence) + return self._sequence[end-1] + + def previous_sequence_start_item(self): + start,end,spam=opt(0, self._start-1+self._overlap, + self._size, self._orphan, self._sequence) + return self._sequence[start-1] + + def next_sequence_end_number(self): + start,end,spam=opt(self._end+1-self._overlap, 0, + self._size, self._orphan, self._sequence) + return end + + def next_sequence_start_number(self): + start,end,spam=opt(self._end+1-self._overlap, 0, + self._size, self._orphan, self._sequence) + return start + + def next_sequence_end_item(self): + start,end,spam=opt(self._end+1-self._overlap, 0, + self._size, self._orphan, self._sequence) + return self._sequence[end-1] + + def next_sequence_start_item(self): + start,end,spam=opt(self._end+1-self._overlap, 0, + self._size, self._orphan, self._sequence) + return self._sequence[start-1] + + + def next_sequence(self): + try: self._sequence[self._end] + except IndexError: return 0 + else: return 1 + + def __getitem__(self, index): + if index > self._last: raise IndexError(index) + return self._sequence[index+self._first] + +def opt(start,end,size,orphan,sequence): + if size < 1: + if start > 0 and end > 0 and end >= start: + size=end+1-start + else: size=7 + + if start > 0: + + try: sequence[start-1] + except: start=len(sequence) + + if end > 0: + if end < start: end=start + else: + end=start+size-1 + try: sequence[end+orphan-1] + except: end=len(sequence) + elif end > 0: + try: sequence[end-1] + except: end=len(sequence) + start=end+1-size + if start - 1 < orphan: start=1 + else: + start=1 + end=start+size-1 + try: sequence[end+orphan-1] + except: end=len(sequence) + return start,end,size diff --git a/src/zope/pagetemplate/tests/input/__init__.py b/src/zope/pagetemplate/tests/input/__init__.py new file mode 100644 index 0000000..b711d36 --- /dev/null +++ b/src/zope/pagetemplate/tests/input/__init__.py @@ -0,0 +1,2 @@ +# +# This file is necessary to make this directory a package. diff --git a/src/zope/pagetemplate/tests/input/checknotexpression.html b/src/zope/pagetemplate/tests/input/checknotexpression.html new file mode 100644 index 0000000..81f3735 --- /dev/null +++ b/src/zope/pagetemplate/tests/input/checknotexpression.html @@ -0,0 +1,9 @@ +<html> +<head></head> +<body> +<div tal:condition="not:python:0">not:python:0</div> +<div tal:condition="not:python:1">not:python:1</div> +<div tal:condition="not: python:1">not: python:1</div> +<div tal:condition="not:python:range(1,20)">not:python:range(1,20)</div> +</body> +</html> diff --git a/src/zope/pagetemplate/tests/input/checknothing.html b/src/zope/pagetemplate/tests/input/checknothing.html new file mode 100644 index 0000000..bb531ba --- /dev/null +++ b/src/zope/pagetemplate/tests/input/checknothing.html @@ -0,0 +1,7 @@ +<html> +<body> +<head> + <title tal:content="nothing">Hello World!</title> +</head> +</body> +</html> diff --git a/src/zope/pagetemplate/tests/input/checkpathalt.html b/src/zope/pagetemplate/tests/input/checkpathalt.html new file mode 100644 index 0000000..3026cda --- /dev/null +++ b/src/zope/pagetemplate/tests/input/checkpathalt.html @@ -0,0 +1,17 @@ +<html> +<body> + <div tal:define="x string:X;nil string:"> + <p tal:content="x">1</p> + <p tal:content="x | nil">2</p> + <p tal:content="python:nil or x">3</p> + <p tal:content="y/z | x">4</p> + <p tal:content="y/z | x | nil">5</p> + + <p tal:attributes="name nil">Z</p> + <p tal:attributes="name y/z | nil">Z</p> + <p tal:attributes="name y/z | nothing">Z</p> + + <p tal:on-error="python:str(error.value[0])" tal:content="a/b | c/d">Z</p> + </div> +</body> +</html> diff --git a/src/zope/pagetemplate/tests/input/checkpathnothing.html b/src/zope/pagetemplate/tests/input/checkpathnothing.html new file mode 100644 index 0000000..99f88be --- /dev/null +++ b/src/zope/pagetemplate/tests/input/checkpathnothing.html @@ -0,0 +1,7 @@ +<html> +<body> +<head> + <title tal:content="path:nothing">Hello World!</title> +</head> +</body> +</html> diff --git a/src/zope/pagetemplate/tests/input/checkwithxmlheader.html b/src/zope/pagetemplate/tests/input/checkwithxmlheader.html new file mode 100644 index 0000000..c184b36 --- /dev/null +++ b/src/zope/pagetemplate/tests/input/checkwithxmlheader.html @@ -0,0 +1,5 @@ +<?xml version="1.0" ?> +<html> +<body tal:content="string:Hello!"> +</body> +</html> diff --git a/src/zope/pagetemplate/tests/input/dtml1.html b/src/zope/pagetemplate/tests/input/dtml1.html new file mode 100644 index 0000000..421a1b1 --- /dev/null +++ b/src/zope/pagetemplate/tests/input/dtml1.html @@ -0,0 +1,19 @@ +<html xmlns:tal="http://xml.zope.org/namespaces/tal"> + <head><title>Test of documentation templates</title></head> + <body> + <span tal:replace="nothing"> blah </span> + <dl tal:condition="options/content/args"> + <dt>The arguments to this test program were:</dt> + <dd> + <ul> + <li tal:repeat="arg options/content/args"> + Argument number <span tal:replace="arg/num">99</span> + is <span tal:replace="arg/arg">default</span> + </li> + </ul> + </dd> + </dl> + <p tal:condition="not:options/content/args">No arguments were given.</p> + And thats da trooth. + </body> +</html> diff --git a/src/zope/pagetemplate/tests/input/dtml3.html b/src/zope/pagetemplate/tests/input/dtml3.html new file mode 100644 index 0000000..d3c84b2 --- /dev/null +++ b/src/zope/pagetemplate/tests/input/dtml3.html @@ -0,0 +1,33 @@ +<head><title>Test of documentation templates</title></head> +<body> + <div tal:condition="options/content/args"> + The arguments were: + <span tal:condition="options/batch/previous_sequence"> + (<span + tal:replace="options/batch/previous_sequence_start_item" + >previous start item</span>-<span + tal:replace="options/batch/previous_sequence_end_item" + >previous end item</span>) + </span> + <dl> + <span tal:repeat="arg options/batch"> + <dt><span tal:replace="arg">??</span>.</dt> + <dd>Argument <span tal:define="num arg/num" + tal:replace="string: $num" + >99</span> was <span tal:replace="arg" + >??</span></dd> + </span> + </dl> + <span tal:condition="options/batch/next_sequence"> + (<span + tal:replace="options/batch/next_sequence_start_item" + >next start item</span>-<span + tal:replace="options/batch/next_sequence_end_item" + >next end item</span>) + </span> + </div> + <p tal:condition="not:options/content/args"> + No arguments were given. + </p> + And I am 100% sure! +</body> diff --git a/src/zope/pagetemplate/tests/input/globalsshadowlocals.html b/src/zope/pagetemplate/tests/input/globalsshadowlocals.html new file mode 100644 index 0000000..c3f99e7 --- /dev/null +++ b/src/zope/pagetemplate/tests/input/globalsshadowlocals.html @@ -0,0 +1,14 @@ +<html tal:define="global x python:1"> +<head></head> +<body> + <div tal:define="x python:2"> + <span tal:content="x">Should be 2 here!</span> + </div> + <div> + <span tal:content="x">Should be 1 here!</span> + </div> + <div tal:define="global x python:3"> + <span tal:content="x">Should be 3 here!</span> + </div> +</body> +</html> diff --git a/src/zope/pagetemplate/tests/input/loop1.html b/src/zope/pagetemplate/tests/input/loop1.html new file mode 100644 index 0000000..a4d0118 --- /dev/null +++ b/src/zope/pagetemplate/tests/input/loop1.html @@ -0,0 +1,15 @@ +<html> +<head> +<title>Loop doc</title> +</head> +<body> +<p>Choose your type:</p> +<ul> + <li tal:repeat="type python:'digital', 'analog', 'organic'"> + <a href="dummy" tal:attributes="href string:/mach/$type"> + <span tal:replace="repeat/type/number">1</span>. + <span tal:replace="type">selection</span></a> + </li> +</ul> +</body> +</html> diff --git a/src/zope/pagetemplate/tests/input/stringexpression.html b/src/zope/pagetemplate/tests/input/stringexpression.html new file mode 100644 index 0000000..a60e72d --- /dev/null +++ b/src/zope/pagetemplate/tests/input/stringexpression.html @@ -0,0 +1,7 @@ +<html> +<body> +<head> + <title tal:content="string:Hello World!">This is the title</title> +</head> +</body> +</html> diff --git a/src/zope/pagetemplate/tests/input/teeshop1.html b/src/zope/pagetemplate/tests/input/teeshop1.html new file mode 100644 index 0000000..111381b --- /dev/null +++ b/src/zope/pagetemplate/tests/input/teeshop1.html @@ -0,0 +1,87 @@ +<html metal:use-macro="options/laf/macros/page"> +<head> +<title>Zope Stuff</title> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> +<link rel="stylesheet" href="/common.css"> +</head> + +<body bgcolor="#FFFFFF" leftmargin="0" topmargin="0" marginwidth="0" marginheight="0"> +<table width="100%" border="0" cellspacing="0" cellpadding="0"> + <tr bgcolor="#0000CC" align="center"> + <td> + <table width="200" border="0" cellspacing="0" cellpadding="0"> + <tr bgcolor="#FFFFFF"> + <td><img src="/images/lside.gif" width="52" height="94"><img src="/images/swlogo.gif" width="150" height="89"><img src="/images/rside.gif" width="52" height="94"></td> + </tr> + </table> + </td> + </tr> +</table> +<br> +<table width="300" border="0" cellspacing="0" cellpadding="0" align="center"> + <tr align="center"> + <td width="25%" class="boldbodylist">apparel</td> + <td width="25%" class="boldbodylist">mugs</td> + <td width="25%" class="boldbodylist">toys</td> + <td width="25%" class="boldbodylist">misc</td> + </tr> +</table> +<br> +<br> +<div metal:fill-slot="body"> +<table width="500" border="0" cellspacing="0" cellpadding="0" align="center"> + <tr> + <td bgcolor="#0000CC"> + <table width="100%" border="0" cellspacing="1" cellpadding="3"> + <tr bgcolor="#FFFFFF" align="center"> + <td><img src="/images/welcome.gif" width="293" height="28"></td> + </tr> + <tr bgcolor="#FFFFFF" align="center" valign="top" + tal:repeat="product options/getProducts"> + <td> + <table width="100%" border="0" cellspacing="0" cellpadding="6"> + <tr> + <td colspan="2" class="bodylist" height="200" valign="top"><b>Description: + </b><span tal:replace="product/description">This is the tee for those who LOVE Zope. Show your heart + on your tee.</span></td> + <td align="right" width="1%" rowspan="2"> + <p><img src="/images/smlatee.jpg" width="200" height="200" + tal:attributes="src string:/images/${product/image}"></p> + </td> + </tr> + <tr> + <td class="bodylist"><img src="images/clear.gif" width="150" height="10"></td> + <td class="bodylist"><b>Price</b>:<span tal:replace="product/price">12.99</span></td> + </tr> + </table> + </td> + </tr> + <tr bgcolor="#FFFFFF" align="center" valign="top"> + <td> + <table width="100%" border="0" cellspacing="0" cellpadding="6"> + <tr> + <td align="center"><img src="images/buttons/submit.gif" width="87" height="30"></td> + <td align="center"><img src="images/buttons/cancel.gif" width="87" height="30"></td> + </tr> + </table> + </td> + </tr> + </table> + </td> + </tr> +</table> +</div> +<p> </p><table width="100%" border="0" cellspacing="1" cellpadding="3" align="center"> + <tr > + <td align="center" bgcolor="#FFFFFF" class="bodylist"> Copyright © 2000 <a href="http://www.4-am.com">4AM + Productions, Inc.</a>. All rights reserved. <br> + Questions or problems should be directed to <a href="mailto:webmaster@teamzonline.com"> + the webmaster</a>, 254-412-0846. </td> + </tr> + <tr> + <td align="center"><img src="/images/zopelogos/buildzope.gif" width="54" height="54"></td> + </tr> +</table> +<p> </p> +</body> +</html> diff --git a/src/zope/pagetemplate/tests/input/teeshop2.html b/src/zope/pagetemplate/tests/input/teeshop2.html new file mode 100644 index 0000000..7ca0cf1 --- /dev/null +++ b/src/zope/pagetemplate/tests/input/teeshop2.html @@ -0,0 +1,5 @@ +<html metal:use-macro="options/laf/macros/page"> +<div metal:fill-slot="body"> +Body +</div> +</html> diff --git a/src/zope/pagetemplate/tests/input/teeshoplaf.html b/src/zope/pagetemplate/tests/input/teeshoplaf.html new file mode 100644 index 0000000..f9477c3 --- /dev/null +++ b/src/zope/pagetemplate/tests/input/teeshoplaf.html @@ -0,0 +1,73 @@ +<html metal:define-macro="page"> +<head> +<title>Zope Stuff</title> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> +<link rel="stylesheet" href="/common.css"> +</head> + +<body bgcolor="#FFFFFF" leftmargin="0" topmargin="0" marginwidth="0" marginheight="0"> +<table width="100%" border="0" cellspacing="0" cellpadding="0"> + <tr bgcolor="#0000CC" align="center"> + <td> + <table width="200" border="0" cellspacing="0" cellpadding="0"> + <tr bgcolor="#FFFFFF"> + <td><img src="/images/lside.gif" width="52" height="94"><img src="/images/swlogo.gif" width="150" height="89"><img src="/images/rside.gif" width="52" height="94"></td> + </tr> + </table> + </td> + </tr> +</table> +<br> +<table width="300" border="0" cellspacing="0" cellpadding="0" align="center"> + <tr align="center"> + <td width="25%" class="boldbodylist">apparel</td> + <td width="25%" class="boldbodylist">mugs</td> + <td width="25%" class="boldbodylist">toys</td> + <td width="25%" class="boldbodylist">misc</td> + </tr> +</table> +<br> +<br> +<div metal:define-slot="body"> +<table width="500" border="0" cellspacing="0" cellpadding="0" align="center"> + <tr> + <td bgcolor="#0000CC"> + <table width="100%" border="0" cellspacing="1" cellpadding="3"> + <tr bgcolor="#FFFFFF" align="center"> + <td><img src="/images/welcome.gif" width="293" height="28"></td> + </tr> + <tr bgcolor="#FFFFFF" align="center" valign="top"> + <td> <br> + <table width="100%" border="0" cellspacing="0" cellpadding="6"> + <tr> + <td>This is the tee for those who LOVE Zope. Show your heart on + your tee.</td> + <td align="right" width="1%"> + <p><img src="/images/smlatee.jpg" width="200" height="200"></p> + </td> + </tr> + </table> + </td> + </tr> + </table> + </td> + </tr> +</table> +</div> +<br><br> +<table width="100%" border="0" cellspacing="1" cellpadding="3" align="center"> + <tr> + <td align="center" bgcolor="#FFFFFF" class="bodylist"> + Copyright © 2000 + <a href="http://www.4-am.com">4AM Productions, Inc.</a>. + All rights reserved. <br> + Questions or problems should be directed to + <a href="mailto:webmaster@teamzonline.com">the webmaster</a>, + 254-412-0846.</td> + </tr> + <tr> + <td align="center"><img src="/images/zopelogos/buildzope.gif" width="54" height="54"></td> + </tr> +</table> +</body> +</html> diff --git a/src/zope/pagetemplate/tests/input/translation.html b/src/zope/pagetemplate/tests/input/translation.html new file mode 100644 index 0000000..1df9bd5 --- /dev/null +++ b/src/zope/pagetemplate/tests/input/translation.html @@ -0,0 +1,2 @@ +<p i18n:translate="">Define and translate message id in ZPT</p> +<p tal:content="options/msg">Insert Message object here</p> diff --git a/src/zope/pagetemplate/tests/output/__init__.py b/src/zope/pagetemplate/tests/output/__init__.py new file mode 100644 index 0000000..b711d36 --- /dev/null +++ b/src/zope/pagetemplate/tests/output/__init__.py @@ -0,0 +1,2 @@ +# +# This file is necessary to make this directory a package. diff --git a/src/zope/pagetemplate/tests/output/checknotexpression.html b/src/zope/pagetemplate/tests/output/checknotexpression.html new file mode 100644 index 0000000..48e2ba0 --- /dev/null +++ b/src/zope/pagetemplate/tests/output/checknotexpression.html @@ -0,0 +1,9 @@ +<html> +<head></head> +<body> +<div>not:python:0</div> + + + +</body> +</html> diff --git a/src/zope/pagetemplate/tests/output/checknothing.html b/src/zope/pagetemplate/tests/output/checknothing.html new file mode 100644 index 0000000..c65a966 --- /dev/null +++ b/src/zope/pagetemplate/tests/output/checknothing.html @@ -0,0 +1,7 @@ +<html> +<body> +<head> + <title></title> +</head> +</body> +</html> diff --git a/src/zope/pagetemplate/tests/output/checkpathalt.html b/src/zope/pagetemplate/tests/output/checkpathalt.html new file mode 100644 index 0000000..ba33be1 --- /dev/null +++ b/src/zope/pagetemplate/tests/output/checkpathalt.html @@ -0,0 +1,17 @@ +<html> +<body> + <div> + <p>X</p> + <p>X</p> + <p>X</p> + <p>X</p> + <p>X</p> + + <p name="">Z</p> + <p name="">Z</p> + <p>Z</p> + + <p>c</p> + </div> +</body> +</html> diff --git a/src/zope/pagetemplate/tests/output/checkpathnothing.html b/src/zope/pagetemplate/tests/output/checkpathnothing.html new file mode 100644 index 0000000..c65a966 --- /dev/null +++ b/src/zope/pagetemplate/tests/output/checkpathnothing.html @@ -0,0 +1,7 @@ +<html> +<body> +<head> + <title></title> +</head> +</body> +</html> diff --git a/src/zope/pagetemplate/tests/output/checkwithxmlheader.html b/src/zope/pagetemplate/tests/output/checkwithxmlheader.html new file mode 100644 index 0000000..d2afeb0 --- /dev/null +++ b/src/zope/pagetemplate/tests/output/checkwithxmlheader.html @@ -0,0 +1,4 @@ +<?xml version="1.0" ?> +<html> +<body>Hello!</body> +</html> diff --git a/src/zope/pagetemplate/tests/output/dtml1a.html b/src/zope/pagetemplate/tests/output/dtml1a.html new file mode 100644 index 0000000..f146b34 --- /dev/null +++ b/src/zope/pagetemplate/tests/output/dtml1a.html @@ -0,0 +1,34 @@ +<html> + <head><title>Test of documentation templates</title></head> + <body> + + <dl> + <dt>The arguments to this test program were:</dt> + <dd> + <ul> + <li> + Argument number 1 + is one + </li><li> + Argument number 2 + is two + </li><li> + Argument number 3 + is three + </li><li> + Argument number 4 + is cha + </li><li> + Argument number 5 + is cha + </li><li> + Argument number 6 + is cha + </li> + </ul> + </dd> + </dl> + + And thats da trooth. + </body> +</html> diff --git a/src/zope/pagetemplate/tests/output/dtml1b.html b/src/zope/pagetemplate/tests/output/dtml1b.html new file mode 100644 index 0000000..edc7637 --- /dev/null +++ b/src/zope/pagetemplate/tests/output/dtml1b.html @@ -0,0 +1,7 @@ +<html> + <head><title>Test of documentation templates</title></head> + <body> + <p>No arguments were given.</p> + And thats da trooth. + </body> +</html> diff --git a/src/zope/pagetemplate/tests/output/dtml3.html b/src/zope/pagetemplate/tests/output/dtml3.html new file mode 100644 index 0000000..fd774e1 --- /dev/null +++ b/src/zope/pagetemplate/tests/output/dtml3.html @@ -0,0 +1,30 @@ +<head><title>Test of documentation templates</title></head> +<body> + <div> + The arguments were: + + <dl> + <span> + <dt>one.</dt> + <dd>Argument 1 was one</dd> + </span><span> + <dt>two.</dt> + <dd>Argument 2 was two</dd> + </span><span> + <dt>three.</dt> + <dd>Argument 3 was three</dd> + </span><span> + <dt>four.</dt> + <dd>Argument 4 was four</dd> + </span><span> + <dt>five.</dt> + <dd>Argument 5 was five</dd> + </span> + </dl> + <span> + (six-ten) + </span> + </div> + + And I am 100% sure! +</body> diff --git a/src/zope/pagetemplate/tests/output/globalsshadowlocals.html b/src/zope/pagetemplate/tests/output/globalsshadowlocals.html new file mode 100644 index 0000000..e22e59b --- /dev/null +++ b/src/zope/pagetemplate/tests/output/globalsshadowlocals.html @@ -0,0 +1,14 @@ +<html> +<head></head> +<body> + <div> + <span>2</span> + </div> + <div> + <span>1</span> + </div> + <div> + <span>3</span> + </div> +</body> +</html> diff --git a/src/zope/pagetemplate/tests/output/loop1.html b/src/zope/pagetemplate/tests/output/loop1.html new file mode 100644 index 0000000..f16ea89 --- /dev/null +++ b/src/zope/pagetemplate/tests/output/loop1.html @@ -0,0 +1,25 @@ +<html> +<head> +<title>Loop doc</title> +</head> +<body> +<p>Choose your type:</p> +<ul> + <li> + <a href="/mach/digital"> + 1. + digital</a> + </li> + <li> + <a href="/mach/analog"> + 2. + analog</a> + </li> + <li> + <a href="/mach/organic"> + 3. + organic</a> + </li> +</ul> +</body> +</html> diff --git a/src/zope/pagetemplate/tests/output/stringexpression.html b/src/zope/pagetemplate/tests/output/stringexpression.html new file mode 100644 index 0000000..58b55f5 --- /dev/null +++ b/src/zope/pagetemplate/tests/output/stringexpression.html @@ -0,0 +1,7 @@ +<html> +<body> +<head> + <title>Hello World!</title> +</head> +</body> +</html> diff --git a/src/zope/pagetemplate/tests/output/teeshop1.html b/src/zope/pagetemplate/tests/output/teeshop1.html new file mode 100644 index 0000000..e5a3c43 --- /dev/null +++ b/src/zope/pagetemplate/tests/output/teeshop1.html @@ -0,0 +1,106 @@ +<html> +<head> +<title>Zope Stuff</title> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> +<link rel="stylesheet" href="/common.css"> +</head> + +<body bgcolor="#FFFFFF" leftmargin="0" topmargin="0" marginwidth="0" marginheight="0"> +<table width="100%" border="0" cellspacing="0" cellpadding="0"> + <tr bgcolor="#0000CC" align="center"> + <td> + <table width="200" border="0" cellspacing="0" cellpadding="0"> + <tr bgcolor="#FFFFFF"> + <td><img src="/images/lside.gif" width="52" height="94"><img src="/images/swlogo.gif" width="150" height="89"><img src="/images/rside.gif" width="52" height="94"></td> + </tr> + </table> + </td> + </tr> +</table> +<br> +<table width="300" border="0" cellspacing="0" cellpadding="0" align="center"> + <tr align="center"> + <td width="25%" class="boldbodylist">apparel</td> + <td width="25%" class="boldbodylist">mugs</td> + <td width="25%" class="boldbodylist">toys</td> + <td width="25%" class="boldbodylist">misc</td> + </tr> +</table> +<br> +<br> +<div> +<table width="500" border="0" cellspacing="0" cellpadding="0" align="center"> + <tr> + <td bgcolor="#0000CC"> + <table width="100%" border="0" cellspacing="1" cellpadding="3"> + <tr bgcolor="#FFFFFF" align="center"> + <td><img src="/images/welcome.gif" width="293" height="28"></td> + </tr> + <tr bgcolor="#FFFFFF" align="center" valign="top"> + <td> + <table width="100%" border="0" cellspacing="0" cellpadding="6"> + <tr> + <td colspan="2" class="bodylist" height="200" valign="top"><b>Description: + </b>This is the tee for those who LOVE Zope. Show your heart on your tee.</td> + <td align="right" width="1%" rowspan="2"> + <p><img src="/images/smlatee.jpg" + width="200" height="200"></p> + </td> + </tr> + <tr> + <td class="bodylist"><img src="images/clear.gif" width="150" height="10"></td> + <td class="bodylist"><b>Price</b>:12.99</td> + </tr> + </table> + </td> + </tr> + <tr bgcolor="#FFFFFF" align="center" valign="top"> + <td> + <table width="100%" border="0" cellspacing="0" cellpadding="6"> + <tr> + <td colspan="2" class="bodylist" height="200" valign="top"><b>Description: + </b>This is the tee for Jim Fulton. He's the Zope Pope!</td> + <td align="right" width="1%" rowspan="2"> + <p><img src="/images/smpztee.jpg" + width="200" height="200"></p> + </td> + </tr> + <tr> + <td class="bodylist"><img src="images/clear.gif" width="150" height="10"></td> + <td class="bodylist"><b>Price</b>:11.99</td> + </tr> + </table> + </td> + </tr> + <tr bgcolor="#FFFFFF" align="center" valign="top"> + <td> + <table width="100%" border="0" cellspacing="0" cellpadding="6"> + <tr> + <td align="center"><img src="images/buttons/submit.gif" width="87" height="30"></td> + <td align="center"><img src="images/buttons/cancel.gif" width="87" height="30"></td> + </tr> + </table> + </td> + </tr> + </table> + </td> + </tr> +</table> +</div> +<br><br> +<table width="100%" border="0" cellspacing="1" cellpadding="3" align="center"> + <tr> + <td align="center" bgcolor="#FFFFFF" class="bodylist"> + Copyright © 2000 + <a href="http://www.4-am.com">4AM Productions, Inc.</a>. + All rights reserved. <br> + Questions or problems should be directed to + <a href="mailto:webmaster@teamzonline.com">the webmaster</a>, + 254-412-0846.</td> + </tr> + <tr> + <td align="center"><img src="/images/zopelogos/buildzope.gif" width="54" height="54"></td> + </tr> +</table> +</body> +</html> diff --git a/src/zope/pagetemplate/tests/output/teeshop2.html b/src/zope/pagetemplate/tests/output/teeshop2.html new file mode 100644 index 0000000..9eef0f2 --- /dev/null +++ b/src/zope/pagetemplate/tests/output/teeshop2.html @@ -0,0 +1,50 @@ +<html> +<head> +<title>Zope Stuff</title> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> +<link rel="stylesheet" href="/common.css"> +</head> + +<body bgcolor="#FFFFFF" leftmargin="0" topmargin="0" marginwidth="0" marginheight="0"> +<table width="100%" border="0" cellspacing="0" cellpadding="0"> + <tr bgcolor="#0000CC" align="center"> + <td> + <table width="200" border="0" cellspacing="0" cellpadding="0"> + <tr bgcolor="#FFFFFF"> + <td><img src="/images/lside.gif" width="52" height="94"><img src="/images/swlogo.gif" width="150" height="89"><img src="/images/rside.gif" width="52" height="94"></td> + </tr> + </table> + </td> + </tr> +</table> +<br> +<table width="300" border="0" cellspacing="0" cellpadding="0" align="center"> + <tr align="center"> + <td width="25%" class="boldbodylist">apparel</td> + <td width="25%" class="boldbodylist">mugs</td> + <td width="25%" class="boldbodylist">toys</td> + <td width="25%" class="boldbodylist">misc</td> + </tr> +</table> +<br> +<br> +<div> +Body +</div> +<br><br> +<table width="100%" border="0" cellspacing="1" cellpadding="3" align="center"> + <tr> + <td align="center" bgcolor="#FFFFFF" class="bodylist"> + Copyright © 2000 + <a href="http://www.4-am.com">4AM Productions, Inc.</a>. + All rights reserved. <br> + Questions or problems should be directed to + <a href="mailto:webmaster@teamzonline.com">the webmaster</a>, + 254-412-0846.</td> + </tr> + <tr> + <td align="center"><img src="/images/zopelogos/buildzope.gif" width="54" height="54"></td> + </tr> +</table> +</body> +</html> diff --git a/src/zope/pagetemplate/tests/output/teeshoplaf.html b/src/zope/pagetemplate/tests/output/teeshoplaf.html new file mode 100644 index 0000000..547dd6d --- /dev/null +++ b/src/zope/pagetemplate/tests/output/teeshoplaf.html @@ -0,0 +1,73 @@ +<html> +<head> +<title>Zope Stuff</title> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> +<link rel="stylesheet" href="/common.css"> +</head> + +<body bgcolor="#FFFFFF" leftmargin="0" topmargin="0" marginwidth="0" marginheight="0"> +<table width="100%" border="0" cellspacing="0" cellpadding="0"> + <tr bgcolor="#0000CC" align="center"> + <td> + <table width="200" border="0" cellspacing="0" cellpadding="0"> + <tr bgcolor="#FFFFFF"> + <td><img src="/images/lside.gif" width="52" height="94"><img src="/images/swlogo.gif" width="150" height="89"><img src="/images/rside.gif" width="52" height="94"></td> + </tr> + </table> + </td> + </tr> +</table> +<br> +<table width="300" border="0" cellspacing="0" cellpadding="0" align="center"> + <tr align="center"> + <td width="25%" class="boldbodylist">apparel</td> + <td width="25%" class="boldbodylist">mugs</td> + <td width="25%" class="boldbodylist">toys</td> + <td width="25%" class="boldbodylist">misc</td> + </tr> +</table> +<br> +<br> +<div> +<table width="500" border="0" cellspacing="0" cellpadding="0" align="center"> + <tr> + <td bgcolor="#0000CC"> + <table width="100%" border="0" cellspacing="1" cellpadding="3"> + <tr bgcolor="#FFFFFF" align="center"> + <td><img src="/images/welcome.gif" width="293" height="28"></td> + </tr> + <tr bgcolor="#FFFFFF" align="center" valign="top"> + <td> <br> + <table width="100%" border="0" cellspacing="0" cellpadding="6"> + <tr> + <td>This is the tee for those who LOVE Zope. Show your heart on + your tee.</td> + <td align="right" width="1%"> + <p><img src="/images/smlatee.jpg" width="200" height="200"></p> + </td> + </tr> + </table> + </td> + </tr> + </table> + </td> + </tr> +</table> +</div> +<br><br> +<table width="100%" border="0" cellspacing="1" cellpadding="3" align="center"> + <tr> + <td align="center" bgcolor="#FFFFFF" class="bodylist"> + Copyright © 2000 + <a href="http://www.4-am.com">4AM Productions, Inc.</a>. + All rights reserved. <br> + Questions or problems should be directed to + <a href="mailto:webmaster@teamzonline.com">the webmaster</a>, + 254-412-0846.</td> + </tr> + <tr> + <td align="center"><img src="/images/zopelogos/buildzope.gif" width="54" height="54"></td> + </tr> +</table> +</body> +</html> diff --git a/src/zope/pagetemplate/tests/output/translation.html b/src/zope/pagetemplate/tests/output/translation.html new file mode 100644 index 0000000..4335d11 --- /dev/null +++ b/src/zope/pagetemplate/tests/output/translation.html @@ -0,0 +1,2 @@ +<p>Define and translate message id in ZPT</p> +<p>Translate this!</p> diff --git a/src/zope/pagetemplate/tests/test_basictemplate.py b/src/zope/pagetemplate/tests/test_basictemplate.py new file mode 100644 index 0000000..376a8d6 --- /dev/null +++ b/src/zope/pagetemplate/tests/test_basictemplate.py @@ -0,0 +1,162 @@ +############################################################################## +# +# Copyright (c) 2001, 2002 Zope Corporation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (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. +# +############################################################################## +"""Basic Page Template tests + +$Id$ +""" +import unittest + +from zope.pagetemplate.tests import util +from zope.pagetemplate.pagetemplate import PageTemplate + +class BasicTemplateTests(unittest.TestCase): + + def setUp(self): + self.t = PageTemplate() + + def test_if_in_var(self): + # DTML test 1: if, in, and var: + pass # for unittest + """ + %(comment)[ blah %(comment)] + <html><head><title>Test of documentation templates</title></head> + <body> + %(if args)[ + <dl><dt>The arguments to this test program were:<p> + <dd> + <ul> + %(in args)[ + <li>Argument number %(num)d was %(arg)s + %(in args)] + </ul></dl><p> + %(if args)] + %(else args)[ + No arguments were given.<p> + %(else args)] + And thats da trooth. + </body></html> + """ + tal = util.read_input('dtml1.html') + self.t.write(tal) + + aa = util.argv(('one', 'two', 'three', 'cha', 'cha', 'cha')) + o = self.t(content=aa) + expect = util.read_output('dtml1a.html') + + util.check_xml(expect, o) + + aa = util.argv(()) + o = self.t(content=aa) + expect = util.read_output('dtml1b.html') + util.check_xml(expect, o) + + def test_batches_and_formatting(self): + # DTML test 3: batches and formatting: + pass # for unittest + """ + <html><head><title>Test of documentation templates</title></head> + <body> + <!--#if args--> + The arguments were: + <!--#in args size=size end=end--> + <!--#if previous-sequence--> + (<!--#var previous-sequence-start-arg-->- + <!--#var previous-sequence-end-arg-->) + <!--#/if previous-sequence--> + <!--#if sequence-start--> + <dl> + <!--#/if sequence-start--> + <dt><!--#var sequence-arg-->.</dt> + <dd>Argument <!--#var num fmt=d--> was <!--#var arg--></dd> + <!--#if next-sequence--> + (<!--#var next-sequence-start-arg-->- + <!--#var next-sequence-end-arg-->) + <!--#/if next-sequence--> + <!--#/in args--> + </dl> + <!--#else args--> + No arguments were given.<p> + <!--#/if args--> + And I\'m 100% sure! + </body></html> + """ + tal = util.read_input('dtml3.html') + self.t.write(tal) + + aa = util.argv(('one', 'two', 'three', 'four', 'five', + 'six', 'seven', 'eight', 'nine', 'ten', + 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', + 'sixteen', 'seventeen', 'eighteen', 'nineteen', + 'twenty', + )) + from zope.pagetemplate.tests import batch + o = self.t(content=aa, batch=batch.batch(aa.args, 5)) + + expect = util.read_output('dtml3.html') + util.check_xml(expect, o) + + def test_on_error_in_slot_filler(self): + # The `here` isn't defined, so the macro definition is + # expected to catch the error that gets raised. + text = '''\ + <div metal:define-macro="foo"> + <div tal:on-error="string:eek"> + <div metal:define-slot="slot" /> + cool + </div> + </div> + + <div metal:use-macro="template/macros/foo"> + <div metal:fill-slot="slot"> + <p tal:content="here/xxx" /> + </div> + </div> + ''' + self.t.write(text) + self.t() + + def test_on_error_in_slot_default(self): + # The `here` isn't defined, so the macro definition is + # expected to catch the error that gets raised. + text = '''\ + <div metal:define-macro="foo"> + <div tal:on-error="string:eek"> + <div metal:define-slot="slot"> + <div tal:content="here/xxx" /> + </div> + </div> + </div> + + <div metal:use-macro="template/macros/foo"> + </div> + ''' + self.t.write(text) + self.t() + + def test_unicode_html(self): + text = u'<p>\xe4\xf6\xfc\xdf</p>' + + # test with HTML parser + self.t.pt_edit(text, 'text/html') + self.assertEquals(self.t().strip(), text) + + # test with XML parser + self.t.pt_edit(text, 'text/xml') + self.assertEquals(self.t().strip(), text) + +def test_suite(): + return unittest.makeSuite(BasicTemplateTests) + +if __name__ == '__main__': + unittest.TextTestRunner().run(test_suite()) diff --git a/src/zope/pagetemplate/tests/test_htmltests.py b/src/zope/pagetemplate/tests/test_htmltests.py new file mode 100644 index 0000000..cc76d11 --- /dev/null +++ b/src/zope/pagetemplate/tests/test_htmltests.py @@ -0,0 +1,143 @@ +############################################################################## +# +# Copyright (c) 2001, 2002 Zope Corporation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (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. +# +############################################################################## +"""Page Template HTML Tests + +$Id$ +""" +import unittest + +from zope.pagetemplate.tests import util +from zope.pagetemplate.pagetemplate import PageTemplate + + +class Folder(object): + context = property(lambda self: self) + +class HTMLTests(unittest.TestCase): + + def setUp(self): + self.folder = f = Folder() + f.laf = PageTemplate() + f.t = PageTemplate() + + def getProducts(self): + return [ + {'description': 'This is the tee for those who LOVE Zope. ' + 'Show your heart on your tee.', + 'price': 12.99, 'image': 'smlatee.jpg' + }, + {'description': 'This is the tee for Jim Fulton. ' + 'He\'s the Zope Pope!', + 'price': 11.99, 'image': 'smpztee.jpg' + }, + ] + + def test_1(self): + laf = self.folder.laf + laf.write(util.read_input('teeshoplaf.html')) + expect = util.read_output('teeshoplaf.html') + util.check_html(expect, laf()) + + def test_2(self): + self.folder.laf.write(util.read_input('teeshoplaf.html')) + + t = self.folder.t + t.write(util.read_input('teeshop2.html')) + expect = util.read_output('teeshop2.html') + out = t(laf = self.folder.laf, getProducts = self.getProducts) + util.check_html(expect, out) + + + def test_3(self): + self.folder.laf.write(util.read_input('teeshoplaf.html')) + + t = self.folder.t + t.write(util.read_input('teeshop1.html')) + expect = util.read_output('teeshop1.html') + out = t(laf = self.folder.laf, getProducts = self.getProducts) + util.check_html(expect, out) + + def test_SimpleLoop(self): + t = self.folder.t + t.write(util.read_input('loop1.html')) + expect = util.read_output('loop1.html') + out = t() + util.check_html(expect, out) + + def test_GlobalsShadowLocals(self): + t = self.folder.t + t.write(util.read_input('globalsshadowlocals.html')) + expect = util.read_output('globalsshadowlocals.html') + out = t() + util.check_html(expect, out) + + def test_StringExpressions(self): + t = self.folder.t + t.write(util.read_input('stringexpression.html')) + expect = util.read_output('stringexpression.html') + out = t() + util.check_html(expect, out) + + def test_ReplaceWithNothing(self): + t = self.folder.t + t.write(util.read_input('checknothing.html')) + expect = util.read_output('checknothing.html') + out = t() + util.check_html(expect, out) + + def test_WithXMLHeader(self): + t = self.folder.t + t.write(util.read_input('checkwithxmlheader.html')) + expect = util.read_output('checkwithxmlheader.html') + out = t() + util.check_html(expect, out) + + def test_NotExpression(self): + t = self.folder.t + t.write(util.read_input('checknotexpression.html')) + expect = util.read_output('checknotexpression.html') + out = t() + util.check_html(expect, out) + + def test_PathNothing(self): + t = self.folder.t + t.write(util.read_input('checkpathnothing.html')) + expect = util.read_output('checkpathnothing.html') + out = t() + util.check_html(expect, out) + + def test_PathAlt(self): + t = self.folder.t + t.write(util.read_input('checkpathalt.html')) + expect = util.read_output('checkpathalt.html') + out = t() + util.check_html(expect, out) + + def test_translation(self): + from zope.i18nmessageid import MessageFactory + _ = MessageFactory('pttest') + msg = _("Translate this!") + + t = self.folder.t + t.write(util.read_input('translation.html')) + expect = util.read_output('translation.html') + out = t(msg=msg) + util.check_html(expect, out) + + +def test_suite(): + return unittest.makeSuite(HTMLTests) + +if __name__=='__main__': + unittest.TextTestRunner().run(test_suite()) diff --git a/src/zope/pagetemplate/tests/test_ptfile.py b/src/zope/pagetemplate/tests/test_ptfile.py new file mode 100644 index 0000000..078bba5 --- /dev/null +++ b/src/zope/pagetemplate/tests/test_ptfile.py @@ -0,0 +1,189 @@ +############################################################################## +# +# Copyright (c) 2004 Zope Corporation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (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. +# +############################################################################## +"""Tests of PageTemplateFile. + +$Id$ +""" +import os +import tempfile +import unittest + +from zope.pagetemplate.pagetemplatefile import PageTemplateFile + + +class TypeSniffingTestCase(unittest.TestCase): + + TEMPFILENAME = tempfile.mktemp() + + def tearDown(self): + if os.path.exists(self.TEMPFILENAME): + os.unlink(self.TEMPFILENAME) + + def get_pt(self, text): + f = open(self.TEMPFILENAME, "wb") + f.write(text) + f.close() + pt = PageTemplateFile(self.TEMPFILENAME) + pt.read() + return pt + + def check_content_type(self, text, expected_type): + pt = self.get_pt(text) + self.assertEqual(pt.content_type, expected_type) + + def test_sniffer_xml_ascii(self): + self.check_content_type( + "<?xml version='1.0' encoding='ascii'?><doc/>", + "text/xml") + self.check_content_type( + "<?xml\tversion='1.0' encoding='ascii'?><doc/>", + "text/xml") + + def test_sniffer_xml_utf8(self): + # w/out byte order mark + self.check_content_type( + "<?xml version='1.0' encoding='utf-8'?><doc/>", + "text/xml") + self.check_content_type( + "<?xml\tversion='1.0' encoding='utf-8'?><doc/>", + "text/xml") + # with byte order mark + self.check_content_type( + "\xef\xbb\xbf<?xml version='1.0' encoding='utf-8'?><doc/>", + "text/xml") + self.check_content_type( + "\xef\xbb\xbf<?xml\tversion='1.0' encoding='utf-8'?><doc/>", + "text/xml") + + def test_sniffer_xml_utf16_be(self): + # w/out byte order mark + self.check_content_type( + "\0<\0?\0x\0m\0l\0 \0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'" + "\0 \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>" + "\0<\0d\0o\0c\0/\0>", + "text/xml") + self.check_content_type( + "\0<\0?\0x\0m\0l\0\t\0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'" + "\0 \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>" + "\0<\0d\0o\0c\0/\0>", + "text/xml") + # with byte order mark + self.check_content_type( + "\xfe\xff" + "\0<\0?\0x\0m\0l\0 \0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'" + "\0 \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>" + "\0<\0d\0o\0c\0/\0>", + "text/xml") + self.check_content_type( + "\xfe\xff" + "\0<\0?\0x\0m\0l\0\t\0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'" + "\0 \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>" + "\0<\0d\0o\0c\0/\0>", + "text/xml") + + def test_sniffer_xml_utf16_le(self): + # w/out byte order mark + self.check_content_type( + "<\0?\0x\0m\0l\0 \0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'\0" + " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>\0" + "<\0d\0o\0c\0/\0>\n", + "text/xml") + self.check_content_type( + "<\0?\0x\0m\0l\0\t\0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'\0" + " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>\0" + "<\0d\0o\0c\0/\0>\0", + "text/xml") + # with byte order mark + self.check_content_type( + "\xff\xfe" + "<\0?\0x\0m\0l\0 \0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'\0" + " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>\0" + "<\0d\0o\0c\0/\0>\0", + "text/xml") + self.check_content_type( + "\xff\xfe" + "<\0?\0x\0m\0l\0\t\0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'\0" + " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>\0" + "<\0d\0o\0c\0/\0>\0", + "text/xml") + + HTML_PUBLIC_ID = "-//W3C//DTD HTML 4.01 Transitional//EN" + HTML_SYSTEM_ID = "http://www.w3.org/TR/html4/loose.dtd" + + def test_sniffer_html_ascii(self): + self.check_content_type( + "<!DOCTYPE html [ SYSTEM '%s' ]><html></html>" + % self.HTML_SYSTEM_ID, + "text/html") + self.check_content_type( + "<html><head><title>sample document</title></head></html>", + "text/html") + + # TODO: This reflects a case that simply isn't handled by the + # sniffer; there are many, but it gets it right more often than + # before. + def donttest_sniffer_xml_simple(self): + self.check_content_type("<doc><element/></doc>", + "text/xml") + + def test_html_default_encoding(self): + pt = self.get_pt( + "<html><head><title>" + # 'Test' in russian (utf-8) + "\xd0\xa2\xd0\xb5\xd1\x81\xd1\x82" + "</title></head></html>") + rendered = pt() + self.failUnless(isinstance(rendered, unicode)) + self.failUnlessEqual(rendered, + u"<html><head><title>" + u"\u0422\u0435\u0441\u0442" + u"</title></head></html>\n") + + def test_html_encoding_by_meta(self): + pt = self.get_pt( + "<html><head><title>" + # 'Test' in russian (windows-1251) + "\xd2\xe5\xf1\xf2" + '</title><meta http-equiv="Content-Type"' + ' content="text/html; charset=windows-1251">' + "</head></html>") + rendered = pt() + self.failUnless(isinstance(rendered, unicode)) + self.failUnlessEqual(rendered, + u"<html><head><title>" + u"\u0422\u0435\u0441\u0442" + u"</title></head></html>\n") + + def test_xhtml(self): + pt = self.get_pt( + "<html><head><title>" + # 'Test' in russian (windows-1251) + "\xd2\xe5\xf1\xf2" + '</title><meta http-equiv="Content-Type"' + ' content="text/html; charset=windows-1251"/>' + "</head></html>") + rendered = pt() + self.failUnless(isinstance(rendered, unicode)) + self.failUnlessEqual(rendered, + u"<html><head><title>" + u"\u0422\u0435\u0441\u0442" + u"</title></head></html>\n") + + + +def test_suite(): + return unittest.makeSuite(TypeSniffingTestCase) + +if __name__ == "__main__": + unittest.main(defaultTest="test_suite") diff --git a/src/zope/pagetemplate/tests/testpackage/__init__.py b/src/zope/pagetemplate/tests/testpackage/__init__.py new file mode 100644 index 0000000..b711d36 --- /dev/null +++ b/src/zope/pagetemplate/tests/testpackage/__init__.py @@ -0,0 +1,2 @@ +# +# This file is necessary to make this directory a package. diff --git a/src/zope/pagetemplate/tests/testpackage/content.py b/src/zope/pagetemplate/tests/testpackage/content.py new file mode 100644 index 0000000..7d51454 --- /dev/null +++ b/src/zope/pagetemplate/tests/testpackage/content.py @@ -0,0 +1,28 @@ +############################################################################## +# +# Copyright (c) 2001, 2002 Zope Corporation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (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. +# +############################################################################## +"""Content + +$Id$ +""" + +class Content(object): + def getSomething(self): + return 42 + + +class PTComponent(object): + def __init__(self, content, request): + self.content = content + + index = PageTemplateFile("view.pt", engine_name="unrestricted") diff --git a/src/zope/pagetemplate/tests/testpackage/view.pt b/src/zope/pagetemplate/tests/testpackage/view.pt new file mode 100644 index 0000000..8ea5029 --- /dev/null +++ b/src/zope/pagetemplate/tests/testpackage/view.pt @@ -0,0 +1 @@ +<span tal:replace="context/getSomething"/> diff --git a/src/zope/pagetemplate/tests/util.py b/src/zope/pagetemplate/tests/util.py new file mode 100644 index 0000000..481b168 --- /dev/null +++ b/src/zope/pagetemplate/tests/util.py @@ -0,0 +1,111 @@ +############################################################################## +# +# Copyright (c) 2001, 2002 Zope Corporation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (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. +# +############################################################################## +"""Utilities + +$Id$ +""" +import os +import re +import sys + + +class Bruce(object): + __allow_access_to_unprotected_subobjects__=1 + def __str__(self): return 'bruce' + def __int__(self): return 42 + def __float__(self): return 42.0 + def keys(self): return ['bruce']*7 + def values(self): return [self]*7 + def items(self): return [('bruce',self)]*7 + def __len__(self): return 7 + def __getitem__(self,index): + if ininstance(index, int) and (index < 0 or index > 6): + raise IndexError(index) + return self + isDocTemp = 0 + def __getattr__(self,name): + if name.startswith('_'): + raise AttributeError(name) + return self + +bruce = Bruce() + +class arg(object): + __allow_access_to_unprotected_subobjects__ = 1 + def __init__(self,nn,aa): self.num, self.arg = nn, aa + def __str__(self): return str(self.arg) + +class argv(object): + __allow_access_to_unprotected_subobjects__ = 1 + + def __init__(self, argv=sys.argv[1:]): + args = self.args = [] + for aa in argv: + args.append(arg(len(args)+1,aa)) + + def items(self): + return map(lambda a: ('spam%d' % a.num, a), self.args) + + def values(self): return self.args + + def getRoot(self): + return self + + context = property(lambda self: self) + +def nicerange(lo, hi): + if hi <= lo+1: + return str(lo+1) + else: + return "%d,%d" % (lo+1, hi) + +def dump(tag, x, lo, hi): + for i in xrange(lo, hi): + print '%s %s' % (tag, x[i]), + +def check_html(s1, s2): + s1 = normalize_html(s1) + s2 = normalize_html(s2) + assert s1==s2, (s1, s2, "HTML Output Changed") + +def check_xml(s1, s2): + s1 = normalize_xml(s1) + s2 = normalize_xml(s2) + assert s1==s2, ("XML Output Changed:\n%r\n\n%r" % (s1, s2)) + +def normalize_html(s): + s = re.sub(r"[ \t]+", " ", s) + s = re.sub(r"/>", ">", s) + return s + +def normalize_xml(s): + s = re.sub(r"\s+", " ", s) + s = re.sub(r"(?s)\s+<", "<", s) + s = re.sub(r"(?s)>\s+", ">", s) + return s + + +import zope.pagetemplate.tests + +dir = os.path.dirname(zope.pagetemplate.tests.__file__) +input_dir = os.path.join(dir, 'input') +output_dir = os.path.join(dir, 'output') + +def read_input(filename): + filename = os.path.join(input_dir, filename) + return open(filename, 'r').read() + +def read_output(filename): + filename = os.path.join(output_dir, filename) + return open(filename, 'r').read() |