SimpleTAL-5.2/0000775000175200017520000000000012537322745013230 5ustar cms103cms10300000000000000SimpleTAL-5.2/PKG-INFO0000664000175200017520000000056612537322745014334 0ustar cms103cms10300000000000000Metadata-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.py0000664000175200017520000000103112537066033014730 0ustar cms103cms10300000000000000#!/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.txt0000664000175200017520000000163212537111772014724 0ustar cms103cms10300000000000000simpleTAL / 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/0000775000175200017520000000000012537322745014372 5ustar cms103cms10300000000000000SimpleTAL-5.2/tests/TALTests/0000775000175200017520000000000012537322745016035 5ustar cms103cms10300000000000000SimpleTAL-5.2/tests/TALTests/HTMLTests/0000775000175200017520000000000012537322745017624 5ustar cms103cms10300000000000000SimpleTAL-5.2/tests/TALTests/HTMLTests/TALOmitTagTestCases.py0000664000175200017520000000610512537067560023725 0ustar cms103cms10300000000000000#!/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.py0000664000175200017520000005767212537122265023612 0ustar cms103cms10300000000000000#!/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

' ,'Hello

Default Word

World' ,'Using default content in repeat loop failed.') def testNestedRepeat (self): self._runTest_ ('

' ,'

Image 1

123

Image 2

523

Image 3

891

' ,'Nested repeat did not create expected outcome.' ) def testNestedRepeatClasses (self): self._runTest_ ('

' ,'

1
2
3

5
2
3

8
9
1

' ,'Nested repeat with classes did not create expected outcome.' ) def testNestedRepeatScope (self): self._runTest_ ('

' ,'

Image 1

123

Image 2

523

Image 3

891

' ,'Nested repeat did not create expected outcome.' ) def testRepeatVarIndex (self): expectedResult = "" for num in range (0,99): expectedResult += str (num) expectedResult += "" 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.py0000664000175200017520000001476612537067562025331 0ustar cms103cms10300000000000000#!/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.py0000664000175200017520000001006212537067565023775 0ustar cms103cms10300000000000000#!/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.py0000664000175200017520000000725612537067556023751 0ustar cms103cms10300000000000000#!/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.py0000664000175200017520000000620012537067566024311 0ustar cms103cms10300000000000000#!/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.py0000664000175200017520000001614512537072144024506 0ustar cms103cms10300000000000000#!/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.py0000664000175200017520000001753212537067563025351 0ustar cms103cms10300000000000000#!/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_ ('' ,'' ,"HTML Element BASE produced end tag.") def testBaseFontElement (self): self._runTest_ ('' ,'' ,"HTML Element BASEFONT produced end tag.") def testBRElement (self): self._runTest_ ('

' ,'
' ,"HTML Element BR produced end tag.") def testColElement (self): self._runTest_ ('' ,'' ,"HTML Element COL produced end tag.") def testFrameElement (self): self._runTest_ ('' ,'' ,"HTML Element FRAME produced end tag.") def testHRElement (self): self._runTest_ ('
' ,'
' ,"HTML Element HR produced end tag.") def testImgElement (self): self._runTest_ ('' ,'' ,"HTML Element IMG produced end tag.") def testInputElement (self): self._runTest_ ('' ,'' ,"HTML Element INPUT produced end tag.") def testIsIndexElement (self): self._runTest_ ('' ,'' ,"HTML Element ISINDEX produced end tag.") def testLinkElement (self): self._runTest_ ('' ,'' ,"HTML Element LINK produced end tag.") def testMetaElement (self): self._runTest_ ('' ,'' ,"HTML Element META produced end tag.") def testParamElement (self): self._runTest_ ('' ,'' ,"HTML Element PARAM produced end tag.") # Same tests again, but with no end tag in the templates def testAreaElementNoClose (self): self._runTest_ ('' ,'' ,"HTML Element AREA produced end tag.") def testBaseElementNoClose (self): self._runTest_ ('' ,'' ,"HTML Element BASE produced end tag.") def testBaseFontElementNoClose (self): self._runTest_ ('' ,'' ,"HTML Element BASEFONT produced end tag.") def testBRElementNoClose (self): self._runTest_ ('
' ,'
' ,"HTML Element BR produced end tag.") def testColElementNoClose (self): self._runTest_ ('' ,'' ,"HTML Element COL produced end tag.") def testFrameElementNoClose (self): self._runTest_ ('' ,'' ,"HTML Element FRAME produced end tag.") def testHRElementNoClose (self): self._runTest_ ('
' ,'
' ,"HTML Element HR produced end tag.") def testImgElementNoClose (self): self._runTest_ ('' ,'' ,"HTML Element IMG produced end tag.") def testInputElementNoClose (self): self._runTest_ ('' ,'' ,"HTML Element INPUT produced end tag.") def testIsIndexElementNoClose (self): self._runTest_ ('' ,'' ,"HTML Element ISINDEX produced end tag.") def testLinkElementNoClose (self): self._runTest_ ('' ,'' ,"HTML Element LINK produced end tag.") def testMetaElementNoClose (self): self._runTest_ ('' ,'' ,"HTML Element META produced end tag.") def testParamElementNoClose (self): self._runTest_ ('' ,'' ,"HTML Element PARAM produced end tag.") if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/TALTests/HTMLTests/TALMinimizeBooleanAttsTestCases.py0000664000175200017520000001335612537067561026305 0ustar cms103cms10300000000000000#!/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') self.context.addGlobal ('bob', 'bob') self.context.addGlobal ('disabled', 'disabled') self.context.addGlobal ('notdisabled', 'notdisabled') def _runTest_ (self, txt, result, errMsg="Error", minimizeBooleanAtts = 1): template = simpleTAL.compileHTMLTemplate (txt, minimizeBooleanAtts = minimizeBooleanAtts) 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 testTemplateWithBooleanAtt (self): self._runTest_ ('Hello' ,'Hello' ,"Template minimized boolean att failed.") def testTemplateWithBooleanAttWithBooleanDisabled (self): self._runTest_ ('Hello' ,'Hello' ,"Template minimized boolean att failed to output full form with support disabled." , 0) def testTemplateWithFullAtt (self): self._runTest_ ('Hello' ,'Hello' ,"Template full att failed.") def testTemplateWithFullAttWithBooleanDisabled (self): self._runTest_ ('Hello' ,'Hello' ,"Template full boolean att failed to output full form with support disabled." , 0) def testTemplateWithBadBooleanAtt (self): self._runTest_ ('Hello' ,'Hello' ,"Template bad boolean att failed.") def testTALRemoveBooleanAtt (self): self._runTest_ ('Hello' ,'Hello' ,"TAL failed to remove minimized boolean tag") def testTALAddBooleanAtt (self): self._runTest_ ('Hello' ,'Hello' ,"TAL failed to add minimized boolean tag") def testTALBadBooleanAtt (self): self._runTest_ ('Hello' ,'Hello' ,"TAL failed to add with bad minimized boolean tag") def testTALNonBooleanAtt (self): self._runTest_ ('Hello' ,'Hello' ,"TAL failed to add non-boolean tag") def testTALBooleanAttSupportDisabled (self): self._runTest_ ('Hello' ,'Hello' ,"TAL failed to keep long form when support for minimized form disabled" ,0) def testTemplateAllBooleanAtts (self): self._runTest_ (""" """ ,""" """ ,"Template failed to handle every boolean option") if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/TALTests/HTMLTests/TALSpecialCharsTestCases.py0000664000175200017520000000655612537067556024741 0ustar cms103cms10300000000000000#!/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 TALSpecialCharsTestCases (unittest.TestCase): def setUp (self): self.context = simpleTALES.Context(allowPythonPath=1) self.context.addGlobal ('test', '< testing > experimenting & twice as useful') 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 testLessThanGreaterThanAmpersand (self): self._runTest_ ('Hello' ,"< testing > experimenting & twice as useful" ,"Less than, greater than or amperand were not encoded correctly") def testEscapedPythonPaths (self): self._runTest_ ('Hello' ,"4000" ,"Python bit shift failed.") def testAmpInTemplate (self): #logging.getLogger().setLevel(logging.DEBUG) NBSP = "\u00a0" self._runTest_ ('Hello Bye Bye' ,"""Hello Bye Bye""" ,"& in template failed.") if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/TALTests/HTMLTests/TALEncodingTestCases.py0000664000175200017520000001221712537067564024114 0ustar cms103cms10300000000000000#!/usr/bin/python # -*- coding: iso-8859-1 -*- """ 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, codecs import logging, logging.config from simpletal import simpleTAL, simpleTALES if (os.path.exists ("logging.ini")): logging.config.fileConfig ("logging.ini") else: logging.basicConfig() import types try: class UnicodeSubclass(str): pass oldPython = 0 except: # Python 2.1 oldPython = 1 class TALEncodingTestCases (unittest.TestCase): def setUp (self): self.context = simpleTALES.Context() self.context.addGlobal ('test', 'Testing this and that') self.context.addGlobal ('HighBC', 'This cost nothing, yep 0!') self.context.addGlobal ('one', [1]) self.context.addGlobal ('two', ["one", "two"]) self.context.addGlobal ('three', [1,"Two",3]) self.context.addGlobal ('badascii', 'This costs nothing, yep 0') if (not oldPython): self.context.addGlobal ('inheritance', UnicodeSubclass('\u2018subclass\u2019')) 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 testISOToUTF8 (self): utf8Pound = b"\xc2\xa3" # Test file is encoded in ISO-8859-1, so we can use literal characters for this test. template = simpleTAL.compileHTMLTemplate ('3.12? ') file = io.StringIO() template.expand (self.context, file) result = file.getvalue() expectedResult = b"" + utf8Pound + b"3.12? This cost nothing, yep " + utf8Pound + b"0!" expectedResult = expectedResult.decode ("utf-8") self.assertTrue (result == expectedResult, "UTF8 Encoding failed. \nResult was: " + result + "\nExpected result: " + expectedResult) def testISOToISO (self): template = simpleTAL.compileHTMLTemplate ('3.12? ') file = io.StringIO() template.expand (self.context, file) result = file.getvalue() expectedResult = "3.12? This cost nothing, yep 0!" self.assertTrue (result == expectedResult, "ISO Encoding failed. \nResult was: " + result + "\nExpected result: " + expectedResult) def testUTF8ToISO (self): template = simpleTAL.compileHTMLTemplate (b'\xc2\xa33.12? '.decode ('utf-8')) file = io.StringIO() template.expand (self.context, file) result = file.getvalue() expectedResult = "3.12? This cost nothing, yep 0!" self.assertTrue (result == expectedResult, "UTF8 -> ISO Encoding failed. \nResult was: " + result + "\nExpected result: " + expectedResult) def testUnicodeSubclass (self): if (oldPython): return template = simpleTAL.compileHTMLTemplate ('') file = io.StringIO() template.expand (self.context, file) result = file.getvalue() expectedResult = "\u2018subclass\u2019" self.assertTrue (result == expectedResult, "Unicode subclass failed. \nResult was: " + result + "\nExpected result: " + expectedResult) # def testBadAscii (self): # template = simpleTAL.compileHTMLTemplate ('

') # file = StringIO.StringIO() # template.expand (self.context, file, 'iso-8859-1') # result = file.getvalue() # expectedResult = "3.12? This cost nothing, yep 0!" # self.assertTrue (result == expectedResult, "ISO Encoding failed. \nResult was: " + result + "\nExpected result: " + expectedResult) if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/TALTests/HTMLTests/TypesTestCases.py0000664000175200017520000001212312537067555023125 0ustar cms103cms10300000000000000#!/usr/bin/env 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, tempfile, codecs 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 testCompileTemplateBinary (self): """ Test creating an HTML template directly from a file that was binary opened. Write output to a binary file, letting simpleTAL do the encoding. """ # Create a temporary file, they auto-delete templateFile = tempfile.TemporaryFile (mode="w+b") # Write out the HTML in UTF-8 txt = '

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.py0000664000175200017520000001175312537067560023426 0ustar cms103cms10300000000000000#!/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

default contentdefault
default content' ,'

Hello

default contenttesting
testing' ,'Binding of namespace failed to nest correctly with 2 nests') def testOtherNameSpaces (self): self._runTest_ ('Hello' ,'Hello' ,'Namespaces removed!') # Now test exceptions def testDefaultTALNameSpace (self): self._runErrTest_ ('Hello' ,'[] Can not use TAL name space by default, a prefix must be provided.' ,'Namespaces removed!') if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/TALTests/HTMLTests/TALDefineTestCases.py0000664000175200017520000001210612537067564023555 0ustar cms103cms10300000000000000#!/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 TALDefineTestCases (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 testDefineString (self): self._runTest_ ('

', "

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

', 'Multiple defines failed.') def testDefineMultipleMixed (self): self._runTest_ ('

Testing

' , '

testing

This is a semi;colon

Test

This is a semi;colon', 'Multiple defines failed.') def testDefineMultipleLocalRef (self): self._runTest_ ('

Testing

' , '

testing

testing

', 'Multiple local defines with references to earlier define failed.') if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/TALTests/HTMLTests/TALHandlerTestCases.py0000775000175200017520000001134012537067562023740 0ustar cms103cms10300000000000000#!/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 TALHandlerTestCases (unittest.TestCase): def setUp (self): self.context = simpleTALES.Context() self.context.addGlobal ('test', 'testing') self.context.addGlobal ('one', [1]) self.context.addGlobal ('two', ["one", "two"]) self.context.addGlobal ('three', [1,"Two",3]) def _runTest_ (self, txt, result, errMsg="Error"): template = simpleTAL.compileHTMLTemplate (txt) file = 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 testEmptyFile (self): self._runTest_ ("", "", "Empty template contains more text than given.") def testSingleEmptyElement (self): self._runTest_ ("", "") def testSingleElement (self): self._runTest_ ("start", "start") def testUnbalancedDocument (self): self._runTest_ ("startend", "startend") def testNoCloseElement (self): self._runTest_ ("

Hello.
World

", "

Hello.
World

") def testCaseSensitivity (self): self._runTest_ ("

Hello.
World

", "

Hello.
World

") def testComments (self): self._runTest_ ("

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_ ("""\n

Somemarkup

""" ,"""\n

Somemarkup

""" ,"""Processing instructions not preserved.""") if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/TALTests/XMLTests/0000775000175200017520000000000012537322745017520 5ustar cms103cms10300000000000000SimpleTAL-5.2/tests/TALTests/XMLTests/TALSingletonTests.py0000664000175200017520000002501512537067550023423 0ustar cms103cms10300000000000000#!/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


""".encode ("iso-8859-1") ,"""\n

Hello


""".encode ('iso-8859-1') ,"""Local define followed by attributes and global tes""") def testDefineAttributes (self): self._runTest_ ("""

""" ,"""

""" ,"""Local define followed by attributes and global test failed.""") def testConditionDefine (self): self._runTest_ ("""

""" ,"""

""" ,"""Global define and condition failed""") def testRepeatAttributes (self): self._runTest_ ("""
""" ,"""


""" ,"""Repeat and attributes failed.""") def testContentRepeat (self): self._runTest_ ("""
""" ,"""
1

Two

3
""" ,"""Content with Repeat failed.""") def testReplaceRepeat (self): self._runTest_ ("""
""" ,"""1Two3""" ,"""Replace with Repeat failed.""") def testReplaceRepeatAttributes (self): self._runTest_ ("""
""" ,"""1Two3""" ,"""Replace with Repeat failed.""") def testContentRepeatAttributes (self): self._runTest_ ("""
""" ,"""
1

Two

3
""" ,"""Content with Repeat and Attributes failed.""") def testOmitTagContentRepeatAttributes (self): self._runTest_ ("""
""" ,"""1Two3""" ,"""OmitTag with Content and Repeat and Attributes failed.""") def testDefineMacroSlots (self): self._runMacroTest_ ("""
""" ,"""

Hello

""" ,"""

Hello

""" ,"""METAL with define-slot on singleton failed.""") def testDefineMacro (self): self._runMacroTest_ ("""""" ,"""

Hello

""" ,"""""" ,"""METAL with define-macro on singleton failed.""") def testUseMacro (self): self._runMacroTest_ ("""
""" ,"""
""" ,"""
""" ,"""METAL with use-macro on singleton failed.""") def testFillSlot (self): self._runMacroTest_ ("""
""" ,"""
""" ,"""""" ,"""METAL with fill-slot on singleton failed.""") def testRepeatUseMacro (self): self._runMacroTest_ ("""
""" ,"""

""" ,"""




""" ,"""METAL with repeat and use-macro on singleton failed.""") if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/TALTests/XMLTests/TALRepeatTestCases.py0000664000175200017520000003370112537067552023500 0ustar cms103cms10300000000000000#!/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() 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 ('bigList', list(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]} ,{'title': 'Image 3', 'catList': [8,9,1]} ]) 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 testInvalidPath (self): self._runTest_ ('

Hello

' ,'\n' , "Repeat of non-existant element failed") def testDefaultValue (self): self._runTest_ ('

Default Only

' ,'\n

Default 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_ ('

' ,'\n

one

two

' ,'Itteration over list with both content and repeat on same element failed.') def testNestedRepeat (self): self._runTest_ ('

' ,'\n

Image 1

123

Image 2

523

Image 3

891

' ,'Nested repeat did not create expected outcome.' ) def testNestedRepeatClasses (self): self._runTest_ ('

' ,'\n

1
2
3

5
2
3

8
9
1

' ,'Nested repeat with classes did not create expected outcome.' ) def testRepeatVarIndex (self): expectedResult = "" for num in range (0,99): expectedResult += str (num) expectedResult += "" self._runTest_ ('

Index

' ,'\n' + expectedResult ,"Repeat variable index failed." ) def testRepeatVarNumber (self): self._runTest_ ('

Index

' ,'\n123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899' ,'Repeat variable number failed.' ) def testRepeatVarEvenOdd (self): self._runTest_ ('

- OddEven

' ,'\n

zero - Even

one - Odd

two - Even

three - Odd

' ,'Repeat variables odd and even failed.' ) def testRepeatVarStartEnd (self): self._runTest_ ('

StartEnd

' ,'\n

Startzero

one

two

threeEnd

' ,'Repeat variables start and end failed.' ) def testRepeatVarLength (self): self._runTest_ ('

Len: lengthEntry:

' ,'\n

Len: 4Entry: zero

Entry: one

Entry: two

Entry: three

' ,'Repeat variable length failed.' ) def testRepeatVarLowerLetter (self): self._runTest_ ('

a,b,c,etc:

' ,'\n

a: zero

b: one

c: two

d: three

' ,'Repeat variable letter failed.' ) def testRepeatVarLowerLetterLarge (self): self._runTest_ ('

a,b,c,etc:

' ,'\n

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:

' ,'\n

A: zero

B: one

C: two

D: three

' ,'Repeat variable Letter failed.' ) def testRepeatVarLowerRoman (self): self._runTest_ ('

i,ii,iii,etc:

' ,'\n

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:

' ,'\n

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' ,'\n

zero

one

two

three

' ,'Local repeat variable remained accessible out of scope!' ) if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/TALTests/XMLTests/TALContentTestCases.py0000664000175200017520000001066112537067553023673 0ustar cms103cms10300000000000000#!/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", allowTALInStructure=1): 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 testContentNothing (self): self._runTest_ ('

' ,'\n

' ,'Content of nothing did not evaluate to empty tag.') def testContentDefault (self): self._runTest_ ('

Original

' ,'\n

Original

' ,'Content of default did not evaluate to existing content') def testContentString (self): self._runTest_ ('

Original

' ,'\n

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: """ weblog = {'subject': 'Test subject', 'entry': simpleTAL.compileXMLTemplate(entry)} self.context.addGlobal ('weblog', weblog) self._runTest_ ('

Original

' ,'\n

Some structure: Test subject

' ,'Content of Structure did not evaluate to expected result') def testTALDisabledContentStructure (self): self._runTest_ ('

Original

' ,'\n

Some structure:

' ,'Content of Structure did not evaluate to expected result' ,allowTALInStructure=0) if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/TALTests/XMLTests/TALReplaceTestCases.py0000664000175200017520000000774012537067551023636 0ustar cms103cms10300000000000000#!/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.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 testContentNothing (self): self._runTest_ ('

' ,'\n' ,'Content of nothing did not remove tag.') def testContentDefault (self): self._runTest_ ('

Original

' ,'\n

Original

' ,'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 = """Some structure: """ weblog = {'subject': 'Test subject', 'entry': simpleTAL.compileXMLTemplate(entry)} self.context.addGlobal ('weblog', weblog) self._runTest_ ('

Original

' ,'\nSome structure: Test subject' ,'Content of Structure did not evaluate to expected result') if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/TALTests/XMLTests/TALConditionTestCases.py0000664000175200017520000000651712537067554024215 0ustar cms103cms10300000000000000#!/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.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 testConditionDefault (self): self._runTest_ ('Hello', '\nHello', "Condition 'default' did not evaluate to true") def testConditionExists (self): self._runTest_ ('Hello' , '\nHello', 'Condition for something that exists evaluated false') def testConditionNothing (self): self._runTest_ ('Hello' , '\n', 'Condition nothing evaluated to true') def testConditionMissing (self): self._runTest_ ('Hello' , '\n', 'Condition for something that does not exist evaluated to true') if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/TALTests/XMLTests/TALForbiddenEndTagTestCases.py0000664000175200017520000001411612537067553025237 0ustar cms103cms10300000000000000#!/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): """ Tests to prove that XML templates do not perform end tag suppression on HTML elements that have forbidden end tags in HTML 4.01. See equivalent HTML test cases for end tag suppression. """ 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.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 testAreaElement (self): self._runTest_ ('' ,'\n' ,"HTML Element AREA did NOT produce end tag.") def testBaseElement (self): self._runTest_ ('' ,'\n' ,"HTML Element BASE did NOT produce end tag.") def testBaseFontElement (self): self._runTest_ ('' ,'\n' ,"HTML Element BASEFONT did NOT produce end tag.") def testBRElement (self): self._runTest_ ('

' ,'\n

' ,"HTML Element BR did NOT produce end tag.") def testColElement (self): self._runTest_ ('' ,'\n' ,"HTML Element COL did NOT produce end tag.") def testFrameElement (self): self._runTest_ ('' ,'\n' ,"HTML Element FRAME did NOT produce end tag.") def testHRElement (self): self._runTest_ ('
' ,'\n
' ,"HTML Element HR did NOT produce end tag.") def testImgElement (self): self._runTest_ ('' ,'\n' ,"HTML Element IMG did NOT produce end tag.") def testInputElement (self): self._runTest_ ('' ,'\n' ,"HTML Element INPUT did NOT produce end tag.") def testIsIndexElement (self): self._runTest_ ('' ,'\n' ,"HTML Element ISINDEX did NOT produce end tag.") def testLinkElement (self): self._runTest_ ('' ,'\n' ,"HTML Element LINK did NOT produce end tag.") def testMetaElement (self): self._runTest_ ('' ,'\n' ,"HTML Element META did NOT produce end tag.") def testParamElement (self): self._runTest_ ('' ,'\n' ,"HTML Element PARAM did NOT produce end tag.") if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/TALTests/XMLTests/TALSpecialCharsTestCases.py0000664000175200017520000001013512537067545024617 0ustar cms103cms10300000000000000#!/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 try: # check to see if pyxml is installed from xml.sax.saxlib import LexicalHandler use_lexical_handler = 1 except ImportError: use_lexical_handler = 0 class LexicalHandler: pass from simpletal import simpleTAL, simpleTALES if (os.path.exists ("logging.ini")): logging.config.fileConfig ("logging.ini") else: logging.basicConfig() class TALSpecialCharsTestCases (unittest.TestCase): def setUp (self): self.context = simpleTALES.Context(allowPythonPath=1) self.context.addGlobal ('test', '< testing > experimenting & twice as useful') 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", allowTALInStructure=1): 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 testLessThanGreaterThanAmpersand (self): self._runTest_ ('Hello' ,"""\n< testing > experimenting & twice as useful""" ,"Less than, greater than or amperand were not encoded correctly") def testEscapedPythonPaths (self): self._runTest_ ('Hello' ,"""\n4000""" ,"Python bit shift failed.") def testAmpInTemplate (self): if use_lexical_handler: expectedResult = """ Hello Bye Bye""" else: expectedResult = """ Hello Bye Bye""" self._runTest_ (""" Hello Bye Bye""" ,expectedResult ,"& in template failed.") if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/TALTests/XMLTests/TALEncodingTestCases.py0000664000175200017520000001051512537067511023777 0ustar cms103cms10300000000000000#!/usr/bin/python # -*- coding: iso-8859-1 -*- """ 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 sourceftware 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, codecs import logging, logging.config from simpletal import simpleTAL, simpleTALES if (os.path.exists ("logging.ini")): logging.config.fileConfig ("logging.ini") else: logging.basicConfig() class TALEncodingTestCases (unittest.TestCase): def setUp (self): self.context = simpleTALES.Context() self.context.addGlobal ('test', 'Testing this and that') self.context.addGlobal ('HighBC', 'This cost nothing, yep 0!') 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, 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 testISOToUTF8 (self): utf8Pound = b"\xc2\xa3" template = simpleTAL.compileXMLTemplate ('\n3.12? '.encode ('iso-8859-1')) file = io.StringIO() template.expand (self.context, file, 'utf-8') result = file.getvalue().encode ('utf-8') expectedResult = b'\n' + utf8Pound + b"3.12? This cost nothing, yep " + utf8Pound + b"0!" self.assertTrue (result == expectedResult, "UTF8 Encoding failed. \nResult was: " + str(result) + "\nExpected result: " + str(expectedResult)) def testISOToISO (self): template = simpleTAL.compileXMLTemplate ('\n3.12? '.encode ('iso-8859-1')) file = io.StringIO() template.expand (self.context, file, 'iso-8859-1') result = file.getvalue().encode ('iso-8859-1') expectedResult = '\n3.12? This cost nothing, yep 0!'.encode ('iso-8859-1') self.assertTrue (result == expectedResult, "ISO Encoding failed. \nResult was: " + str(result) + "\nExpected result: " + str(expectedResult)) def testUTF8ToISO (self): template = simpleTAL.compileXMLTemplate (b'\n\xc2\xa33.12? ') file = io.StringIO() template.expand (self.context, file, 'iso-8859-1') result = file.getvalue().encode ('iso-8859-1') expectedResult = '\n3.12? This cost nothing, yep 0!'.encode ('iso-8859-1') self.assertTrue (result == expectedResult, "UTF8 -> ISO Encoding failed. \nResult was: " + str (result) + "\nExpected result: " + str (expectedResult)) if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/TALTests/XMLTests/TypesTestCases.py0000664000175200017520000001275512537067477023037 0ustar cms103cms10300000000000000#!/usr/bin/env 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, tempfile, codecs 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 testCompileTemplateBinary (self): """ Test creating an XML template directly from a file that was binary opened. Write output to a binary file, letting simpleTAL do the encoding. NOTE: Can not use tempfile.TemporaryFile as this sets the 'name' attribute to an integer, which then breaks Expat. """ # Create a temporary file manually try: fileHandle, fileName = tempfile.mkstemp () with open (fileName, mode='b+w') as templateFile: # Write out the XML in UTF-8 txt = '\n

Somethings cost £3

Two

' expectedOutput = '\n

Somethings 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 = '\n

Somethings cost £3

Two

' expectedOutput = '\n

Somethings 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.py0000664000175200017520000001540012537067466023320 0ustar cms103cms10300000000000000#!/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' ,'\n

Hello

default contenttesting' ,'Binding of namespace failed to nest correctly') def testDoubleNestedBind (self): self._runTest_ ('

Hello

default contentdefault
default content' ,'\n

Hello

default contenttesting
testing' ,'Binding of namespace failed to nest correctly with 2 nests') def testOtherNameSpaces (self): self._runTest_ ('Hello' ,'\nHello' ,'Namespaces removed!') # Test to ensure that using elements in the tal namespace omits tags def testTALEmlement (self): self._runTest_ ('Hello' ,'\ntesting' ,'TAL Element written out') def testTALEmlementAttNameSpaced (self): self._runTest_ ('Hello' ,'\ntesting' ,'TAL Element failed when namespace specified for attribute') def testTALEmlementWithOmitTag (self): self._runTest_ ('Hello' ,'\ntesting' ,'TAL Element written out when omit tag specified') def testTALEmlementWithDefaultNS (self): self._runTest_ ('Hello' ,'\ntesting' ,'TAL Element written!') def testMetalBlockWithRepeat (self): self._runTest_ ('Some value here' ,'\nSome one hereSome two here' ,"Repeat on Metal:Block failed.") # Now test exceptions def testDefaultTALNameSpace (self): self._runErrTest_ ('Hello' ,'[] Can not use TAL name space by default, a prefix must be provided.' ,'Namespaces removed!') if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/TALTests/XMLTests/TALDefineTestCases.py0000664000175200017520000001114512537067404023444 0ustar cms103cms10300000000000000#!/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 TALDefineTestCases (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 testDefineString (self): self._runTest_ ('

', '\n

testing

', "Simple string define failed.") def testDefineList (self): self._runTest_ ('

Hello

' , '\n

Hello one

Hello two

', 'List define failed.') def testDefineGlobal (self): self._runTest_ ('

' , '\n

testing

', '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

' , '\n

testing

This is a semi;colon

Test

', 'Multiple defines failed.') def testDefineMultipleMixed (self): self._runTest_ ('

Testing

' , '\n

testing

This is a semi;colon

Test

This is a semi;colon', 'Multiple defines failed.') if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/TALTests/XMLTests/TALHandlerTestCases.py0000775000175200017520000003163712537067356023650 0ustar cms103cms10300000000000000#!/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 import xml.sax, xml.sax.handler from hashlib import md5 try: # check to see if pyxml is installed from xml.sax.saxlib import LexicalHandler use_lexical_handler = 1 except ImportError: use_lexical_handler = 0 class LexicalHandler: pass from simpletal import simpleTAL, simpleTALES if (os.path.exists ("logging.ini")): logging.config.fileConfig ("logging.ini") else: logging.basicConfig() class 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, LexicalHandler): def __init__ (self, parser): xml.sax.handler.ContentHandler.__init__ (self) self.ourParser = parser def getDigest (self): return self.digest.hexdigest() def startDocument (self): self.digest = 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 comment (self, data): self.digest.update (data) def skippedEntity (self, name): self.digest.update (name) # DTD Handler def notationDecl(self, name, publicId, systemId): self.digest.update (name) self.digest.update (publicId) self.digest.update (systemId) def unparsedEntityDecl(name, publicId, systemId, ndata): self.digest.update (name) self.digest.update (publicId) self.digest.update (systemId) self.digest.update (ndata) def error (self, excpt): print("Error: %s" % str (excpt)) def warning (self, excpt): print("Warning: %s" % str (excpt)) def startDTD(self, name, publicId, systemId): self.digest.update (name) self.digest.update (publicId) self.digest.update (systemId) CHECKSUMPARSER = xml.sax.make_parser() CHECKSUMHANDLER = XMLChecksumHandler(CHECKSUMPARSER) CHECKSUMPARSER.setContentHandler (CHECKSUMHANDLER) CHECKSUMPARSER.setDTDHandler (CHECKSUMHANDLER) CHECKSUMPARSER.setErrorHandler (CHECKSUMHANDLER) try: CHECKSUMPARSER.setFeature (xml.sax.handler.feature_external_ges, 0) except: pass if use_lexical_handler: CHECKSUMPARSER.setProperty(xml.sax.handler.property_lexical_handler, CHECKSUMHANDLER) def getXMLChecksum (doc): CHECKSUMPARSER.parse (io.StringIO (doc)) return CHECKSUMHANDLER.getDigest() class TALHandlerTestCases (unittest.TestCase): def setUp (self): self.context = simpleTALES.Context() self.context.addGlobal ('test', 'testing') self.context.addGlobal ('one', [1]) self.context.addGlobal ('two', ["one", "two"]) self.context.addGlobal ('three', [1,"Two",3]) def _runTest_ (self, txt, result, errMsg="Error"): template = simpleTAL.compileXMLTemplate (txt) fh = io.StringIO () template.expand (self.context, fh, outputEncoding="iso-8859-1") realResult = fh.getvalue() expectedChecksum = getXMLChecksum (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 testSingleEmptyElement (self): self._runTest_ ("", '\n') def testSingleElement (self): self._runTest_ ("start", '\nstart') def testSingleElementSpaces (self): self._runTest_ ('


', '\n


') def testSingleElementNewLines (self): self._runTest_ ('

', '\n


') def testSingleElementEasyAttributes (self): self._runTest_ ('
', '\n
') def testSingleElementHardAttributes (self): self._runTest_ ("""


""", """\n


""") def testSingleElementHarderAttributes (self): self._runTest_ ("""
""" ,"""
""") def testCDATASection (self): self._runTest_ (" CDATA section stuff & things.]]>" ,"""\nHere's some <escaped> CDATA section stuff & things.""" ,"CDATA section was not re-encoded correctly.") def testNameSpaces (self): self._runTest_ ("""\nTesting""" ,"""\nTesting""" ,"""Namespaces not preserved.""") def testProcessingInstructions (self): self._runTest_ ("""\n

Somemarkup

""" ,"""\n

Somemarkup

""" ,"""Processing instructions not preserved.""") def testCommentHandling (self): if (not use_lexical_handler): return self._runTest_ ("""\n

Here

""" ,"""\n

Here

""" ,"Comments not preserved.") def testDocumentTypeDeclaration (self): txt = """\n\n

Test

""" template = simpleTAL.compileXMLTemplate (txt) fh = io.StringIO () template.expand (self.context, fh, docType="""""", outputEncoding="iso-8859-1") realResult = fh.getvalue() expectedResult = """\n\n

Test

""" 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\n

Test

""" template = simpleTAL.compileXMLTemplate (txt) fh = io.StringIO () template.expand (self.context, fh, docType="""""", suppressXMLDeclaration=1) realResult = fh.getvalue() expectedResult = """\n

Test

""" 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\n

Test 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 = """\n

Test\xa0Space

""".encode ("utf-8") else: expectedResult = """\n\n

Test\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 = """\n

Test

""" 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_ ("""Hi""", """\n\nHi""") def testSampleXHTML11Doc (self): """ Cut and pasted right out of the xhtml 1.1 spec """ if not use_lexical_handler: return self._runTest_ ("""\ Virtual Library

Moved to vlib.org.

""","""\ Virtual Library

Moved to vlib.org.

""") if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/TALTests/XMLTests/TALAttributeTestCases.py0000664000175200017520000002073012537067344024220 0ustar cms103cms10300000000000000#!/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/0000775000175200017520000000000012537322745017656 5ustar cms103cms10300000000000000SimpleTAL-5.2/tests/PerformanceTests/HTMLTests/0000775000175200017520000000000012537322745021445 5ustar cms103cms10300000000000000SimpleTAL-5.2/tests/PerformanceTests/HTMLTests/DeeplyNestedRepeatProfile.py0000664000175200017520000001063612537066033027067 0ustar cms103cms10300000000000000""" 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 = """

Performance Template

Itteration title

Colour

  • All numbers

""" # 3 X 7 X 8 = 168 itterations per template expansion. thirdLevelList = ["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight"] secondLevelList = [{"colour": "red", "num": thirdLevelList}, {"colour": "orange", "num": thirdLevelList}, {"colour": "yellow", "num": thirdLevelList}, {"colour": "green", "num": thirdLevelList}, {"colour": "blue", "num": thirdLevelList}, {"colour": "indigo", "num": thirdLevelList}, {"colour": "violet", "num": thirdLevelList}] firstLevelList = [{"title": "First", "content": secondLevelList}, {"title": "Second", "content": secondLevelList}, {"title": "Third", "content": secondLevelList}] context = simpleTALES.Context() context.addGlobal ("title", "Performance testing!") context.addGlobal ("myList", firstLevelList ) def NGTemplates (count): tempFile = io.StringIO (performanceTemplate) compiler = simpleTAL.HTMLTemplateCompiler() compiler.parseTemplate (tempFile) template = compiler.getTemplate() file = io.StringIO() start = time.clock() for attempt in range (count): template.expand (context, file) end = time.clock() #print "Resuling file: " + file.getvalue() return (end - start) def NGTemplateOverhead (count): file = io.StringIO() start = time.clock() for attempt in range (count): tempFile = io.StringIO (performanceTemplate) compiler = simpleTAL.HTMLTemplateCompiler() compiler.parseTemplate (tempFile) template = compiler.getTemplate() #template.expand (context, file) end = time.clock() #print "Resuling file: " + file.getvalue() return (end - start) print("Timing TAL templates") #profiler = hotshot.Profile ("profile.data") profiler = profile.run("NGTemplates (20)", "profile.data") #profiler = profile.run("NGTemplateOverhead (20)", "profile.data") #profiler.runcall (NGTemplates, 20) print("Re-enabling garbage collection.") gc.enable() print("Loading profile data.") #data = hotshot.stats.load ("profile.data") data = pstats.Stats("profile.data") data = data.strip_dirs() sortedData = data.sort_stats ('time', 'calls') sortedData.print_stats (25) #sortedData.print_callees ('cmdRepeat') #sortedData.print_callees ('cmdContent') data.print_callees ('cmdEndTagEndScope')SimpleTAL-5.2/tests/PerformanceTests/HTMLTests/DeeplyNestedRepeatTest.py0000664000175200017520000000771712537066033026414 0ustar cms103cms10300000000000000""" 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 performanceTemplate = """

Performance Template

Itteration title

Colour

  • All numbers

""" # 3 X 7 X 8 = 168 itterations per template expansion. thirdLevelList = ["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight"] secondLevelList = [{"colour": "red", "num": thirdLevelList}, {"colour": "orange", "num": thirdLevelList}, {"colour": "yellow", "num": thirdLevelList}, {"colour": "green", "num": thirdLevelList}, {"colour": "blue", "num": thirdLevelList}, {"colour": "indigo", "num": thirdLevelList}, {"colour": "violet", "num": thirdLevelList}] firstLevelList = [{"title": "First", "content": secondLevelList}, {"title": "Second", "content": secondLevelList}, {"title": "Third", "content": secondLevelList}] context = simpleTALES.Context() context.addGlobal ("title", "Performance testing!") context.addGlobal ("myList", firstLevelList ) def NGTemplates (count): tempFile = io.StringIO (performanceTemplate) compiler = simpleTAL.HTMLTemplateCompiler() compiler.parseTemplate (tempFile) template = compiler.getTemplate() file = io.StringIO() start = time.clock() for attempt in range (count): template.expand (context, file) end = time.clock() #print "Resuling file: " + file.getvalue() return (end - start) def NGTemplateOverhead (count): file = io.StringIO() start = time.clock() for attempt in range (count): tempFile = io.StringIO (performanceTemplate) compiler = simpleTAL.HTMLTemplateCompiler() compiler.parseTemplate (tempFile) template = compiler.getTemplate() template.expand (context, file) end = time.clock() #print "Resuling file: " + file.getvalue() return (end - start) print("Timing TAL templates") result = NGTemplates (1000) print("Result: " + str(result) + " for 1000 template expansions") print("Timing TAL templates (with template parsing)") result = NGTemplateOverhead (1000) print("Result: " + str(result) + " for 1000 template expansions") SimpleTAL-5.2/tests/PerformanceTests/HTMLTests/BasicMETALTest.py0000664000175200017520000000750412537066033024464 0ustar cms103cms10300000000000000#!/usr/bin/python # -*- coding: iso-8859-1 -*- """ 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 macroTemplate = """

Macros follow

A sample macro

  • First
Important Stuff, worth s
Table
""" performanceTemplate = """

Performance Template

Some text, with some tags that are adding to the parsing load.

This title is dynamic

Here's a table as well - lots of tags in there:
Here's a list of thing:

things

things

That should do...

""" context = simpleTALES.Context() context.addGlobal ("title", "Performance testing!") context.addGlobal ("myList", ["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight"]) template = simpleTAL.compileHTMLTemplate (performanceTemplate) macTemplate = simpleTAL.compileHTMLTemplate (macroTemplate) context.addGlobal ("macTemp", macTemplate) def METALTime (count, template): file = io.StringIO() start = time.clock() for attempt in range (count): template.expand (context, file) end = time.clock() #print ("Resuling file: " + file.getvalue()) return (end - start) #print "Timing TAL templates" #result = NGTemplates (2000) #print "Result: " + str(result) + " for 2000 template expansions" # Pre-expand macros expanded = simpleTALUtils.ExpandMacros (context, template) #print expanded realTemplate = simpleTAL.compileHTMLTemplate (expanded) print("Timing macro expansion...") result = METALTime (4000, realTemplate) print("Total time %s for 4000 itterations" % (str (result))) SimpleTAL-5.2/tests/PerformanceTests/HTMLTests/BasicTemplateTest.py0000664000175200017520000001136312537066033025373 0ustar cms103cms10300000000000000""" 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 performanceTemplate = """

Performance Template

Some text, with some tags that are adding to the parsing load.

This title is dynamic

Here's a table as well - lots of tags in there:
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.
Here's a list of thing:
  • An item
That should do...

""" context = simpleTALES.Context() context.addGlobal ("title", "Performance testing!") context.addGlobal ("myList", ["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight"]) def NGTemplates (count): tempFile = io.StringIO (performanceTemplate) compiler = simpleTAL.HTMLTemplateCompiler() compiler.parseTemplate (tempFile) template = compiler.getTemplate() file = io.StringIO() start = time.clock() for attempt in range (count): template.expand (context, file) end = time.clock() #print "Resuling file: " + file.getvalue() return (end - start) def NGTemplateOverhead (count): file = io.StringIO() start = time.clock() for attempt in range (count): tempFile = io.StringIO (performanceTemplate) compiler = simpleTAL.HTMLTemplateCompiler() compiler.parseTemplate (tempFile) template = compiler.getTemplate() template.expand (context, file) end = time.clock() #print "Resuling file: " + file.getvalue() return (end - start) print("Timing TAL templates") result = NGTemplates (10000) print("Result: " + str(result) + " for 10000 template expansions") print("Timing TAL templates (with template parsing)") result = NGTemplateOverhead (1000) print("Result: " + str(result) + " for 1000 template expansions") SimpleTAL-5.2/tests/PerformanceTests/XMLTests/0000775000175200017520000000000012537322745021341 5ustar cms103cms10300000000000000SimpleTAL-5.2/tests/PerformanceTests/XMLTests/BasicTemplateTest.py0000664000175200017520000001141412537066033025264 0ustar cms103cms10300000000000000""" 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 performanceTemplate = """

Performance Template

Some text, with some tags that are adding to the parsing load.

This title is dynamic

Here's a table as well - lots of tags in there:
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.
Here's a list of thing:
  • An item
That should do...

""" context = simpleTALES.Context() context.addGlobal ("title", "Performance testing!") context.addGlobal ("myList", ["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight"]) def NGTemplates (count): tempFile = io.StringIO (performanceTemplate) compiler = simpleTAL.XMLTemplateCompiler() compiler.parseTemplate (tempFile) template = compiler.getTemplate() file = io.StringIO() start = time.clock() for attempt in range (count): template.expand (context, file) end = time.clock() #print "Resuling file: " + file.getvalue() return (end - start) def NGTemplateOverhead (count): file = io.StringIO() start = time.clock() for attempt in range (count): tempFile = io.StringIO (performanceTemplate) compiler = simpleTAL.XMLTemplateCompiler() compiler.parseTemplate (tempFile) template = compiler.getTemplate() template.expand (context, file) end = time.clock() #print "Resuling file: " + file.getvalue() return (end - start) print("Timing TAL templates") result = NGTemplates (10000) print("Result: " + str(result) + " for 10000 template expansions") print("Timing TAL templates (with template parsing)") result = NGTemplateOverhead (1000) print("Result: " + str(result) + " for 1000 template expansions") SimpleTAL-5.2/tests/TALESTests/0000775000175200017520000000000012537322745016265 5ustar cms103cms10300000000000000SimpleTAL-5.2/tests/TALESTests/PathTests.py0000664000175200017520000001517612537067325020570 0ustar cms103cms10300000000000000#!/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 World" def nestedFunction (): return {'nest': simpleFunction} def pathFunction (thePath): return thePath class CallRecorder: def __init__ (self): self.called = 0 def simpleFunction (self): self.called += 1 return "Hello" class PathTests (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 ('theMap', {'top': 'Hello', 'onelevel': {'top': 'Bye'}}) self.context.addGlobal ('funcMap', {'simple': simpleFunction, 'nested': nestedFunction, 'pathFunc': simpleTALES.PathFunctionVariable (pathFunction)}) self.context.addGlobal ('topFunc', simpleFunction) self.context.addGlobal ('pathFunc', simpleTALES.PathFunctionVariable (pathFunction)) self.context.addGlobal ('cacheFunc', simpleTALES.CachedFuncResult (self.recorder.simpleFunction)) self.context.addGlobal ('alist', [{'a': 'An A', 'b': 'A B'},"Hello!"]) 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 _runCacheTest_ (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)) self.assertTrue (self.recorder.called == 1, 'Recorder shows function was called %s times!' % str (self.recorder.called)) def testSimpleTopPath (self): self._runTest_ ('Top' ,'Hello from the top' ,'Simple top level path failed.' ) def testOneLevelMap (self): self._runTest_ ('Map' ,'Hello' ,'One level deep map access failed.' ) def testTwoLevelMap (self): self._runTest_ ('Map' ,'Bye' ,'Two level deep map access failed.' ) def testOneLevelFuncMap (self): self._runTest_ ('Map' ,'Hello World' ,'One level deep function access failed.' ) def testTwoLevelFuncMap (self): self._runTest_ ('Map' ,'Hello World' ,'Two level deep function access failed.' ) def testTopLevelFunc (self): self._runTest_ ('Map' ,'Hello World' ,'Top level function access failed.' ) def testFirstORPath (self): self._runTest_ ('hmm' ,'Hello from the top' ,'First valid path was not selected.' ) def testSecondORPath (self): self._runTest_ ('hmm' ,'Wobble the way' ,'Second valid path was not selected.' ) def testPathFunctionNoParams (self): self._runTest_ ('hmm' ,'' ,'Path Function with no parameters failed.' ) def testPathFunctionWithOnePath (self): self._runTest_ ('hmm' ,'firstPath' ,'Path Function with one parameter failed.' ) def testPathFunctionWithTwoPath (self): self._runTest_ ('hmm' ,'firstPath/second' ,'Path Function with two parameters failed.' ) def testPathFunctionWithOnePathOneDeep (self): self._runTest_ ('hmm' ,'firstPath' ,'Path Function with one parameter, nested one deep, failed.' ) def testAList (self): self._runTest_ ('hmm' ,'An A' ,'Index into list then dictionary failed.' ) def testAList2ndItem (self): self._runTest_ ('hmm' ,'Hello!' ,'Index into list failed.' ) def testAListNoSuchItem (self): self._runTest_ ('hmm' ,'' ,'Index past end of list failed.' ) def testCachedFuction (self): self._runCacheTest_ ('' ,'HelloHello' ,"Cached function didn't return as expected." ) if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/TALESTests/StringTests.py0000664000175200017520000001430612537067316021134 0ustar cms103cms10300000000000000#!/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 StringTests (unittest.TestCase): def setUp (self): self.context = simpleTALES.Context() self.context.addGlobal ('top', 'Hello from the top') self.context.addGlobal ('alt', 'Wobble the way') self.context.addGlobal ('holder', {'helloFunc': simpleFunction ,'falseFunc': simpleFalseFunc}) self.context.addGlobal ('version', 3.1) self.context.addGlobal ('uniString', "Hello") 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 testEmptyString (self): self._runTest_ ('Exists' ,'' ,'Empty string returned something!' ) def testStaticString (self): self._runTest_ ('Exists' ,'Hello World!' ,'Static string didnt appear!' ) def testSingleVariable (self): self._runTest_ ('Exists' ,'Hello from the top' ,'Single variable failed.' ) def testStartVariable (self): self._runTest_ ('Exists' ,'Hello from the top of here' ,'Start variable failed.' ) def testMidVariable (self): self._runTest_ ('Exists' ,'Thoughts - Hello from the top eh?' ,'Mid variable failed.' ) def testEndVariable (self): self._runTest_ ('Exists' ,'Thought - Hello from the top' ,'End variable failed.' ) def testNumericVariable (self): self._runTest_ ('Exists' ,'Thought - 3.1' ,'Numeric test variable failed.' ) def testUnicodeVariable (self): self._runTest_ ('Exists' ,'Thought - Hello' ,'Unicode test variable failed.' ) def testSinglePath (self): self._runTest_ ('Exists' ,'Hello from the top' ,'Single path failed.' ) def testStartPath (self): self._runTest_ ('Exists' ,'Hello from the top of here' ,'Start path failed.' ) def testMidPath (self): self._runTest_ ('Exists' ,'Thoughts - Hello from the topeh?' ,'Mid path failed.' ) def testEndPath (self): self._runTest_ ('Exists' ,'Thought - Hello from the top' ,'End path failed.' ) def testMultiplePath (self): self._runTest_ ('Exists' ,'Thought - Hello from the top is here and recursive' ,'Multiple paths failed.' ) def testNoSuchPath (self): self._runTest_ ('Exists' ,'' ,'No such path failed.' ) def testTrailingDollar (self): self._runTest_ ('Exists' ,'A trailing dollar: ' ,'No such path failed.' ) def testDollarEscaping (self): self._runTest_ ('Exists' ,'$A trailing $dollar: $' ,'No such path failed.' ) def testPartialMissing (self): self._runTest_ ('Exists' ,'First bit here: Wobble the way second bit not: there.' ,'Combination of non-existant variable and existing test failed.' ) if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/TALESTests/VariablePathTest.py0000664000175200017520000000750312537067307022046 0ustar cms103cms10300000000000000#!/usr/bn/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 World" def nestedFunction (): return {'nest': simpleFunction} def pathFunction (thePath): return thePath class PathTests (unittest.TestCase): def setUp (self): self.context = simpleTALES.Context() self.context.addGlobal ('colours', {'blue': 'The sea is blue', 'red': 'The ball is red', 'green': 'The grass is green'}) self.context.addGlobal ('aList', ['blue', 'green']) self.context.addGlobal ('goodColour', 'goodColourPath') self.context.addGlobal ('goodColourPath', 'Black is good') self.context.addGlobal ('noSuchColour', 'pink') def _runTest_ (self, txt, result, errMsg="Error"): template = simpleTAL.compileHTMLTemplate (txt) file = 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 testRepeatVariablePath (self): self._runTest_ ('
  • List
' ,'
  • The sea is blue
  • The grass is green
' ,'Path variable during repeat failed.' ) def testLocalVariablePath (self): self._runTest_ ('

It is red:

' ,'

It is red: The ball is red

' ,'Local variable path failed.' ) def testGlobalVariablePath (self): self._runTest_ ('

' ,'

Black is good

' ,'Global variable path failed.' ) def testNoSuchVariablePath (self): self._runTest_ ('

' ,'

' ,'No such variable failed.' ) def testNoSuchVariablePath2 (self): self._runTest_ ('

' ,'

' ,'No such variable2 failed.' ) SimpleTAL-5.2/tests/TALESTests/PythonPathTests.py0000664000175200017520000001557612537067276022003 0ustar cms103cms10300000000000000#!/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.py0000664000175200017520000001070512537067145020425 0ustar cms103cms10300000000000000#!/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.py0000664000175200017520000001011312537067135021025 0ustar cms103cms10300000000000000#!/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.py0000664000175200017520000001010612537067122021132 0ustar cms103cms10300000000000000#!/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/0000775000175200017520000000000012537322745017056 5ustar cms103cms10300000000000000SimpleTAL-5.2/tests/TALUtilsTests/MacroExpansionTestCases.py0000664000175200017520000000700512537067077024203 0ustar cms103cms10300000000000000#!/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 = '
HelloBlue
' template = simpleTAL.compileHTMLTemplate (txt) self._runTest_ (template ,txt ,'World is Blue' ,'Expasion with slots failed.') def testXMLMacroExpansionSlots (self): txt = '\n
HelloBlue
' template = simpleTAL.compileXMLTemplate (txt) self._runTest_ (template ,txt ,'\nWorld is Blue' ,'Expasion with slots failed.') if __name__ == '__main__': unittest.main()SimpleTAL-5.2/tests/TALUtilsTests/TemplateCacheTestCases.py0000664000175200017520000002750612537067050023753 0ustar cms103cms10300000000000000#!/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, os.path, time import io import logging, logging.config logging.basicConfig(level = logging.INFO) from simpletal import simpleTALUtils, simpleTALES, simpleTAL HTMLTemplate1 = """

Title

""" HTMLTemplate2 = """

Title

Message

""" XMLTemplate1 = """\n

Title

""" XMLTemplate2 = """\n

Title

Message

""" 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 = """

Cache Test

""" 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 == 1, "Cache miss not recorded!") # Get the cached template template = self.cache.getTemplate (name) outputFile = io.StringIO () template.expand (self.context, outputFile) expectedResult = """

Cache Test

""" 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 == 1, "Cache hit not recorded!") # Update the template, should cause a re-compile of the template # Ensure that time ellapses so that a ctime change is recorded time.sleep (1) tf = open (name, 'w') tf.write (HTMLTemplate2) tf.close() # Get the template template = self.cache.getTemplate (name) outputFile = io.StringIO () template.expand (self.context, outputFile) expectedResult = """

Cache Test

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 = """

Cache Test

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 = """\n

Cache Test

""" self.assertTrue (type (template) == simpleTAL.XMLTemplate, "Error: Template was not auto-detected as XML") 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 == 1, "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 = """\n

Cache Test

""" 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 == 1, "Cache hit not recorded!") # Update the template, should cause a re-compile of the template # Ensure that time ellapses so that a ctime change is recorded time.sleep (1) tf = open (name, 'w') tf.write (XMLTemplate2) tf.close() # Get the template template = self.cache.getTemplate (name) outputFile = io.StringIO () template.expand (self.context, outputFile, outputEncoding="iso-8859-1") expectedResult = """\n

Cache Test

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, outputEncoding="iso-8859-1") expectedResult = """\n

Cache Test

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 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 = """\n

Cache Test

""" 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 == 1, "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 = """\n

Cache Test

""" 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 == 1, "Cache hit not recorded!") # Update the template, should cause a re-compile of the template # Ensure that time ellapses so that a ctime change is recorded time.sleep (1) tf = open (name, 'w') tf.write (XMLTemplate2) tf.close() # Get the template template = self.cache.getXMLTemplate (name) outputFile = io.StringIO () template.expand (self.context, outputFile, outputEncoding="iso-8859-1") expectedResult = """\n

Cache Test

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.getXMLTemplate (name) outputFile = io.StringIO () template.expand (self.context, outputFile, outputEncoding="iso-8859-1") expectedResult = """\n

Cache Test

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!") if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/METALTests/0000775000175200017520000000000012537322745016257 5ustar cms103cms10300000000000000SimpleTAL-5.2/tests/METALTests/HTMLTests/0000775000175200017520000000000012537322745020046 5ustar cms103cms10300000000000000SimpleTAL-5.2/tests/METALTests/HTMLTests/METALNameSpaceTests.py0000664000175200017520000001064512537066740024070 0ustar cms103cms10300000000000000#!/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_ ('
Before blue After
' ,'Nowt white here' ,'Nowt white here' ,"Single Bind, commands, failed.") def testSingleBindCommands (self): self._runTest_ ('
Before blue After
' ,'Nowt white here' ,'
Before white After
' ,"Single Bind, commands, failed.") # Test to ensure that using elements in the metal namespace omits tags def testMETALEmlement (self): self._runTest_ ('Before blue After' ,'Nowt white here' ,'Before white After' ,"METAL namespace does not cause implicit omit-tag") if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/METALTests/HTMLTests/DefineMacroTests.py0000664000175200017520000001400112537066717023617 0ustar cms103cms10300000000000000#!/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() pageTemplate = simpleTAL.compileHTMLTemplate ("""

Expansion of macro one

""") pageTemplate2 = simpleTAL.compileHTMLTemplate ("""
""") class DefineMacroTests (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, txt, result, errMsg="Error"): macroTemplate = simpleTAL.compileHTMLTemplate (txt) self.context.addGlobal ("site", macroTemplate) file = io.StringIO () pageTemplate.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, pageTemplate)) def _runTest2_ (self, txt, result, errMsg="Error"): macroTemplate = simpleTAL.compileHTMLTemplate (txt) self.context.addGlobal ("site", macroTemplate) file = io.StringIO () pageTemplate2.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, pageTemplate)) 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 testSingleMacroDefinition (self): self._runTest_ ('
No slots here
' ,'\n
No slots here
\n' ,"Single macro with no slots failed.") def testSingleMacroDefinitionInRepeat (self): self._runTest2_ ('
No slots here
' ,'\n
\n
No slots here
\n
\n
No slots here
\n
\n
No slots here
\n
\n' ,"Single macro with no slots failed.") def testTwoMacroDefinition (self): self._runTest_ ('A second macro
No slots here
' ,'\n
No slots here
\n' ,"Two macros with no slots failed.") def testNestedMacroDefinition (self): self._runTest_ ('
A second macroNo slots here
' ,'\nA second macro\n' ,"Nested macro with no slots failed.") def testDuplicateMacroDefinition (self): self._runCompileTest_ ('
A second macroNo slots here
' ,'[] Macro name one is already defined!' ,"Duplicate macro failed to error.") def testUnballancedMacroDefinition (self): self._runCompileTest_ ('
' ,'[
] TAL/METAL Elements must be balanced - found close tag html expecting div' ,"Unballanced macro tag failed to error.") def testForbiddenEndTagMacroDefinition (self): self._runTest_ ('' ,'\n\n' ,"Macro on a forbidden end tag did not work.") def testMacroTALDefinition (self): self._runTest_ ('

Wibble

' ,'\n

testing

\n' ,"TAL Command on a macro failed.") if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/METALTests/HTMLTests/DefineSlotsTests.py0000664000175200017520000001534512537066732023673 0ustar cms103cms10300000000000000#!/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_ ('
Before blue After
' ,'Nowt white here' ,'
Before white After
' ,"Single slot expansion failed.") def testDoubleSlot (self): self._runTest_ ('
Before blue After red
' ,'Nowt white here black' ,'
Before white After black
' ,"Double slot expansion failed.") def testDoubleOneDefaultSlot (self): self._runTest_ ('
Before blue After red
' ,'Nowt white here purple' ,'
Before white After red
' ,"Double slot with default, expansion failed.") def testDoubleMacroDefaultSlot (self): self._runTest_ ('

Internal macro, colour blue: blue

Before blue After Internal
' ,'Nowt white' ,'
Before white After

Internal macro, colour blue: blue

' ,"Nested macro with same slot name.") def testDoubleMacroDoubleFillSlot (self): self._runTest_ ('

Internal macro, colour blue: blue

Before blue After Internal

pink!

finally outer blue again: blue goes here
' ,'Nowt white' ,'
Before white After

Internal macro, colour blue:

pink!

finally outer blue again: white
' ,"Nested macro with same slot name and slot being used failed.") def testSingleSlotDefaultTAL (self): self._runTest_ ('
Before blue After
' ,'Nowt here' ,'
Before testing After
' ,"Slot defaulting that holds TAL failed.") def testSingleSlotPassedInTAL (self): self._runTest_ ('
Before blue After
' ,'Nowt boo here' ,'
Before Does "this" & work? After
' ,"Slot filled with TAL failed.") if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/METALTests/XMLTests/0000775000175200017520000000000012537322745017742 5ustar cms103cms10300000000000000SimpleTAL-5.2/tests/METALTests/XMLTests/METALNameSpaceTests.py0000664000175200017520000001107512537066677023773 0ustar cms103cms10300000000000000#!/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.compileXMLTemplate (macros) #print "Macro template: " + str (macroTemplate) pageTemplate = simpleTAL.compileXMLTemplate (page) self.context.addGlobal ("site", macroTemplate) self.context.addGlobal ("here", pageTemplate) file = io.StringIO () pageTemplate.expand (self.context, file, outputEncoding="iso-8859-1") 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_ ('
Before blue After
' ,'Nowt white here' ,'\nNowt white here' ,"Single Bind, commands, failed.") def testSingleBindCommands (self): self._runTest_ ('
Before blue After
' ,'Nowt white here' ,'\n
Before white After
' ,"Single Bind, commands, failed.") # Test to ensure that using elements in the metal namespace omits tags def testMETALEmlement (self): self._runTest_ ('Before blue After' ,'Nowt white here' ,'\nBefore white After' ,"METAL namespace does not cause implicit omit-tag") if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/METALTests/XMLTests/DefineMacroTests.py0000664000175200017520000001233112537066646023520 0ustar cms103cms10300000000000000#!/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 try: # Is PyXML's LexicalHandler available? from xml.sax.saxlib import LexicalHandler use_lexical_handler = 1 except ImportError: use_lexical_handler = 0 if (os.path.exists ("logging.ini")): logging.config.fileConfig ("logging.ini") else: logging.basicConfig() pageTemplate = simpleTAL.compileXMLTemplate ("""

Expansion of macro one


""") class DefineMacroTests (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, txt, result, errMsg="Error"): macroTemplate = simpleTAL.compileXMLTemplate (txt) self.context.addGlobal ("site", macroTemplate) file = io.StringIO () pageTemplate.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, pageTemplate)) def _runCompileTest_ (self, txt, result, errMsg="Error"): try: macroTemplate = simpleTAL.compileXMLTemplate (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 testSingleMacroDefinition (self): result = '\n\n
No slots here
\n
\n' self._runTest_ ('
No slots here
' ,result ,"Single macro with no slots failed.") def testTwoMacroDefinition (self): result = '\n\n
No slots here
\n
\n' self._runTest_ ('A second macro
No slots here
' ,result ,"Two macros with no slots failed.") def testNestedMacroDefinition (self): result = '\n\nA second macro\n
\n' self._runTest_ ('
A second macroNo slots here
' ,result ,"Nested macro with no slots failed.") def testDuplicateMacroDefinition (self): self._runCompileTest_ ('
A second macroNo slots here
' ,'[] Macro name one is already defined!' ,"Duplicate macro failed to error.") def testMacroTALDefinition (self): result = '\n\n

testing

\n
\n' self._runTest_ ('

Wibble

' , result ,"TAL Command on a macro failed.") def testSingletonMacros (self): result = '\n\n

Wibble

\n
\n' self._runTest_ ('

Wibble

' ,result ,"Singleton inside slot failed.") if __name__ == '__main__': unittest.main() SimpleTAL-5.2/tests/METALTests/XMLTests/DefineSlotsTests.py0000664000175200017520000001607012537066420023555 0ustar cms103cms10300000000000000#!/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.compileXMLTemplate (macros) #print "Macro template: " + str (macroTemplate) pageTemplate = simpleTAL.compileXMLTemplate (page) self.context.addGlobal ("site", macroTemplate) self.context.addGlobal ("here", pageTemplate) file = io.StringIO () pageTemplate.expand (self.context, file, outputEncoding="iso-8859-1") realResult = file.getvalue() self.assertEqual (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.compileXMLTemplate (txt) except simpleTAL.TemplateParseException as e: self.failUnless (str (e) == result, "%s - \npassed in: %s \ngot back %s \nexpected %s\n\nTemplate: %s" % (errMsg, txt, str(e), result, pageTemplate)) return self.fail ("Expected exception '%s' during compile - but got no exception" % result) def testSingleSlot (self): self._runTest_ ('
Before blue After
' ,'Nowt white here' ,'\n
Before white After
' ,"Single slot expansion failed.") def testDoubleSlot (self): self._runTest_ ('
Before blue After red
' ,'Nowt white here black' ,'\n
Before white After black
' ,"Double slot expansion failed.") def testDoubleOneDefaultSlot (self): self._runTest_ ('
Before blue After red
' ,'Nowt white here purple' ,'\n
Before white After red
' ,"Double slot with default, expansion failed.") def testDoubleMacroDefaultSlot (self): self._runTest_ ('

Internal macro, colour blue: blue

Before blue After Internal
' ,'Nowt white' ,'\n
Before white After

Internal macro, colour blue: blue

' ,"Nested macro with same slot name.") def testDoubleMacroDoubleFillSlot (self): self._runTest_ ('

Internal macro, colour blue: blue

Before blue After Internal

pink!

finally outer blue again: blue goes here
' ,'Nowt white' ,'\n
Before white After

Internal macro, colour blue:

pink!

finally outer blue again: white
' ,"Nested macro with same slot name and slot being used failed.") def testSingleSlotDefaultTAL (self): self._runTest_ ('
Before blue After
' ,'Nowt here' ,'\n
Before testing After
' ,"Slot defaulting that holds TAL failed.") def testSingleSlotPassedInTAL (self): self._runTest_ ('
Before blue After
' ,'Nowt boo here' ,'\n
Before Does "this" & work? After
' ,"Slot filled with TAL failed.") if __name__ == '__main__': unittest.main() SimpleTAL-5.2/runtests.py0000775000175200017520000000363012537066033015471 0ustar cms103cms10300000000000000#!/usr/bin/env python """Regression testing framework Borrowed from http://www.diveintopython.org/ This module will search for scripts in the same directory named XYZtest.py. Each such script should be a test suite that tests a module through PyUnit. (As of Python 2.1, PyUnit is included in the standard library as "unittest".) This script will aggregate all found test suites into one big test suite and run them all at once. * Modified to use os.path.walk to find all the test scripts * Modified to find all python scripts, not just ones of the form *test.py """ import sys, os, re, unittest, imp import logging rootLogger = logging.getLogger () rootLogger.setLevel (logging.CRITICAL) #ensure that the module in this directory is used instead of the system one #or else we would be testing the system one and not the one with the changes :) import sys sys.path.insert(0, os.path.join(os.getcwd(),'lib')) print("System path is: " + str (sys.path)) def path_visitor(files, dirname, names): """Visits each file in the and appends the filename to the given list""" if (dirname.find ("PerformanceTests") > 0): return for name in names: files.append(os.path.join(dirname, name)) def regressionTest(): #Find all the files to run files = [] for curdir, dirlist, filelist in os.walk ("tests"): path_visitor (files, curdir, filelist) test = re.compile(".*\.py$", re.IGNORECASE) files = list(filter(test.search, files)) #load each test into the testsuite modules = [] modCount = 1 for filename in files: modules.append (imp.load_source ("TestModule%s" % str (modCount), filename)) modCount += 1 #modules = map(__import__, moduleNames) load = unittest.defaultTestLoader.loadTestsFromModule suite = [] for module in modules: suite.append (load (module)) return unittest.TestSuite (suite) #return unittest.TestSuite(map(load, modules)) if __name__ == "__main__": unittest.main(defaultTest="regressionTest") SimpleTAL-5.2/examples/0000775000175200017520000000000012537322745015046 5ustar cms103cms10300000000000000SimpleTAL-5.2/examples/basic/0000775000175200017520000000000012537322745016127 5ustar cms103cms10300000000000000SimpleTAL-5.2/examples/basic/basic.html0000664000175200017520000000040012537066033020063 0ustar cms103cms10300000000000000

The title

  • Colour of the rainbow
  • One Two

SimpleTAL-5.2/examples/basic/basic-example.py0000775000175200017520000000473612537066033021223 0ustar cms103cms10300000000000000#!/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! As simple as it gets: 1 - Create a context 2 - Compile a template 3 - Expand the template Module Dependencies: simpleTAL, simpleTALES """ from simpletal import simpleTAL, simpleTALES import sys # Creat the context that is used by the template context = simpleTALES.Context(allowPythonPath=1) # Add a string to the context under the variable title context.addGlobal ("title", "Colours of the rainbow") # A list of strings colours = ["red", "orange", "yellow", "green", "blue", "indigo", "violet"] # Add the list to the context under the variable rainbow context.addGlobal ("rainbow", colours) # Open the template file templateFile = open ("basic.html", 'rt', encoding='utf-8') # Compile a template template = simpleTAL.compileHTMLTemplate (templateFile) # Close the template file templateFile.close() # Expand the template as HTML using this context template.expand (context, sys.stdout, outputEncoding="utf-8") SimpleTAL-5.2/examples/cgi-example/0000775000175200017520000000000012537322745017241 5ustar cms103cms10300000000000000SimpleTAL-5.2/examples/cgi-example/simple-cgi.py0000775000175200017520000000744612537066033021655 0ustar cms103cms10300000000000000#!/usr/bin/python """ Example TAL based CGI 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! A demonstration of how TAL/TALES can be used from a cgi program. Quick instructions: 1 - Copy this file and the two templates ("fields.html" and "results.html") to the cgi-bin directory on your webserver 2 - Ensure that simpleTAL, simpleTALES and DummyLogger are installed in your site-packages directory 3 - Go to http://servername/cgi-bin/simple-cgi.py Module Dependencies: simpleTAL, simpleTALES """ from simpletal import simpleTAL, simpleTALES import cgi, sys, logging logging.basicConfig() class ExampleCGI: def __init__ (self): self.missingFields = {} self.fieldValues = {} self.form = cgi.FieldStorage() self.formValid = 1 self.context = simpleTALES.Context() def buildContext (self, title): self.context.addGlobal ("missingFields", self.missingFields) self.context.addGlobal ("fieldValues", self.fieldValues) self.context.addGlobal ("title", title) def getValue (self, name, mandatory=1): if (name in self.form): self.fieldValues [name] = self.form [name].value elif (mandatory): self.missingFields [name] = 1 self.formValid = 0 def main (self): if ("submit" in self.form): # Recieved the posting, get the name, occupation, and (optional) age self.getValue ("username") self.getValue ("occupation") self.getValue ("age", mandatory=0) if (self.formValid): # Valid form, show the results self.buildContext ("Valid Results") self.expandTemplate ("results.html") else: self.buildContext ("Missing fields") self.expandTemplate ("fields.html") else: self.buildContext ("Enter data") self.expandTemplate ("fields.html") def expandTemplate (self, templateName): # Print out the headers sys.stdout.write ("Content-Type: text/html\n") # HTML is following sys.stdout.write ("\n") # blank line, end of headers # Expand the template and print it out templateFile = open (templateName, 'rt', encoding = "utf-8") template = simpleTAL.compileHTMLTemplate (templateFile) # Close the template file templateFile.close() # Expand the template as HTML using this context template.expand (self.context, sys.stdout) sys.exit (0) # Entry point for the cgi cgiInstance = ExampleCGI() cgiInstance.main() SimpleTAL-5.2/examples/cgi-example/fields.html0000664000175200017520000000133612537066033021373 0ustar cms103cms10300000000000000 Title

Title

Name: (Please fill in)
Occupation: (Please fill in)
Age:
SimpleTAL-5.2/examples/cgi-example/results.html0000664000175200017520000000074312537066033021627 0ustar cms103cms10300000000000000 Title

Title

Name: Your name
Occupation: Your occupation
Age: Your age

SimpleTAL-5.2/examples/elementtree-example/0000775000175200017520000000000012537322745021010 5ustar cms103cms10300000000000000SimpleTAL-5.2/examples/elementtree-example/input.xml0000664000175200017520000000053212537066033022664 0ustar cms103cms10300000000000000 This is a test texttail First Note Second Note Third Note Last Note - worth £3 SimpleTAL-5.2/examples/elementtree-example/basic-example.py0000775000175200017520000000451112537066033024073 0ustar cms103cms10300000000000000#!/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! As simple as it gets: 1 - Create a context 2 - Compile a template 3 - Expand the template Module Dependencies: simpleTAL, simpleTALES """ from simpletal import simpleTAL, simpleTALES, simpleElementTree import sys, logging logging.basicConfig() xmlTree = simpleElementTree.parseFile (file="input.xml") # Create the context that is used by the template context = simpleTALES.Context(allowPythonPath=1) # Add the XML element tree to the context context.addGlobal ("input", xmlTree) # Open the template file templateFile = open ("basic.xml", 'rb') # Compile a template template = simpleTAL.compileXMLTemplate (templateFile) # Close the template file templateFile.close() # Expand the template as HTML using this context template.expand (context, sys.stdout, "utf-8") SimpleTAL-5.2/examples/elementtree-example/basic.xml0000664000175200017520000000055412537066033022612 0ustar cms103cms10300000000000000

Title here

SimpleTAL-5.2/examples/structure-example/0000775000175200017520000000000012537322745020537 5ustar cms103cms10300000000000000SimpleTAL-5.2/examples/structure-example/structure-example.py0000664000175200017520000000503312537066033024576 0ustar cms103cms10300000000000000""" 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! This shows how to include structure into a template, and how multiple templates can be embedded within each other. Module Dependencies: simpleTAL, simpleTALES """ from simpletal import simpleTAL, simpleTALES import sys # Create the context that is used by the template context = simpleTALES.Context() context.addGlobal ("title", "Hello World") context.addGlobal ("author", "Colin Stewart") # A list that contains a dictionary chapters = [{"heading": "Introduction", "text": "Some text here"} ,{"heading": "Details", "text": "Notice tags are preserved."} ] advancedText = 'Structured text can contain other templates like this - written by Me' chapters.append ({"heading": "Advanced", "text": simpleTAL.compileHTMLTemplate (advancedText)}) context.addGlobal ("doc", chapters) templateFile = open ("structure.html", 'rt', encoding = "utf-8") template = simpleTAL.compileHTMLTemplate (templateFile) templateFile.close() template.expand (context, sys.stdout)SimpleTAL-5.2/examples/structure-example/structure.html0000664000175200017520000000034712537066033023464 0ustar cms103cms10300000000000000

The title

Chapter Heading

Text

SimpleTAL-5.2/examples/metal-example/0000775000175200017520000000000012537322745017601 5ustar cms103cms10300000000000000SimpleTAL-5.2/examples/metal-example/page.html0000664000175200017520000000026512537066033021401 0ustar cms103cms10300000000000000

The title

SimpleTAL!
SimpleTAL-5.2/examples/metal-example/macro.html0000664000175200017520000000033212537066033021561 0ustar cms103cms10300000000000000

The title

This macro is brought to you by the colour blue. Now you know.

SimpleTAL-5.2/examples/metal-example/metal-example.py0000775000175200017520000000456512537066033022716 0ustar cms103cms10300000000000000#!/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.txt0000664000175200017520000000273512537111757015061 0ustar cms103cms10300000000000000SimpleTAL 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/0000775000175200017520000000000012537322745013776 5ustar cms103cms10300000000000000SimpleTAL-5.2/lib/simpletal/0000775000175200017520000000000012537322745015770 5ustar cms103cms10300000000000000SimpleTAL-5.2/lib/simpletal/simpleTALUtils.py0000664000175200017520000002102012537066033021203 0ustar cms103cms10300000000000000""" 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 ('') 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.py0000664000175200017520000004550612537117414020431 0ustar cms103cms10300000000000000""" 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.py0000664000175200017520000015744412537111702020200 0ustar cms103cms10300000000000000""" 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 ('') 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, '')) return else: # We are suppressing the output of this tag, so just return return else: # We have a different tag, which means something like
which never closes is in # between us and the real tag. # If the tag that we did pop off has a command though it means un-balanced TAL tags! if (endTagSymbol is not None): # ERROR msg = "TAL/METAL Elements must be balanced - found close tag %s expecting %s" % (tag[0], oldTag[0]) self.log.error (msg) raise TemplateParseException (self.tagAsText(oldTag), msg) self.log.error ("Close tag %s found with no corresponding open tag." % tag[0]) raise TemplateParseException ("" % tag[0], "Close tag encountered with no corresponding open tag.") def parseStartTag (self, tag, attributes, singletonElement=0): # Note down the tag we are handling, it will be used for error handling during # compilation self.currentStartTag = (tag, attributes) # Look for tal/metal attributes foundTALAtts = [] foundMETALAtts = [] foundCommandsArgs = {} cleanAttributes = [] originalAttributes = {} tagProperties = {} popTagFuncList = [] TALElementNameSpace = 0 prefixToAdd = "" tagProperties ['singletonTag'] = singletonElement # Determine whether this element is in either the METAL or TAL namespace if (tag.find (':') > 0): # We have a namespace involved, so let's look to see if its one of ours namespace = tag[0:tag.find (':')] if (namespace == self.metal_namespace_prefix): TALElementNameSpace = 1 prefixToAdd = self.metal_namespace_prefix +":" elif (namespace == self.tal_namespace_prefix): TALElementNameSpace = 1 prefixToAdd = self.tal_namespace_prefix +":" if (TALElementNameSpace): # We should treat this an implicit omit-tag foundTALAtts.append (TAL_OMITTAG) # Will go to default, i.e. yes foundCommandsArgs [TAL_OMITTAG] = "" for att, value in attributes: originalAttributes [att] = value if (TALElementNameSpace and not att.find (':') > 0): # This means that the attribute name does not have a namespace, so use the prefix for this tag. commandAttName = prefixToAdd + att else: commandAttName = att self.log.debug ("Command name is now %s" % commandAttName) if (att[0:5] == "xmlns"): # We have a namespace declaration. prefix = att[6:] if (value == METAL_NAME_URI): # It's a METAL namespace declaration if (len (prefix) > 0): self.metal_namespace_prefix_stack.append (self.metal_namespace_prefix) self.setMETALPrefix (prefix) # We want this function called when the scope ends popTagFuncList.append (self.popMETALNamespace) else: # We don't allow METAL/TAL to be declared as a default msg = "Can not use METAL name space by default, a prefix must be provided." raise TemplateParseException (self.tagAsText (self.currentStartTag), msg) elif (value == TAL_NAME_URI): # TAL this time if (len (prefix) > 0): self.tal_namespace_prefix_stack.append (self.tal_namespace_prefix) self.setTALPrefix (prefix) # We want this function called when the scope ends popTagFuncList.append (self.popTALNamespace) else: # We don't allow METAL/TAL to be declared as a default msg = "Can not use TAL name space by default, a prefix must be provided." raise TemplateParseException (self.tagAsText (self.currentStartTag), msg) else: # It's nothing special, just an ordinary namespace declaration cleanAttributes.append ((att, value)) elif (commandAttName in self.tal_attribute_map): # It's a TAL attribute cmnd = self.tal_attribute_map [commandAttName] if (cmnd == TAL_OMITTAG and TALElementNameSpace): self.log.warning ("Supressing omit-tag command present on TAL or METAL element") else: foundCommandsArgs [cmnd] = value foundTALAtts.append (cmnd) elif (commandAttName in self.metal_attribute_map): # It's a METAL attribute cmnd = self.metal_attribute_map [commandAttName] foundCommandsArgs [cmnd] = value foundMETALAtts.append (cmnd) else: cleanAttributes.append ((att, value)) tagProperties ['popFunctionList'] = popTagFuncList # This might be just content if ((len (foundTALAtts) + len (foundMETALAtts)) == 0): # Just content, add it to the various stacks self.addTag ((tag, cleanAttributes), tagProperties) return # Create a symbol for the end of the tag - we don't know what the offset is yet self.endTagSymbol += 1 tagProperties ['endTagSymbol'] = self.endTagSymbol # Sort the METAL commands foundMETALAtts.sort() # Sort the tags by priority foundTALAtts.sort() # We handle the METAL before the TAL allCommands = foundMETALAtts + foundTALAtts firstTag = 1 for talAtt in allCommands: # Parse and create a command for each cmnd = self.commandHandler [talAtt](foundCommandsArgs[talAtt]) if (cmnd is not None): if (firstTag): # The first one needs to add the tag firstTag = 0 tagProperties ['originalAtts'] = originalAttributes tagProperties ['command'] = cmnd self.addTag ((tag, cleanAttributes), tagProperties) else: # All others just append self.addCommand(cmnd) if (firstTag): tagProperties ['originalAtts'] = originalAttributes tagProperties ['command'] = (TAL_STARTTAG, (tag, singletonElement)) self.addTag ((tag, cleanAttributes), tagProperties) else: # Add the start tag command in as a child of the last TAL command self.addCommand((TAL_STARTTAG, (tag,singletonElement))) def parseEndTag (self, tag): """ Just pop the tag and related commands off the stack. """ self.popTag ((tag,None)) def parseData (self, data): # Just add it as an output self.addCommand((TAL_OUTPUT, data)) def compileCmdDefine (self, argument): # Compile a define command, resulting argument is: # [(isLocalFlag (Y/n), variableName, variablePath),...] # Break up the list of defines first commandArgs = [] # We only want to match semi-colons that are not escaped argumentSplitter = re.compile ('(?2 elements means a local|global flag if (len (stmtBits) > 2): if (stmtBits[0] == 'global'): isLocal = 0 varName = stmtBits[1] expression = ' '.join (stmtBits[2:]) elif (stmtBits[0] == 'local'): varName = stmtBits[1] expression = ' '.join (stmtBits[2:]) else: # Must be a space in the expression that caused the >3 thing varName = stmtBits[0] expression = ' '.join (stmtBits[1:]) else: # Only two bits varName = stmtBits[0] expression = ' '.join (stmtBits[1:]) commandArgs.append ((isLocal, varName, expression)) return (TAL_DEFINE, commandArgs) def compileCmdCondition (self, argument): # Compile a condition command, resulting argument is: # path, endTagSymbol # Sanity check if (len (argument) == 0): # No argument passed msg = "No argument passed! condition commands must be of the form: 'path'" self.log.error (msg) raise TemplateParseException (self.tagAsText (self.currentStartTag), msg) return (TAL_CONDITION, (argument, self.endTagSymbol)) def compileCmdRepeat (self, argument): # Compile a repeat command, resulting argument is: # (varname, expression, endTagSymbol) attProps = argument.split (' ') if (len (attProps) < 2): # Error, badly formed repeat command msg = "Badly formed repeat command '%s'. Repeat commands must be of the form: 'localVariable path'" % argument self.log.error (msg) raise TemplateParseException (self.tagAsText (self.currentStartTag), msg) varName = attProps [0] expression = " ".join (attProps[1:]) return (TAL_REPEAT, (varName, expression, self.endTagSymbol)) def compileCmdContent (self, argument, replaceFlag=0): # Compile a content command, resulting argument is # (replaceFlag, structureFlag, expression, endTagSymbol) # Sanity check if (len (argument) == 0): # No argument passed msg = "No argument passed! content/replace commands must be of the form: 'path'" self.log.error (msg) raise TemplateParseException (self.tagAsText (self.currentStartTag), msg) structureFlag = 0 attProps = argument.split (' ') if (len(attProps) > 1): if (attProps[0] == "structure"): structureFlag = 1 express = " ".join (attProps[1:]) elif (attProps[1] == "text"): structureFlag = 0 express = " ".join (attProps[1:]) else: # It's not a type selection after all - assume it's part of the path express = argument else: express = argument return (TAL_CONTENT, (replaceFlag, structureFlag, express, self.endTagSymbol)) def compileCmdReplace (self, argument): return self.compileCmdContent (argument, replaceFlag=1) def compileCmdAttributes (self, argument): # Compile tal:attributes into attribute command # Argument: [(attributeName, expression)] # Break up the list of attribute settings first commandArgs = [] # We only want to match semi-colons that are not escaped argumentSplitter = re.compile ('(?") else: result.append (">") return "".join (result) def handle_startendtag (self, tag, attributes): self.handle_starttag (tag, attributes) if not (tag.upper() in HTML_FORBIDDEN_ENDTAG): self.handle_endtag(tag) def handle_starttag (self, tag, attributes): self.log.debug ("Received Start Tag: " + tag + " Attributes: " + str (attributes)) atts = [] for att, attValue in attributes: # We need to spot empty tal:omit-tags if (attValue is None): if (att == self.tal_namespace_omittag): atts.append ((att, "")) else: atts.append ((att, att)) elif not HTML_ENTITIES_PRE_EXPANDED: # Expand any SGML entity references or char references goodAttValue = [] last = 0 match = ENTITY_REF_REGEX.search (attValue) while (match): goodAttValue.append (attValue[last:match.start()]) ref = attValue[match.start():match.end()] if (ref.startswith ('&#')): # A char reference if (ref[2] in ['x', 'X']): # Hex refValue = int (ref[3:-1], 16) else: refValue = int (ref[2:-1]) goodAttValue.append (chr (refValue)) else: # A named reference. goodAttValue.append (chr (sgmlentitynames.htmlNameToUnicodeNumber.get (ref[1:-1], 65533))) last = match.end() match = ENTITY_REF_REGEX.search (attValue, last) goodAttValue.append (attValue [last:]) atts.append ((att, "".join (goodAttValue))) else: atts.append ((att, attValue)) if (tag.upper() in HTML_FORBIDDEN_ENDTAG): # This should have no end tag, so we just do the start and suppress the end self.parseStartTag (tag, atts) self.log.debug ("End tag forbidden, generating close tag with no output.") self.popTag ((tag, None), omitTagFlag=1) else: self.parseStartTag (tag, atts) def handle_endtag (self, tag): self.log.debug ("Recieved End Tag: " + tag) if (tag.upper() in HTML_FORBIDDEN_ENDTAG): self.log.warning ("HTML 4.01 forbids end tags for the %s element" % tag) else: # Normal end tag self.popTag ((tag, None)) def handle_data (self, data): self.parseData (html.escape (data, quote=False)) # These two methods are required so that we expand all character and entity references prior to parsing the template. def handle_charref (self, ref): self.log.debug ("Got Ref: %s", ref) self.parseData (chr (int (ref))) def handle_entityref (self, ref): self.log.debug ("Got Ref: %s", ref) # Use handle_data so that <&> are re-encoded as required. self.handle_data( chr (sgmlentitynames.htmlNameToUnicodeNumber.get (ref, 65533))) # Handle document type declarations def handle_decl (self, data): self.parseData ('' % data) # Pass comments through un-affected. def handle_comment (self, data): self.parseData ('' % data) def handle_pi (self, data): self.log.debug ("Recieved processing instruction.") self.parseData ('' % data) def report_unbalanced (self, tag): self.log.warning ("End tag %s present with no corresponding open tag.") def getTemplate (self): template = HTMLTemplate (self.commandList, self.macroMap, self.symbolLocationTable, minimizeBooleanAtts = self.minimizeBooleanAtts) return template class XMLTemplateCompiler (TemplateCompiler, xml.sax.handler.ContentHandler, xml.sax.handler.DTDHandler, LexicalHandler): def __init__ (self): TemplateCompiler.__init__ (self) xml.sax.handler.ContentHandler.__init__ (self) self.doctype = None self.log = logging.getLogger ("simpleTAL.XMLTemplateCompiler") self.singletonElement = 0 def parseTemplate (self, templateFile): self.ourParser = xml.sax.make_parser() self.log.debug ("Setting features of parser") try: self.ourParser.setFeature (xml.sax.handler.feature_external_ges, False) self.log.debug ("Set SAX Handler feature OK") except: pass if use_lexical_handler: self.ourParser.setProperty(xml.sax.handler.property_lexical_handler, self) self.ourParser.setContentHandler (self) self.ourParser.setDTDHandler (self) self.ourParser.parse (templateFile) def startDTD(self, name, public_id, system_id): self.log.debug ("Recieved DOCTYPE: " + name + " public_id: " + public_id + " system_id: " + system_id) if public_id: self.doctype = '' % (name, public_id, system_id,) else: self.doctype = '' % (name, system_id,) def startElement (self, tag, attributes): self.log.debug ("Recieved Real Start Tag: " + tag + " Attributes: " + str (attributes)) try: xmlText = self.ourParser.getProperty (xml.sax.handler.property_xml_string) if (isinstance (xmlText, str)): # Once issue 6686 is solved this should allow singletons to be detected if (SINGLETON_XML_REGEX.match (xmlText)): # This is a singleton! self.singletonElement=1 else: if (SINGLETON_BYTES_XML_REGEX.match (xmlText)): # This is a singleton! self.singletonElement = 1 except xml.sax.SAXException as e: # Parser doesn't support this property pass # Convert attributes into a list of tuples atts = [] for att in attributes.getNames(): self.log.debug ("Attribute name %s has value %s" % (att, attributes[att])) atts.append ((att, attributes [att])) self.parseStartTag (tag, atts, singletonElement=self.singletonElement) def endElement (self, tag): self.log.debug ("Recieved Real End Tag: " + tag) self.parseEndTag (tag) self.singletonElement = 0 def skippedEntity (self, name): self.log.info ("Recieved skipped entity: %s" % name) self.characters( chr (sgmlentitynames.htmlNameToUnicodeNumber.get (name, 65533))) def characters (self, data): #self.log.debug ("Recieved Real Data: " + data) # Escape any data we recieve - we don't want any: <&> in there. self.parseData (html.escape (data, quote=False)) def processingInstruction (self, target, data): self.log.debug ("Recieved processing instruction.") self.parseData ('' % (target, data)) def comment (self, data): # This is only called if your XML parser supports the LexicalHandler interface. self.parseData ('' % data) def getTemplate (self): template = XMLTemplate (self.commandList, self.macroMap, self.symbolLocationTable, self.doctype) return template def compileHTMLTemplate (template, minimizeBooleanAtts = 0): """ Reads the templateFile and produces a compiled template. To use the resulting template object call: template.expand (context, outputFile) """ if (isinstance (template, str)): # It's a string! templateFile = io.StringIO (template) else: templateFile = template compiler = HTMLTemplateCompiler() compiler.parseTemplate (templateFile, minimizeBooleanAtts) return compiler.getTemplate() def compileXMLTemplate (template): """ Reads the templateFile and produces a compiled template. To use the resulting template object call: template.expand (context, outputFile) """ if (isinstance (template, str)): # It's a string! templateFile = io.StringIO (template) elif (isinstance (template, bytes)): templateFile = io.BytesIO (template) else: templateFile = template compiler = XMLTemplateCompiler() compiler.parseTemplate (templateFile) return compiler.getTemplate() SimpleTAL-5.2/lib/simpletal/sgmlentitynames.py0000664000175200017520000001545612537066033021573 0ustar cms103cms10300000000000000""" simpleTAL 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! A dictionary of HTML entity names to their decimal value. """ htmlNameToUnicodeNumber = {"nbsp": 160 ,"iexcl": 161 ,"cent": 162 ,"pound": 163 ,"curren": 164 ,"yen": 165 ,"brvbar": 166 ,"sect": 167 ,"uml": 168 ,"copy": 169 ,"ordf": 170 ,"laquo": 171 ,"not": 172 ,"shy": 173 ,"reg": 174 ,"macr": 175 ,"deg": 176 ,"plusmn": 177 ,"sup2": 178 ,"sup3": 179 ,"acute": 180 ,"micro": 181 ,"para": 182 ,"middot": 183 ,"cedil": 184 ,"sup1": 185 ,"ordm": 186 ,"raquo": 187 ,"frac14": 188 ,"frac12": 189 ,"frac34": 190 ,"iquest": 191 ,"Agrave": 192 ,"Aacute": 193 ,"Acirc": 194 ,"Atilde": 195 ,"Auml": 196 ,"Aring": 197 ,"AElig": 198 ,"Ccedil": 199 ,"Egrave": 200 ,"Eacute": 201 ,"Ecirc": 202 ,"Euml": 203 ,"Igrave": 204 ,"Iacute": 205 ,"Icirc": 206 ,"Iuml": 207 ,"ETH": 208 ,"Ntilde": 209 ,"Ograve": 210 ,"Oacute": 211 ,"Ocirc": 212 ,"Otilde": 213 ,"Ouml": 214 ,"times": 215 ,"Oslash": 216 ,"Ugrave": 217 ,"Uacute": 218 ,"Ucirc": 219 ,"Uuml": 220 ,"Yacute": 221 ,"THORN": 222 ,"szlig": 223 ,"agrave": 224 ,"aacute": 225 ,"acirc": 226 ,"atilde": 227 ,"auml": 228 ,"aring": 229 ,"aelig": 230 ,"ccedil": 231 ,"egrave": 232 ,"eacute": 233 ,"ecirc": 234 ,"euml": 235 ,"igrave": 236 ,"iacute": 237 ,"icirc": 238 ,"iuml": 239 ,"eth": 240 ,"ntilde": 241 ,"ograve": 242 ,"oacute": 243 ,"ocirc": 244 ,"otilde": 245 ,"ouml": 246 ,"divide": 247 ,"oslash": 248 ,"ugrave": 249 ,"uacute": 250 ,"ucirc": 251 ,"uuml": 252 ,"yacute": 253 ,"thorn": 254 ,"yuml": 255 ,"fnof": 402 ,"Alpha": 913 ,"Beta": 914 ,"Gamma": 915 ,"Delta": 916 ,"Epsilon": 917 ,"Zeta": 918 ,"Eta": 919 ,"Theta": 920 ,"Iota": 921 ,"Kappa": 922 ,"Lambda": 923 ,"Mu": 924 ,"Nu": 925 ,"Xi": 926 ,"Omicron": 927 ,"Pi": 928 ,"Rho": 929 ,"Sigma": 931 ,"Tau": 932 ,"Upsilon": 933 ,"Phi": 934 ,"Chi": 935 ,"Psi": 936 ,"Omega": 937 ,"alpha": 945 ,"beta": 946 ,"gamma": 947 ,"delta": 948 ,"epsilon": 949 ,"zeta": 950 ,"eta": 951 ,"theta": 952 ,"iota": 953 ,"kappa": 954 ,"lambda": 955 ,"mu": 956 ,"nu": 957 ,"xi": 958 ,"omicron": 959 ,"pi": 960 ,"rho": 961 ,"sigmaf": 962 ,"sigma": 963 ,"tau": 964 ,"upsilon": 965 ,"phi": 966 ,"chi": 967 ,"psi": 968 ,"omega": 969 ,"thetasym": 977 ,"upsih": 978 ,"piv": 982 ,"bull": 8226 ,"hellip": 8230 ,"prime": 8242 ,"Prime": 8243 ,"oline": 8254 ,"frasl": 8260 ,"weierp": 8472 ,"image": 8465 ,"real": 8476 ,"trade": 8482 ,"alefsym": 8501 ,"larr": 8592 ,"uarr": 8593 ,"rarr": 8594 ,"darr": 8595 ,"harr": 8596 ,"crarr": 8629 ,"lArr": 8656 ,"uArr": 8657 ,"rArr": 8658 ,"dArr": 8659 ,"hArr": 8660 ,"forall": 8704 ,"part": 8706 ,"exist": 8707 ,"empty": 8709 ,"nabla": 8711 ,"isin": 8712 ,"notin": 8713 ,"ni": 8715 ,"prod": 8719 ,"sum": 8721 ,"minus": 8722 ,"lowast": 8727 ,"radic": 8730 ,"prop": 8733 ,"infin": 8734 ,"ang": 8736 ,"and": 8743 ,"or": 8744 ,"cap": 8745 ,"cup": 8746 ,"int": 8747 ,"there4": 8756 ,"sim": 8764 ,"cong": 8773 ,"asymp": 8776 ,"ne": 8800 ,"equiv": 8801 ,"le": 8804 ,"ge": 8805 ,"sub": 8834 ,"sup": 8835 ,"nsub": 8836 ,"sube": 8838 ,"supe": 8839 ,"oplus": 8853 ,"otimes": 8855 ,"perp": 8869 ,"sdot": 8901 ,"lceil": 8968 ,"rceil": 8969 ,"lfloor": 8970 ,"rfloor": 8971 ,"lang": 9001 ,"rang": 9002 ,"loz": 9674 ,"spades": 9824 ,"clubs": 9827 ,"hearts": 9829 ,"diams": 9830 ,"quot": 34 ,"amp": 38 ,"lt": 60 ,"gt": 62 ,"OElig": 338 ,"oelig": 339 ,"Scaron": 352 ,"scaron": 353 ,"Yuml": 376 ,"circ": 710 ,"tilde": 732 ,"ensp": 8194 ,"emsp": 8195 ,"thinsp": 8201 ,"zwnj": 8204 ,"zwj": 8205 ,"lrm": 8206 ,"rlm": 8207 ,"ndash": 8211 ,"mdash": 8212 ,"lsquo": 8216 ,"rsquo": 8217 ,"sbquo": 8218 ,"ldquo": 8220 ,"rdquo": 8221 ,"bdquo": 8222 ,"dagger": 8224 ,"Dagger": 8225 ,"permil": 8240 ,"lsaquo": 8249 ,"rsaquo": 8250 ,"euro": 8364} SimpleTAL-5.2/lib/simpletal/__init__.py0000664000175200017520000000002412537112021020055 0ustar cms103cms10300000000000000__version__ = "5.2" SimpleTAL-5.2/lib/simpletal/FixedHTMLParser.py0000664000175200017520000000360312537066033021240 0ustar cms103cms10300000000000000""" Fixed up HTMLParser 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 simpletal import html.parser class HTMLParser (html.parser.HTMLParser): def unescape(self, s): # Just return the data - we don't partially unescaped data! return s SimpleTAL-5.2/documentation/0000775000175200017520000000000012537322745016101 5ustar cms103cms10300000000000000SimpleTAL-5.2/documentation/html/0000775000175200017520000000000012537322745017045 5ustar cms103cms10300000000000000SimpleTAL-5.2/documentation/html/api-simpletal.html0000664000175200017520000000702512537066033022473 0ustar cms103cms10300000000000000 SimpleTAL API: simpleTAL Module

SimpleTAL API: simpleTAL Module

Documentation on how to use the simpleTAL Module.

simpleTAL

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.

compileHTMLTemplate (template, minimizeBooleanAtts=0)

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.

compileXMLTemplate (template)

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.

Template Instances

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).

Back to SimpleTAL API

PubTal Version

SimpleTAL-5.2/documentation/html/index.html0000664000175200017520000000273212537066033021041 0ustar cms103cms10300000000000000 SimpleTAL

SimpleTAL

Welcome 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.html0000664000175200017520000001617312537066033021066 0ustar cms103cms10300000000000000 Notes on SimpleTAL

Notes on SimpleTAL

Notes, known limitations, and differences between SimpleTAL and Zope's ZPT.

Upgrading from SimpleTAL 4.x to 5.x

Porting SimpleTAL to Python 3 has introduced a number of small changes:

  • simpleTALUtils.HTMLStructureCleaner is not available from SimpleTAL 5 onwards.  The sgmlib library that it utilised was removed in Python 3.
  • simpleTAL.compileHTMLTemplate no longer accepts the inputEncoding argument.  All HTML templates must be either Strings or file objects that produce Strings.
  • compileDOMTemplate is not available from SimpleTAL 5 onwards.  The pyxml library that provides the Dom2SaxParser implementation is not yet available in Python 3.
  • simpleTALUtils.ExpandMacros defaults to utf-8 for outputEncoding rather than iso-8859-1.
  • simpleTALUtils.FastStringOutput has been removed in favour of the new io.StringIO which is faster.
  • simpleTALUtils.TemplateCache.getTemplate now defaults to utf-8 rather than iso-8859-1 for HTML templates.

Notes

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.

HTML and XHTML Templates

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:

  • Allow TAL attributes on all HTML elements that forbid close tags, and process them despite the lack of close tag
  • When compiling a HTML template issue a warning if a close tag is present for elements that are forbidden to have close tags.
  • Suppress the output of close tags for elements that are forbidden to have close tags.

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.

Character set encoding

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.

Structured Content

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.

Object Attributes versus Key Values

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()'.

Using < and > in TAL Paths

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 &lt; b">Conditional Text</div>
instead of: <div tal:condition="python: a < b">Conditional Text</div>

Known limitations

  1. Repeat Variables do not support 'first' and 'last'.
  2. When using 'not:' on an empty expression the result will be true rather than an error.
  3. Path type 'python:' is not supported by default.  You can enable this by passing allowPythonPath=1 to the Context constructor.  Note that this should only be used when the authors of the templates are completely trusted, the code included in the 'python:' path can do anything.
  4. TAL markup "on-error" is not yet supported.
  5. HTML Templates will have duplicate attributes if an attribute is added using "tal:attributes" and the name is in upper case.  The cause of this is the HTMLParser implementation, which always converts attributes to lower case.

Known differences

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.

Back to SimpleTAL

PubTal Version

SimpleTAL-5.2/documentation/html/api-simpleelementtree.html0000664000175200017520000000556512537066033024233 0ustar cms103cms10300000000000000 SimpleTAL API: simpleElementTree Module.

SimpleTAL API: simpleElementTree Module.

Documentation on how to use the simpleElementTree Module.

simpleElementTree

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.

parseFile (file)

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)

ElementTree Paths

The Context variable provided by parseFile provides the following syntax for path access in TAL:

  • Accessing the variable directly returns the Text value for this node.
  • Accessing variable/find/path returns the first node to match the path, as supported by ElementTree (see XPath Support in ElementTree).
  • Accessing variable/findall/path returns a list of nodes that match the path, as supported by ElementTree (see XPath Support in ElementTree).
  • Accessing variable@name returns the XML attribute "name".
  • Accessing variable/anotherElement is a short-cut for variable/find/anotherElement.

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.html0000664000175200017520000002561412537066033021611 0ustar cms103cms10300000000000000 TAL/TALES & METAL Reference Guide

TAL/TALES & METAL Reference Guide

A guide to using TAL, TALES, and METAL.

Introduction

This is a simple reference guide to the TAL and TALES languages.  Formal language specifications are hosted by Zope: TAL, TALES, and METAL.

TAL Commands

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>

tal:define

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">

tal:condition

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>

tal:repeat

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:

  1. index - Iteration number starting from zero

  2. number - Iteration number starting from one

  3. even - True if this is an even iteration

  4. odd - True if this is an odd iteration

  5. start - True if this is the first item in the sequence

  6. end - True if this is the last item in the sequence.  For iterators this is never true

  7. length - The length of the sequence.  For iterators this is maxint as the length of an iterator is unknown

  8. letter - The lower case letter for this iteration, starting at "a"

  9. Letter - Upper case version of letter

  10. roman - Iteration number in Roman numerals, starting at i

  11. 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>

tal:content

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>

tal:replace

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>

tal:attributes

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>

tal:omit-tag

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>

TALES Expressions

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.

path

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:

  1. nothing - acts as None in Python

  2. default - keeps the existing value of the node (tag content or attribute value)

  3. options - the dictionary of values passed to the template (through the Context __init__ method)

  4. repeat - access the current repeat variable (see tal:repeat)

  5. attrs - a dictionary of original attributes of the current tag

  6. CONTEXTS - a dictionary containing all of the above

exists

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>

nocall

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>

not

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>

string

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>

python

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 &lt; 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) &gt; 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 Macro Language

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.

metal:define-macro

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>

metal:use-macro

Syntax: metal:use-macro="expression"

Description:  Evaluates "expression" and uses this as a macro.

Example:  <div metal:use-macro="footer"></div>

metal:define-slot

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>

metal:fill-slot

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.html0000664000175200017520000000401712537066033020501 0ustar cms103cms10300000000000000 SimpleTAL API

SimpleTAL API

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

PubTal Version

SimpleTAL-5.2/documentation/html/api-simpletales.html0000664000175200017520000000723612537066033023027 0ustar cms103cms10300000000000000 SimpleTAL API: simpleTALES Module.

SimpleTAL API: simpleTALES Module.

Documentation on how to use the simpleTALES Module.

simpleTALES

The only external class in this module is the Context class.

Context ([options] [,allowPythonPath])

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.

Context.addGlobal (name, value)

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.

PathFunctionVariable (callableObject)

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.

CachedFuncResult (callableObject)

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.

clearCache ()

Clears the cache.  Use this to clear the cache between multiple template expansions if the callable should be executed once per template expansion.

Back to SimpleTAL API

PubTal Version

SimpleTAL-5.2/documentation/html/api-simpletalutils.html0000664000175200017520000000475612537066033023564 0ustar cms103cms10300000000000000 SimpleTAL API: simpleTALUtils Module.

SimpleTAL API: simpleTALUtils Module.

Documentation on how to use the simpleTALUtils Module.

simpleTALUtils

This module holds optional classes and functions that might be of use while using SimpleTAL, but are not required by SimpleTAL directly.

def ExpandMacros (context, template, outputEncoding="utf-8")

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.

TemplateCache

This class implements a cache for compiled templates which automatically invalidates entries when their template file changes.  The instance has one public method: getTemplate

getTemplate (name, inputEncoding="utf-8")

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.

getXMLTemplate (name)

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.

Back to SimpleTAL API

PubTal Version

SimpleTAL-5.2/documentation/templates/0000775000175200017520000000000012537322745020077 5ustar cms103cms10300000000000000SimpleTAL-5.2/documentation/templates/template.html0000664000175200017520000000174112537066033022576 0ustar cms103cms10300000000000000 Title

Title

Subject

Body

Version

SimpleTAL-5.2/documentation/style/0000775000175200017520000000000012537322745017241 5ustar cms103cms10300000000000000SimpleTAL-5.2/documentation/style/site.css0000664000175200017520000000203512537066033020712 0ustar cms103cms10300000000000000.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.config0000664000175200017520000000064112537066033022135 0ustar  cms103cms10300000000000000# 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/0000775000175200017520000000000012537322745016670 5ustar  cms103cms10300000000000000SimpleTAL-5.2/documentation/src/api.txt0000664000175200017520000000265312537066033020203 0ustar  cms103cms10300000000000000title: 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.sxw0000664000175200017520000004226512537066033021312 0ustar cms103cms10300000000000000PK>19mimetypeapplication/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(na8\3Y!璇4 %d+K@0f<|1qJӴԌǁd(#rULD}Ou :gzґVR(\qv52O.fYn:&cLh@$ YһoaFEZihB~dҲ%g""Y~hUm؎K[K5߰h I[7SW4v@@x9壱&5a}]su돳Ng42λBy8˾n5_ۧxmH#3oxixO`inR7w0ᲶKXY2Z63ߦ+H ephnDaǰ(Tat$i6 qm D43\ԜB.IqOo.l4$MASLcΜ7SJ`ztK]La҅ADp3 QNAmIQoO(@E5qURq4=XEKKf#EAQ9zY&|?M)0i'Gt> Y0ûh3HNA':8eݙW2.nwp?J T+n:z@22J &`}חsˬ'fs NqU*xͮιf;)Z~w|vxp^{cSzKc9oȌ2>*d8{3K{'~HZ p1@RD `$C; m)y81Sd TQDll"fj /}18Wг֒r͔չHh: `'"%_!Ot[vh:=sK)NYįur= 1 :5`aw0 vT_0J`rORMoE b@OvI̭R|v?5f0ާ}r/艮h3D]@tRT*r<ֆ1rgY V{iFfvW`rzq &b/}Iqsс:Ҋ@o~$?M6!Aj^2X@`HayKM㞯77N=`!k@dgBL3yQR73mpkCl}D7P1 L Utp\gi=\Om!B < <2(7ݠwqozEbd`S1⩃ПX a`b~a|븷m hm|8'tց! ],T5 DBX$p\*(ϻlV{v|r sibNoyc%JZՐj!*rk#ތq8ڝh(X`$OĮX-p鰡G̸q<{Aӈ݀Az]U0C)W&E)J:ƒc:K *b1MP#^nťBm4YaӶ3zk =Y=mKilq9)4Ֆt+Iґ &Oq\2iAl2ZilɈ.) 0-6C K_WEFk{F✖|2/zahZo7 MϚoI5+ldCL3ldRe>YmyXKwY`Őg(sCT]28 e [% :&ᤷnw+t X' E}o}/"e\O[ﱘ \s."ph?ṔTXC hk {ퟃs&ybe <"VWl1XTn$4: [EY`_%gesiەSh)rć."Zf]R;EjH/ɕ_ϳgVl}8#-鹒a1F7Č[C'p$;:ct%n*Z&= 32-7P/<U;s<#g̫A\$ӓ z ?c{~̼{L-x~/Jam=o~sN˳s V}/7Tc{6>IhKX-vg- |oB%ND(yU{Ujs-'>8ƞD > .+hJ Pi./~0&P+JDE29w# &Uaתܶc`=2 V#ZӨvP2GJ_?*WF{W6fb1:NL.a*bM6)r*/N򇰝 ,K<*$vАRͯ|:ΓʴySvlDxO Wwr:53nMr?ET } Kzx#!<6u+ܕini*MG+ǦXYU"SnŹICH[P(0(txaq25s2)3sმKTWfY96111X*k,E>TG.ݱ*&x$IOn_[8 5@/,Vܥ3Nb.|a# ԥ ߮SwBYdf]:<9|5f%_,jcv-e-_D9>s/u Gt@C.Җ2m yREe:zV-FF5)x/.DPQcbh|Ih(9u_߮<a%K /Ad$5eQe5-Dز]xlZP.J_+Lk1bX O:F v;' gR]@ZMڽ_0{,f~jJ D6ׄc'˻nP`?P8|qةMR𸍯 ge7(pPSC |*^0L=T$\$2ߪ8~eΓ7][9c .n^-a5XD*)Orl;7)y 4T{Ahߍ &\خݛA cnW>-.Y,ZDNA;h"NPKLM7`oPK> layout-cachecd`d(d``d``1 a w#PKL=-PK> styles.xmlZs_a} EQK=]&].c'+DB"$_@K Eَ'ө<#y1ѵ澇iBwkޱx1OLbek?X!+05C3wb>_MгGa(Zj0ڜptE+ⷬFJ#r.xj] 5#qE3JgX[, -6L|DΥ̾E">hL}1URtr=/<ebNq N`{ 豘H[x,D! Wb|t7!kĶktŐ 8(ǐNJMU4[a<sEO'Թ w:=o:eU;l~s &(&|԰ 0[_@~CmN^t&su,}✆cLm-*L+-w·%6\+` Ap\U -#"Fq C.tq; +5S( S@<ͲR23meEZfB ~%|) jkX@B:ui[Rʪff6[7!&W-T' c`S=J@]b`i_GKXY eY^d8:4 ]*aYuzJ#SWҧ"TfA|ya%ei E΅5AH @/x5 ,=)ZRpj wƥ_Gc|mG3RPY۸ZR=H7Gkjø rAPV b"IE T쀞9mA+9n!!@-u{aY0P_Une2V:v0W9݌m4TRc3&U[^[pb 8^\/i@ĊiuI=r~eEͿԁ9.y5ϱ2a3MP+n!&ئX5ս>Q݋kIAh_n[@?'3ώ=گ\z+Y{[Z}!v9ٌo;vxLnu#u>2&)]L/+R,rt:~v0ZxkAc j|s 1O̡n<֗%5'u7goZg()l_C_3ӧQ1*]+,(a M_?hx`%MIqX]U\,C{ qV͞vf+\(5Nx;QWo'DݼNۉZh*R)/nɮn(áBԶ;⁆_Tk޾'`C̍~km]irXi8]V9svzFʨO?5Q_.ͩ%b-[YMsdhvPKǠb-PK><`meta.xml LibreOffice/3.3$Unix LibreOffice_project/330m19$Build-301TAL/TALES & METAL Reference GuideA guide to using TAL, TALES, and METAL.2004-07-16T21:47:27Colin 2011-07-07T20:24:27TAL TALES METALen-GB30PT5H33M50SPK>qThumbnails/thumbnail.pngPNG  IHDRg?aIDATx]ᒳ8Wu}uO>SyԭAHGْ0- ч`2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2qʥ33_\+Y/oG c!B卷q'넃1MW Antra WeՍ7qVZ~/ͰK8D>hyNTEYL  >c/΅{W7kRͼG :S| 3cnւzpVb;EzJ<Ї(]gÄ\6h/x W< O J uJ/:A^S.=i<{^lMt-LXhڗ Byc/{qA{9<g獦vX?Oz[ CV2=5I|  )ElfۮNN83w͹ʦ!^ՓD,pC^ISgbP cS;Kr 3|NxjI\g_u0ۅD2@= J/D'=_F.czJ0D+IKͰK8ڎCQ9#H@0o4#[1d<=?g)J!=YO.apt3Ws'B+Vƻ ьect_޻eVt™a'p͞ǘW$.NH.Yhma[̟ؔqg[6F3D܈xt,I;z֨Mm*T$^2iE|t#.Ƴ,ZeZ0fm Zpby*x+spɦB:?Kw[)ta}<ܙg@CeT Xcaĩ>PE0+z(phv&+BN=^<UT#=zԨo6R){ (:rgMÅ~U8r&}3PgZBq X @,M@yu\xHu䙂"N(&f&h*ETqW`Ba *+PUM)dpnХF2yl)Qb'⬨Kzh&+XźuG%IOѯǯKuu c/uF rM fvʷCؑn%XKLx>zRnϸv)v)-tW'=%v9Sh9ug-pp³v8g@Y˯E,_+ T83a2a2ZJ޺`-o?c'O߿.760M?(?V !L "OAg *5Y'=<*SYY*TM!D Y d0*]^R1%?괴27ٺp&0Ҁ_2Lѳf ,JuZqy)kg\9˾5`6Dgoz7dk~gHи# 'x ?@2Gw@Pw* V<3d~C=3.l<&y_l@FJuY.ґ VhYp)K[ ^B\`-S5 ^ v">YQX7XgasK `i\xt`,C3Gг3N#- GiA0)v{. 0#HVBZ~x8RF3{Jb#C2 c@ ѵ mhOfO0^NCWeQz8gC5V#c] ",5F:k ѳ< D UbE<]AS{qBz>͞OEϻۯՄZ =?g@H.6*h>%ET/L{a W^6J^gTD~)zGB9G~fz~ c4.e4.e4—go1i4%,`.|yڀ4柿;AmƫpӨe؍>/xyZVg ьg8 i#tx-4{~xӂ;*B6Ob3;{Y˗S^6ԇ?& #Nυ`HKҭt|0 0ëF-<<-s2[Fv۝+S,TqVg5t𔗧exvZ֡ef6e괢J;v„ 7Y/ěvͥ0Uzދoo#QxgdS#83cT=ka0U2 7ZglU a ߒ/(:PFճL5eܴ :29{9e`x֩06 +Fd0U1.M%\gq"oV̩m=VlZ*{Ѱ_jW -0Ӈ YYA8Q V B[^%(dl,")`Z;]h]h^!Wh_hN[ FY?6k T2>v,F:ۏfa"s^U. by8zHnYAYP,hEɔ^<EWZXX9uxg[%E#J8{SssKk _qcaۂ̀iѸm?~__ NuͰKͰKͰKx2KΐYa,\v?AI G > ^`Qh)1 N"ͰKx34s^mg~T֥%Ã3d-0,7 S%vl?;U΅Uvy۟NAogZK#>z;muhv&cnaA)j &M@\KYa'vFÈ.< vt`W)(]IdsB2Jb(wAog(zT=Ζ",]T .,GsogxթnvU xtBqUVFazQS 0pF4ZQ, Y0Y(0 ϠgA&@ۗ^Kg+q^uo˩iY/ZgXE} Oͬ}ű^l䘑E]]b[g@fn*Qr^3.s2d6ADGWsY~I\*}FHhf{;A,,=_^.o+ɞ3f/A*泴;T;zU$IJ.ԩBE2SѯerȮi>^DpCWԒ}W.z,<;g׋h8c޺Oo@ϲ1u$HeFPsYEF{Rx6u9f\lyFQ+u=xnS}xKo ь׸`=D8L"|%dA䚳BKs c"g4{ϋyXʖG!*֑C(Z?XD,Y 30=g4.e4r0ݫ9^G|`O1|ek4f0{D(6fE|_/G|qZ"ӯ7AٟFoķ\!i)jUN 0=g]h]h \JGF!@(M[3Z6ոubr+'ƞZ$BT0fkN?!i]0.I"-MϋvVFF3RF3nuzAs78(\'WzK8ʻ+Šn ьNh罩LLmI |'`) w*aE ȱ*ГDuWr|*ŲtXN(?+ΰ̯X6. Sugm3{`zn4.e4㍗=t`aNXo0xHy|9Yhs7 ׍4Ӟ*'˱ CtژV.<*[Vvn'Configurations2/accelerator/current.xmlPKPK>Configurations2/progressbar/PK>Configurations2/floater/PK>Configurations2/popupmenu/PK>Configurations2/toolpanel/PK>Configurations2/menubar/PK>Configurations2/toolbar/PK>Configurations2/images/Bitmaps/PK>Configurations2/statusbar/PK> settings.xmlZW:~{\zu㺧Q@,5MzwҢ׋.s/HNf&3|pcӃqTb<{~\q(o!:N:ߊ數Rɷr'G_,*K4bO/,s+j>O 8GwdWŔ8>ydi+Jϖ>xq^_q)njh,'uw~H'Hpr6)]Tώo|^tjlk7(TӵV݄_C4Wrv|rΔg>TN \Ya9JJuIh6I*?-0&aBCY,S,>zT"Vn-7Qݔ.q-K.Hp7׻rrzC.Z )j'\jOiޗt%[x$P\׽ru ` <| 2~UK*;զgm2uG.a#~.MqT ;,nR[pqP|D'(W\xxkӋH8=q"FĢt1ɮ,[!4'd|L_ .u:li}ݳ[_Ym5zs9h_^&y\8ALӰ_qgA5mYZnܚ5J_܍+ Q#_ k:bզeK[6h> bݺkGAV}=ke.uL \Ӱvu۫ylo%N=ۿg(䎶у#hSjw,߻{ZN~ik k;U!`X/":+\DŽm OLF!.@ݍ~ $u߿| 9jwhpekNEB*r#bZi<MۯQS)'$.՝UGX̋&7͐>PJ3!6Vz-%I"(S*_a3'ٲɃ- NymOt($l"I riPGyP!koHT]6DڀА;. hpg`}^sLjlK#6E V`9sCPlƲjcs [W\&ؘW1!ީi p71R_s-i>56& x 42Y묆-S@iеMW?HƝ&i"x< w]Qf@5`_F(ZO$>mhl xA88Uxt9$@bc]'aCզ<;D`4ݒ˛$7듶Opۂ9}?v,O#E?D.{ 2R,{T%JUuӰmt']+D3YgHv9K4aY۞. }F'MPK-F-S#PK>META-INF/manifest.xmlMO0+'S8P-HHC9p:Ԓc[%ZB6c4^x&58& #mLWmK\]/f˧GZ |1Y!J#h[%/ş1/nE!ƩF$gf2eǰkfw`nI TlITa?8FaɃZsZIkx6Mh+&/ڨu׵i00$~]+e46r)Q#pO]c2tj}ʗfִr9) ?Eyy aZm1Uo&EדylvhHog;lpG5#cZTT6bN0-=|PK&ZPK>19mimetypePK>LM7`o Dcontent.xmlPK>L=- layout-cachePK>Ǡb- styles.xmlPK><`meta.xmlPK>q!Thumbnails/thumbnail.pngPK>'5Configurations2/accelerator/current.xmlPK> 6Configurations2/progressbar/PK>F6Configurations2/floater/PK>|6Configurations2/popupmenu/PK>6Configurations2/toolpanel/PK>6Configurations2/menubar/PK>"7Configurations2/toolbar/PK>X7Configurations2/images/Bitmaps/PK>7Configurations2/statusbar/PK>-F-S# 7settings.xmlPK>&ZZ>META-INF/manifest.xmlPKp/@SimpleTAL-5.2/documentation/src/api-simpletales.txt0000664000175200017520000000566512537066033022531 0ustar cms103cms10300000000000000title: SimpleTAL API: simpleTALES Module. subject: Documentation on how to use the simpleTALES Module.

simpleTALES

The only external class in this module is the Context class.

Context ([options] [,allowPythonPath])

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.

Context.addGlobal (name, value)

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.

PathFunctionVariable (callableObject)

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.

CachedFuncResult (callableObject)

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.

clearCache ()

Clears the cache. Use this to clear the cache between multiple template expansions if the callable should be executed once per template expansion. Back to SimpleTAL API SimpleTAL-5.2/documentation/src/api-simpletalutils.txt0000664000175200017520000000347012537066033023252 0ustar cms103cms10300000000000000title: SimpleTAL API: simpleTALUtils Module. subject: Documentation on how to use the simpleTALUtils Module.

simpleTALUtils

This module holds optional classes and functions that might be of use while using SimpleTAL, but are not required by SimpleTAL directly.

def ExpandMacros (context, template, outputEncoding="utf-8")

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.

TemplateCache

This class implements a cache for compiled templates which automatically invalidates entries when their template file changes. The instance has one public method: getTemplate

getTemplate (name, inputEncoding="utf-8")

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.

getXMLTemplate (name)

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. Back to SimpleTAL API SimpleTAL-5.2/documentation/src/api-simpleelementtree.txt0000664000175200017520000000413412537066033023720 0ustar cms103cms10300000000000000title: SimpleTAL API: simpleElementTree Module. subject: Documentation on how to use the simpleElementTree Module.

simpleElementTree

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.

parseFile (file)

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)

ElementTree Paths

The Context variable provided by parseFile provides the following syntax for path access in TAL:
  • Accessing the variable directly returns the Text value for this node.
  • Accessing variable/find/path returns the first node to match the path, as supported by ElementTree (see XPath Support in ElementTree).
  • Accessing variable/findall/path returns a list of nodes that match the path, as supported by ElementTree (see XPath Support in ElementTree).
  • Accessing variable@name returns the XML attribute "name".
  • Accessing variable/anotherElement is a short-cut for variable/find/anotherElement.
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>
SimpleTAL-5.2/documentation/src/index.txt0000664000175200017520000000160012537066033020530 0ustar cms103cms10300000000000000title: SimpleTAL subject: Welcome 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! SimpleTAL-5.2/documentation/src/api-simpletal.txt0000664000175200017520000000546112537066033022173 0ustar cms103cms10300000000000000title: SimpleTAL API: simpleTAL Module subject: Documentation on how to use the simpleTAL Module.

simpleTAL

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.

compileHTMLTemplate (template, minimizeBooleanAtts=0)

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.

compileXMLTemplate (template)

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.

Template Instances

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). Back to SimpleTAL API SimpleTAL-5.2/documentation/src/notes.txt0000664000175200017520000001520612537120223020550 0ustar cms103cms10300000000000000title: Notes on SimpleTAL subject: Notes, known limitations, and differences between SimpleTAL and Zope's ZPT.

Upgrading from SimpleTAL 4.x to 5.x

Porting SimpleTAL to Python 3 has introduced a number of small changes:
  • simpleTALUtils.HTMLStructureCleaner is not available from SimpleTAL 5 onwards. The sgmlib library that it utilised was removed in Python 3.
  • simpleTAL.compileHTMLTemplate no longer accepts the inputEncoding argument. All HTML templates must be either Strings or file objects that produce Strings.
  • compileDOMTemplate is not available from SimpleTAL 5 onwards. The pyxml library that provides the Dom2SaxParser implementation is not yet available in Python 3.
  • simpleTALUtils.ExpandMacros defaults to utf-8 for outputEncoding rather than iso-8859-1.
  • simpleTALUtils.FastStringOutput has been removed in favour of the new io.StringIO which is faster.
  • simpleTALUtils.TemplateCache.getTemplate now defaults to utf-8 rather than iso-8859-1 for HTML templates.

Notes

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.

HTML and XHTML Templates

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:
  • Allow TAL attributes on all HTML elements that forbid close tags, and process them despite the lack of close tag
  • When compiling a HTML template issue a warning if a close tag is present for elements that are forbidden to have close tags.
  • Suppress the output of close tags for elements that are forbidden to have close tags.
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.

Character set encoding

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.

Structured Content

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.

Object Attributes versus Key Values

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()'.

Using < and > in TAL Paths

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 &lt; b">Conditional Text</div> instead of: <div tal:condition="python: a < b">Conditional Text</div>

Known limitations

  1. Repeat Variables do not support 'first' and 'last'.
  2. When using 'not:' on an empty expression the result will be true rather than an error.
  3. Path type 'python:' is not supported by default. You can enable this by passing allowPythonPath=1 to the Context constructor. Note that this should only be used when the authors of the templates are completely trusted, the code included in the 'python:' path can do anything.
  4. TAL markup "on-error" is not yet supported.
  5. HTML Templates will have duplicate attributes if an attribute is added using "tal:attributes" and the name is in upper case. The cause of this is the HTMLParser implementation, which always converts attributes to lower case.

Known differences

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. SimpleTAL 5.2 onwards supports accessing repeat variables through Python paths. Unlike Zope, all variables on the repeat variable are methods, with the exception of length. To access the value from a python path you need to call the method, e.g.: '<b tal:content="python:repeat['item'].index()"></b> Back to SimpleTAL SimpleTAL-5.2/Changes.txt0000664000175200017520000002746112537121133015337 0ustar cms103cms10300000000000000simpleTAL / simpleTALES (Version 5.2) ------------------------------------- Version 5.2 ----------- This version requires a minimum of Python 3.2 and has been tested on Python 3.3 & 3.4 Bug fixes: - Removed ElementTree support due to incompatible API in Python 3.4 - Switched to non-deprecated methods - Fixed issue with Ampersand escaping in attributed in Python 3.4 - Repeat variables can now be accessed from Python Paths Version 5.1 ----------- Bug fixes: - Added missing XML files from the ElementTree example. Version 5.0 ----------- NOTE: This version of SimpleTAL is for Python 3.1 and later. For Python 2.x. support please use SimpleTAL version 4.2. New features: - Ported from Python 2.6 to Python 3.1 Version 4.2 ----------- WARNING: This version is not fully backwards compatible! The default character encoding for XML templates is not utf-8 rather than iso8859-1. Bug fixes: - XML Templates now default to utf-8 for output encoding. - Fixed corruption of attributes on a repeat tag if use-macro was used inside it (thanks to Benjamin Niemann for the bug report). - Updates to runtests.py for compatibility with Python 2.6. - Use md5 from hashlib to fix DeprecationWarning within tests. Version 4.1 ----------- New features: - Processing Instructions are now supported in HTML templates. Bug fixes: - The use of "&" in attributes was broken in 4.0 - fixed (thanks to Alain Spineux for the bug report). Version 4.0 ------------ This version of SimpleTAL is not 100% backwards compatible with the 3.x series of releases. Version 4.0 of SimpleTAL requires Python 2.2 or higher. New features: - Added support for minimizing boolean attributes in HTML (minimizeBooleanAtts = 1). - Switched HTML parser library from SGMLParser to HTMLParser. HTMLParser is generally less strict than the SGMLParser, however it doesn't handle unbalanced quotes around attributes (thanks to Carlos Neves for the initial patch). - Python 2.2 or higher supported. - All METAL namespace attributes are automatically omitted, not just those in XML templates. Version 3.13 ------------ New features: - Added support for compiling a template from a DOM tree (thanks to Benjamin Niemann for the patch). - Added support for iterators in the Context (thanks to Kevin Smith for the ideas). Bug fixes: - ElementTree paths can now be used from 'python: path ()' expressions (thanks to Jochen Kupperschmidt for the fix). Version 3.12 ------------ New features: - Integration with ElementTree. - Use Python 2.2's unicode function if available (honours the __unicode__ method) when converting non-unicode variables in the Context. Bug fixes: - Allow sub-classes of string and Unicode strings to be placed in the Context. Version 3.11 ------------ This release changes how HTML templates containing entity references and character references are handled. In previous releases any references contained in the HTML would be passed through to the output intact. In order to solve the double escaping bug described below all character references are now expanded in the output with the exception of <, > and & Bug fixes: - If multiple variable substitutions are used in a single 'string:' path and one failed the whole path would evaluate to an empty string. - When was used was output. - The global variable 'attrs' should be a dictionary, not a list (Thanks to Christoph Zwerschke for the bug report). - Content accessed through attrs would be double escaped. Version 3.10 ------------ New features: - Included API documentation and TAL reference guide with archive. Bug fixes: - Attributes on repeat tags were not correctly kept for nested repeats. (Thanks to Aadish Shrestha for the bug report) Version 3.9 ----------- This is release is focused on improving performance. Compared to version 3.8 the performance of expanding templates is ~45-70% faster. The performance of parsing templates is unchanged. WARNING: IF you rely on the internal workings of SimpleTALES in your application then there will be changes that are required to make use of this version of SimpleTAL. The API for SimpleTAL is however unchanged. New features: - Introduced simpleTALUtils.FastStringOutput which can be used to capture the output of SimpleTAL in a faster manner than StringIO. - Introduced simpleTALES.CachedFuncResult which can be used to wrap functions in the Context, and which cache's the result of the function call to ensure that the function is only called once during template expansion. - TALES no longer wraps all results in ContextVariable instances when returning values to TAL. - Changed copy.copy to {}.copy for performance improvement. - Removed logging.debug() calls from performance critical paths. - Replaced DefaultVariable class with simpleTALES.DEFAULTVALUE - Replaced NothingVariable class with None - Removed NoCallVariable - Removed isDefault, isNothing, isSequence, isCallable, and isTrue from ContextVariable. Version 3.8 ----------- New features: - Added new method getXMLTemplate to simpleTALUtils.TemplateCache - Comments in XML templates are now included in the output if pyxml is installed. - Lists can now be indexed into. Bug fixes: - TAL commands on METAL namespaced elements and vice-versa now work correctly (thanks to Kevin Smith for the bug report). Version 3.7 ----------- New features: - When non-ascii, non-Unicode strings are present in the Context a Unicode error is thrown. Now an ERROR log message indicates that this is the most likely cause of the problem. Bug fixes: - Correction to cgi-example (thanks to Frank Wierzbicki for the patch). - Local defines that reference earlier local defines on one tag now work. - Using default values in a repeat list now work as expected. - Errors during codec conversions will now use 'replace' rather than 'strict' Version 3.6 ----------- New features: - The XML Declaration can now be suppressed by passing suppressXMLDeclaration=1 to the template "expand" method. Bug fixes: - Removed stray 'info' logging call. Version 3.5 ----------- New features: - The 'test' function is now available to code used in 'python:' paths. Usage is the same as zope: test (test1,val1[,test2,val2][,default]). (Thanks to Mark McEahern for the feature request) - Uses PyXML (http://pyxml.sourceforge.net/) to determine the DOCTYPE of XML templates (if installed). (Thanks to Myers Carpenter for the implementation) Bug fixes: - CGI Example fixes. - XML Templates containing attributes with character entities are now output correctly. - HTML Templates with special characters as part of TAL or METAL commands are now handled correctly. - Default encoding is now iso-8859-1 rather than iso8859-1 Version 3.4 ----------- New features: - TemplateCache now uses MTIME rather than CTIME to spot changes to templates. - SimpleTAL is now compatible with PyXML 0.8.2 (Thanks to Myers Carpenter for the testing). - Added support for passing in an XML Doctype when calling template.expand - Added support to maintain XML singleton tags, including use of METAL and TAL on singleton tags. - Added support for using variables in paths (e.g. If colour='blue' then the path 'colourMap/?colour' is equivalent to 'colourMap/blue'). This is not part of the TALES specification, but is supported by Zope. (Thanks to Bastian Kleineidam for the initial implementation). Bug fixes: - If the logging module was not installed exceptions would be thrown when SimpleTAL attempted to log errors - fixed. Version 3.3 ----------- New features: - TemplateCache now supports inputEncoding, allowing HTML templates using character sets other than ISO8859-1 to be used. - Functions path, string, exists, and nocall are available to python: paths. - Functions can now receive parameters via paths by wrapping them in simpleTALES.PathFunctionVariable before placing them into the Context. Bug fixes: - In tal:attributes and tal:define double escaped semi-colons are now handled. - Space after a semi-colon in tal:attributes and tal:define is now handled (thanks to Sean Reifschneider) - Handling of stray quotes at the start and end of attributes shouldn't interfere with python: paths anymore. Version 3.2 ----------- This release incorporates patches from Wichert Akkerman implementing the Python TAL path and moving to string methods instead of using the string module. New features: - The 'python:' path can now be used, pass the parameter 'allowPythonPath=1' to the constructor of SimpleTALES.Context to enable this to be used. - simpleTALUtils now contains a template caching class (TemplateCache) that can be used to cache compiled templates, automatically invalidating the cache if the template file has changed. - The string module is no longer used, replaced by string methods Bug fixes: - Nested repeat variables with the same name are now scoped correctly. - If logging is available all error messages are now suppressed during testing. Version 3.1 ----------- With this release import statements need to be changed. Please now use: from simpletal import simpleTAL, simpleTALES. The API has not changed. New features: - SimpleTAL can now be installed using distutils, thanks to Michael Twomey. Bug fixes: - If tal:repeat and tal:content were used on the same element, the last piece of content would be present twice - fixed. - If a path element inside a string: path evaluated to something other than a string or unicode string, it would not be evaluated. Now an attempt to coerce the value to a string is done using the str function. Version 3.0 ----------- New features: - METAL Support added - The TAL and METAL name-spaces can now be bound to any prefix - When using XML Templates any elements in the TAL or METAL name-space have their start and end tags suppressed. Version 2.3 ----------- Bug fixes: - Using tal:repeat on empty lists would cause an exception to be thrown. Now the repeating elements are removed from the output. Version 2.2 ----------- Bug fixes: - HTML Document type declarations were not being passed through from the template - HTML Comments are now passed through to the output - End tags with no start tag now raise an error rather than failing silently - The first text element in a template is now combined with other text elements - XML Processing Instructions are now passed through the template correctly. Version 2.1 ----------- Bug fixes: - HTML Templates will now suppress the output of close tags for elements that are forbidden to have them in HTML 4.01. Additionally tags that can have no close tag in HTML can still have TAL attributes. This means that HTML templates can still be valid HTML, and produce valid HTML. For example: '' is now valid, and will only output the tag. New features: - A simplification of how local variables are handled brings a 5-10% performance gain Version 2.0 ----------- Complete refactoring of simpleTAL leading to very significant performance improvements. Bug fixes: - Any unknown entity references present in a HTML template were not passed through to the rendered template, now they are. - Attributes created using tal:attributes did not have their values escaped properly New features: - Large performance improvements by splitting the process into two - Templates once compiled can now be re-used, leading to large performance gains Version 1.1 ----------- Bug fixes: - The "structure" keyword when used in XML templates would fail with an exception. New features: - Added test cases for TALES and TAL (both HTML and XML) - Added allowTALInStructure flag to control expansion of TAL attributes Version 1.0 ----------- Initial release.