Skip to content
Browse files

Merge commit 'origin/next' into slide-compat

Le sigh

Conflicts:
	cheetah/Version.py
  • Loading branch information...
2 parents 4490f68 + 9bc0b37 commit 290f5e45c04f82034d700cf016d71e6256f1058e @rtyler committed Sep 1, 2009
Showing with 2,162 additions and 5,434 deletions.
  1. +1 −1 BUGS
  2. +11 −0 CHANGES
  3. +37 −20 SetupConfig.py
  4. +2 −18 SetupTools.py
  5. +1 −1 TODO
  6. +2 −2 bin/cheetah
  7. +2 −4 bin/cheetah-compile
  8. 0 {src → cheetah}/CacheRegion.py
  9. 0 {src → cheetah}/CacheStore.py
  10. +23 −2 {src → cheetah}/CheetahWrapper.py
  11. +45 −40 {src → cheetah}/Compiler.py
  12. +16 −0 cheetah/Django.py
  13. +0 −1 {src → cheetah}/DummyTransaction.py
  14. +0 −1 {src → cheetah}/ErrorCatchers.py
  15. +0 −1 {src → cheetah}/FileUtils.py
  16. +15 −23 {src → cheetah}/Filters.py
  17. +0 −1 {src → cheetah}/ImportHooks.py
  18. +0 −1 {src → cheetah}/ImportManager.py
  19. 0 {src → cheetah}/Macros/I18n.py
  20. 0 {src/Utils → cheetah/Macros}/__init__.py
  21. +5 −1 {src → cheetah}/NameMapper.py
  22. +38 −2 {src → cheetah}/Parser.py
  23. +5 −6 {src → cheetah}/Servlet.py
  24. +3 −31 {src → cheetah}/SettingsManager.py
  25. +0 −1 {src → cheetah}/SourceReader.py
  26. +49 −51 {src → cheetah}/Template.py
  27. +0 −1 {src → cheetah}/TemplateCmdLineIface.py
  28. +0 −1 {src → cheetah}/Templates/SkeletonPage.py
  29. 0 {src → cheetah}/Templates/SkeletonPage.tmpl
  30. +0 −1 {src → cheetah}/Templates/_SkeletonPage.py
  31. +1 −0 cheetah/Templates/__init__.py
  32. +46 −51 {src → cheetah}/Tests/CheetahWrapper.py
  33. +39 −0 cheetah/Tests/Cheps.py
  34. +4 −1 {src → cheetah}/Tests/Filters.py
  35. +3 −16 {src → cheetah}/Tests/NameMapper.py
  36. +106 −0 {src → cheetah}/Tests/Regressions.py
  37. +2 −11 {src → cheetah}/Tests/SyntaxAndOutput.py
  38. +18 −33 {src → cheetah}/Tests/Template.py
  39. +2 −4 {src → cheetah}/Tests/Test.py
  40. +23 −2 {src → cheetah}/Tests/Unicode.py
  41. 0 {src/Tools/turbocheetah/tests → cheetah/Tests}/__init__.py
  42. 0 {src → cheetah}/Tests/unittest_local_copy.py
  43. 0 {src → cheetah}/Tests/xmlrunner.py
  44. +0 −1 {src → cheetah}/Tools/CGITemplate.py
  45. +0 −1 {src → cheetah}/Tools/MondoReport.py
  46. 0 {src → cheetah}/Tools/MondoReportDoc.txt
  47. +0 −1 {src → cheetah}/Tools/RecursiveNull.py
  48. +0 −1 {src → cheetah}/Tools/SiteHierarchy.py
  49. 0 {src → cheetah}/Tools/__init__.py
  50. 0 {src → cheetah}/Tools/turbocheetah/__init__.py
  51. 0 {src → cheetah}/Tools/turbocheetah/cheetahsupport.py
  52. 0 {src/Tests → cheetah/Tools/turbocheetah/tests}/__init__.py
  53. 0 {src → cheetah}/Tools/turbocheetah/tests/test_template.py
  54. 0 {src → cheetah}/Unspecified.py
  55. +12 −24 {src → cheetah}/Utils/Indenter.py
  56. +0 −1 {src → cheetah}/Utils/Misc.py
  57. +2 −1 {src → cheetah}/Utils/VerifyType.py
  58. +0 −1 {src → cheetah}/Utils/WebInputMixin.py
  59. 0 {src/Macros → cheetah/Utils}/__init__.py
  60. 0 {src → cheetah}/Utils/htmlDecode.py
  61. 0 {src → cheetah}/Utils/htmlEncode.py
  62. +0 −1 {src → cheetah}/Utils/memcache.py
  63. 0 {src → cheetah}/Utils/statprof.py
  64. +2 −2 {src → cheetah}/Version.py
  65. +0 −2 {src → cheetah}/__init__.py
  66. +47 −0 cheetah/c/Cheetah.h
  67. +93 −0 cheetah/c/_filters.c
  68. +5 −2 {src → cheetah/c}/_namemapper.c
  69. +52 −0 cheetah/c/_template.c
  70. +107 −0 cheetah/c/_verifytype.c
  71. 0 {src → cheetah}/convertTmplPathToModuleName.py
  72. +0 −1 src/Templates/__init__.py
  73. +220 −0 src/Tests/Performance.py
  74. +157 −0 src/Tests/VerifyType.py
  75. 0 src/contrib/__init__.py
  76. +0 −30 src/contrib/markdown/LICENSE
  77. +0 −603 src/contrib/markdown/__init__.py
  78. +0 −95 src/contrib/markdown/blockparser.py
  79. +0 −460 src/contrib/markdown/blockprocessors.py
  80. +0 −96 src/contrib/markdown/commandline.py
  81. +0 −33 src/contrib/markdown/etree_loader.py
  82. 0 src/contrib/markdown/extensions/__init__.py
  83. +0 −95 src/contrib/markdown/extensions/abbr.py
  84. +0 −224 src/contrib/markdown/extensions/codehilite.py
  85. +0 −104 src/contrib/markdown/extensions/def_list.py
  86. +0 −49 src/contrib/markdown/extensions/extra.py
  87. +0 −117 src/contrib/markdown/extensions/fenced_code.py
  88. +0 −293 src/contrib/markdown/extensions/footnotes.py
  89. +0 −195 src/contrib/markdown/extensions/headerid.py
  90. +0 −62 src/contrib/markdown/extensions/html_tidy.py
  91. +0 −119 src/contrib/markdown/extensions/imagelinks.py
  92. +0 −468 src/contrib/markdown/extensions/legacy.py
  93. +0 −90 src/contrib/markdown/extensions/meta.py
  94. +0 −114 src/contrib/markdown/extensions/rss.py
  95. +0 −97 src/contrib/markdown/extensions/tables.py
  96. +0 −140 src/contrib/markdown/extensions/toc.py
  97. +0 −155 src/contrib/markdown/extensions/wikilinks.py
  98. +0 −274 src/contrib/markdown/html4.py
  99. +0 −371 src/contrib/markdown/inlinepatterns.py
  100. +0 −162 src/contrib/markdown/odict.py
  101. +0 −77 src/contrib/markdown/postprocessors.py
  102. +0 −214 src/contrib/markdown/preprocessors.py
  103. +0 −329 src/contrib/markdown/treeprocessors.py
  104. +88 −0 www/Makefile
  105. +17 −0 www/chep.rst
  106. +26 −0 www/cheps/1_chep.rst
  107. +122 −0 www/cheps/2_import.rst
  108. +36 −0 www/cheps/3_super.rst
  109. +197 −0 www/conf.py
  110. +49 −0 www/developers.rst
  111. +12 −0 www/documentation.rst
  112. +19 −0 www/download.rst
  113. +82 −0 www/index.rst
  114. +112 −0 www/make.bat
  115. +62 −0 www/recipes/inheritance.rst
  116. +59 −0 www/recipes/precompiled.rst
  117. +54 −0 www/recipes/staticmethod.rst
  118. +4 −0 www/recipes/writing_a_recipe.rst
  119. +27 −0 www/roadmap.rst
View
2 BUGS
@@ -1,2 +1,2 @@
-Please see http://bugs.communitycheetah.org
+Please see http://bugs.cheetahtemplate.org
View
11 CHANGES
@@ -1,4 +1,15 @@
+2.2.2 (Unreleased)
+ - Prevent _namemapper.c from segfaulting when PyImport_ImportModule fails for some reason (Bogdano Arendartchuk <debogdano@gmail.com>)
+ - Removal of the contrib/markdown module (in favor of a setuptools dependency)
+ - Default setup.py to use setuptools by default, failing that, fall back to distutils
+
+2.2.1 (June 1st, 2009)
+ - 0000020: [Templates] Builtin support for using Cheetah with Django (rtyler)
+ - 0000021: [Compiler] @static and @classmethod don't properly define the _filter local (rtyler)
+ - 0000023: [Compiler] Update Template super calls to use super() (rtyler)
+ - Update all references to communitycheetah.org to point back at cheetahtemplate.org
+
2.2.0 (May 17th, 2009)
- Switch all internal representations of template code to unicode objects instead of str() objects
- Convert unicode compiled template to an utf8 char buffer when writing to a file (Jean-Baptiste Quenot <jbq@caraldi.com>)
View
57 SetupConfig.py
@@ -1,18 +1,16 @@
#-------Main Package Settings-----------#
-name = "Cheetah"
-from src.Version import Version as version
+name = 'Cheetah'
+from cheetah.Version import Version as version
maintainer = "R. Tyler Ballance"
author = "Tavis Rudd"
author_email = "cheetahtemplate-discuss@lists.sf.net"
-url = "http://www.communitycheetah.org/"
+url = "http://www.cheetahtemplate.org/"
packages = ['Cheetah',
'Cheetah.Macros',
'Cheetah.Templates',
'Cheetah.Tests',
'Cheetah.Tools',
'Cheetah.Utils',
- 'Cheetah.contrib',
- 'Cheetah.contrib.markdown',
]
classifiers = [line.strip() for line in '''\
#Development Status :: 4 - Beta
@@ -31,28 +29,47 @@
Topic :: Text Processing'''.splitlines() if not line.strip().startswith('#')]
del line
-package_dir = {'Cheetah':'src'}
+package_dir = {'Cheetah':'cheetah'}
import os
import os.path
from distutils.core import Extension
-## we only assume the presence of a c compiler on Posix systems, NT people will
-# have to enable this manually.
-if os.name == 'posix':
- ext_modules=[Extension("Cheetah._namemapper", [os.path.join("src" ,"_namemapper.c")]
- )
- ]
-else:
- ext_modules=[]
-
+ext_modules=[
+ Extension("Cheetah._namemapper",
+ [os.path.join('cheetah', 'c', '_namemapper.c')]),
+ Extension("Cheetah._verifytype",
+ [os.path.join('cheetah', 'c', '_verifytype.c')]),
+ Extension("Cheetah._filters",
+ [os.path.join('cheetah', 'c', '_filters.c')]),
+ Extension('Cheetah._template',
+ [os.path.join('cheetah', 'c', '_template.c')]),
+ ]
## Data Files and Scripts
scripts = ['bin/cheetah-compile',
'bin/cheetah',
]
-data_files = ['recursive: src *.tmpl *.txt LICENSE README TODO CHANGES',
- ]
+
+data_files = ['recursive: src *.tmpl *.txt LICENSE README TODO CHANGES',]
+
+if not os.getenv('CHEETAH_INSTALL_WITHOUT_SETUPTOOLS'):
+ try:
+ from setuptools import setup
+ install_requires = [
+ "Markdown >= 2.0.1",
+ ]
+ # use 'entry_points' instead of 'scripts'
+ del scripts
+ entry_points = {
+ 'console_scripts': [
+ 'cheetah = Cheetah.CheetahWrapper:_cheetah',
+ 'cheetah-compile = Cheetah.CheetahWrapper:_cheetah_compile',
+ ]
+ }
+ except ImportError:
+ print 'Not using setuptools, so we cannot install the Markdown dependency'
+
description = "Cheetah is a template engine and code generation tool."
@@ -65,7 +82,7 @@
Documentation
================================================================================
For a high-level introduction to Cheetah please refer to the User\'s Guide
-at http://www.communitycheetah.org/learn.html
+at http://www.cheetahtemplate.org/learn.html
Mailing list
================================================================================
@@ -74,10 +91,10 @@
Credits
================================================================================
-http://www.communitycheetah.org/credits.html
+http://www.cheetahtemplate.org/credits.html
Recent Changes
================================================================================
-See http://www.communitycheetah.org/CHANGES.txt for full details
+See http://www.cheetahtemplate.org/CHANGES.txt for full details
'''
View
20 SetupTools.py
@@ -1,15 +1,4 @@
#!/usr/bin/env python
-# $Id: SetupTools.py,v 1.9 2007/11/03 19:44:38 tavis_rudd Exp $
-"""Some tools for extending and working with distutils
-
-CREDITS: This module borrows code and ideas from M.A. Lemburg's excellent setup
-tools for the mxBase package.
-
-"""
-
-__author__ = "Tavis Rudd <tavis@damnsimple.com>"
-__version__ = "$Revision: 1.9 $"[11:-2]
-
import os
from os import listdir
import os.path
@@ -20,13 +9,8 @@
import traceback
from distutils.core import setup
-if 'CHEETAH_USE_SETUPTOOLS' in os.environ:
- # @@TR: Please note that this is for testing purposes only! PEAK setuptools
- # is not required or recommended for installing Cheetah. Downstream
- # package managers (linux distros, etc.) should *not* enable this.
+if not os.getenv('CHEETAH_INSTALL_WITHOUT_SETUPTOOLS'):
try:
- # use http://peak.telecommunity.com/DevCenter/setuptools if it's installed
- # requires Py >=2.3
from setuptools import setup
except ImportError:
from distutils.core import setup
@@ -35,7 +19,7 @@
from distutils.command.install_data import install_data
#imports from Cheetah ...
-from src.FileUtils import findFiles
+from cheetah.FileUtils import findFiles
##################################################
## CLASSES ##
View
2 TODO
@@ -1,4 +1,4 @@
-NOTE: Please see http://bugs.communitycheetah.org
+NOTE: Please see http://bugs.cheetahtemplate.org
for future feature requests/bugs/TODO
View
4 bin/cheetah
@@ -1,3 +1,3 @@
#!/usr/bin/env python
-from Cheetah.CheetahWrapper import CheetahWrapper
-CheetahWrapper().main()
+from Cheetah.CheetahWrapper import _cheetah
+_cheetah()
View
6 bin/cheetah-compile
@@ -1,5 +1,3 @@
#!/usr/bin/env python
-import sys
-from Cheetah.CheetahWrapper import CheetahWrapper
-sys.argv.insert(1, "compile")
-CheetahWrapper().main()
+from Cheetah.CheetahWrapper import _cheetah_compile
+_cheetah_compile()
View
0 src/CacheRegion.py → cheetah/CacheRegion.py
File renamed without changes.
View
0 src/CacheStore.py → cheetah/CacheStore.py
File renamed without changes.
View
25 src/CheetahWrapper.py → cheetah/CheetahWrapper.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
# $Id: CheetahWrapper.py,v 1.26 2007/10/02 01:22:04 tavis_rudd Exp $
"""Cheetah command-line interface.
@@ -174,7 +173,19 @@ def parseOpts(self, args):
pao("--parallel", action="store", type="int", dest="parallel", default=1, help='Compile/fill templates in parallel, e.g. --parallel=4')
pao('--shbang', dest='shbang', default='#!/usr/bin/env python', help='Specify the shbang to place at the top of compiled templates, e.g. --shbang="#!/usr/bin/python2.6"')
- self.opts, self.pathArgs = opts, files = self.parser.parse_args(args)
+ opts, files = self.parser.parse_args(args)
+ self.opts = opts
+ if sys.platform == "win32":
+ new_files = []
+ for spec in files:
+ file_list = glob.glob(spec)
+ if file_list:
+ new_files.extend(file_list)
+ else:
+ new_files.append(spec)
+ files = new_files
+ self.pathArgs = files
+
D("""\
cheetah compile %s
Options are
@@ -603,6 +614,16 @@ def _compileOrFillBundle(self, b):
f.close()
+# Called when invoked as `cheetah`
+def _cheetah():
+ CheetahWrapper().main()
+
+# Called when invoked as `cheetah-compile`
+def _cheetah_compile():
+ sys.argv.insert(1, "compile")
+ CheetahWrapper().main()
+
+
##################################################
## if run from the command line
if __name__ == '__main__': CheetahWrapper().main()
View
85 src/Compiler.py → cheetah/Compiler.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
'''
Compiler classes for Cheetah:
ModuleCompiler aka 'Compiler'
@@ -106,7 +105,7 @@ class Error(Exception): pass
-class GenUtils:
+class GenUtils(object):
"""An abstract baseclass for the Compiler classes that provides methods that
perform generic utility functions or generate pieces of output code from
information passed in by the Parser baseclass. These methods don't do any
@@ -1077,8 +1076,11 @@ def _addAutoSetupCode(self):
self.addChunk('SL = self._CHEETAH__searchList')
else:
self.addChunk('SL = [KWS]')
- if self.setting('useFilters') and not self.isClassMethod() and not self.isStaticMethod():
- self.addChunk('_filter = self._CHEETAH__currentFilter')
+ if self.setting('useFilters'):
+ if self.isClassMethod() or self.isStaticMethod():
+ self.addChunk('_filter = lambda x, **kwargs: unicode(x)')
+ else:
+ self.addChunk('_filter = self._CHEETAH__currentFilter')
self.addChunk('')
self.addChunk("#" *40)
self.addChunk('## START - generated method body')
@@ -1224,8 +1226,8 @@ def _setupInitMethod(self):
__init__ = self._spawnMethodCompiler('__init__',
klass=self.methodCompilerClassForInit)
__init__.setMethodSignature("def __init__(self, *args, **KWs)")
- __init__.addChunk("%s.__init__(self, *args, **KWs)" % self._baseClass)
- __init__.addChunk(_initMethod_initCheetah%{'className':self._className})
+ __init__.addChunk('super(%s, self).__init__(*args, **KWs)' % self._className)
+ __init__.addChunk(_initMethod_initCheetah % {'className' : self._className})
for chunk in self._initMethChunks:
__init__.addChunk(chunk)
__init__.cleanupState()
@@ -1508,7 +1510,7 @@ def __init__(self, source=None, file=None,
extraImportStatements=None, # list of strings
settings=None # dict
):
- SettingsManager.__init__(self)
+ super(ModuleCompiler, self).__init__()
if settings:
self.updateSettings(settings)
# disable useStackFrames if the C version of NameMapper isn't compiled
@@ -1706,8 +1708,9 @@ def addImportedVarNames(self, varNames, raw_statement=None):
settings = self.settings()
if not varNames:
return
- if self._methodBodyChunks and raw_statement and not settings.get('useLegacyImportMode'):
- self.addChunk(raw_statement)
+ if not settings.get('useLegacyImportMode'):
+ if raw_statement and getattr(self, '_methodBodyChunks'):
+ self.addChunk(raw_statement)
else:
self._importedVarNames.extend(varNames)
@@ -1736,38 +1739,40 @@ def setBaseClass(self, baseClassName):
# - We also assume that the final . separates the classname from the
# module name. This might break if people do something really fancy
# with their dots and namespaces.
- chunks = baseClassName.split('.')
- if len(chunks)==1:
- self._getActiveClassCompiler().setBaseClass(baseClassName)
- if baseClassName not in self.importedVarNames():
- modName = baseClassName
- # we assume the class name to be the module name
- # and that it's not a builtin:
- importStatement = "from %s import %s" % (modName, baseClassName)
- self.addImportStatement(importStatement)
- self.addImportedVarNames( [baseClassName,] )
- else:
- needToAddImport = True
- modName = chunks[0]
- #print chunks, ':', self.importedVarNames()
- for chunk in chunks[1:-1]:
- if modName in self.importedVarNames():
- needToAddImport = False
- finalBaseClassName = baseClassName.replace(modName+'.', '')
- self._getActiveClassCompiler().setBaseClass(finalBaseClassName)
- break
- else:
- modName += '.'+chunk
- if needToAddImport:
- modName, finalClassName = '.'.join(chunks[:-1]), chunks[-1]
- #if finalClassName != chunks[:-1][-1]:
- if finalClassName != chunks[-2]:
+ baseclasses = baseClassName.split(',')
+ for klass in baseclasses:
+ chunks = klass.split('.')
+ if len(chunks)==1:
+ self._getActiveClassCompiler().setBaseClass(klass)
+ if klass not in self.importedVarNames():
+ modName = klass
# we assume the class name to be the module name
- modName = '.'.join(chunks)
- self._getActiveClassCompiler().setBaseClass(finalClassName)
- importStatement = "from %s import %s" % (modName, finalClassName)
- self.addImportStatement(importStatement)
- self.addImportedVarNames( [finalClassName,] )
+ # and that it's not a builtin:
+ importStatement = "from %s import %s" % (modName, klass)
+ self.addImportStatement(importStatement)
+ self.addImportedVarNames((klass,))
+ else:
+ needToAddImport = True
+ modName = chunks[0]
+ #print chunks, ':', self.importedVarNames()
+ for chunk in chunks[1:-1]:
+ if modName in self.importedVarNames():
+ needToAddImport = False
+ finalBaseClassName = klass.replace(modName+'.', '')
+ self._getActiveClassCompiler().setBaseClass(finalBaseClassName)
+ break
+ else:
+ modName += '.'+chunk
+ if needToAddImport:
+ modName, finalClassName = '.'.join(chunks[:-1]), chunks[-1]
+ #if finalClassName != chunks[:-1][-1]:
+ if finalClassName != chunks[-2]:
+ # we assume the class name to be the module name
+ modName = '.'.join(chunks)
+ self._getActiveClassCompiler().setBaseClass(finalClassName)
+ importStatement = "from %s import %s" % (modName, finalClassName)
+ self.addImportStatement(importStatement)
+ self.addImportedVarNames( [finalClassName,] )
def setCompilerSetting(self, key, valueExpr):
self.setSetting(key, eval(valueExpr) )
View
16 cheetah/Django.py
@@ -0,0 +1,16 @@
+import Cheetah.Template
+
+def render(template_file, **kwargs):
+ '''
+ Cheetah.Django.render() takes the template filename
+ (the filename should be a file in your Django
+ TEMPLATE_DIRS)
+
+ Any additional keyword arguments are passed into the
+ template are propogated into the template's searchList
+ '''
+ import django.http
+ import django.template.loader
+ source, loader = django.template.loader.find_template_source(template_file)
+ t = Cheetah.Template.Template(source, searchList=[kwargs])
+ return django.http.HttpResponse(t.__str__())
View
1 src/DummyTransaction.py → cheetah/DummyTransaction.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
'''
Provides dummy Transaction and Response classes is used by Cheetah in place
View
1 src/ErrorCatchers.py → cheetah/ErrorCatchers.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
# $Id: ErrorCatchers.py,v 1.7 2005/01/03 19:59:07 tavis_rudd Exp $
"""ErrorCatcher class for Cheetah Templates
View
1 src/FileUtils.py → cheetah/FileUtils.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
# $Id: FileUtils.py,v 1.12 2005/11/02 22:26:07 tavis_rudd Exp $
"""File utitilies for Python:
View
38 src/Filters.py → cheetah/Filters.py
@@ -1,12 +1,10 @@
-#!/usr/bin/env python
'''
Filters for the #filter directive as well as #transform
#filter results in output filters Cheetah's $placeholders .
#transform results in a filter on the entirety of the output
'''
import sys
-import Cheetah.contrib
# Additional entities WebSafe knows how to transform. No need to include
# '<', '>' or '&' since those will have been done already.
@@ -24,30 +22,26 @@ def __init__(self, template=None):
"""
self.template = template
- def filter(self, val,
- #encoding='utf8',
- encoding=None,
- str=str,
- **kw):
- """Pass Unicode strings through unmolested, unless an encoding is specified.
- """
+ def filter(self, val, encoding=None, str=str, **kw):
+ '''
+ Pass Unicode strings through unmolested, unless an encoding is specified.
+ '''
+ if val is None:
+ return u''
if isinstance(val, unicode):
if encoding:
- filtered = val.encode(encoding)
+ return val.encode(encoding)
else:
- filtered = val
- elif val is None:
- filtered = ''
+ return val
else:
try:
- filtered = str(val)
+ return str(val)
except UnicodeEncodeError:
- filtered = unicode(val)
- return filtered
+ return unicode(val)
+ return u''
RawOrEncodedUnicode = Filter
-
class EncodeUnicode(Filter):
def filter(self, val,
encoding='utf8',
@@ -90,11 +84,8 @@ class Markdown(EncodeUnicode):
def filter(self, value, **kwargs):
# This is a bit of a hack to allow outright embedding of the markdown module
try:
- markdown_path = '/'.join(Cheetah.contrib.__file__.split('/')[:-1])
- sys.path.append(markdown_path)
- from Cheetah.contrib import markdown
- sys.path.pop()
- except:
+ import markdown
+ except ImportError:
print '>>> Exception raised importing the "markdown" module'
print '>>> Are you sure you have the ElementTree module installed?'
print ' http://effbot.org/downloads/#elementtree'
@@ -236,6 +227,7 @@ def test():
print "Unicode:", `EncodeUnicode().filter(u'aoeu12345\u1234')`
-if __name__ == "__main__": test()
+if __name__ == "__main__":
+ test()
# vim: shiftwidth=4 tabstop=4 expandtab
View
1 src/ImportHooks.py → cheetah/ImportHooks.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
# $Id: ImportHooks.py,v 1.27 2007/11/16 18:28:47 tavis_rudd Exp $
"""Provides some import hooks to allow Cheetah's .tmpl files to be imported
View
1 src/ImportManager.py → cheetah/ImportManager.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
# $Id: ImportManager.py,v 1.6 2007/04/03 01:56:24 tavis_rudd Exp $
"""Provides an emulator/replacement for Python's standard import system.
View
0 src/Macros/I18n.py → cheetah/Macros/I18n.py
File renamed without changes.
View
0 src/Utils/__init__.py → cheetah/Macros/__init__.py
File renamed without changes.
View
6 src/NameMapper.py → cheetah/NameMapper.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
# $Id: NameMapper.py,v 1.32 2007/12/10 19:20:09 tavis_rudd Exp $
"""This module supports Cheetah's optional NameMapper syntax.
@@ -160,6 +159,11 @@
'valueFromFrame',
]
+if not hasattr(inspect.imp, 'get_suffixes'):
+ # This is to fix broken behavior of the inspect module under the
+ # Google App Engine, see the following issue:
+ # http://bugs.communitycheetah.org/view.php?id=10
+ setattr(inspect.imp, 'get_suffixes', lambda: [('.py', 'U', 1)])
## N.B. An attempt is made at the end of this module to import C versions of
## these functions. If _namemapper.c has been compiled succesfully and the
View
40 src/Parser.py → cheetah/Parser.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
# $Id: Parser.py,v 1.137 2008/03/10 05:25:13 tavis_rudd Exp $
"""Parser classes for Cheetah's Compiler
@@ -597,6 +596,42 @@ def getMultiLineCommentEndToken(self):
if not match:
raise ParseError(self, msg='Invalid multi-line comment end token')
return self.readTo(match.end())
+
+ def getCommaSeparatedSymbols(self):
+ """
+ Loosely based on getDottedName to pull out comma separated
+ named chunks
+ """
+ srcLen = len(self)
+ pieces = []
+ nameChunks = []
+
+ if not self.peek() in identchars:
+ raise ParseError(self)
+
+ while self.pos() < srcLen:
+ c = self.peek()
+ if c in namechars:
+ nameChunk = self.getIdentifier()
+ nameChunks.append(nameChunk)
+ elif c == '.':
+ if self.pos()+1 <srcLen and self.peek(1) in identchars:
+ nameChunks.append(self.getc())
+ else:
+ break
+ elif c == ',':
+ self.getc()
+ pieces.append(''.join(nameChunks))
+ nameChunks = []
+ elif c in (' ', '\t'):
+ self.getc()
+ else:
+ break
+
+ if nameChunks:
+ pieces.append(''.join(nameChunks))
+
+ return pieces
def getDottedName(self):
srcLen = len(self)
@@ -2038,7 +2073,8 @@ def eatExtends(self):
if self.setting('allowExpressionsInExtendsDirective'):
baseName = self.getExpression()
else:
- baseName = self.getDottedName()
+ baseName = self.getCommaSeparatedSymbols()
+ baseName = ', '.join(baseName)
baseName = self._applyExpressionFilters(baseName, 'extends', startPos=startPos)
self._compiler.setBaseClass(baseName) # in compiler
View
11 src/Servlet.py → cheetah/Servlet.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
'''
Provides an abstract Servlet baseclass for Cheetah's Template class
'''
@@ -49,16 +48,16 @@ class Servlet(BaseServlet):
request = None
session = None
- def __init__(self):
- super(Servlet, self).__init__()
+ def __init__(self, *args, **kwargs):
+ super(Servlet, self).__init__(*args, **kwargs)
# this default will be changed by the .awake() method
self._CHEETAH__isControlledByWebKit = False
## methods called by Webware during the request-response
def awake(self, transaction):
- BaseServlet.awake(self, transaction)
+ super(Servlet, self).awake(transaction)
# a hack to signify that the servlet is being run directly from WebKit
self._CHEETAH__isControlledByWebKit = True
@@ -86,7 +85,7 @@ def respond(self, trans=None):
definition.""")
def sleep(self, transaction):
- BaseServlet.sleep(self, transaction)
+ super(Servlet, self).sleep(transaction)
self.session = None
self.request = None
self._request = None
@@ -102,7 +101,7 @@ def serverSidePath(self, path=None,
):
if self._CHEETAH__isControlledByWebKit:
- return BaseServlet.serverSidePath(self, path)
+ return super(Servlet, self).serverSidePath(path)
elif path:
return normpath(abspath(path.replace("\\",'/')))
elif hasattr(self, '_filePath') and self._filePath:
View
34 src/SettingsManager.py → cheetah/SettingsManager.py
@@ -1,17 +1,3 @@
-"""Provides a mixin/base class for collecting and managing application settings
-
-Meta-Data
-==========
-Author: Tavis Rudd <tavis@damnsimple.com>
-Version: $Revision: 1.30 $
-Start Date: 2001/05/30
-Last Revision Date: $Date: 2008/02/14 03:03:16 $
-"""
-
-# $Id: SettingsManager.py,v 1.30 2008/02/14 03:03:16 tavis_rudd Exp $
-__author__ = "Tavis Rudd <tavis@damnsimple.com>"
-__revision__ = "$Revision: 1.30 $"[11:-2]
-
import sys
import os.path
import copy as copyModule
@@ -25,13 +11,6 @@
from StringIO import StringIO # not cStringIO because of unicode support
import imp # used by SettingsManager.updateSettingsFromPySrcFile()
-##################################################
-## CONSTANTS & GLOBALS ##
-
-try:
- True,False
-except NameError:
- True, False = (1==1),(1==0)
numberRE = re.compile(Number)
complexNumberRE = re.compile('[\(]*' +Number + r'[ \t]*\+[ \t]*' + Number + '[\)]*')
@@ -89,13 +68,10 @@ def convStringToNum(theString):
return eval(theString, {}, {})
-##################################################
-## CLASSES ##
-
class Error(Exception):
pass
-class NoDefault:
+class NoDefault(object):
pass
class ConfigParserCaseSensitive(ConfigParser):
@@ -105,7 +81,7 @@ def optionxform(self, optionstr):
"""Don't change the case as is done in the default implemenation."""
return optionstr
-class _SettingsCollector:
+class _SettingsCollector(object):
"""An abstract base class that provides the methods SettingsManager uses to
collect settings from config files and strings.
@@ -115,9 +91,6 @@ class _SettingsCollector:
_ConfigParserClass = ConfigParserCaseSensitive
- def __init__(self):
- pass
-
def readSettingsFromModule(self, mod, ignoreUnderscored=True):
"""Returns all settings from a Python module.
"""
@@ -230,8 +203,7 @@ class SettingsManager(_SettingsCollector):
"""
def __init__(self):
- """MUST BE CALLED BY SUBCLASSES"""
- _SettingsCollector.__init__(self)
+ super(SettingsManager, self).__init__()
self._settings = {}
self._initializeSettings()
View
1 src/SourceReader.py → cheetah/SourceReader.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
# $Id: SourceReader.py,v 1.15 2007/04/03 01:57:42 tavis_rudd Exp $
"""SourceReader class for Cheetah's Parser and CodeGenerator
View
100 src/Template.py → cheetah/Template.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
'''
Provides the core API for Cheetah.
@@ -26,11 +25,6 @@
from types import StringTypes
except ImportError:
StringTypes = (types.StringType,types.UnicodeType)
-try:
- from types import BooleanType
- boolTypeAvailable = True
-except ImportError:
- boolTypeAvailable = False
try:
from threading import Lock
@@ -57,7 +51,14 @@ def release(self):
from Cheetah import ErrorCatchers # for placeholder tags
from Cheetah import Filters # the output filters
from Cheetah.convertTmplPathToModuleName import convertTmplPathToModuleName
-from Cheetah.Utils import VerifyType # Used in Template.__init__
+
+try:
+ from Cheetah._verifytype import *
+except ImportError:
+ from Cheetah.Utils import VerifyType
+ verifyType = VerifyType.VerifyType
+ verifyTypeClass = VerifyType.VerifyTypeClass
+
from Cheetah.Utils.Misc import checkKeywords # Used in Template.__init__
from Cheetah.Utils.Indenter import Indenter # Used in Template.__init__ and for
# placeholders
@@ -118,11 +119,14 @@ def _genUniqueModuleName(baseModuleName):
# This is only relavent to templates used as CGI scripts.
_formUsedByWebInput = None
-# used in Template.compile()
-def valOrDefault(val, default):
- if val is not Unspecified:
- return val
- return default
+try:
+ from Cheetah._template import valOrDefault
+except ImportError:
+ # used in Template.compile()
+ def valOrDefault(val, default):
+ if val is not Unspecified:
+ return val
+ return default
def updateLinecache(filename, src):
import linecache
@@ -593,74 +597,70 @@ def __str__(self): return self.respond()
##################################################
## normalize and validate args
try:
- vt = VerifyType.VerifyType
- vtc = VerifyType.VerifyTypeClass
+ vt = verifyType
+ vtc = verifyTypeClass
N = types.NoneType; S = types.StringType; U = types.UnicodeType
D = types.DictType; F = types.FileType
C = types.ClassType; M = types.ModuleType
- I = types.IntType
+ I = types.IntType; B = types.BooleanType
- if boolTypeAvailable:
- B = types.BooleanType
-
- vt(source, 'source', [N,S,U], 'string or None')
- vt(file, 'file',[N,S,U,F], 'string, file-like object, or None')
+ IB = (I, B)
+ NS = (N, S)
+
+ vt(source, 'source', (N,S,U), 'string or None')
+ vt(file, 'file',(N,S,U,F), 'string, file-like object, or None')
baseclass = valOrDefault(baseclass, klass._CHEETAH_defaultBaseclassForTemplates)
if isinstance(baseclass, Template):
baseclass = baseclass.__class__
- vt(baseclass, 'baseclass', [N,S,C,type], 'string, class or None')
+ vt(baseclass, 'baseclass', (N,S,C,type), 'string, class or None')
cacheCompilationResults = valOrDefault(
cacheCompilationResults, klass._CHEETAH_cacheCompilationResults)
- if boolTypeAvailable:
- vt(cacheCompilationResults, 'cacheCompilationResults', [I,B], 'boolean')
+ vt(cacheCompilationResults, 'cacheCompilationResults', IB, 'boolean')
useCache = valOrDefault(useCache, klass._CHEETAH_useCompilationCache)
- if boolTypeAvailable:
- vt(cacheCompilationResults, 'cacheCompilationResults', [I,B], 'boolean')
+ vt(useCache, 'useCache', IB, 'boolean')
compilerSettings = valOrDefault(
compilerSettings, klass._getCompilerSettings(source, file) or {})
- vt(compilerSettings, 'compilerSettings', [D], 'dictionary')
+ vt(compilerSettings, 'compilerSettings', (D,), 'dictionary')
compilerClass = valOrDefault(compilerClass, klass._getCompilerClass(source, file))
preprocessors = valOrDefault(preprocessors, klass._CHEETAH_preprocessors)
keepRefToGeneratedCode = valOrDefault(
keepRefToGeneratedCode, klass._CHEETAH_keepRefToGeneratedCode)
- if boolTypeAvailable:
- vt(cacheCompilationResults, 'cacheCompilationResults', [I,B], 'boolean')
-
- vt(moduleName, 'moduleName', [N,S], 'string or None')
+ vt(keepRefToGeneratedCode, 'keepRefToGeneratedCode', IB, 'boolean')
+
+ vt(moduleName, 'moduleName', NS, 'string or None')
__orig_file__ = None
if not moduleName:
if file and type(file) in StringTypes:
moduleName = convertTmplPathToModuleName(file)
__orig_file__ = file
else:
moduleName = klass._CHEETAH_defaultModuleNameForTemplates
-
+
className = valOrDefault(
className, klass._CHEETAH_defaultClassNameForTemplates)
- vt(className, 'className', [N,S], 'string or None')
+ vt(className, 'className', NS, 'string or None')
className = className or moduleName
mainMethodName = valOrDefault(
mainMethodName, klass._CHEETAH_defaultMainMethodNameForTemplates)
- vt(mainMethodName, 'mainMethodName', [N,S], 'string or None')
+ vt(mainMethodName, 'mainMethodName', NS, 'string or None')
moduleGlobals = valOrDefault(
moduleGlobals, klass._CHEETAH_defaultModuleGlobalsForTemplates)
cacheModuleFilesForTracebacks = valOrDefault(
cacheModuleFilesForTracebacks, klass._CHEETAH_cacheModuleFilesForTracebacks)
- if boolTypeAvailable:
- vt(cacheModuleFilesForTracebacks, 'cacheModuleFilesForTracebacks', [I,B], 'boolean')
-
+ vt(cacheModuleFilesForTracebacks, 'cacheModuleFilesForTracebacks', IB, 'boolean')
+
cacheDirForModuleFiles = valOrDefault(
cacheDirForModuleFiles, klass._CHEETAH_cacheDirForModuleFiles)
- vt(cacheDirForModuleFiles, 'cacheDirForModuleFiles', [N,S], 'string or None')
+ vt(cacheDirForModuleFiles, 'cacheDirForModuleFiles', NS, 'string or None')
except TypeError, reason:
raise TypeError(reason)
@@ -1145,26 +1145,24 @@ def __init__(self, source=None,
D = types.DictType; F = types.FileType
C = types.ClassType; M = types.ModuleType
N = types.NoneType
- vt = VerifyType.VerifyType
- vtc = VerifyType.VerifyTypeClass
+ vt = verifyType
+ vtc = verifyTypeClass
try:
- vt(source, 'source', [N,S,U], 'string or None')
- vt(file, 'file', [N,S,U,F], 'string, file open for reading, or None')
- vtc(filter, 'filter', [S,C,type], 'string or class',
+ vt(source, 'source', (N,S,U), 'string or None')
+ vt(file, 'file', (N,S,U,F), 'string, file open for reading, or None')
+ vtc(filter, 'filter', (S,C,type), 'string or class',
Filters.Filter,
'(if class, must be subclass of Cheetah.Filters.Filter)')
- vt(filtersLib, 'filtersLib', [S,M], 'string or module',
+ vt(filtersLib, 'filtersLib', (S,M), 'string or module',
'(if module, must contain subclasses of Cheetah.Filters.Filter)')
- vtc(errorCatcher, 'errorCatcher', [N,S,C,type], 'string, class or None',
+ vtc(errorCatcher, 'errorCatcher', (N,S,C,type), 'string, class or None',
ErrorCatchers.ErrorCatcher,
'(if class, must be subclass of Cheetah.ErrorCatchers.ErrorCatcher)')
if compilerSettings is not Unspecified:
- vt(compilerSettings, 'compilerSettings', [D], 'dictionary')
+ vt(compilerSettings, 'compilerSettings', (D,), 'dictionary')
- except TypeError, reason:
- # Re-raise the exception here so that the traceback will end in
- # this function rather than in some utility function.
- raise TypeError(reason)
+ except TypeError:
+ raise
if source is not None and file is not None:
raise TypeError("you must supply either a source string or the" +
@@ -1465,7 +1463,7 @@ def _initCheetahInstance(self,
# @@TR: consider allowing simple callables as the filter argument
self._CHEETAH__filtersLib = filtersLib
self._CHEETAH__filters = {}
- if type(filter) in StringTypes:
+ if isinstance(filter, basestring):
filterName = filter
klass = getattr(self._CHEETAH__filtersLib, filterName)
else:
@@ -1476,7 +1474,7 @@ def _initCheetahInstance(self,
self._CHEETAH__errorCatchers = {}
if errorCatcher:
- if type(errorCatcher) in StringTypes:
+ if isinstance(errorCatcher, basestring):
errorCatcherClass = getattr(ErrorCatchers, errorCatcher)
elif type(errorCatcher) == ClassType:
errorCatcherClass = errorCatcher
View
1 src/TemplateCmdLineIface.py → cheetah/TemplateCmdLineIface.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
# $Id: TemplateCmdLineIface.py,v 1.13 2006/01/10 20:34:35 tavis_rudd Exp $
"""Provides a command line interface to compiled Cheetah template modules.
View
1 src/Templates/SkeletonPage.py → cheetah/Templates/SkeletonPage.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
"""A Skeleton HTML page template, that provides basic structure and utility methods.
View
0 src/Templates/SkeletonPage.tmpl → cheetah/Templates/SkeletonPage.tmpl
File renamed without changes.
View
1 src/Templates/_SkeletonPage.py → cheetah/Templates/_SkeletonPage.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
# $Id: _SkeletonPage.py,v 1.13 2002/10/01 17:52:02 tavis_rudd Exp $
"""A baseclass for the SkeletonPage template
View
1 cheetah/Templates/__init__.py
@@ -0,0 +1 @@
+
View
97 src/Tests/CheetahWrapper.py → cheetah/Tests/CheetahWrapper.py
@@ -11,10 +11,14 @@
--output
Show the output of each subcommand. (Normally suppressed.)
'''
-import commands, os, shutil, sys, tempfile
-import unittest_local_copy as unittest
-
+import os
+import popen2
import re # Used by listTests.
+import shutil
+import sys
+import tempfile
+import unittest
+
from optparse import OptionParser
from Cheetah.CheetahWrapper import CheetahWrapper # Used by NoBackup.
@@ -137,6 +141,38 @@ def checkNoBackup(self, path):
msg = "backup file exists in spite of --nobackup: %s" % path
self.failIf(exists, msg)
+
+ def assertWin32Subprocess(self, cmd):
+ _in, _out = os.popen4(cmd)
+ _in.close()
+ output = _out.read()
+ rc = _out.close()
+ if rc is None:
+ rc = 0
+ return rc, output
+
+ def assertPosixSubprocess(self, cmd):
+ process = popen2.Popen4(cmd)
+ process.tochild.close()
+ output = process.fromchild.read()
+ status = process.wait()
+ process.fromchild.close()
+ return status, output
+
+ def assertSubprocess(self, cmd, nonzero=False):
+ status, output = None, None
+ if sys.platform == 'win32':
+ status, output = self.assertWin32Subprocess(cmd)
+ else:
+ status, output = self.assertPosixSubprocess(cmd)
+
+ if not nonzero:
+ self.failUnlessEqual(status, 0, '''Subprocess exited with a non-zero status (%d)
+ %s''' % (status, output))
+ else:
+ self.failIfEqual(status, 0, '''Subprocess exited with a zero status (%d)
+ %s''' % (status, output))
+ return output
def go(self, cmd, expectedStatus=0, expectedOutputSubstring=None):
"""Run a "cheetah compile" or "cheetah fill" subcommand.
@@ -149,55 +185,14 @@ def go(self, cmd, expectedStatus=0, expectedOutputSubstring=None):
test.
out: None.
"""
- # Use commands.getstatusoutput instead of os.system so
- # that we can mimic ">/dev/null 2>/dev/null" even on
- # non-Unix platforms.
- exit, output = commands.getstatusoutput(cmd)
- status, signal = divmod(exit, 256)
- if OUTPUT:
- if output.endswith("\n"):
- output = output[:-1]
- print
- print "SUBCOMMAND:", cmd
- print output
- print
- msg = "subcommand killed by signal %d: %s" % (signal, cmd)
- self.failUnlessEqual(signal, 0, msg)
- msg = "subcommand exit status %d: %s" % (status, cmd)
- if status!=expectedStatus:
- print output
- self.failUnlessEqual(status, expectedStatus, msg)
+ output = self.assertSubprocess(cmd)
if expectedOutputSubstring is not None:
msg = "substring %r not found in subcommand output: %s" % \
(expectedOutputSubstring, cmd)
substringTest = output.find(expectedOutputSubstring) != -1
self.failUnless(substringTest, msg)
- def goExpectError(self, cmd):
- """Run a subcommand and expect it to fail.
-
- in : cmd, string, the command to run.
- out: None.
- """
- # Use commands.getstatusoutput instead of os.system so
- # that we can mimic ">/dev/null 2>/dev/null" even on
- # non-Unix platforms.
- exit, output = commands.getstatusoutput(cmd)
- status, signal = divmod(exit, 256)
- msg = "subcommand killed by signal %s: %s" % (signal, cmd)
- self.failUnlessEqual(signal, 0, msg) # Signal must be 0.
- msg = "subcommand exit status %s: %s" % (status, cmd)
- self.failIfEqual(status, 0, msg) # Status must *not* be 0.
- if OUTPUT:
- if output.endswith("\n"):
- output = output[:-1]
- print
- print "SUBCOMMAND:", cmd
- print output
- print
-
-
class CFIdirBase(CFBase):
"""Subclass for tests with --idir.
"""
@@ -422,13 +417,13 @@ class FlatRecurseCollision(CFBase):
expectError = True
def testCompile(self):
- self.goExpectError("cheetah compile -R --flat")
+ self.assertSubprocess("cheetah compile -R --flat", nonzero=True)
def testFill(self):
- self.goExpectError("cheetah fill -R --flat")
+ self.assertSubprocess("cheetah fill -R --flat", nonzero=True)
def testText(self):
- self.goExpectError("cheetah fill -R --flat")
+ self.assertSubprocess("cheetah fill -R --flat", nonzero=True)
class IdirRecurse(CFIdirBase):
@@ -473,13 +468,13 @@ class IdirFlatRecurseCollision(CFIdirBase):
expectError = True
def testCompile(self):
- self.goExpectError("cheetah compile -R --flat --idir SRC")
+ self.assertSubprocess("cheetah compile -R --flat --idir SRC", nonzero=True)
def testFill(self):
- self.goExpectError("cheetah fill -R --flat --idir SRC")
+ self.assertSubprocess("cheetah fill -R --flat --idir SRC", nonzero=True)
def testText(self):
- self.goExpectError("cheetah fill -R --flat --idir SRC --oext txt")
+ self.assertSubprocess("cheetah fill -R --flat --idir SRC --oext txt", nonzero=True)
class NoBackup(CFBase):
View
39 cheetah/Tests/Cheps.py
@@ -0,0 +1,39 @@
+#!/usr/bin/env python
+
+import unittest
+
+import Cheetah
+import Cheetah.Parser
+import Cheetah.Template
+
+class Chep_2_Conditionalized_Import_Behavior(unittest.TestCase):
+ def test_ModuleLevelImport(self):
+ ''' Verify module level (traditional) import behavior '''
+ pass
+
+ def test_InlineImport(self):
+ ''' Verify (new) inline import behavior works '''
+ template = '''
+ #def funky($s)
+ #try
+ #import urllib
+ #except ImportError
+ #pass
+ #end try
+ #return urllib.quote($s)
+ #end def
+ '''
+ try:
+ template = Cheetah.Template.Template.compile(template)
+ except Cheetah.Parser.ParseError, ex:
+ self.fail('Failed to properly generate code %s' % ex)
+ template = template()
+ rc = tepmlate.funky('abc def')
+ assert rc == 'abc+def'
+
+ def test_LegacyMode(self):
+ ''' Verify disabling of CHEP #2 works '''
+ pass
+
+if __name__ == '__main__':
+ unittest.main()
View
5 src/Tests/Filters.py → cheetah/Tests/Filters.py
@@ -7,6 +7,9 @@
import unittest_local_copy as unittest
+majorVer, minorVer = sys.version_info[0], sys.version_info[1]
+versionTuple = (majorVer, minorVer)
+
class BasicMarkdownFilterTest(unittest.TestCase):
'''
Test that our markdown filter works
@@ -27,7 +30,7 @@ def test_BasicHeader(self):
template = str(template)
assert template == expected
except Exception, ex:
- if ex.__class__.__name__ == 'MarkdownException' and sys.version_info[0] == 2 and sys.version_info[1] < 5:
+ if ex.__class__.__name__ == 'MarkdownException' and majorVer == 2 and minorVer < 5:
print '>>> NOTE: Support for the Markdown filter will be broken for you. Markdown says: %s' % ex
return
raise
View
19 src/Tests/NameMapper.py → cheetah/Tests/NameMapper.py
@@ -1,30 +1,17 @@
#!/usr/bin/env python
-# $Id: NameMapper.py,v 1.11 2006/01/15 20:45:22 tavis_rudd Exp $
-"""NameMapper Tests
-
-Meta-Data
-================================================================================
-Author: Tavis Rudd <tavis@damnsimple.com>,
-Version: $Revision: 1.11 $
-Start Date: 2001/10/01
-Last Revision Date: $Date: 2006/01/15 20:45:22 $
-"""
+
from __future__ import generators
-__author__ = "Tavis Rudd <tavis@damnsimple.com>"
-__revision__ = "$Revision: 1.11 $"[11:-2]
import sys
import types
import os
import os.path
-import unittest_local_copy as unittest
+#import unittest_local_copy as unittest
+import unittest
from Cheetah.NameMapper import NotFound, valueForKey, \
valueForName, valueFromSearchList, valueFromFrame, valueFromFrameOrSearchList
-##################################################
-## TEST DATA FOR USE IN THE TEMPLATES ##
-
class DummyClass:
classVar1 = 123
View
106 src/Tests/Regressions.py → cheetah/Tests/Regressions.py
@@ -2,10 +2,19 @@
import Cheetah.NameMapper
import Cheetah.Template
+
import pdb
+import sys
import unittest_local_copy as unittest # This is just stupid
+majorVer, minorVer = sys.version_info[0], sys.version_info[1]
+versionTuple = (majorVer, minorVer)
+
+def isPython23():
+ ''' Python 2.3 is still supported by Cheetah, but doesn't support decorators '''
+ return majorVer == 2 and minorVer < 4
+
class GetAttrException(Exception):
pass
@@ -137,6 +146,103 @@ def test_FailingBehaviorWithSetting(self):
assert template
assert template.respond()
+class Mantis_Issue_21_Regression_Test(unittest.TestCase):
+ '''
+ Test case for bug outlined in issue #21
+
+ Effectively @staticmethod and @classmethod
+ decorated methods in templates don't
+ properly define the _filter local, which breaks
+ when using the NameMapper
+ '''
+ def runTest(self):
+ if isPython23():
+ return
+ template = '''
+ #@staticmethod
+ #def testMethod()
+ This is my $output
+ #end def
+ '''
+ template = Cheetah.Template.Template.compile(template)
+ assert template
+ assert template.testMethod(output='bug') # raises a NameError: global name '_filter' is not defined
+
+
+class Mantis_Issue_22_Regression_Test(unittest.TestCase):
+ '''
+ Test case for bug outlined in issue #22
+
+ When using @staticmethod and @classmethod
+ in conjunction with the #filter directive
+ the generated code for the #filter is reliant
+ on the `self` local, breaking the function
+ '''
+ def test_NoneFilter(self):
+ # XXX: Disabling this test for now
+ return
+ if isPython23():
+ return
+ template = '''
+ #@staticmethod
+ #def testMethod()
+ #filter None
+ This is my $output
+ #end filter
+ #end def
+ '''
+ template = Cheetah.Template.Template.compile(template)
+ assert template
+ assert template.testMethod(output='bug')
+
+ def test_DefinedFilter(self):
+ # XXX: Disabling this test for now
+ return
+ if isPython23():
+ return
+ template = '''
+ #@staticmethod
+ #def testMethod()
+ #filter Filter
+ This is my $output
+ #end filter
+ #end def
+ '''
+ # The generated code for the template's testMethod() should look something
+ # like this in the 'error' case:
+ '''
+ @staticmethod
+ def testMethod(**KWS):
+ ## CHEETAH: generated from #def testMethod() at line 3, col 13.
+ trans = DummyTransaction()
+ _dummyTrans = True
+ write = trans.response().write
+ SL = [KWS]
+ _filter = lambda x, **kwargs: unicode(x)
+
+ ########################################
+ ## START - generated method body
+
+ _orig_filter_18517345 = _filter
+ filterName = u'Filter'
+ if self._CHEETAH__filters.has_key("Filter"):
+ _filter = self._CHEETAH__currentFilter = self._CHEETAH__filters[filterName]
+ else:
+ _filter = self._CHEETAH__currentFilter = \
+ self._CHEETAH__filters[filterName] = getattr(self._CHEETAH__filtersLib, filterName)(self).filter
+ write(u' This is my ')
+ _v = VFFSL(SL,"output",True) # u'$output' on line 5, col 32
+ if _v is not None: write(_filter(_v, rawExpr=u'$output')) # from line 5, col 32.
+
+ ########################################
+ ## END - generated method body
+
+ return _dummyTrans and trans.response().getvalue() or ""
+ '''
+ template = Cheetah.Template.Template.compile(template)
+ assert template
+ assert template.testMethod(output='bug')
+
if __name__ == '__main__':
unittest.main()
View
13 src/Tests/SyntaxAndOutput.py → cheetah/Tests/SyntaxAndOutput.py
@@ -33,21 +33,12 @@
from Cheetah.Compiler import Compiler, DEFAULT_COMPILER_SETTINGS
import unittest_local_copy as unittest
-class Unspecified: pass
-##################################################
-## CONSTANTS & GLOBALS ##
+class Unspecified(object):
+ pass
majorVer, minorVer = sys.version_info[0], sys.version_info[1]
versionTuple = (majorVer, minorVer)
-try:
- True,False
-except NameError:
- True, False = (1==1),(1==0)
-
-##################################################
-## TEST DATA FOR USE IN THE TEMPLATES ##
-
def testdecorator(func):
return func
View
51 src/Tests/Template.py → cheetah/Tests/Template.py
@@ -1,21 +1,6 @@
#!/usr/bin/env python
-# $Id: Template.py,v 1.16 2006/02/03 21:05:50 tavis_rudd Exp $
-"""Tests of the Template class API
-
-Meta-Data
-================================================================================
-Author: Tavis Rudd <tavis@damnsimple.com>,
-Version: $Revision: 1.16 $
-Start Date: 2001/10/01
-Last Revision Date: $Date: 2006/02/03 21:05:50 $
-"""
-__author__ = "Tavis Rudd <tavis@damnsimple.com>"
-__revision__ = "$Revision: 1.16 $"[11:-2]
-
-
-##################################################
-## DEPENDENCIES ##
+import pdb
import sys
import types
import os
@@ -25,29 +10,12 @@
import unittest_local_copy as unittest
from Cheetah.Template import Template
-##################################################
-## CONSTANTS & GLOBALS ##
-
majorVer, minorVer = sys.version_info[0], sys.version_info[1]
versionTuple = (majorVer, minorVer)
-try:
- True,False
-except NameError:
- True, False = (1==1),(1==0)
-
-##################################################
-## TEST DATA FOR USE IN THE TEMPLATES ##
-
-##################################################
-## TEST BASE CLASSES
-
class TemplateTest(unittest.TestCase):
pass
-##################################################
-## TEST CASE CLASSES
-
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().
@@ -358,7 +326,24 @@ def test_BasicDecorator(self):
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
##################################################
View
6 src/Tests/Test.py → cheetah/Tests/Test.py
@@ -19,6 +19,7 @@
import NameMapper
import Template
import CheetahWrapper
+import Cheps
import Regressions
import Unicode
@@ -28,6 +29,7 @@
unittest.findTestCases(Template),
unittest.findTestCases(Regressions),
unittest.findTestCases(Unicode),
+ unittest.findTestCases(Cheps),
]
if not sys.platform.startswith('java'):
@@ -41,7 +43,3 @@
results = runner.run(unittest.TestSuite(suites))
-
-
-
-
View
25 src/Tests/Unicode.py → cheetah/Tests/Unicode.py
@@ -24,8 +24,8 @@ def createAndCompile(self, source):
wrap = CheetahWrapper.CheetahWrapper()
wrap.main(['cheetah', 'compile', '--nobackup', sourcefile])
- module_name = os.path.basename(sourcefile)
- module = loadModule(module_name, ['/tmp'])
+ module_path, module_name = os.path.split(sourcefile)
+ module = loadModule(module_name, [module_path])
template = getattr(module, module_name)
return template
@@ -131,6 +131,27 @@ def runTest(self):
assert unicode(template())
+class JBQ_UTF8_Test8(CommandLineTest):
+ def testStaticCompile(self):
+ source = """#encoding utf-8
+#set $someUnicodeString = u"Bébé"
+$someUnicodeString"""
+
+ template = self.createAndCompile(source)()
+
+ a = unicode(template).encode("utf-8")
+ self.assertEquals("Bébé", a)
+
+ def testDynamicCompile(self):
+ source = """#encoding utf-8
+#set $someUnicodeString = u"Bébé"
+$someUnicodeString"""
+
+ template = Template(source = source)
+
+ a = unicode(template).encode("utf-8")
+ self.assertEquals("Bébé", a)
+
class Unicode_in_SearchList_Test(CommandLineTest):
def test_BasicASCII(self):
source = '''This is $adjective'''
View
0 src/Tools/turbocheetah/tests/__init__.py → cheetah/Tests/__init__.py
File renamed without changes.
View
0 src/Tests/unittest_local_copy.py → cheetah/Tests/unittest_local_copy.py
File renamed without changes.
View
0 src/Tests/xmlrunner.py → cheetah/Tests/xmlrunner.py
File renamed without changes.
View
1 src/Tools/CGITemplate.py → cheetah/Tools/CGITemplate.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
# $Id: CGITemplate.py,v 1.6 2006/01/29 02:09:59 tavis_rudd Exp $
"""A subclass of Cheetah.Template for use in CGI scripts.
View
1 src/Tools/MondoReport.py → cheetah/Tools/MondoReport.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
"""
@@TR: This code is pretty much unsupported.
View
0 src/Tools/MondoReportDoc.txt → cheetah/Tools/MondoReportDoc.txt
File renamed without changes.
View
1 src/Tools/RecursiveNull.py → cheetah/Tools/RecursiveNull.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
"""
Nothing, but in a friendly way. Good for filling in for objects you want to
hide. If $form.f1 is a RecursiveNull object, then
View
1 src/Tools/SiteHierarchy.py → cheetah/Tools/SiteHierarchy.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
# $Id: SiteHierarchy.py,v 1.1 2001/10/11 03:25:54 tavis_rudd Exp $
"""Create menus and crumbs from a site hierarchy.
View
0 src/Tools/__init__.py → cheetah/Tools/__init__.py
File renamed without changes.
View
0 src/Tools/turbocheetah/__init__.py → cheetah/Tools/turbocheetah/__init__.py
File renamed without changes.
View
0 src/Tools/turbocheetah/cheetahsupport.py → cheetah/Tools/turbocheetah/cheetahsupport.py
File renamed without changes.
View
0 src/Tests/__init__.py → cheetah/Tools/turbocheetah/tests/__init__.py
File renamed without changes.
View
0 ...Tools/turbocheetah/tests/test_template.py → ...Tools/turbocheetah/tests/test_template.py
File renamed without changes.
View
0 src/Unspecified.py → cheetah/Unspecified.py
File renamed without changes.
View
36 src/Utils/Indenter.py → cheetah/Utils/Indenter.py
@@ -1,6 +1,5 @@
-#!/usr/bin/env python
-# $Id: Indenter.py,v 1.7 2006/01/08 01:09:30 tavis_rudd Exp $
-"""Indentation maker.
+"""
+Indentation maker.
@@TR: this code is unsupported and largely undocumented ...
This version is based directly on code by Robert Kuzelj
@@ -9,26 +8,15 @@
$self._CHEETAH__indenter.indent() to prevent '_indenter' being looked up on the
searchList and another one being found. The directive syntax will
soon be changed somewhat.
-
-Meta-Data
-================================================================================
-Author: Mike Orr <iron@mso.oz.net>
-License: This software is released for unlimited distribution under the
- terms of the MIT license. See the LICENSE file.
-Version: $Revision: 1.7 $
-Start Date: 2001/11/07
-Last Revision Date: $Date: 2006/01/08 01:09:30 $
"""
-__author__ = "Mike Orr <iron@mso.oz.net>"
-__revision__ = "$Revision: 1.7 $"[11:-2]
import re
import sys
def indentize(source):
return IndentProcessor().process(source)
-class IndentProcessor:
+class IndentProcessor(object):
"""Preprocess #indent tags."""
LINE_SEP = '\n'
ARGS = "args"
@@ -89,15 +77,16 @@ def process(self, _txt):
return self.LINE_SEP.join(result)
-class Indenter:
- """A class that keeps track of the current indentation level.
+class Indenter(object):
+ """
+ A class that keeps track of the current indentation level.
.indent() returns the appropriate amount of indentation.
"""
- def __init__(self):
- self.On = 1
- self.Level = 0
- self.Chars = " "*4
- self.LevelStack = []
+ On = 1
+ Level = 0
+ Chars = ' '
+ LevelStack = []
+
def on(self):
self.On = 1
def off(self):
@@ -130,6 +119,5 @@ def setChar(self, _chars):
def indent(self, _default=0):
if self.On:
return self.Chars * self.Level
- else:
- return " " * _default
+ return " " * _default
View
1 src/Utils/Misc.py → cheetah/Utils/Misc.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
# $Id: Misc.py,v 1.8 2005/11/02 22:26:08 tavis_rudd Exp $
"""Miscellaneous functions/objects used by Cheetah but also useful standalone.
View
3 src/Utils/VerifyType.py → cheetah/Utils/VerifyType.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
# $Id: VerifyType.py,v 1.4 2005/11/02 22:26:08 tavis_rudd Exp $
"""Functions to verify an argument's type
@@ -52,6 +51,7 @@ def VerifyType(arg, argname, legalTypes, ltd, errmsgExtra=''):
if type(arg) not in legalTypes:
m = _errmsg(argname, ltd, errmsgExtra)
raise TypeError(m)
+ return True
def VerifyTypeClass(arg, argname, legalTypes, ltd, klass, errmsgExtra=''):
@@ -72,6 +72,7 @@ def VerifyTypeClass(arg, argname, legalTypes, ltd, klass, errmsgExtra=''):
# Must test for "is class type" to avoid TypeError from issubclass().
m = _errmsg(argname, ltd, errmsgExtra)
raise TypeError(m)
+ return True
# @@MO: Commented until we determine whether it's useful.
#def VerifyClass(arg, argname, klass, ltd):
View
1 src/Utils/WebInputMixin.py → cheetah/Utils/WebInputMixin.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
# $Id: WebInputMixin.py,v 1.10 2006/01/06 21:56:54 tavis_rudd Exp $
"""Provides helpers for Template.webInput(), a method for importing web
transaction variables in bulk. See the docstring of webInput for full details.
View
0 src/Macros/__init__.py → cheetah/Utils/__init__.py
File renamed without changes.
View
0 src/Utils/htmlDecode.py → cheetah/Utils/htmlDecode.py
File renamed without changes.
View
0 src/Utils/htmlEncode.py → cheetah/Utils/htmlEncode.py
File renamed without changes.
View
1 src/Utils/memcache.py → cheetah/Utils/memcache.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
"""
client module for memcached (memory cache daemon)
View
0 src/Utils/statprof.py → cheetah/Utils/statprof.py
File renamed without changes.
View
4 src/Version.py → cheetah/Version.py
@@ -1,5 +1,5 @@
-Version = '2.2.0.1'
-VersionTuple = (2, 2, 0, 1, 'final', 0)
+Version = '2.2.2.1'
+VersionTuple = (2, 2, 2, 1, 'candidate', 0)
MinCompatibleVersion = '2.0rc6'
MinCompatibleVersionTuple = (2,0,0,'candidate',6)
View
2 src/__init__.py → cheetah/__init__.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
'''
Cheetah is an open source template engine and code generation tool.
View
47 cheetah/c/Cheetah.h
@@ -0,0 +1,47 @@
+/*
+ * (c) 2009, R. Tyler Ballance <tyler@slide.com>
+ */
+
+#ifndef _CHEETAH_H_
+#define _CHEETAH_H_
+
+#include <Python.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Python 2.3 compatibility
+ */
+#ifndef Py_RETURN_TRUE
+#define Py_RETURN_TRUE Py_INCREF(Py_True);\
+ return Py_True
+#endif
+#ifndef Py_RETURN_FALSE
+#define Py_RETURN_FALSE Py_INCREF(Py_False);\
+ return Py_False
+#endif
+#ifndef Py_RETURN_NONE
+#define Py_RETURN_NONE Py_INCREF(Py_None);\
+ return Py_None
+#endif
+
+
+/*
+ * Filter Module
+ */
+typedef struct {
+ PyObject_HEAD
+ /* type specific fields */
+} PyFilter;
+
+/*
+ * End Filter Module
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
View
93 cheetah/c/_filters.c
@@ -0,0 +1,93 @@
+/*
+ * C-version of the src/Filters.py module
+ *
+ * (c) 2009, R. Tyler Ballance <tyler@slide.com>
+ */
+#include <Python.h>
+
+#include "Cheetah.h"