SimpleTAL-5.2/ 0000775 0001752 0001752 00000000000 12537322745 013230 5 ustar cms103 cms103 0000000 0000000 SimpleTAL-5.2/PKG-INFO 0000664 0001752 0001752 00000000566 12537322745 014334 0 ustar cms103 cms103 0000000 0000000 Metadata-Version: 1.0 Name: SimpleTAL Version: 5.2 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-5.2/setup.py 0000664 0001752 0001752 00000001031 12537066033 014730 0 ustar cms103 cms103 0000000 0000000 #!/usr/bin/env python import sys, os sys.path.insert(0, os.path.join(os.getcwd(),'lib')) from distutils.core import setup import simpletal setup(name="SimpleTAL", version= simpletal.__version__, description="SimpleTAL is a stand alone Python implementation of the TAL, TALES and METAL specifications used in Zope to power HTML and XML templates.", author="Colin Stewart", author_email="colin@owlfish.com", url="http://www.owlfish.com/software/simpleTAL/index.html", packages=[ 'simpletal', ], package_dir = {'': 'lib'}, ) SimpleTAL-5.2/README.txt 0000664 0001752 0001752 00000001632 12537111772 014724 0 ustar cms103 cms103 0000000 0000000 simpleTAL / simpleTALES (Version 5.2) ------------------------------------- This is an implementation of the TAL and TALES specifications for Python 3.2 and higher. Installation ------------ To install SimpleTAL under Unix: (Note that to perform the installation of SimpleTAL you will probably have to have the Python Development package installed.) 1 - Become root 2 - Run "python setup.py install" Under MacOS X: 1 - Run "sudo python setup.py install" 2 - Close the terminal program and re-open it. Notes ----- This code is made freely available under a BSD style license, see LICENSE.txt for more details. The API of SimpleTAL 5.x is very similar to earlier releases, but is not fully backwards compatible. Unit Tests ---------- All unit tests can be run with the "runtests.py" command. Documentation ------------- Documentation on the SimpleTAL API can be found in documentation/html/ SimpleTAL-5.2/tests/ 0000775 0001752 0001752 00000000000 12537322745 014372 5 ustar cms103 cms103 0000000 0000000 SimpleTAL-5.2/tests/TALTests/ 0000775 0001752 0001752 00000000000 12537322745 016035 5 ustar cms103 cms103 0000000 0000000 SimpleTAL-5.2/tests/TALTests/HTMLTests/ 0000775 0001752 0001752 00000000000 12537322745 017624 5 ustar cms103 cms103 0000000 0000000 SimpleTAL-5.2/tests/TALTests/HTMLTests/TALOmitTagTestCases.py 0000664 0001752 0001752 00000006105 12537067560 023725 0 ustar cms103 cms103 0000000 0000000 #!/usr/bin/python """ Copyright (c) 2009 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 io import logging, logging.config from simpletal import simpleTAL, simpleTALES if (os.path.exists ("logging.ini")): logging.config.fileConfig ("logging.ini") else: logging.basicConfig() class TALOmitTagTestCases (unittest.TestCase): def setUp (self): self.context = simpleTALES.Context() self.context.addGlobal ('test', 'testing') self.context.addGlobal ('link', 'www.owlfish.com') def _runTest_ (self, txt, result, errMsg="Error"): template = simpleTAL.compileHTMLTemplate (txt) file = io.StringIO () template.expand (self.context, file) realResult = file.getvalue() self.assertTrue (realResult == result, "%s - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (errMsg, txt, realResult, result, template)) def testOmitTagTrue (self): self._runTest_ ('Hello' ,'Hello' ,"Omit tag, true, failed.") def testOmitTagNoArg (self): self._runTest_ ('Hello' ,'Hello' ,"Omit tag, no arg, failed.") def testOmitTagEmptyArg (self): self._runTest_ ('Hello' ,'Hello' ,"Omit tag, empty arg, failed.") def testOmitTagFalse (self): self._runTest_ ('Hello' ,'Hello' ,"Omit tag, false, failed.") if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/TALTests/HTMLTests/TALRepeatTestCases.py 0000664 0001752 0001752 00000057672 12537122265 023612 0 ustar cms103 cms103 0000000 0000000 #!/usr/bin/python """ Copyright (c) 2009 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 io import logging, logging.config from simpletal import simpleTAL, simpleTALES if (os.path.exists ("logging.ini")): logging.config.fileConfig ("logging.ini") else: logging.basicConfig() class TALRepeatTestCases (unittest.TestCase): def setUp (self): self.context = simpleTALES.Context(allowPythonPath=1) 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 ('emptyList', []) self.context.addGlobal ('bigList', list(range(1,100))) self.context.addGlobal ('iterList', range(1,100)) self.context.addGlobal ('fourList', ["zero", "one", "two", "three"]) self.context.addGlobal ('nested', [{'title': 'Image 1', 'catList': [1,2,3]} ,{'title': 'Image 2', 'catList': [5,2,3], 'selected': simpleTALES.DEFAULTVALUE} ,{'title': 'Image 3', 'catList': [8,9,1]} ]) self.context.addGlobal ('defList', ["Hello", simpleTALES.DEFAULTVALUE, "World"]) def _runTest_ (self, txt, result, errMsg="Error"): template = simpleTAL.compileHTMLTemplate (txt) file = io.StringIO () try: template.expand (self.context, file) except Exception as e: print("Error, template compiled to: " + str (template)) raise e realResult = file.getvalue() self.assertTrue (realResult == result, "%s - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (errMsg, txt, realResult, result, template)) def testInvalidPath (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!' ) def testRepeatVarNumberPython (self): self._runTest_ ("""Index
""" ,'123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899' ,'Python repeat variable number failed.' ) def testRepeatVarIndexPython (self): expectedResult = "" for num in range (0,99): expectedResult += str (num) expectedResult += "" self._runTest_ ("""Index
""" ,expectedResult ,"Python repeat variable index failed." ) def testRepeatVarEvenOddPython (self): self._runTest_ ("""- OddEven
""" ,'zero - Even
one - Odd
two - Even
three - Odd
' ,'Python Repeat variables odd and even failed.' ) def testRepeatVarStartEndPython (self): self._runTest_ ("""StartEnd
""" ,'Startzero
one
two
threeEnd
' ,'Python Repeat variables start and end failed.' ) def testRepeatVarLengthPython (self): self._runTest_ ("""Len: lengthEntry:
""" ,'Len: 4Entry: zero
Entry: one
Entry: two
Entry: three
' ,'Python Repeat variable length failed.' ) def testRepeatVarLowerLetterPython (self): self._runTest_ ("""a,b,c,etc:
""" ,'a: zero
b: one
c: two
d: three
' ,'Python Repeat variable letter failed.' ) def testRepeatVarLowerLetterLargePython (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
' ,'Python Repeat variable letter failed on a large list.' ) def testRepeatVarUpperLetterPython (self): self._runTest_ ("""A,B,C,etc:
""" ,'A: zero
B: one
C: two
D: three
' ,'Python Repeat variable Letter failed.' ) def testRepeatVarLowerRomanPython (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
' ,'Python Repeat variable roman failed.' ) def testRepeatVarUpperRomanPython (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 testRepeatVarUpperRomanIterPython (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.' ) if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/TALTests/HTMLTests/TALIteratorRepeatTestCases.py 0000664 0001752 0001752 00000014766 12537067562 025331 0 ustar cms103 cms103 0000000 0000000 #!/usr/bin/python """ Copyright (c) 2009 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 io 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 = io.StringIO () try: template.expand (self.context, file) except Exception as e: print("Error, template compiled to: " + str (template)) raise e realResult = file.getvalue() self.assertTrue (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.") def testLengthAct (self): self._runTest_ ('Hello
', "%s
%s
" % (str (sys.maxsize), str (sys.maxsize)), "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-5.2/tests/TALTests/HTMLTests/TALContentTestCases.py 0000664 0001752 0001752 00000010062 12537067565 023775 0 ustar cms103 cms103 0000000 0000000 #!/usr/bin/python """ Copyright (c) 2009 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 io 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 = io.StringIO () template.expand (self.context, file) realResult = file.getvalue() self.assertTrue (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-5.2/tests/TALTests/HTMLTests/TALReplaceTestCases.py 0000664 0001752 0001752 00000007256 12537067556 023751 0 ustar cms103 cms103 0000000 0000000 #!/usr/bin/python """ Copyright (c) 2009 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 io import logging, logging.config from simpletal import simpleTAL, simpleTALES if (os.path.exists ("logging.ini")): logging.config.fileConfig ("logging.ini") else: logging.basicConfig() class TALReplaceTestCases (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 = io.StringIO () template.expand (self.context, file) realResult = file.getvalue() self.assertTrue (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 remove tag.') def testContentDefault (self): self._runTest_ ('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-5.2/tests/TALTests/HTMLTests/TALConditionTestCases.py 0000664 0001752 0001752 00000006200 12537067566 024311 0 ustar cms103 cms103 0000000 0000000 #!/usr/bin/python """ Copyright (c) 2009 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 io import logging, logging.config from simpletal import simpleTAL, simpleTALES if (os.path.exists ("logging.ini")): logging.config.fileConfig ("logging.ini") else: logging.basicConfig() class TALConditionTestCases (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 = io.StringIO () template.expand (self.context, file) realResult = file.getvalue() self.assertTrue (realResult == result, "%s - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (errMsg, txt, realResult, result, template)) def testConditionDefault (self): self._runTest_ ('Hello', "Hello", "Condition 'default' did not evaluate to true") def testConditionExists (self): self._runTest_ ('Hello' , 'Hello', 'Condition for something that exists evaluated false') def testConditionNothing (self): self._runTest_ ('Hello' , '', 'Condition nothing evaluated to true') def testConditionMissing (self): self._runTest_ ('Hello' , '', 'Condition for something that does not exist evaluated to true') if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/TALTests/HTMLTests/TALAttributesTestCases.py 0000664 0001752 0001752 00000016145 12537072144 024506 0 ustar cms103 cms103 0000000 0000000 #!/usr/bin/python """ Copyright (c) 2009 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 io import logging, logging.config from simpletal import simpleTAL, simpleTALES if (os.path.exists ("logging.ini")): logging.config.fileConfig ("logging.ini") else: logging.basicConfig() class TALAttributesTestCases (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?""") self.context.addGlobal ('number', 5) self.context.addGlobal ('uniQuote', 'Does "this" work?') self.context.addGlobal ('anotherdefault', {'inhere': simpleTALES.DEFAULTVALUE}) def _runTest_ (self, txt, result, errMsg="Error"): template = simpleTAL.compileHTMLTemplate (txt) file = io.StringIO () template.expand (self.context, file) realResult = file.getvalue() self.assertTrue (realResult == result, "%s - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (errMsg, txt, realResult, result, template)) def testAddingAnAttribute (self): self._runTest_ ('Hello' ,'Hello' ,"Addition of attribute 'link' failed.") def testRemovingAnAttribute (self): self._runTest_ ('Hello' ,'Hello' ,"Removal of attribute 'href' failed.") def testDefaultAttribute (self): self._runTest_ ('Hello' ,'Hello' ,"Defaulting of attribute 'href' failed.") def testAnotherDefaultAttribute (self): self._runTest_ ('Hello' ,'Hello' ,"Defaulting of attribute 'href' failed.") def testMultipleAttributes (self): self._runTest_ ('Hello' ,'Hello' ,"Setting multiple attributes at once failed.") def testMultipleAttributesSpace (self): self._runTest_ ('Hello' ,'Hello' ,"Setting multiple attributes at once, with spaces between semi-colons, failed.") def testMultipleAttributesEscaped (self): self._runTest_ ('Hello' ,'Hello' ,"Setting multiple attributes at once, with spaces between semi-colons, failed.") def testAttributeEscaping (self): self._runTest_ ('Hello' ,"""Hello""" ,"Escaping of new attributes failed.") def testNumberAttributeEscaping (self): self._runTest_ ('Hello' ,"""Hello""" ,"Escaping of new attributes failed.") def testNumberAttributeEscaping (self): self._runTest_ ('Hello' ,"""Hello""" ,"Escaping of new attributes failed.") def testOriginalAttributes (self): self._runTest_ ('Hello' ,""""Testing"""" ,"Accessing existing attributes failed.") def testMultipleOriginalAttributes (self): self._runTest_ ('Hello' ,"""Value One""" ,"Accessing multiple existing attributes failed.") def testAmpersandEscapeInAttributes (self): self._runTest_ ('Hello' ,"""&Testing&""" ,"Accessing existing attributes failed.") def testPreviouslyEscapedAmpersandInAttributes (self): self._runTest_ ('Hello' ,"""Hello""" ,"Setting attribute to previously escaped value failed.") #~ def testAttributeCase (self): #~ self._runTest_ ('Hello' #~ ,"""Hello""" #~ ,"HTML Attributes not treated as case insensitive.") if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/TALTests/HTMLTests/TALForbiddenEndTagTestCases.py 0000664 0001752 0001752 00000017532 12537067563 025351 0 ustar cms103 cms103 0000000 0000000 #!/usr/bin/python """ Copyright (c) 2009 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 io 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 = io.StringIO () template.expand (self.context, file) realResult = file.getvalue() self.assertTrue (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_ ('Somethings cost £3
Two
' expectedOutput = 'Somethings cost £3
1
' templateFile.write (txt.encode ('utf-8')) templateFile.seek (0) # Wrap the file in a reader, and bring it back in. reader = codecs.lookup ("utf-8").streamreader(templateFile) template = simpleTAL.compileHTMLTemplate (reader) # Now expand the template into a destination file that is binary outputFile = tempfile.TemporaryFile (mode="w+b") template.expand (self.context,outputFile) # Read it back in and compare with what we expected outputFile.seek(0) outputValue = outputFile.read ().decode ('utf-8') self.assertTrue (outputValue == expectedOutput, "passed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (txt, outputValue, expectedOutput, template)) def testCompileTemplateText (self): """ Test creating an HTML template directly from a file that was text opened. Write output to a text file, letting the caller do the encoding. """ # Create a temporary file manually try: fileHandle, fileName = tempfile.mkstemp () with open (fileName, mode='t+w', encoding = "utf-8") as templateFile: # Write out the HTML in UTF-8 txt = 'Somethings cost £3
Two
' expectedOutput = 'Somethings cost £3
1
' templateFile.write (txt) templateFile.seek (0) template = simpleTAL.compileHTMLTemplate (templateFile) finally: # Delete the temporary file we created os.remove (fileName) try: fileHandle, fileName = tempfile.mkstemp () with open (fileName, mode="t+w", encoding = "utf-8") as outputFile: # Now expand the template into a destination file that is binary template.expand (self.context,outputFile) # Read it back in and compare with what we expected outputFile.seek(0) outputValue = outputFile.read () finally: # Delete the temporary file we created os.remove (fileName) self.assertTrue (outputValue == expectedOutput, "passed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (txt, outputValue, expectedOutput, template)) if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/TALTests/HTMLTests/TALNameSpaceTests.py 0000664 0001752 0001752 00000011753 12537067560 023426 0 ustar cms103 cms103 0000000 0000000 #!/usr/bin/python """ Copyright (c) 2009 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 io import logging, logging.config from simpletal import simpleTAL, simpleTALES if (os.path.exists ("logging.ini")): logging.config.fileConfig ("logging.ini") else: logging.basicConfig() class TALNameSpaceTests (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 = io.StringIO () template.expand (self.context, file) realResult = file.getvalue() self.assertTrue (realResult == result, "%s - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (errMsg, txt, realResult, result, template)) def _runErrTest_ (self, txt, result, errMsg="Error"): try: template = simpleTAL.compileHTMLTemplate (txt) except simpleTAL.TemplateParseException as e: realResult = str (e) self.assertTrue (realResult == result, "%s - \npassed in: %s \ngot back exception %s \nexpected exception %s\n" % (errMsg, txt, realResult, result)) return self.fail ("No exception thrown!") # Test that rebinding the namespaces works def testSingleBindNoCommands (self): self._runTest_ ('Hello' ,'Hello' ,'Binding of namespace failed.') def testSingleBind (self): self._runTest_ ('Hello' ,'Hello' ,'Binding of namespace failed.') def testSingleNestedBind (self): self._runTest_ ('Hello
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
Hello.
World
Hello.
World
Hello.
World
Hello.
World
Boo
", "Boo
") def testUnbalancedCloseTag (self): try: template = simpleTAL.compileHTMLTemplate ("Hello World
") file = io.StringIO () template.expand (self.context, file) realResult = file.getvalue() self.fail ("No exception raised during parsing of unbalanced tag.") except simpleTAL.TemplateParseException as 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-5.2/tests/TALTests/XMLTests/ 0000775 0001752 0001752 00000000000 12537322745 017520 5 ustar cms103 cms103 0000000 0000000 SimpleTAL-5.2/tests/TALTests/XMLTests/TALSingletonTests.py 0000664 0001752 0001752 00000025015 12537067550 023423 0 ustar cms103 cms103 0000000 0000000 #!/usr/bin/python """ Copyright (c) 2009 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 io import logging, logging.config import xml.sax, xml.sax.handler from hashlib import md5 from simpletal import simpleTAL, simpleTALES if (os.path.exists ("logging.ini")): logging.config.fileConfig ("logging.ini") else: logging.basicConfig() class stringHasher: def __init__ (self, encoding = 'utf-8'): self.encoding = encoding self.hasher = md5() def update (self, avalue): if (isinstance (avalue, str)): self.hasher.update(avalue.encode ('utf-8')) else: self.hasher.update (avalue) def digest (self): return self.hasher.digest() def hexdigest (self): return self.hasher.hexdigest() class XMLChecksumHandler (xml.sax.handler.ContentHandler, xml.sax.handler.DTDHandler, xml.sax.handler.ErrorHandler): def __init__ (self, parser): xml.sax.handler.ContentHandler.__init__ (self) self.ourParser = parser def startDocument (self): self.digest = stringHasher() 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 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 getDigest (self): return self.digest.hexdigest() CHECKSUMPARSER = xml.sax.make_parser() CHECKSUMHANDLER = XMLChecksumHandler(CHECKSUMPARSER) CHECKSUMPARSER.setContentHandler (CHECKSUMHANDLER) CHECKSUMPARSER.setDTDHandler (CHECKSUMHANDLER) CHECKSUMPARSER.setErrorHandler (CHECKSUMHANDLER) def getXMLChecksum (doc): CHECKSUMPARSER.parse (io.StringIO (doc)) return CHECKSUMHANDLER.getDigest() class TALSingletonTests (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 _runBasicTest_ (self, text, result, errMsg = "Error"): """ Runs a basic test - i.e. does full string compare rather than checksum. """ template = simpleTAL.compileXMLTemplate (text) file = io.StringIO () template.expand (self.context, file, outputEncoding="iso-8859-1") realResult = file.getvalue().encode ('iso-8859-1') self.assertTrue (result == realResult, "%s - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (errMsg, text, realResult, result, template)) def _runTest_ (self, txt, result, errMsg="Error"): template = simpleTAL.compileXMLTemplate (txt) file = io.StringIO () template.expand (self.context, file, outputEncoding="iso-8859-1") realResult = file.getvalue() try: expectedChecksum = getXMLChecksum (result) except Exception as e: self.fail ("Exception (%s) thrown parsing XML expected result: %s" % (str (e), result)) try: realChecksum = getXMLChecksum (realResult) except Exception as e: self.fail ("Exception (%s) thrown parsing XML actual result: %s\nPage Template: %s" % (str (e), realResult, str (template))) self.assertTrue (expectedChecksum == realChecksum, "%s - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (errMsg, txt, realResult, result, template)) def _runMacroTest_ (self, macros, page, result, errMsg="Error"): macroTemplate = simpleTAL.compileXMLTemplate (macros) pageTemplate = simpleTAL.compileXMLTemplate (page) self.context.addGlobal ("site", macroTemplate) self.context.addGlobal ("here", pageTemplate) file = io.StringIO () pageTemplate.expand (self.context, file) realResult = file.getvalue() try: expectedChecksum = getXMLChecksum (result) except Exception as e: self.fail ("Exception (%s) thrown parsing XML expected result: %s" % (str (e), result)) try: realChecksum = getXMLChecksum (realResult) except Exception as e: self.fail ("Exception (%s) thrown parsing XML actual result: %s\nPage Template: %s\nMacro Template: %s" % (str (e), realResult, str (pageTemplate), str (macroTemplate))) self.assertTrue (expectedChecksum == realChecksum, "%s - \npassed in macro: %s \n and page: %s\ngot back %s \nexpected %s\n\nPage Template: %s" % (errMsg, macros,page, realResult, result, pageTemplate)) def testBasicPassThrough (self): self._runBasicTest_ ("""Hello
Hello
Hello
Hello
""" ,"""METAL with define-slot on singleton failed.""") def testDefineMacro (self): self._runMacroTest_ ("""Hello
Hello
' ,'\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-5.2/tests/TALTests/XMLTests/TALContentTestCases.py 0000664 0001752 0001752 00000010661 12537067553 023673 0 ustar cms103 cms103 0000000 0000000 #!/usr/bin/python """ Copyright (c) 2009 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 io 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
' ,'\nOriginal
' ,'\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
' ,'\nSomethings cost £3
Two
' expectedOutput = '\nSomethings cost £3
1
'.encode ('utf-8') templateFile.write (txt.encode ('utf-8')) templateFile.seek (0) template = simpleTAL.compileXMLTemplate (templateFile) finally: # Delete the temporary file we created os.remove (fileName) try: fileHandle, fileName = tempfile.mkstemp () with open (fileName, mode="b+w") as outputFile: # Now expand the template into a destination file that is binary template.expand (self.context,outputFile) # Read it back in and compare with what we expected outputFile.seek(0) outputValue = outputFile.read () finally: # Delete the temporary file we created os.remove (fileName) self.assertTrue (outputValue == expectedOutput, "passed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (txt, outputValue, expectedOutput, template)) def testCompileTemplateText (self): """ Test creating an XML template directly from a file that was text opened. Write output to a text file, letting the caller do the encoding. """ # Create a temporary file manually try: fileHandle, fileName = tempfile.mkstemp () with open (fileName, mode='t+w', encoding = "utf-8") as templateFile: # Write out the XML in UTF-8 txt = '\nSomethings cost £3
Two
' expectedOutput = '\nSomethings cost £3
1
' templateFile.write (txt) templateFile.seek (0) template = simpleTAL.compileXMLTemplate (templateFile) finally: # Delete the temporary file we created os.remove (fileName) try: fileHandle, fileName = tempfile.mkstemp () with open (fileName, mode="t+w", encoding = "utf-8") as outputFile: # Now expand the template into a destination file that is binary template.expand (self.context,outputFile) # Read it back in and compare with what we expected outputFile.seek(0) outputValue = outputFile.read () finally: # Delete the temporary file we created os.remove (fileName) self.assertTrue (outputValue == expectedOutput, "passed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (txt, outputValue, expectedOutput, template)) if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/TALTests/XMLTests/TALNameSpaceTests.py 0000664 0001752 0001752 00000015400 12537067466 023320 0 ustar cms103 cms103 0000000 0000000 #!/usr/bin/python """ Copyright (c) 2009 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 io import logging, logging.config from simpletal import simpleTAL, simpleTALES if (os.path.exists ("logging.ini")): logging.config.fileConfig ("logging.ini") else: logging.basicConfig() class TALNameSpaceTests (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) file = io.StringIO () template.expand (self.context, file, outputEncoding="iso-8859-1") realResult = file.getvalue() self.assertTrue (realResult == result, "%s - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (errMsg, txt, realResult, result, template)) def _runErrTest_ (self, txt, result, errMsg="Error"): try: template = simpleTAL.compileXMLTemplate (txt) except simpleTAL.TemplateParseException as e: realResult = str (e) self.assertTrue (realResult == result, "%s - \npassed in: %s \ngot back exception %s \nexpected exception %s\n" % (errMsg, txt, realResult, result)) return self.fail ("No exception thrown!") # Test that rebinding the namespaces works def testSingleBindNoCommands (self): self._runTest_ ('Hello' ,'\nHello' ,'Binding of namespace failed.') def testSingleBind (self): self._runTest_ ('Hello' ,'\nHello' ,'Binding of namespace failed.') def testSingleNestedBind (self): self._runTest_ ('Hello
default contentdefault content' ,'\nHello
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
' , '\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
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 = io.StringIO () template.expand (self.context, fh, docType="""""", outputEncoding="iso-8859-1") realResult = fh.getvalue() expectedResult = """\n\nTest
""" self.assertTrue (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 = io.StringIO () template.expand (self.context, fh, docType="""""", suppressXMLDeclaration=1) realResult = fh.getvalue() expectedResult = """\nTest
""" self.assertTrue (realResult == expectedResult, "Doctype failed - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (txt, realResult, expectedResult, str(template))) def testNBSPparsing (self): txt = """\n\nTest Space
""".encode ("iso-8859-1") template = simpleTAL.compileXMLTemplate (txt) fh = io.BytesIO () template.expand (self.context, fh) realResult = fh.getvalue() if not use_lexical_handler: expectedResult = """\nTest\xa0Space
""".encode ("utf-8") else: expectedResult = """\n\nTest\xa0Space
""".encode ("utf-8") self.assertTrue (realResult == expectedResult, "NBSP expansion failed - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (txt, realResult, expectedResult, template)) def testXMLDeclarationSuppressionWithNoDocType (self): txt = """\nTest
""" template = simpleTAL.compileXMLTemplate (txt) fh = io.StringIO () template.expand (self.context, fh, suppressXMLDeclaration=1) realResult = fh.getvalue() expectedResult = """Test
""" self.assertTrue (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-5.2/tests/TALTests/XMLTests/TALAttributeTestCases.py 0000664 0001752 0001752 00000020730 12537067344 024220 0 ustar cms103 cms103 0000000 0000000 #!/usr/bin/python # -*- coding: utf-8 -*- """ Copyright (c) 2009 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 io import logging, logging.config from simpletal import simpleTAL, simpleTALES import xml.sax, xml.sax.handler from hashlib import md5 if (os.path.exists ("logging.ini")): logging.config.fileConfig ("logging.ini") else: logging.basicConfig() class stringHasher: def __init__ (self, encoding = 'utf-8'): self.encoding = encoding self.hasher = md5() def update (self, avalue): if (isinstance (avalue, str)): self.hasher.update(avalue.encode ('utf-8')) else: self.hasher.update (avalue) def digest (self): return self.hasher.digest() def hexdigest (self): return self.hasher.hexdigest() class XMLChecksumHandler (xml.sax.handler.ContentHandler, xml.sax.handler.DTDHandler, xml.sax.handler.ErrorHandler): def __init__ (self, parser): xml.sax.handler.ContentHandler.__init__ (self) self.ourParser = parser def startDocument (self): self.digest = stringHasher() 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.encode ('utf-8')) def processingInstruction (self, target, data): self.digest.update (target) 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 getDigest (self): return self.digest.hexdigest() CHECKSUMPARSER = xml.sax.make_parser() CHECKSUMHANDLER = XMLChecksumHandler(CHECKSUMPARSER) CHECKSUMPARSER.setContentHandler (CHECKSUMHANDLER) CHECKSUMPARSER.setDTDHandler (CHECKSUMHANDLER) CHECKSUMPARSER.setErrorHandler (CHECKSUMHANDLER) def getXMLChecksum (doc): CHECKSUMPARSER.parse (io.StringIO (doc)) return CHECKSUMHANDLER.getDigest() class TALAttributesTestCases (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?""") self.context.addGlobal ('number', '5') self.context.addGlobal ('uniQuote', 'Does "this" work?') def _runTest_ (self, txt, result, errMsg="Error"): template = simpleTAL.compileXMLTemplate (txt) file = io.StringIO () template.expand (self.context, file) realResult = file.getvalue() try: expectedChecksum = getXMLChecksum (result) except Exception as e: self.fail ("Exception (%s) thrown parsing XML expected result: %s" % (str (e), result)) try: realChecksum = getXMLChecksum (realResult) except Exception as e: self.fail ("Exception (%s) thrown parsing XML actual result: %s\nPage Template: %s" % (str (e), realResult, str (template))) self.assertTrue (expectedChecksum == realChecksum, "%s - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (errMsg, txt, realResult, result, template)) def testAddingAnAttribute (self): self._runTest_ ('Hello' ,'\nHello' ,"Addition of attribute 'link' failed.") def testRemovingAnAttribute (self): self._runTest_ ('Hello' ,'\nHello' ,"Removal of attribute 'href' failed.") def testDefaultAttribute (self): self._runTest_ ('Hello' ,'\nHello' ,"Defaulting of attribute 'href' failed.") def testMultipleAttributes (self): self._runTest_ ('Hello' ,'\nHello' ,"Setting multiple attributes at once failed.") def testMultipleAttributesSpace (self): self._runTest_ ('Hello' ,'\nHello' ,"Setting multiple attributes at once, with spaces between semi-colons, failed.") def testMultipleAttributesEscaped (self): self._runTest_ ('Hello' ,'\nHello' ,"Setting multiple attributes at once, with spaces between semi-colons, failed.") def testAttributeEscaping (self): self._runTest_ ('Hello' ,"""\nHello""" ,"Escaping of new attributes failed.") def testNumberAttributeEscaping (self): self._runTest_ ('Hello' ,"""\nHello""" ,"Escaping of new attributes failed.") def testNumberAttributeEscaping2 (self): self._runTest_ ('Hello' ,"""\nHello""" ,"Escaping of new attributes failed.") def testAttributeCase (self): self._runTest_ ('Hello' ,"""\nHello""" ,"Capitalised attributes not carried through template.") if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/PerformanceTests/ 0000775 0001752 0001752 00000000000 12537322745 017656 5 ustar cms103 cms103 0000000 0000000 SimpleTAL-5.2/tests/PerformanceTests/HTMLTests/ 0000775 0001752 0001752 00000000000 12537322745 021445 5 ustar cms103 cms103 0000000 0000000 SimpleTAL-5.2/tests/PerformanceTests/HTMLTests/DeeplyNestedRepeatProfile.py 0000664 0001752 0001752 00000010636 12537066033 027067 0 ustar cms103 cms103 0000000 0000000 """ Copyright (c) 2009 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! Performance test cases. """ from simpletal import simpleTAL, simpleTALES, simpleTALUtils import time, io, sys #import hotshot, hotshot.stats import profile, pstats import gc print("Disabling garbage collection!") gc.disable() performanceTemplate = """Colour
Colour
Important Stuff, worth s |
---|
Table |
things
things
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. |
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-5.2/tests/TALESTests/PythonPathTests.py 0000664 0001752 0001752 00000015576 12537067276 022003 0 ustar cms103 cms103 0000000 0000000 #!/usr/bin/python """ Copyright (c) 2009 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 io 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 = io.StringIO () template.expand (self.context, file) realResult = file.getvalue() self.assertTrue (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-5.2/tests/TALESTests/NotTests.py 0000664 0001752 0001752 00000010705 12537067145 020425 0 ustar cms103 cms103 0000000 0000000 #!/usr/bin/python """ Copyright (c) 2009 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 io 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 = io.StringIO () template.expand (self.context, file) realResult = file.getvalue() self.assertTrue (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-5.2/tests/TALESTests/NoCallTests.py 0000664 0001752 0001752 00000010113 12537067135 021025 0 ustar cms103 cms103 0000000 0000000 #!/usr/bin/python """ Copyright (c) 2009 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 io 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 = io.StringIO () template.expand (self.context, file) realResult = file.getvalue() self.assertTrue (realResult == result, "%s - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (errMsg, txt, realResult, result, template)) self.assertTrue (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-5.2/tests/TALESTests/ExistsTests.py 0000664 0001752 0001752 00000010106 12537067122 021132 0 ustar cms103 cms103 0000000 0000000 #!/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 io 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 = io.StringIO () template.expand (self.context, file) realResult = file.getvalue() self.assertTrue (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-5.2/tests/TALUtilsTests/ 0000775 0001752 0001752 00000000000 12537322745 017056 5 ustar cms103 cms103 0000000 0000000 SimpleTAL-5.2/tests/TALUtilsTests/MacroExpansionTestCases.py 0000664 0001752 0001752 00000007005 12537067077 024203 0 ustar cms103 cms103 0000000 0000000 #!/usr/bin/python """ Copyright (c) 2009 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 io import logging, logging.config from simpletal import simpleTALUtils, simpleTALES, simpleTAL macroTemplate = simpleTAL.compileHTMLTemplate (""" World is White """) #print "Macro is: %s" % str (macroTemplate) class MacroExpansionTestCases (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 ('mac', macroTemplate) self.context.addGlobal ('two', ["one", "two"]) self.context.addGlobal ('three', [1,"Two",3]) self.context.addGlobal ('weblog', weblog) def _runTest_ (self, template, txt, result, errMsg="Error"): realResult = simpleTALUtils.ExpandMacros (self.context, template) self.assertTrue (realResult == result, "%s - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (errMsg, txt, realResult, result, template)) def testMacroExpansionSlots (self): txt = '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.assertTrue (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 as 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 = io.StringIO () template.expand (self.context, outputFile) expectedResult = """Testing the cache...
""" self.assertTrue (outputFile.getvalue() == expectedResult ,"Error: template did not expand to expected result. Expected: %s got: %s" % (expectedResult, outputFile.getvalue())) self.assertTrue (self.cache.misses == 2, "Cache miss not recorded!") # Get the cached template template = self.cache.getTemplate (name) outputFile = io.StringIO () template.expand (self.context, outputFile) expectedResult = """Testing the cache...
""" self.assertTrue (outputFile.getvalue() == expectedResult ,"Error: template did not expand to expected result. Expected: %s got: %s" % (expectedResult, outputFile.getvalue())) self.assertTrue (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 as e: # Pass! pass def testXMLTemplateCache (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, 'wt', encoding = 'iso-8859-1') tf.write (XMLTemplate1) tf.close() # Get the template template = self.cache.getTemplate (name) outputFile = io.StringIO () template.expand (self.context, outputFile, outputEncoding="iso-8859-1") expectedResult = """\nTesting the cache...
""" self.assertTrue (outputFile.getvalue() == expectedResult ,"Error: template did not expand to expected result. Expected: %s got: %s" % (expectedResult, outputFile.getvalue())) self.assertTrue (self.cache.misses == 2, "Cache miss not recorded!") # Get the cached template template = self.cache.getTemplate (name) outputFile = io.StringIO () template.expand (self.context, outputFile, outputEncoding="iso-8859-1") expectedResult = """\nTesting the cache...
""" self.assertTrue (outputFile.getvalue() == expectedResult ,"Error: template did not expand to expected result. Expected: %s got: %s" % (expectedResult, outputFile.getvalue())) self.assertTrue (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 = io.StringIO () template.expand (self.context, outputFile, outputEncoding="iso-8859-1") expectedResult = """\nTesting the cache...
""" self.assertTrue (outputFile.getvalue() == expectedResult ,"Error: template did not expand to expected result. Expected: %s got: %s" % (expectedResult, outputFile.getvalue())) self.assertTrue (self.cache.misses == 2, "Cache miss not recorded!") # Get the cached template template = self.cache.getXMLTemplate (name) outputFile = io.StringIO () template.expand (self.context, outputFile, outputEncoding="iso-8859-1") expectedResult = """\nTesting the cache...
""" self.assertTrue (outputFile.getvalue() == expectedResult ,"Error: template did not expand to expected result. Expected: %s got: %s" % (expectedResult, outputFile.getvalue())) self.assertTrue (self.cache.hits == 2, "Cache hit not recorded!") if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/METALTests/ 0000775 0001752 0001752 00000000000 12537322745 016257 5 ustar cms103 cms103 0000000 0000000 SimpleTAL-5.2/tests/METALTests/HTMLTests/ 0000775 0001752 0001752 00000000000 12537322745 020046 5 ustar cms103 cms103 0000000 0000000 SimpleTAL-5.2/tests/METALTests/HTMLTests/METALNameSpaceTests.py 0000664 0001752 0001752 00000010645 12537066740 024070 0 ustar cms103 cms103 0000000 0000000 #!/usr/bin/python """ Copyright (c) 2009 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 io 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.compileHTMLTemplate (macros) #print "Macro template: " + str (macroTemplate) pageTemplate = simpleTAL.compileHTMLTemplate (page) self.context.addGlobal ("site", macroTemplate) self.context.addGlobal ("here", pageTemplate) file = io.StringIO () pageTemplate.expand (self.context, file) realResult = file.getvalue() self.assertTrue (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_ ('Wibble
' ,'\ntesting
\n' ,"TAL Command on a macro failed.") if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/METALTests/HTMLTests/DefineSlotsTests.py 0000664 0001752 0001752 00000015345 12537066732 023673 0 ustar cms103 cms103 0000000 0000000 #!/usr/bin/python """ Copyright (c) 2009 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 io 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 = io.StringIO () pageTemplate.expand (self.context, file) realResult = file.getvalue() self.assertTrue (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 as e: self.assertTrue (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: whitetesting
\nWibble
' , result ,"TAL Command on a macro failed.") def testSingletonMacros (self): result = '\n\nWibble
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: whiteText
This macro is brought to you by the colour blue. Now you know.
SimpleTAL-5.2/examples/metal-example/metal-example.py 0000775 0001752 0001752 00000004565 12537066033 022716 0 ustar cms103 cms103 0000000 0000000 #!/usr/bin/python """ Example TAL program Copyright (c) 2009 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! An example of how to use METAL. Module Dependencies: simpleTAL, simpleTALES """ from simpletal import simpleTAL, simpleTALES import sys # Creat the context that is used by the template context = simpleTALES.Context() # Add a string to the context under the variable title context.addGlobal ("title", "Simple METAL Example") # Compile the macro pages templateFile = open ("macro.html", 'rt', encoding = 'utf-8') macros = simpleTAL.compileHTMLTemplate (templateFile) templateFile.close() # Add the macros page to the Context context.addGlobal ("sitemacros", macros) # Now compile the page which will use the macros templateFile = open ("page.html", 'rt', encoding = 'utf-8') page = simpleTAL.compileHTMLTemplate (templateFile) templateFile.close() # Expand the page using this context page.expand (context, sys.stdout) SimpleTAL-5.2/LICENSE.txt 0000664 0001752 0001752 00000002735 12537111757 015061 0 ustar cms103 cms103 0000000 0000000 SimpleTAL 5.2 -------------------------------------------------------------------- Copyright (c) 2015 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. SimpleTAL-5.2/lib/ 0000775 0001752 0001752 00000000000 12537322745 013776 5 ustar cms103 cms103 0000000 0000000 SimpleTAL-5.2/lib/simpletal/ 0000775 0001752 0001752 00000000000 12537322745 015770 5 ustar cms103 cms103 0000000 0000000 SimpleTAL-5.2/lib/simpletal/simpleTALUtils.py 0000664 0001752 0001752 00000021020 12537066033 021203 0 ustar cms103 cms103 0000000 0000000 """ simpleTALUtils Copyright (c) 2009 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! This module is holds utilities that make using SimpleTAL easier. Initially this is just the HTMLStructureCleaner class, used to clean up HTML that can then be used as 'structure' content. Module Dependencies: None """ import io, os, stat, threading, sys, codecs, cgi, re, types, logging from . import __version__, simpleTAL # This is used to check for already escaped attributes. ESCAPED_TEXT_REGEX=re.compile (r"\&\S+?;") class TemplateCache: """ A TemplateCache is a multi-thread safe object that caches compiled templates. This cache only works with file based templates, the ctime of the file is checked on each hit, if the file has changed the template is re-compiled. """ def __init__ (self): self.templateCache = {} self.cacheLock = threading.Lock() self.hits = 0 self.misses = 0 def getTemplate (self, name, inputEncoding='utf-8'): """ Name should be the path of a template file. If the path ends in 'xml' it is treated as an XML Template, otherwise it's treated as an HTML Template. If the template file has changed since the last cache it will be re-compiled. inputEncoding is only used for HTML templates, and should be the encoding that the template is stored in. """ if (name in self.templateCache): template, oldctime = self.templateCache [name] ctime = os.stat (name)[stat.ST_MTIME] if (oldctime == ctime): # Cache hit! self.hits += 1 return template # Cache miss, let's cache this template return self._cacheTemplate_ (name, inputEncoding) def getXMLTemplate (self, name): """ Name should be the path of an XML template file. """ if (name in self.templateCache): template, oldctime = self.templateCache [name] ctime = os.stat (name)[stat.ST_MTIME] if (oldctime == ctime): # Cache hit! self.hits += 1 return template # Cache miss, let's cache this template return self._cacheTemplate_ (name, None, xmlTemplate=1) def _cacheTemplate_ (self, name, inputEncoding, xmlTemplate=0): self.cacheLock.acquire () try: tempFile = open (name, 'rb') if (xmlTemplate): # We know it is XML template = simpleTAL.compileXMLTemplate (tempFile) else: # We have to guess... firstline = tempFile.readline() tempFile.seek(0) if (name [-3:] == "xml") or (firstline.strip ()[:5] == b'" return result class MacroExpansionInterpreter (simpleTAL.TemplateInterpreter): def __init__ (self): simpleTAL.TemplateInterpreter.__init__ (self) # Override the standard interpreter way of doing things. self.macroStateStack = [] self.commandHandler [simpleTAL.TAL_DEFINE] = self.cmdNoOp self.commandHandler [simpleTAL.TAL_CONDITION] = self.cmdNoOp self.commandHandler [simpleTAL.TAL_REPEAT] = self.cmdNoOp self.commandHandler [simpleTAL.TAL_CONTENT] = self.cmdNoOp self.commandHandler [simpleTAL.TAL_ATTRIBUTES] = self.cmdNoOp self.commandHandler [simpleTAL.TAL_OMITTAG] = self.cmdNoOp self.commandHandler [simpleTAL.TAL_START_SCOPE] = self.cmdStartScope self.commandHandler [simpleTAL.TAL_OUTPUT] = self.cmdOutput self.commandHandler [simpleTAL.TAL_STARTTAG] = self.cmdOutputStartTag self.commandHandler [simpleTAL.TAL_ENDTAG_ENDSCOPE] = self.cmdEndTagEndScope self.commandHandler [simpleTAL.METAL_USE_MACRO] = self.cmdUseMacro self.commandHandler [simpleTAL.METAL_DEFINE_SLOT] = self.cmdDefineSlot self.commandHandler [simpleTAL.TAL_NOOP] = self.cmdNoOp self.inMacro = None self.macroArg = None # Original cmdOutput # Original cmdEndTagEndScope def popProgram (self): self.inMacro = self.macroStateStack.pop() simpleTAL.TemplateInterpreter.popProgram (self) def pushProgram (self): self.macroStateStack.append (self.inMacro) simpleTAL.TemplateInterpreter.pushProgram (self) def cmdOutputStartTag (self, command, args): newAtts = [] for att, value in list(self.originalAttributes.items()): if (self.macroArg is not None and att == "metal:define-macro"): newAtts.append (("metal:use-macro",self.macroArg)) elif (self.inMacro and att=="metal:define-slot"): newAtts.append (("metal:fill-slot", value)) else: newAtts.append ((att, value)) self.macroArg = None self.currentAttributes = newAtts simpleTAL.TemplateInterpreter.cmdOutputStartTag (self, command, args) def cmdUseMacro (self, command, args): simpleTAL.TemplateInterpreter.cmdUseMacro (self, command, args) if (self.tagContent is not None): # We have a macro, add the args to the in-macro list self.inMacro = 1 self.macroArg = args[0] def cmdEndTagEndScope (self, command, args): # Args: tagName, omitFlag if (self.tagContent is not None): contentType, resultVal = self.tagContent if (contentType): if (isinstance (resultVal, simpleTAL.Template)): # We have another template in the context, evaluate it! # Save our state! self.pushProgram() resultVal.expandInline (self.context, self.file, self) # Restore state self.popProgram() # End of the macro expansion (if any) so clear the parameters self.slotParameters = {} # End of the macro self.inMacro = 0 else: if (isinstance (resultVal, str)): self.file.write (resultVal) elif (isinstance (resultVal, bytes)): self.file.write (str (resultVal, 'ascii')) else: self.file.write (str (str (resultVal), 'ascii')) else: if (isinstance (resultVal, str)): self.file.write (cgi.escape (resultVal)) elif (isinstance (resultVal, bytes)): self.file.write (cgi.escape (str (resultVal, 'ascii'))) else: self.file.write (cgi.escape (str (str (resultVal), 'ascii'))) if (self.outputTag and not args[1]): self.file.write ('' + args[0] + '>') if (self.movePCBack is not None): self.programCounter = self.movePCBack return if (self.localVarsDefined): self.context.popLocals() self.movePCForward,self.movePCBack,self.outputTag,self.originalAttributes,self.currentAttributes,self.repeatVariable,self.tagContent,self.localVarsDefined = self.scopeStack.pop() self.programCounter += 1 def ExpandMacros (context, template, outputEncoding="utf-8"): out = io.StringIO() interp = MacroExpansionInterpreter() interp.initialise (context, out) template.expand (context, out, outputEncoding=outputEncoding, interpreter=interp) return out.getvalue() SimpleTAL-5.2/lib/simpletal/simpleTALES.py 0000664 0001752 0001752 00000045506 12537117414 020431 0 ustar cms103 cms103 0000000 0000000 """ simpleTALES Implementation Copyright (c) 2009 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! The classes in this module implement the TALES specification, used by the simpleTAL module. Module Dependencies: logging """ import types, sys import logging import simpletal __version__ = simpletal.__version__ DEFAULTVALUE = "This represents a Default value." class PathNotFoundException (Exception): pass class ContextContentException (Exception): """ This is raised when invalid content has been placed into the Context object. For example using non-ascii characters instead of Unicode strings. """ pass PATHNOTFOUNDEXCEPTION = PathNotFoundException() class ContextVariable (BaseException): def __init__ (self, value = None): self.ourValue = value def value (self, currentPath=None): if (hasattr (self.ourValue, "__call__")): return self.ourValue() return self.ourValue def rawValue (self): return self.ourValue def __str__ (self): return repr (self.ourValue) class RepeatVariable (ContextVariable): """ To be written""" def __init__ (self, sequence): ContextVariable.__init__ (self, 1) self.sequence = sequence self.position = 0 self.map = None def __getattr__(self, name): # to be used from python eval if (self.map is None): self.createMap() return self.map[name] def value (self, currentPath=None): if (self.map is None): self.createMap() return self.map def rawValue (self): return self.value() def getCurrentValue (self): return self.sequence [self.position] def increment (self): self.position += 1 if (self.position == len (self.sequence)): raise IndexError ("Repeat Finished") def createMap (self): self.map = {} self.map ['index'] = self.getIndex self.map ['number'] = self.getNumber self.map ['even'] = self.getEven self.map ['odd'] = self.getOdd self.map ['start'] = self.getStart self.map ['end'] = self.getEnd # TODO: first and last need to be implemented. self.map ['length'] = len (self.sequence) self.map ['letter'] = self.getLowerLetter self.map ['Letter'] = self.getUpperLetter self.map ['roman'] = self.getLowerRoman self.map ['Roman'] = self.getUpperRoman # Repeat implementation goes here def getIndex (self): return self.position def getNumber (self): return self.position + 1 def getEven (self): if ((self.position % 2) != 0): return 0 return 1 def getOdd (self): if ((self.position % 2) == 0): return 0 return 1 def getStart (self): if (self.position == 0): return 1 return 0 def getEnd (self): if (self.position == len (self.sequence) - 1): return 1 return 0 def getLowerLetter (self): result = "" nextCol = self.position if (nextCol == 0): return 'a' while (nextCol > 0): nextCol, thisCol = divmod (nextCol, 26) result = chr (ord ('a') + thisCol) + result return result def getUpperLetter (self): return self.getLowerLetter().upper() def getLowerRoman (self): romanNumeralList = (('m', 1000) ,('cm', 900) ,('d', 500) ,('cd', 400) ,('c', 100) ,('xc', 90) ,('l', 50) ,('xl', 40) ,('x', 10) ,('ix', 9) ,('v', 5) ,('iv', 4) ,('i', 1) ) if (self.position > 3999): # Roman numbers only supported up to 4000 return ' ' num = self.position + 1 result = "" for roman, integer in romanNumeralList: while (num >= integer): result += roman num -= integer return result def getUpperRoman (self): return self.getLowerRoman().upper() class IteratorRepeatVariable (RepeatVariable): def __init__ (self, sequence): RepeatVariable.__init__ (self, sequence) self.curValue = None self.iterStatus = 0 def getCurrentValue (self): if (self.iterStatus == 0): self.iterStatus = 1 try: self.curValue = next(self.sequence) except StopIteration as e: self.iterStatus = 2 raise IndexError ("Repeat Finished") return self.curValue def increment (self): # Need this for the repeat variable functions. self.position += 1 try: self.curValue = next(self.sequence) except StopIteration as e: self.iterStatus = 2 raise IndexError ("Repeat Finished") def createMap (self): self.map = {} self.map ['index'] = self.getIndex self.map ['number'] = self.getNumber self.map ['even'] = self.getEven self.map ['odd'] = self.getOdd self.map ['start'] = self.getStart self.map ['end'] = self.getEnd # TODO: first and last need to be implemented. self.map ['length'] = sys.maxsize self.map ['letter'] = self.getLowerLetter self.map ['Letter'] = self.getUpperLetter self.map ['roman'] = self.getLowerRoman self.map ['Roman'] = self.getUpperRoman def getEnd (self): if (self.iterStatus == 2): return 1 return 0 class PathFunctionVariable (ContextVariable): def __init__ (self, func): ContextVariable.__init__ (self, value = func) self.func = func def value (self, currentPath=None): if (currentPath is not None): index, paths = currentPath result = ContextVariable (self.func ('/'.join (paths[index:]))) # Fast track the result raise result class CachedFuncResult (ContextVariable): def value (self, currentPath=None): try: return self.cachedValue except: self.cachedValue = ContextVariable.value (self) return self.cachedValue def clearCache (self): try: del self.cachedValue except: pass class PythonPathFunctions: def __init__ (self, context): self.context = context def path (self, expr): return self.context.evaluatePath (expr) def string (self, expr): return self.context.evaluateString (expr) def exists (self, expr): return self.context.evaluateExists (expr) def nocall (self, expr): return self.context.evaluateNoCall (expr) def test (self, *arguments): if (len (arguments) % 2): # We have an odd number of arguments - which means the last one is a default pairs = arguments[:-1] defaultValue = arguments[-1] else: # No default - so use None pairs = arguments defaultValue = None index = 0 while (index < len (pairs)): test = pairs[index] index += 1 value = pairs[index] index += 1 if (test): return value return defaultValue class Context: def __init__ (self, options=None, allowPythonPath=0): self.allowPythonPath = allowPythonPath self.globals = {} self.locals = {} self.localStack = [] self.repeatStack = [] self.populateDefaultVariables (options) self.log = logging.getLogger ("simpleTALES.Context") self.true = 1 self.false = 0 self.pythonPathFuncs = PythonPathFunctions (self) def addRepeat (self, name, var, initialValue): # Pop the current repeat map onto the stack self.repeatStack.append (self.repeatMap) self.repeatMap = self.repeatMap.copy() self.repeatMap [name] = var # Map this repeatMap into the global space self.addGlobal ('repeat', self.repeatMap) # Add in the locals self.pushLocals() self.setLocal (name, initialValue) def removeRepeat (self, name): # Bring the old repeat map back self.repeatMap = self.repeatStack.pop() # Map this repeatMap into the global space self.addGlobal ('repeat', self.repeatMap) def addGlobal (self, name, value): self.globals[name] = value def pushLocals (self): # Push the current locals onto a stack so that we can safely over-ride them. self.localStack.append (self.locals) self.locals = self.locals.copy() def setLocal (self, name, value): # Override the current local if present with the new one self.locals [name] = value def popLocals (self): self.locals = self.localStack.pop() def evaluate (self, expr, originalAtts = None): # Returns a ContextVariable #self.log.debug ("Evaluating %s" % expr) if (originalAtts is not None): # Call from outside self.globals['attrs'] = originalAtts suppressException = 1 else: suppressException = 0 # Supports path, exists, nocall, not, and string expr = expr.strip () try: if expr.startswith ('path:'): return self.evaluatePath (expr[5:].lstrip ()) elif expr.startswith ('exists:'): return self.evaluateExists (expr[7:].lstrip()) elif expr.startswith ('nocall:'): return self.evaluateNoCall (expr[7:].lstrip()) elif expr.startswith ('not:'): return self.evaluateNot (expr[4:].lstrip()) elif expr.startswith ('string:'): return self.evaluateString (expr[7:].lstrip()) elif expr.startswith ('python:'): return self.evaluatePython (expr[7:].lstrip()) else: # Not specified - so it's a path return self.evaluatePath (expr) except PathNotFoundException as e: if (suppressException): return None raise e def evaluatePython (self, expr): if (not self.allowPythonPath): self.log.warning ("Parameter allowPythonPath is false. NOT Evaluating python expression %s" % expr) return self.false #self.log.debug ("Evaluating python expression %s" % expr) globals={} for name, value in list(self.globals.items()): if (isinstance (value, ContextVariable)): value = value.rawValue() globals [name] = value globals ['path'] = self.pythonPathFuncs.path globals ['string'] = self.pythonPathFuncs.string globals ['exists'] = self.pythonPathFuncs.exists globals ['nocall'] = self.pythonPathFuncs.nocall globals ['test'] = self.pythonPathFuncs.test locals={} for name, value in list(self.locals.items()): if (isinstance (value, ContextVariable)): value = value.rawValue() locals [name] = value try: result = eval(expr, globals, locals) if (isinstance (result, ContextVariable)): return result.value() return result except Exception as e: # An exception occured evaluating the template, return the exception as text self.log.warning ("Exception occurred evaluating python path, exception: " + str (e)) return "Exception: %s" % str (e) def evaluatePath (self, expr): #self.log.debug ("Evaluating path expression %s" % expr) allPaths = expr.split ('|') if (len (allPaths) > 1): for path in allPaths: # Evaluate this path try: return self.evaluate (path.strip ()) except PathNotFoundException as e: # Path didn't exist, try the next one pass # No paths evaluated - raise exception. raise PATHNOTFOUNDEXCEPTION else: # A single path - so let's evaluate it. # This *can* raise PathNotFoundException return self.traversePath (allPaths[0]) def evaluateExists (self, expr): #self.log.debug ("Evaluating %s to see if it exists" % expr) allPaths = expr.split ('|') # The first path is for us # Return true if this first bit evaluates, otherwise test the rest try: result = self.traversePath (allPaths[0], canCall = 0) return self.true except PathNotFoundException as e: # Look at the rest of the paths. pass for path in allPaths[1:]: # Evaluate this path try: pathResult = self.evaluate (path.strip ()) # If this is part of a "exists: path1 | exists: path2" path then we need to look at the actual result. if (pathResult): return self.true except PathNotFoundException as e: pass # If we get this far then there are *no* paths that exist. return self.false def evaluateNoCall (self, expr): #self.log.debug ("Evaluating %s using nocall" % expr) allPaths = expr.split ('|') # The first path is for us try: return self.traversePath (allPaths[0], canCall = 0) except PathNotFoundException as e: # Try the rest of the paths. pass for path in allPaths[1:]: # Evaluate this path try: return self.evaluate (path.strip ()) except PathNotFoundException as e: pass # No path evaluated - raise error raise PATHNOTFOUNDEXCEPTION def evaluateNot (self, expr): #self.log.debug ("Evaluating NOT value of %s" % expr) # Evaluate what I was passed try: pathResult = self.evaluate (expr) except PathNotFoundException as e: # In SimpleTAL the result of "not: no/such/path" should be TRUE not FALSE. return self.true if (pathResult is None): # Value was Nothing return self.true if (pathResult == DEFAULTVALUE): return self.false try: resultLen = len (pathResult) if (resultLen > 0): return self.false else: return self.true except: # Not a sequence object. pass if (not pathResult): return self.true # Everything else is true, so we return false! return self.false def evaluateString (self, expr): #self.log.debug ("Evaluating String %s" % expr) result = "" skipCount = 0 for position in range (0,len (expr)): if (skipCount > 0): skipCount -= 1 else: if (expr[position] == '$'): try: if (expr[position + 1] == '$'): # Escaped $ sign result += '$' skipCount = 1 elif (expr[position + 1] == '{'): # Looking for a path! endPos = expr.find ('}', position + 1) if (endPos > 0): path = expr[position + 2:endPos] # Evaluate the path - missing paths raise exceptions as normal. try: pathResult = self.evaluate (path) except PathNotFoundException as e: # This part of the path didn't evaluate to anything - leave blank pathResult = '' if (pathResult is not None): if (isinstance (pathResult, str)): result += pathResult else: # THIS IS NOT A BUG! # Use Unicode in Context if you aren't using Ascii! result += str (pathResult) skipCount = endPos - position else: # It's a variable endPos = expr.find (' ', position + 1) if (endPos == -1): endPos = len (expr) path = expr [position + 1:endPos] # Evaluate the variable - missing paths raise exceptions as normal. try: pathResult = self.traversePath (path) except PathNotFoundException as e: # This part of the path didn't evaluate to anything - leave blank pathResult = '' if (pathResult is not None): if (isinstance (pathResult, str)): result += pathResult else: # THIS IS NOT A BUG! # Use Unicode in Context if you aren't using Ascii! result += str (pathResult) skipCount = endPos - position - 1 except IndexError as e: # Trailing $ sign - just suppress it self.log.warning ("Trailing $ detected") pass else: result += expr[position] return result def traversePath (self, expr, canCall=1): # canCall only applies to the *final* path destination, not points down the path. # Check for and correct for trailing/leading quotes if (expr.startswith ('"') or expr.startswith ("'")): if (expr.endswith ('"') or expr.endswith ("'")): expr = expr [1:-1] else: expr = expr [1:] elif (expr.endswith ('"') or expr.endswith ("'")): expr = expr [0:-1] pathList = expr.split ('/') path = pathList[0] if path.startswith ('?'): path = path[1:] if path in self.locals: path = self.locals[path] if (isinstance (path, ContextVariable)): path = path.value() elif (hasattr (path, "__call__")):path = path() elif path in self.globals: path = self.globals[path] if (isinstance (path, ContextVariable)): path = path.value() elif (hasattr (path, "__call__")):path = path() #self.log.debug ("Dereferenced to %s" % path) if path in self.locals: val = self.locals[path] elif path in self.globals: val = self.globals[path] else: # If we can't find it then raise an exception raise PATHNOTFOUNDEXCEPTION index = 1 for path in pathList[1:]: #self.log.debug ("Looking for path element %s" % path) if path.startswith ('?'): path = path[1:] if path in self.locals: path = self.locals[path] if (isinstance (path, ContextVariable)): path = path.value() elif (hasattr (path, "__call__")):path = path() elif path in self.globals: path = self.globals[path] if (isinstance (path, ContextVariable)): path = path.value() elif (hasattr (path, "__call__")):path = path() #self.log.debug ("Dereferenced to %s" % path) try: if (isinstance (val, ContextVariable)): temp = val.value((index,pathList)) elif (hasattr (val, "__call__")):temp = val() else: temp = val except ContextVariable as e: # Fast path for those functions that return values return e.value() if (hasattr (temp, path)): val = getattr (temp, path) else: try: try: val = temp[path] except TypeError: val = temp[int(path)] except: #self.log.debug ("Not found.") raise PATHNOTFOUNDEXCEPTION index = index + 1 #self.log.debug ("Found value %s" % str (val)) if (canCall): try: if (isinstance (val, ContextVariable)): result = val.value((index,pathList)) elif (hasattr (val, "__call__")):result = val() else: result = val except ContextVariable as e: # Fast path for those functions that return values return e.value() else: if (isinstance (val, ContextVariable)): result = val.realValue else: result = val return result def __str__ (self): return "Globals: " + str (self.globals) + "Locals: " + str (self.locals) def populateDefaultVariables (self, options): vars = {} self.repeatMap = {} vars['nothing'] = None vars['default'] = DEFAULTVALUE vars['options'] = options # To start with there are no repeats vars['repeat'] = self.repeatMap vars['attrs'] = None # Add all of these to the global context for name in list(vars.keys()): self.addGlobal (name,vars[name]) # Add also under CONTEXTS self.addGlobal ('CONTEXTS', vars) SimpleTAL-5.2/lib/simpletal/simpleTAL.py 0000664 0001752 0001752 00000157444 12537111702 020200 0 ustar cms103 cms103 0000000 0000000 """ simpleTAL Interpreter Copyright (c) 2009 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! The classes in this module implement the TAL language, expanding both XML and HTML templates. Module Dependencies: logging, simpleTALES, simpleTALTemplates """ import logging import xml.sax, xml.sax.saxutils,html, io, re, types, codecs import simpletal, copy, sys from . import FixedHTMLParser, sgmlentitynames __version__ = simpletal.__version__ try: # Is PyXML's LexicalHandler available? from xml.sax.saxlib import LexicalHandler use_lexical_handler = 1 except ImportError: use_lexical_handler = 0 class LexicalHandler: pass try: # Is PyXML's DOM2SAX available? import xml.dom.ext.Dom2Sax use_dom2sax = 1 except ImportError: use_dom2sax = 0 # Check Python version. If 3.3 or later, all SGML entities will be expanded in the HTML Parser if sys.version_info[0] > 3 or (sys.version_info[0] == 3 and sys.version_info[1] > 3): HTML_ENTITIES_PRE_EXPANDED = True else: HTML_ENTITIES_PRE_EXPANDED = False from . import simpleTALES # Name-space URIs METAL_NAME_URI="http://xml.zope.org/namespaces/metal" TAL_NAME_URI="http://xml.zope.org/namespaces/tal" # All commands are of the form (opcode, args, commandList) # The numbers are the opcodes, and also the order of priority # Argument: [(isLocalFlag (Y/n), variableName, variablePath),...] TAL_DEFINE = 1 # Argument: expression, endTagSymbol TAL_CONDITION = 2 # Argument: (varname, expression, endTagSymbol) TAL_REPEAT = 3 # Argument: (replaceFlag, type, expression) TAL_CONTENT = 4 # Not used in byte code, only ordering. TAL_REPLACE = 5 # Argument: [(attributeName, expression)] TAL_ATTRIBUTES = 6 # Argument: expression TAL_OMITTAG = 7 # Argument: (originalAttributeList, currentAttributeList) TAL_START_SCOPE = 8 # Argument: String to output TAL_OUTPUT = 9 # Argument: None TAL_STARTTAG = 10 # Argument: Tag, omitTagFlag TAL_ENDTAG_ENDSCOPE = 11 # Argument: None TAL_NOOP = 13 # METAL Starts here # Argument: expression, slotParams, endTagSymbol METAL_USE_MACRO = 14 # Argument: macroName, endTagSymbol METAL_DEFINE_SLOT=15 # Only used for parsing METAL_FILL_SLOT=16 METAL_DEFINE_MACRO=17 METAL_NAME_REGEX = re.compile ("[a-zA-Z_][a-zA-Z0-9_]*") SINGLETON_XML_REGEX = re.compile ('^<[^\s/>]+(?:\s*[^=>]+="[^">]+")*\s*/>') SINGLETON_BYTES_XML_REGEX = re.compile (b'^<[^\s/>]+(?:\s*[^=>]+="[^">]+")*\s*/>') ENTITY_REF_REGEX = re.compile (r'(?:&[a-zA-Z][\-\.a-zA-Z0-9]*[^\-\.a-zA-Z0-9])|(?:[xX]?[a-eA-E0-9]*[^0-9a-eA-E])') # The list of elements in HTML that can not have end tags - done as a dictionary for fast # lookup. HTML_FORBIDDEN_ENDTAG = {'AREA': 1, 'BASE': 1, 'BASEFONT': 1, 'BR': 1, 'COL': 1 ,'FRAME': 1, 'HR': 1, 'IMG': 1, 'INPUT': 1, 'ISINDEX': 1 ,'LINK': 1, 'META': 1, 'PARAM': 1} # List of element:attribute pairs that can use minimized form in HTML HTML_BOOLEAN_ATTS = {'AREA:NOHREF': 1, 'IMG:ISMAP': 1, 'OBJECT:DECLARE': 1 , 'INPUT:CHECKED': 1, 'INPUT:DISABLED': 1, 'INPUT:READONLY': 1, 'INPUT:ISMAP': 1 , 'SELECT:MULTIPLE': 1, 'SELECT:DISABLED': 1 , 'OPTGROUP:DISABLED': 1 , 'OPTION:SELECTED': 1, 'OPTION:DISABLED': 1 , 'TEXTAREA:DISABLED': 1, 'TEXTAREA:READONLY': 1 , 'BUTTON:DISABLED': 1, 'SCRIPT:DEFER': 1} class TemplateInterpreter: def __init__ (self): self.programStack = [] self.commandList = None self.symbolTable = None self.slotParameters = {} self.commandHandler = {} self.commandHandler [TAL_DEFINE] = self.cmdDefine self.commandHandler [TAL_CONDITION] = self.cmdCondition self.commandHandler [TAL_REPEAT] = self.cmdRepeat self.commandHandler [TAL_CONTENT] = self.cmdContent self.commandHandler [TAL_ATTRIBUTES] = self.cmdAttributes self.commandHandler [TAL_OMITTAG] = self.cmdOmitTag self.commandHandler [TAL_START_SCOPE] = self.cmdStartScope self.commandHandler [TAL_OUTPUT] = self.cmdOutput self.commandHandler [TAL_STARTTAG] = self.cmdOutputStartTag self.commandHandler [TAL_ENDTAG_ENDSCOPE] = self.cmdEndTagEndScope self.commandHandler [METAL_USE_MACRO] = self.cmdUseMacro self.commandHandler [METAL_DEFINE_SLOT] = self.cmdDefineSlot self.commandHandler [TAL_NOOP] = self.cmdNoOp def tagAsText (self, tagObj, singletonFlag=0): """ This returns a tag as text. """ tag,atts = tagObj result = ["<"] result.append (tag) for attName, attValue in atts: result.append (' ') result.append (attName) result.append ('="') result.append (html.escape (attValue, quote=1)) result.append ('"') if (singletonFlag): result.append (" />") else: result.append (">") return "".join (result) def initialise (self, context, outputFile): self.context = context self.file = outputFile def cleanState (self): self.scopeStack = [] self.programCounter = 0 self.movePCForward = None self.movePCBack = None self.outputTag = 1 self.originalAttributes = {} self.currentAttributes = [] # Used in repeat only. self.repeatAttributesCopy = [] self.currentSlots = {} self.repeatVariable = None self.tagContent = None # tagState flag as to whether there are any local variables to pop self.localVarsDefined = 0 # Pass in the parameters self.currentSlots = self.slotParameters def popProgram (self): vars, self.commandList, self.symbolTable = self.programStack.pop() self.programCounter,self.scopeStack,self.slotParameters,self.currentSlots, self.movePCForward,self.movePCBack,self.outputTag,self.originalAttributes,self.currentAttributes,self.repeatVariable,self.repeatAttributesCopy,self.tagContent,self.localVarsDefined = vars def pushProgram (self): vars = (self.programCounter ,self.scopeStack ,self.slotParameters ,self.currentSlots ,self.movePCForward ,self.movePCBack ,self.outputTag ,self.originalAttributes ,self.currentAttributes ,self.repeatVariable ,self.repeatAttributesCopy ,self.tagContent ,self.localVarsDefined) self.programStack.append ((vars,self.commandList, self.symbolTable)) def execute (self, template): self.cleanState() self.commandList, self.programCounter, programLength, self.symbolTable = template.getProgram() cmndList = self.commandList while (self.programCounter < programLength): cmnd = cmndList [self.programCounter] #print "PC: %s - Executing command: %s" % (str (self.programCounter), str (cmnd)) self.commandHandler[cmnd[0]] (cmnd[0], cmnd[1]) def cmdDefine (self, command, args): """ args: [(isLocalFlag (Y/n), variableName, variablePath),...] Define variables in either the local or global context """ foundLocals = 0 for isLocal, varName, varPath in args: result = self.context.evaluate (varPath, self.originalAttributes) if (isLocal): if (not foundLocals): foundLocals = 1 self.context.pushLocals () self.context.setLocal (varName, result) else: self.context.addGlobal (varName, result) self.localVarsDefined = foundLocals self.programCounter += 1 def cmdCondition (self, command, args): """ args: expression, endTagSymbol Conditionally continues with execution of all content contained by it. """ result = self.context.evaluate (args[0], self.originalAttributes) #~ if (result is None or (not result)): conditionFalse = 0 if (result is None): conditionFalse = 1 else: if (not result): conditionFalse = 1 try: temp = len (result) if (temp == 0): conditionFalse = 1 except: # Result is not a sequence. pass if (conditionFalse): # Nothing to output - evaluated to false. self.outputTag = 0 self.tagContent = None self.programCounter = self.symbolTable[args[1]] return self.programCounter += 1 def cmdRepeat (self, command, args): """ args: (varName, expression, endTagSymbol) Repeats anything in the cmndList """ if (self.repeatVariable is not None): # We are already part way through a repeat # Restore any attributes that might have been changed. if (self.currentAttributes != self.repeatAttributesCopy): self.currentAttributes = copy.copy (self.repeatAttributesCopy) self.outputTag = 1 self.tagContent = None self.movePCForward = None try: self.repeatVariable.increment() self.context.setLocal (args[0], self.repeatVariable.getCurrentValue()) self.programCounter += 1 return except IndexError as e: # We have finished the repeat self.repeatVariable = None self.context.removeRepeat (args[0]) # The locals were pushed in context.addRepeat self.context.popLocals() self.movePCBack = None # Suppress the final close tag and content self.tagContent = None self.outputTag = 0 self.programCounter = self.symbolTable [args[2]] # Restore the state of repeatAttributesCopy in case we are nested. self.repeatAttributesCopy = self.scopeStack.pop() return # The first time through this command result = self.context.evaluate (args[1], self.originalAttributes) if (result is not None and result == simpleTALES.DEFAULTVALUE): # Leave everything un-touched. self.programCounter += 1 return try: # We have three options, either the result is a natural sequence, an iterator, or something that can produce an iterator. isSequence = len (result) if (isSequence): # Only setup if we have a sequence with length self.repeatVariable = simpleTALES.RepeatVariable (result) else: # Delete the tags and their contents self.outputTag = 0 self.programCounter = self.symbolTable [args[2]] return except: # Not a natural sequence, can it produce an iterator? if (hasattr (result, "__iter__") and hasattr (result.__iter__, "__call__")): # We can get an iterator! self.repeatVariable = simpleTALES.IteratorRepeatVariable (result.__iter__()) elif (hasattr (result, "__next__") and hasattr (result.__next__, "__call__")): # Treat as an iterator self.repeatVariable = simpleTALES.IteratorRepeatVariable (result) else: # Just a plain object, let's not loop # Delete the tags and their contents self.outputTag = 0 self.programCounter = self.symbolTable [args[2]] return try: curValue = self.repeatVariable.getCurrentValue() except IndexError as e: # The iterator ran out of values before we started - treat as an empty list self.outputTag = 0 self.repeatVariable = None self.programCounter = self.symbolTable [args[2]] return # We really do want to repeat - so lets do it self.movePCBack = self.programCounter self.context.addRepeat (args[0], self.repeatVariable, curValue) # We keep the old state of the repeatAttributesCopy for nested loops self.scopeStack.append (self.repeatAttributesCopy) # Keep a copy of the current attributes for this tag self.repeatAttributesCopy = copy.copy (self.currentAttributes) self.programCounter += 1 def cmdContent (self, command, args): """ args: (replaceFlag, structureFlag, expression, endTagSymbol) Expands content """ result = self.context.evaluate (args[2], self.originalAttributes) if (result is None): if (args[0]): # Only output tags if this is a content not a replace self.outputTag = 0 # Output none of our content or the existing content, but potentially the tags self.movePCForward = self.symbolTable [args[3]] self.programCounter += 1 return elif (not result == simpleTALES.DEFAULTVALUE): # We have content, so let's suppress the natural content and output this! if (args[0]): self.outputTag = 0 self.tagContent = (args[1], result) self.movePCForward = self.symbolTable [args[3]] self.programCounter += 1 return else: # Default, let's just run through as normal self.programCounter += 1 return def cmdAttributes (self, command, args): """ args: [(attributeName, expression)] Add, leave, or remove attributes from the start tag """ attsToRemove = {} newAtts = [] for attName, attExpr in args: resultVal = self.context.evaluate (attExpr, self.originalAttributes) if (resultVal is None): # Remove this attribute from the current attributes attsToRemove [attName]=1 elif (not resultVal == simpleTALES.DEFAULTVALUE): # We have a value - let's use it! attsToRemove [attName]=1 if (isinstance (resultVal, str)): escapedAttVal = resultVal elif (isinstance (resultVal, bytes)): # THIS IS NOT A BUG! # Use Unicode in the Context object if you are not using Ascii escapedAttVal = str (resultVal, 'ascii') else: # THIS IS NOT A BUG! # Use Unicode in the Context object if you are not using Ascii escapedAttVal = str (resultVal) newAtts.append ((attName, escapedAttVal)) # Copy over the old attributes for oldAttName, oldAttValue in self.currentAttributes: if (not oldAttName in attsToRemove): newAtts.append ((oldAttName, oldAttValue)) self.currentAttributes = newAtts # Evaluate all other commands self.programCounter += 1 def cmdOmitTag (self, command, args): """ args: expression Conditionally turn off tag output """ result = self.context.evaluate (args, self.originalAttributes) if (result is not None and result): # Turn tag output off self.outputTag = 0 self.programCounter += 1 def cmdOutputStartTag (self, command, args): # Args: tagName tagName, singletonTag = args if (self.outputTag): if (self.tagContent is None and singletonTag): self.file.write (self.tagAsText ((tagName, self.currentAttributes), 1)) else: self.file.write (self.tagAsText ((tagName, self.currentAttributes))) if (self.movePCForward is not None): self.programCounter = self.movePCForward return self.programCounter += 1 return def cmdEndTagEndScope (self, command, args): # Args: tagName, omitFlag, singletonTag if (self.tagContent is not None): contentType, resultVal = self.tagContent if (contentType): if (isinstance (resultVal, Template)): # We have another template in the context, evaluate it! # Save our state! self.pushProgram() resultVal.expandInline (self.context, self.file, self) # Restore state self.popProgram() # End of the macro expansion (if any) so clear the parameters self.slotParameters = {} else: if (isinstance (resultVal, str)): self.file.write (resultVal) elif (isinstance (resultVal, bytes)): # THIS IS NOT A BUG! # Use Unicode in the Context object if you are not using Ascii self.file.write (str (resultVal, 'ascii')) else: # THIS IS NOT A BUG! # Use Unicode in the Context object if you are not using Ascii self.file.write (str (resultVal)) else: if (isinstance (resultVal, str)): self.file.write (html.escape (resultVal, quote=False)) elif (isinstance (resultVal, bytes)): # THIS IS NOT A BUG! # Use Unicode in the Context object if you are not using Ascii self.file.write (html.escape (str (resultVal, 'ascii'), quote=False)) else: # THIS IS NOT A BUG! # Use Unicode in the Context object if you are not using Ascii self.file.write (html.escape (str (resultVal), quote=False)) if (self.outputTag and not args[1]): # Do NOT output end tag if a singleton with no content if not (args[2] and self.tagContent is None): self.file.write ('' + args[0] + '>') if (self.movePCBack is not None): self.programCounter = self.movePCBack return if (self.localVarsDefined): self.context.popLocals() self.movePCForward,self.movePCBack,self.outputTag,self.originalAttributes,self.currentAttributes,self.repeatVariable,self.tagContent,self.localVarsDefined = self.scopeStack.pop() self.programCounter += 1 def cmdOutput (self, command, args): self.file.write (args) self.programCounter += 1 def cmdStartScope (self, command, args): """ args: (originalAttributes, currentAttributes) Pushes the current state onto the stack, and sets up the new state """ self.scopeStack.append ((self.movePCForward ,self.movePCBack ,self.outputTag ,self.originalAttributes ,self.currentAttributes ,self.repeatVariable ,self.tagContent ,self.localVarsDefined)) self.movePCForward = None self.movePCBack = None self.outputTag = 1 self.originalAttributes = args[0] self.currentAttributes = args[1] self.repeatVariable = None self.tagContent = None self.localVarsDefined = 0 self.programCounter += 1 def cmdNoOp (self, command, args): self.programCounter += 1 def cmdUseMacro (self, command, args): """ args: (macroExpression, slotParams, endTagSymbol) Evaluates the expression, if it resolves to a SubTemplate it then places the slotParams into currentSlots and then jumps to the end tag """ value = self.context.evaluate (args[0], self.originalAttributes) if (value is None): # Don't output anything self.outputTag = 0 # Output none of our content or the existing content self.movePCForward = self.symbolTable [args[2]] self.programCounter += 1 return if (not value == simpleTALES.DEFAULTVALUE and isinstance (value, SubTemplate)): # We have a macro, so let's use it self.outputTag = 0 self.slotParameters = args[1] self.tagContent = (1, value) # NOTE: WE JUMP STRAIGHT TO THE END TAG, NO OTHER TAL/METAL COMMANDS ARE EVALUATED. self.programCounter = self.symbolTable [args[2]] return else: # Default, let's just run through as normal self.programCounter += 1 return def cmdDefineSlot (self, command, args): """ args: (slotName, endTagSymbol) If the slotName is filled then that is used, otherwise the original conent is used. """ if (args[0] in self.currentSlots): # This slot is filled, so replace us with that content self.outputTag = 0 self.tagContent = (1, self.currentSlots [args[0]]) # Output none of our content or the existing content # NOTE: NO FURTHER TAL/METAL COMMANDS ARE EVALUATED self.programCounter = self.symbolTable [args[1]] return # Slot isn't filled, so just use our own content self.programCounter += 1 return class HTMLTemplateInterpreter (TemplateInterpreter): def __init__ (self, minimizeBooleanAtts = 0): TemplateInterpreter.__init__ (self) self.minimizeBooleanAtts = minimizeBooleanAtts if (minimizeBooleanAtts): # Override the tagAsText method for this instance self.tagAsText = self.tagAsTextMinimizeAtts def tagAsTextMinimizeAtts (self, tagObj, singletonFlag=0): """ This returns a tag as text. """ tag,atts = tagObj result = ["<"] result.append (tag) upperTag = tag.upper() for attName, attValue in atts: if ('%s:%s' % (upperTag, attName.upper()) in HTML_BOOLEAN_ATTS): # We should output a minimised boolean value result.append (' ') result.append (attName) else: result.append (' ') result.append (attName) result.append ('="') result.append (html.escape (attValue, quote=1)) result.append ('"') if (singletonFlag): result.append (" />") else: result.append (">") return "".join (result) class Template: def __init__ (self, commands, macros, symbols, doctype = None): self.commandList = commands self.macros = macros self.symbolTable = symbols self.doctype = doctype self.log = logging.getLogger("simpleTAL.Template") # Setup the macros for macro in list(self.macros.values()): macro.setParentTemplate (self) # Setup the slots for cmnd, arg in self.commandList: if (cmnd == METAL_USE_MACRO): # Set the parent of each slot slotMap = arg[1] for slot in list(slotMap.values()): slot.setParentTemplate (self) def expand (self, context, outputFile, outputEncoding=None, interpreter=None): """ This method will write to the outputFile, using the encoding specified, the expanded version of this template. The context passed in is used to resolve all expressions with the template. """ # This method must wrap outputFile if required by the encoding, and write out # any template pre-amble (DTD, Encoding, etc) self.expandInline (context, outputFile, interpreter) def expandInline (self, context, outputFile, interpreter=None): """ Internally used when expanding a template that is part of a context.""" if (interpreter is None): ourInterpreter = TemplateInterpreter() ourInterpreter.initialise (context, outputFile) else: ourInterpreter = interpreter try: ourInterpreter.execute (self) except UnicodeError as unierror: self.log.error ("UnicodeError caused by placing a non-Unicode string in the Context object.") raise simpleTALES.ContextContentException ("Found non-unicode string in Context!") def getProgram (self): """ Returns a tuple of (commandList, startPoint, endPoint, symbolTable) """ return (self.commandList, 0, len (self.commandList), self.symbolTable) def __str__ (self): result = "Commands:\n" index = 0 for cmd in self.commandList: if (cmd[0] != METAL_USE_MACRO): result = result + "\n[%s] %s" % (str (index), str (cmd)) else: result = result + "\n[%s] %s, (%s{" % (str (index), str (cmd[0]), str (cmd[1][0])) for slot in list(cmd[1][1].keys()): result = result + "%s: %s" % (slot, str (cmd[1][1][slot])) result = result + "}, %s)" % str (cmd[1][2]) index += 1 result = result + "\n\nSymbols:\n" for symbol in list(self.symbolTable.keys()): result = result + "Symbol: " + str (symbol) + " points to: " + str (self.symbolTable[symbol]) + ", which is command: " + str (self.commandList[self.symbolTable[symbol]]) + "\n" result = result + "\n\nMacros:\n" for macro in list(self.macros.keys()): result = result + "Macro: " + str (macro) + " value of: " + str (self.macros[macro]) return result class SubTemplate (Template): """ A SubTemplate is part of another template, and is used for the METAL implementation. The two uses for this class are: 1 - metal:define-macro results in a SubTemplate that is the macro 2 - metal:fill-slot results in a SubTemplate that is a parameter to metal:use-macro """ def __init__ (self, startRange, endRangeSymbol): """ The parentTemplate is the template for which we are a sub-template. The startRange and endRange are indexes into the parent templates command list, and defines the range of commands that we can execute """ Template.__init__ (self, [], {}, {}) self.startRange = startRange self.endRangeSymbol = endRangeSymbol def setParentTemplate (self, parentTemplate): self.parentTemplate = parentTemplate self.commandList = parentTemplate.commandList self.symbolTable = parentTemplate.symbolTable def getProgram (self): """ Returns a tuple of (commandList, startPoint, endPoint, symbolTable) """ return (self.commandList, self.startRange, self.symbolTable[self.endRangeSymbol]+1, self.symbolTable) def __str__ (self): endRange = self.symbolTable [self.endRangeSymbol] result = "SubTemplate from %s to %s\n" % (str (self.startRange), str (endRange)) return result class HTMLTemplate (Template): """A specialised form of a template that knows how to output HTML """ def __init__ (self, commands, macros, symbols, doctype = None, minimizeBooleanAtts = 0): self.minimizeBooleanAtts = minimizeBooleanAtts Template.__init__ (self, commands, macros, symbols, doctype = None) def expand (self, context, outputFile, outputEncoding = "utf-8", interpreter=None): """ This method will write to the outputFile the expanded version of this template. The context passed in is used to resolve all expressions with the template. """ if (isinstance (outputFile, io.TextIOBase) or isinstance (outputFile, codecs.StreamWriter)): self.log.debug ("Text based output file detected") else: self.log.debug ("Bytes based output file detected - wrapping in codec for %s", outputEncoding) outputFile = codecs.lookup (outputEncoding).streamwriter (outputFile, 'xmlcharrefreplace') self.expandInline (context, outputFile, interpreter) def expandInline (self, context, outputFile, interpreter=None): """ Ensure we use the HTMLTemplateInterpreter""" if (interpreter is None): ourInterpreter = HTMLTemplateInterpreter(minimizeBooleanAtts = self.minimizeBooleanAtts) ourInterpreter.initialise (context, outputFile) else: ourInterpreter = interpreter Template.expandInline (self, context, outputFile, ourInterpreter) class XMLTemplate (Template): """A specialised form of a template that knows how to output XML """ def __init__ (self, commands, macros, symbols, doctype = None): Template.__init__ (self, commands, macros, symbols) self.doctype = doctype def expand (self, context, outputFile, outputEncoding = "utf-8", docType=None, suppressXMLDeclaration=False,interpreter=None): """ This method will write to the outputFile, using the encoding attached to the outputFile, the expanded version of this template. The context passed in is used to resolve all expressions with the template. """ if (isinstance (outputFile, io.TextIOBase) or isinstance (outputFile, codecs.StreamWriter)): self.log.debug ("Text based output file detected") else: self.log.debug ("Bytes based output file detected - wrapping in codec for %s", outputEncoding) outputFile = codecs.lookup (outputEncoding).streamwriter (outputFile, 'xmlcharrefreplace') if (not suppressXMLDeclaration): if (outputEncoding.lower() != "utf-8"): outputFile.write ('\n' % outputEncoding.lower()) else: outputFile.write ('\n') if not docType and self.doctype: docType = self.doctype if docType: outputFile.write (docType) outputFile.write ('\n') self.expandInline (context, outputFile, interpreter) class TemplateCompiler: def __init__ (self): """ Initialise a template compiler. """ self.commandList = [] self.tagStack = [] self.symbolLocationTable = {} self.macroMap = {} self.endTagSymbol = 1 self.commandHandler = {} self.commandHandler [TAL_DEFINE] = self.compileCmdDefine self.commandHandler [TAL_CONDITION] = self.compileCmdCondition self.commandHandler [TAL_REPEAT] = self.compileCmdRepeat self.commandHandler [TAL_CONTENT] = self.compileCmdContent self.commandHandler [TAL_REPLACE] = self.compileCmdReplace self.commandHandler [TAL_ATTRIBUTES] = self.compileCmdAttributes self.commandHandler [TAL_OMITTAG] = self.compileCmdOmitTag # Metal commands self.commandHandler [METAL_USE_MACRO] = self.compileMetalUseMacro self.commandHandler [METAL_DEFINE_SLOT] = self.compileMetalDefineSlot self.commandHandler [METAL_FILL_SLOT] = self.compileMetalFillSlot self.commandHandler [METAL_DEFINE_MACRO] = self.compileMetalDefineMacro # Default namespaces self.setTALPrefix ('tal') self.tal_namespace_prefix_stack = [] self.metal_namespace_prefix_stack = [] self.tal_namespace_prefix_stack.append ('tal') self.setMETALPrefix ('metal') self.metal_namespace_prefix_stack.append ('metal') self.log = logging.getLogger ("simpleTAL.TemplateCompiler") def setTALPrefix (self, prefix): self.tal_namespace_prefix = prefix self.tal_namespace_omittag = '%s:omit-tag' % self.tal_namespace_prefix self.tal_attribute_map = {} self.tal_attribute_map ['%s:attributes'%prefix] = TAL_ATTRIBUTES self.tal_attribute_map ['%s:content'%prefix]= TAL_CONTENT self.tal_attribute_map ['%s:define'%prefix] = TAL_DEFINE self.tal_attribute_map ['%s:replace'%prefix] = TAL_REPLACE self.tal_attribute_map ['%s:omit-tag'%prefix] = TAL_OMITTAG self.tal_attribute_map ['%s:condition'%prefix] = TAL_CONDITION self.tal_attribute_map ['%s:repeat'%prefix] = TAL_REPEAT def setMETALPrefix (self, prefix): self.metal_namespace_prefix = prefix self.metal_attribute_map = {} self.metal_attribute_map ['%s:define-macro'%prefix] = METAL_DEFINE_MACRO self.metal_attribute_map ['%s:use-macro'%prefix] = METAL_USE_MACRO self.metal_attribute_map ['%s:define-slot'%prefix] = METAL_DEFINE_SLOT self.metal_attribute_map ['%s:fill-slot'%prefix] = METAL_FILL_SLOT def popTALNamespace (self): newPrefix = self.tal_namespace_prefix_stack.pop() self.setTALPrefix (newPrefix) def popMETALNamespace (self): newPrefix = self.metal_namespace_prefix_stack.pop() self.setMETALPrefix (newPrefix) def tagAsText (self, tagObj, singletonFlag=0): """ This returns a tag as text. """ tag,atts = tagObj result = ["<"] result.append (tag) for attName, attValue in atts: result.append (' ') result.append (attName) result.append ('="') result.append (html.escape (attValue, quote=1)) result.append ('"') if (singletonFlag): result.append (" />") else: result.append (">") return "".join (result) def getTemplate (self): template = Template (self.commandList, self.macroMap, self.symbolLocationTable) return template def addCommand (self, command): if (command[0] == TAL_OUTPUT and (len (self.commandList) > 0) and self.commandList[-1][0] == TAL_OUTPUT): # We can combine output commands self.commandList[-1] = (TAL_OUTPUT, self.commandList[-1][1] + command[1]) else: self.commandList.append (command) def addTag (self, tag, tagProperties={}): """ Used to add a tag to the stack. Various properties can be passed in the dictionary as being information required by the tag. Currently supported properties are: 'command' - The (command,args) tuple associated with this command 'originalAtts' - The original attributes that include any metal/tal attributes 'endTagSymbol' - The symbol associated with the end tag for this element 'popFunctionList' - A list of functions to execute when this tag is popped 'singletonTag' - A boolean to indicate that this is a singleton flag """ # Add the tag to the tagStack (list of tuples (tag, properties, useMacroLocation)) self.log.debug ("Adding tag %s to stack" % tag[0]) command = tagProperties.get ('command',None) originalAtts = tagProperties.get ('originalAtts', None) singletonTag = tagProperties.get ('singletonTag', 0) if (command is not None): if (command[0] == METAL_USE_MACRO): self.tagStack.append ((tag, tagProperties, len (self.commandList)+1)) else: self.tagStack.append ((tag, tagProperties, None)) else: self.tagStack.append ((tag, tagProperties, None)) if (command is not None): # All tags that have a TAL attribute on them start with a 'start scope' self.addCommand((TAL_START_SCOPE, (originalAtts, tag[1]))) # Now we add the TAL command self.addCommand(command) else: # It's just a straight output, so create an output command and append it self.addCommand((TAL_OUTPUT, self.tagAsText (tag, singletonTag))) def popTag (self, tag, omitTagFlag=0): """ omitTagFlag is used to control whether the end tag should be included in the output or not. In HTML 4.01 there are several tags which should never have end tags, this flag allows the template compiler to specify that these should not be output. """ while (len (self.tagStack) > 0): oldTag, tagProperties, useMacroLocation = self.tagStack.pop() endTagSymbol = tagProperties.get ('endTagSymbol', None) popCommandList = tagProperties.get ('popFunctionList', []) singletonTag = tagProperties.get ('singletonTag', 0) for func in popCommandList: func() self.log.debug ("Popped tag %s off stack" % oldTag[0]) if (oldTag[0] == tag[0]): # We've found the right tag, now check to see if we have any TAL commands on it if (endTagSymbol is not None): # We have a command (it's a TAL tag) # Note where the end tag symbol should point (i.e. the next command) self.symbolLocationTable [endTagSymbol] = len (self.commandList) # We need a "close scope and tag" command self.addCommand((TAL_ENDTAG_ENDSCOPE, (tag[0], omitTagFlag, singletonTag))) return elif (omitTagFlag == 0 and singletonTag == 0): # We are popping off an un-interesting tag, just add the close as text self.addCommand((TAL_OUTPUT, '' + tag[0] + '>')) return else: # We are suppressing the output of this tag, so just return return else: # We have a different tag, which means something likeDocumentation 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 that returns strings. 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 a string or bytes object containing the template, or a file-like object that returns strings or bytes. The XML template must be a well formed XML document. See below for details of how to use the Template class.
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 to re-compile them unless the underlying template changes. They have one method of interest as part of the external API:
def expand (self, context, outputFile [,outputEncoding='utf-8'] [,docType=None] [,suppressXMLDeclaration=False])
This method will expand the template, using the simpleTALES.Context object provided, and write the output into the given file-like object. If the outputFile is an instance of io.TextIOBase or codecs.StreamWriter then strings are written to the file, otherwise the output is encoded in outputEncoding. XML Templates will output the appropriate XML declaration for the outputEncoding, independently of whether strings or bytes are written out.
The docType and suppressXMLDeclaration arguments only apply 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. The doctype must be passed as a named variable to the expand method.
For example to produce a valid strict XHTML document 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-5.2/documentation/html/index.html 0000664 0001752 0001752 00000002732 12537066033 021041 0 ustar cms103 cms103 0000000 0000000Welcome 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.
Feedback, feature enhancements and bug fixes will all be gladly received!
PubTal Version
SimpleTAL-5.2/documentation/html/notes.html 0000664 0001752 0001752 00000016173 12537066033 021066 0 ustar cms103 cms103 0000000 0000000Notes, known limitations, and differences between SimpleTAL and Zope's ZPT.
Porting SimpleTAL to Python 3 has introduced a number of small changes:
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.
SimpleTAL 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 will:
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 it is important that any XHTML templates are handled as XML rather than HTML, i.e. by calling compileXMLTemplate to compile the template.
HTML templates can be provided as a string or a file like object that generates strings. If loading from a file use open (filename, 'rt', encoding = "character-set") to load the template encoded in a particular character set.
XML templates specify within the document what encoding they use and so can be passed as a string, bytes, or a file like object. When using strings the XML must have been originally in UTF-8. To load from a file use open (filename, 'rb').
When expanding a template SimpleTAL will determine whether to write out strings if the output file is a sub-class of io.TextIOBase or codecs.StreamWriter. Otherwise the file like object will be assumed to require bytes, and the output will be encoded first using 'outputEncoding', which defaults to utf-8.
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.
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 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 the variable "item" will be set to the output of "myDict.items()" - i.e. it will call the Python dictionary method 'items()'.
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-5.2/documentation/html/api-simpleelementtree.html 0000664 0001752 0001752 00000005565 12537066033 024233 0 ustar cms103 cms103 0000000 0000000Documentation on how to use the simpleElementTree Module.
This module provides 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-5.2/documentation/html/tal-guide.html 0000664 0001752 0001752 00000025614 12537066033 021611 0 ustar cms103 cms103 0000000 0000000A 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>
Syntax: [path:]object/?attribute
Description: The "attribute" is evaluated as a local or global variable, and it's value is used as the attribute to lookup on the object. Useful for accessing the contents of a dictionary within a loop:
Example: <div tal:content="myDictionary/loopValue"/>
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-5.2/documentation/html/api.html 0000664 0001752 0001752 00000004017 12537066033 020501 0 ustar cms103 cms103 0000000 0000000Documentation on how to use the SimpleTAL API.
SimpleTAL consists of four different modules: simpleTAL, simpleTALES, and simpleTALUtils. The API for each of these modules is documented separately:
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-5.2/documentation/html/api-simpletales.html 0000664 0001752 0001752 00000007236 12537066033 023027 0 ustar cms103 cms103 0000000 0000000Documentation 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.
Any python modules that you wish to use need to be added to the Context object using addGlobal.
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 text placed into the context, and text returned by callable objects should be strings rather than bytes.
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-5.2/documentation/html/api-simpletalutils.html 0000664 0001752 0001752 00000004756 12537066033 023564 0 ustar cms103 cms103 0000000 0000000Documentation 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 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.
PubTal Version
SimpleTAL-5.2/documentation/templates/ 0000775 0001752 0001752 00000000000 12537322745 020077 5 ustar cms103 cms103 0000000 0000000 SimpleTAL-5.2/documentation/templates/template.html 0000664 0001752 0001752 00000001741 12537066033 022576 0 ustar cms103 cms103 0000000 0000000Subject
Version
SimpleTAL-5.2/documentation/style/ 0000775 0001752 0001752 00000000000 12537322745 017241 5 ustar cms103 cms103 0000000 0000000 SimpleTAL-5.2/documentation/style/site.css 0000664 0001752 0001752 00000002035 12537066033 020712 0 ustar cms103 cms103 0000000 0000000 .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-5.2/documentation/documentation.config 0000664 0001752 0001752 00000000641 12537066033 022135 0 ustar cms103 cms103 0000000 0000000 # 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-5.2/documentation/src/ 0000775 0001752 0001752 00000000000 12537322745 016670 5 ustar cms103 cms103 0000000 0000000 SimpleTAL-5.2/documentation/src/api.txt 0000664 0001752 0001752 00000002653 12537066033 020203 0 ustar cms103 cms103 0000000 0000000 title: SimpleTAL API
subject: Documentation on how to use the SimpleTAL API.
SimpleTAL consists of four 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 - integration with ElementTree allowing XML documents to be parsed and placed directly into the Context instance.
Logging in SimpleTAL
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-5.2/documentation/src/tal-guide.sxw 0000664 0001752 0001752 00000042265 12537066033 021312 0 ustar cms103 cms103 0000000 0000000 PK >19 mimetypeapplication/vnd.sun.xml.writerPK > content.xml]r7}߯^b-,zuXW!R(t˪B
"3>üx_%Kݺ$[XD"8LoIbrŤ"}"އ:O=opC֏D',՝P%;U}|ouԾ
9
:(=
OٍK1,m(