diff options
Diffstat (limited to 'cheetah/Tests/Template.py')
-rw-r--r-- | cheetah/Tests/Template.py | 353 |
1 files changed, 353 insertions, 0 deletions
diff --git a/cheetah/Tests/Template.py b/cheetah/Tests/Template.py new file mode 100644 index 0000000..085180d --- /dev/null +++ b/cheetah/Tests/Template.py @@ -0,0 +1,353 @@ +#!/usr/bin/env python + +import pdb +import sys +import types +import os +import os.path +import tempfile +import shutil +import unittest_local_copy as unittest +from Cheetah.Template import Template + +majorVer, minorVer = sys.version_info[0], sys.version_info[1] +versionTuple = (majorVer, minorVer) + +class TemplateTest(unittest.TestCase): + pass + +class ClassMethods_compile(TemplateTest): + """I am using the same Cheetah source for each test to root out clashes + caused by the compile caching in Template.compile(). + """ + + def test_basicUsage(self): + klass = Template.compile(source='$foo') + t = klass(namespaces={'foo':1234}) + assert str(t)=='1234' + + def test_baseclassArg(self): + klass = Template.compile(source='$foo', baseclass=dict) + t = klass({'foo':1234}) + assert str(t)=='1234' + + klass2 = Template.compile(source='$foo', baseclass=klass) + t = klass2({'foo':1234}) + assert str(t)=='1234' + + klass3 = Template.compile(source='#implements dummy\n$bar', baseclass=klass2) + t = klass3({'foo':1234}) + assert str(t)=='1234' + + klass4 = Template.compile(source='$foo', baseclass='dict') + t = klass4({'foo':1234}) + assert str(t)=='1234' + + def test_moduleFileCaching(self): + if versionTuple < (2,3): + return + tmpDir = tempfile.mkdtemp() + try: + #print tmpDir + assert os.path.exists(tmpDir) + klass = Template.compile(source='$foo', + cacheModuleFilesForTracebacks=True, + cacheDirForModuleFiles=tmpDir) + mod = sys.modules[klass.__module__] + #print mod.__file__ + assert os.path.exists(mod.__file__) + assert os.path.dirname(mod.__file__)==tmpDir + finally: + shutil.rmtree(tmpDir, True) + + def test_classNameArg(self): + klass = Template.compile(source='$foo', className='foo123') + assert klass.__name__=='foo123' + t = klass(namespaces={'foo':1234}) + assert str(t)=='1234' + + def test_moduleNameArg(self): + klass = Template.compile(source='$foo', moduleName='foo99') + mod = sys.modules['foo99'] + assert klass.__name__=='foo99' + t = klass(namespaces={'foo':1234}) + assert str(t)=='1234' + + + klass = Template.compile(source='$foo', + moduleName='foo1', + className='foo2') + mod = sys.modules['foo1'] + assert klass.__name__=='foo2' + t = klass(namespaces={'foo':1234}) + assert str(t)=='1234' + + + def test_mainMethodNameArg(self): + klass = Template.compile(source='$foo', + className='foo123', + mainMethodName='testMeth') + assert klass.__name__=='foo123' + t = klass(namespaces={'foo':1234}) + #print t.generatedClassCode() + assert str(t)=='1234' + assert t.testMeth()=='1234' + + klass = Template.compile(source='$foo', + moduleName='fooXXX', + className='foo123', + mainMethodName='testMeth', + baseclass=dict) + assert klass.__name__=='foo123' + t = klass({'foo':1234}) + #print t.generatedClassCode() + assert str(t)=='1234' + assert t.testMeth()=='1234' + + + + def test_moduleGlobalsArg(self): + klass = Template.compile(source='$foo', + moduleGlobals={'foo':1234}) + t = klass() + assert str(t)=='1234' + + klass2 = Template.compile(source='$foo', baseclass='Test1', + moduleGlobals={'Test1':dict}) + t = klass2({'foo':1234}) + assert str(t)=='1234' + + klass3 = Template.compile(source='$foo', baseclass='Test1', + moduleGlobals={'Test1':dict, 'foo':1234}) + t = klass3() + assert str(t)=='1234' + + + def test_keepRefToGeneratedCodeArg(self): + klass = Template.compile(source='$foo', + className='unique58', + cacheCompilationResults=False, + keepRefToGeneratedCode=False) + t = klass(namespaces={'foo':1234}) + assert str(t)=='1234' + assert not t.generatedModuleCode() + + + klass2 = Template.compile(source='$foo', + className='unique58', + keepRefToGeneratedCode=True) + t = klass2(namespaces={'foo':1234}) + assert str(t)=='1234' + assert t.generatedModuleCode() + + klass3 = Template.compile(source='$foo', + className='unique58', + keepRefToGeneratedCode=False) + t = klass3(namespaces={'foo':1234}) + assert str(t)=='1234' + # still there as this class came from the cache + assert t.generatedModuleCode() + + + def test_compilationCache(self): + klass = Template.compile(source='$foo', + className='unique111', + cacheCompilationResults=False) + t = klass(namespaces={'foo':1234}) + assert str(t)=='1234' + assert not klass._CHEETAH_isInCompilationCache + + + # this time it will place it in the cache + klass = Template.compile(source='$foo', + className='unique111', + cacheCompilationResults=True) + t = klass(namespaces={'foo':1234}) + assert str(t)=='1234' + assert klass._CHEETAH_isInCompilationCache + + # by default it will be in the cache + klass = Template.compile(source='$foo', + className='unique999099') + t = klass(namespaces={'foo':1234}) + assert str(t)=='1234' + assert klass._CHEETAH_isInCompilationCache + + +class ClassMethods_subclass(TemplateTest): + + def test_basicUsage(self): + klass = Template.compile(source='$foo', baseclass=dict) + t = klass({'foo':1234}) + assert str(t)=='1234' + + klass2 = klass.subclass(source='$foo') + t = klass2({'foo':1234}) + assert str(t)=='1234' + + klass3 = klass2.subclass(source='#implements dummy\n$bar') + t = klass3({'foo':1234}) + assert str(t)=='1234' + + +class Preprocessors(TemplateTest): + + def test_basicUsage1(self): + src='''\ + %set foo = @a + $(@foo*10) + @a''' + src = '\n'.join([ln.strip() for ln in src.splitlines()]) + preprocessors = {'tokens':'@ %', + 'namespaces':{'a':99} + } + klass = Template.compile(src, preprocessors=preprocessors) + assert str(klass())=='990\n99' + + def test_normalizePreprocessorArgVariants(self): + src='%set foo = 12\n%%comment\n$(@foo*10)' + + class Settings1: tokens = '@ %' + Settings1 = Settings1() + + from Cheetah.Template import TemplatePreprocessor + settings = Template._normalizePreprocessorSettings(Settings1) + preprocObj = TemplatePreprocessor(settings) + + def preprocFunc(source, file): + return '$(12*10)', None + + class TemplateSubclass(Template): + pass + + compilerSettings = {'cheetahVarStartToken':'@', + 'directiveStartToken':'%', + 'commentStartToken':'%%', + } + + for arg in ['@ %', + {'tokens':'@ %'}, + {'compilerSettings':compilerSettings}, + {'compilerSettings':compilerSettings, + 'templateInitArgs':{}}, + {'tokens':'@ %', + 'templateAPIClass':TemplateSubclass}, + Settings1, + preprocObj, + preprocFunc, + ]: + + klass = Template.compile(src, preprocessors=arg) + assert str(klass())=='120' + + + def test_complexUsage(self): + src='''\ + %set foo = @a + %def func1: #def func(arg): $arg("***") + %% comment + $(@foo*10) + @func1 + $func(lambda x:c"--$x--@a")''' + src = '\n'.join([ln.strip() for ln in src.splitlines()]) + + + for arg in [{'tokens':'@ %', 'namespaces':{'a':99} }, + {'tokens':'@ %', 'namespaces':{'a':99} }, + ]: + klass = Template.compile(src, preprocessors=arg) + t = klass() + assert str(t)=='990\n--***--99' + + + + def test_i18n(self): + src='''\ + %i18n: This is a $string that needs translation + %i18n id="foo", domain="root": This is a $string that needs translation + ''' + src = '\n'.join([ln.strip() for ln in src.splitlines()]) + klass = Template.compile(src, preprocessors='@ %', baseclass=dict) + t = klass({'string':'bit of text'}) + #print str(t), repr(str(t)) + assert str(t)==('This is a bit of text that needs translation\n'*2)[:-1] + + +class TryExceptImportTest(TemplateTest): + def test_FailCase(self): + ''' Test situation where an inline #import statement will get relocated ''' + source = ''' + #def myFunction() + Ahoy! + #try + #import sys + #except ImportError + $print "This will never happen!" + #end try + #end def + ''' + # This should raise an IndentationError (if the bug exists) + klass = Template.compile(source=source, compilerSettings={'useLegacyImportMode' : False}) + t = klass(namespaces={'foo' : 1234}) + +class ClassMethodSupport(TemplateTest): + def test_BasicDecorator(self): + if sys.version_info[0] == 2 and sys.version_info[1] == 3: + print 'This version of Python doesn\'t support decorators, skipping tests' + return + template = ''' + #@classmethod + #def myClassMethod() + #return '$foo = %s' % $foo + #end def + ''' + template = Template.compile(source=template) + try: + rc = template.myClassMethod(foo='bar') + assert rc == '$foo = bar', (rc, 'Template class method didn\'t return what I expected') + except AttributeError, ex: + self.fail(ex) + +class StaticMethodSupport(TemplateTest): + def test_BasicDecorator(self): + if sys.version_info[0] == 2 and sys.version_info[1] == 3: + print 'This version of Python doesn\'t support decorators, skipping tests' + return + template = ''' + #@staticmethod + #def myStaticMethod() + #return '$foo = %s' % $foo + #end def + ''' + template = Template.compile(source=template) + try: + rc = template.myStaticMethod(foo='bar') + assert rc == '$foo = bar', (rc, 'Template class method didn\'t return what I expected') + except AttributeError, ex: + self.fail(ex) + +class Useless(object): + def boink(self): + return [1, 2, 3] + +class MultipleInheritanceSupport(TemplateTest): + def runTest(self): + template = ''' + #extends Template, Useless + #def foo() + #return [4,5] + $boink() + #end def + ''' + template = Template.compile(template, + moduleGlobals={'Useless' : Useless}, + compilerSettings={'autoImportForExtendsDirective' : False}) + template = template() + result = template.foo() + print result + + +################################################## +## if run from the command line ## + +if __name__ == '__main__': + unittest.main() |