SimpleTAL-4.1/ 0000755 0001750 0001750 00000000000 10364737165 011762 5 ustar cms103 cms103 SimpleTAL-4.1/Changes.txt 0000644 0001750 0001750 00000025266 10354332656 014101 0 ustar cms103 cms103 simpleTAL / simpleTALES (Version 4.1)
-------------------------------------
Version 4.1
-----------
New features:
- Processing Instructions are now supported in HTML templates.
Bug fixes:
- The use of "&" in attributes was broken in 4.0 - fixed (thanks to Alain Spineux for the bug report).
Version 4.0
------------
This version of SimpleTAL is not 100% backwards compatible with the 3.x series of releases. Version 4.0 of SimpleTAL requires Python 2.2 or higher.
New features:
- Added support for minimizing boolean attributes in HTML (minimizeBooleanAtts = 1).
- Switched HTML parser library from SGMLParser to HTMLParser. HTMLParser is generally less
strict than the SGMLParser, however it doesn't handle unbalanced quotes around attributes (thanks to Carlos Neves for the initial patch).
- Python 2.2 or higher supported.
- All METAL namespace attributes are automatically omitted, not just those in XML templates.
Version 3.13
------------
New features:
- Added support for compiling a template from a DOM tree (thanks to Benjamin Niemann for the
patch).
- Added support for iterators in the Context (thanks to Kevin Smith for the ideas).
Bug fixes:
- ElementTree paths can now be used from 'python: path ()' expressions (thanks to Jochen
Kupperschmidt for the fix).
Version 3.12
------------
New features:
- Integration with ElementTree.
- Use Python 2.2's unicode function if available (honours the __unicode__ method) when
converting non-unicode variables in the Context.
Bug fixes:
- Allow sub-classes of string and Unicode strings to be placed in the Context.
Version 3.11
------------
This release changes how HTML templates containing entity references and character references are
handled. In previous releases any references contained in the HTML would be passed through to
the output intact. In order to solve the double escaping bug described below all character references
are now expanded in the output with the exception of <, > and &
Bug fixes:
- If multiple variable substitutions are used in a single 'string:' path and one failed
the whole path would evaluate to an empty string.
- When was used was output.
- The global variable 'attrs' should be a dictionary, not a list
(Thanks to Christoph Zwerschke for the bug report).
- Content accessed through attrs would be double escaped.
Version 3.10
------------
New features:
- Included API documentation and TAL reference guide with archive.
Bug fixes:
- Attributes on repeat tags were not correctly kept for nested repeats.
(Thanks to Aadish Shrestha for the bug report)
Version 3.9
-----------
This is release is focused on improving performance. Compared to version 3.8
the performance of expanding templates is ~45-70% faster. The performance of parsing
templates is unchanged.
WARNING: IF you rely on the internal workings of SimpleTALES in your application then
there will be changes that are required to make use of this version of SimpleTAL. The API
for SimpleTAL is however unchanged.
New features:
- Introduced simpleTALUtils.FastStringOutput which can be used to capture the
output of SimpleTAL in a faster manner than StringIO.
- Introduced simpleTALES.CachedFuncResult which can be used to wrap functions in
the Context, and which cache's the result of the function call to ensure that
the function is only called once during template expansion.
- TALES no longer wraps all results in ContextVariable instances when returning
values to TAL.
- Changed copy.copy to {}.copy for performance improvement.
- Removed logging.debug() calls from performance critical paths.
- Replaced DefaultVariable class with simpleTALES.DEFAULTVALUE
- Replaced NothingVariable class with None
- Removed NoCallVariable
- Removed isDefault, isNothing, isSequence, isCallable, and isTrue from ContextVariable.
Version 3.8
-----------
New features:
- Added new method getXMLTemplate to simpleTALUtils.TemplateCache
- Comments in XML templates are now included in the output if pyxml is
installed.
- Lists can now be indexed into.
Bug fixes:
- TAL commands on METAL namespaced elements and vice-versa now work correctly
(thanks to Kevin Smith for the bug report).
Version 3.7
-----------
New features:
- When non-ascii, non-Unicode strings are present in the Context a Unicode
error is thrown. Now an ERROR log message indicates that this is the most
likely cause of the problem.
Bug fixes:
- Correction to cgi-example (thanks to Frank Wierzbicki for the patch).
- Local defines that reference earlier local defines on one tag now work.
- Using default values in a repeat list now work as expected.
- Errors during codec conversions will now use 'replace' rather than 'strict'
Version 3.6
-----------
New features:
- The XML Declaration can now be suppressed by passing
suppressXMLDeclaration=1 to the template "expand" method.
Bug fixes:
- Removed stray 'info' logging call.
Version 3.5
-----------
New features:
- The 'test' function is now available to code used in 'python:' paths.
Usage is the same as zope: test (test1,val1[,test2,val2][,default]).
(Thanks to Mark McEahern for the feature request)
- Uses PyXML (http://pyxml.sourceforge.net/) to determine the DOCTYPE of
XML templates (if installed). (Thanks to Myers Carpenter for the
implementation)
Bug fixes:
- CGI Example fixes.
- XML Templates containing attributes with character entities are now
output correctly.
- HTML Templates with special characters as part of TAL or METAL commands
are now handled correctly.
- Default encoding is now iso-8859-1 rather than iso8859-1
Version 3.4
-----------
New features:
- TemplateCache now uses MTIME rather than CTIME to spot
changes to templates.
- SimpleTAL is now compatible with PyXML 0.8.2 (Thanks to
Myers Carpenter for the testing).
- Added support for passing in an XML Doctype when calling
template.expand
- Added support to maintain XML singleton tags, including use of
METAL and TAL on singleton tags.
- Added support for using variables in paths (e.g. If colour='blue' then
the path 'colourMap/?colour' is equivalent to 'colourMap/blue'). This
is not part of the TALES specification, but is supported by Zope.
(Thanks to Bastian Kleineidam for the initial implementation).
Bug fixes:
- If the logging module was not installed exceptions would be thrown
when SimpleTAL attempted to log errors - fixed.
Version 3.3
-----------
New features:
- TemplateCache now supports inputEncoding, allowing HTML templates using
character sets other than ISO8859-1 to be used.
- Functions path, string, exists, and nocall are available to python: paths.
- Functions can now receive parameters via paths by wrapping them in
simpleTALES.PathFunctionVariable before placing them into the Context.
Bug fixes:
- In tal:attributes and tal:define double escaped semi-colons are now handled.
- Space after a semi-colon in tal:attributes and tal:define is now handled
(thanks to Sean Reifschneider)
- Handling of stray quotes at the start and end of attributes shouldn't interfere
with python: paths anymore.
Version 3.2
-----------
This release incorporates patches from Wichert Akkerman implementing the Python TAL path
and moving to string methods instead of using the string module.
New features:
- The 'python:' path can now be used, pass the parameter 'allowPythonPath=1' to the
constructor of SimpleTALES.Context to enable this to be used.
- simpleTALUtils now contains a template caching class (TemplateCache) that
can be used to cache compiled templates, automatically invalidating the cache if
the template file has changed.
- The string module is no longer used, replaced by string methods
Bug fixes:
- Nested repeat variables with the same name are now scoped correctly.
- If logging is available all error messages are now suppressed during testing.
Version 3.1
-----------
With this release import statements need to be changed. Please now use:
from simpletal import simpleTAL, simpleTALES. The API has not changed.
New features:
- SimpleTAL can now be installed using distutils, thanks to Michael Twomey.
Bug fixes:
- If tal:repeat and tal:content were used on the same element, the last piece of
content would be present twice - fixed.
- If a path element inside a string: path evaluated to something other than a string or
unicode string, it would not be evaluated. Now an attempt to coerce the value to a
string is done using the str function.
Version 3.0
-----------
New features:
- METAL Support added
- The TAL and METAL name-spaces can now be bound to any prefix
- When using XML Templates any elements in the TAL or METAL name-space
have their start and end tags suppressed.
Version 2.3
-----------
Bug fixes:
- Using tal:repeat on empty lists would cause an exception to be thrown.
Now the repeating elements are removed from the output.
Version 2.2
-----------
Bug fixes:
- HTML Document type declarations were not being passed through from the template
- HTML Comments are now passed through to the output
- End tags with no start tag now raise an error rather than failing silently
- The first text element in a template is now combined with other text elements
- XML Processing Instructions are now passed through the template correctly.
Version 2.1
-----------
Bug fixes:
- HTML Templates will now suppress the output of close tags for elements
that are forbidden to have them in HTML 4.01. Additionally tags that
can have no close tag in HTML can still have TAL attributes. This means
that HTML templates can still be valid HTML, and produce valid HTML.
For example:
'' is now valid, and will only
output the
tag.
New features:
- A simplification of how local variables are handled brings a 5-10%
performance gain
Version 2.0
-----------
Complete refactoring of simpleTAL leading to very significant performance
improvements.
Bug fixes:
- Any unknown entity references present in a HTML template were not passed
through to the rendered template, now they are.
- Attributes created using tal:attributes did not have their values escaped
properly
New features:
- Large performance improvements by splitting the process into two
- Templates once compiled can now be re-used, leading to large performance
gains
Version 1.1
-----------
Bug fixes:
- The "structure" keyword when used in XML templates would fail with an exception.
New features:
- Added test cases for TALES and TAL (both HTML and XML)
- Added allowTALInStructure flag to control expansion of TAL attributes
Version 1.0
-----------
Initial release.
SimpleTAL-4.1/PKG-INFO 0000644 0001750 0001750 00000000566 10364737165 013066 0 ustar cms103 cms103 Metadata-Version: 1.0
Name: SimpleTAL
Version: 4.1
Summary: SimpleTAL is a stand alone Python implementation of the TAL, TALES and METAL specifications used in Zope to power HTML and XML templates.
Home-page: http://www.owlfish.com/software/simpleTAL/index.html
Author: Colin Stewart
Author-email: colin@owlfish.com
License: UNKNOWN
Description: UNKNOWN
Platform: UNKNOWN
SimpleTAL-4.1/tests/ 0000755 0001750 0001750 00000000000 10364737163 013122 5 ustar cms103 cms103 SimpleTAL-4.1/tests/METALTests/ 0000755 0001750 0001750 00000000000 10364737163 015007 5 ustar cms103 cms103 SimpleTAL-4.1/tests/METALTests/XMLTests/ 0000755 0001750 0001750 00000000000 10364737164 016473 5 ustar cms103 cms103 SimpleTAL-4.1/tests/METALTests/XMLTests/METALNameSpaceTests.py 0000644 0001750 0001750 00000011055 10347331422 022475 0 ustar cms103 cms103 #!/usr/bin/python
""" Copyright (c) 2004 Colin Stewart (http://www.owlfish.com/)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
If you make any bug fixes or feature enhancements please let me know!
Unit test cases.
"""
import unittest, os
import StringIO
import logging, logging.config
from simpletal import simpleTAL, simpleTALES
if (os.path.exists ("logging.ini")):
logging.config.fileConfig ("logging.ini")
else:
logging.basicConfig()
class METALNameSpaceTests (unittest.TestCase):
def setUp (self):
self.context = simpleTALES.Context()
self.context.addGlobal ('test', 'testing')
self.context.addGlobal ('one', [1])
self.context.addGlobal ('two', ["one", "two"])
self.context.addGlobal ('three', [1,"Two",3])
def _runTest_ (self, macros, page, result, errMsg="Error"):
macroTemplate = simpleTAL.compileXMLTemplate (macros)
#print "Macro template: " + str (macroTemplate)
pageTemplate = simpleTAL.compileXMLTemplate (page)
self.context.addGlobal ("site", macroTemplate)
self.context.addGlobal ("here", pageTemplate)
file = StringIO.StringIO ()
pageTemplate.expand (self.context, file)
realResult = file.getvalue()
self.failUnless (realResult == result, "%s - \npassed in macro: %s \npage: %s\ngot back %s \nexpected %s\n" % (errMsg, macros, page, realResult, result))
# Test that rebinding the namespaces works
def testSingleBindNoCommands (self):
self._runTest_ ('
testing
\ntesting
\nWibble
' , result ,"TAL Command on a macro failed.") def testSingletonMacros (self): if (use_lexical_handler): result = '\n\nWibble
Wibble
Wibble
Internal macro, colour blue: blue
Internal macro, colour blue: blue
Internal macro, colour blue: blue
pink!
finally outer blue again: blue goes hereInternal macro, colour blue:
pink!
finally outer blue again: whiteWibble
' ,'\ntesting
\n' ,"TAL Command on a macro failed.") if __name__ == '__main__': unittest.main() SimpleTAL-4.1/tests/METALTests/HTMLTests/DefineSlotsTests.py 0000644 0001750 0001750 00000015357 10007245640 022411 0 ustar cms103 cms103 #!/usr/bin/python """ Copyright (c) 2004 Colin Stewart (http://www.owlfish.com/) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. If you make any bug fixes or feature enhancements please let me know! Unit test cases. """ import unittest, os import StringIO import logging, logging.config from simpletal import simpleTAL, simpleTALES if (os.path.exists ("logging.ini")): logging.config.fileConfig ("logging.ini") else: logging.basicConfig() class DefineSlotsTests (unittest.TestCase): def setUp (self): self.context = simpleTALES.Context() self.context.addGlobal ('test', 'testing') self.context.addGlobal ('link', 'www.owlfish.com') self.context.addGlobal ('needsQuoting', """Does "this" & work?""") def _runTest_ (self, macros, page, result, errMsg="Error"): macroTemplate = simpleTAL.compileHTMLTemplate (macros) #print "Macro template: " + str (macroTemplate) pageTemplate = simpleTAL.compileHTMLTemplate (page) self.context.addGlobal ("site", macroTemplate) self.context.addGlobal ("here", pageTemplate) file = StringIO.StringIO () pageTemplate.expand (self.context, file) realResult = file.getvalue() self.failUnless (realResult == result, "%s - \npassed in macro: %s \npage: %s\ngot back %s \nexpected %s\n" % (errMsg, macros, page, realResult, result)) def _runCompileTest_ (self, txt, result, errMsg="Error"): try: macroTemplate = simpleTAL.compileHTMLTemplate (txt) except simpleTAL.TemplateParseException, e: self.failUnless (str (e) == result, "%s - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (errMsg, txt, str(e), result, pageTemplate)) return self.fail ("Expected exception '%s' during compile - but got no exception" % result) def testSingleSlot (self): self._runTest_ ('Internal macro, colour blue: blue
Internal macro, colour blue: blue
Internal macro, colour blue: blue
pink!
finally outer blue again: blue goes hereInternal macro, colour blue:
pink!
finally outer blue again: whiteHello
default contentdefault content' ,'\nHello
default contenttesting' ,'Binding of namespace failed to nest correctly') def testDoubleNestedBind (self): self._runTest_ ('Hello
Hello
Hello
Hello
""" ,"""METAL with define-slot on singleton failed.""") def testDefineMacro (self): self._runMacroTest_ ("""Hello
testing
', "Simple string define failed.") def testDefineList (self): self._runTest_ ('Hello
' , '\nHello one
Hello two
', 'List define failed.') def testDefineGlobal (self): self._runTest_ ('' , '\ntesting
', 'Global did not set globally') def testDefineLocal (self): self._runTest_ ('' , '\n', 'Explicit local available globaly') def testDefineImplicitLocal (self): self._runTest_ ('' , '\n', 'Implicit local available globaly') def testDefineMultipleLocal (self): self._runTest_ ('Testing
testing
This is a semi;colon
Test
Testing
testing
This is a semi;colon
Test
Original
' ,'\nOriginal
' ,'Content of default did not evaluate to existing content without tags') def testContentString (self): self._runTest_ ('Original
' ,'\ntesting' ,'Content of string did not evaluate to contain string') def testContentStructure (self): # This test has specific needs - i.e. wrap the weblog/entry in a template... entry = """Original
' ,'\nHello
' ,'\n' , "Repeat of non-existant element failed") def testDefaultValue (self): self._runTest_ ('Default Only
' ,'\nDefault Only
' , 'Default did not keep existing structure intact') def testEmptyList (self): self._runTest_ ('Empty
' ,'\n' ,'Empty list repeat failed.' ) def testStringRepeat (self): self._runTest_ ('' ,'\ntesting' ,'Itteration over string failed.') def testListRepeat (self): self._runTest_ ('
' ,'\n
one
two
' ,'Itteration over list failed.') def testTwoCmndsOneTagListRepeat (self): self._runTest_ ('' ,'\none
two
' ,'Itteration over list with both content and repeat on same element failed.') def testNestedRepeat (self): self._runTest_ ('' ,'\nIndex
' ,'\n' + expectedResult ,"Repeat variable index failed." ) def testRepeatVarNumber (self): self._runTest_ ('Index
' ,'\n123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899' ,'Repeat variable number failed.' ) def testRepeatVarEvenOdd (self): self._runTest_ ('- OddEven
' ,'\nzero - Even
one - Odd
two - Even
three - Odd
' ,'Repeat variables odd and even failed.' ) def testRepeatVarStartEnd (self): self._runTest_ ('StartEnd
' ,'\nStartzero
one
two
threeEnd
' ,'Repeat variables start and end failed.' ) def testRepeatVarLength (self): self._runTest_ ('Len: lengthEntry:
' ,'\nLen: 4Entry: zero
Entry: one
Entry: two
Entry: three
' ,'Repeat variable length failed.' ) def testRepeatVarLowerLetter (self): self._runTest_ ('a,b,c,etc:
' ,'\na: zero
b: one
c: two
d: three
' ,'Repeat variable letter failed.' ) def testRepeatVarLowerLetterLarge (self): self._runTest_ ('a,b,c,etc:
' ,'\na: 1
b: 2
c: 3
d: 4
e: 5
f: 6
g: 7
h: 8
i: 9
j: 10
k: 11
l: 12
m: 13
n: 14
o: 15
p: 16
q: 17
r: 18
s: 19
t: 20
u: 21
v: 22
w: 23
x: 24
y: 25
z: 26
ba: 27
bb: 28
bc: 29
bd: 30
be: 31
bf: 32
bg: 33
bh: 34
bi: 35
bj: 36
bk: 37
bl: 38
bm: 39
bn: 40
bo: 41
bp: 42
bq: 43
br: 44
bs: 45
bt: 46
bu: 47
bv: 48
bw: 49
bx: 50
by: 51
bz: 52
ca: 53
cb: 54
cc: 55
cd: 56
ce: 57
cf: 58
cg: 59
ch: 60
ci: 61
cj: 62
ck: 63
cl: 64
cm: 65
cn: 66
co: 67
cp: 68
cq: 69
cr: 70
cs: 71
ct: 72
cu: 73
cv: 74
cw: 75
cx: 76
cy: 77
cz: 78
da: 79
db: 80
dc: 81
dd: 82
de: 83
df: 84
dg: 85
dh: 86
di: 87
dj: 88
dk: 89
dl: 90
dm: 91
dn: 92
do: 93
dp: 94
dq: 95
dr: 96
ds: 97
dt: 98
du: 99
' ,'Repeat variable letter failed on a large list.' ) def testRepeatVarUpperLetter (self): self._runTest_ ('A,B,C,etc:
' ,'\nA: zero
B: one
C: two
D: three
' ,'Repeat variable Letter failed.' ) def testRepeatVarLowerRoman (self): self._runTest_ ('i,ii,iii,etc:
' ,'\ni: 1
ii: 2
iii: 3
iv: 4
v: 5
vi: 6
vii: 7
viii: 8
ix: 9
x: 10
xi: 11
xii: 12
xiii: 13
xiv: 14
xv: 15
xvi: 16
xvii: 17
xviii: 18
xix: 19
xx: 20
xxi: 21
xxii: 22
xxiii: 23
xxiv: 24
xxv: 25
xxvi: 26
xxvii: 27
xxviii: 28
xxix: 29
xxx: 30
xxxi: 31
xxxii: 32
xxxiii: 33
xxxiv: 34
xxxv: 35
xxxvi: 36
xxxvii: 37
xxxviii: 38
xxxix: 39
xl: 40
xli: 41
xlii: 42
xliii: 43
xliv: 44
xlv: 45
xlvi: 46
xlvii: 47
xlviii: 48
xlix: 49
l: 50
li: 51
lii: 52
liii: 53
liv: 54
lv: 55
lvi: 56
lvii: 57
lviii: 58
lix: 59
lx: 60
lxi: 61
lxii: 62
lxiii: 63
lxiv: 64
lxv: 65
lxvi: 66
lxvii: 67
lxviii: 68
lxix: 69
lxx: 70
lxxi: 71
lxxii: 72
lxxiii: 73
lxxiv: 74
lxxv: 75
lxxvi: 76
lxxvii: 77
lxxviii: 78
lxxix: 79
lxxx: 80
lxxxi: 81
lxxxii: 82
lxxxiii: 83
lxxxiv: 84
lxxxv: 85
lxxxvi: 86
lxxxvii: 87
lxxxviii: 88
lxxxix: 89
xc: 90
xci: 91
xcii: 92
xciii: 93
xciv: 94
xcv: 95
xcvi: 96
xcvii: 97
xcviii: 98
xcix: 99
' ,'Repeat variable roman failed.' ) def testRepeatVarUpperRoman (self): self._runTest_ ('I,II,III,etc:
' ,'\nI: 1
II: 2
III: 3
IV: 4
V: 5
VI: 6
VII: 7
VIII: 8
IX: 9
X: 10
XI: 11
XII: 12
XIII: 13
XIV: 14
XV: 15
XVI: 16
XVII: 17
XVIII: 18
XIX: 19
XX: 20
XXI: 21
XXII: 22
XXIII: 23
XXIV: 24
XXV: 25
XXVI: 26
XXVII: 27
XXVIII: 28
XXIX: 29
XXX: 30
XXXI: 31
XXXII: 32
XXXIII: 33
XXXIV: 34
XXXV: 35
XXXVI: 36
XXXVII: 37
XXXVIII: 38
XXXIX: 39
XL: 40
XLI: 41
XLII: 42
XLIII: 43
XLIV: 44
XLV: 45
XLVI: 46
XLVII: 47
XLVIII: 48
XLIX: 49
L: 50
LI: 51
LII: 52
LIII: 53
LIV: 54
LV: 55
LVI: 56
LVII: 57
LVIII: 58
LIX: 59
LX: 60
LXI: 61
LXII: 62
LXIII: 63
LXIV: 64
LXV: 65
LXVI: 66
LXVII: 67
LXVIII: 68
LXIX: 69
LXX: 70
LXXI: 71
LXXII: 72
LXXIII: 73
LXXIV: 74
LXXV: 75
LXXVI: 76
LXXVII: 77
LXXVIII: 78
LXXIX: 79
LXXX: 80
LXXXI: 81
LXXXII: 82
LXXXIII: 83
LXXXIV: 84
LXXXV: 85
LXXXVI: 86
LXXXVII: 87
LXXXVIII: 88
LXXXIX: 89
XC: 90
XCI: 91
XCII: 92
XCIII: 93
XCIV: 94
XCV: 95
XCVI: 96
XCVII: 97
XCVIII: 98
XCIX: 99
' ,'Repeat variable Roman failed.' ) def testLocalVarScope (self): self._runTest_ ('bold
VAR EXISTS' ,'\nzero
one
two
three
' ,'Local repeat variable remained accessible out of scope!' ) if __name__ == '__main__': unittest.main() SimpleTAL-4.1/tests/TALTests/XMLTests/TALHandlerTestCases.py 0000755 0001750 0001750 00000027152 10142751013 022351 0 ustar cms103 cms103 #!/usr/bin/python """ Copyright (c) 2004 Colin Stewart (http://www.owlfish.com/) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. If you make any bug fixes or feature enhancements please let me know! Unit test cases. """ import unittest, os import StringIO import logging, logging.config import xml.sax, xml.sax.handler, md5 try: # check to see if pyxml is installed from xml.sax.saxlib import LexicalHandler use_lexical_handler = 1 except ImportError: use_lexical_handler = 0 class LexicalHandler: pass from simpletal import simpleTAL, simpleTALES if (os.path.exists ("logging.ini")): logging.config.fileConfig ("logging.ini") else: logging.basicConfig() class XMLChecksumHandler (xml.sax.handler.ContentHandler, xml.sax.handler.DTDHandler, xml.sax.handler.ErrorHandler, LexicalHandler): def __init__ (self, parser): xml.sax.handler.ContentHandler.__init__ (self) self.ourParser = parser def getDigest (self): return self.digest.hexdigest() def startDocument (self): self.digest = md5.new() def startPrefixMapping (self, prefix, uri): self.digest.update (prefix) self.digest.update (uri) def endPrefixMapping (self, prefix): self.digest.update (prefix) def startElement (self, name, atts): self.digest.update (name) allAtts = atts.getNames() allAtts.sort() for att in allAtts: self.digest.update (att) self.digest.update (atts [att]) def endElement (self, name): self.digest.update (name) def characters (self, data): self.digest.update (data) def processingInstruction (self, target, data): self.digest.update (target) self.digest.update (data) def comment (self, data): self.digest.update (data) def skippedEntity (self, name): self.digest.update (name) # DTD Handler def notationDecl(self, name, publicId, systemId): self.digest.update (name) self.digest.update (publicId) self.digest.update (systemId) def unparsedEntityDecl(name, publicId, systemId, ndata): self.digest.update (name) self.digest.update (publicId) self.digest.update (systemId) self.digest.update (ndata) def error (self, excpt): print "Error: %s" % str (excpt) def warning (self, excpt): print "Warning: %s" % str (excpt) def startDTD(self, name, publicId, systemId): self.digest.update (name) self.digest.update (publicId) self.digest.update (systemId) CHECKSUMPARSER = xml.sax.make_parser() CHECKSUMHANDLER = XMLChecksumHandler(CHECKSUMPARSER) CHECKSUMPARSER.setContentHandler (CHECKSUMHANDLER) CHECKSUMPARSER.setDTDHandler (CHECKSUMHANDLER) CHECKSUMPARSER.setErrorHandler (CHECKSUMHANDLER) try: CHECKSUMPARSER.setFeature (xml.sax.handler.feature_external_ges, 0) except: pass if use_lexical_handler: CHECKSUMPARSER.setProperty(xml.sax.handler.property_lexical_handler, CHECKSUMHANDLER) def getXMLChecksum (doc): CHECKSUMPARSER.parse (StringIO.StringIO (doc)) return CHECKSUMHANDLER.getDigest() class TALHandlerTestCases (unittest.TestCase): def setUp (self): self.context = simpleTALES.Context() self.context.addGlobal ('test', 'testing') self.context.addGlobal ('one', [1]) self.context.addGlobal ('two', ["one", "two"]) self.context.addGlobal ('three', [1,"Two",3]) def _runTest_ (self, txt, result, errMsg="Error"): template = simpleTAL.compileXMLTemplate (txt) fh = StringIO.StringIO () template.expand (self.context, fh) realResult = fh.getvalue() expectedChecksum = getXMLChecksum (result) try: realChecksum = getXMLChecksum (realResult) except Exception, e: self.fail ("Exception (%s) thrown parsing XML actual result: %s\nPage Template: %s" % (str (e), realResult, str (template))) self.failUnless (expectedChecksum == realChecksum, "%s - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (errMsg, txt, realResult, result, template)) def testSingleEmptyElement (self): self._runTest_ ("Somemarkup
""" ,"""\nSomemarkup
""" ,"""Processing instructions not preserved.""") def testCommentHandling (self): if (not use_lexical_handler): return self._runTest_ ("""\nHere
""" ,"""\nHere
""" ,"Comments not preserved.") def testDocumentTypeDeclaration (self): txt = """\n\nTest
""" template = simpleTAL.compileXMLTemplate (txt) fh = StringIO.StringIO () template.expand (self.context, fh, docType="""""") realResult = fh.getvalue() expectedResult = """\n\nTest
""" self.failUnless (realResult == expectedResult, "Doctype failed - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (txt, realResult, expectedResult, str(template))) def testXMLDeclarationSuppressionWithDocType (self): txt = """\n\nTest
""" template = simpleTAL.compileXMLTemplate (txt) fh = StringIO.StringIO () template.expand (self.context, fh, docType="""""", suppressXMLDeclaration=1) realResult = fh.getvalue() expectedResult = """\nTest
""" self.failUnless (realResult == expectedResult, "Doctype failed - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (txt, realResult, expectedResult, str(template))) def testXMLDeclarationSuppressionWithNoDocType (self): txt = """\nTest
""" template = simpleTAL.compileXMLTemplate (txt) fh = StringIO.StringIO () template.expand (self.context, fh, suppressXMLDeclaration=1) realResult = fh.getvalue() expectedResult = """Test
""" self.failUnless (realResult == expectedResult, "Doctype failed - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (txt, realResult, expectedResult, str(template))) def testDTDPassthru (self): if not use_lexical_handler: return self._runTest_ ("""Moved to vlib.org.
""","""\Moved to vlib.org.
""") if __name__ == '__main__': unittest.main() SimpleTAL-4.1/tests/TALTests/XMLTests/TALContentTestCases.py 0000644 0001750 0001750 00000010642 10007245640 022403 0 ustar cms103 cms103 #!/usr/bin/python """ Copyright (c) 2004 Colin Stewart (http://www.owlfish.com/) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. If you make any bug fixes or feature enhancements please let me know! Unit test cases. """ import unittest, os import StringIO import logging, logging.config from simpletal import simpleTAL, simpleTALES if (os.path.exists ("logging.ini")): logging.config.fileConfig ("logging.ini") else: logging.basicConfig() class TALContentTestCases (unittest.TestCase): def setUp (self): self.context = simpleTALES.Context() entry = """Original
' ,'\nOriginal
' ,'Content of default did not evaluate to existing content') def testContentString (self): self._runTest_ ('Original
' ,'\ntesting
' ,'Content of string did not evaluate to contain string') def testContentStructure (self): # This test has specific needs - i.e. wrap the weblog/entry in a template... entry = """Original
' ,'\nOriginal
' ,'\nHello
default contentdefault content' ,'Hello
default contenttesting' ,'Binding of namespace failed to nest correctly') def testDoubleNestedBind (self): self._runTest_ ('Hello
Hello
testing
", "Simple string define failed.") def testDefineList (self): self._runTest_ ('Hello
' , 'Hello one
Hello two
', 'List define failed.') def testDefineGlobal (self): self._runTest_ ('' , 'testing
', 'Global did not set globally') def testDefineLocal (self): self._runTest_ ('' , '', 'Explicit local available globaly') def testDefineImplicitLocal (self): self._runTest_ ('' , '', 'Implicit local available globaly') def testDefineDefault (self): self._runTest_ ('Can you see me?
' , 'Can you see me?
', 'Default variable did not define proplerly.') def testDefineNothing (self): self._runTest_ ('Can you see me?
' , '', 'Nothing variable did not define proplerly.') def testDefineMultipleLocal (self): self._runTest_ ('Testing
testing
This is a semi;colon
Test
Testing
testing
This is a semi;colon
Test
Testing
testing
testing
Original
' ,'Original
' ,'Content of default did not evaluate to existing content without tags') def testContentString (self): self._runTest_ ('Original
' ,'testing' ,'Content of string did not evaluate to contain string') def testContentStructure (self): # This test uses a specific context entry = """Some structure: """ weblog = {'subject': 'Test subject', 'entry': simpleTAL.compileHTMLTemplate(entry)} self.context.addGlobal ('weblog', weblog) self._runTest_ ('Original
' ,'Some structure: Test subject' ,'Content of Structure did not evaluate to expected result') if __name__ == '__main__': unittest.main() SimpleTAL-4.1/tests/TALTests/HTMLTests/TALForbiddenEndTagTestCases.py 0000644 0001750 0001750 00000017546 10007245640 024066 0 ustar cms103 cms103 #!/usr/bin/python """ Copyright (c) 2004 Colin Stewart (http://www.owlfish.com/) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. If you make any bug fixes or feature enhancements please let me know! Unit test cases. """ import unittest, os import StringIO import logging, logging.config from simpletal import simpleTAL, simpleTALES if (os.path.exists ("logging.ini")): logging.config.fileConfig ("logging.ini") else: logging.basicConfig() class TALForbiddenEndTagTestCases (unittest.TestCase): def setUp (self): self.context = simpleTALES.Context() self.context.addGlobal ('test', 'testing') self.context.addGlobal ('link', 'www.owlfish.com') self.context.addGlobal ('scrWidth', '640') def _runTest_ (self, txt, result, errMsg="Error"): template = simpleTAL.compileHTMLTemplate (txt) file = StringIO.StringIO () template.expand (self.context, file) realResult = file.getvalue() self.failUnless (realResult == result, "%s - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (errMsg, txt, realResult, result, template)) def testAreaElement (self): self._runTest_ ('' ,'' ,"HTML Element AREA produced end tag.") def testBaseElement (self): self._runTest_ ('Hello
', "", "Repeat of non-existant element failed") def testDefaultValue (self): self._runTest_ ('Default Only
', 'Default Only
', 'Default did not keep existing structure intact') def testStringRepeat (self): self._runTest_ ('', 'testing', 'Itteration over string failed.') def testEmptyList (self): self._runTest_ ('
Empty
' ,'' ,'Empty list repeat failed.' ) def testListRepeat (self): self._runTest_ ('', '
one
two
', 'Itteration over list failed.') def testTwoCmndsOneTagListRepeat (self): self._runTest_ ('' ,'one
two
' ,'Itteration over list with both content and repeat on same element failed.') def testAttributesInRepeat (self): self._runTest_ ('' ,'Image 1
Image 2
Image 3
' ,'Accessing attributes in repeat loop failed.') def testDefaultInContentInRepeat (self): self._runTest_ ('Default Word
' ,'Hello
Default Word
World
' ,'Using default content in repeat loop failed.') def testDefaultInReplaceInRepeat (self): self._runTest_ ('Default Word
' ,'HelloDefault Word
World' ,'Using default content in repeat loop failed.') def testNestedRepeat (self): self._runTest_ ('' ,'Index
' ,expectedResult ,"Repeat variable index failed." ) def testRepeatVarNumber (self): self._runTest_ ('Index
' ,'123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899' ,'Repeat variable number failed.' ) def testRepeatVarEvenOdd (self): self._runTest_ ('- OddEven
' ,'zero - Even
one - Odd
two - Even
three - Odd
' ,'Repeat variables odd and even failed.' ) def testRepeatVarStartEnd (self): self._runTest_ ('StartEnd
' ,'Startzero
one
two
threeEnd
' ,'Repeat variables start and end failed.' ) def testRepeatVarLength (self): self._runTest_ ('Len: lengthEntry:
' ,'Len: 4Entry: zero
Entry: one
Entry: two
Entry: three
' ,'Repeat variable length failed.' ) def testRepeatVarLowerLetter (self): self._runTest_ ('a,b,c,etc:
' ,'a: zero
b: one
c: two
d: three
' ,'Repeat variable letter failed.' ) def testRepeatVarLowerLetterLarge (self): self._runTest_ ('a,b,c,etc:
' ,'a: 1
b: 2
c: 3
d: 4
e: 5
f: 6
g: 7
h: 8
i: 9
j: 10
k: 11
l: 12
m: 13
n: 14
o: 15
p: 16
q: 17
r: 18
s: 19
t: 20
u: 21
v: 22
w: 23
x: 24
y: 25
z: 26
ba: 27
bb: 28
bc: 29
bd: 30
be: 31
bf: 32
bg: 33
bh: 34
bi: 35
bj: 36
bk: 37
bl: 38
bm: 39
bn: 40
bo: 41
bp: 42
bq: 43
br: 44
bs: 45
bt: 46
bu: 47
bv: 48
bw: 49
bx: 50
by: 51
bz: 52
ca: 53
cb: 54
cc: 55
cd: 56
ce: 57
cf: 58
cg: 59
ch: 60
ci: 61
cj: 62
ck: 63
cl: 64
cm: 65
cn: 66
co: 67
cp: 68
cq: 69
cr: 70
cs: 71
ct: 72
cu: 73
cv: 74
cw: 75
cx: 76
cy: 77
cz: 78
da: 79
db: 80
dc: 81
dd: 82
de: 83
df: 84
dg: 85
dh: 86
di: 87
dj: 88
dk: 89
dl: 90
dm: 91
dn: 92
do: 93
dp: 94
dq: 95
dr: 96
ds: 97
dt: 98
du: 99
' ,'Repeat variable letter failed on a large list.' ) def testRepeatVarUpperLetter (self): self._runTest_ ('A,B,C,etc:
' ,'A: zero
B: one
C: two
D: three
' ,'Repeat variable Letter failed.' ) def testRepeatVarLowerRoman (self): self._runTest_ ('i,ii,iii,etc:
' ,'i: 1
ii: 2
iii: 3
iv: 4
v: 5
vi: 6
vii: 7
viii: 8
ix: 9
x: 10
xi: 11
xii: 12
xiii: 13
xiv: 14
xv: 15
xvi: 16
xvii: 17
xviii: 18
xix: 19
xx: 20
xxi: 21
xxii: 22
xxiii: 23
xxiv: 24
xxv: 25
xxvi: 26
xxvii: 27
xxviii: 28
xxix: 29
xxx: 30
xxxi: 31
xxxii: 32
xxxiii: 33
xxxiv: 34
xxxv: 35
xxxvi: 36
xxxvii: 37
xxxviii: 38
xxxix: 39
xl: 40
xli: 41
xlii: 42
xliii: 43
xliv: 44
xlv: 45
xlvi: 46
xlvii: 47
xlviii: 48
xlix: 49
l: 50
li: 51
lii: 52
liii: 53
liv: 54
lv: 55
lvi: 56
lvii: 57
lviii: 58
lix: 59
lx: 60
lxi: 61
lxii: 62
lxiii: 63
lxiv: 64
lxv: 65
lxvi: 66
lxvii: 67
lxviii: 68
lxix: 69
lxx: 70
lxxi: 71
lxxii: 72
lxxiii: 73
lxxiv: 74
lxxv: 75
lxxvi: 76
lxxvii: 77
lxxviii: 78
lxxix: 79
lxxx: 80
lxxxi: 81
lxxxii: 82
lxxxiii: 83
lxxxiv: 84
lxxxv: 85
lxxxvi: 86
lxxxvii: 87
lxxxviii: 88
lxxxix: 89
xc: 90
xci: 91
xcii: 92
xciii: 93
xciv: 94
xcv: 95
xcvi: 96
xcvii: 97
xcviii: 98
xcix: 99
' ,'Repeat variable roman failed.' ) def testRepeatVarUpperRoman (self): self._runTest_ ('I,II,III,etc:
' ,'I: 1
II: 2
III: 3
IV: 4
V: 5
VI: 6
VII: 7
VIII: 8
IX: 9
X: 10
XI: 11
XII: 12
XIII: 13
XIV: 14
XV: 15
XVI: 16
XVII: 17
XVIII: 18
XIX: 19
XX: 20
XXI: 21
XXII: 22
XXIII: 23
XXIV: 24
XXV: 25
XXVI: 26
XXVII: 27
XXVIII: 28
XXIX: 29
XXX: 30
XXXI: 31
XXXII: 32
XXXIII: 33
XXXIV: 34
XXXV: 35
XXXVI: 36
XXXVII: 37
XXXVIII: 38
XXXIX: 39
XL: 40
XLI: 41
XLII: 42
XLIII: 43
XLIV: 44
XLV: 45
XLVI: 46
XLVII: 47
XLVIII: 48
XLIX: 49
L: 50
LI: 51
LII: 52
LIII: 53
LIV: 54
LV: 55
LVI: 56
LVII: 57
LVIII: 58
LIX: 59
LX: 60
LXI: 61
LXII: 62
LXIII: 63
LXIV: 64
LXV: 65
LXVI: 66
LXVII: 67
LXVIII: 68
LXIX: 69
LXX: 70
LXXI: 71
LXXII: 72
LXXIII: 73
LXXIV: 74
LXXV: 75
LXXVI: 76
LXXVII: 77
LXXVIII: 78
LXXIX: 79
LXXX: 80
LXXXI: 81
LXXXII: 82
LXXXIII: 83
LXXXIV: 84
LXXXV: 85
LXXXVI: 86
LXXXVII: 87
LXXXVIII: 88
LXXXIX: 89
XC: 90
XCI: 91
XCII: 92
XCIII: 93
XCIV: 94
XCV: 95
XCVI: 96
XCVII: 97
XCVIII: 98
XCIX: 99
' ,'Repeat variable Roman failed.' ) def testLocalVarScope (self): self._runTest_ ('bold
VAR EXISTS' ,'zero
one
two
three
' ,'Local repeat variable remained accessible out of scope!' ) if __name__ == '__main__': unittest.main() SimpleTAL-4.1/tests/TALTests/HTMLTests/TALIteratorRepeatTestCases.py 0000644 0001750 0001750 00000015544 10347326342 024043 0 ustar cms103 cms103 #!/usr/bin/python """ Copyright (c) 2005 Colin Stewart (http://www.owlfish.com/) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. If you make any bug fixes or feature enhancements please let me know! Unit test cases. """ import unittest, os, sys import StringIO import logging, logging.config from simpletal import simpleTAL, simpleTALES if (os.path.exists ("logging.ini")): logging.config.fileConfig ("logging.ini") else: logging.basicConfig() try: b = StopIteration() ITERATOR_SUPPORT = 1 except: ITERATOR_SUPPORT = 0 class ActualIter: def __init__ (self, size): self.size = size self.cur = 0 def next (self): if (self.cur == self.size): raise StopIteration () self.cur += 1 return self.cur class IterContainer: def __init__ (self, size): self.size = size def __iter__ (self): return ActualIter (self.size) class TALIteratorRepeatTestCases (unittest.TestCase): def setUp (self): self.context = simpleTALES.Context() self.context.addGlobal ('test', 'testing') self.context.addGlobal ('zeroCont', IterContainer (0)) self.context.addGlobal ('oneCont', IterContainer (1)) self.context.addGlobal ('twoCont', IterContainer (2)) self.context.addGlobal ('zeroAct', ActualIter (0)) self.context.addGlobal ('oneAct', ActualIter (1)) self.context.addGlobal ('twoAct', ActualIter (2)) def _runTest_ (self, txt, result, errMsg="Error"): if (not ITERATOR_SUPPORT): return template = simpleTAL.compileHTMLTemplate (txt) file = StringIO.StringIO () try: template.expand (self.context, file) except Exception, e: print "Error, template compiled to: " + str (template) raise e realResult = file.getvalue() self.failUnless (realResult == result, "%s - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (errMsg, txt, realResult, result, template)) def testZeroCont (self): self._runTest_ ('Hello
', "", "Repeat of zero length container failed.") def testOneCont (self): self._runTest_ ('Hello
', "Hello
", "Repeat of single length container failed.") def testTwoCont (self): self._runTest_ ('Hello
', "Hello
Hello
", "Repeat of two length container failed.") def testZeroAct (self): self._runTest_ ('Hello
', "", "Repeat of zero length actual failed.") def testOneAct (self): self._runTest_ ('Hello
', "Hello
", "Repeat of single length actual failed.") def testTwoAct (self): self._runTest_ ('Hello
', "Hello
Hello
", "Repeat of two length actual failed.") def testIndexAct (self): self._runTest_ ('Hello
', "0
1
", "Repeat of two length actual iterator failed to generate index.") def testNumberAct (self): self._runTest_ ('Hello
', "1
2
", "Repeat of two length actual iterator failed to generate numbers.") def testEvenAct (self): self._runTest_ ('Hello
', "1
0
", "Repeat of two length actual iterator failed to even.") def testOddAct (self): self._runTest_ ('Hello
', "0
1
", "Repeat of two length actual iterator failed to odd.") def testStartAct (self): self._runTest_ ('Hello
', "1
0
", "Repeat of two length actual iterator failed to start.") # The only way to see inside an iterator is to cheat, and call it early. Doing this might be unexpected, so iterators don't support end. # def testEndAct (self): # self._runTest_ ('Hello
', "0
1
", "Repeat of two length actual iterator failed to end.") def testLengthAct (self): self._runTest_ ('Hello
', "%s
%s
" % (str (sys.maxint), str (sys.maxint)), "Repeat of two length actual iterator failed to generate length.") def testLetterSmallAct (self): self._runTest_ ('Hello
', "a
b
", "Repeat of two length actual iterator failed to letter.") def testLetterAct (self): self._runTest_ ('Hello
', "A
B
", "Repeat of two length actual iterator failed to Letter.") def testSmallRomanNumAct (self): self._runTest_ ('Hello
', "i
ii
", "Repeat of two length actual iterator failed to generate roman numerals.") def testRomanNumAct (self): self._runTest_ ('Hello
', "I
II
", "Repeat of two length actual iterator failed to generate roman numerals.") if __name__ == '__main__': unittest.main() SimpleTAL-4.1/tests/TALTests/HTMLTests/TALHandlerTestCases.py 0000755 0001750 0001750 00000011362 10354332656 022466 0 ustar cms103 cms103 #!/usr/bin/python """ Copyright (c) 2004 Colin Stewart (http://www.owlfish.com/) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. If you make any bug fixes or feature enhancements please let me know! Unit test cases. """ import unittest, os import StringIO import logging, logging.config from simpletal import simpleTAL, simpleTALES if (os.path.exists ("logging.ini")): logging.config.fileConfig ("logging.ini") else: logging.basicConfig() class TALHandlerTestCases (unittest.TestCase): def setUp (self): self.context = simpleTALES.Context() self.context.addGlobal ('test', 'testing') self.context.addGlobal ('one', [1]) self.context.addGlobal ('two', ["one", "two"]) self.context.addGlobal ('three', [1,"Two",3]) def _runTest_ (self, txt, result, errMsg="Error"): template = simpleTAL.compileHTMLTemplate (txt) file = StringIO.StringIO () template.expand (self.context, file) realResult = file.getvalue() self.failUnless (realResult == result, "%s - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (errMsg, txt, realResult, result, template)) def testEmptyFile (self): self._runTest_ ("", "", "Empty template contains more text than given.") def testSingleEmptyElement (self): self._runTest_ ("Hello.
World
Hello.
World
Hello.
World
Hello.
World
Boo
", "Boo
") def testUnbalancedCloseTag (self): try: template = simpleTAL.compileHTMLTemplate ("Hello World
") file = StringIO.StringIO () template.expand (self.context, file) realResult = file.getvalue() self.fail ("No exception raised during parsing of unbalanced tag.") except simpleTAL.TemplateParseException, e: pass def testEncodedCharsSection (self): self._runTest_ ("""<section> stuff & things.
""" ,"""<section> stuff & things.
""" ,"Quoted chars were not re-encoded correctly.") def testDocumentTypeDeclaration (self): self._runTest_("""""" ,"""testing
""" ,"""Document type was not output correctly.""" ) def testHTMLComments (self): self._runTest_("""""" ,"""testing
""" ,"""Comment not output correctly.""" ) def testProcessingInstructions (self): self._runTest_ ("""\nSomemarkup
""" ,"""\nSomemarkup
""" ,"""Processing instructions not preserved.""") if __name__ == '__main__': unittest.main() SimpleTAL-4.1/tests/TALTests/HTMLTests/TALContentTestCases.py 0000644 0001750 0001750 00000010076 10007245640 022510 0 ustar cms103 cms103 #!/usr/bin/python """ Copyright (c) 2004 Colin Stewart (http://www.owlfish.com/) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. If you make any bug fixes or feature enhancements please let me know! Unit test cases. """ import unittest, os import StringIO import logging, logging.config from simpletal import simpleTAL, simpleTALES if (os.path.exists ("logging.ini")): logging.config.fileConfig ("logging.ini") else: logging.basicConfig() class TALContentTestCases (unittest.TestCase): def setUp (self): self.context = simpleTALES.Context() entry = """Some structure: """ weblog = {'subject': 'Test subject', 'entry': entry} self.context.addGlobal ('test', 'testing') self.context.addGlobal ('one', [1]) self.context.addGlobal ('two', ["one", "two"]) self.context.addGlobal ('three', [1,"Two",3]) self.context.addGlobal ('weblog', weblog) def _runTest_ (self, txt, result, errMsg="Error"): template = simpleTAL.compileHTMLTemplate (txt) file = StringIO.StringIO () template.expand (self.context, file) realResult = file.getvalue() self.failUnless (realResult == result, "%s - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (errMsg, txt, realResult, result, template)) def testContentNothing (self): self._runTest_ ('' ,'' ,'Content of nothing did not evaluate to empty tag.') def testContentDefault (self): self._runTest_ ('Original
' ,'Original
' ,'Content of default did not evaluate to existing content') def testContentString (self): self._runTest_ ('Original
' ,'testing
' ,'Content of string did not evaluate to contain string') def testContentStructure (self): # This test has specific needs - i.e. wrap the weblog/entry in a template... entry = """Some structure: """ entryTemplate = simpleTAL.compileHTMLTemplate(entry) weblog = {'subject': 'Test subject', 'entry': entryTemplate} self.context.addGlobal ('weblog', weblog) self._runTest_ ('Original
' ,'Some structure: Test subject
' ,'Content of Structure did not evaluate to expected result') def testTALDisabledContentStructure (self): self._runTest_ ('Original
' ,'Some structure:
' ,'Content of Structure did not evaluate to expected result') if __name__ == '__main__': unittest.main() SimpleTAL-4.1/tests/TALESTests/ 0000755 0001750 0001750 00000000000 10364737164 015016 5 ustar cms103 cms103 SimpleTAL-4.1/tests/TALESTests/StringTests.py 0000644 0001750 0001750 00000014323 10136353026 017650 0 ustar cms103 cms103 #!/usr/bin/python """ Copyright (c) 2004 Colin Stewart (http://www.owlfish.com/) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. If you make any bug fixes or feature enhancements please let me know! Unit test cases. """ import unittest, os import StringIO import logging, logging.config from simpletal import simpleTAL, simpleTALES if (os.path.exists ("logging.ini")): logging.config.fileConfig ("logging.ini") else: logging.basicConfig() def simpleFunction (): return "Hello" def simpleFalseFunc (): return 0 class StringTests (unittest.TestCase): def setUp (self): self.context = simpleTALES.Context() self.context.addGlobal ('top', 'Hello from the top') self.context.addGlobal ('alt', 'Wobble the way') self.context.addGlobal ('holder', {'helloFunc': simpleFunction ,'falseFunc': simpleFalseFunc}) self.context.addGlobal ('version', 3.1) self.context.addGlobal ('uniString', u"Hello") def _runTest_ (self, txt, result, errMsg="Error"): template = simpleTAL.compileHTMLTemplate (txt) file = StringIO.StringIO () template.expand (self.context, file) realResult = file.getvalue() self.failUnless (realResult == result, "%s - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (errMsg, txt, realResult, result, template)) def testEmptyString (self): self._runTest_ ('Exists' ,'' ,'Empty string returned something!' ) def testStaticString (self): self._runTest_ ('Exists' ,'Hello World!' ,'Static string didnt appear!' ) def testSingleVariable (self): self._runTest_ ('Exists' ,'Hello from the top' ,'Single variable failed.' ) def testStartVariable (self): self._runTest_ ('Exists' ,'Hello from the top of here' ,'Start variable failed.' ) def testMidVariable (self): self._runTest_ ('Exists' ,'Thoughts - Hello from the top eh?' ,'Mid variable failed.' ) def testEndVariable (self): self._runTest_ ('Exists' ,'Thought - Hello from the top' ,'End variable failed.' ) def testNumericVariable (self): self._runTest_ ('Exists' ,'Thought - 3.1' ,'Numeric test variable failed.' ) def testUnicodeVariable (self): self._runTest_ ('Exists' ,'Thought - Hello' ,'Unicode test variable failed.' ) def testSinglePath (self): self._runTest_ ('Exists' ,'Hello from the top' ,'Single path failed.' ) def testStartPath (self): self._runTest_ ('Exists' ,'Hello from the top of here' ,'Start path failed.' ) def testMidPath (self): self._runTest_ ('Exists' ,'Thoughts - Hello from the topeh?' ,'Mid path failed.' ) def testEndPath (self): self._runTest_ ('Exists' ,'Thought - Hello from the top' ,'End path failed.' ) def testMultiplePath (self): self._runTest_ ('Exists' ,'Thought - Hello from the top is here and recursive' ,'Multiple paths failed.' ) def testNoSuchPath (self): self._runTest_ ('Exists' ,'' ,'No such path failed.' ) def testTrailingDollar (self): self._runTest_ ('Exists' ,'A trailing dollar: ' ,'No such path failed.' ) def testDollarEscaping (self): self._runTest_ ('Exists' ,'$A trailing $dollar: $' ,'No such path failed.' ) def testPartialMissing (self): self._runTest_ ('Exists' ,'First bit here: Wobble the way second bit not: there.' ,'Combination of non-existant variable and existing test failed.' ) if __name__ == '__main__': unittest.main() SimpleTAL-4.1/tests/TALESTests/ExistsTests.py 0000644 0001750 0001750 00000010122 10347326342 017657 0 ustar cms103 cms103 #!/usr/bin/python """ Copyright (c) 2004 Colin Stewart (http://www.owlfish.com/) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. If you make any bug fixes or feature enhancements please let me know! Unit test cases. """ import unittest, os import StringIO import logging, logging.config from simpletal import simpleTAL, simpleTALES if (os.path.exists ("logging.ini")): logging.config.fileConfig ("logging.ini") else: logging.basicConfig() def simpleFunction (): return "Hello World" def nestedFunction (): return {'nest': simpleFunction} class ExistsTests (unittest.TestCase): def setUp (self): self.context = simpleTALES.Context() self.context.addGlobal ('top', 'Hello from the top') self.context.addGlobal ('alt', 'Wobble the way') self.context.addGlobal ('theMap', {'top': 'Hello', 'onelevel': {'top': 'Bye'}}) self.context.addGlobal ('funcMap', {'simple': simpleFunction, 'nested': nestedFunction}) self.context.addGlobal ('topFunc', simpleFunction) def _runTest_ (self, txt, result, errMsg="Error"): template = simpleTAL.compileHTMLTemplate (txt) file = StringIO.StringIO () template.expand (self.context, file) realResult = file.getvalue() self.failUnless (realResult == result, "%s - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (errMsg, txt, realResult, result, template)) def testOneVarDoesExist (self): self._runTest_ ('Top' ,'Top' ,'Exists check on single variable failed.' ) def testOneVarDoesNotExist (self): self._runTest_ ('Top' ,'' ,'Exists check on single variable that does not exist failed.' ) def testTwoVarDoesExist (self): self._runTest_ ('Top' ,'Top' ,'Exists check on two variables failed.' ) def testTwoVarDoesNotExist (self): self._runTest_ ('Top' ,'' ,'Exists check on two variables that dont exist failed.' ) def testOneFuncExist (self): self._runTest_ ('Top' ,'Top' ,'Exists check on one function failed.' ) def testTwoFuncExist (self): self._runTest_ ('Top' ,'Top' ,'Exists check on two function failed.' ) def testNothingExists (self): self._runTest_ ('Top' ,'Top' ,'Nothing should exist!' ) if __name__ == '__main__': unittest.main() SimpleTAL-4.1/tests/TALESTests/NoCallTests.py 0000644 0001750 0001750 00000010127 10007245640 017547 0 ustar cms103 cms103 #!/usr/bin/python """ Copyright (c) 2004 Colin Stewart (http://www.owlfish.com/) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. If you make any bug fixes or feature enhancements please let me know! Unit test cases. """ import unittest, os import StringIO import logging, logging.config from simpletal import simpleTAL, simpleTALES if (os.path.exists ("logging.ini")): logging.config.fileConfig ("logging.ini") else: logging.basicConfig() class CallRecorder: def __init__ (self): self.called = 0 def simpleFunction (self): self.called = 1 return "Hello" class NoCallTests (unittest.TestCase): def setUp (self): self.context = simpleTALES.Context() self.recorder = CallRecorder() self.context.addGlobal ('top', 'Hello from the top') self.context.addGlobal ('alt', 'Wobble the way') self.context.addGlobal ('holder', {'recorder': self.recorder.simpleFunction}) def _runTest_ (self, txt, result, errMsg="Error", expectedRecorderVal=0): template = simpleTAL.compileHTMLTemplate (txt) file = StringIO.StringIO () template.expand (self.context, file) realResult = file.getvalue() self.failUnless (realResult == result, "%s - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (errMsg, txt, realResult, result, template)) self.failUnless (self.recorder.called == expectedRecorderVal, 'Call recorder detected that the call recorder object has state %s' % str (self.recorder.called)) def testNoCallString (self): self._runTest_ ('Exists' ,'Exists' ,'Binding string using nocall failed.' ) def testNoCallRecorder (self): self._runTest_ ('Exists' ,'Exists' ,'Binding function using nocall failed.' ) def testNoCallORPath (self): self._runTest_ ('Exists' ,'Exists' ,'Binding function using nocall as first part of path failed' ) def testNoCallORPathTwo (self): self._runTest_ ('Exists' ,'Exists' ,'Binding function using nocall as second part of path failed' ) def testNoCallRecorderInfra (self): self._runTest_ ('Exists' ,'Exists' ,'Recorder failed to note call' ,1 ) if __name__ == '__main__': unittest.main() SimpleTAL-4.1/tests/TALESTests/VariablePathTest.py 0000644 0001750 0001750 00000007517 10007245640 020567 0 ustar cms103 cms103 #!/usr/bn/python """ Copyright (c) 2004 Colin Stewart (http://www.owlfish.com/) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. If you make any bug fixes or feature enhancements please let me know! Unit test cases. """ import unittest, os import StringIO import logging, logging.config from simpletal import simpleTAL, simpleTALES if (os.path.exists ("logging.ini")): logging.config.fileConfig ("logging.ini") else: logging.basicConfig() def simpleFunction (): return "Hello World" def nestedFunction (): return {'nest': simpleFunction} def pathFunction (thePath): return thePath class PathTests (unittest.TestCase): def setUp (self): self.context = simpleTALES.Context() self.context.addGlobal ('colours', {'blue': 'The sea is blue', 'red': 'The ball is red', 'green': 'The grass is green'}) self.context.addGlobal ('aList', ['blue', 'green']) self.context.addGlobal ('goodColour', 'goodColourPath') self.context.addGlobal ('goodColourPath', 'Black is good') self.context.addGlobal ('noSuchColour', 'pink') def _runTest_ (self, txt, result, errMsg="Error"): template = simpleTAL.compileHTMLTemplate (txt) file = StringIO.StringIO () template.expand (self.context, file) realResult = file.getvalue() self.failUnless (realResult == result, "%s - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (errMsg, txt, realResult, result, template)) def testRepeatVariablePath (self): self._runTest_ ('It is red:
' ,'It is red: The ball is red
' ,'Local variable path failed.' ) def testGlobalVariablePath (self): self._runTest_ ('' ,'Black is good
' ,'Global variable path failed.' ) def testNoSuchVariablePath (self): self._runTest_ ('' ,'' ,'No such variable failed.' ) def testNoSuchVariablePath2 (self): self._runTest_ ('' ,'' ,'No such variable2 failed.' ) SimpleTAL-4.1/tests/TALESTests/PythonPathTests.py 0000644 0001750 0001750 00000015612 10007245640 020501 0 ustar cms103 cms103 #!/usr/bin/python """ Copyright (c) 2004 Colin Stewart (http://www.owlfish.com/) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. If you make any bug fixes or feature enhancements please let me know! Unit test cases. """ import unittest, os import StringIO import logging, logging.config from simpletal import simpleTAL, simpleTALES if (os.path.exists ("logging.ini")): logging.config.fileConfig ("logging.ini") else: logging.basicConfig() def simpleFunction (param): return "Hello %s" % param def helloFunction (): return "Hello" def exceptionalFunction (param): raise Exception (param) class PythonPathTests (unittest.TestCase): def setUp (self): pass def _runTest_ (self, txt, result, errMsg="Error", allowPythonPath=0): self.context = simpleTALES.Context(allowPythonPath=allowPythonPath) self.context.addGlobal ('top', 'Hello from the top') self.context.addGlobal ('exceptFunc', exceptionalFunction) self.context.addGlobal ('helloFunc', simpleFunction) self.context.addGlobal ('helloPath', simpleTALES.PathFunctionVariable(simpleFunction)) self.context.addGlobal ('helloFunction', helloFunction) self.context.addGlobal ('myList', [1,2,3,4,5,6]) self.context.addGlobal ('testing', 'testing') self.context.addGlobal ('map', {'test': 'maptest'}) self.context.addGlobal ('data', {'one': 1, 'zero': 0}) template = simpleTAL.compileHTMLTemplate (txt) file = StringIO.StringIO () template.expand (self.context, file) realResult = file.getvalue() self.failUnless (realResult == result, "%s - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (errMsg, txt, realResult, result, template)) def testPythonPathException (self): self._runTest_ ("""Exists""" ,'Exception: Test exception!' ,'Exception thrown during python path not handled!' ,allowPythonPath=1 ) def testPythonPathDisabled (self): self._runTest_ ("""Exists""" ,'0' ,'Python path with allowPythonPath=false still expanded!' ,allowPythonPath=0 ) def testPythonPathFuncSuccess (self): self._runTest_ ("""Exists""" ,'Hello Colin!' ,'Python path with function failed.' ,allowPythonPath=1 ) def testPythonPathSliceSuccess (self): self._runTest_ ("""Exists""" ,'34' ,'Python path with slice failed.' ,allowPythonPath=1 ) def testPythonStringCompare (self): self._runTest_ ("""Passed.""" ,'Passed.' ,'Python string compare failed.' ,allowPythonPath=1 ) def testPythonPathFunc (self): self._runTest_ ("""Passed.""" ,'maptest' ,'Python path function call failed' ,allowPythonPath=1 ) def testPythonStringFunc (self): self._runTest_ ("""Passed.""" ,'Hello maptest there' ,'Python string function call failed' ,allowPythonPath=1 ) def testPythonExistsFunc1 (self): self._runTest_ ("""Passed.""" ,'Passed.' ,'Python exists function call failed' ,allowPythonPath=1 ) def testPythonExistsFunc2 (self): self._runTest_ ("""Passed.""" ,'' ,'Python exists function call failed' ,allowPythonPath=1 ) def testPythonNocallFunc (self): self._runTest_ ("""Passed.""" ,'Passed.' ,'Python nocall function call failed' ,allowPythonPath=1 ) def testPythonPathFuncWithFunc (self): self._runTest_ ("""Passed.""" ,'Passed.' ,'Python path function using a function failed' ,allowPythonPath=1 ) def testPythonPathFuncWithPath (self): self._runTest_ ("""Passed.""" ,'Passed.' ,'Python path function wrapped in a PathFunctionVariable failed' ,allowPythonPath=1 ) def testTestFunctionDefault (self): self._runTest_ ("""Passed.""" ,'Passed.' ,'Test function failed to use default.' ,allowPythonPath=1 ) def testTestFunctionTwoArgs (self): self._runTest_ ("""Passed.""" ,'' ,'Test function failed to use default of false.' ,allowPythonPath=1 ) def testTestFunctionThreeArgs (self): self._runTest_ ("""Passed.""" ,'2' ,'Test function failed to use default.' ,allowPythonPath=1 ) def testTestFunctionFiveArgs (self): self._runTest_ ("""Passed.""" ,'5' ,'Test function failed to use default.' ,allowPythonPath=1 ) if __name__ == '__main__': unittest.main() SimpleTAL-4.1/tests/TALESTests/NotTests.py 0000644 0001750 0001750 00000010721 10007245640 017137 0 ustar cms103 cms103 #!/usr/bin/python """ Copyright (c) 2004 Colin Stewart (http://www.owlfish.com/) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. If you make any bug fixes or feature enhancements please let me know! Unit test cases. """ import unittest, os import StringIO import logging, logging.config from simpletal import simpleTAL, simpleTALES if (os.path.exists ("logging.ini")): logging.config.fileConfig ("logging.ini") else: logging.basicConfig() def simpleFunction (): return "Hello" def simpleFalseFunc (): return 0 class NotTests (unittest.TestCase): def setUp (self): self.context = simpleTALES.Context() self.context.addGlobal ('top', 'Hello from the top') self.context.addGlobal ('alt', 'Wobble the way') self.context.addGlobal ('holder', {'helloFunc': simpleFunction ,'falseFunc': simpleFalseFunc}) def _runTest_ (self, txt, result, errMsg="Error"): template = simpleTAL.compileHTMLTemplate (txt) file = StringIO.StringIO () template.expand (self.context, file) realResult = file.getvalue() self.failUnless (realResult == result, "%s - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (errMsg, txt, realResult, result, template)) def testNotNothing (self): self._runTest_ ('Exists' ,'Exists' ,'not:nothing returned false' ) def testNotDefault (self): self._runTest_ ('Exists' ,'' ,'not:default returned true' ) def testNotNoSuchPath (self): self._runTest_ ('Exists' ,'Exists' ,'not:no/such/path returned false' ) def testNotSomething (self): self._runTest_ ('Exists' ,'' ,'not:string returned true' ) def testNotFalse (self): self._runTest_ ('Exists' ,'Exists' ,'not:false returned false' ) def testNotExists (self): self._runTest_ ('Exists' ,'' ,'not:exists:nothing returned true' ) def testNotORPathOne (self): self._runTest_ ('Exists' ,'' ,'not:no/such/path | holder/helloFunc returned true' ) def testNotORPathTwo (self): self._runTest_ ('Exists' ,'Exists' ,'not:no/such/path | holder/falseFunc returned false' ) def testNotORPathThree (self): self._runTest_ ('Exists' ,'' ,'no/such/path | not:holder/helloFunc returned true' ) def testNotORPathFour (self): self._runTest_ ('Exists' ,'Exists' ,'no/such/path | not:holder/falseFunc returned false' ) if __name__ == '__main__': unittest.main() SimpleTAL-4.1/tests/TALESTests/ElementTreeTests.py 0000644 0001750 0001750 00000007351 10347326342 020623 0 ustar cms103 cms103 #!/usr/bin/python """ Copyright (c) 20045Colin Stewart (http://www.owlfish.com/) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. If you make any bug fixes or feature enhancements please let me know! Unit test cases. """ import unittest, os import StringIO import logging, logging.config try: from simpletal import simpleElementTree ELEMENT_TREE_SUPPORT = 1 except: ELEMENT_TREE_SUPPORT = 0 from simpletal import simpleTAL, simpleTALES if (os.path.exists ("logging.ini")): logging.config.fileConfig ("logging.ini") else: logging.basicConfig() def simpleFunction (param): return "Hello %s" % param def helloFunction (): return "Hello" class ElementTreeTestCases (unittest.TestCase): def setUp (self): pass def _runTest_ (self, txt, result, errMsg="Error", allowPythonPath=0): if (not ELEMENT_TREE_SUPPORT): logging.warn ("No ElementTree support found, skipping test.") return self.context = simpleTALES.Context(allowPythonPath=allowPythonPath) self.context.addGlobal ('top', 'Hello from the top') self.context.addGlobal ('helloFunc', simpleFunction) self.context.addGlobal ('helloPath', simpleTALES.PathFunctionVariable(simpleFunction)) self.context.addGlobal ('helloFunction', helloFunction) self.context.addGlobal ('myList', [1,2,3,4,5,6]) self.context.addGlobal ('testing', 'testing') self.context.addGlobal ('map', {'test': 'maptest'}) self.context.addGlobal ('data', {'one': 1, 'zero': 0}) testXML = 'Simple |
Sample |
Real Results |
Expected Results |
Template parsed each time around the loop |
100 |
Slow, SGMLParser takes a while |
Slow |
Template parsed once, then used multiple times |
100 |
Fast! |
Hopefully faster than parsing each time |
XML Version |
100 |
Faster than SGML |
Still too slow |
XML Version of TALTemplates |
100 |
As fast as SGML |
We can hope. |
Simple |
Sample |
Real Results |
Expected Results |
Template parsed each time around the loop |
100 |
Slow, SGMLParser takes a while |
Slow |
Template parsed once, then used multiple times |
100 |
Fast! |
Hopefully faster than parsing each time |
XML Version |
100 |
Faster than SGML |
Still too slow |
XML Version of TALTemplates |
100 |
As fast as SGML |
We can hope. |
Colour
Colour
Important Stuff, worth £££s |
---|
Table |
things
things
Message
""" XMLTemplate1 = """\nMessage
""" TEMP_DIR="/tmp/" HTML_TEMPLATE_NAME='TemplateCacheTestCasesHtmlTemplate.html' XML_TEMPLATE_NAME='TemplateCacheTestCasesXmlTemplate.xml' EXPXML_TEMPLATE_NAME='TemplateCacheTestCasesXmlTemplate.xhtml' #print "Macro is: %s" % str (macroTemplate) class TemplateCacheTestCases (unittest.TestCase): def setUp (self): self.context = simpleTALES.Context() self.cache = simpleTALUtils.TemplateCache() self.context.addGlobal ('title', 'Cache Test') self.context.addGlobal ('message', 'Testing the cache...') def _runTest_ (self, template, txt, result, errMsg="Error"): realResult = simpleTALUtils.ExpandMacros (self.context, template) self.failUnless (realResult == result, "%s - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (errMsg, txt, realResult, result, template)) def testHTMLTemplateCacheNoFile (self): # Remove any previously created test files name = os.path.join (TEMP_DIR, HTML_TEMPLATE_NAME) try: os.remove (name) except: pass # This should error out... try: template = self.cache.getTemplate (name) self.fail ("Expected exception trying to retrieve anavailable template") except Exception, e: # Pass! pass def testHTMLTemplateCache (self): # Remove any previously created test files name = os.path.join (TEMP_DIR, HTML_TEMPLATE_NAME) try: os.remove (name) except: pass # Ensure that time ellapses so that a ctime change is recorded time.sleep (1) tf = open (name, 'w') tf.write (HTMLTemplate1) tf.close() # Get the template template = self.cache.getTemplate (name) outputFile = StringIO.StringIO () template.expand (self.context, outputFile) expectedResult = """Testing the cache...
""" self.failUnless (outputFile.getvalue() == expectedResult ,"Error: template did not expand to expected result. Expected: %s got: %s" % (expectedResult, outputFile.getvalue())) self.failUnless (self.cache.misses == 2, "Cache miss not recorded!") # Get the cached template template = self.cache.getTemplate (name) outputFile = StringIO.StringIO () template.expand (self.context, outputFile) expectedResult = """Testing the cache...
""" self.failUnless (outputFile.getvalue() == expectedResult ,"Error: template did not expand to expected result. Expected: %s got: %s" % (expectedResult, outputFile.getvalue())) self.failUnless (self.cache.hits == 2, "Cache hit not recorded!") def testXMLTemplateCacheNoFile (self): # Remove any previously created test files name = os.path.join (TEMP_DIR, XML_TEMPLATE_NAME) try: os.remove (name) except: pass # This should error out... try: template = self.cache.getTemplate (name) self.fail ("Expected exception trying to retrieve anavailable template") except Exception, e: # Pass! pass def testXMLTemplateCache (self): # Remove any previously created test files name = os.path.join (TEMP_DIR, XML_TEMPLATE_NAME) try: os.remove (name) except: pass # Ensure that time ellapses so that a ctime change is recorded time.sleep (1) tf = open (name, 'w') tf.write (XMLTemplate1) tf.close() # Get the template template = self.cache.getTemplate (name) outputFile = StringIO.StringIO () template.expand (self.context, outputFile) expectedResult = """\nTesting the cache...
""" self.failUnless (outputFile.getvalue() == expectedResult ,"Error: template did not expand to expected result. Expected: %s got: %s" % (expectedResult, outputFile.getvalue())) self.failUnless (self.cache.misses == 2, "Cache miss not recorded!") # Get the cached template template = self.cache.getTemplate (name) outputFile = StringIO.StringIO () template.expand (self.context, outputFile) expectedResult = """\nTesting the cache...
""" self.failUnless (outputFile.getvalue() == expectedResult ,"Error: template did not expand to expected result. Expected: %s got: %s" % (expectedResult, outputFile.getvalue())) self.failUnless (self.cache.hits == 2, "Cache hit not recorded!") def testExplicitXMLTemplateCache (self): # Remove any previously created test files name = os.path.join (TEMP_DIR, EXPXML_TEMPLATE_NAME) try: os.remove (name) except: pass # Ensure that time ellapses so that a ctime change is recorded time.sleep (1) tf = open (name, 'w') tf.write (XMLTemplate1) tf.close() # Get the template template = self.cache.getXMLTemplate (name) outputFile = StringIO.StringIO () template.expand (self.context, outputFile) expectedResult = """\nTesting the cache...
""" self.failUnless (outputFile.getvalue() == expectedResult ,"Error: template did not expand to expected result. Expected: %s got: %s" % (expectedResult, outputFile.getvalue())) self.failUnless (self.cache.misses == 2, "Cache miss not recorded!") # Get the cached template template = self.cache.getXMLTemplate (name) outputFile = StringIO.StringIO () template.expand (self.context, outputFile) expectedResult = """\nTesting the cache...
""" self.failUnless (outputFile.getvalue() == expectedResult ,"Error: template did not expand to expected result. Expected: %s got: %s" % (expectedResult, outputFile.getvalue())) self.failUnless (self.cache.hits == 2, "Cache hit not recorded!") if __name__ == '__main__': unittest.main() SimpleTAL-4.1/tests/TALUtilsTests/HTMLStructureCleanerTestCases.py 0000644 0001750 0001750 00000011616 10007245640 023747 0 ustar cms103 cms103 #!/usr/bin/python # -*- coding: iso-8859-1 -*- """ Copyright (c) 2004 Colin Stewart (http://www.owlfish.com/) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. If you make any bug fixes or feature enhancements please let me know! Unit test cases. """ import unittest, os, codecs import StringIO import logging, logging.config from simpletal import simpleTALUtils isoText = """Documentation on how to use the simpleTAL Module.
Two helper functions are provided for convenience, one for compiling HTML templates, and one for compiling XML templates. If an error is encountered during compilation (for example mismatched TAL tags or bad syntax) an TemplateParseException will be thrown.
Compiles the passed in HTML template into an instance of the 'Template' class. The template object should be either a string containing the template, or a file-like object. The inputEncoding specifies the encoding that the template was written using and deafults to iso-8859-1. The minimizeBooleanAtts flag controls whether HTML boolean attributes (e.g. <img ismap>) should be written out in minimized form. See below for details of how to use the Template class.
Compiles the passed in XML template into an instance of the 'Template' class. The template object should be either a string containing the template, or a file-like object. The XML template must be a well formed XML document. The character set will be determined from the prolog of the template or be assumed to be utf-8. See below for details of how to use the Template class.
Compiles an XML template that is stored as a DOM tree. This requires PyXML to be installed to function.
The compiled templates contain all of the logic required to be able to expand themselves for a given context. They can be kept around and reused as often as required, there is no need or benefit to re-compiling them unless the underlying template changes. They have one method of interest as part of the external API:
def expand (self, context, outputFile[,outputEncoding] [,docType][,suppressXMLDeclaration])
This method will expand the template, using the simpleTALES.Context object provided, and write the output into the given file-like object. If the template is a HTML template then the result will, by default, be encoded in iso-8859-1. If no outputEncoding is specified and the template is an XML template then it will default to utf-8.
The docType and suppressXMLDeclaration variables apply only to XML Templates.
Python's support for XML does not currently extend to the LexicalHandler API, which is required for an application to be able to read an XML documents DOCTYPE. If pyXML is installed SimpleTAL will make use of it to determine the XML DOCTYPE, otherwise the doctype must be passed as a named variable to the expand method.
For example to produce a valid strict XHTML document without pyXML use:
template.expand (context, outputFile, docType='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">')
If the suppressXMLDeclaration is set to true then the XML Declaration will not be included in the output (required for XHTML in IE6).
PubTal Version
SimpleTAL-4.1/documentation/html/index.html 0000644 0001750 0001750 00000003171 10347331422 017561 0 ustar cms103 cms103Welcome to SimpleTAL
SimpleTAL is a stand alone Python implementation of the TAL, TALES and METAL specifications used in Zope to power HTML and XML templates. SimpleTAL is an independent implementation of TAL; there are no dependencies on Zope nor is any of the Zope work re-used.
A mailing list exists for discussion of SimpleTAL and support questions.
Feedback, feature enhancements and bug fixes will all be gladly received!
PubTal Version
SimpleTAL-4.1/documentation/html/api-simpletales.html 0000644 0001750 0001750 00000007261 10347331422 021547 0 ustar cms103 cms103Documentation on how to use the simpleTALES Module.
The only external class in this module is the Context class.
Creates a new Context object, used by SimpleTAL when expanding a template. The options variable, if passed, will be made available as a global variable under the name "options" as per the TALES specification.
By default Python TAL paths (e.g. 'python: 1 + 2') are not allowed. If you require them, and you completely trust the authors of the templates, they can be enabled by passing in allowPythonPath=1.
Adds the value to the context under name. Value can either be a fundamental python data type or a callable object. For example, take the code:
class Test:
def __init__ (self, val):
self.val = val
def getResult (self):
return str (self.val + 4)
test = Test (10)
context = SimpleTALES.Context()
context.addGlobal ("number14", test.getResult)
context.addGlobal ("data", {"one": {"blue": ("Cat", "Dog", "Mouse"), "pink": ["One"]}})
The affect of this context is shown for several different TALES expressions:
<b tal:define="test1 nocall:number14"></b>
The method 'getResult' is bound to the local variable test1.
<b tal:define="test2 number14"></b>
The local variable test2 is assigned the value "14"
<b tal:repeat="pets data/one/blue"><i tal:replace="pets"></i></b>
Prints out <b>CatDogMouse</b>
All strings placed into the context, and all strings returned by callable objects should be unicode strings. This allows the rendering of the template into different character sets without requiring any code changes.
This class wraps a callable object (e.g. function) so that it can receive part of a TAL path as it's argument. To use this simply create a new instance of the PathFunctionVariable and then place this into the Context (see above). The path passed to the function is that part of the path not already used. For example if the function "helloFunc" is placed in the Context the path "helloFunc/an/example" results in the string "an/example" being passed to the function.
This class wraps a callable object (e.g. function) so that the callable is only called once. In normal SimpleTAL operation any function placed into a Context will be called multiple times during template expansion. To ensure that it is only called once simply wrap in the CachedFuncResult object first.
Clears the cache. Use this to clear the cache between multiple template expansions if the callable should be executed once per template expansion.
PubTal Version
SimpleTAL-4.1/documentation/html/notes.html 0000644 0001750 0001750 00000015704 10347331422 017607 0 ustar cms103 cms103Notes, known limitations, and differences between SimpleTAL and Zope's ZPT.
Some notes on aspects of SimpleTAL that might require a little explanation. If there is something you feel should be included in here, please let me know.
As a bug fix version 2.1 of SimpleTAL now processes HTML templates slightly differently to XML templates. In the HTML 4.01 specification there are several elements (e.g. <img>) for which end tags are forbidden. This would normally cause a problem with TAL, because all tags that have TAL attributes on them must be closed. To solve this problem SimpleTAL has been modified to:
These changes ensure that a HTML template can still be a valid HTML document, even if TAL needs to be used on elements that forbid end tags. Additionally the output from the expanded template will also be valid HTML, in that the end tags will be suppressed even if present in the template.
As a consequence of this change it is important that any XHTML templates are handled as XML rather than HTML, i.e. by calling compileXMLTemplate to compile the template.
SimpleTAL fully supports international character sets, providing all of the encoding options that Python supports. To painlessly support the correct conversion between character sets, just follow these simple rules:
When content is included into a template using 'tal:content' or 'tal:replace' the content is by default treated as text. This means that the '<', '>' and '&' characters will be automatically escaped so that they appear in the rendered template correctly.
When using the 'structure' keyword, however, SimpleTAL will pass the content straight through into the template with no escaping. As such it's important to realise that the content placed into a template in such a way can affect the validity of the output. For example if you take user input that contains HTML markup it's important to ensure that the markup is valid HTML, otherwise the resulting template output will not be valid. In order to assist in doing this I've put together a class (HTMLStructureCleaner) in simpleTALUtils that will escape any stray '<', '>' or '&' characters present while leaving all elements and attributes intact.
The restriction in SimpleTAL 1.x when including structured content into an XML template is now removed - the structure is not re-parsed, and so does not have to be valid XML.
When adding a mapping object (e.g. a Dictionary) to the Context, care should be taken on the naming conventions used within the mapping. When SimpleTAL/ES resolves a path, it will first look for attributes on the object with that name, before trying to treat the object as a mapping object. What this means in practice is that paths which match object attributes (e.g. methods) will never select the values given in the mapping. As an example of this consider the following:
Template: <p tal:repeat="item dict/items"><b tal:replace="item"></b></p>
Context:
myDict = {'items': [1,2,3]}
Context.addGlobal ("dict", myDict)
You would expect the output from this to be:
<p>1</p><p>2</p><p>3</p>
However this is not what happens. Instead the variable "item" will be set to the output of "myDict.items()" - i.e. it will call the Python dictionary method 'items()'.
I have considered changing this so that mapping checks are made first in path resolution rather than attribute lookups. When I checked the Zope 2.5 behaviour however, I found that it works the same way as SimpleTAL, so for now I've left it to be consistent with Zope.
When using the 'python:' path type, care must be taken with the use of the less than (<) and greater than (>) signs. These must be escaped in the same way as all other HTML markup. For example:
use: <div tal:condition="python: a < b">Conditional Text</div>
instead of: <div tal:condition="python: a < b">Conditional Text</div>
Non-existent path types, e.g. '<b tal:content="total: $totalAmount"></b>' are not supported. In Zope, this results in the path being interpreted as a string - in simpleTAL/ES the result will be an error.
PubTal Version
SimpleTAL-4.1/documentation/html/api-simpleelementtree.html 0000644 0001750 0001750 00000005737 10347331422 022756 0 ustar cms103 cms103Documentation on how to use the simpleElementTree Module.
This module provides optional integration with ElementTree, allowing XML documents to be parsed and placed directly into the Context. The contents of the XML document can then be accessed using an sub-set of XPATH from within TAL templates.
This function takes one parameter, which should be either a file-like object or a string holding the name of a file on the filesystem. The file is read, the XML it contains is parsed, and an instance of simpleTALES.ContextVariable is returned.
The returned ContextVariable can then be added to the Context using addGlobal in the normal way, e.g.
xmlTree = simpleElementTree.parseFile (file="input.xml")
context = simpleTALES.Context(allowPythonPath=1)
context.addGlobal ("input", xmlTree)
The Context variable provided by parseFile provides the following syntax for path access in TAL:
Here are some examples:
<html>
<body>
<h1 tal:attributes="class input/title/@type" tal:content="input/title">Title here</h1>
<ul>
<li tal:repeat="note input/findall/.//note">
<b tal:condition="note/@type" tal:replace="string: Note (${note/@type}) - $note and then some"></b>
</li>
</ul>
</body>
</html>
PubTal Version
SimpleTAL-4.1/documentation/html/api-simpletalutils.html 0000644 0001750 0001750 00000010443 10347331422 022274 0 ustar cms103 cms103Documentation on how to use the simpleTALUtils Module.
This module holds optional classes and functions that might be of use while using SimpleTAL, but are not required by SimpleTAL directly.
This function can be used to expand a template which contains METAL macros, while leaving in place all the TAL and METAL commands. Doing this makes editing a template which uses METAL macros easier, because the results of the macro can be seen immediately.
The macros referred to by the passed in template must be present in the context so that their contents can be referenced. The outputEncoding determines the encoding of the returned string, which will contain the expanded macro.
This class implements a very restricted File type object that can return a string containing all data written into it. Unlike StringIO, FastStringOutput only supports write operations, and so is faster. Only two methods are supported: write and getvalue.
Used by SimpleTAL to write the expanded template.
Use this to retrieve a string with the resulting output.
This class implements a cache for compiled templates which automatically invalidates entries when their template file changes. The instance has one public method: getTemplate
This method will return a compiled template from the file 'name'. If the file ends in '.xml' it will be compiled using simpleTAL.compileXMLTemplate, otherwise it will be compiled as a HTML template. If the method is called again it will check to see whether the file 'name' has changed since the last call, and if it has it will re-compile the template,otherwise it will return the cached version.
HTML Templates will be taken as being stored in the "inputEncoding", XML templates ignore this parameter.
This method will return a compiled XML template from the file 'name'. This works identically to getTemplate as described above, except that it always treats the template as XML.
This class can be used to encode any stray special characters within a given string or file-like object. Its intended use is in preparing data that will be placed into a Context object and then included in a template using the 'structure' keyword. The class uses the Python SGML parser to determine what tags are present, so any HTML markup will be left intact. As an example, take the content:
This is some <b>bad</b> html that is < than great!
If this was included in a template in its current state the result would be bad markup. Once cleaned by this class, the result would be:
This is some <b>bad</b> html that is < than great!
The class has one external method:
def clean (self, content, encoding=None)
The content should be either a string or a file-like object. If the string is a unicode string (u"") it will be cleaned as is. If the string is an ordinary string then the encoding must be supplied, and it will first be converted to unicode. If the content object is a file-like object then it will be converted only if the encoding is supplied.
The call returns a unicode string that has the '<', '>' and '&' characters encoded.
PubTal Version
SimpleTAL-4.1/documentation/html/tal-guide.html 0000644 0001750 0001750 00000025024 10347331422 020326 0 ustar cms103 cms103A guide to using TAL, TALES, and METAL.
This is a simple reference guide to the TAL and TALES languages. Formal language specifications are hosted by Zope: TAL, TALES, and METAL.
TAL consists of seven different commands (highest priority first): define, condition, repeat, content, replace, attributes, and omit-tag. Commands are attributes on HTML or XML tags, e.g. <div tal:content="article">Article goes here</div>
Syntax: tal:define="[local | global] name expression [; define-expression...]
Description: Sets the value of "name" to "expression". By default the name will be applicable in the "local" scope, which consists of this tag, and all other tags nested inside this tag. If the "global" keyword is used then this name will keep its value for the rest of the document.
Example: <div tal:define="global title book/theTitle; local chapterTitle book/chapter/theTitle">
Syntax: tal:condition="expression"
Description: If the expression evaluates to true then this tag and all its children will be output. If the expression evaluates to false then this tag and all its children will not be included in the output.
Example: <h1 tal:condition="user/firstLogin">Welcome to this page!</h1>
Syntax: tal:repeat="name expression"
Description: Evaluates "expression", and if it is a sequence, repeats this tag and all children once for each item in the sequence. The "name" will be set to the value of the item in the current iteration, and is also the name of the repeat variable. The repeat variable is accessible using the TAL path: repeat/name and has the following properties:
index - Iteration number starting from zero
number - Iteration number starting from one
even - True if this is an even iteration
odd - True if this is an odd iteration
start - True if this is the first item in the sequence
end - True if this is the last item in the sequence. For iterators this is never true
length - The length of the sequence. For iterators this is maxint as the length of an iterator is unknown
letter - The lower case letter for this iteration, starting at "a"
Letter - Upper case version of letter
roman - Iteration number in Roman numerals, starting at i
Roman - Upper case version of roman
Example:
<table>
<tr tal:repeat="fruit basket">
<td tal:content="repeat/fruit/number"></td>
<td tal:content="fruit/name"></td>
</tr>
</table>
Syntax: tal:content="[text | structure] expression"
Description: Replaces the contents of the tag with the value of "expression". By default, and if the "text" keyword is present, then the value of the expression will be escaped as required (i.e. characters "&<> will be escaped). If the "structure" keyword is present then the value will be output with no escaping performed.
Example: <h1 tal:content="user/firstName"></h1>
Syntax: tal:replace="[text | structure] expression"
Description: Behaves identically to tal:content, except that the tag is removed from the output (as if tal:omit-tag had been used).
Example: <h1>Welcome <b tal:replace="user/firstName"></b></h1>
Syntax: tal:attributes="name expression[;attributes-expression]"
Description: Evaluates each "expression" and replaces the tag's attribute "name". If the expression evaluates to nothing then the attribute is removed from the tag. If the expression evaluates to default then the original tag's attribute is kept. If the "expression" requires a semi-colon then it must be escaped by using ";;".
Example: <a tal:attributes="href user/homepage;title user/fullname">Your Homepage</a>
Syntax: tal:omit-tag="expression"
Description: Removes the tag (leaving the tags content) if the expression evaluates to true. If expression is empty then it is taken as true.
Example: <p><b tal:omit-tag="not:user/firstVisit">Welcome</b> to this page!</h1>
The expressions used in TAL are called TALES expressions. The simplest TALES expression is a path which references a value, e.g. page/body references the body property of the page object.
Syntax: [path:]string[|TALES Expression]
Description: A path, optionally starting with the modifier 'path:', references a property of an object. The '/' delimiter is used to end the name of an object and the start of the property name. Properties themselves may be objects that in turn have properties. The '|' ("or") character is used to find an alternative value to a path if the first path evaluates to 'Nothing' or does not exist.
Example: <p tal:content="book/chapter/title | string:Untitled"></p>
There are several built in paths that can be used in paths:
nothing - acts as None in Python
default - keeps the existing value of the node (tag content or attribute value)
options - the dictionary of values passed to the template (through the Context __init__ method)
repeat - access the current repeat variable (see tal:repeat)
attrs - a dictionary of original attributes of the current tag
CONTEXTS - a dictionary containing all of the above
Syntax: exists:path
Description: Returns true if the path exists, false otherwise. This is particularly useful for removing tags from output when the tags will have no content.
Example: <p tal:omit-tag="not:exists:book/chapter/title" tal:content="book/chapter/title"></p>
Syntax: nocall:path
Description: Returns a reference to a path, but without evaluating the path. Useful when you wish to define a new name to reference a function, not the current value of a function.
Example: <p tal:define="title nocall:titleFunction" tal:content="title"></p>
Syntax: not:tales-path
Description: Returns the inverse of the tales-path. If the path returns true, not:path will return false.
Example: <p tal:condition="not: user/firstLogin">Welcome to the site!</p>
Syntax: string:text
Description: Evaluates to a literal string with value text while substituting variables with the form ${pathName} and $pathName
Example: <b tal:content="string:Welcome ${user/name}!"></b>
Syntax: python:python-code
Description: Evaluates the python-code and returns the result. The python code must be properly escaped, e.g. "python: 1 < 2" must be written as "python: 1 < 2". The python code has access to all Python functions, including four extra functions that correspond to their TALES commands: path (string), string (string), exists (string), and nocall (string)
Example: <div tal:condition="python: path (basket/items) > 1">Checkout!</div>
METAL is a macro language commonly used with TAL & TALES. METAL allows part of a template to be used as a macro in later parts of a template, or a separate template altogether.
Syntax: metal:define-macro="name"
Description: Defines a new macro that can be reference later as "name".
Example: <div metal:define-macro="footer">Copyright <span tal:content="page/lastModified">2004</span></div>
Syntax: metal:use-macro="expression"
Description: Evaluates "expression" and uses this as a macro.
Example: <div metal:use-macro="footer"></div>
Syntax: metal:define-slot="name"
Description: Defines a customisation point in a macro with the given name.
Example:
<div metal:define-macro="footer">
<b>Standard disclaimer for the site.</b>
<i metal:define-slot="Contact">Contact admin@site.com</i>
</div>
Syntax: metal:fill-slot="name"
Description: Replaces the content of a slot with this element.
Example:
<div metal:use-macro="footer">
<i metal:fill-slot="Contact">Contact someone else</i>
</div>
PubTal Version
SimpleTAL-4.1/documentation/html/api.html 0000644 0001750 0001750 00000005213 10347331422 017222 0 ustar cms103 cms103Documentation on how to use the SimpleTAL API.
SimpleTAL consists of three different modules: simpleTAL, simpleTALES, and simpleTALUtils. The API for each of these modules is documented separately:
SimpleTAL supports all character sets that Python supports. To use non-ASCII characters first convert them to Unicode strings prior to placing them into the Context object.
SimpleTAL uses the logging library, which is shipped as part of Python 2.3, to handle logging of debug messages, warnings, and errors. When used on a system that has no logging library SimpleTAL will suppress all logging messages.
To control the output of logging messages from SimpleTAL it is necessary to retrieve the logger objects for each module, which can be done using:
simpleTALLogger = logging.getLogger ("simpleTAL")
simpleTALESLogger = logging.getLogger ("simpleTALES")
The configuration of these loggers can then be adjusted as described in the logging library documentation. For example to stop warnings being logged:
simpleTALLogger.setLevel (logging.ERROR)
simpleTALESLogger.setLevel (logging.ERROR)
PubTal Version
SimpleTAL-4.1/documentation/style/ 0000755 0001750 0001750 00000000000 10364737164 015772 5 ustar cms103 cms103 SimpleTAL-4.1/documentation/style/site.css 0000644 0001750 0001750 00000002035 10101613234 017424 0 ustar cms103 cms103 .navbar { margin-top: 2em; text-align: center; } h1 { margin-bottom: 0px; padding-bottom: 0px; } #subject { font-style: italic; margin-top: 0px; padding-top: 0px; } #footer { font-size: smaller; margin-top: 2em; } #footer p { padding: 0px; margin: 0px; } #version { margin-top: 2em; font-size: smaller; float: right; } code { font-size: small; margin-top: 0em; white-space: pre; font-family: monospace; overflow: auto; } p + code { margin-top: 0em; } /* To work around the block effect of using as well as - more IE bugs */
pre {
display: block;
margin-top: 0px;
margin-bottom: 0px;
margin-left: 30px;
line-height: 100%;
}
* Paragraphs in tables are small */
table p {
margin: 0px;
}
/* Ordinary tables have borders. */
table {
border: 1px solid black;
}
td {
border: 1px solid black;
}
/* Nested tables do not. */
td table {
border: 0px;
}
td table td {
border: 0px;
}
/* Lists with paragraphs in them should not be spread out. */
li p {
margin: 0px;
}
.configOptions {
margin-left: 2em;
}
SimpleTAL-4.1/documentation/documentation.config 0000644 0001750 0001750 00000000641 10101613234 020647 0 ustar cms103 cms103 # Configuration file for SimpleTAL Documentation
#
# If SiteConfig is used it must be the first entry in the config file.
#
# Use ignore-filter to specify regular expressions for files that should not be treated
# as content (examples shown here are files in CVS directories and backup files)
content-dir src
dest-dir html
template-dir templates
ignore-filter .*\.svn.*
ignore-filter .*~$
SimpleTAL-4.1/documentation/src/ 0000755 0001750 0001750 00000000000 10364737164 015421 5 ustar cms103 cms103 SimpleTAL-4.1/documentation/src/api.txt 0000644 0001750 0001750 00000004017 10202213623 016711 0 ustar cms103 cms103 title: SimpleTAL API
subject: Documentation on how to use the SimpleTAL API.
SimpleTAL consists of three different modules: simpleTAL, simpleTALES, and simpleTALUtils. The API for each of these modules is documented separately:
- simpleTAL - contains functions to compile HTML and XML templates into objects ready for use.
- simpleTALES - contains the Context class which provides the environment in which templates are expanded.
- simpleTALUtils - optional utility functions for dealing with SimpleTAL templates.
- simpleElementTree - optional integration with ElementTree allowing XML documents to be parsed and placed directly into the Context instance.
International character support
SimpleTAL supports all character sets that Python supports. To use non-ASCII characters first convert them to Unicode strings prior to placing them into the Context object.
Logging in SimpleTAL
SimpleTAL uses the logging library, which is shipped as part of Python 2.3, to handle logging of debug messages, warnings, and errors. When used on a system that has no logging library SimpleTAL will suppress all logging messages.
To control the output of logging messages from SimpleTAL it is necessary to retrieve the logger objects for each module, which can be done using:
simpleTALLogger = logging.getLogger ("simpleTAL")
simpleTALESLogger = logging.getLogger ("simpleTALES")
The configuration of these loggers can then be adjusted as described in the logging library documentation. For example to stop warnings being logged:
simpleTALLogger.setLevel (logging.ERROR)
simpleTALESLogger.setLevel (logging.ERROR)
Back to SimpleTAL
SimpleTAL-4.1/documentation/src/tal-guide.sxw 0000644 0001750 0001750 00000030256 10326747752 020047 0 ustar cms103 cms103 PK …ŽW3á¥19 mimetypeapplication/vnd.sun.xml.writerPK …ŽW3 Configurations2/PK …ŽW3 Pictures/PK …ŽW3 layout-cachecd`d(0d``àd``1x$@"!0Ž;aSd PK¥©½ú$ 5 PK …ŽW3 content.xmlÕ]Ýr7²¾?O¨r\v•È%9¶©X{lGÙxKÊQ…ônκ\)p$q43˜`$q7[•78çbo²7ûhy’íÆÏüqøO‰tU*ÖÝÆ×F#}ý»û($·,•\į:í£Âb_<½>øÐÿ¶õòàwçÿñµ¹Ïºð³ˆÅªå‹XÁ¿zDzkZ_Œ•Jºž'›Wm‘Ž¼ã££#Ï<ØRMÂùôšÂ‘+v¯æR#ANLxk
G¤ôn.5€5ýPäÔwwwí»MÙyõê•÷cïÒûV¤Íu¹y|3“^·æzø9]’¥¡¦
|…
.½N»ã9Úˆ):Wg$pÄq
X:ˆTÑŠÁåí¨Ik33·¹-ü1MçOŒ¦(L},0õI‘ªñ˽ô® Qÿï겘—4šË òñù)OæknH\!ÄêÓ¼z¦N½»”+––Èý¹ä>
ý܈"š15(Zìá’G-gt8öLsN,ƒ™¬¼ºìùcÑ‚˜/&nñX*£el©†ûÒ©%µŸ»Xc&ÀËŸ‡rZóCyþµkñ†˜ç˜Fàø=EÓÞ$ˆð€…!Òˆ‡“j[‰¢T2ÀÃ}KšVo¾Œ>‹ˆv¦˜†Cr™ù< ’Æò<¡‰gæ
éÁ+óÂ5¼I9
ɇ˜CÔeäªgÞ.Òà-WR¥ŒFä,5lÉ•ˆÅ´J†ß,z+l
Ó±5b1K9 3½Ò¸B’påƒwù=ÖдÁp3µlPÐJ¿¥`9Œäøî÷äŠÇþXK>+ò‡YÒ§«uÕ³ÍÕ×E¯?Ìj¸œÑà^›§’œëù‚f©÷{¡ÆÜŸêe^7¨gÞÎhp¯ÍSY½&Aoâ€†Ì ëÃûe0ÞàŽÆÚdö‡‡óÔ
”«ãn¸¬o íÞ›Â(w]Á,›¹o]CyÇ¥\¤¡×°
ØW4S0FÅý–f‘/úÿ•¡\wr1Vt”Òdìàæ·ú¡eˈ`âhB.«—Ç…¤?Ô“¹RO6“ê8')d$©âLæ“n³÷SÝêBjXQÉi<§ÝQ²ûœ§·4ŒÙcêOÍŸM©Ê
¹?[Õ™í¹ª–byU§&}IUw`Õ)¤˜íÔL\ÜSµŸƒ9]q0=‘¥>#ý]ϪYòñÊ .;e‚rüÐ
BïîˆiÄ÷Y;ñÐÖêýèë¸4‡ã9œlÌátcÏ7æðÕÆ^lÌáåÆ^mÌ¡s4‹…WƒíÏÄñ C¦ê8Öeo}kÈÌN–µ’dà_mÛË0Ô[»×¿ýãÿšœ[F