#!/usr/bin/env python import pdb import sys import types import os import os.path import tempfile import shutil import 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() assert result == [4, 5, 1, 2, 3], (result, 'Unexpected result') ################################################## ## if run from the command line ## if __name__ == '__main__': unittest.main()