From bf8648bd1b8647eef3dccaed2a34c78ba8715d3c Mon Sep 17 00:00:00 2001 From: Hyunjee Kim Date: Thu, 9 Apr 2020 15:44:17 +0900 Subject: Imported Upstream version 3.2.0 Change-Id: I989e6464b6855bab648938a2200c74a66f2e501c Signed-off-by: Hyunjee Kim --- .travis.yml | 41 +- ANNOUNCE.rst | 43 +- Cheetah/CacheRegion.py | 8 +- Cheetah/CheetahWrapper.py | 8 +- Cheetah/Compiler.py | 177 +- Cheetah/ErrorCatchers.py | 2 +- Cheetah/FileUtils.py | 4 +- Cheetah/Filters.py | 2 +- Cheetah/ImportHooks.py | 35 +- Cheetah/ImportManager.py | 54 +- Cheetah/LoadTemplate.py | 56 + Cheetah/Macros/I18n.py | 2 +- Cheetah/NameMapper.py | 10 +- Cheetah/Parser.py | 210 +- Cheetah/SettingsManager.py | 2 +- Cheetah/SourceReader.py | 24 +- Cheetah/Template.py | 117 +- Cheetah/TemplateCmdLineIface.py | 2 +- Cheetah/Templates/_SkeletonPage.py | 2 +- Cheetah/Tests/Filters.py | 2 +- Cheetah/Tests/ImportHooks.py | 81 + Cheetah/Tests/ImportHooksTemplates/index.tmpl | 5 + Cheetah/Tests/ImportHooksTemplates/layout.tmpl | 16 + Cheetah/Tests/LoadTemplate.py | 52 + Cheetah/Tests/NameMapper.py | 6 +- Cheetah/Tests/NameMapper_pure.py | 13 +- Cheetah/Tests/Performance.py | 2 +- Cheetah/Tests/Regressions.py | 2 +- Cheetah/Tests/SyntaxAndOutput.py | 32 +- Cheetah/Tests/Template.py | 2 +- Cheetah/Tests/Test.py | 40 +- Cheetah/Tests/Unicode.py | 14 +- Cheetah/Tests/xmlrunner.py | 4 +- Cheetah/Tools/MondoReport.py | 6 +- Cheetah/Tools/SiteHierarchy.py | 12 +- Cheetah/Tools/turbocheetah/cheetahsupport.py | 2 +- Cheetah/Tools/turbocheetah/tests/test_template.py | 2 +- Cheetah/Utils/WebInputMixin.py | 2 +- Cheetah/Utils/statprof.py | 4 +- Cheetah/Version.py | 6 +- Cheetah3.egg-info/PKG-INFO | 23 +- Cheetah3.egg-info/SOURCES.txt | 276 +- LICENSE | 2 +- PKG-INFO | 23 +- README.rst | 2 +- SetupConfig.py | 64 +- SetupTools.py | 17 +- TODO | 6 +- docs/conf.py | 10 +- docs/dev_guide/bnf.rst | 6 - docs/dev_guide/cache.rst | 9 - docs/dev_guide/comments.rst | 2 - docs/dev_guide/compiler.rst | 8 - docs/dev_guide/design.rst | 6 - docs/dev_guide/errorHandling.rst | 7 - docs/dev_guide/files.rst | 11 - docs/dev_guide/flowControl.rst | 10 - docs/dev_guide/history.rst | 1 - docs/dev_guide/index.rst | 5 - docs/dev_guide/inheritanceEtc.rst | 9 - docs/dev_guide/output.rst | 9 - docs/dev_guide/parser.rst | 9 - docs/dev_guide/parserInstructions.rst | 3 - docs/dev_guide/patching.rst | 3 - docs/dev_guide/placeholders.rst | 3 - docs/dev_guide/pyModules.rst | 3 - docs/dev_guide/safeDelegation.rst | 1 - docs/dev_guide/template.rst | 11 - docs/documentation.rst | 1 - docs/download.rst | 2 +- docs/html/_sources/api/Cheetah.CacheRegion.rst.txt | 7 - docs/html/_sources/api/Cheetah.CacheStore.rst.txt | 7 - .../_sources/api/Cheetah.CheetahWrapper.rst.txt | 7 - docs/html/_sources/api/Cheetah.Compiler.rst.txt | 7 - .../_sources/api/Cheetah.DirectiveAnalyzer.rst.txt | 7 - docs/html/_sources/api/Cheetah.Django.rst.txt | 7 - .../_sources/api/Cheetah.DummyTransaction.rst.txt | 7 - .../_sources/api/Cheetah.ErrorCatchers.rst.txt | 7 - docs/html/_sources/api/Cheetah.FileUtils.rst.txt | 7 - docs/html/_sources/api/Cheetah.Filters.rst.txt | 7 - docs/html/_sources/api/Cheetah.ImportHooks.rst.txt | 7 - .../_sources/api/Cheetah.ImportManager.rst.txt | 7 - docs/html/_sources/api/Cheetah.Macros.I18n.rst.txt | 7 - docs/html/_sources/api/Cheetah.Macros.rst.txt | 15 - docs/html/_sources/api/Cheetah.NameMapper.rst.txt | 7 - docs/html/_sources/api/Cheetah.Parser.rst.txt | 7 - docs/html/_sources/api/Cheetah.Servlet.rst.txt | 7 - .../_sources/api/Cheetah.SettingsManager.rst.txt | 7 - .../html/_sources/api/Cheetah.SourceReader.rst.txt | 7 - docs/html/_sources/api/Cheetah.Template.rst.txt | 7 - .../api/Cheetah.TemplateCmdLineIface.rst.txt | 7 - .../api/Cheetah.Templates.SkeletonPage.rst.txt | 7 - docs/html/_sources/api/Cheetah.Templates.rst.txt | 15 - .../_sources/api/Cheetah.Tests.Analyzer.rst.txt | 7 - .../_sources/api/Cheetah.Tests.Boinker.rst.txt | 7 - .../api/Cheetah.Tests.CheetahWrapper.rst.txt | 7 - docs/html/_sources/api/Cheetah.Tests.Cheps.rst.txt | 7 - .../_sources/api/Cheetah.Tests.Filters.rst.txt | 7 - docs/html/_sources/api/Cheetah.Tests.Misc.rst.txt | 7 - .../_sources/api/Cheetah.Tests.NameMapper.rst.txt | 7 - .../api/Cheetah.Tests.NameMapper_pure.rst.txt | 7 - .../html/_sources/api/Cheetah.Tests.Parser.rst.txt | 7 - .../_sources/api/Cheetah.Tests.Performance.rst.txt | 7 - .../html/_sources/api/Cheetah.Tests.Pinger.rst.txt | 7 - .../_sources/api/Cheetah.Tests.Regressions.rst.txt | 7 - .../api/Cheetah.Tests.SyntaxAndOutput.rst.txt | 7 - .../_sources/api/Cheetah.Tests.Template.rst.txt | 7 - docs/html/_sources/api/Cheetah.Tests.Test.rst.txt | 7 - .../_sources/api/Cheetah.Tests.Unicode.rst.txt | 7 - docs/html/_sources/api/Cheetah.Tests.rst.txt | 31 - .../_sources/api/Cheetah.Tests.xmlrunner.rst.txt | 7 - .../_sources/api/Cheetah.Tools.CGITemplate.rst.txt | 7 - .../_sources/api/Cheetah.Tools.MondoReport.rst.txt | 7 - .../api/Cheetah.Tools.RecursiveNull.rst.txt | 7 - .../api/Cheetah.Tools.SiteHierarchy.rst.txt | 7 - docs/html/_sources/api/Cheetah.Tools.rst.txt | 25 - ...eetah.Tools.turbocheetah.cheetahsupport.rst.txt | 7 - .../api/Cheetah.Tools.turbocheetah.rst.txt | 22 - .../api/Cheetah.Tools.turbocheetah.tests.rst.txt | 15 - ....Tools.turbocheetah.tests.test_template.rst.txt | 7 - docs/html/_sources/api/Cheetah.Unspecified.rst.txt | 7 - .../_sources/api/Cheetah.Utils.Indenter.rst.txt | 7 - docs/html/_sources/api/Cheetah.Utils.Misc.rst.txt | 7 - .../api/Cheetah.Utils.WebInputMixin.rst.txt | 7 - .../_sources/api/Cheetah.Utils.htmlDecode.rst.txt | 7 - .../_sources/api/Cheetah.Utils.htmlEncode.rst.txt | 7 - docs/html/_sources/api/Cheetah.Utils.rst.txt | 20 - .../_sources/api/Cheetah.Utils.statprof.rst.txt | 7 - docs/html/_sources/api/Cheetah.Version.rst.txt | 7 - docs/html/_sources/api/Cheetah.compat.rst.txt | 7 - .../Cheetah.convertTmplPathToModuleName.rst.txt | 7 - docs/html/_sources/api/Cheetah.rst.txt | 48 - docs/html/_sources/api/modules.rst.txt | 7 - docs/html/_sources/authors.rst.txt | 31 - docs/html/_sources/chep.rst.txt | 17 - docs/html/_sources/cheps/1_chep.rst.txt | 26 - docs/html/_sources/cheps/2_import.rst.txt | 122 - docs/html/_sources/cheps/3_super.rst.txt | 36 - docs/html/_sources/dev_guide/bnf.rst.txt | 6 - docs/html/_sources/dev_guide/cache.rst.txt | 404 - docs/html/_sources/dev_guide/comments.rst.txt | 103 - docs/html/_sources/dev_guide/compiler.rst.txt | 8 - docs/html/_sources/dev_guide/design.rst.txt | 104 - docs/html/_sources/dev_guide/errorHandling.rst.txt | 329 - docs/html/_sources/dev_guide/files.rst.txt | 11 - docs/html/_sources/dev_guide/flowControl.rst.txt | 394 - docs/html/_sources/dev_guide/history.rst.txt | 88 - docs/html/_sources/dev_guide/index.rst.txt | 30 - .../html/_sources/dev_guide/inheritanceEtc.rst.txt | 255 - docs/html/_sources/dev_guide/introduction.rst.txt | 28 - docs/html/_sources/dev_guide/output.rst.txt | 315 - docs/html/_sources/dev_guide/parser.rst.txt | 9 - .../_sources/dev_guide/parserInstructions.rst.txt | 67 - docs/html/_sources/dev_guide/patching.rst.txt | 149 - docs/html/_sources/dev_guide/placeholders.rst.txt | 489 - docs/html/_sources/dev_guide/pyModules.rst.txt | 252 - .../html/_sources/dev_guide/safeDelegation.rst.txt | 40 - docs/html/_sources/dev_guide/template.rst.txt | 11 - docs/html/_sources/developers.rst.txt | 53 - docs/html/_sources/documentation.rst.txt | 10 - docs/html/_sources/download.rst.txt | 14 - docs/html/_sources/index.rst.txt | 89 - docs/html/_sources/news.rst.txt | 66 - docs/html/_sources/news2.rst.txt | 1701 ---- docs/html/_sources/recipes/inheritance.rst.txt | 62 - docs/html/_sources/recipes/precompiled.rst.txt | 59 - docs/html/_sources/recipes/staticmethod.rst.txt | 54 - .../html/_sources/recipes/writing_a_recipe.rst.txt | 4 - docs/html/_sources/roadmap.rst.txt | 14 - docs/html/_sources/users_guide/comments.rst.txt | 101 - docs/html/_sources/users_guide/comparisons.rst.txt | 515 - docs/html/_sources/users_guide/editors.rst.txt | 37 - .../_sources/users_guide/errorHandling.rst.txt | 144 - docs/html/_sources/users_guide/examples.rst.txt | 27 - docs/html/_sources/users_guide/flowControl.rst.txt | 436 - .../_sources/users_guide/gettingStarted.rst.txt | 284 - docs/html/_sources/users_guide/glossary.rst.txt | 99 - docs/html/_sources/users_guide/index.rst.txt | 28 - .../_sources/users_guide/inheritanceEtc.rst.txt | 517 - docs/html/_sources/users_guide/intro.rst.txt | 311 - docs/html/_sources/users_guide/language.rst.txt | 741 -- docs/html/_sources/users_guide/libraries.rst.txt | 315 - docs/html/_sources/users_guide/links.rst.txt | 120 - docs/html/_sources/users_guide/nonHtml.rst.txt | 16 - docs/html/_sources/users_guide/otherHtml.rst.txt | 101 - docs/html/_sources/users_guide/output.rst.txt | 468 - .../users_guide/parserInstructions.rst.txt | 129 - .../_sources/users_guide/tipsAndTricks.rst.txt | 586 -- docs/html/_sources/users_guide/webware.rst.txt | 598 -- docs/html/_static/ajax-loader.gif | Bin 673 -> 0 bytes docs/html/_static/basic.css | 643 -- docs/html/_static/comment-bright.png | Bin 756 -> 0 bytes docs/html/_static/comment-close.png | Bin 829 -> 0 bytes docs/html/_static/comment.png | Bin 641 -> 0 bytes docs/html/_static/contents.png | Bin 107 -> 0 bytes docs/html/_static/doctools.js | 311 - docs/html/_static/down-pressed.png | Bin 222 -> 0 bytes docs/html/_static/down.png | Bin 202 -> 0 bytes docs/html/_static/file.png | Bin 286 -> 0 bytes docs/html/_static/jquery-3.1.0.js | 10074 ------------------- docs/html/_static/jquery.js | 4 - docs/html/_static/minus.png | Bin 90 -> 0 bytes docs/html/_static/navigation.png | Bin 120 -> 0 bytes docs/html/_static/plus.png | Bin 90 -> 0 bytes docs/html/_static/pygments.css | 69 - docs/html/_static/searchtools.js | 761 -- docs/html/_static/sphinxdoc.css | 345 - docs/html/_static/underscore-1.3.1.js | 999 -- docs/html/_static/underscore.js | 31 - docs/html/_static/up-pressed.png | Bin 214 -> 0 bytes docs/html/_static/up.png | Bin 203 -> 0 bytes docs/html/_static/websupport.js | 808 -- docs/html/api/Cheetah.CacheRegion.html | 200 - docs/html/api/Cheetah.CacheStore.html | 224 - docs/html/api/Cheetah.CheetahWrapper.html | 202 - docs/html/api/Cheetah.Compiler.html | 918 -- docs/html/api/Cheetah.DirectiveAnalyzer.html | 138 - docs/html/api/Cheetah.Django.html | 105 - docs/html/api/Cheetah.DummyTransaction.html | 183 - docs/html/api/Cheetah.ErrorCatchers.html | 162 - docs/html/api/Cheetah.FileUtils.html | 192 - docs/html/api/Cheetah.Filters.html | 240 - docs/html/api/Cheetah.ImportHooks.html | 135 - docs/html/api/Cheetah.ImportManager.html | 254 - docs/html/api/Cheetah.Macros.I18n.html | 101 - docs/html/api/Cheetah.Macros.html | 111 - docs/html/api/Cheetah.NameMapper.html | 268 - docs/html/api/Cheetah.Parser.html | 218 - docs/html/api/Cheetah.Servlet.html | 143 - docs/html/api/Cheetah.SettingsManager.html | 212 - docs/html/api/Cheetah.SourceReader.html | 301 - docs/html/api/Cheetah.Template.html | 816 -- docs/html/api/Cheetah.TemplateCmdLineIface.html | 118 - docs/html/api/Cheetah.Templates.SkeletonPage.html | 117 - docs/html/api/Cheetah.Templates.html | 111 - docs/html/api/Cheetah.Tests.Analyzer.html | 111 - docs/html/api/Cheetah.Tests.Boinker.html | 106 - docs/html/api/Cheetah.Tests.CheetahWrapper.html | 638 -- docs/html/api/Cheetah.Tests.Cheps.html | 119 - docs/html/api/Cheetah.Tests.Filters.html | 124 - docs/html/api/Cheetah.Tests.Misc.html | 106 - docs/html/api/Cheetah.Tests.NameMapper.html | 668 -- docs/html/api/Cheetah.Tests.NameMapper_pure.html | 116 - docs/html/api/Cheetah.Tests.Parser.html | 127 - docs/html/api/Cheetah.Tests.Performance.html | 250 - docs/html/api/Cheetah.Tests.Pinger.html | 106 - docs/html/api/Cheetah.Tests.Regressions.html | 228 - docs/html/api/Cheetah.Tests.SyntaxAndOutput.html | 3020 ------ docs/html/api/Cheetah.Tests.Template.html | 249 - docs/html/api/Cheetah.Tests.Test.html | 112 - docs/html/api/Cheetah.Tests.Unicode.html | 261 - docs/html/api/Cheetah.Tests.html | 130 - docs/html/api/Cheetah.Tests.xmlrunner.html | 235 - docs/html/api/Cheetah.Tools.CGITemplate.html | 158 - docs/html/api/Cheetah.Tools.MondoReport.html | 405 - docs/html/api/Cheetah.Tools.RecursiveNull.html | 105 - docs/html/api/Cheetah.Tools.SiteHierarchy.html | 148 - docs/html/api/Cheetah.Tools.html | 144 - .../Cheetah.Tools.turbocheetah.cheetahsupport.html | 133 - docs/html/api/Cheetah.Tools.turbocheetah.html | 163 - .../html/api/Cheetah.Tools.turbocheetah.tests.html | 111 - ...tah.Tools.turbocheetah.tests.test_template.html | 115 - docs/html/api/Cheetah.Unspecified.html | 95 - docs/html/api/Cheetah.Utils.Indenter.html | 269 - docs/html/api/Cheetah.Utils.Misc.html | 138 - docs/html/api/Cheetah.Utils.WebInputMixin.html | 103 - docs/html/api/Cheetah.Utils.html | 116 - docs/html/api/Cheetah.Utils.htmlDecode.html | 104 - docs/html/api/Cheetah.Utils.htmlEncode.html | 104 - docs/html/api/Cheetah.Utils.statprof.html | 95 - docs/html/api/Cheetah.Version.html | 100 - docs/html/api/Cheetah.compat.html | 95 - .../api/Cheetah.convertTmplPathToModuleName.html | 100 - docs/html/api/Cheetah.html | 246 - docs/html/api/modules.html | 158 - docs/html/authors.html | 143 - docs/html/chep.html | 137 - docs/html/cheps/1_chep.html | 161 - docs/html/cheps/2_import.html | 254 - docs/html/cheps/3_super.html | 166 - docs/html/dev_guide/bnf.html | 118 - docs/html/dev_guide/cache.html | 451 - docs/html/dev_guide/comments.html | 203 - docs/html/dev_guide/compiler.html | 119 - docs/html/dev_guide/design.html | 214 - docs/html/dev_guide/errorHandling.html | 415 - docs/html/dev_guide/files.html | 122 - docs/html/dev_guide/flowControl.html | 455 - docs/html/dev_guide/history.html | 193 - docs/html/dev_guide/index.html | 150 - docs/html/dev_guide/inheritanceEtc.html | 327 - docs/html/dev_guide/introduction.html | 147 - docs/html/dev_guide/output.html | 375 - docs/html/dev_guide/parser.html | 120 - docs/html/dev_guide/parserInstructions.html | 172 - docs/html/dev_guide/patching.html | 243 - docs/html/dev_guide/placeholders.html | 582 -- docs/html/dev_guide/pyModules.html | 346 - docs/html/dev_guide/safeDelegation.html | 145 - docs/html/dev_guide/template.html | 121 - docs/html/developers.html | 167 - docs/html/documentation.html | 132 - docs/html/download.html | 123 - docs/html/genindex.html | 3373 ------- docs/html/index.html | 246 - docs/html/news.html | 203 - docs/html/news2.html | 2150 ---- docs/html/py-modindex.html | 406 - docs/html/recipes/inheritance.html | 179 - docs/html/recipes/precompiled.html | 180 - docs/html/recipes/staticmethod.html | 163 - docs/html/recipes/writing_a_recipe.html | 118 - docs/html/roadmap.html | 133 - docs/html/search.html | 105 - docs/html/searchindex.js | 1 - docs/html/users_guide/comments.html | 208 - docs/html/users_guide/comparisons.html | 573 -- docs/html/users_guide/editors.html | 145 - docs/html/users_guide/errorHandling.html | 245 - docs/html/users_guide/examples.html | 145 - docs/html/users_guide/flowControl.html | 480 - docs/html/users_guide/gettingStarted.html | 357 - docs/html/users_guide/glossary.html | 197 - docs/html/users_guide/index.html | 272 - docs/html/users_guide/inheritanceEtc.html | 550 - docs/html/users_guide/intro.html | 402 - docs/html/users_guide/language.html | 713 -- docs/html/users_guide/libraries.html | 397 - docs/html/users_guide/links.html | 281 - docs/html/users_guide/nonHtml.html | 133 - docs/html/users_guide/otherHtml.html | 205 - docs/html/users_guide/output.html | 501 - docs/html/users_guide/parserInstructions.html | 219 - docs/html/users_guide/tipsAndTricks.html | 598 -- docs/html/users_guide/webware.html | 667 -- docs/news.rst | 41 + docs/recipes/writing_a_recipe.rst | 4 - docs/roadmap.rst | 7 +- docs/users_guide/comments.rst | 2 - docs/users_guide/comparisons.rst | 9 - docs/users_guide/editors.rst | 1 - docs/users_guide/errorHandling.rst | 3 - docs/users_guide/examples.rst | 1 - docs/users_guide/flowControl.rst | 10 - docs/users_guide/gettingStarted.rst | 8 - docs/users_guide/inheritanceEtc.rst | 9 - docs/users_guide/language.rst | 12 - docs/users_guide/libraries.rst | 9 - docs/users_guide/links.rst | 9 - docs/users_guide/nonHtml.rst | 2 - docs/users_guide/otherHtml.rst | 3 - docs/users_guide/output.rst | 12 - docs/users_guide/parserInstructions.rst | 3 - docs/users_guide/tipsAndTricks.rst | 59 +- docs/users_guide/webware.rst | 13 - setup.cfg | 8 +- tox.ini | 16 +- 357 files changed, 903 insertions(+), 62854 deletions(-) create mode 100644 Cheetah/LoadTemplate.py create mode 100755 Cheetah/Tests/ImportHooks.py create mode 100644 Cheetah/Tests/ImportHooksTemplates/index.tmpl create mode 100644 Cheetah/Tests/ImportHooksTemplates/layout.tmpl create mode 100755 Cheetah/Tests/LoadTemplate.py delete mode 100644 docs/dev_guide/bnf.rst delete mode 100644 docs/dev_guide/compiler.rst delete mode 100644 docs/dev_guide/files.rst delete mode 100644 docs/dev_guide/parser.rst delete mode 100644 docs/dev_guide/template.rst delete mode 100644 docs/html/_sources/api/Cheetah.CacheRegion.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.CacheStore.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.CheetahWrapper.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Compiler.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.DirectiveAnalyzer.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Django.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.DummyTransaction.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.ErrorCatchers.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.FileUtils.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Filters.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.ImportHooks.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.ImportManager.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Macros.I18n.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Macros.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.NameMapper.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Parser.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Servlet.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.SettingsManager.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.SourceReader.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Template.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.TemplateCmdLineIface.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Templates.SkeletonPage.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Templates.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Tests.Analyzer.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Tests.Boinker.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Tests.CheetahWrapper.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Tests.Cheps.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Tests.Filters.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Tests.Misc.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Tests.NameMapper.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Tests.NameMapper_pure.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Tests.Parser.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Tests.Performance.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Tests.Pinger.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Tests.Regressions.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Tests.SyntaxAndOutput.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Tests.Template.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Tests.Test.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Tests.Unicode.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Tests.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Tests.xmlrunner.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Tools.CGITemplate.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Tools.MondoReport.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Tools.RecursiveNull.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Tools.SiteHierarchy.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Tools.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Tools.turbocheetah.cheetahsupport.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Tools.turbocheetah.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Tools.turbocheetah.tests.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Tools.turbocheetah.tests.test_template.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Unspecified.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Utils.Indenter.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Utils.Misc.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Utils.WebInputMixin.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Utils.htmlDecode.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Utils.htmlEncode.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Utils.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Utils.statprof.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.Version.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.compat.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.convertTmplPathToModuleName.rst.txt delete mode 100644 docs/html/_sources/api/Cheetah.rst.txt delete mode 100644 docs/html/_sources/api/modules.rst.txt delete mode 100644 docs/html/_sources/authors.rst.txt delete mode 100644 docs/html/_sources/chep.rst.txt delete mode 100644 docs/html/_sources/cheps/1_chep.rst.txt delete mode 100644 docs/html/_sources/cheps/2_import.rst.txt delete mode 100644 docs/html/_sources/cheps/3_super.rst.txt delete mode 100644 docs/html/_sources/dev_guide/bnf.rst.txt delete mode 100644 docs/html/_sources/dev_guide/cache.rst.txt delete mode 100644 docs/html/_sources/dev_guide/comments.rst.txt delete mode 100644 docs/html/_sources/dev_guide/compiler.rst.txt delete mode 100644 docs/html/_sources/dev_guide/design.rst.txt delete mode 100644 docs/html/_sources/dev_guide/errorHandling.rst.txt delete mode 100644 docs/html/_sources/dev_guide/files.rst.txt delete mode 100644 docs/html/_sources/dev_guide/flowControl.rst.txt delete mode 100644 docs/html/_sources/dev_guide/history.rst.txt delete mode 100644 docs/html/_sources/dev_guide/index.rst.txt delete mode 100644 docs/html/_sources/dev_guide/inheritanceEtc.rst.txt delete mode 100644 docs/html/_sources/dev_guide/introduction.rst.txt delete mode 100644 docs/html/_sources/dev_guide/output.rst.txt delete mode 100644 docs/html/_sources/dev_guide/parser.rst.txt delete mode 100644 docs/html/_sources/dev_guide/parserInstructions.rst.txt delete mode 100644 docs/html/_sources/dev_guide/patching.rst.txt delete mode 100644 docs/html/_sources/dev_guide/placeholders.rst.txt delete mode 100644 docs/html/_sources/dev_guide/pyModules.rst.txt delete mode 100644 docs/html/_sources/dev_guide/safeDelegation.rst.txt delete mode 100644 docs/html/_sources/dev_guide/template.rst.txt delete mode 100644 docs/html/_sources/developers.rst.txt delete mode 100644 docs/html/_sources/documentation.rst.txt delete mode 100644 docs/html/_sources/download.rst.txt delete mode 100644 docs/html/_sources/index.rst.txt delete mode 100644 docs/html/_sources/news.rst.txt delete mode 100644 docs/html/_sources/news2.rst.txt delete mode 100644 docs/html/_sources/recipes/inheritance.rst.txt delete mode 100644 docs/html/_sources/recipes/precompiled.rst.txt delete mode 100644 docs/html/_sources/recipes/staticmethod.rst.txt delete mode 100644 docs/html/_sources/recipes/writing_a_recipe.rst.txt delete mode 100644 docs/html/_sources/roadmap.rst.txt delete mode 100644 docs/html/_sources/users_guide/comments.rst.txt delete mode 100644 docs/html/_sources/users_guide/comparisons.rst.txt delete mode 100644 docs/html/_sources/users_guide/editors.rst.txt delete mode 100644 docs/html/_sources/users_guide/errorHandling.rst.txt delete mode 100644 docs/html/_sources/users_guide/examples.rst.txt delete mode 100644 docs/html/_sources/users_guide/flowControl.rst.txt delete mode 100644 docs/html/_sources/users_guide/gettingStarted.rst.txt delete mode 100644 docs/html/_sources/users_guide/glossary.rst.txt delete mode 100644 docs/html/_sources/users_guide/index.rst.txt delete mode 100644 docs/html/_sources/users_guide/inheritanceEtc.rst.txt delete mode 100644 docs/html/_sources/users_guide/intro.rst.txt delete mode 100644 docs/html/_sources/users_guide/language.rst.txt delete mode 100644 docs/html/_sources/users_guide/libraries.rst.txt delete mode 100644 docs/html/_sources/users_guide/links.rst.txt delete mode 100644 docs/html/_sources/users_guide/nonHtml.rst.txt delete mode 100644 docs/html/_sources/users_guide/otherHtml.rst.txt delete mode 100644 docs/html/_sources/users_guide/output.rst.txt delete mode 100644 docs/html/_sources/users_guide/parserInstructions.rst.txt delete mode 100644 docs/html/_sources/users_guide/tipsAndTricks.rst.txt delete mode 100644 docs/html/_sources/users_guide/webware.rst.txt delete mode 100644 docs/html/_static/ajax-loader.gif delete mode 100644 docs/html/_static/basic.css delete mode 100644 docs/html/_static/comment-bright.png delete mode 100644 docs/html/_static/comment-close.png delete mode 100644 docs/html/_static/comment.png delete mode 100644 docs/html/_static/contents.png delete mode 100644 docs/html/_static/doctools.js delete mode 100644 docs/html/_static/down-pressed.png delete mode 100644 docs/html/_static/down.png delete mode 100644 docs/html/_static/file.png delete mode 100644 docs/html/_static/jquery-3.1.0.js delete mode 100644 docs/html/_static/jquery.js delete mode 100644 docs/html/_static/minus.png delete mode 100644 docs/html/_static/navigation.png delete mode 100644 docs/html/_static/plus.png delete mode 100644 docs/html/_static/pygments.css delete mode 100644 docs/html/_static/searchtools.js delete mode 100644 docs/html/_static/sphinxdoc.css delete mode 100644 docs/html/_static/underscore-1.3.1.js delete mode 100644 docs/html/_static/underscore.js delete mode 100644 docs/html/_static/up-pressed.png delete mode 100644 docs/html/_static/up.png delete mode 100644 docs/html/_static/websupport.js delete mode 100644 docs/html/api/Cheetah.CacheRegion.html delete mode 100644 docs/html/api/Cheetah.CacheStore.html delete mode 100644 docs/html/api/Cheetah.CheetahWrapper.html delete mode 100644 docs/html/api/Cheetah.Compiler.html delete mode 100644 docs/html/api/Cheetah.DirectiveAnalyzer.html delete mode 100644 docs/html/api/Cheetah.Django.html delete mode 100644 docs/html/api/Cheetah.DummyTransaction.html delete mode 100644 docs/html/api/Cheetah.ErrorCatchers.html delete mode 100644 docs/html/api/Cheetah.FileUtils.html delete mode 100644 docs/html/api/Cheetah.Filters.html delete mode 100644 docs/html/api/Cheetah.ImportHooks.html delete mode 100644 docs/html/api/Cheetah.ImportManager.html delete mode 100644 docs/html/api/Cheetah.Macros.I18n.html delete mode 100644 docs/html/api/Cheetah.Macros.html delete mode 100644 docs/html/api/Cheetah.NameMapper.html delete mode 100644 docs/html/api/Cheetah.Parser.html delete mode 100644 docs/html/api/Cheetah.Servlet.html delete mode 100644 docs/html/api/Cheetah.SettingsManager.html delete mode 100644 docs/html/api/Cheetah.SourceReader.html delete mode 100644 docs/html/api/Cheetah.Template.html delete mode 100644 docs/html/api/Cheetah.TemplateCmdLineIface.html delete mode 100644 docs/html/api/Cheetah.Templates.SkeletonPage.html delete mode 100644 docs/html/api/Cheetah.Templates.html delete mode 100644 docs/html/api/Cheetah.Tests.Analyzer.html delete mode 100644 docs/html/api/Cheetah.Tests.Boinker.html delete mode 100644 docs/html/api/Cheetah.Tests.CheetahWrapper.html delete mode 100644 docs/html/api/Cheetah.Tests.Cheps.html delete mode 100644 docs/html/api/Cheetah.Tests.Filters.html delete mode 100644 docs/html/api/Cheetah.Tests.Misc.html delete mode 100644 docs/html/api/Cheetah.Tests.NameMapper.html delete mode 100644 docs/html/api/Cheetah.Tests.NameMapper_pure.html delete mode 100644 docs/html/api/Cheetah.Tests.Parser.html delete mode 100644 docs/html/api/Cheetah.Tests.Performance.html delete mode 100644 docs/html/api/Cheetah.Tests.Pinger.html delete mode 100644 docs/html/api/Cheetah.Tests.Regressions.html delete mode 100644 docs/html/api/Cheetah.Tests.SyntaxAndOutput.html delete mode 100644 docs/html/api/Cheetah.Tests.Template.html delete mode 100644 docs/html/api/Cheetah.Tests.Test.html delete mode 100644 docs/html/api/Cheetah.Tests.Unicode.html delete mode 100644 docs/html/api/Cheetah.Tests.html delete mode 100644 docs/html/api/Cheetah.Tests.xmlrunner.html delete mode 100644 docs/html/api/Cheetah.Tools.CGITemplate.html delete mode 100644 docs/html/api/Cheetah.Tools.MondoReport.html delete mode 100644 docs/html/api/Cheetah.Tools.RecursiveNull.html delete mode 100644 docs/html/api/Cheetah.Tools.SiteHierarchy.html delete mode 100644 docs/html/api/Cheetah.Tools.html delete mode 100644 docs/html/api/Cheetah.Tools.turbocheetah.cheetahsupport.html delete mode 100644 docs/html/api/Cheetah.Tools.turbocheetah.html delete mode 100644 docs/html/api/Cheetah.Tools.turbocheetah.tests.html delete mode 100644 docs/html/api/Cheetah.Tools.turbocheetah.tests.test_template.html delete mode 100644 docs/html/api/Cheetah.Unspecified.html delete mode 100644 docs/html/api/Cheetah.Utils.Indenter.html delete mode 100644 docs/html/api/Cheetah.Utils.Misc.html delete mode 100644 docs/html/api/Cheetah.Utils.WebInputMixin.html delete mode 100644 docs/html/api/Cheetah.Utils.html delete mode 100644 docs/html/api/Cheetah.Utils.htmlDecode.html delete mode 100644 docs/html/api/Cheetah.Utils.htmlEncode.html delete mode 100644 docs/html/api/Cheetah.Utils.statprof.html delete mode 100644 docs/html/api/Cheetah.Version.html delete mode 100644 docs/html/api/Cheetah.compat.html delete mode 100644 docs/html/api/Cheetah.convertTmplPathToModuleName.html delete mode 100644 docs/html/api/Cheetah.html delete mode 100644 docs/html/api/modules.html delete mode 100644 docs/html/authors.html delete mode 100644 docs/html/chep.html delete mode 100644 docs/html/cheps/1_chep.html delete mode 100644 docs/html/cheps/2_import.html delete mode 100644 docs/html/cheps/3_super.html delete mode 100644 docs/html/dev_guide/bnf.html delete mode 100644 docs/html/dev_guide/cache.html delete mode 100644 docs/html/dev_guide/comments.html delete mode 100644 docs/html/dev_guide/compiler.html delete mode 100644 docs/html/dev_guide/design.html delete mode 100644 docs/html/dev_guide/errorHandling.html delete mode 100644 docs/html/dev_guide/files.html delete mode 100644 docs/html/dev_guide/flowControl.html delete mode 100644 docs/html/dev_guide/history.html delete mode 100644 docs/html/dev_guide/index.html delete mode 100644 docs/html/dev_guide/inheritanceEtc.html delete mode 100644 docs/html/dev_guide/introduction.html delete mode 100644 docs/html/dev_guide/output.html delete mode 100644 docs/html/dev_guide/parser.html delete mode 100644 docs/html/dev_guide/parserInstructions.html delete mode 100644 docs/html/dev_guide/patching.html delete mode 100644 docs/html/dev_guide/placeholders.html delete mode 100644 docs/html/dev_guide/pyModules.html delete mode 100644 docs/html/dev_guide/safeDelegation.html delete mode 100644 docs/html/dev_guide/template.html delete mode 100644 docs/html/developers.html delete mode 100644 docs/html/documentation.html delete mode 100644 docs/html/download.html delete mode 100644 docs/html/genindex.html delete mode 100644 docs/html/index.html delete mode 100644 docs/html/news.html delete mode 100644 docs/html/news2.html delete mode 100644 docs/html/py-modindex.html delete mode 100644 docs/html/recipes/inheritance.html delete mode 100644 docs/html/recipes/precompiled.html delete mode 100644 docs/html/recipes/staticmethod.html delete mode 100644 docs/html/recipes/writing_a_recipe.html delete mode 100644 docs/html/roadmap.html delete mode 100644 docs/html/search.html delete mode 100644 docs/html/searchindex.js delete mode 100644 docs/html/users_guide/comments.html delete mode 100644 docs/html/users_guide/comparisons.html delete mode 100644 docs/html/users_guide/editors.html delete mode 100644 docs/html/users_guide/errorHandling.html delete mode 100644 docs/html/users_guide/examples.html delete mode 100644 docs/html/users_guide/flowControl.html delete mode 100644 docs/html/users_guide/gettingStarted.html delete mode 100644 docs/html/users_guide/glossary.html delete mode 100644 docs/html/users_guide/index.html delete mode 100644 docs/html/users_guide/inheritanceEtc.html delete mode 100644 docs/html/users_guide/intro.html delete mode 100644 docs/html/users_guide/language.html delete mode 100644 docs/html/users_guide/libraries.html delete mode 100644 docs/html/users_guide/links.html delete mode 100644 docs/html/users_guide/nonHtml.html delete mode 100644 docs/html/users_guide/otherHtml.html delete mode 100644 docs/html/users_guide/output.html delete mode 100644 docs/html/users_guide/parserInstructions.html delete mode 100644 docs/html/users_guide/tipsAndTricks.html delete mode 100644 docs/html/users_guide/webware.html delete mode 100644 docs/recipes/writing_a_recipe.rst diff --git a/.travis.yml b/.travis.yml index 64d6b43..e68e027 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,6 @@ -# Config file for automatic testing at travis-ci.org +os: linux -# Only test maint, master and pull requests; skip tags. -# Other branches can allow themselves. -branches: - only: - - maint - - master - - next +dist: xenial # Prefer docker containers sudo: required @@ -14,36 +8,53 @@ sudo: required language: python python: - - "2.7" + - "3.7" cache: pip +addons: + apt: + packages: + - patchelf + +env: + global: + - TWINE_USERNAME=phd + # Note: TWINE_PASSWORD is set in Travis settings. + #- TWINE_REPOSITORY_URL=https://test.pypi.org/legacy/ + matrix: include: - python: "2.7" env: TOXENV=py27 - - python: "3.3" - env: TOXENV=py33 - python: "3.4" env: TOXENV=py34 - python: "3.5" env: TOXENV=py35 - python: "3.6" env: TOXENV=py36 + - python: "3.7" + env: TOXENV=py37 - python: "2.7" env: TOXENV=py27-flake8 - - python: "3.4" - env: TOXENV=py34-flake8 - - python: "pypy" + - python: "3.7" + env: TOXENV=py37-flake8 + - python: "pypy2.7-6.0" env: TOXENV=pypy fast_finish: true install: - - travis_retry pip install --upgrade pip setuptools tox ppu + - travis_retry pip install --upgrade "pip < 19.1" setuptools tox ppu script: - tox before_cache: - remove-old-files.py -o 180 ~/.cache/pip + +deploy: + provider: script + script: devscripts/CI/travisci-release + on: + tags: true diff --git a/ANNOUNCE.rst b/ANNOUNCE.rst index 889c00d..655cdb2 100644 --- a/ANNOUNCE.rst +++ b/ANNOUNCE.rst @@ -1,31 +1,48 @@ Hello! -I'm pleased to announce version 3.1.0, the first stable release of branch -3.1 of CheetahTemplate3. +I'm pleased to announce version 3.2.0, the first stable release of branch +3.2 of CheetahTemplate3. What's new in CheetahTemplate3 ============================== -Contributors for this release is Mathias Stearn. - Features: - - Fix Cheetah to work with PyPy. Pull request by Mathias Stearn. + - Dropped support for Python 3.3. + - Implement LoadTemplate.loadTemplate{Module,Class} to load templates + from .py[co], .py or .tmpl. + - CheetahDirOwner caches compiled template in the template directory. + - CheetahDirOwner now silently ignores errors on compiled templates + writing. To get tracebacks set CheetahDirOwner.debuglevel = 1. + - CheetahDirOwner and DirOwner byte-compile compiled templates + to .pyc/.pyo. Errors on writing are silently ignored. Minor features: - - Code cleanup: fix code style to satisfy flake8 linter. + - Implement Compiler.__unicode__ under Python 2 and Compiler.__bytes__ + under Python 3. + +Bug fixes: + + - Fix a bug in Compiler.__str__: under Python 2 the method now always + returns str; it encodes unicode to str using encoding from the + compiled source. Under Python 3 the method decodes bytes to str. + +Code: + + - Source code was made flake8-clean using the latest flake8. Documentation: - - Rename www directory to docs. + - Remove outdated section markers. + - Better documentation for ImportHooks. + - Add an example of a universal makefile. -Tests: +CI: - - Run pypy tests at AppVeyor. - - Use remove-old-files.py from ppu to cleanup pip cache - at Travis and AppVeyor. + - Run tests with Python 3.7. + - At travis deploy sdists and wheels for tags. What is CheetahTemplate3 @@ -34,7 +51,7 @@ What is CheetahTemplate3 Cheetah3 is a free and open source template engine. It's a fork of the original CheetahTemplate library. -Python 2.7 or 3.3+ is required. +Python 2.7 or 3.4+ is required. Where is CheetahTemplate3 @@ -47,7 +64,7 @@ Development: https://github.com/CheetahTemplate3 Download: -https://pypi.python.org/pypi/Cheetah3/3.1.0 +https://pypi.org/project/Cheetah3/3.2.0/ News and changes: http://cheetahtemplate.org/news.html diff --git a/Cheetah/CacheRegion.py b/Cheetah/CacheRegion.py index 130fa50..230e8ba 100644 --- a/Cheetah/CacheRegion.py +++ b/Cheetah/CacheRegion.py @@ -78,13 +78,13 @@ class _CacheDataStoreWrapper(object): self._keyPrefix = keyPrefix def get(self, key): - return self._dataStore.get(self._keyPrefix+key) + return self._dataStore.get(self._keyPrefix + key) def delete(self, key): - self._dataStore.delete(self._keyPrefix+key) + self._dataStore.delete(self._keyPrefix + key) def set(self, key, val, time=0): - self._dataStore.set(self._keyPrefix+key, val, time=time) + self._dataStore.set(self._keyPrefix + key, val, time=time) class CacheRegion(object): @@ -108,7 +108,7 @@ class CacheRegion(object): cacheStore = Cheetah.CacheStore.MemoryCacheStore() self._cacheStore = cacheStore self._wrappedCacheDataStore = _CacheDataStoreWrapper( - cacheStore, keyPrefix=templateCacheIdPrefix+':'+regionID+':') + cacheStore, keyPrefix=templateCacheIdPrefix + ':' + regionID + ':') self._cacheItems = {} def isNew(self): diff --git a/Cheetah/CheetahWrapper.py b/Cheetah/CheetahWrapper.py index fcfa7a5..c43e31c 100644 --- a/Cheetah/CheetahWrapper.py +++ b/Cheetah/CheetahWrapper.py @@ -457,8 +457,8 @@ you do have write permission to and re-run the tests.""") raise Error("source file '%s' is a directory" % path) elif os.path.isfile(path): files.append(path) - elif (addIextIfMissing and not path.endswith(iext) and - os.path.isfile(pathWithExt)): + elif (addIextIfMissing and not path.endswith(iext) + and os.path.isfile(pathWithExt)): files.append(pathWithExt) # Do not recurse directories discovered by iext appending. elif os.path.exists(path): @@ -531,8 +531,8 @@ you do have write permission to and re-run the tests.""") if p >= 0: mod = getattr( - __import__(modname[:p], {}, {}, [modname[p+1:]]), - modname[p+1:]) + __import__(modname[:p], {}, {}, [modname[p+1:]]), # noqa: E226,E501 missing whitespace around operator + modname[p+1:]) # noqa: E226 missing whitespace around operator else: mod = __import__(modname, {}, {}, []) diff --git a/Cheetah/Compiler.py b/Cheetah/Compiler.py index 3160764..1305571 100644 --- a/Cheetah/Compiler.py +++ b/Cheetah/Compiler.py @@ -24,9 +24,9 @@ from Cheetah.SettingsManager import SettingsManager from Cheetah.Utils.Indenter import indentize # an undocumented preprocessor from Cheetah import NameMapper from Cheetah.Parser import Parser, ParseError, specialVarRE, \ - STATIC_CACHE, REFRESH_CACHE, SET_GLOBAL, SET_MODULE, \ - unicodeDirectiveRE, encodingDirectiveRE, escapedNewlineRE -from Cheetah.compat import string_type, unicode + STATIC_CACHE, REFRESH_CACHE, SET_GLOBAL, SET_MODULE, \ + unicodeDirectiveRE, encodingDirectiveRE, escapedNewlineRE +from Cheetah.compat import PY2, string_type, unicode from Cheetah.NameMapper import valueForName, valueFromSearchList, \ valueFromFrameOrSearchList @@ -147,15 +147,15 @@ class GenUtils(object): if timeString[-1] == 's': interval = float(timeString[:-1]) elif timeString[-1] == 'm': - interval = float(timeString[:-1])*60 + interval = float(timeString[:-1])*60 # noqa: E226,E501 missing whitespace around operator elif timeString[-1] == 'h': - interval = float(timeString[:-1])*60*60 + interval = float(timeString[:-1])*60*60 # noqa: E226,E501 missing whitespace around operator elif timeString[-1] == 'd': - interval = float(timeString[:-1])*60*60*24 + interval = float(timeString[:-1])*60*60*24 # noqa: E226,E501 missing whitespace around operator elif timeString[-1] == 'w': - interval = float(timeString[:-1])*60*60*24*7 + interval = float(timeString[:-1])*60*60*24*7 # noqa: E226,E501 missing whitespace around operator else: # default to minutes - interval = float(timeString)*60 + interval = float(timeString)*60 # noqa: E226,E501 missing whitespace around operator return interval def genCacheInfo(self, cacheTokenParts): @@ -293,13 +293,13 @@ class GenUtils(object): firstDotIdx = name.find('.') if firstDotIdx != -1 and firstDotIdx < len(name): beforeFirstDot = name[:firstDotIdx] - afterDot = name[firstDotIdx+1:] - pythonCode = ('VFN(' + beforeFirstDot + - ',"' + afterDot + - '",' + repr(defaultUseAC and useAC) + ')' + afterDot = name[firstDotIdx+1:] # noqa: E226,E501 missing whitespace around operator + pythonCode = ('VFN(' + beforeFirstDot + + ',"' + afterDot + + '",' + repr(defaultUseAC and useAC) + ')' + remainder) else: - pythonCode = name+remainder + pythonCode = name + remainder elif self.setting('useStackFrames'): pythonCode = ('VFFSL(SL,' '"' + name + '",' @@ -313,9 +313,9 @@ class GenUtils(object): ## while nameChunks: name, useAC, remainder = nameChunks.pop() - pythonCode = ('VFN(' + pythonCode + - ',"' + name + - '",' + repr(defaultUseAC and useAC) + ')' + pythonCode = ('VFN(' + pythonCode + + ',"' + name + + '",' + repr(defaultUseAC and useAC) + ')' + remainder) return pythonCode @@ -417,11 +417,10 @@ class MethodCompiler(GenUtils): if not self._docStringLines: return '' - ind = self._indent*2 - docStr = (ind + '"""\n' + ind + - ('\n' + ind).join( - [ln.replace('"""', "'''") - for ln in self._docStringLines]) + ind = self._indent*2 # noqa: E226 missing whitespace around operator + docStr = (ind + '"""\n' + ind + + ('\n' + ind).join([ln.replace('"""', "'''") + for ln in self._docStringLines]) + '\n' + ind + '"""\n') return docStr @@ -491,7 +490,7 @@ class MethodCompiler(GenUtils): if reprstr.startswith('u'): i = 1 out = ['u'] - body = escapedNewlineRE.sub('\\1\n', reprstr[i+1:-1]) + body = escapedNewlineRE.sub('\\1\n', reprstr[i+1:-1]) # noqa: E226,E501 missing whitespace around operator if reprstr[i] == "'": out.append("'''") @@ -508,7 +507,7 @@ class MethodCompiler(GenUtils): """ if self._pendingStrConstChunks: src = self._pendingStrConstChunks[-1] - BOL = max(src.rfind('\n')+1, src.rfind('\r')+1, 0) + BOL = max(src.rfind('\n') + 1, src.rfind('\r') + 1, 0) if BOL < len(src): self._pendingStrConstChunks[-1] = src[:BOL] @@ -530,7 +529,7 @@ class MethodCompiler(GenUtils): def addMethComment(self, comm): offSet = self.setting('commentOffset') - self.addChunk('#' + ' '*offSet + comm) + self.addChunk('#' + ' '*offSet + comm) # noqa: E226,E501 missing whitespace around operator def addPlaceholder(self, expr, filterArgs, rawPlaceholder, cacheTokenParts, lineCol, @@ -599,10 +598,10 @@ class MethodCompiler(GenUtils): self.addChunk(expr) def addInclude(self, sourceExpr, includeFrom, isRaw): - self.addChunk('self._handleCheetahInclude(' + sourceExpr + - ', trans=trans, ' + - 'includeFrom="' + includeFrom + '", raw=' + - repr(isRaw) + ')') + self.addChunk('self._handleCheetahInclude(' + sourceExpr + + ', trans=trans, ' + + 'includeFrom="' + includeFrom + '", raw=' + + repr(isRaw) + ')') def addWhile(self, expr, lineCol=None): self.addIndentingDirective(expr, lineCol=lineCol) @@ -680,7 +679,7 @@ class MethodCompiler(GenUtils): signature = \ "def " + functionName + "(" + ','.join(argStringChunks) + "):" self.addIndentingDirective(signature) - self.addChunk('#'+parserComment) + self.addChunk('#' + parserComment) def addTry(self, expr, lineCol=None): self.addIndentingDirective(expr, lineCol=lineCol) @@ -757,7 +756,7 @@ class MethodCompiler(GenUtils): self.indent() def nextCacheID(self): - return ('_'+str(random.randrange(100, 999)) + return ('_' + str(random.randrange(100, 999)) + str(random.randrange(10000, 99999))) def startCacheRegion(self, cacheInfo, lineCol, rawPlaceholder=None): @@ -852,7 +851,7 @@ class MethodCompiler(GenUtils): self.addChunk('del _cacheCollector_%(ID)s' % locals()) self.addChunk('del _orig_trans%(ID)s' % locals()) self.dedent() - self.addChunk('## END CACHE REGION: '+ID) + self.addChunk('## END CACHE REGION: ' + ID) self.addChunk('') def nextCallRegionID(self): @@ -925,14 +924,14 @@ class MethodCompiler(GenUtils): '_callCollector%(ID)s.response().getvalue()' % locals()) self.addChunk('del _callCollector%(ID)s' % locals()) if initialKwArgs: - initialKwArgs = ', '+initialKwArgs + initialKwArgs = ', ' + initialKwArgs self.addFilteredChunk( '%(functionName)s(_callArgVal%(ID)s%(initialKwArgs)s)' % locals()) self.addChunk('del _callArgVal%(ID)s' % locals()) else: if initialKwArgs: - initialKwArgs = initialKwArgs+', ' + initialKwArgs = initialKwArgs + ', ' self._endCallArg() reset() self.addFilteredChunk( @@ -990,8 +989,8 @@ class MethodCompiler(GenUtils): 'if "' + errorCatcherName + '" in self._CHEETAH__errorCatchers:') self.indent() self.addChunk( - 'self._CHEETAH__errorCatcher = self._CHEETAH__errorCatchers["' + - errorCatcherName + '"]') + 'self._CHEETAH__errorCatcher = self._CHEETAH__errorCatchers["' + + errorCatcherName + '"]') self.dedent() self.addChunk('else:') self.indent() @@ -999,7 +998,7 @@ class MethodCompiler(GenUtils): 'self._CHEETAH__errorCatcher = self._CHEETAH__errorCatchers["' + errorCatcherName + '"] = ErrorCatchers.' + errorCatcherName + '(self)' - ) + ) self.dedent() def nextFilterRegionID(self): @@ -1163,13 +1162,13 @@ class AutoMethodCompiler(MethodCompiler): else: self.addChunk('_filter = self._CHEETAH__currentFilter') self.addChunk('') - self.addChunk("#"*40) + self.addChunk("#"*40) # noqa: E226 missing whitespace around operator self.addChunk('## START - generated method body') self.addChunk('') def _addAutoCleanupCode(self): self.addChunk('') - self.addChunk("#"*40) + self.addChunk("#"*40) # noqa: E226 missing whitespace around operator self.addChunk('## END - generated method body') self.addChunk('') @@ -1203,8 +1202,8 @@ class AutoMethodCompiler(MethodCompiler): output.append(''.join([self._indent + decorator + '\n' for decorator in self._decorators])) output.append(self._indent + "def " - + self.methodName() + "(" + - argString + "):\n\n") + + self.methodName() + "(" + + argString + "):\n\n") return ''.join(output) @@ -1218,7 +1217,7 @@ if not self._CHEETAH__instanceInitialized: for k,v in KWs.items(): if k in allowedKWs: cheetahKWArgs[k] = v self._initCheetahInstance(**cheetahKWArgs) -""".replace('\n', '\n'+' '*8) +""".replace('\n', '\n' + ' '*8) # noqa: E226,E501 missing whitespace around operator class ClassCompiler(GenUtils): @@ -1293,7 +1292,7 @@ class ClassCompiler(GenUtils): if self.setting('templateMetaclass'): self._generatedAttribs.append( - '__metaclass__ = '+self.setting('templateMetaclass')) + '__metaclass__ = ' + self.setting('templateMetaclass')) self._initMethChunks = [] self._blockMetaData = {} self._errorCatcherCount = 0 @@ -1308,8 +1307,9 @@ class ClassCompiler(GenUtils): if self.setting('setup__str__method'): self._generatedAttribs.append( 'def __str__(self): return self.respond()') - self.addAttribute('_mainCheetahMethod_for_' + self._className + - ' = ' + repr(self._mainMethodName)) + self.addAttribute( + '_mainCheetahMethod_for_' + self._className + + ' = ' + repr(self._mainMethodName)) def _setupInitMethod(self): __init__ = self._spawnMethodCompiler( @@ -1332,8 +1332,9 @@ class ClassCompiler(GenUtils): # the rest is added to the main output method of the class # ('mainMethod') - self.addChunk('if exists(self._filePath) and ' + - 'getmtime(self._filePath) > self._fileMtime:') + self.addChunk( + 'if exists(self._filePath) and ' + + 'getmtime(self._filePath) > self._fileMtime:') self.indent() self.addChunk( 'self._compile(file=self._filePath, moduleName=' @@ -1437,9 +1438,10 @@ class ClassCompiler(GenUtils): # any fancy Cheetah syntax (placeholders, directives, etc.) # inside the expression if attribExpr.find('VFN(') != -1 or attribExpr.find('VFFSL(') != -1: - raise ParseError(self, - 'Invalid #attr directive.' + - ' It should only contain simple Python literals.') + raise ParseError( + self, + 'Invalid #attr directive. It should only contain ' + + 'simple Python literals.') # now add the attribute self._generatedAttribs.append(attribExpr) @@ -1474,24 +1476,25 @@ class ClassCompiler(GenUtils): catcherMeth = self._spawnMethodCompiler( methodName, klass=MethodCompiler, - initialMethodComment=('## CHEETAH: Generated from ' + rawCode + - ' at line %s, col %s' % lineCol + '.') - ) + initialMethodComment=( + '## CHEETAH: Generated from ' + rawCode + + ' at line %s, col %s' % lineCol + '.') + ) catcherMeth.setMethodSignature( - 'def ' + methodName + - '(self, localsDict={})') # is this use of localsDict right? + 'def ' + methodName + + '(self, localsDict={})') # is this use of localsDict right? catcherMeth.addChunk('try:') catcherMeth.indent() - catcherMeth.addChunk("return eval('''" + codeChunk + - "''', globals(), localsDict)") + catcherMeth.addChunk( + "return eval('''" + codeChunk + "''', globals(), localsDict)") catcherMeth.dedent() catcherMeth.addChunk( 'except self._CHEETAH__errorCatcher.exceptions() as e:') catcherMeth.indent() catcherMeth.addChunk( - "return self._CHEETAH__errorCatcher.warn(exc_val=e, code= " + - repr(codeChunk) + " , rawCode= " + - repr(rawCode) + " , lineCol=" + str(lineCol) + ")") + "return self._CHEETAH__errorCatcher.warn(exc_val=e, code= " + + repr(codeChunk) + " , rawCode= " + + repr(rawCode) + " , lineCol=" + str(lineCol) + ")") catcherMeth.cleanupState() @@ -1543,19 +1546,19 @@ class ClassCompiler(GenUtils): def addMethods(): classDefChunks.extend([ - ind + '#'*50, + ind + '#'*50, # noqa: E226 missing whitespace around operator ind + '## CHEETAH GENERATED METHODS', '\n', self.methodDefs(), - ]) + ]) def addAttributes(): classDefChunks.extend([ - ind + '#'*50, + ind + '#'*50, # noqa: E226 missing whitespace around operator ind + '## CHEETAH GENERATED ATTRIBUTES', '\n', self.attributes(), - ]) + ]) if self.setting('outputMethodsBeforeAttributes'): addMethods() addAttributes() @@ -1574,9 +1577,9 @@ class ClassCompiler(GenUtils): if not self._classDocStringLines: return '' ind = self.setting('indentationStep') - docStr = ('%(ind)s"""\n%(ind)s' + - '\n%(ind)s'.join(self._classDocStringLines) + - '\n%(ind)s"""\n' + docStr = ('%(ind)s"""\n%(ind)s' + + '\n%(ind)s'.join(self._classDocStringLines) + + '\n%(ind)s"""\n' ) % {'ind': ind} return docStr @@ -1769,7 +1772,7 @@ class ModuleCompiler(SettingsManager, GenUtils): "import Cheetah.Filters as Filters", "import Cheetah.ErrorCatchers as ErrorCatchers", "from Cheetah.compat import unicode", - ] + ] self._importedVarNames = ['sys', 'os', @@ -1789,7 +1792,7 @@ class ModuleCompiler(SettingsManager, GenUtils): "VFSL=valueFromSearchList", "VFN=valueForName", "currentTime=time.time", - ] + ] def compile(self): classCompiler = self._spawnClassCompiler(self._mainClassName) @@ -1891,11 +1894,12 @@ class ModuleCompiler(SettingsManager, GenUtils): for chunk in chunks[1:-1]: if modName in self.importedVarNames(): needToAddImport = False - finalBaseClassName = klass.replace(modName+'.', '') + finalBaseClassName = klass.replace(modName + '.', + '') baseclasses.append(finalBaseClassName) break else: - modName += '.'+chunk + modName += '.' + chunk if needToAddImport: modName, finalClassName = ( '.'.join(chunks[:-1]), chunks[-1]) @@ -1962,7 +1966,7 @@ class ModuleCompiler(SettingsManager, GenUtils): def addSpecialVar(self, basename, contents, includeUnderscores=True): """Adds module __specialConstant__ to the module globals. """ - name = includeUnderscores and '__'+basename+'__' or basename + name = includeUnderscores and '__' + basename + '__' or basename self._specialVars[name] = contents.strip() def addImportStatement(self, impStatement): @@ -2027,7 +2031,24 @@ class ModuleCompiler(SettingsManager, GenUtils): else: return self.wrapModuleDef() - __str__ = getModuleCode + def __to_bytes(self): + code = self.getModuleCode() + if isinstance(code, bytes): + return code + return code.encode(self.getModuleEncoding()) + + def __to_unicode(self): + code = self.getModuleCode() + if isinstance(code, bytes): + return code.decode(self.getModuleEncoding()) + return code + + if PY2: + __str__ = __to_bytes + __unicode__ = __to_unicode + else: + __bytes__ = __to_bytes + __str__ = __to_unicode def wrapModuleDef(self): self.addSpecialVar('CHEETAH_docstring', self.setting('defDocStrMsg')) @@ -2087,7 +2108,7 @@ if not hasattr(%(mainClassName)s, '_initCheetahAttributes'): 'classes': self.classDefs(), 'footer': self.moduleFooter(), 'mainClassName': self._mainClassName, - } + } # noqa self._moduleDef = moduleDef return moduleDef @@ -2104,8 +2125,9 @@ if not hasattr(%(mainClassName)s, '_initCheetahAttributes'): offSet = self.setting('commentOffset') header += ( - '#' + ' '*offSet + - ('\n#' + ' '*offSet).join(self._moduleHeaderLines) + '\n') + '#' + ' '*offSet # noqa: E226,E501 missing whitespace around operator + + ('\n#' + ' '*offSet).join(self._moduleHeaderLines) # noqa: E226,E501 missing whitespace around operator + + '\n') return header @@ -2113,9 +2135,8 @@ if not hasattr(%(mainClassName)s, '_initCheetahAttributes'): if not self._moduleDocStringLines: return '' - return ('"""' + - '\n'.join(self._moduleDocStringLines) + - '\n"""\n') + return ('"""' + '\n'.join(self._moduleDocStringLines) + + '\n"""\n') def specialVars(self): chunks = [] diff --git a/Cheetah/ErrorCatchers.py b/Cheetah/ErrorCatchers.py index 835683f..aad302d 100644 --- a/Cheetah/ErrorCatchers.py +++ b/Cheetah/ErrorCatchers.py @@ -26,7 +26,7 @@ Echo = ErrorCatcher class BigEcho(ErrorCatcher): def warn(self, exc_val, code, rawCode, lineCol): - return "="*15 + "<" + rawCode + " could not be found>" + "="*15 + return "="*15 + "<" + rawCode + " could not be found>" + "="*15 # noqa: E226,E501 missing whitespace around operator class KeyError(ErrorCatcher): diff --git a/Cheetah/FileUtils.py b/Cheetah/FileUtils.py index c0f2afb..bdfa448 100644 --- a/Cheetah/FileUtils.py +++ b/Cheetah/FileUtils.py @@ -101,8 +101,8 @@ class FileFinder: """A hook for filtering out certain dirs. """ - return not (baseName in self._ignoreBasenames or - fullPath in self._ignoreDirs) + return not (baseName in self._ignoreBasenames + or fullPath in self._ignoreDirs) def processDir(self, dir, glob=glob): extend = self._files.extend diff --git a/Cheetah/Filters.py b/Cheetah/Filters.py index a0e59a2..abb740b 100644 --- a/Cheetah/Filters.py +++ b/Cheetah/Filters.py @@ -67,7 +67,7 @@ class Markdown(EncodeUnicode): tag, as it's usefulness with #filter is marginal at best ''' - def filter(self, value, **kwargs): + def filter(self, value, **kwargs): # This is a bit of a hack to allow outright embedding # of the markdown module. import markdown diff --git a/Cheetah/ImportHooks.py b/Cheetah/ImportHooks.py index e2a26e9..2441fa2 100644 --- a/Cheetah/ImportHooks.py +++ b/Cheetah/ImportHooks.py @@ -7,8 +7,13 @@ To use these: Cheetah.ImportHooks.install() """ +try: + from importlib import invalidate_caches +except ImportError: + invalidate_caches = None import sys import os.path +import py_compile import types try: import builtins as builtin @@ -44,6 +49,7 @@ class CheetahDirOwner(DirOwner): _releaseLock = _lock.release templateFileExtensions = ('.tmpl',) + debuglevel = 0 def getmod(self, name): self._acquireLock() @@ -71,22 +77,31 @@ class CheetahDirOwner(DirOwner): self._releaseLock() def _compile(self, name, tmplPath): + if invalidate_caches: + invalidate_caches() + # @@ consider adding an ImportError raiser here code = str(Compiler(file=tmplPath, moduleName=name, mainClassName=name)) if _cacheDir: - __file__ = os.path.join(_cacheDir[0], - convertTmplPathToModuleName(tmplPath)) \ - + '.py' - try: - open(__file__, 'w').write(code) - except OSError: - # @@ TR: need to add some error code here - traceback.print_exc(file=sys.stderr) - __file__ = tmplPath + __file__ = os.path.join( + _cacheDir[0], convertTmplPathToModuleName(tmplPath)) + '.py' else: + __file__ = os.path.splitext(tmplPath)[0] + '.py' + try: + with open(__file__, 'w') as _py_file: + _py_file.write(code) + except (IOError, OSError): + # @@ TR: need to add some error code here + if self.debuglevel > 0: + traceback.print_exc(file=sys.stderr) __file__ = tmplPath - co = compile(code+'\n', __file__, 'exec') + else: + try: + py_compile.compile(__file__) + except IOError: + pass + co = compile(code + '\n', __file__, 'exec') mod = types.ModuleType(name) mod.__file__ = co.co_filename diff --git a/Cheetah/ImportManager.py b/Cheetah/ImportManager.py index dbb2c96..8ea7419 100644 --- a/Cheetah/ImportManager.py +++ b/Cheetah/ImportManager.py @@ -17,9 +17,10 @@ This is a hacked/documented version of Gordon McMillan's iu.py. I have: - reorganized the code layout to enhance readability """ -import sys import imp import marshal +import py_compile +import sys from Cheetah.compat import string_type _installed = False @@ -77,7 +78,7 @@ def _os_bootstrap(): if dirname is None: def dirname(a, sep=sep): - for i in range(len(a)-1, -1, -1): + for i in range(len(a) - 1, -1, -1): c = a[i] if c == '/' or c == sep: return a[:i] @@ -100,7 +101,7 @@ _os_bootstrap() def packageName(s): - for i in range(len(s)-1, -1, -1): + for i in range(len(s) - 1, -1, -1): if s[i] == '.': break else: @@ -114,14 +115,14 @@ def nameSplit(s): for j in range(len(s)): if s[j] == '.': rslt.append(s[i:j]) - i = j+1 + i = j + 1 if i < len(s): rslt.append(s[i:]) return rslt def getPathExt(fnm): - for i in range(len(fnm)-1, -1, -1): + for i in range(len(fnm) - 1, -1, -1): if fnm[i] == '.': return fnm[i:] return '' @@ -186,18 +187,18 @@ class DirOwner(Owner): py = pyc = None for pth, ispkg, pkgpth in possibles: for ext, mode, typ in getsuffixes(): - attempt = pth+ext + attempt = pth + ext try: st = _os_stat(attempt) except Exception: pass else: if typ == imp.C_EXTENSION: - fp = open(attempt, 'rb') - mod = imp.load_module( - nm, fp, attempt, (ext, mode, typ)) - mod.__file__ = attempt - return mod + with open(attempt, 'rb') as fp: + mod = imp.load_module( + nm, fp, attempt, (ext, mode, typ)) + mod.__file__ = attempt + return mod elif typ == imp.PY_SOURCE: py = (attempt, st) else: @@ -209,23 +210,32 @@ class DirOwner(Owner): while True: if pyc is None or py and pyc[1][8] < py[1][8]: try: - co = compile(open(py[0], 'r').read()+'\n', py[0], 'exec') + with open(py[0], 'r') as py_code_file: + py_code = py_code_file.read() + co = compile(py_code + '\n', py[0], 'exec') + try: + py_compile.compile(py[0]) + except IOError: + pass + __file__ = py[0] break except SyntaxError as e: print("Invalid syntax in %s" % py[0]) print(e.args) raise elif pyc: - stuff = open(pyc[0], 'rb').read() + with open(pyc[0], 'rb') as pyc_file: + stuff = pyc_file.read() try: co = loadco(stuff[8:]) + __file__ = pyc[0] break except (ValueError, EOFError): pyc = None else: return None mod = newmod(nm) - mod.__file__ = co.co_filename + mod.__file__ = __file__ if ispkg: mod.__path__ = [pkgpth] subimporter = PathImportDirector(mod.__path__) @@ -268,7 +278,7 @@ class FrozenImportDirector(ImportDirector): if hasattr(mod, '__path__'): mod.__importsub__ = \ lambda name, pname=nm, owner=self: \ - owner.getmod(pname+'.'+name) + owner.getmod(pname + '.' + name) return mod return None @@ -313,10 +323,10 @@ class RegistryImportDirector(ImportDirector): stuff = self.map.get(nm) if stuff: fnm, desc = stuff - fp = open(fnm, 'rb') - mod = imp.load_module(nm, fp, fnm, desc) - mod.__file__ = fnm - return mod + with open(fnm, 'rb') as fp: + mod = imp.load_module(nm, fp, fnm, desc) + mod.__file__ = fnm + return mod return None @@ -466,7 +476,7 @@ class ImportManager: raise ImportError("No module named %s" % fqname) if fromlist is None: if context: - return sys.modules[context+'.'+nmparts[0]] + return sys.modules[context + '.' + nmparts[0]] return sys.modules[nmparts[0]] bottommod = sys.modules[ctx] if hasattr(bottommod, '__path__'): @@ -475,7 +485,7 @@ class ImportManager: while i < len(fromlist): nm = fromlist[i] if nm == '*': - fromlist[i:i+1] = list(getattr(bottommod, '__all__', [])) + fromlist[i:i+1] = list(getattr(bottommod, '__all__', [])) # noqa: E226,E501 missing whitespace around operator if i >= len(fromlist): break nm = fromlist[i] @@ -483,7 +493,7 @@ class ImportManager: if not hasattr(bottommod, nm): if self.threaded: self._acquire() - mod = self.doimport(nm, ctx, ctx+'.'+nm) + mod = self.doimport(nm, ctx, ctx + '.' + nm) if self.threaded: self._release() if not mod: diff --git a/Cheetah/LoadTemplate.py b/Cheetah/LoadTemplate.py new file mode 100644 index 0000000..6d4d173 --- /dev/null +++ b/Cheetah/LoadTemplate.py @@ -0,0 +1,56 @@ +import imp +import os +import sys +from Cheetah.ImportHooks import CheetahDirOwner + + +def _loadTemplate(templatePath, debuglevel=0): + """Load template by full or relative path (including extension) + + Example: template = loadTemplate('views/index.tmpl') + + Template is loaded from from .py[co], .py or .tmpl - + whatever will be found. Files *.tmpl are compiled to *.py; + *.py are byte-compiled to *.py[co]. Compiled files are cached + in the template directory. Errors on writing are silently ignored. + """ + drive, localPath = os.path.splitdrive(templatePath) + dirname, filename = os.path.split(localPath) + filename, ext = os.path.splitext(filename) + if dirname: + # Cleanup: Convert /Templates//views/ -> /Templates/views + dirname_list = dirname.replace(os.sep, '/').split('/') + dirname_list = [d for (i, d) in enumerate(dirname_list) + if i == 0 or d] # Preserve root slash + dirname = os.sep.join(dirname_list) + # Add all "modules" to sys.modules + components = [] + for d in dirname_list: + components.append(d) + _mod_name = '.'.join(components) + _mod = imp.new_module(_mod_name) + _d = os.path.abspath(os.sep.join(components)) + _mod.__file__ = _d + _mod.__path__ = [_d] + sys.modules[_mod_name] = _mod + template_dir = CheetahDirOwner(drive + dirname) + if ext: + template_dir.templateFileExtensions = (ext,) + template_dir.debuglevel = debuglevel + mod = template_dir.getmod(filename) + fqname = os.path.join(dirname, filename).replace(os.sep, '.') + mod.__name__ = fqname + sys.modules[fqname] = mod + co = mod.__co__ + del mod.__co__ + exec(co, mod.__dict__) + return mod, filename + + +def loadTemplateModule(templatePath, debuglevel=0): + return _loadTemplate(templatePath, debuglevel=debuglevel)[0] + + +def loadTemplateClass(templatePath, debuglevel=0): + mod, filename = _loadTemplate(templatePath, debuglevel=debuglevel) + return getattr(mod, filename) diff --git a/Cheetah/Macros/I18n.py b/Cheetah/Macros/I18n.py index 02a815b..8a4ac09 100644 --- a/Cheetah/Macros/I18n.py +++ b/Cheetah/Macros/I18n.py @@ -49,6 +49,6 @@ class I18n(object): # print macros['i18n'] src = _(src) if isShortForm and endPos < len(parser): - return src+EOLCharsInShortForm + return src + EOLCharsInShortForm else: return src diff --git a/Cheetah/NameMapper.py b/Cheetah/NameMapper.py index 68ded17..40cdf1f 100755 --- a/Cheetah/NameMapper.py +++ b/Cheetah/NameMapper.py @@ -197,8 +197,8 @@ def _isInstanceOrClass(obj): if hasattr(obj, 'mro'): # type/class return True - elif (hasattr(obj, '__func__') or hasattr(obj, '__code__') or - hasattr(obj, '__self__')): + elif (hasattr(obj, '__func__') or hasattr(obj, '__code__') + or hasattr(obj, '__self__')): # method, func, or builtin func return False elif hasattr(obj, '__init__'): @@ -260,7 +260,7 @@ def hasName(obj, name): try: from Cheetah._namemapper import NotFound, valueForKey, valueForName, \ - valueFromSearchList, valueFromFrameOrSearchList, valueFromFrame + valueFromSearchList, valueFromFrameOrSearchList, valueFromFrame C_VERSION = True except Exception: class NotFound(LookupError): @@ -365,7 +365,7 @@ def example(): 'default': 'default output', 'one': 'output option one', 'two': 'output option two' - } + } return values[whichOne] a.dic = { @@ -373,7 +373,7 @@ def example(): 'method': a.method3, 'item': 'itemval', 'subDict': {'nestedMethod': a.method3} - } + } # b = 'this is local b' print(valueForKey(a.dic, 'subDict')) diff --git a/Cheetah/Parser.py b/Cheetah/Parser.py index 0b7f508..5d6837e 100644 --- a/Cheetah/Parser.py +++ b/Cheetah/Parser.py @@ -42,20 +42,24 @@ def escapeRegexChars(txt, return escapeRE.sub(r'\\\1', txt) -def group(*choices): return '(' + '|'.join(choices) + ')' +def group(*choices): + return '(' + '|'.join(choices) + ')' -def nongroup(*choices): return '(?:' + '|'.join(choices) + ')' +def nongroup(*choices): + return '(?:' + '|'.join(choices) + ')' def namedGroup(name, *choices): return '(P:<' + name + '>' + '|'.join(choices) + ')' -def any(*choices): return group(*choices) + '*' +def any(*choices): + return group(*choices) + '*' -def maybe(*choices): return group(*choices) + '?' +def maybe(*choices): + return group(*choices) + '?' ################################################## # CONSTANTS & GLOBALS ## @@ -73,8 +77,7 @@ SET_MODULE = 2 # Tokens for the parser ## # generic -identchars = "abcdefghijklmnopqrstuvwxyz" \ - "ABCDEFGHIJKLMNOPQRSTUVWXYZ_" +identchars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_" namechars = identchars + "0123456789" # operators @@ -91,19 +94,19 @@ assignmentOps = (assignOp,) + augAssignOps compOps = ('<', '>', '==', '!=', '<=', '>=', '<>', 'is', 'in',) booleanOps = ('and', 'or', 'not') operators = (powerOp,) + unaryArithOps + binaryArithOps \ - + shiftOps + bitwiseOps + assignmentOps \ - + compOps + booleanOps + + shiftOps + bitwiseOps + assignmentOps \ + + compOps + booleanOps delimeters = ('(', ')', '{', '}', '[', ']', ',', '.', ':', ';', '=', '`') + augAssignOps -keywords = ('and', 'del', 'for', 'is', 'raise', - 'assert', 'elif', 'from', 'lambda', 'return', - 'break', 'else', 'global', 'not', 'try', - 'class', 'except', 'if', 'or', 'while', - 'continue', 'exec', 'import', 'pass', - 'def', 'finally', 'in', 'print', +keywords = ('and', 'del', 'for', 'is', 'raise', # noqa: E241,E501 multiple spaces after ',' + 'assert', 'elif', 'from', 'lambda', 'return', # noqa: E241,E501 multiple spaces after ',' + 'break', 'else', 'global', 'not', 'try', # noqa: E241,E501 multiple spaces after ',' + 'class', 'except', 'if', 'or', 'while', # noqa: E241,E501 multiple spaces after ',' + 'continue', 'exec', 'import', 'pass', # noqa: E241,E501 multiple spaces after ',' + 'def', 'finally', 'in', 'print', # noqa: E241,E501 multiple spaces after ',' ) single3 = "'''" @@ -235,7 +238,7 @@ directiveNamesAndParsers = { 'encoding': 'eatEncoding', 'end': 'eatEndDirective', - } +} endDirectiveNamesAndHandlers = { 'def': 'handleEndDef', # has short-form @@ -252,7 +255,7 @@ endDirectiveNamesAndHandlers = { 'try': None, # has short-form 'repeat': None, # has short-form 'unless': None, # has short-form - } +} ################################################## # CLASSES ## @@ -285,7 +288,7 @@ class ParseError(ValueError): if self.lineno: lineno = self.lineno row, col, line = (lineno, (self.col or 0), - self.stream.splitlines()[lineno-1]) + self.stream.splitlines()[lineno - 1]) else: row, col, line = self.stream.getRowColLine() @@ -295,13 +298,13 @@ class ParseError(ValueError): for i in range(1, 4): if row - 1 - i <= 0: break - prevLines.append((row-i, lines[row-1-i])) + prevLines.append((row - i, lines[row - 1 - i])) nextLines = [] # (rowNum, content) for i in range(1, 4): - if not row-1+i < len(lines): + if not row - 1 + i < len(lines): break - nextLines.append((row+i, lines[row-1+i])) + nextLines.append((row + i, lines[row - 1 + i])) nextLines.reverse() # print the main message @@ -315,7 +318,7 @@ class ParseError(ValueError): report += "%(row)-4d|%(line)s\n" \ % {'row': lineInfo[0], 'line': lineInfo[1]} report += "%(row)-4d|%(line)s\n" % {'row': row, 'line': line} - report += ' '*5 + ' '*(col-1) + "^\n" + report += ' '*5 + ' '*(col - 1) + "^\n" # noqa: E226,E501 missing whitespace around operator while nextLines: lineInfo = nextLines.pop() @@ -426,11 +429,11 @@ class _LowLevelParser(SourceReader): self._makeDirectiveREs() self._makePspREs() self._possibleNonStrConstantChars = ( - self.setting('commentStartToken')[0] + - self.setting('multiLineCommentStartToken')[0] + - self.setting('cheetahVarStartToken')[0] + - self.setting('directiveStartToken')[0] + - self.setting('PSPStartToken')[0]) + self.setting('commentStartToken')[0] + + self.setting('multiLineCommentStartToken')[0] + + self.setting('cheetahVarStartToken')[0] + + self.setting('directiveStartToken')[0] + + self.setting('PSPStartToken')[0]) self._nonStrConstMatchers = [ self.matchCommentStartToken, self.matchMultiLineCommentStartToken, @@ -439,7 +442,7 @@ class _LowLevelParser(SourceReader): self.matchDirective, self.matchPSPStartToken, self.matchEOLSlurpToken, - ] + ] # regex setup ## @@ -448,64 +451,66 @@ class _LowLevelParser(SourceReader): """Setup the regexs for Cheetah $var parsing.""" num = r'[0-9\.]+' - interval = (r'(?P' + - num + r's|' + - num + r'm|' + - num + r'h|' + - num + r'd|' + - num + r'w|' + - num + ')' + interval = (r'(?P' + + num + r's|' + + num + r'm|' + + num + r'h|' + + num + r'd|' + + num + r'w|' + + num + ')' ) - cacheToken = (r'(?:' + - r'(?P\*' + interval + '\*)' + - '|' + - r'(?P\*)' + - '|' + - r'(?P)' + - ')') + cacheToken = (r'(?:' + + r'(?P\*' + interval + '\*)' + + '|' + + r'(?P\*)' + + '|' + + r'(?P)' + + ')') self.cacheTokenRE = cachedRegex(cacheToken) - silentPlaceholderToken = (r'(?:' + - r'(?P' + escapeRegexChars('!')+')' + - '|' + - r'(?P)' + - ')') + silentPlaceholderToken = (r'(?:' + + r'(?P' + + escapeRegexChars('!') + ')' + + '|' + + r'(?P)' + + ')') self.silentPlaceholderTokenRE = cachedRegex(silentPlaceholderToken) self.cheetahVarStartRE = cachedRegex( - escCharLookBehind + r'(?P' + - escapeRegexChars(self.setting('cheetahVarStartToken')) + ')' + - r'(?P' + silentPlaceholderToken+')' + - r'(?P' + cacheToken + ')' + + escCharLookBehind + r'(?P' + + escapeRegexChars(self.setting('cheetahVarStartToken')) + ')' + + r'(?P' + silentPlaceholderToken + ')' + + r'(?P' + cacheToken + ')' # allow WS after enclosure - r'(?P|(?:(?:\{|\(|\[)[ \t\f]*))' + r'(?=[A-Za-z_])') + + r'(?P|(?:(?:\{|\(|\[)[ \t\f]*))' + r'(?=[A-Za-z_])') validCharsLookAhead = r'(?=[A-Za-z_\*!\{\(\[])' self.cheetahVarStartToken = self.setting('cheetahVarStartToken') self.cheetahVarStartTokenRE = cachedRegex( - escCharLookBehind + - escapeRegexChars(self.setting('cheetahVarStartToken')) + escCharLookBehind + + escapeRegexChars(self.setting('cheetahVarStartToken')) + validCharsLookAhead - ) + ) self.cheetahVarInExpressionStartTokenRE = cachedRegex( escapeRegexChars(self.setting('cheetahVarStartToken')) + r'(?=[A-Za-z_])' - ) + ) self.expressionPlaceholderStartRE = cachedRegex( - escCharLookBehind + r'(?P' + - escapeRegexChars(self.setting('cheetahVarStartToken')) + ')' + - r'(?P' + cacheToken + ')' + + escCharLookBehind + r'(?P' + + escapeRegexChars(self.setting('cheetahVarStartToken')) + + ')' + + r'(?P' + cacheToken + ')' # r'\[[ \t\f]*' - r'(?:\{|\(|\[)[ \t\f]*' + r'(?=[^\)\}\]])') + + r'(?:\{|\(|\[)[ \t\f]*' + r'(?=[^\)\}\]])') if self.setting('EOLSlurpToken'): self.EOLSlurpRE = cachedRegex( escapeRegexChars(self.setting('EOLSlurpToken')) + r'[ \t\f]*' - + r'(?:'+EOL+')' - ) + + r'(?:' + EOL + ')' + ) else: self.EOLSlurpRE = None @@ -520,10 +525,10 @@ class _LowLevelParser(SourceReader): self.setting('multiLineCommentStartToken')) endTokenEsc = escapeRegexChars( self.setting('multiLineCommentEndToken')) - self.multiLineCommentTokenStartRE = cachedRegex(escCharLookBehind + - startTokenEsc) - self.multiLineCommentEndTokenRE = cachedRegex(escCharLookBehind + - endTokenEsc) + self.multiLineCommentTokenStartRE = cachedRegex( + escCharLookBehind + startTokenEsc) + self.multiLineCommentEndTokenRE = cachedRegex( + escCharLookBehind + endTokenEsc) def _makeDirectiveREs(self): """Construct the regexs that are used in directive parsing.""" @@ -744,7 +749,8 @@ class _LowLevelParser(SourceReader): self.setPos(startPos) return directiveName - def matchDirectiveName(self, directiveNameChars=identchars+'0123456789-@'): + def matchDirectiveName(self, + directiveNameChars=identchars + '0123456789-@'): startPos = self.pos() possibleMatches = self._directiveNamesAndParsers.keys() name = '' @@ -791,7 +797,7 @@ class _LowLevelParser(SourceReader): def matchColonForSingleLineShortFormDirective(self): if not self.atEnd() and self.peek() == ':': - restOfLine = self[self.pos()+1:self.findEOL()] + restOfLine = self[self.pos()+1:self.findEOL()] # noqa: E226,E501 missing whitespace around operator restOfLine = restOfLine.strip() if not restOfLine: return False @@ -937,7 +943,7 @@ class _LowLevelParser(SourceReader): break elif self.peek() == '.': - if self.pos()+1 < len(self) and self.peek(1) in identchars: + if self.pos() + 1 < len(self) and self.peek(1) in identchars: # discard the period as it isn't needed with NameMapper self.advance() else: @@ -953,7 +959,7 @@ class _LowLevelParser(SourceReader): period = max(dottedName.rfind('.'), 0) if period: chunks.append((dottedName[:period], autoCall, '')) - dottedName = dottedName[period+1:] + dottedName = dottedName[period+1:] # noqa: E226,E501 missing whitespace around operator if rest and rest[0] == '(': autoCall = False chunks.append((dottedName, autoCall, rest)) @@ -994,8 +1000,8 @@ class _LowLevelParser(SourceReader): close = closurePairsRev[open] self.setPos(enclosures[-1][1]) raise ParseError( - self, msg="EOF was reached before a matching '" + close + - "' was found for the '" + open + "'") + self, msg="EOF was reached before a matching '" + close + + "' was found for the '" + open + "'") c = self.peek() if c in ")}]": # get the ending enclosure and break @@ -1163,8 +1169,8 @@ class _LowLevelParser(SourceReader): self.setPos(enclosures[-1][1]) raise ParseError( self, - msg="EOF was reached before a matching '" + close + - "' was found for the '" + open + "'") + msg="EOF was reached before a matching '" + close + + "' was found for the '" + open + "'") else: break @@ -1189,18 +1195,18 @@ class _LowLevelParser(SourceReader): self.setPos(enclosures[-1][1]) raise ParseError( self, - msg="A '" + c + "' was found at line " + str(row) + - ", col " + str(col) + - " before a matching '" + close + - "' was found\nfor the '" + open + "'") + msg="A '" + c + "' was found at line " + str(row) + + ", col " + str(col) + + " before a matching '" + close + + "' was found\nfor the '" + open + "'") self.advance() elif c in " \f\t": exprBits.append(self.getWhiteSpace()) elif self.matchDirectiveEndToken() and not enclosures: break - elif c == "\\" and self.pos()+1 < srcLen: - eolMatch = EOLre.match(self.src(), self.pos()+1) + elif c == "\\" and self.pos() + 1 < srcLen: + eolMatch = EOLre.match(self.src(), self.pos() + 1) if not eolMatch: self.advance() raise ParseError(self, msg='Line ending expected') @@ -1275,23 +1281,23 @@ class _LowLevelParser(SourceReader): startPosIdx = 3 else: startPosIdx = 1 - self.setPos(beforeTokenPos+startPosIdx+1) + self.setPos(beforeTokenPos + startPosIdx + 1) outputExprs = [] strConst = '' - while self.pos() < (endPos-startPosIdx): + while self.pos() < (endPos - startPosIdx): if self.matchCheetahVarStart() \ or self.matchExpressionPlaceholderStart(): if strConst: outputExprs.append(repr(strConst)) strConst = '' placeholderExpr = self.getPlaceholder() - outputExprs.append('str('+placeholderExpr+')') + outputExprs.append('str(' + placeholderExpr + ')') else: strConst += self.getc() self.setPos(endPos) if strConst: outputExprs.append(repr(strConst)) - token = "''.join(["+','.join(outputExprs)+"])" + token = "''.join([" + ','.join(outputExprs) + "])" return token def _raiseErrorAboutInvalidCheetahVarSyntaxInExpr(self): @@ -1511,7 +1517,7 @@ class _HighLevelParser(_LowLevelParser): but I haven't thought of a better name yet. Suggestions? """ for callback in self.setting('expressionFilterHooks'): - expr = callback(parser=self, expr=expr, exprType=exprType, + expr = callback(parser=self, expr=expr, exprType=exprType, rawExpr=rawExpr, startPos=startPos) return expr @@ -1675,13 +1681,13 @@ class _HighLevelParser(_LowLevelParser): elif directiveName in self._simpleIndentingDirectives: handlerName = self._directiveHandlerNames.get(directiveName) if not handlerName: - handlerName = 'add'+directiveName.capitalize() + handlerName = 'add' + directiveName.capitalize() handler = getattr(self._compiler, handlerName) self.eatSimpleIndentingDirective(directiveName, callback=handler) elif directiveName in self._simpleExprDirectives: handlerName = self._directiveHandlerNames.get(directiveName) if not handlerName: - handlerName = 'add'+directiveName.capitalize() + handlerName = 'add' + directiveName.capitalize() handler = getattr(self._compiler, handlerName) if directiveName in ('silent', 'echo'): includeDirectiveNameInExpr = False @@ -1936,12 +1942,12 @@ class _HighLevelParser(_LowLevelParser): 'An error occurred while processing ' 'the following #compiler directive.\n') sys.stderr.write( - '------------------------------------' - '----------------------------------\n') + '------------------------------------' + '----------------------------------\n') sys.stderr.write('%s\n' % self[startPos:endPos]) sys.stderr.write( - '------------------------------------' - '----------------------------------\n') + '------------------------------------' + '----------------------------------\n') sys.stderr.write('Please check the syntax of these settings.\n\n') raise @@ -1976,8 +1982,8 @@ class _HighLevelParser(_LowLevelParser): 'An error occurred while processing ' 'the following compiler settings.\n') sys.stderr.write( - '------------------------------------' - '----------------------------------\n') + '------------------------------------' + '----------------------------------\n') sys.stderr.write('%s\n' % settingsStr.strip()) sys.stderr.write( '------------------------------------' @@ -2037,7 +2043,7 @@ class _HighLevelParser(_LowLevelParser): self._compiler._blockMetaData[methodName] = { 'raw': rawSignature, 'lineCol': self.getRowCol(startPos), - } + } def eatClosure(self): # filtered @@ -2119,8 +2125,8 @@ class _HighLevelParser(_LowLevelParser): endOfFirstLinePos = self.findEOL() self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos) signature = ' '.join([line.strip() for line in signature.splitlines()]) - parserComment = ('## CHEETAH: generated from ' + signature + - ' at line %s, col %s' % self.getRowCol(startPos) + parserComment = ('## CHEETAH: generated from ' + signature + + ' at line %s, col %s' % self.getRowCol(startPos) + '.') isNestedDef = (self.setting('allowNestedDefScopes') @@ -2140,8 +2146,8 @@ class _HighLevelParser(_LowLevelParser): argsList, startPos, endPos): # filtered in calling method fullSignature = self[startPos:endPos] - parserComment = ('## Generated from ' + fullSignature + - ' at line %s, col %s' % self.getRowCol(startPos) + parserComment = ('## Generated from ' + fullSignature + + ' at line %s, col %s' % self.getRowCol(startPos) + '.') isNestedDef = (self.setting('allowNestedDefScopes') and [name for name in self._openDirectivesStack @@ -2704,8 +2710,8 @@ class _HighLevelParser(_LowLevelParser): expr = ''.join(expressionParts).strip() expr = self._applyExpressionFilters(expr, 'if', startPos=startPos) - isTernaryExpr = ('then' in expressionParts and - 'else' in expressionParts) + isTernaryExpr = ('then' in expressionParts + and 'else' in expressionParts) if isTernaryExpr: conditionExpr = [] trueExpr = [] @@ -2744,9 +2750,9 @@ class _HighLevelParser(_LowLevelParser): # end directive handlers def handleEndDef(self): - isNestedDef = (self.setting('allowNestedDefScopes') and - [name for name in self._openDirectivesStack - if name == 'def']) + isNestedDef = (self.setting('allowNestedDefScopes') + and [name for name in self._openDirectivesStack + if name == 'def']) if not isNestedDef: self._compiler.closeDef() else: diff --git a/Cheetah/SettingsManager.py b/Cheetah/SettingsManager.py index e2e847d..ac6e598 100644 --- a/Cheetah/SettingsManager.py +++ b/Cheetah/SettingsManager.py @@ -114,7 +114,7 @@ class _SettingsCollector(object): 'False': (0 == 1), } newSettings = {'self': self} - exec((theString+os.linesep), globalsDict, newSettings) + exec((theString + os.linesep), globalsDict, newSettings) del newSettings['self'] module = types.ModuleType('temp_settings_module') module.__dict__.update(newSettings) diff --git a/Cheetah/SourceReader.py b/Cheetah/SourceReader.py index 44eb3ba..a45f1eb 100644 --- a/Cheetah/SourceReader.py +++ b/Cheetah/SourceReader.py @@ -77,13 +77,13 @@ class SourceReader(object): pos = self._pos lineNum = self.lineNum(pos) BOL = self._BOLs[lineNum] - return lineNum+1, pos-BOL+1 + return lineNum + 1, pos - BOL + 1 def getRowColLine(self, pos=None): if pos is None: pos = self._pos row, col = self.getRowCol(pos) - return row, col, self.splitlines()[row-1] + return row, col, self.splitlines()[row - 1] def getLine(self, pos): if pos is None: @@ -105,7 +105,7 @@ class SourceReader(object): if not pos <= self._breakPoint: raise Error( "pos (" + str(pos) + ") is invalid: beyond the stream's end (" - + str(self._breakPoint-1) + ")") + + str(self._breakPoint - 1) + ")") elif not pos >= 0: raise Error("pos (" + str(pos) + ") is invalid: less than 0") @@ -115,9 +115,9 @@ class SourceReader(object): def setBreakPoint(self, pos): if pos > self._srcLen: raise Error( - "New breakpoint (" + str(pos) + - ") is invalid: beyond the end of stream's source string (" + - str(self._srcLen) + ")") + "New breakpoint (" + str(pos) + + ") is invalid: beyond the end of stream's source string (" + + str(self._srcLen) + ")") elif not pos >= 0: raise Error( "New breakpoint (" + str(pos) + ") is invalid: less than 0") @@ -137,8 +137,8 @@ class SourceReader(object): "Invalid bookmark (" + name + ") is invalid: does not exist") pos = self._bookmarks[name] if not self.validPos(pos): - raise Error("Invalid bookmark (" + name + ', ' + - str(pos) + ") is invalid: pos is out of range") + raise Error("Invalid bookmark (" + name + ', ' + + str(pos) + ") is invalid: pos is out of range") self._pos = pos def atEnd(self): @@ -148,13 +148,13 @@ class SourceReader(object): return self._pos == 0 def peek(self, offset=0): - self.checkPos(self._pos+offset) + self.checkPos(self._pos + offset) pos = self._pos + offset return self._src[pos] def getc(self): pos = self._pos - if self.validPos(pos+1): + if self.validPos(pos + 1): self._pos += 1 return self._src[pos] @@ -215,7 +215,7 @@ class SourceReader(object): if pos is None: pos = self._pos src = self.src() - return max(src.rfind('\n', 0, pos)+1, src.rfind('\r', 0, pos)+1, 0) + return max(src.rfind('\n', 0, pos) + 1, src.rfind('\r', 0, pos) + 1, 0) def findEOL(self, pos=None, gobble=False): if pos is None: @@ -250,7 +250,7 @@ class SourceReader(object): start = self.pos() breakPoint = self.breakPoint() if max is not None: - breakPoint = min(breakPoint, self.pos()+max) + breakPoint = min(breakPoint, self.pos() + max) while self.pos() < breakPoint: self.advance() if not self.matchWhiteSpace(WSchars): diff --git a/Cheetah/Template.py b/Cheetah/Template.py index 2cfd404..c66c030 100644 --- a/Cheetah/Template.py +++ b/Cheetah/Template.py @@ -274,31 +274,31 @@ class Template(Servlet): # this is used by ._addCheetahPlumbingCodeToClass() _CHEETAH_requiredCheetahMethods = ( - '_initCheetahInstance', - 'searchList', - 'errorCatcher', - 'getVar', - 'varExists', - 'getFileContents', - 'i18n', - 'runAsMainProgram', - 'respond', - 'shutdown', - 'webInput', - 'serverSidePath', - 'generatedClassCode', - 'generatedModuleCode', - - '_getCacheStore', - '_getCacheStoreIdPrefix', - '_createCacheRegion', - 'getCacheRegion', - 'getCacheRegions', - 'refreshCache', - - '_handleCheetahInclude', - '_getTemplateAPIClassForIncludeDirectiveCompilation', - ) + '_initCheetahInstance', + 'searchList', + 'errorCatcher', + 'getVar', + 'varExists', + 'getFileContents', + 'i18n', + 'runAsMainProgram', + 'respond', + 'shutdown', + 'webInput', + 'serverSidePath', + 'generatedClassCode', + 'generatedModuleCode', + + '_getCacheStore', + '_getCacheStoreIdPrefix', + '_createCacheRegion', + 'getCacheRegion', + 'getCacheRegions', + 'refreshCache', + + '_handleCheetahInclude', + '_getTemplateAPIClassForIncludeDirectiveCompilation', + ) _CHEETAH_requiredCheetahClassMethods = ('subclass',) _CHEETAH_requiredCheetahClassAttributes = ( 'cacheRegionClass', 'cacheStore', @@ -979,15 +979,15 @@ class Template(Servlet): compilerSettings=settings.compilerSettings, placeholderToken=settings.placeholderToken, directiveToken=settings.directiveToken - ) + ) return settings @classmethod def _updateSettingsWithPreprocessTokens( klass, compilerSettings, placeholderToken, directiveToken): - if (placeholderToken and - 'cheetahVarStartToken' not in compilerSettings): + if (placeholderToken + and 'cheetahVarStartToken' not in compilerSettings): compilerSettings['cheetahVarStartToken'] = placeholderToken if directiveToken: if 'directiveStartToken' not in compilerSettings: @@ -995,13 +995,13 @@ class Template(Servlet): if 'directiveEndToken' not in compilerSettings: compilerSettings['directiveEndToken'] = directiveToken if 'commentStartToken' not in compilerSettings: - compilerSettings['commentStartToken'] = directiveToken*2 + compilerSettings['commentStartToken'] = directiveToken*2 # noqa: E226,E501 missing whitespace around operator if 'multiLineCommentStartToken' not in compilerSettings: compilerSettings['multiLineCommentStartToken'] = ( - directiveToken+'*') + directiveToken + '*') if 'multiLineCommentEndToken' not in compilerSettings: compilerSettings['multiLineCommentEndToken'] = ( - '*'+directiveToken) + '*' + directiveToken) if 'EOLSlurpToken' not in compilerSettings: compilerSettings['EOLSlurpToken'] = directiveToken @@ -1029,7 +1029,7 @@ class Template(Servlet): classmethod(meth.__func__)) for attrname in klass._CHEETAH_requiredCheetahClassAttributes: - attrname = '_CHEETAH_'+attrname + attrname = '_CHEETAH_' + attrname if not hasattr(concreteTemplateClass, attrname): attrVal = getattr(klass, attrname) setattr(concreteTemplateClass, attrname, attrVal) @@ -1236,8 +1236,8 @@ class Template(Servlet): ('file', 'string, file open for reading, or None')) if not isinstance(filter, (string_type, type)) \ - and not (isinstance(filter, type) and - issubclass(filter, Filters.Filter)): + and not (isinstance(filter, type) + and issubclass(filter, Filters.Filter)): raise TypeError(errmsgextra % ('filter', 'string or class', '(if class, must be subclass ' @@ -1266,8 +1266,8 @@ class Template(Servlet): ('compilerSettings', 'dictionary')) if source is not None and file is not None: - raise TypeError("you must supply either a source string or the" + - " 'file' keyword argument, but not both") + raise TypeError("you must supply either a source string or the" + + " 'file' keyword argument, but not both") ################################################## # Do superclass initialization. @@ -1283,9 +1283,10 @@ class Template(Servlet): convertVersionStringToTuple(compiledVersion) if compiledVersionTuple < MinCompatibleVersionTuple: raise AssertionError( - 'This template was compiled with Cheetah version %s.' - 'Templates compiled before version %s must be recompiled.' - % (compiledVersion, MinCompatibleVersion)) + 'This template was compiled with Cheetah version %s.' + 'Templates compiled before version %s ' + 'must be recompiled.' + % (compiledVersion, MinCompatibleVersion)) except AssertionError: raise except Exception: @@ -1348,9 +1349,9 @@ class Template(Servlet): """ return self._CHEETAH_generatedModuleCode[ - self._CHEETAH_generatedModuleCode.find('\nclass '): - self._CHEETAH_generatedModuleCode.find( - '\n## END CLASS DEFINITION')] + self._CHEETAH_generatedModuleCode.find('\nclass '): + self._CHEETAH_generatedModuleCode.find( + '\n## END CLASS DEFINITION')] def searchList(self): """Return a reference to the searchlist @@ -1919,28 +1920,28 @@ class Template(Servlet): global _formUsedByWebInput if _formUsedByWebInput is None: _formUsedByWebInput = cgi.FieldStorage() - source, func = 'field', _formUsedByWebInput.getvalue + source, func = 'field', _formUsedByWebInput.getvalue elif isCgi and src == 'c': raise RuntimeError("can't get cookies from a CGI script") elif isCgi and src == 's': raise RuntimeError("can't get session variables from a CGI script") elif isCgi and src == 'v': - source, func = 'value', self.request().value + source, func = 'value', self.request().value elif isCgi and src == 's': source, func = 'session', self.request().session().value elif src == 'f': - source, func = 'field', self.request().field + source, func = 'field', self.request().field elif src == 'c': - source, func = 'cookie', self.request().cookie + source, func = 'cookie', self.request().cookie elif src == 'v': - source, func = 'value', self.request().value + source, func = 'value', self.request().value elif src == 's': source, func = 'session', self.request().session().value # noqa: E501,F841 else: raise TypeError("arg 'src' invalid") converters = { - '': _Converter('string', None, default, default), - 'int': _Converter('int', int, defaultInt, badInt), + '': _Converter('string', None, default, default), + 'int': _Converter('int', int, defaultInt, badInt), 'float': _Converter('float', float, defaultFloat, badFloat), } # pprint.pprint(locals()); return {} @@ -1986,15 +1987,15 @@ def genParserErrorFromPythonException(source, file, prevLines = [] # (i, content) for i in range(1, 4): - if pyLineno-i <= 0: + if pyLineno - i <= 0: break - prevLines.append((pyLineno+1-i, lines[pyLineno-i])) + prevLines.append((pyLineno + 1 - i, lines[pyLineno - i])) nextLines = [] # (i, content) for i in range(1, 4): - if not pyLineno+i < len(lines): + if not pyLineno + i < len(lines): break - nextLines.append((pyLineno+i, lines[pyLineno+i])) + nextLines.append((pyLineno + i, lines[pyLineno + i])) nextLines.reverse() report = 'Line|Python Code\n' report += '----|--------------------------' \ @@ -2005,7 +2006,7 @@ def genParserErrorFromPythonException(source, file, % {'row': lineInfo[0], 'line': lineInfo[1]} if hasattr(exception, 'offset'): - report += ' '*(3+(exception.offset or 0)) + '^\n' + report += ' '*(3 + (exception.offset or 0)) + '^\n' # noqa: E226,E501 missing whitespace around operator while nextLines: lineInfo = nextLines.pop() @@ -2014,13 +2015,13 @@ def genParserErrorFromPythonException(source, file, message = [ "Error in the Python code which Cheetah generated for this template:", - '='*80, + '='*80, # noqa: E226 missing whitespace around operator '', str(exception), '', report, - '='*80, - ] + '='*80, # noqa: E226 missing whitespace around operator + ] cheetahPosMatch = re.search('line (\d+), col (\d+)', formatedExc) if cheetahPosMatch: lineno = int(cheetahPosMatch.group(1)) @@ -2032,7 +2033,7 @@ def genParserErrorFromPythonException(source, file, lineno = None col = None cheetahPosMatch = re.search('line (\d+), col (\d+)', - '\n'.join(lines[max(pyLineno-2, 0):])) + '\n'.join(lines[max(pyLineno - 2, 0):])) if cheetahPosMatch: lineno = int(cheetahPosMatch.group(1)) col = int(cheetahPosMatch.group(2)) diff --git a/Cheetah/TemplateCmdLineIface.py b/Cheetah/TemplateCmdLineIface.py index 17c8be5..eef0f2d 100644 --- a/Cheetah/TemplateCmdLineIface.py +++ b/Cheetah/TemplateCmdLineIface.py @@ -36,7 +36,7 @@ class CmdLineIface: try: self._opts, self._args = getopt.getopt( self._cmdLineArgs, 'h', ['help', 'env', 'pickle='] - ) + ) except getopt.GetoptError as v: # print help information and exit: diff --git a/Cheetah/Templates/_SkeletonPage.py b/Cheetah/Templates/_SkeletonPage.py index 085d625..1e0fcc5 100644 --- a/Cheetah/Templates/_SkeletonPage.py +++ b/Cheetah/Templates/_SkeletonPage.py @@ -38,7 +38,7 @@ class _SkeletonPage(Template): 'Content-Type': 'text/html; charset=iso-8859-1', }, 'NAME': { - 'generator': 'Cheetah: The Python-Powered Template Engine' + 'generator': 'Cheetah: The Python-Powered Template Engine' } } # metaTags = { diff --git a/Cheetah/Tests/Filters.py b/Cheetah/Tests/Filters.py index 23d2ebb..c973887 100755 --- a/Cheetah/Tests/Filters.py +++ b/Cheetah/Tests/Filters.py @@ -28,7 +28,7 @@ Header except ImportError as ex: print('>>> We probably failed to import markdown, bummer %s' % ex) return - except Exception as ex: + except Exception: raise diff --git a/Cheetah/Tests/ImportHooks.py b/Cheetah/Tests/ImportHooks.py new file mode 100755 index 0000000..fb631ce --- /dev/null +++ b/Cheetah/Tests/ImportHooks.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python + +from glob import glob +import os +import shutil +import sys +import unittest +import Cheetah.ImportHooks + + +ImportHooksTemplatesDir = os.path.join( + os.path.dirname(__file__), 'ImportHooksTemplates') + + +def setUpModule(): + sys.path.append(ImportHooksTemplatesDir) + + +def tearDownModule(): + assert sys.path[-1] == ImportHooksTemplatesDir + del sys.path[-1] + + +def _cleanup(): + py_files = os.path.join(ImportHooksTemplatesDir, '*.py') + pyc_files = py_files + 'c' + for fname in glob(py_files) + glob(pyc_files): + os.remove(fname) + __pycache__ = os.path.join(ImportHooksTemplatesDir, '__pycache__') + if os.path.isdir(__pycache__): + shutil.rmtree(__pycache__) + + for modname in list(sys.modules.keys()): + if '.ImportHooksTemplates.' in modname \ + or modname.endswith('.ImportHooksTemplates'): + del sys.modules[modname] + + for modname in 'index', 'layout': + if modname in sys.modules: + del sys.modules[modname] + + +def _exec(code, _dict): + exec(code, _dict) + + +class ImportHooksTest(unittest.TestCase): + def setUp(self): + _cleanup() + + def test_CheetahDirOwner(self): + templates = list(sorted(os.listdir(ImportHooksTemplatesDir))) + self.assertListEqual(templates, ['index.tmpl', 'layout.tmpl']) + + cdo = Cheetah.ImportHooks.CheetahDirOwner(ImportHooksTemplatesDir) + index_mod = cdo.getmod('index') + templates = os.listdir(ImportHooksTemplatesDir) + self.assertIn('index.py', templates) + self.assertNotIn('layout.py', templates) + + index_co = index_mod.__co__ + del index_mod.__co__ + self.assertRaises(ImportError, _exec, index_co, index_mod.__dict__) + + cdo.getmod('layout') # Compiled to layout.py and .pyc + self.assertIn('layout.py', os.listdir(ImportHooksTemplatesDir)) + + def test_ImportHooks(self): + templates = os.listdir(ImportHooksTemplatesDir) + self.assertNotIn('index.py', templates) + self.assertNotIn('layout.py', templates) + Cheetah.ImportHooks.install() + from index import index # noqa + templates = os.listdir(ImportHooksTemplatesDir) + self.assertIn('index.py', templates) + self.assertIn('layout.py', templates) + Cheetah.ImportHooks.uninstall() + + +if __name__ == '__main__': + unittest.main() diff --git a/Cheetah/Tests/ImportHooksTemplates/index.tmpl b/Cheetah/Tests/ImportHooksTemplates/index.tmpl new file mode 100644 index 0000000..9dd4ee3 --- /dev/null +++ b/Cheetah/Tests/ImportHooksTemplates/index.tmpl @@ -0,0 +1,5 @@ +#extends layout +#attr $title = 'Index' +#def body +

Index

+#end def diff --git a/Cheetah/Tests/ImportHooksTemplates/layout.tmpl b/Cheetah/Tests/ImportHooksTemplates/layout.tmpl new file mode 100644 index 0000000..d632430 --- /dev/null +++ b/Cheetah/Tests/ImportHooksTemplates/layout.tmpl @@ -0,0 +1,16 @@ +#attr $title = '' + + + + +$title + + + + + + +$body + + diff --git a/Cheetah/Tests/LoadTemplate.py b/Cheetah/Tests/LoadTemplate.py new file mode 100755 index 0000000..c656d8b --- /dev/null +++ b/Cheetah/Tests/LoadTemplate.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python + +import os +import unittest +import Cheetah.ImportHooks +from Cheetah.LoadTemplate import loadTemplateClass +from Cheetah.Tests.ImportHooks import ImportHooksTemplatesDir, _cleanup +from Cheetah.Tests.ImportHooks import setUpModule, tearDownModule # noqa + + +class LoadTemplateTest(unittest.TestCase): + def setUp(self): + _cleanup() + + def test_loadTemplate(self): + templates = os.listdir(ImportHooksTemplatesDir) + self.assertNotIn('index.py', templates) + self.assertNotIn('layout.py', templates) + + self.assertRaises(ImportError, loadTemplateClass, + os.path.join(ImportHooksTemplatesDir, 'index.tmpl')) + + templates = os.listdir(ImportHooksTemplatesDir) + self.assertIn('index.py', templates) + self.assertNotIn('layout.py', templates) + + loadTemplateClass( + os.path.join(ImportHooksTemplatesDir, 'layout.tmpl')) + + templates = os.listdir(ImportHooksTemplatesDir) + self.assertIn('index.py', templates) + self.assertIn('layout.py', templates) + + loadTemplateClass( + os.path.join(ImportHooksTemplatesDir, 'index.tmpl')) + + def test_ImportHooks(self): + templates = os.listdir(ImportHooksTemplatesDir) + self.assertNotIn('index.py', templates) + self.assertNotIn('layout.py', templates) + + Cheetah.ImportHooks.install() + loadTemplateClass( + os.path.join(ImportHooksTemplatesDir, 'index.tmpl')) + templates = os.listdir(ImportHooksTemplatesDir) + self.assertIn('index.py', templates) + self.assertIn('layout.py', templates) + Cheetah.ImportHooks.uninstall() + + +if __name__ == '__main__': + unittest.main() diff --git a/Cheetah/Tests/NameMapper.py b/Cheetah/Tests/NameMapper.py index 7a635ee..6066b6c 100755 --- a/Cheetah/Tests/NameMapper.py +++ b/Cheetah/Tests/NameMapper.py @@ -4,8 +4,8 @@ import sys import unittest from Cheetah.NameMapper import NotFound, \ - valueForName, valueFromSearchList, valueFromFrame, \ - valueFromFrameOrSearchList + valueForName, valueFromSearchList, valueFromFrame, \ + valueFromFrameOrSearchList class DummyClass(object): @@ -76,7 +76,7 @@ testNamespace = { 'none': None, 'emptyString': '', 'funcThatRaises': funcThatRaises, - } +} autoCallResults = {'aFunc': 'Scooby', 'aMeth': 'doo', diff --git a/Cheetah/Tests/NameMapper_pure.py b/Cheetah/Tests/NameMapper_pure.py index 2a26e3a..307882a 100755 --- a/Cheetah/Tests/NameMapper_pure.py +++ b/Cheetah/Tests/NameMapper_pure.py @@ -11,10 +11,7 @@ except ImportError: pass -def setUpModule(): - if 'Cheetah.NameMapper' in sys.modules: - del sys.modules['Cheetah.NameMapper'] - sys.modules['Cheetah._namemapper'] = None +def _setNameMapperFunctions(): from Cheetah.NameMapper import NotFound, \ valueForName, valueFromSearchList, valueFromFrame, \ valueFromFrameOrSearchList @@ -26,10 +23,18 @@ def setUpModule(): setattr(NameMapper, func.__name__, func) +def setUpModule(): + if 'Cheetah.NameMapper' in sys.modules: + del sys.modules['Cheetah.NameMapper'] + sys.modules['Cheetah._namemapper'] = None # emulate absence of the module + _setNameMapperFunctions() + + def tearDownModule(): del sys.modules['Cheetah.NameMapper'] del sys.modules['Cheetah._namemapper'] del sys.modules['Cheetah.Tests.NameMapper'] + _setNameMapperFunctions() # restore NameMapper class NameMapperTest(unittest.TestCase): diff --git a/Cheetah/Tests/Performance.py b/Cheetah/Tests/Performance.py index 25272f4..e07dcee 100755 --- a/Cheetah/Tests/Performance.py +++ b/Cheetah/Tests/Performance.py @@ -20,7 +20,7 @@ DEBUG = False # TOLERANCE in Pystones kPS = 1000 -TOLERANCE = 0.5*kPS +TOLERANCE = 0.5*kPS # noqa: E226 missing whitespace around operator class DurationError(AssertionError): diff --git a/Cheetah/Tests/Regressions.py b/Cheetah/Tests/Regressions.py index c38c113..b380e6d 100755 --- a/Cheetah/Tests/Regressions.py +++ b/Cheetah/Tests/Regressions.py @@ -24,7 +24,7 @@ class GetAttrTest(unittest.TestCase): o = CustomGetAttrClass() try: print(o.attr) - except GetAttrException as e: + except GetAttrException: # expected return except Exception as e: diff --git a/Cheetah/Tests/SyntaxAndOutput.py b/Cheetah/Tests/SyntaxAndOutput.py index dc14ec3..66b6825 100755 --- a/Cheetah/Tests/SyntaxAndOutput.py +++ b/Cheetah/Tests/SyntaxAndOutput.py @@ -99,12 +99,12 @@ defaultTestNameSpace = { 'list': [ {'index': 0, 'numOne': 1, 'numTwo': 2}, {'index': 1, 'numOne': 1, 'numTwo': 2}, - ], + ], 'nameList': [('john', 'doe'), ('jane', 'smith')], 'letterList': ['a', 'b', 'c'], '_': lambda x: 'Translated: ' + x, 'unicodeData': u'aoeu12345\u1234', - } +} ################################################## @@ -159,7 +159,7 @@ Template output mismatch: compilerSettings=self._getCompilerSettings(), keepRefToGeneratedCode=True, **extraKwArgs - ) + ) moduleCode = templateClass._CHEETAH_generatedModuleCode searchList = self.searchList() or self._searchList self.template = templateObj = templateClass(searchList=searchList) @@ -168,7 +168,7 @@ Template output mismatch: input, searchList=self.searchList(), compilerSettings=self._getCompilerSettings(), - ) + ) moduleCode = templateObj._CHEETAH_generatedModuleCode if self.DEBUGLEV >= 1: print("Module: %s" % templateObj.__module__) @@ -631,16 +631,16 @@ class Placeholders(OutputTest): assert str(tmpl({'names': names})).strip() == namesStr tmpl = tmpl.subclass('#for name in $names: $*name ') - assert str(tmpl({'names': names})) == 'You '*len(names) + assert str(tmpl({'names': names})) == 'You ' * len(names) tmpl = tmpl.subclass('#for name in $names: $*1*name ') - assert str(tmpl({'names': names})) == 'You '*len(names) + assert str(tmpl({'names': names})) == 'You ' * len(names) tmpl = tmpl.subclass('#for name in $names: $*1*(name) ') - assert str(tmpl({'names': names})) == 'You '*len(names) + assert str(tmpl({'names': names})) == 'You ' * len(names) tmpl = tmpl.subclass('#for name in $names: $*1*(name) ') - assert str(tmpl(names=names)) == 'You '*len(names) + assert str(tmpl(names=names)) == 'You ' * len(names) class Placeholders_Vals(OutputTest): @@ -1130,7 +1130,7 @@ $i#slurp $aStr#slurp #end def $foo$foo$foo$foo$foo""", - "1\n01234blarg"*5) + "1\n01234blarg"*5) # noqa: E226,E501 missing whitespace around operator def test5(self): r"""nested #cache blocks""" @@ -1148,7 +1148,7 @@ $*(6)#slurp $aStr#slurp #end def $foo$foo$foo$foo$foo""", - "1\n012346blarg"*5) + "1\n012346blarg"*5) # noqa: E226,E501 missing whitespace around operator def test6(self): r"""Make sure that partial directives don't match""" @@ -1652,8 +1652,8 @@ class ForDirective(OutputTest): def test15(self): """2 times single line #for""" - self.verify("#for $i in range($aFunc(5)): $i#slurp\n"*2, - "01234"*2) + self.verify("#for $i in range($aFunc(5)): $i#slurp\n"*2, # noqa: E226,E501 missing whitespace around operator + "01234"*2) # noqa: E226 missing whitespace around operator def test16(self): """false single line #for """ @@ -1700,8 +1700,8 @@ class RepeatDirective(OutputTest): """single-line #repeat""" self.verify("#repeat $numTwo: 1", "11") - self.verify("#repeat $numTwo: 1\n"*2, - "1\n1\n"*2) + self.verify("#repeat $numTwo: 1\n"*2, # noqa: E226,E501 missing whitespace around operator + "1\n1\n"*2) # noqa: E226,E501 missing whitespace around operator # false single-line self.verify("#repeat 3: \n1\n#end repeat", @@ -2434,7 +2434,7 @@ class UnlessDirective(OutputTest): """single-line #unless""" self.verify("#unless 1: 1234", "") self.verify("#unless 0: 1234", "1234") - self.verify("#unless 0: 1234\n"*2, "1234\n"*2) + self.verify("#unless 0: 1234\n"*2, "1234\n"*2) # noqa: E226,E501 missing whitespace around operator class PSP(OutputTest): @@ -2443,7 +2443,7 @@ class PSP(OutputTest): def test1(self): """simple <%= [int] %>""" - self.verify("<%= 1234 %>", "1234") + self.verify("<%= 1234 %>", "1234") def test2(self): """simple <%= [string] %>""" diff --git a/Cheetah/Tests/Template.py b/Cheetah/Tests/Template.py index 69461be..4316e6c 100755 --- a/Cheetah/Tests/Template.py +++ b/Cheetah/Tests/Template.py @@ -256,7 +256,7 @@ class Preprocessors(TemplateTest): 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] + 'This is a bit of text that needs translation\n'*2)[:-1] # noqa: E226,E501 missing whitespace around operator class TryExceptImportTest(TemplateTest): diff --git a/Cheetah/Tests/Test.py b/Cheetah/Tests/Test.py index 3464081..d1a07dd 100755 --- a/Cheetah/Tests/Test.py +++ b/Cheetah/Tests/Test.py @@ -14,33 +14,37 @@ TODO import sys import unittest -from Cheetah.Tests import SyntaxAndOutput +from Cheetah.Tests import Analyzer +from Cheetah.Tests import CheetahWrapper +# from Cheetah.Tests import Cheps +from Cheetah.Tests import Filters +from Cheetah.Tests import ImportHooks +from Cheetah.Tests import LoadTemplate +from Cheetah.Tests import Misc from Cheetah.Tests import NameMapper from Cheetah.Tests import NameMapper_pure -from Cheetah.Tests import Misc -from Cheetah.Tests import Filters -from Cheetah.Tests import Template -# from Cheetah.Tests import Cheps from Cheetah.Tests import Parser from Cheetah.Tests import Regressions +from Cheetah.Tests import SyntaxAndOutput +from Cheetah.Tests import Template from Cheetah.Tests import Unicode -from Cheetah.Tests import CheetahWrapper -from Cheetah.Tests import Analyzer SyntaxAndOutput.install_eols() suites = [ - unittest.findTestCases(SyntaxAndOutput), - unittest.findTestCases(NameMapper), - unittest.findTestCases(NameMapper_pure), - unittest.findTestCases(Filters), - unittest.findTestCases(Template), - # unittest.findTestCases(Cheps), - unittest.findTestCases(Regressions), - unittest.findTestCases(Unicode), - unittest.findTestCases(Misc), - unittest.findTestCases(Parser), - unittest.findTestCases(Analyzer), + unittest.findTestCases(Analyzer), + # unittest.findTestCases(Cheps), + unittest.findTestCases(Filters), + unittest.findTestCases(ImportHooks), + unittest.findTestCases(LoadTemplate), + unittest.findTestCases(Misc), + unittest.findTestCases(NameMapper), + unittest.findTestCases(Parser), + unittest.findTestCases(Regressions), + unittest.findTestCases(SyntaxAndOutput), + unittest.findTestCases(Template), + unittest.findTestCases(Unicode), + unittest.findTestCases(NameMapper_pure), ] if not sys.platform.startswith('java'): diff --git a/Cheetah/Tests/Unicode.py b/Cheetah/Tests/Unicode.py index c574195..77ade04 100755 --- a/Cheetah/Tests/Unicode.py +++ b/Cheetah/Tests/Unicode.py @@ -8,6 +8,7 @@ import sys from shutil import rmtree import tempfile import unittest +from Cheetah.Compiler import Compiler from Cheetah.Template import Template from Cheetah import CheetahWrapper from Cheetah.compat import PY2, unicode @@ -215,7 +216,7 @@ class Unicode_in_SearchList_Test(CommandLineTest): 'adjective': u'\u0e22\u0e34\u0e19\u0e14\u0e35\u0e15' u'\u0e49\u0e2d\u0e19\u0e23\u0e31\u0e1a' - }]) + }]) assert template.respond() def test_Thai_utf8(self): @@ -272,5 +273,16 @@ class InlineSpanishTest(unittest.TestCase): self.assertTrue(unicode(template)) +class CompilerTest(unittest.TestCase): + def test_compiler_str(self): + """ Test Compiler.__str__ """ + source = """#encoding utf-8 +#set $someUnicodeString = u"Bébé" +$someUnicodeString""" + compiler = Compiler(source) + self.assertIsInstance(str(compiler), str) + self.assertEqual(compiler.getModuleEncoding(), 'utf-8') + + if __name__ == '__main__': unittest.main() diff --git a/Cheetah/Tests/xmlrunner.py b/Cheetah/Tests/xmlrunner.py index 9668d8d..2748bb4 100644 --- a/Cheetah/Tests/xmlrunner.py +++ b/Cheetah/Tests/xmlrunner.py @@ -58,8 +58,8 @@ class _TestInfo(object): stream.write( ' <%s type="%s">%s\n' % (tagname, - issubclass(error[0], Exception) and - error[0].__name__ or str(error[0]), text)) + issubclass(error[0], Exception) + and error[0].__name__ or str(error[0]), text)) tb_stream = StringIO() traceback.print_tb(error[2], None, tb_stream) stream.write(escape(tb_stream.getvalue())) diff --git a/Cheetah/Tools/MondoReport.py b/Cheetah/Tools/MondoReport.py index bc7d476..e76de91 100644 --- a/Cheetah/Tools/MondoReport.py +++ b/Cheetah/Tools/MondoReport.py @@ -102,7 +102,7 @@ def mean(lis): def median(lis): lis = sorted(lis[:]) - return lis[int(len(lis)/2)] + return lis[int(len(lis)/2)] # noqa: E226,E501 missing whitespace around operator def variance(lis): @@ -320,9 +320,9 @@ class RecordStats(IndexFormats, ValuesGetterMixin): start = 1 else: start = 1 - end = start+size-1 + end = start + size - 1 try: - sequence[end+orphan-1] + sequence[end + orphan - 1] except Exception: end = len(sequence) # if l - end < orphan: end=l diff --git a/Cheetah/Tools/SiteHierarchy.py b/Cheetah/Tools/SiteHierarchy.py index a1c6f73..3416ca0 100644 --- a/Cheetah/Tools/SiteHierarchy.py +++ b/Cheetah/Tools/SiteHierarchy.py @@ -92,11 +92,11 @@ class Hierarchy: def menuLink(self, url, text, indent): if url == self._currentURL or self._prefix + url == self._currentURL: - return '%s%s
\n' % (' '*2*indent, + return '%s%s
\n' % (' ' * 2 * indent, self._menuCSSClass, text) else: return '%s%s
\n' % \ - (' '*2*indent, self._prefix, url, + (' '*2*indent, self._prefix, url, # noqa: E226,E501 missing whitespace around operator self._menuCSSClass, text) def crumbLink(self, url, text): @@ -128,7 +128,7 @@ class Hierarchy: stream.write(self.menuLink(url, text, indent)) if self._inContents(contents): for item in rest: - self._menubarRecurse(item, indent+1, stream) + self._menubarRecurse(item, indent + 1, stream) def _inContents(self, contents): if isinstance(contents, tuple): @@ -154,13 +154,13 @@ if __name__ == '__main__': ('/services/prices', 'Prices'), ], ('/contact', 'Contact Us'), - ] + ] for url in ['/', '/services', '/services/products/widget', '/contact']: - print('

', '='*50) + print('

', '='*50) # noqa: E226 missing whitespace around operator print('
%s:
\n' % url) n = Hierarchy(hierarchy, url, menuCSSClass='menu', crumbCSSClass='crumb', prefix='/here') print(n.menuList()) - print('

', '-'*50) + print('

', '-'*50) # noqa: E226 missing whitespace around operator print(n.crumbs()) diff --git a/Cheetah/Tools/turbocheetah/cheetahsupport.py b/Cheetah/Tools/turbocheetah/cheetahsupport.py index b7e77c3..6510896 100644 --- a/Cheetah/Tools/turbocheetah/cheetahsupport.py +++ b/Cheetah/Tools/turbocheetah/cheetahsupport.py @@ -66,7 +66,7 @@ class TurboCheetah: divider = classname.rfind(".") if divider > -1: package = classname[0:divider] - basename = classname[divider+1:] + basename = classname[divider+1:] # noqa: E226,E501 missing whitespace around operator else: raise ValueError("All templates must be in a package") diff --git a/Cheetah/Tools/turbocheetah/tests/test_template.py b/Cheetah/Tools/turbocheetah/tests/test_template.py index 045e5f9..50847c5 100644 --- a/Cheetah/Tools/turbocheetah/tests/test_template.py +++ b/Cheetah/Tools/turbocheetah/tests/test_template.py @@ -6,7 +6,7 @@ here = os.path.dirname(__file__) values = { 'v': 'VV', 'one': 1, - } +} def test_normal(): diff --git a/Cheetah/Utils/WebInputMixin.py b/Cheetah/Utils/WebInputMixin.py index 12af587..9c06c08 100644 --- a/Cheetah/Utils/WebInputMixin.py +++ b/Cheetah/Utils/WebInputMixin.py @@ -39,7 +39,7 @@ def _lookup(name, func, multi, converters): colon = name.find(':') if colon != -1: longName = name - shortName, ext = name[:colon], name[colon+1:] + shortName, ext = name[:colon], name[colon+1:] # noqa: E226,E501 missing whitespace around operator else: longName = shortName = name ext = '' diff --git a/Cheetah/Utils/statprof.py b/Cheetah/Utils/statprof.py index d26896c..b0f97dc 100644 --- a/Cheetah/Utils/statprof.py +++ b/Cheetah/Utils/statprof.py @@ -163,10 +163,10 @@ class ProfileState(object): self.sample_count = 0 # a float if frequency: - self.sample_interval = 1.0/frequency + self.sample_interval = 1.0 / frequency elif not hasattr(self, 'sample_interval'): # default to 100 Hz - self.sample_interval = 1.0/100.0 + self.sample_interval = 1.0 / 100.0 else: # leave the frequency as it was pass diff --git a/Cheetah/Version.py b/Cheetah/Version.py index 01c6e1b..3ba1a4f 100644 --- a/Cheetah/Version.py +++ b/Cheetah/Version.py @@ -1,5 +1,5 @@ -Version = '3.1.0' -VersionTuple = (3, 1, 0, 'final', 1) +Version = '3.2.0' +VersionTuple = (3, 2, 0, 'final', 0) MinCompatibleVersion = '3.0.0a1' MinCompatibleVersionTuple = (3, 0, 0, 'alpha', 1) @@ -29,7 +29,7 @@ def convertVersionStringToTuple(s): versionNum += [0] releaseTypeSubNum = int(releaseTypeSubNum) - return tuple(versionNum+[releaseType, releaseTypeSubNum]) + return tuple(versionNum + [releaseType, releaseTypeSubNum]) if __name__ == '__main__': diff --git a/Cheetah3.egg-info/PKG-INFO b/Cheetah3.egg-info/PKG-INFO index 9028fc1..5552c9b 100644 --- a/Cheetah3.egg-info/PKG-INFO +++ b/Cheetah3.egg-info/PKG-INFO @@ -1,13 +1,20 @@ -Metadata-Version: 1.1 +Metadata-Version: 2.1 Name: Cheetah3 -Version: 3.1.0 +Version: 3.2.0 Summary: Cheetah is a template engine and code generation tool Home-page: http://cheetahtemplate.org/ -Author: Oleg Broytman -Author-email: phd@phdru.name +Author: Tavis Rudd +Author-email: tavis@damnsimple.com +Maintainer: Oleg Broytman +Maintainer-email: phd@phdru.name License: MIT -Download-URL: https://pypi.python.org/pypi/Cheetah3/3.1.0 -Description-Content-Type: UNKNOWN +Download-URL: https://pypi.org/project/Cheetah3/3.2.0 +Project-URL: Wikipedia, https://en.wikipedia.org/wiki/CheetahTemplate +Project-URL: Documentation, http://cheetahtemplate.org/users_guide/index.html +Project-URL: Github repo, https://github.com/CheetahTemplate3 +Project-URL: Issue tracker, https://github.com/CheetahTemplate3/cheetah3/issues +Project-URL: Download, https://pypi.org/project/Cheetah3/3.2.0/ +Project-URL: Homepage, http://cheetahtemplate.org/ Description: Cheetah3 is a free (BSD-style) and open source template engine and code generation tool. @@ -47,10 +54,10 @@ Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 Classifier: Topic :: Internet :: WWW/HTTP Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content Classifier: Topic :: Internet :: WWW/HTTP :: Site Management @@ -58,3 +65,5 @@ Classifier: Topic :: Software Development :: Code Generators Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Topic :: Software Development :: User Interfaces Classifier: Topic :: Text Processing +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* +Description-Content-Type: text/x-rst diff --git a/Cheetah3.egg-info/SOURCES.txt b/Cheetah3.egg-info/SOURCES.txt index daacb8a..33f0fde 100644 --- a/Cheetah3.egg-info/SOURCES.txt +++ b/Cheetah3.egg-info/SOURCES.txt @@ -23,6 +23,7 @@ Cheetah/FileUtils.py Cheetah/Filters.py Cheetah/ImportHooks.py Cheetah/ImportManager.py +Cheetah/LoadTemplate.py Cheetah/NameMapper.py Cheetah/Parser.py Cheetah/Servlet.py @@ -46,6 +47,8 @@ Cheetah/Tests/Boinker.py Cheetah/Tests/CheetahWrapper.py Cheetah/Tests/Cheps.py Cheetah/Tests/Filters.py +Cheetah/Tests/ImportHooks.py +Cheetah/Tests/LoadTemplate.py Cheetah/Tests/Misc.py Cheetah/Tests/NameMapper.py Cheetah/Tests/NameMapper_pure.py @@ -59,6 +62,8 @@ Cheetah/Tests/Test.py Cheetah/Tests/Unicode.py Cheetah/Tests/__init__.py Cheetah/Tests/xmlrunner.py +Cheetah/Tests/ImportHooksTemplates/index.tmpl +Cheetah/Tests/ImportHooksTemplates/layout.tmpl Cheetah/Tools/CGITemplate.py Cheetah/Tools/MondoReport.py Cheetah/Tools/MondoReportDoc.txt @@ -168,295 +173,24 @@ docs/api/modules.rst docs/cheps/1_chep.rst docs/cheps/2_import.rst docs/cheps/3_super.rst -docs/dev_guide/bnf.rst docs/dev_guide/cache.rst docs/dev_guide/comments.rst -docs/dev_guide/compiler.rst docs/dev_guide/design.rst docs/dev_guide/errorHandling.rst -docs/dev_guide/files.rst docs/dev_guide/flowControl.rst docs/dev_guide/history.rst docs/dev_guide/index.rst docs/dev_guide/inheritanceEtc.rst docs/dev_guide/introduction.rst docs/dev_guide/output.rst -docs/dev_guide/parser.rst docs/dev_guide/parserInstructions.rst docs/dev_guide/patching.rst docs/dev_guide/placeholders.rst docs/dev_guide/pyModules.rst docs/dev_guide/safeDelegation.rst -docs/dev_guide/template.rst -docs/html/authors.html -docs/html/chep.html -docs/html/developers.html -docs/html/documentation.html -docs/html/download.html -docs/html/genindex.html -docs/html/index.html -docs/html/news.html -docs/html/news2.html -docs/html/py-modindex.html -docs/html/roadmap.html -docs/html/search.html -docs/html/searchindex.js -docs/html/_sources/authors.rst.txt -docs/html/_sources/chep.rst.txt -docs/html/_sources/developers.rst.txt -docs/html/_sources/documentation.rst.txt -docs/html/_sources/download.rst.txt -docs/html/_sources/index.rst.txt -docs/html/_sources/news.rst.txt -docs/html/_sources/news2.rst.txt -docs/html/_sources/roadmap.rst.txt -docs/html/_sources/api/Cheetah.CacheRegion.rst.txt -docs/html/_sources/api/Cheetah.CacheStore.rst.txt -docs/html/_sources/api/Cheetah.CheetahWrapper.rst.txt -docs/html/_sources/api/Cheetah.Compiler.rst.txt -docs/html/_sources/api/Cheetah.DirectiveAnalyzer.rst.txt -docs/html/_sources/api/Cheetah.Django.rst.txt -docs/html/_sources/api/Cheetah.DummyTransaction.rst.txt -docs/html/_sources/api/Cheetah.ErrorCatchers.rst.txt -docs/html/_sources/api/Cheetah.FileUtils.rst.txt -docs/html/_sources/api/Cheetah.Filters.rst.txt -docs/html/_sources/api/Cheetah.ImportHooks.rst.txt -docs/html/_sources/api/Cheetah.ImportManager.rst.txt -docs/html/_sources/api/Cheetah.Macros.I18n.rst.txt -docs/html/_sources/api/Cheetah.Macros.rst.txt -docs/html/_sources/api/Cheetah.NameMapper.rst.txt -docs/html/_sources/api/Cheetah.Parser.rst.txt -docs/html/_sources/api/Cheetah.Servlet.rst.txt -docs/html/_sources/api/Cheetah.SettingsManager.rst.txt -docs/html/_sources/api/Cheetah.SourceReader.rst.txt -docs/html/_sources/api/Cheetah.Template.rst.txt -docs/html/_sources/api/Cheetah.TemplateCmdLineIface.rst.txt -docs/html/_sources/api/Cheetah.Templates.SkeletonPage.rst.txt -docs/html/_sources/api/Cheetah.Templates.rst.txt -docs/html/_sources/api/Cheetah.Tests.Analyzer.rst.txt -docs/html/_sources/api/Cheetah.Tests.Boinker.rst.txt -docs/html/_sources/api/Cheetah.Tests.CheetahWrapper.rst.txt -docs/html/_sources/api/Cheetah.Tests.Cheps.rst.txt -docs/html/_sources/api/Cheetah.Tests.Filters.rst.txt -docs/html/_sources/api/Cheetah.Tests.Misc.rst.txt -docs/html/_sources/api/Cheetah.Tests.NameMapper.rst.txt -docs/html/_sources/api/Cheetah.Tests.NameMapper_pure.rst.txt -docs/html/_sources/api/Cheetah.Tests.Parser.rst.txt -docs/html/_sources/api/Cheetah.Tests.Performance.rst.txt -docs/html/_sources/api/Cheetah.Tests.Pinger.rst.txt -docs/html/_sources/api/Cheetah.Tests.Regressions.rst.txt -docs/html/_sources/api/Cheetah.Tests.SyntaxAndOutput.rst.txt -docs/html/_sources/api/Cheetah.Tests.Template.rst.txt -docs/html/_sources/api/Cheetah.Tests.Test.rst.txt -docs/html/_sources/api/Cheetah.Tests.Unicode.rst.txt -docs/html/_sources/api/Cheetah.Tests.rst.txt -docs/html/_sources/api/Cheetah.Tests.xmlrunner.rst.txt -docs/html/_sources/api/Cheetah.Tools.CGITemplate.rst.txt -docs/html/_sources/api/Cheetah.Tools.MondoReport.rst.txt -docs/html/_sources/api/Cheetah.Tools.RecursiveNull.rst.txt -docs/html/_sources/api/Cheetah.Tools.SiteHierarchy.rst.txt -docs/html/_sources/api/Cheetah.Tools.rst.txt -docs/html/_sources/api/Cheetah.Tools.turbocheetah.cheetahsupport.rst.txt -docs/html/_sources/api/Cheetah.Tools.turbocheetah.rst.txt -docs/html/_sources/api/Cheetah.Tools.turbocheetah.tests.rst.txt -docs/html/_sources/api/Cheetah.Tools.turbocheetah.tests.test_template.rst.txt -docs/html/_sources/api/Cheetah.Unspecified.rst.txt -docs/html/_sources/api/Cheetah.Utils.Indenter.rst.txt -docs/html/_sources/api/Cheetah.Utils.Misc.rst.txt -docs/html/_sources/api/Cheetah.Utils.WebInputMixin.rst.txt -docs/html/_sources/api/Cheetah.Utils.htmlDecode.rst.txt -docs/html/_sources/api/Cheetah.Utils.htmlEncode.rst.txt -docs/html/_sources/api/Cheetah.Utils.rst.txt -docs/html/_sources/api/Cheetah.Utils.statprof.rst.txt -docs/html/_sources/api/Cheetah.Version.rst.txt -docs/html/_sources/api/Cheetah.compat.rst.txt -docs/html/_sources/api/Cheetah.convertTmplPathToModuleName.rst.txt -docs/html/_sources/api/Cheetah.rst.txt -docs/html/_sources/api/modules.rst.txt -docs/html/_sources/cheps/1_chep.rst.txt -docs/html/_sources/cheps/2_import.rst.txt -docs/html/_sources/cheps/3_super.rst.txt -docs/html/_sources/dev_guide/bnf.rst.txt -docs/html/_sources/dev_guide/cache.rst.txt -docs/html/_sources/dev_guide/comments.rst.txt -docs/html/_sources/dev_guide/compiler.rst.txt -docs/html/_sources/dev_guide/design.rst.txt -docs/html/_sources/dev_guide/errorHandling.rst.txt -docs/html/_sources/dev_guide/files.rst.txt -docs/html/_sources/dev_guide/flowControl.rst.txt -docs/html/_sources/dev_guide/history.rst.txt -docs/html/_sources/dev_guide/index.rst.txt -docs/html/_sources/dev_guide/inheritanceEtc.rst.txt -docs/html/_sources/dev_guide/introduction.rst.txt -docs/html/_sources/dev_guide/output.rst.txt -docs/html/_sources/dev_guide/parser.rst.txt -docs/html/_sources/dev_guide/parserInstructions.rst.txt -docs/html/_sources/dev_guide/patching.rst.txt -docs/html/_sources/dev_guide/placeholders.rst.txt -docs/html/_sources/dev_guide/pyModules.rst.txt -docs/html/_sources/dev_guide/safeDelegation.rst.txt -docs/html/_sources/dev_guide/template.rst.txt -docs/html/_sources/recipes/inheritance.rst.txt -docs/html/_sources/recipes/precompiled.rst.txt -docs/html/_sources/recipes/staticmethod.rst.txt -docs/html/_sources/recipes/writing_a_recipe.rst.txt -docs/html/_sources/users_guide/comments.rst.txt -docs/html/_sources/users_guide/comparisons.rst.txt -docs/html/_sources/users_guide/editors.rst.txt -docs/html/_sources/users_guide/errorHandling.rst.txt -docs/html/_sources/users_guide/examples.rst.txt -docs/html/_sources/users_guide/flowControl.rst.txt -docs/html/_sources/users_guide/gettingStarted.rst.txt -docs/html/_sources/users_guide/glossary.rst.txt -docs/html/_sources/users_guide/index.rst.txt -docs/html/_sources/users_guide/inheritanceEtc.rst.txt -docs/html/_sources/users_guide/intro.rst.txt -docs/html/_sources/users_guide/language.rst.txt -docs/html/_sources/users_guide/libraries.rst.txt -docs/html/_sources/users_guide/links.rst.txt -docs/html/_sources/users_guide/nonHtml.rst.txt -docs/html/_sources/users_guide/otherHtml.rst.txt -docs/html/_sources/users_guide/output.rst.txt -docs/html/_sources/users_guide/parserInstructions.rst.txt -docs/html/_sources/users_guide/tipsAndTricks.rst.txt -docs/html/_sources/users_guide/webware.rst.txt -docs/html/_static/ajax-loader.gif -docs/html/_static/basic.css -docs/html/_static/comment-bright.png -docs/html/_static/comment-close.png -docs/html/_static/comment.png -docs/html/_static/contents.png -docs/html/_static/doctools.js -docs/html/_static/down-pressed.png -docs/html/_static/down.png -docs/html/_static/file.png -docs/html/_static/jquery-3.1.0.js -docs/html/_static/jquery.js -docs/html/_static/minus.png -docs/html/_static/navigation.png -docs/html/_static/plus.png -docs/html/_static/pygments.css -docs/html/_static/searchtools.js -docs/html/_static/sphinxdoc.css -docs/html/_static/underscore-1.3.1.js -docs/html/_static/underscore.js -docs/html/_static/up-pressed.png -docs/html/_static/up.png -docs/html/_static/websupport.js -docs/html/api/Cheetah.CacheRegion.html -docs/html/api/Cheetah.CacheStore.html -docs/html/api/Cheetah.CheetahWrapper.html -docs/html/api/Cheetah.Compiler.html -docs/html/api/Cheetah.DirectiveAnalyzer.html -docs/html/api/Cheetah.Django.html -docs/html/api/Cheetah.DummyTransaction.html -docs/html/api/Cheetah.ErrorCatchers.html -docs/html/api/Cheetah.FileUtils.html -docs/html/api/Cheetah.Filters.html -docs/html/api/Cheetah.ImportHooks.html -docs/html/api/Cheetah.ImportManager.html -docs/html/api/Cheetah.Macros.I18n.html -docs/html/api/Cheetah.Macros.html -docs/html/api/Cheetah.NameMapper.html -docs/html/api/Cheetah.Parser.html -docs/html/api/Cheetah.Servlet.html -docs/html/api/Cheetah.SettingsManager.html -docs/html/api/Cheetah.SourceReader.html -docs/html/api/Cheetah.Template.html -docs/html/api/Cheetah.TemplateCmdLineIface.html -docs/html/api/Cheetah.Templates.SkeletonPage.html -docs/html/api/Cheetah.Templates.html -docs/html/api/Cheetah.Tests.Analyzer.html -docs/html/api/Cheetah.Tests.Boinker.html -docs/html/api/Cheetah.Tests.CheetahWrapper.html -docs/html/api/Cheetah.Tests.Cheps.html -docs/html/api/Cheetah.Tests.Filters.html -docs/html/api/Cheetah.Tests.Misc.html -docs/html/api/Cheetah.Tests.NameMapper.html -docs/html/api/Cheetah.Tests.NameMapper_pure.html -docs/html/api/Cheetah.Tests.Parser.html -docs/html/api/Cheetah.Tests.Performance.html -docs/html/api/Cheetah.Tests.Pinger.html -docs/html/api/Cheetah.Tests.Regressions.html -docs/html/api/Cheetah.Tests.SyntaxAndOutput.html -docs/html/api/Cheetah.Tests.Template.html -docs/html/api/Cheetah.Tests.Test.html -docs/html/api/Cheetah.Tests.Unicode.html -docs/html/api/Cheetah.Tests.html -docs/html/api/Cheetah.Tests.xmlrunner.html -docs/html/api/Cheetah.Tools.CGITemplate.html -docs/html/api/Cheetah.Tools.MondoReport.html -docs/html/api/Cheetah.Tools.RecursiveNull.html -docs/html/api/Cheetah.Tools.SiteHierarchy.html -docs/html/api/Cheetah.Tools.html -docs/html/api/Cheetah.Tools.turbocheetah.cheetahsupport.html -docs/html/api/Cheetah.Tools.turbocheetah.html -docs/html/api/Cheetah.Tools.turbocheetah.tests.html -docs/html/api/Cheetah.Tools.turbocheetah.tests.test_template.html -docs/html/api/Cheetah.Unspecified.html -docs/html/api/Cheetah.Utils.Indenter.html -docs/html/api/Cheetah.Utils.Misc.html -docs/html/api/Cheetah.Utils.WebInputMixin.html -docs/html/api/Cheetah.Utils.html -docs/html/api/Cheetah.Utils.htmlDecode.html -docs/html/api/Cheetah.Utils.htmlEncode.html -docs/html/api/Cheetah.Utils.statprof.html -docs/html/api/Cheetah.Version.html -docs/html/api/Cheetah.compat.html -docs/html/api/Cheetah.convertTmplPathToModuleName.html -docs/html/api/Cheetah.html -docs/html/api/modules.html -docs/html/cheps/1_chep.html -docs/html/cheps/2_import.html -docs/html/cheps/3_super.html -docs/html/dev_guide/bnf.html -docs/html/dev_guide/cache.html -docs/html/dev_guide/comments.html -docs/html/dev_guide/compiler.html -docs/html/dev_guide/design.html -docs/html/dev_guide/errorHandling.html -docs/html/dev_guide/files.html -docs/html/dev_guide/flowControl.html -docs/html/dev_guide/history.html -docs/html/dev_guide/index.html -docs/html/dev_guide/inheritanceEtc.html -docs/html/dev_guide/introduction.html -docs/html/dev_guide/output.html -docs/html/dev_guide/parser.html -docs/html/dev_guide/parserInstructions.html -docs/html/dev_guide/patching.html -docs/html/dev_guide/placeholders.html -docs/html/dev_guide/pyModules.html -docs/html/dev_guide/safeDelegation.html -docs/html/dev_guide/template.html -docs/html/recipes/inheritance.html -docs/html/recipes/precompiled.html -docs/html/recipes/staticmethod.html -docs/html/recipes/writing_a_recipe.html -docs/html/users_guide/comments.html -docs/html/users_guide/comparisons.html -docs/html/users_guide/editors.html -docs/html/users_guide/errorHandling.html -docs/html/users_guide/examples.html -docs/html/users_guide/flowControl.html -docs/html/users_guide/gettingStarted.html -docs/html/users_guide/glossary.html -docs/html/users_guide/index.html -docs/html/users_guide/inheritanceEtc.html -docs/html/users_guide/intro.html -docs/html/users_guide/language.html -docs/html/users_guide/libraries.html -docs/html/users_guide/links.html -docs/html/users_guide/nonHtml.html -docs/html/users_guide/otherHtml.html -docs/html/users_guide/output.html -docs/html/users_guide/parserInstructions.html -docs/html/users_guide/tipsAndTricks.html -docs/html/users_guide/webware.html docs/recipes/inheritance.rst docs/recipes/precompiled.rst docs/recipes/staticmethod.rst -docs/recipes/writing_a_recipe.rst docs/users_guide/comments.rst docs/users_guide/comparisons.rst docs/users_guide/editors.rst diff --git a/LICENSE b/LICENSE index 6c4141a..da29eb3 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright 2017, Oleg Broytman and contributors. +Copyright 2017-2018, Oleg Broytman and contributors. Copyright 2009-2012, R. Tyler Croy and contributors. Copyright 2001-2008, The Cheetah Development Team: Tavis Rudd, Mike Orr, Chuck Esterbrook, Ian Bicking. diff --git a/PKG-INFO b/PKG-INFO index 9028fc1..5552c9b 100644 --- a/PKG-INFO +++ b/PKG-INFO @@ -1,13 +1,20 @@ -Metadata-Version: 1.1 +Metadata-Version: 2.1 Name: Cheetah3 -Version: 3.1.0 +Version: 3.2.0 Summary: Cheetah is a template engine and code generation tool Home-page: http://cheetahtemplate.org/ -Author: Oleg Broytman -Author-email: phd@phdru.name +Author: Tavis Rudd +Author-email: tavis@damnsimple.com +Maintainer: Oleg Broytman +Maintainer-email: phd@phdru.name License: MIT -Download-URL: https://pypi.python.org/pypi/Cheetah3/3.1.0 -Description-Content-Type: UNKNOWN +Download-URL: https://pypi.org/project/Cheetah3/3.2.0 +Project-URL: Wikipedia, https://en.wikipedia.org/wiki/CheetahTemplate +Project-URL: Documentation, http://cheetahtemplate.org/users_guide/index.html +Project-URL: Github repo, https://github.com/CheetahTemplate3 +Project-URL: Issue tracker, https://github.com/CheetahTemplate3/cheetah3/issues +Project-URL: Download, https://pypi.org/project/Cheetah3/3.2.0/ +Project-URL: Homepage, http://cheetahtemplate.org/ Description: Cheetah3 is a free (BSD-style) and open source template engine and code generation tool. @@ -47,10 +54,10 @@ Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 Classifier: Topic :: Internet :: WWW/HTTP Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content Classifier: Topic :: Internet :: WWW/HTTP :: Site Management @@ -58,3 +65,5 @@ Classifier: Topic :: Software Development :: Code Generators Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Topic :: Software Development :: User Interfaces Classifier: Topic :: Text Processing +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* +Description-Content-Type: text/x-rst diff --git a/README.rst b/README.rst index e58d79e..07d616a 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,4 @@ -Cheetah Template 3.1.0 +Cheetah Template 3.2.0 ====================== Cheetah3 is a free (BSD-style) and open source template engine and code diff --git a/SetupConfig.py b/SetupConfig.py index 3410fb3..157ad11 100644 --- a/SetupConfig.py +++ b/SetupConfig.py @@ -1,5 +1,5 @@ # -------Main Package Settings-----------# -from distutils.core import Extension +from setuptools import Extension import os import os.path import sys @@ -18,8 +18,17 @@ maintainer = "Oleg Broytman" maintainer_email = "phd@phdru.name" url = "http://cheetahtemplate.org/" dev_tag = "" -download_url = "https://pypi.python.org/pypi/%s/%s%s" \ +download_url = "https://pypi.org/project/%s/%s%s" \ % (name, version, dev_tag) +project_urls = { + 'Homepage': 'http://cheetahtemplate.org/', + 'Documentation': 'http://cheetahtemplate.org/users_guide/index.html', + 'Download': 'https://pypi.org/project/%s/%s%s/' + % (name, version, dev_tag), + 'Github repo': 'https://github.com/CheetahTemplate3', + 'Issue tracker': 'https://github.com/CheetahTemplate3/cheetah3/issues', + 'Wikipedia': 'https://en.wikipedia.org/wiki/CheetahTemplate', +} del dev_tag keywords = ["template"] platforms = "Any" @@ -42,10 +51,10 @@ classifiers = [line.strip() for line in '''\ Programming Language :: Python :: 2 Programming Language :: Python :: 2.7 Programming Language :: Python :: 3 - Programming Language :: Python :: 3.3 Programming Language :: Python :: 3.4 Programming Language :: Python :: 3.5 Programming Language :: Python :: 3.6 + Programming Language :: Python :: 3.7 Topic :: Internet :: WWW/HTTP Topic :: Internet :: WWW/HTTP :: Dynamic Content Topic :: Internet :: WWW/HTTP :: Site Management @@ -59,15 +68,15 @@ if PY2: del PY2 # Hide it from setup() 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')]), - ] + 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', @@ -77,20 +86,19 @@ scripts = ('bin/cheetah-compile', data_files = ['recursive: Cheetah *.tmpl *.txt *.rst LICENSE README.rst TODO'] -if not os.getenv('CHEETAH_INSTALL_WITHOUT_SETUPTOOLS'): - try: - if sys.platform == 'win32': - # use 'entry_points' instead of 'scripts' - del scripts - entry_points = { - 'console_scripts': [ - 'cheetah = Cheetah.CheetahWrapper:_cheetah', - 'cheetah-compile = ' - 'Cheetah.CheetahWrapper:_cheetah_compile', - ] - } - except ImportError: - pass +try: + if sys.platform == 'win32': + # use 'entry_points' instead of 'scripts' + del scripts + entry_points = { + 'console_scripts': [ + 'cheetah = Cheetah.CheetahWrapper:_cheetah', + 'cheetah-compile = ' + 'Cheetah.CheetahWrapper:_cheetah_compile', + ] + } +except ImportError: + pass long_description = '''\ Cheetah3 is a free (BSD-style) and open source template engine and code @@ -119,3 +127,7 @@ Recent Changes See http://cheetahtemplate.org/news.html for full details ''' + +long_description_content_type = "text/x-rst" + +python_requires = '>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*' diff --git a/SetupTools.py b/SetupTools.py index 470198e..1d89680 100644 --- a/SetupTools.py +++ b/SetupTools.py @@ -3,22 +3,16 @@ import os import os.path import sys -from distutils.command.build_ext import build_ext from distutils.command.install_data import install_data -from distutils.core import setup from distutils.errors import CCompilerError, DistutilsExecError, \ DistutilsPlatformError +from setuptools import setup +from setuptools.command.build_ext import build_ext # imports from Cheetah ... from Cheetah.FileUtils import findFiles from Cheetah.compat import string_type -if not os.getenv('CHEETAH_INSTALL_WITHOUT_SETUPTOOLS'): - try: - from setuptools import setup # noqa: F811 - except ImportError: - pass - if sys.platform == 'win32': # 2.6's distutils.msvc9compiler can raise an IOError when failing to # find the compiler @@ -36,7 +30,7 @@ class BuildFailed(Exception): class mod_build_ext(build_ext): - """A modified version of the distutils build_ext command that raises an + """A modified version of build_ext command that raises an exception when building of the extension fails. """ @@ -118,7 +112,7 @@ class mod_install_data(install_data): def run_setup(configurations): - """Run distutils setup. + """Run distutils/setuptools setup. The parameters passed to setup() are extracted from the list of modules, classes or instances given in configurations. @@ -145,11 +139,10 @@ def run_setup(configurations): cmdclasses = { 'build_ext': mod_build_ext, 'install_data': mod_install_data, - } + } kws['cmdclass'] = cmdclasses - # Invoke distutils setup try: setup(**kws) except BuildFailed as x: diff --git a/TODO b/TODO index d8a63fc..09d2181 100644 --- a/TODO +++ b/TODO @@ -1,7 +1,7 @@ -- https://pypi.python.org/pypi/cibuildwheel or +- https://pypi.org/project/cibuildwheel/ or https://github.com/matthew-brett/multibuild or - https://pypi.python.org/pypi/wheelhouse-uploader + https://pypi.org/project/wheelhouse-uploader/ -- https://pypi.python.org/pypi/appveyor-artifacts +- https://pypi.org/project/appveyor-artifacts/ - Support PyPy3. diff --git a/docs/conf.py b/docs/conf.py index c9fdf71..2437be8 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -29,7 +29,7 @@ sys.path.insert(0, os.path.abspath('..')) # or your custom ones. extensions = [ 'sphinx.ext.autodoc', - ] +] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -45,7 +45,7 @@ master_doc = 'index' # General information about the project. project = u'Cheetah3' -copyright = u'2017, Oleg Broytman; 2009-2012, R. Tyler Croy; ' \ +copyright = u'2017-2018, Oleg Broytman; 2009-2012, R. Tyler Croy; ' \ u'2001-2008, The Cheetah Development Team.' # The version info for the project you're documenting, acts as replacement for @@ -181,9 +181,9 @@ htmlhelp_basename = 'CheetahTemplateEnginedoc' # (source start file, target name, title, # author, documentclass [howto/manual]). latex_documents = [ - ('index', 'CheetahTemplateEngine.tex', - u'Cheetah Template Engine Documentation', - u'R. Tyler Ballance', 'manual'), + ('index', 'CheetahTemplateEngine.tex', + u'Cheetah Template Engine Documentation', + u'R. Tyler Ballance', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of diff --git a/docs/dev_guide/bnf.rst b/docs/dev_guide/bnf.rst deleted file mode 100644 index ef214b4..0000000 --- a/docs/dev_guide/bnf.rst +++ /dev/null @@ -1,6 +0,0 @@ -A BNF Grammar of Cheetah -======================== - -(bnf) - - diff --git a/docs/dev_guide/cache.rst b/docs/dev_guide/cache.rst index ce0829c..18014c5 100644 --- a/docs/dev_guide/cache.rst +++ b/docs/dev_guide/cache.rst @@ -1,12 +1,10 @@ Caching placeholders and #cache =============================== -(cache) Dynamic placeholder - no cache ------------------------------ -(cache.dynamic) The template: @@ -34,7 +32,6 @@ Just what we expected, like any other dynamic placeholder. Static placeholder ------------------ -(cache.static) The template: @@ -105,7 +102,6 @@ into the cache. Timed-refresh placeholder ------------------------- -(cache.timed) The template: @@ -192,7 +188,6 @@ can you figure that out. Timed-refresh placeholder with braces ------------------------------------- -(cache.timed.braces) This example is the same but with the long placeholder syntax. It's here because it's a Cheetah FAQ whether to put the cache interval @@ -239,7 +234,6 @@ text. #cache ------ -(cache.directive) The template: @@ -286,7 +280,6 @@ text around the placeholder is inside the second if-block. #cache with timer and id ------------------------ -(cache.directive.timer) The template: @@ -319,7 +312,6 @@ first if-block: #cache with test: expression and method conditions -------------------------------------------------- -(cache.directive.test) The template: @@ -329,7 +321,6 @@ The template: This is a cached region. $voom #end cache -(Analysis postponed: bug in Cheetah produces invalid Python.) The template: diff --git a/docs/dev_guide/comments.rst b/docs/dev_guide/comments.rst index c2f9a89..51e285b 100644 --- a/docs/dev_guide/comments.rst +++ b/docs/dev_guide/comments.rst @@ -1,7 +1,6 @@ Directives: Comments ==================== -(comments) The template: @@ -38,7 +37,6 @@ The generated code: Docstring and header comments ----------------------------- -(comments.docstring) The template: diff --git a/docs/dev_guide/compiler.rst b/docs/dev_guide/compiler.rst deleted file mode 100644 index 33f3bcd..0000000 --- a/docs/dev_guide/compiler.rst +++ /dev/null @@ -1,8 +0,0 @@ -The compiler -============ - -(compiler) - -How templates are compiled: a walk through Compiler.py. - - diff --git a/docs/dev_guide/design.rst b/docs/dev_guide/design.rst index 1ffabbd..e144a46 100644 --- a/docs/dev_guide/design.rst +++ b/docs/dev_guide/design.rst @@ -1,12 +1,10 @@ Design Decisions and Tradeoffs ============================== -(design) Delimiters ---------- -(design.Delimiters) One of the first decisions we encountered was which delimiter syntax to use. We decided to follow Velocity's {$placeholder} and @@ -41,7 +39,6 @@ disappearing as bogus HTML tags do in browsers. Late binding ------------ -(design.lateBinding) One of Cheetah's unique features is the name mapper, which lets you write {$a.b} without worrying much about the type of {a} or {b}. @@ -89,16 +86,13 @@ goals are unattainable due to performance considerations. Caching framework ----------------- -(design.cache) Webware compatibility and the transaction framework --------------------------------------------------- -(design.webware) Single inheritance ------------------ -(design.singleInheritance) diff --git a/docs/dev_guide/errorHandling.rst b/docs/dev_guide/errorHandling.rst index e97d1fb..6768203 100644 --- a/docs/dev_guide/errorHandling.rst +++ b/docs/dev_guide/errorHandling.rst @@ -1,12 +1,10 @@ Directives: Error Handling ========================== -(errorHandling) #try and #raise --------------- -(errorHandling.try) The template: @@ -67,7 +65,6 @@ The generated code: #assert ------- -(errorHandling.assert) The template: @@ -101,12 +98,10 @@ The generated code: #errorCatcher ------------- -(errorHandling.errorCatcher) No error catcher ~~~~~~~~~~~~~~~~ -(errorHandling.errorCatcher.no) The template: @@ -143,7 +138,6 @@ The generated code: Echo and BigEcho ~~~~~~~~~~~~~~~~ -(errorHandling.errorCatcher.echo) The template: @@ -184,7 +178,6 @@ The generated code: ListErrors ~~~~~~~~~~ -(errorHandling.errorCatcher.listErrors) The template: diff --git a/docs/dev_guide/files.rst b/docs/dev_guide/files.rst deleted file mode 100644 index ab8d7a1..0000000 --- a/docs/dev_guide/files.rst +++ /dev/null @@ -1,11 +0,0 @@ -Files -===== - -(files) - -This chapter will be an overview of the files in the Cheetah -package, and how they interrelate in compiling and filling a -template. We'll also look at files in the Cheetah tarball that -don't get copied into the package. - - diff --git a/docs/dev_guide/flowControl.rst b/docs/dev_guide/flowControl.rst index d391b2f..06e5366 100644 --- a/docs/dev_guide/flowControl.rst +++ b/docs/dev_guide/flowControl.rst @@ -1,12 +1,10 @@ Directives: Flow Control ======================== -(flowControl) #for ---- -(flowControl.for) The template: @@ -33,7 +31,6 @@ The generated code: #repeat ------- -(flowControl.repeat) The template: @@ -53,7 +50,6 @@ The output: My bonnie lies over the ocean O, bring back my bonnie to me! -(OK, so the second line should be "sea" instead of "ocean".) The generated code: @@ -69,7 +65,6 @@ for each instance of {repeat} in order to permit nesting. #while ------ -(flowControl.while) The template: @@ -135,7 +130,6 @@ The generated code: #unless ------- -(flowControl.unless) The template: @@ -167,7 +161,6 @@ calculating something different than it should. #break and #continue -------------------- -(flowControl.break) The template: @@ -206,7 +199,6 @@ The generated code: #pass ----- -(flowControl.pass) The template: @@ -247,7 +239,6 @@ The generated code: #stop ----- -(flowControl.stop) The template: @@ -285,7 +276,6 @@ The generated code: #return ------- -(flowControl.return) The template: diff --git a/docs/dev_guide/history.rst b/docs/dev_guide/history.rst index d0e1ceb..ca42d83 100644 --- a/docs/dev_guide/history.rst +++ b/docs/dev_guide/history.rst @@ -1,7 +1,6 @@ History of Cheetah ================== -(history) In Spring 2001, several members of the webware-discuss mailing list expressed the need for a template engine. Webware like Python is diff --git a/docs/dev_guide/index.rst b/docs/dev_guide/index.rst index 83ff7d9..4a289bd 100644 --- a/docs/dev_guide/index.rst +++ b/docs/dev_guide/index.rst @@ -9,8 +9,6 @@ This guide needs to really be filled out more :maxdepth: 1 introduction.rst - compiler.rst - parser.rst errorHandling.rst placeholders.rst patching.rst @@ -19,12 +17,9 @@ This guide needs to really be filled out more safeDelegation.rst history.rst output.rst - files.rst cache.rst - bnf.rst pyModules.rst comments.rst parserInstructions.rst - template.rst inheritanceEtc.rst diff --git a/docs/dev_guide/inheritanceEtc.rst b/docs/dev_guide/inheritanceEtc.rst index 0b06ab9..1d89f46 100644 --- a/docs/dev_guide/inheritanceEtc.rst +++ b/docs/dev_guide/inheritanceEtc.rst @@ -1,12 +1,10 @@ Directives: Import, Inheritance, Declaration and Assignment =========================================================== -(inheritanceEtc) #import and #from ----------------- -(inheritanceEtc.import) The template: @@ -25,7 +23,6 @@ The generated module, at the bottom of the import section: #extends -------- -(inheritanceEtc.extends) The template: @@ -49,7 +46,6 @@ The generated class: #implements ----------- -(inheritanceEtc.implements) The template: @@ -67,7 +63,6 @@ In the generated class, the main method is {.doOutput} instead of #set and #set global -------------------- -(inheritanceEtc.set) The template: @@ -104,7 +99,6 @@ very first namespace.) #del ---- -(inheritanceEtc.del) The template: @@ -129,7 +123,6 @@ In the generated class: #attr ----- -(inheritanceEtc.attr) The template: @@ -148,7 +141,6 @@ In the generated class: #def ---- -(inheritanceEtc.def) The template: @@ -219,7 +211,6 @@ default values. #block ------ -(inheritanceEtc.block) The template: diff --git a/docs/dev_guide/output.rst b/docs/dev_guide/output.rst index 55172d1..2e945f8 100644 --- a/docs/dev_guide/output.rst +++ b/docs/dev_guide/output.rst @@ -1,12 +1,10 @@ Directives: Output ================== -(output) #echo ----- -(output.echo) The template: @@ -31,7 +29,6 @@ The generated code: #silent ------- -(output.silent) The template: @@ -59,7 +56,6 @@ but it almost succeeds. #raw ---- -(output.raw) The template: @@ -96,7 +92,6 @@ a separate {write} call. #include -------- -(output.include) The main template: @@ -127,7 +122,6 @@ The generated code: #include raw ~~~~~~~~~~~~ -(output.include.raw) The main template: @@ -154,7 +148,6 @@ That last argument, {raw}, makes the difference. #include from a string or expression (eval) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -(output.include.expression) The template: @@ -192,7 +185,6 @@ Later in the generated class: #slurp ------ -(output.slurp) The template: @@ -235,7 +227,6 @@ in the template definition. #filter ------- -(output.filter) The template: diff --git a/docs/dev_guide/parser.rst b/docs/dev_guide/parser.rst deleted file mode 100644 index 802b43f..0000000 --- a/docs/dev_guide/parser.rst +++ /dev/null @@ -1,9 +0,0 @@ -The parser -========== - -(parser) - -How templates are compiled: a walk through Parser.py's source. -(Also need to look at Lexer.py, but not too closely.) - - diff --git a/docs/dev_guide/parserInstructions.rst b/docs/dev_guide/parserInstructions.rst index 805df7c..af9e4aa 100644 --- a/docs/dev_guide/parserInstructions.rst +++ b/docs/dev_guide/parserInstructions.rst @@ -1,12 +1,10 @@ Directives: Parser Instructions =============================== -(parserInstructions) #breakpoint ----------- -(parserInstructions.breakpoint) The template: @@ -34,7 +32,6 @@ Nothing after the breakpoint was compiled. #compiler --------- -(parserInstructions.compiler) The template: diff --git a/docs/dev_guide/patching.rst b/docs/dev_guide/patching.rst index 095d9a2..4d7441a 100644 --- a/docs/dev_guide/patching.rst +++ b/docs/dev_guide/patching.rst @@ -1,7 +1,6 @@ Patching Cheetah ================ -(patching) How to commit changes to CVS or submit patches, how to run the test suite. Describe distutils and how the regression tests work. @@ -9,7 +8,6 @@ suite. Describe distutils and how the regression tests work. File Requirements ----------------- -(patching.fileRequirements) The code{Template} class contains not only the Cheetah infrastructure, but also some convenience methods useful in all @@ -37,7 +35,6 @@ imported that subsystem). Testing Changes and Building Regression Tests --------------------------------------------- -(patching.testing) Cheetah ships with a regression test suite. To run the built-in tests, execute at the shell prompt: diff --git a/docs/dev_guide/placeholders.rst b/docs/dev_guide/placeholders.rst index 60aa0d2..fa306db 100644 --- a/docs/dev_guide/placeholders.rst +++ b/docs/dev_guide/placeholders.rst @@ -1,12 +1,10 @@ Placeholders ============ -(placeholders) Simple placeholders ------------------- -(placeholders.simple) Let's add a few $placeholders to our template: @@ -181,7 +179,6 @@ outputs for true {and} expressions.) Complex placeholders -------------------- -(placeholders.complex) Placeholders can get far more complicated than that. This example shows what kind of code the various NameMapper features produce. diff --git a/docs/dev_guide/pyModules.rst b/docs/dev_guide/pyModules.rst index 86c95dc..64bdcee 100644 --- a/docs/dev_guide/pyModules.rst +++ b/docs/dev_guide/pyModules.rst @@ -1,7 +1,6 @@ .py Template Modules ==================== -(pyModules) This chapter examines the structure of a .py template module. The following few chapters will then show how each placeholder and @@ -10,7 +9,6 @@ directive affects the generated Python code. An example ---------- -(pyModules.example) Our first template follows a long noble tradition in computer tutorials. It produces a familiar, friendly greeting. Here's the @@ -170,7 +168,6 @@ The examples were generated from CVS versions of Cheetah between A walk through the example -------------------------- -(pyModules.walk) Lines 20-24 are the Cheetah-specific imports. Line 33 introduces our generated class, {x}, a subclass of {Template}. It's called x diff --git a/docs/dev_guide/safeDelegation.rst b/docs/dev_guide/safeDelegation.rst index 87f3dc1..03609e9 100644 --- a/docs/dev_guide/safeDelegation.rst +++ b/docs/dev_guide/safeDelegation.rst @@ -1,7 +1,6 @@ Safe Delegation =============== -(safeDelegation) Safe delegation, as provided by Zope and Allaire's Spectra, is not implemented in Cheetah. The core aim has been to help developers diff --git a/docs/dev_guide/template.rst b/docs/dev_guide/template.rst deleted file mode 100644 index 8dd23d9..0000000 --- a/docs/dev_guide/template.rst +++ /dev/null @@ -1,11 +0,0 @@ -Template -======== - -(template) - -This chapter will mainly walk through the {Cheetah.Template} -constructor and not at what point the template is compiled. - -(Also need to look at Transaction,py and Servlet.py.) - - diff --git a/docs/documentation.rst b/docs/documentation.rst index af5cc44..835389d 100644 --- a/docs/documentation.rst +++ b/docs/documentation.rst @@ -7,4 +7,3 @@ Cheetah Recipes recipes/inheritance.rst recipes/precompiled.rst recipes/staticmethod.rst - recipes/writing_a_recipe.rst diff --git a/docs/download.rst b/docs/download.rst index dc73d33..8c318d7 100644 --- a/docs/download.rst +++ b/docs/download.rst @@ -2,7 +2,7 @@ Downloading Cheetah =================== You can download wheels, eggs and tarballs of Cheetah from the `Python -Package Index `_. +Package Index `_. You can keep up to date with release candidates or other downloads of Cheetah by visiting the `CheetahTemplate GitHub page diff --git a/docs/html/_sources/api/Cheetah.CacheRegion.rst.txt b/docs/html/_sources/api/Cheetah.CacheRegion.rst.txt deleted file mode 100644 index f9d3643..0000000 --- a/docs/html/_sources/api/Cheetah.CacheRegion.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.CacheRegion module -=========================== - -.. automodule:: Cheetah.CacheRegion - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.CacheStore.rst.txt b/docs/html/_sources/api/Cheetah.CacheStore.rst.txt deleted file mode 100644 index dd3acce..0000000 --- a/docs/html/_sources/api/Cheetah.CacheStore.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.CacheStore module -========================== - -.. automodule:: Cheetah.CacheStore - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.CheetahWrapper.rst.txt b/docs/html/_sources/api/Cheetah.CheetahWrapper.rst.txt deleted file mode 100644 index 437699b..0000000 --- a/docs/html/_sources/api/Cheetah.CheetahWrapper.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.CheetahWrapper module -============================== - -.. automodule:: Cheetah.CheetahWrapper - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Compiler.rst.txt b/docs/html/_sources/api/Cheetah.Compiler.rst.txt deleted file mode 100644 index 88adbb5..0000000 --- a/docs/html/_sources/api/Cheetah.Compiler.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Compiler module -======================== - -.. automodule:: Cheetah.Compiler - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.DirectiveAnalyzer.rst.txt b/docs/html/_sources/api/Cheetah.DirectiveAnalyzer.rst.txt deleted file mode 100644 index c8a6c9c..0000000 --- a/docs/html/_sources/api/Cheetah.DirectiveAnalyzer.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.DirectiveAnalyzer module -================================= - -.. automodule:: Cheetah.DirectiveAnalyzer - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Django.rst.txt b/docs/html/_sources/api/Cheetah.Django.rst.txt deleted file mode 100644 index 861e95a..0000000 --- a/docs/html/_sources/api/Cheetah.Django.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Django module -====================== - -.. automodule:: Cheetah.Django - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.DummyTransaction.rst.txt b/docs/html/_sources/api/Cheetah.DummyTransaction.rst.txt deleted file mode 100644 index 193d5eb..0000000 --- a/docs/html/_sources/api/Cheetah.DummyTransaction.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.DummyTransaction module -================================ - -.. automodule:: Cheetah.DummyTransaction - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.ErrorCatchers.rst.txt b/docs/html/_sources/api/Cheetah.ErrorCatchers.rst.txt deleted file mode 100644 index 1fb9140..0000000 --- a/docs/html/_sources/api/Cheetah.ErrorCatchers.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.ErrorCatchers module -============================= - -.. automodule:: Cheetah.ErrorCatchers - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.FileUtils.rst.txt b/docs/html/_sources/api/Cheetah.FileUtils.rst.txt deleted file mode 100644 index 3302322..0000000 --- a/docs/html/_sources/api/Cheetah.FileUtils.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.FileUtils module -========================= - -.. automodule:: Cheetah.FileUtils - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Filters.rst.txt b/docs/html/_sources/api/Cheetah.Filters.rst.txt deleted file mode 100644 index 5612700..0000000 --- a/docs/html/_sources/api/Cheetah.Filters.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Filters module -======================= - -.. automodule:: Cheetah.Filters - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.ImportHooks.rst.txt b/docs/html/_sources/api/Cheetah.ImportHooks.rst.txt deleted file mode 100644 index 0217927..0000000 --- a/docs/html/_sources/api/Cheetah.ImportHooks.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.ImportHooks module -=========================== - -.. automodule:: Cheetah.ImportHooks - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.ImportManager.rst.txt b/docs/html/_sources/api/Cheetah.ImportManager.rst.txt deleted file mode 100644 index 7200c3d..0000000 --- a/docs/html/_sources/api/Cheetah.ImportManager.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.ImportManager module -============================= - -.. automodule:: Cheetah.ImportManager - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Macros.I18n.rst.txt b/docs/html/_sources/api/Cheetah.Macros.I18n.rst.txt deleted file mode 100644 index 338726b..0000000 --- a/docs/html/_sources/api/Cheetah.Macros.I18n.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Macros\.I18n module -============================ - -.. automodule:: Cheetah.Macros.I18n - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Macros.rst.txt b/docs/html/_sources/api/Cheetah.Macros.rst.txt deleted file mode 100644 index 1cf8052..0000000 --- a/docs/html/_sources/api/Cheetah.Macros.rst.txt +++ /dev/null @@ -1,15 +0,0 @@ -Cheetah\.Macros package -======================= - -.. automodule:: Cheetah.Macros - :members: - :undoc-members: - :show-inheritance: - -Submodules ----------- - -.. toctree:: - - Cheetah.Macros.I18n - diff --git a/docs/html/_sources/api/Cheetah.NameMapper.rst.txt b/docs/html/_sources/api/Cheetah.NameMapper.rst.txt deleted file mode 100644 index d995359..0000000 --- a/docs/html/_sources/api/Cheetah.NameMapper.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.NameMapper module -========================== - -.. automodule:: Cheetah.NameMapper - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Parser.rst.txt b/docs/html/_sources/api/Cheetah.Parser.rst.txt deleted file mode 100644 index f459b45..0000000 --- a/docs/html/_sources/api/Cheetah.Parser.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Parser module -====================== - -.. automodule:: Cheetah.Parser - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Servlet.rst.txt b/docs/html/_sources/api/Cheetah.Servlet.rst.txt deleted file mode 100644 index ca3cc39..0000000 --- a/docs/html/_sources/api/Cheetah.Servlet.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Servlet module -======================= - -.. automodule:: Cheetah.Servlet - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.SettingsManager.rst.txt b/docs/html/_sources/api/Cheetah.SettingsManager.rst.txt deleted file mode 100644 index d067e6c..0000000 --- a/docs/html/_sources/api/Cheetah.SettingsManager.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.SettingsManager module -=============================== - -.. automodule:: Cheetah.SettingsManager - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.SourceReader.rst.txt b/docs/html/_sources/api/Cheetah.SourceReader.rst.txt deleted file mode 100644 index 5e3d318..0000000 --- a/docs/html/_sources/api/Cheetah.SourceReader.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.SourceReader module -============================ - -.. automodule:: Cheetah.SourceReader - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Template.rst.txt b/docs/html/_sources/api/Cheetah.Template.rst.txt deleted file mode 100644 index 0eb6c21..0000000 --- a/docs/html/_sources/api/Cheetah.Template.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Template module -======================== - -.. automodule:: Cheetah.Template - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.TemplateCmdLineIface.rst.txt b/docs/html/_sources/api/Cheetah.TemplateCmdLineIface.rst.txt deleted file mode 100644 index 9eb13f9..0000000 --- a/docs/html/_sources/api/Cheetah.TemplateCmdLineIface.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.TemplateCmdLineIface module -==================================== - -.. automodule:: Cheetah.TemplateCmdLineIface - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Templates.SkeletonPage.rst.txt b/docs/html/_sources/api/Cheetah.Templates.SkeletonPage.rst.txt deleted file mode 100644 index 1689faa..0000000 --- a/docs/html/_sources/api/Cheetah.Templates.SkeletonPage.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Templates\.SkeletonPage module -======================================= - -.. automodule:: Cheetah.Templates.SkeletonPage - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Templates.rst.txt b/docs/html/_sources/api/Cheetah.Templates.rst.txt deleted file mode 100644 index a1cab72..0000000 --- a/docs/html/_sources/api/Cheetah.Templates.rst.txt +++ /dev/null @@ -1,15 +0,0 @@ -Cheetah\.Templates package -========================== - -.. automodule:: Cheetah.Templates - :members: - :undoc-members: - :show-inheritance: - -Submodules ----------- - -.. toctree:: - - Cheetah.Templates.SkeletonPage - diff --git a/docs/html/_sources/api/Cheetah.Tests.Analyzer.rst.txt b/docs/html/_sources/api/Cheetah.Tests.Analyzer.rst.txt deleted file mode 100644 index 674b25e..0000000 --- a/docs/html/_sources/api/Cheetah.Tests.Analyzer.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Tests\.Analyzer module -=============================== - -.. automodule:: Cheetah.Tests.Analyzer - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Tests.Boinker.rst.txt b/docs/html/_sources/api/Cheetah.Tests.Boinker.rst.txt deleted file mode 100644 index dfaee8b..0000000 --- a/docs/html/_sources/api/Cheetah.Tests.Boinker.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Tests\.Boinker module -============================== - -.. automodule:: Cheetah.Tests.Boinker - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Tests.CheetahWrapper.rst.txt b/docs/html/_sources/api/Cheetah.Tests.CheetahWrapper.rst.txt deleted file mode 100644 index 66dadcf..0000000 --- a/docs/html/_sources/api/Cheetah.Tests.CheetahWrapper.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Tests\.CheetahWrapper module -===================================== - -.. automodule:: Cheetah.Tests.CheetahWrapper - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Tests.Cheps.rst.txt b/docs/html/_sources/api/Cheetah.Tests.Cheps.rst.txt deleted file mode 100644 index a7bcacc..0000000 --- a/docs/html/_sources/api/Cheetah.Tests.Cheps.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Tests\.Cheps module -============================ - -.. automodule:: Cheetah.Tests.Cheps - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Tests.Filters.rst.txt b/docs/html/_sources/api/Cheetah.Tests.Filters.rst.txt deleted file mode 100644 index 8d97947..0000000 --- a/docs/html/_sources/api/Cheetah.Tests.Filters.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Tests\.Filters module -============================== - -.. automodule:: Cheetah.Tests.Filters - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Tests.Misc.rst.txt b/docs/html/_sources/api/Cheetah.Tests.Misc.rst.txt deleted file mode 100644 index ec9133b..0000000 --- a/docs/html/_sources/api/Cheetah.Tests.Misc.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Tests\.Misc module -=========================== - -.. automodule:: Cheetah.Tests.Misc - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Tests.NameMapper.rst.txt b/docs/html/_sources/api/Cheetah.Tests.NameMapper.rst.txt deleted file mode 100644 index fb76c2a..0000000 --- a/docs/html/_sources/api/Cheetah.Tests.NameMapper.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Tests\.NameMapper module -================================= - -.. automodule:: Cheetah.Tests.NameMapper - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Tests.NameMapper_pure.rst.txt b/docs/html/_sources/api/Cheetah.Tests.NameMapper_pure.rst.txt deleted file mode 100644 index 927661f..0000000 --- a/docs/html/_sources/api/Cheetah.Tests.NameMapper_pure.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Tests\.NameMapper\_pure module -======================================= - -.. automodule:: Cheetah.Tests.NameMapper_pure - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Tests.Parser.rst.txt b/docs/html/_sources/api/Cheetah.Tests.Parser.rst.txt deleted file mode 100644 index dd1bc7f..0000000 --- a/docs/html/_sources/api/Cheetah.Tests.Parser.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Tests\.Parser module -============================= - -.. automodule:: Cheetah.Tests.Parser - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Tests.Performance.rst.txt b/docs/html/_sources/api/Cheetah.Tests.Performance.rst.txt deleted file mode 100644 index a2ebf49..0000000 --- a/docs/html/_sources/api/Cheetah.Tests.Performance.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Tests\.Performance module -================================== - -.. automodule:: Cheetah.Tests.Performance - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Tests.Pinger.rst.txt b/docs/html/_sources/api/Cheetah.Tests.Pinger.rst.txt deleted file mode 100644 index a714077..0000000 --- a/docs/html/_sources/api/Cheetah.Tests.Pinger.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Tests\.Pinger module -============================= - -.. automodule:: Cheetah.Tests.Pinger - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Tests.Regressions.rst.txt b/docs/html/_sources/api/Cheetah.Tests.Regressions.rst.txt deleted file mode 100644 index 249e4b6..0000000 --- a/docs/html/_sources/api/Cheetah.Tests.Regressions.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Tests\.Regressions module -================================== - -.. automodule:: Cheetah.Tests.Regressions - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Tests.SyntaxAndOutput.rst.txt b/docs/html/_sources/api/Cheetah.Tests.SyntaxAndOutput.rst.txt deleted file mode 100644 index 5b2fbab..0000000 --- a/docs/html/_sources/api/Cheetah.Tests.SyntaxAndOutput.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Tests\.SyntaxAndOutput module -====================================== - -.. automodule:: Cheetah.Tests.SyntaxAndOutput - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Tests.Template.rst.txt b/docs/html/_sources/api/Cheetah.Tests.Template.rst.txt deleted file mode 100644 index eb24526..0000000 --- a/docs/html/_sources/api/Cheetah.Tests.Template.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Tests\.Template module -=============================== - -.. automodule:: Cheetah.Tests.Template - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Tests.Test.rst.txt b/docs/html/_sources/api/Cheetah.Tests.Test.rst.txt deleted file mode 100644 index 23d5291..0000000 --- a/docs/html/_sources/api/Cheetah.Tests.Test.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Tests\.Test module -=========================== - -.. automodule:: Cheetah.Tests.Test - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Tests.Unicode.rst.txt b/docs/html/_sources/api/Cheetah.Tests.Unicode.rst.txt deleted file mode 100644 index f3ee955..0000000 --- a/docs/html/_sources/api/Cheetah.Tests.Unicode.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Tests\.Unicode module -============================== - -.. automodule:: Cheetah.Tests.Unicode - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Tests.rst.txt b/docs/html/_sources/api/Cheetah.Tests.rst.txt deleted file mode 100644 index 8d6c879..0000000 --- a/docs/html/_sources/api/Cheetah.Tests.rst.txt +++ /dev/null @@ -1,31 +0,0 @@ -Cheetah\.Tests package -====================== - -.. automodule:: Cheetah.Tests - :members: - :undoc-members: - :show-inheritance: - -Submodules ----------- - -.. toctree:: - - Cheetah.Tests.Analyzer - Cheetah.Tests.Boinker - Cheetah.Tests.CheetahWrapper - Cheetah.Tests.Cheps - Cheetah.Tests.Filters - Cheetah.Tests.Misc - Cheetah.Tests.NameMapper - Cheetah.Tests.NameMapper_pure - Cheetah.Tests.Parser - Cheetah.Tests.Performance - Cheetah.Tests.Pinger - Cheetah.Tests.Regressions - Cheetah.Tests.SyntaxAndOutput - Cheetah.Tests.Template - Cheetah.Tests.Test - Cheetah.Tests.Unicode - Cheetah.Tests.xmlrunner - diff --git a/docs/html/_sources/api/Cheetah.Tests.xmlrunner.rst.txt b/docs/html/_sources/api/Cheetah.Tests.xmlrunner.rst.txt deleted file mode 100644 index 23e34f4..0000000 --- a/docs/html/_sources/api/Cheetah.Tests.xmlrunner.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Tests\.xmlrunner module -================================ - -.. automodule:: Cheetah.Tests.xmlrunner - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Tools.CGITemplate.rst.txt b/docs/html/_sources/api/Cheetah.Tools.CGITemplate.rst.txt deleted file mode 100644 index 3e72776..0000000 --- a/docs/html/_sources/api/Cheetah.Tools.CGITemplate.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Tools\.CGITemplate module -================================== - -.. automodule:: Cheetah.Tools.CGITemplate - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Tools.MondoReport.rst.txt b/docs/html/_sources/api/Cheetah.Tools.MondoReport.rst.txt deleted file mode 100644 index e875ead..0000000 --- a/docs/html/_sources/api/Cheetah.Tools.MondoReport.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Tools\.MondoReport module -================================== - -.. automodule:: Cheetah.Tools.MondoReport - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Tools.RecursiveNull.rst.txt b/docs/html/_sources/api/Cheetah.Tools.RecursiveNull.rst.txt deleted file mode 100644 index eb5f72b..0000000 --- a/docs/html/_sources/api/Cheetah.Tools.RecursiveNull.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Tools\.RecursiveNull module -==================================== - -.. automodule:: Cheetah.Tools.RecursiveNull - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Tools.SiteHierarchy.rst.txt b/docs/html/_sources/api/Cheetah.Tools.SiteHierarchy.rst.txt deleted file mode 100644 index 9c8b983..0000000 --- a/docs/html/_sources/api/Cheetah.Tools.SiteHierarchy.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Tools\.SiteHierarchy module -==================================== - -.. automodule:: Cheetah.Tools.SiteHierarchy - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Tools.rst.txt b/docs/html/_sources/api/Cheetah.Tools.rst.txt deleted file mode 100644 index e5dd5a2..0000000 --- a/docs/html/_sources/api/Cheetah.Tools.rst.txt +++ /dev/null @@ -1,25 +0,0 @@ -Cheetah\.Tools package -====================== - -.. automodule:: Cheetah.Tools - :members: - :undoc-members: - :show-inheritance: - -Subpackages ------------ - -.. toctree:: - - Cheetah.Tools.turbocheetah - -Submodules ----------- - -.. toctree:: - - Cheetah.Tools.CGITemplate - Cheetah.Tools.MondoReport - Cheetah.Tools.RecursiveNull - Cheetah.Tools.SiteHierarchy - diff --git a/docs/html/_sources/api/Cheetah.Tools.turbocheetah.cheetahsupport.rst.txt b/docs/html/_sources/api/Cheetah.Tools.turbocheetah.cheetahsupport.rst.txt deleted file mode 100644 index c488cdd..0000000 --- a/docs/html/_sources/api/Cheetah.Tools.turbocheetah.cheetahsupport.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Tools\.turbocheetah\.cheetahsupport module -=================================================== - -.. automodule:: Cheetah.Tools.turbocheetah.cheetahsupport - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Tools.turbocheetah.rst.txt b/docs/html/_sources/api/Cheetah.Tools.turbocheetah.rst.txt deleted file mode 100644 index 6ea7430..0000000 --- a/docs/html/_sources/api/Cheetah.Tools.turbocheetah.rst.txt +++ /dev/null @@ -1,22 +0,0 @@ -Cheetah\.Tools\.turbocheetah package -==================================== - -.. automodule:: Cheetah.Tools.turbocheetah - :members: - :undoc-members: - :show-inheritance: - -Subpackages ------------ - -.. toctree:: - - Cheetah.Tools.turbocheetah.tests - -Submodules ----------- - -.. toctree:: - - Cheetah.Tools.turbocheetah.cheetahsupport - diff --git a/docs/html/_sources/api/Cheetah.Tools.turbocheetah.tests.rst.txt b/docs/html/_sources/api/Cheetah.Tools.turbocheetah.tests.rst.txt deleted file mode 100644 index a7b1e4e..0000000 --- a/docs/html/_sources/api/Cheetah.Tools.turbocheetah.tests.rst.txt +++ /dev/null @@ -1,15 +0,0 @@ -Cheetah\.Tools\.turbocheetah\.tests package -=========================================== - -.. automodule:: Cheetah.Tools.turbocheetah.tests - :members: - :undoc-members: - :show-inheritance: - -Submodules ----------- - -.. toctree:: - - Cheetah.Tools.turbocheetah.tests.test_template - diff --git a/docs/html/_sources/api/Cheetah.Tools.turbocheetah.tests.test_template.rst.txt b/docs/html/_sources/api/Cheetah.Tools.turbocheetah.tests.test_template.rst.txt deleted file mode 100644 index b04f2cf..0000000 --- a/docs/html/_sources/api/Cheetah.Tools.turbocheetah.tests.test_template.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Tools\.turbocheetah\.tests\.test\_template module -========================================================== - -.. automodule:: Cheetah.Tools.turbocheetah.tests.test_template - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Unspecified.rst.txt b/docs/html/_sources/api/Cheetah.Unspecified.rst.txt deleted file mode 100644 index 52fc6f7..0000000 --- a/docs/html/_sources/api/Cheetah.Unspecified.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Unspecified module -=========================== - -.. automodule:: Cheetah.Unspecified - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Utils.Indenter.rst.txt b/docs/html/_sources/api/Cheetah.Utils.Indenter.rst.txt deleted file mode 100644 index 74c8bd6..0000000 --- a/docs/html/_sources/api/Cheetah.Utils.Indenter.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Utils\.Indenter module -=============================== - -.. automodule:: Cheetah.Utils.Indenter - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Utils.Misc.rst.txt b/docs/html/_sources/api/Cheetah.Utils.Misc.rst.txt deleted file mode 100644 index 5baddfa..0000000 --- a/docs/html/_sources/api/Cheetah.Utils.Misc.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Utils\.Misc module -=========================== - -.. automodule:: Cheetah.Utils.Misc - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Utils.WebInputMixin.rst.txt b/docs/html/_sources/api/Cheetah.Utils.WebInputMixin.rst.txt deleted file mode 100644 index 3083ae3..0000000 --- a/docs/html/_sources/api/Cheetah.Utils.WebInputMixin.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Utils\.WebInputMixin module -==================================== - -.. automodule:: Cheetah.Utils.WebInputMixin - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Utils.htmlDecode.rst.txt b/docs/html/_sources/api/Cheetah.Utils.htmlDecode.rst.txt deleted file mode 100644 index dc09574..0000000 --- a/docs/html/_sources/api/Cheetah.Utils.htmlDecode.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Utils\.htmlDecode module -================================= - -.. automodule:: Cheetah.Utils.htmlDecode - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Utils.htmlEncode.rst.txt b/docs/html/_sources/api/Cheetah.Utils.htmlEncode.rst.txt deleted file mode 100644 index 4d8efa6..0000000 --- a/docs/html/_sources/api/Cheetah.Utils.htmlEncode.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Utils\.htmlEncode module -================================= - -.. automodule:: Cheetah.Utils.htmlEncode - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Utils.rst.txt b/docs/html/_sources/api/Cheetah.Utils.rst.txt deleted file mode 100644 index 54d238c..0000000 --- a/docs/html/_sources/api/Cheetah.Utils.rst.txt +++ /dev/null @@ -1,20 +0,0 @@ -Cheetah\.Utils package -====================== - -.. automodule:: Cheetah.Utils - :members: - :undoc-members: - :show-inheritance: - -Submodules ----------- - -.. toctree:: - - Cheetah.Utils.Indenter - Cheetah.Utils.Misc - Cheetah.Utils.WebInputMixin - Cheetah.Utils.htmlDecode - Cheetah.Utils.htmlEncode - Cheetah.Utils.statprof - diff --git a/docs/html/_sources/api/Cheetah.Utils.statprof.rst.txt b/docs/html/_sources/api/Cheetah.Utils.statprof.rst.txt deleted file mode 100644 index 30628cf..0000000 --- a/docs/html/_sources/api/Cheetah.Utils.statprof.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Utils\.statprof module -=============================== - -.. automodule:: Cheetah.Utils.statprof - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.Version.rst.txt b/docs/html/_sources/api/Cheetah.Version.rst.txt deleted file mode 100644 index 5560b29..0000000 --- a/docs/html/_sources/api/Cheetah.Version.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.Version module -======================= - -.. automodule:: Cheetah.Version - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.compat.rst.txt b/docs/html/_sources/api/Cheetah.compat.rst.txt deleted file mode 100644 index 58b262c..0000000 --- a/docs/html/_sources/api/Cheetah.compat.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.compat module -====================== - -.. automodule:: Cheetah.compat - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.convertTmplPathToModuleName.rst.txt b/docs/html/_sources/api/Cheetah.convertTmplPathToModuleName.rst.txt deleted file mode 100644 index f6efa39..0000000 --- a/docs/html/_sources/api/Cheetah.convertTmplPathToModuleName.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah\.convertTmplPathToModuleName module -=========================================== - -.. automodule:: Cheetah.convertTmplPathToModuleName - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/html/_sources/api/Cheetah.rst.txt b/docs/html/_sources/api/Cheetah.rst.txt deleted file mode 100644 index 1a39047..0000000 --- a/docs/html/_sources/api/Cheetah.rst.txt +++ /dev/null @@ -1,48 +0,0 @@ -Cheetah package -=============== - -.. automodule:: Cheetah - :members: - :undoc-members: - :show-inheritance: - -Subpackages ------------ - -.. toctree:: - - Cheetah.Macros - Cheetah.Templates - Cheetah.Tests - Cheetah.Tools - Cheetah.Utils - -Submodules ----------- - -.. toctree:: - - Cheetah.CacheRegion - Cheetah.CacheStore - Cheetah.CheetahWrapper - Cheetah.Compiler - Cheetah.DirectiveAnalyzer - Cheetah.Django - Cheetah.DummyTransaction - Cheetah.ErrorCatchers - Cheetah.FileUtils - Cheetah.Filters - Cheetah.ImportHooks - Cheetah.ImportManager - Cheetah.NameMapper - Cheetah.Parser - Cheetah.Servlet - Cheetah.SettingsManager - Cheetah.SourceReader - Cheetah.Template - Cheetah.TemplateCmdLineIface - Cheetah.Unspecified - Cheetah.Version - Cheetah.compat - Cheetah.convertTmplPathToModuleName - diff --git a/docs/html/_sources/api/modules.rst.txt b/docs/html/_sources/api/modules.rst.txt deleted file mode 100644 index 3aee30a..0000000 --- a/docs/html/_sources/api/modules.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -Cheetah -======= - -.. toctree:: - :maxdepth: 4 - - Cheetah diff --git a/docs/html/_sources/authors.rst.txt b/docs/html/_sources/authors.rst.txt deleted file mode 100644 index 9140385..0000000 --- a/docs/html/_sources/authors.rst.txt +++ /dev/null @@ -1,31 +0,0 @@ -Authors and contributors -======================== - -Cheetah was originally written by Tavis Rudd . - -Contributions have been made by: - -* Mike Orr -* Chuck Esterbrook -* Shannon JJ Behrens -* Ian Bicking -* \R. Tyler Croy -* James Abbatiello -* Jean-Baptiste Quenot -* Marc Abramowitz -* Mike Bonnet -* Doug Knight -* Jon Siddle -* Anwesha Das -* Arun Kumar -* Austin Haigh -* Darren Yin -* Evan Klitzke -* Kurt Schwehr -* Lakshmi Vyasarajan -* Mika Eloranta -* mikola -* Adam Karpierz -* Jonathan Ross Rogers -* Mathias Stearn -* Oleg Broytman diff --git a/docs/html/_sources/chep.rst.txt b/docs/html/_sources/chep.rst.txt deleted file mode 100644 index abe8d22..0000000 --- a/docs/html/_sources/chep.rst.txt +++ /dev/null @@ -1,17 +0,0 @@ -Cheetah Enhancement Proposals -============================= - -The concept of the **Cheetah Enhancement Proposal** is similar to the -`Python Enhancement Proposal `_ in that -they are used to outline the future development of Cheetah as both a -language and a framework. - -Existing CHEPs --------------- - -.. toctree:: - :maxdepth: 1 - - cheps/1_chep.rst - cheps/2_import.rst - cheps/3_super.rst diff --git a/docs/html/_sources/cheps/1_chep.rst.txt b/docs/html/_sources/cheps/1_chep.rst.txt deleted file mode 100644 index 0dae336..0000000 --- a/docs/html/_sources/cheps/1_chep.rst.txt +++ /dev/null @@ -1,26 +0,0 @@ -(#1) CHEP Purpose and Guidelines -================================= - - -:CHEP: 1 -:Title: CHEP Purpose and Guidelines -:Version: 1 -:Author: R Tyler Ballance -:Status: Active -:Type: Process -:Content-Type: text/x-rst -:Created: 07-Jun-2009 - ----- - -Abstract --------- -One can consider the basis for all CHEP documents to be -modeled after `PEP #1 `_, -for this reason you should refer to `PEP #1 `_ -for the true CHEP "purpose and guidelines" instead of them being -enumerated here (and duplicated). - -Copyright ---------- -This document has been placed in the public domain. diff --git a/docs/html/_sources/cheps/2_import.rst.txt b/docs/html/_sources/cheps/2_import.rst.txt deleted file mode 100644 index 25fc4b7..0000000 --- a/docs/html/_sources/cheps/2_import.rst.txt +++ /dev/null @@ -1,122 +0,0 @@ -(#2) Conditionalized #import behavior -===================================== - - -:CHEP: 2 -:Title: Conditionalized #import behavior -:Version: 1 -:Author: R Tyler Ballance -:Status: Draft -:Type: Standards Track -:Content-Type: text/x-rst -:Created: 07-Jun-2009 - ----- - -Abstract --------- -This CHEP proposes an update to the way the #import and #from -directives are handled such that locally scoped imports and -module-level imports are handled appropriately. - - -Motivation ----------- -Currently Cheetah (v2.2.1) provides two different, but mutually exclusive, -means of importing Python modules with the #from/#import directives. The -"traditional" handling for #from/#import (hereafter referred to as "module imports") -is that the generated import statements shall all be relocated to -the top of the generated module's source code, i.e. :: - - #import cjson - - Hello $cjson.encode([1, 2, 3]) - - -Will result in generated module code along the lines of:: - - import cjson - - class Foo(Template): - def writeBody(self): - write('Hello ') - write(cjson.encode([1, 2, 3])) - - -Also currently in Cheetah is the ability to switch off this -behavior and enable location specific #from/#import handling -(hereafter referred to as "function imports") in the generated -code, with this block of Cheetah for example:: - - #def aFunction(arg) - #try - #from hashlib import md5 - #except ImportError - #from md5 import md5 - #end try - #return $md5.new(arg).hexdigest() - #end def - -Will result in code generated with everything in -place such that the Python looks something like:: - - class Foo(Template): - def aFunction(self, arg): - try: - from hashlib import md5 - except ImportError: - from md5 import md5 - return md5.new(arg).hexdigest() - - -These two approaches to handling the #from/#import directives -are both beneficial for different situations but currently they -are handled in mutually exclusive code paths and in mutually -exclusive fashions. - -Specification -------------- -The change in #from/#import behavior and how these directives -are handled is all based on context of their use, making the -#from/#import handling "intelligent". For module imports, the -"traditional" handling of the #from/#import directives will -still apply. Whereas function imports will result in inline -generated import code. - -The basic premise of the change proposed by this document is -that all #from/#import directives contained within a #def/#end def -closure will result in import statements contained within that -function block whereas everywhere else the statements will be relocated -to the top of the generated module code (i.e. the module import) - - -Rationale ---------- -The concept of the "function import" was introduced in Cheetah v2.1.0 -and quickly retrofitted to "live" behind a compiler setting due to the -regressions with older templates or templates that were designed to utilize -module imports (through heavy #block/#end block use, etc). Through discussion -with Tavis Rudd, this middle ground between the two styles of importing was -concluded to be the most reasonable solution to providing "pythonic" import -functionality (i.e. "function import" also known as "inline imports") while -still providing the ability to have #from/#import directives declared at the -module scope within the template (within the Cheetah templates, markup and most -directives declared within the module scope are placed inside the default method). - - -Backwards Compatibility ------------------------ -Changes proposed in this document should be *mostly* backwards -compatible with current versions of Cheetah, Any unforeseen issues -could arise from the use of #from/#import inside of a function -expecting those symbols to be available outside of the function -that they're declared in. - - -Reference Implementation ------------------------- -*still in development* - -Copyright ---------- -This document has been placed in the public domain. diff --git a/docs/html/_sources/cheps/3_super.rst.txt b/docs/html/_sources/cheps/3_super.rst.txt deleted file mode 100644 index 71f15f3..0000000 --- a/docs/html/_sources/cheps/3_super.rst.txt +++ /dev/null @@ -1,36 +0,0 @@ -(#3) Exposing of super() and self via Template searchList -========================================================= - - -:CHEP: 3 -:Title: Exposing of super() and self via Template searchList -:Version: 1 -:Author: R Tyler Ballance -:Status: Draft -:Type: Standards Track -:Content-Type: text/x-rst -:Created: 07-Jun-2009 - ----- - -Abstract --------- - -Specification -------------- - -Motivation ----------- - -Rationale ---------- - -Backwards Compatibility ------------------------ - -Reference Implementation ------------------------- - -Copyright ---------- -This document has been placed in the public domain. diff --git a/docs/html/_sources/dev_guide/bnf.rst.txt b/docs/html/_sources/dev_guide/bnf.rst.txt deleted file mode 100644 index ef214b4..0000000 --- a/docs/html/_sources/dev_guide/bnf.rst.txt +++ /dev/null @@ -1,6 +0,0 @@ -A BNF Grammar of Cheetah -======================== - -(bnf) - - diff --git a/docs/html/_sources/dev_guide/cache.rst.txt b/docs/html/_sources/dev_guide/cache.rst.txt deleted file mode 100644 index ce0829c..0000000 --- a/docs/html/_sources/dev_guide/cache.rst.txt +++ /dev/null @@ -1,404 +0,0 @@ -Caching placeholders and #cache -=============================== - -(cache) - -Dynamic placeholder - no cache ------------------------------- - -(cache.dynamic) - -The template: - -:: - - Dynamic variable: $voom - -The command line and the output: - -:: - - % voom='Voom!' python x.py --env - Dynamic variable: Voom! - -The generated code: - -:: - - write('Dynamic variable: ') - write(filter(VFS(SL,"voom",1))) # generated from '$voom' at line 1, col 20. - write('\n') - -Just what we expected, like any other dynamic placeholder. - -Static placeholder ------------------- - -(cache.static) - -The template: - -:: - - Cached variable: $*voom - -The command line and output: - -:: - - % voom='Voom!' python x.py --env - Cached variable: Voom! - -The generated code, with line numbers: - -:: - - 1 write('Cached variable: ') - 2 ## START CACHE REGION: at line, col (1, 19) in the source. - 3 RECACHE = True - 4 if '19760169' not in self._cacheData: - 5 pass - 6 else: - 7 RECACHE = False - 8 if RECACHE: - 9 orig_trans = trans - 10 trans = cacheCollector = DummyTransaction() - 11 write = cacheCollector.response().write - 12 write(filter(VFS(SL,"voom",1))) # generated from '$*voom' at line 1, - # col 19. - 13 trans = orig_trans - 14 write = trans.response().write - 15 self._cacheData['19760169'] = cacheCollector.response().getvalue() - 16 del cacheCollector - 17 write(self._cacheData['19760169']) - 18 ## END CACHE REGION - - 19 write('\n') - -That one little star generated a whole lotta code. First, instead -of an ordinary {VFS} lookup (searchList) lookup, it converted the -placeholder to a lookup in the {.\_cacheData} dictionary. Cheetah -also generated a unique key ({'19760169'}) for our cached item - -this is its cache ID. - -Second, Cheetah put a pair of if-blocks before the {write}. The -first (lines 3-7) determine whether the cache value is missing or -out of date, and sets local variable {RECACHE} true or false. This -stanza may look unnecessarily verbose - lines 3-7 could be -eliminated if line 8 was changed to - -:: - - if '19760169' not in self._cacheData: - -- but this model is expandable for some of the cache features we'll -see below. - -The second if-block, lines 8-16, do the cache updating if -necessary. Clearly, the programmer is trying to stick as close to -normal (dynamic) workflow as possible. Remember that {write}, even -though it looks like a local function, is actually a method of a -file-like object. So we create a temporary file-like object to -divert the {write} object into, then read the result and stuff it -into the cache. - -Timed-refresh placeholder -------------------------- - -(cache.timed) - -The template: - -:: - - Timed cache: $*.5m*voom - -The command line and the output: - -:: - - % voom='Voom!' python x.py --env - Timed cache: Voom! - -The generated method's docstring: - -:: - - """ - This is the main method generated by Cheetah - This cache will be refreshed every 30.0 seconds. - """ - -The generated code: - -:: - - 1 write('Timed cache: ') - 2 ## START CACHE REGION: at line, col (1, 15) in the source. - 3 RECACHE = True - 4 if '55048032' not in self._cacheData: - 5 self.__cache55048032__refreshTime = currentTime() + 30.0 - 6 elif currentTime() > self.__cache55048032__refreshTime: - 7 self.__cache55048032__refreshTime = currentTime() + 30.0 - 8 else: - 9 RECACHE = False - 10 if RECACHE: - 11 orig_trans = trans - 12 trans = cacheCollector = DummyTransaction() - 13 write = cacheCollector.response().write - 14 write(filter(VFS(SL,"voom",1))) # generated from '$*.5m*voom' at - # line 1, col 15. - 15 trans = orig_trans - 16 write = trans.response().write - 17 self._cacheData['55048032'] = cacheCollector.response().getvalue() - 18 del cacheCollector - 19 write(self._cacheData['55048032']) - 20 ## END CACHE REGION - - 21 write('\n') - -This code is identical to the static cache example except for the -docstring and the first if-block. (OK, so the cache ID is different -and the comment on line 14 is different too. Big deal.) - -Each timed-refresh cache item has a corrsponding private attribute -{.\_\_cache########\_\_refreshTime} giving the refresh time in -ticks (=seconds since January 1, 1970). The first if-block (lines -3-9) checks whether the cache value is missing or its update time -has passed, and if so, sets {RECACHE} to true and also schedules -another refresh at the next interval. - -The method docstring reminds the user how often the cache will be -refreshed. This information is unfortunately not as robust as it -could be. Each timed-cache placeholder blindly generates a line in -the docstring. If all refreshes are at the same interval, there -will be multiple identical lines in the docstring. If the refreshes -are at different intervals, you get a situation like this: - -:: - - """ - This is the main method generated by Cheetah - This cache will be refreshed every 30.0 seconds. - This cache will be refreshed every 60.0 seconds. - This cache will be refreshed every 120.0 seconds. - """ - -The docstring tells only that "something" will be refreshed every -60.0 seconds, but doesn't reveal { which} placeholder that is. Only -if you know the relative order of the placeholders in the template -can you figure that out. - -Timed-refresh placeholder with braces -------------------------------------- - -(cache.timed.braces) - -This example is the same but with the long placeholder syntax. It's -here because it's a Cheetah FAQ whether to put the cache interval -inside or outside the braces. (It's also here so I can look it up -because I frequently forget.) The answer is: outside. The braces go -around only the placeholder name (and perhaps some output-filter -arguments.) - -The template: - -:: - - Timed with {}: $*.5m*{voom} - -The output: - -:: - - Timed with {}: Voom! - -The generated code differs only in the comment. Inside the -cache-refresh if-block: - -:: - - write(filter(VFS(SL,"voom",1))) # generated from '$*.5m*{voom}' at line 1, - #col 17. - -If you try to do it this way: - -:: - - Timed with {}: ${*.5m*voom} ## Wrong! - -you get: - -:: - - Timed with {}: ${*.5m*voom} - -``${`` is not a valid placeholder, so it gets treated as ordinary -text. - -#cache ------- - -(cache.directive) - -The template: - -:: - - #cache - This is a cached region. $voom - #end cache - -The output: - -:: - - This is a cached region. Voom! - -The generated code: - -:: - - 1 ## START CACHE REGION: at line, col (1, 1) in the source. - 2 RECACHE = True - 3 if '23711421' not in self._cacheData: - 4 pass - 5 else: - 6 RECACHE = False - 7 if RECACHE: - 8 orig_trans = trans - 9 trans = cacheCollector = DummyTransaction() - 10 write = cacheCollector.response().write - 11 write('This is a cached region. ') - 12 write(filter(VFS(SL,"voom",1))) # generated from '$voom' at line 2, - # col 27. - 13 write('\n') - 14 trans = orig_trans - 15 write = trans.response().write - 16 self._cacheData['23711421'] = cacheCollector.response().getvalue() - 17 del cacheCollector - 18 write(self._cacheData['23711421']) - 19 ## END CACHE REGION - -This is the same as the {$\*voom} example, except that the plain -text around the placeholder is inside the second if-block. - -#cache with timer and id ------------------------- - -(cache.directive.timer) - -The template: - -:: - - #cache timer='.5m', id='cache1' - This is a cached region. $voom - #end cache - -The output: - -:: - - This is a cached region. Voom! - -The generated code is the same as the previous example except the -first if-block: - -:: - - RECACHE = True - if '13925129' not in self._cacheData: - self._cacheIndex['cache1'] = '13925129' - self.__cache13925129__refreshTime = currentTime() + 30.0 - elif currentTime() > self.__cache13925129__refreshTime: - self.__cache13925129__refreshTime = currentTime() + 30.0 - else: - RECACHE = False - -#cache with test: expression and method conditions --------------------------------------------------- - -(cache.directive.test) - -The template: - -:: - - #cache test=$isDBUpdated - This is a cached region. $voom - #end cache - -(Analysis postponed: bug in Cheetah produces invalid Python.) - -The template: - -:: - - #cache id='cache1', test=($isDBUpdated or $someOtherCondition) - This is a cached region. $voom - #end cache - -The output: - -:: - - This is a cached region. Voom! - -The first if-block in the generated code: - -:: - - RECACHE = True - if '36798144' not in self._cacheData: - self._cacheIndex['cache1'] = '36798144' - elif (VFS(SL,"isDBUpdated",1) or VFS(SL,"someOtherCondition",1)): - RECACHE = True - else: - RECACHE = False - -The second if-block is the same as in the previous example. If you -leave out the {()} around the test expression, the result is the -same, although it may be harder for the template maintainer to -read. - -You can even combine arguments, although this is of questionable -value. - -The template: - -:: - - #cache id='cache1', timer='30m', test=$isDBUpdated or $someOtherCondition - This is a cached region. $voom - #end cache - -The output: - -:: - - This is a cached region. Voom! - -The first if-block: - -:: - - RECACHE = True - if '88939345' not in self._cacheData: - self._cacheIndex['cache1'] = '88939345' - self.__cache88939345__refreshTime = currentTime() + 1800.0 - elif currentTime() > self.__cache88939345__refreshTime: - self.__cache88939345__refreshTime = currentTime() + 1800.0 - elif VFS(SL,"isDBUpdated",1) or VFS(SL,"someOtherCondition",1): - RECACHE = True - else: - RECACHE = False - -We are planning to add a {'varyBy'} keyword argument in the future -that will allow separate cache instances to be created for a -variety of conditions, such as different query string parameters or -browser types. This is inspired by ASP.net's varyByParam and -varyByBrowser output caching keywords. Since this is not -implemented yet, I cannot provide examples here. - - diff --git a/docs/html/_sources/dev_guide/comments.rst.txt b/docs/html/_sources/dev_guide/comments.rst.txt deleted file mode 100644 index c2f9a89..0000000 --- a/docs/html/_sources/dev_guide/comments.rst.txt +++ /dev/null @@ -1,103 +0,0 @@ -Directives: Comments -==================== - -(comments) - -The template: - -:: - - Text before the comment. - ## The comment. - Text after the comment. - #* A multi-line comment spanning several lines. - It spans several lines, too. - *# - Text after the multi-line comment. - -The output: - -:: - - Text before the comment. - Text after the comment. - - Text after the multi-line comment. - -The generated code: - -:: - - write('Text before the comment.\n') - # The comment. - write('Text after the comment.\n') - # A multi-line comment spanning several lines. - # It spans several lines, too. - write('\nText after the multi-line comment.\n') - -Docstring and header comments ------------------------------ - -(comments.docstring) - -The template: - -:: - - ##doc: .respond() method comment. - ##doc-method: Another .respond() method comment. - ##doc-class: A class comment. - ##doc-module: A module comment. - ##header: A header comment. - -The output: - -:: - - - -The beginning of the generated {.respond} method: - -:: - - def respond(self, - trans=None, - dummyTrans=False, - VFS=valueFromSearchList, - VFN=valueForName, - getmtime=getmtime, - currentTime=time.time): - - """ - This is the main method generated by Cheetah - .respond() method comment. - Another .respond() method comment. - """ - -The class docstring: - -:: - - """ - A class comment. - - Autogenerated by CHEETAH: The Python-Powered Template Engine - """ - -The top of the module: - -:: - - #!/usr/bin/env python - # A header comment. - - """A module comment. - - Autogenerated by CHEETAH: The Python-Powered Template Engine - CHEETAH VERSION: 0.9.13a1 - Generation time: Fri Apr 26 22:39:23 2002 - Source file: x.tmpl - Source file last modified: Fri Apr 26 22:36:23 2002 - """ - - diff --git a/docs/html/_sources/dev_guide/compiler.rst.txt b/docs/html/_sources/dev_guide/compiler.rst.txt deleted file mode 100644 index 33f3bcd..0000000 --- a/docs/html/_sources/dev_guide/compiler.rst.txt +++ /dev/null @@ -1,8 +0,0 @@ -The compiler -============ - -(compiler) - -How templates are compiled: a walk through Compiler.py. - - diff --git a/docs/html/_sources/dev_guide/design.rst.txt b/docs/html/_sources/dev_guide/design.rst.txt deleted file mode 100644 index 1ffabbd..0000000 --- a/docs/html/_sources/dev_guide/design.rst.txt +++ /dev/null @@ -1,104 +0,0 @@ -Design Decisions and Tradeoffs -============================== - -(design) - -Delimiters ----------- - -(design.Delimiters) - -One of the first decisions we encountered was which delimiter -syntax to use. We decided to follow Velocity's {$placeholder} and -{#directive} syntax because the former is widely used in other -languages for the same purpose, and the latter stands out in an -HTML or text document. We also implemented the -``${longPlaceholder}`` syntax like the shells for cases where -Cheetah or you might be confused where a placeholder ends. Tavis -went ahead and made ``${longPlaceholder}`` and -``$[longPlaceholder]`` interchangeable with it since it was trivial -to implement. Finally, the {#compiler} directive allows you to -change the delimiters if you don't like them or if they conflict -with the text in your document. (Obviously, if your document -contains a Perl program listing, you don't necessarily want to -backslash each and every {$} and {#}, do you?) - -The choice of comment delimiters was more arbitrary. {##} and {#\* -... \*#} doesn't match any language, but it's reminiscent of Python -and C while also being consistent with our "{#} is for directives" -convention. - -We specifically chose { not} to use pseudo HTML tags for -placeholders and directives, as described more thoroughly in the -Cheetah Users' Guide introduction. Pseudo HTML tags may be easier -to see in a visual editor (supposedly), but in text editors they're -hard to distinguish from "real" HTML tags unless you look closely, -and they're many more keystrokes to type. Also, if you make a -mistake, the tag will show up as literal text in the rendered HTML -page where it will be easy to notice and eradicate, rather than -disappearing as bogus HTML tags do in browsers. - -Late binding ------------- - -(design.lateBinding) - -One of Cheetah's unique features is the name mapper, which lets you -write {$a.b} without worrying much about the type of {a} or {b}. -Prior to version 0.9.7, Cheetah did the entire NameMapper lookup at -runtime. This provided maximum flexibility at the expense of speed. -Doing a NameMapper lookup is intrinsically more expensive than an -ordinary Python expression because Cheetah has to decide what type -of container {a} is, whether the the value is a function (autocall -it), issue the appropriate Python incantation to look up {b} in it, -autocall again if necessary, and then convert the result to a -string. - -To maximize run-time (filling-time) performance, Cheetah 0.9.7 -pushed much of this work back into the compiler. The compiler -looked up {a} in the searchList at compile time, noted its type, -and generated an eval'able Python expression based on that. - -This approach had two significant drawbacks. What if {a} later -changes type before a template filling? Answer: unpredictable -exceptions occur. What if {a} does not exist in the searchList at -compile time? Answer: the template can't compile. - -To prevent these catastrophes, users were required to prepopulate -the searchList before instantiating the template instance, and then -not to change {a}'s type. Static typing is repugnant in a dynamic -language like Python, and having to prepopulate the searchList made -certain usages impossible. For example, you couldn't instantiate -the template object without a searchList and then set {self} -attributes to specify the values. - -After significant user complaints about the fragility of this -system, Tavis rewrote placeholder handling, and in version 0.9.8a3 -(August 2001), Tavis moved the name mapper lookup back into -runtime. Performance wasn't crippled because he discovered that -writing a C version of the name mapper was easier than anticipated, -and the C version completed the lookup quickly. Now Cheetah had -"late binding", meaning the compiler does not look up {a} or care -whether it exists. This allows users to create {a} or change its -type anytime before a template filling. - -The lesson we learned is that it's better to decide what you want -and then figure out how to do it, rather than assuming that certain -goals are unattainable due to performance considerations. - -Caching framework ------------------ - -(design.cache) - -Webware compatibility and the transaction framework ---------------------------------------------------- - -(design.webware) - -Single inheritance ------------------- - -(design.singleInheritance) - - diff --git a/docs/html/_sources/dev_guide/errorHandling.rst.txt b/docs/html/_sources/dev_guide/errorHandling.rst.txt deleted file mode 100644 index e97d1fb..0000000 --- a/docs/html/_sources/dev_guide/errorHandling.rst.txt +++ /dev/null @@ -1,329 +0,0 @@ -Directives: Error Handling -========================== - -(errorHandling) - -#try and #raise ---------------- - -(errorHandling.try) - -The template: - -:: - - #import traceback - #try - #raise RuntimeError - #except RuntimeError - A runtime error occurred. - #end try - - #try - #raise RuntimeError("Hahaha!") - #except RuntimeError - #echo $sys.exc_info()[1] - #end try - - #try - #echo 1/0 - #except ZeroDivisionError - You can't divide by zero, idiot! - #end try - -The output: - -:: - - A runtime error occurred. - - Hahaha! - - You can't divide by zero, idiot! - -The generated code: - -:: - - try: - raise RuntimeError - except RuntimeError: - write('A runtime error occurred.\n') - write('\n') - try: - raise RuntimeError("Hahaha!") - except RuntimeError: - write(filter(VFN(sys,"exc_info",0)()[1])) - write('\n') - write('\n') - try: - write(filter(1/0)) - write('\n') - except ZeroDivisionError: - write("You can't divide by zero, idiot!\n") - -{#finally} works just like in Python. - -#assert -------- - -(errorHandling.assert) - -The template: - -:: - - #assert False, "You lose, buster!" - -The output: - -:: - - Traceback (most recent call last): - File "x.py", line 117, in ? - x().runAsMainProgram() - File "/local/opt/Python/lib/python2.2/site-packages/Webware/Cheetah/ - Template.py", line 331, in runAsMainProgram - CmdLineIface(templateObj=self).run() - File "/local/opt/Python/lib/python2.2/site-packages/Webware/Cheetah/ - TemplateCmdLineIface.py", line 59, in run - print self._template - File "x.py", line 91, in respond - assert False, "You lose, buster!" - AssertionError: You lose, buster! - -The generated code: - -:: - - assert False, "You lose, buster!" - -#errorCatcher -------------- - -(errorHandling.errorCatcher) - -No error catcher -~~~~~~~~~~~~~~~~ - -(errorHandling.errorCatcher.no) - -The template: - -:: - - $noValue - -The output: - -:: - - Traceback (most recent call last): - File "x.py", line 118, in ? - x().runAsMainProgram() - File "/local/opt/Python/lib/python2.2/site-packages/Webware/Cheetah/ - Template.py", line 331, in runAsMainProgram - CmdLineIface(templateObj=self).run() - File "/local/opt/Python/lib/python2.2/site-packages/Webware/Cheetah/ - TemplateCmdLineIface.py", line 59, in run - print self._template - File "x.py", line 91, in respond - write(filter(VFS(SL,"noValue",1))) # generated from '$noValue' at line - 1, col 1. - NameMapper.NotFound: noValue - -The generated code: - -:: - - write(filter(VFS(SL,"noValue",1))) # generated from '$noValue' at line 1, - # col 1. - write('\n') - -Echo and BigEcho -~~~~~~~~~~~~~~~~ - -(errorHandling.errorCatcher.echo) - -The template: - -:: - - #errorCatcher Echo - $noValue - #errorCatcher BigEcho - $noValue - -The output: - -:: - - $noValue - ===============<$noValue could not be found>=============== - -The generated code: - -:: - - if "Echo" in self._errorCatchers: - self._errorCatcher = self._errorCatchers["Echo"] - else: - self._errorCatcher = self._errorCatchers["Echo"] = ErrorCatchers.Echo(self) - write(filter(self.__errorCatcher1(localsDict=locals()))) - # generated from '$noValue' at line 2, col 1. - write('\n') - if "BigEcho" in self._errorCatchers: - self._errorCatcher = self._errorCatchers["BigEcho"] - else: - self._errorCatcher = self._errorCatchers["BigEcho"] = \ - ErrorCatchers.BigEcho(self) - write(filter(self.__errorCatcher1(localsDict=locals()))) - # generated from '$noValue' at line 4, col 1. - write('\n') - -ListErrors -~~~~~~~~~~ - -(errorHandling.errorCatcher.listErrors) - -The template: - -:: - - #import pprint - #errorCatcher ListErrors - $noValue - $anotherMissingValue.really - $pprint.pformat($errorCatcher.listErrors) - ## This is really self.errorCatcher().listErrors() - -The output: - -:: - - $noValue - $anotherMissingValue.really - [{'code': 'VFS(SL,"noValue",1)', - 'exc_val': , - 'lineCol': (3, 1), - 'rawCode': '$noValue', - 'time': 'Wed May 15 00:38:23 2002'}, - {'code': 'VFS(SL,"anotherMissingValue.really",1)', - 'exc_val': , - 'lineCol': (4, 1), - 'rawCode': '$anotherMissingValue.really', - 'time': 'Wed May 15 00:38:23 2002'}] - -The generated import: - -:: - - import pprint - -Then in the generated class, we have our familiar {.respond} method -and several new methods: - -:: - - def __errorCatcher1(self, localsDict={}): - """ - Generated from $noValue at line, col (3, 1). - """ - - try: - return eval('''VFS(SL,"noValue",1)''', globals(), localsDict) - except self._errorCatcher.exceptions(), e: - return self._errorCatcher.warn(exc_val=e, code= 'VFS(SL,"noValue",1)' , - rawCode= '$noValue' , lineCol=(3, 1)) - - def __errorCatcher2(self, localsDict={}): - """ - Generated from $anotherMissingValue.really at line, col (4, 1). - """ - - try: - return eval('''VFS(SL,"anotherMissingValue.really",1)''', globals(), - localsDict) - except self._errorCatcher.exceptions(), e: - return self._errorCatcher.warn(exc_val=e, - code= 'VFS(SL,"anotherMissingValue.really",1)' , - rawCode= '$anotherMissingValue.really' , lineCol=(4, 1)) - - def __errorCatcher3(self, localsDict={}): - """ - Generated from $pprint.pformat($errorCatcher.listErrors) at line, col - (5, 1). - """ - - try: - return eval('''VFN(pprint,"pformat",0)(VFS(SL, - "errorCatcher.listErrors",1))''', globals(), localsDict) - except self._errorCatcher.exceptions(), e: - return self._errorCatcher.warn(exc_val=e, code= - 'VFN(pprint,"pformat",0)(VFS(SL,"errorCatcher.listErrors",1))' , - rawCode= '$pprint.pformat($errorCatcher.listErrors)' , - lineCol=(5, 1)) - -:: - - def respond(self, - trans=None, - dummyTrans=False, - VFS=valueFromSearchList, - VFN=valueForName, - getmtime=getmtime, - currentTime=time.time): - - - """ - This is the main method generated by Cheetah - """ - - if not trans: - trans = DummyTransaction() - dummyTrans = True - write = trans.response().write - SL = self._searchList - filter = self._currentFilter - globalSetVars = self._globalSetVars - - ######################################## - ## START - generated method body - - if exists(self._filePath) and getmtime(self._filePath) > self._fileMtime: - self.compile(file=self._filePath) - write(getattr(self, self._mainCheetahMethod_for_x)(trans=trans)) - if dummyTrans: - return trans.response().getvalue() - else: - return "" - if "ListErrors" in self._errorCatchers: - self._errorCatcher = self._errorCatchers["ListErrors"] - else: - self._errorCatcher = self._errorCatchers["ListErrors"] = \ - ErrorCatchers.ListErrors(self) - write(filter(self.__errorCatcher1(localsDict=locals()))) - # generated from '$noValue' at line 3, col 1. - write('\n') - write(filter(self.__errorCatcher2(localsDict=locals()))) - # generated from '$anotherMissingValue.really' at line 4, col 1. - write('\n') - write(filter(self.__errorCatcher3(localsDict=locals()))) - # generated from '$pprint.pformat($errorCatcher.listErrors)' at line - # 5, col 1. - write('\n') - # This is really self.errorCatcher().listErrors() - - ######################################## - ## END - generated method body - - if dummyTrans: - return trans.response().getvalue() - else: - return "" - -So whenever an error catcher is active, each placeholder gets -wrapped in its own method. No wonder error catchers slow down the -system! - - diff --git a/docs/html/_sources/dev_guide/files.rst.txt b/docs/html/_sources/dev_guide/files.rst.txt deleted file mode 100644 index ab8d7a1..0000000 --- a/docs/html/_sources/dev_guide/files.rst.txt +++ /dev/null @@ -1,11 +0,0 @@ -Files -===== - -(files) - -This chapter will be an overview of the files in the Cheetah -package, and how they interrelate in compiling and filling a -template. We'll also look at files in the Cheetah tarball that -don't get copied into the package. - - diff --git a/docs/html/_sources/dev_guide/flowControl.rst.txt b/docs/html/_sources/dev_guide/flowControl.rst.txt deleted file mode 100644 index d391b2f..0000000 --- a/docs/html/_sources/dev_guide/flowControl.rst.txt +++ /dev/null @@ -1,394 +0,0 @@ -Directives: Flow Control -======================== - -(flowControl) - -#for ----- - -(flowControl.for) - -The template: - -:: - - #for $i in $range(10) - $i #slurp - #end for - -The output: - -:: - - 0 1 2 3 4 5 6 7 8 9 - -The generated code: - -:: - - for i in range(10): - write(filter(i)) # generated from '$i' at line 2, col 1. - write(' ') - -#repeat -------- - -(flowControl.repeat) - -The template: - -:: - - #repeat 3 - My bonnie lies over the ocean - #end repeat - O, bring back my bonnie to me! - -The output: - -:: - - My bonnie lies over the ocean - My bonnie lies over the ocean - My bonnie lies over the ocean - O, bring back my bonnie to me! - -(OK, so the second line should be "sea" instead of "ocean".) - -The generated code: - -:: - - for __i0 in range(3): - write('My bonnie lies over the ocean\n') - write('O, bring back my bonnie to me!\n') - -Note that a new local variable of the form {\_\_i$num} will be used -for each instance of {repeat} in order to permit nesting. - -#while ------- - -(flowControl.while) - -The template: - -:: - - #set $alive = True - #while $alive - I am alive! - #set $alive = False - #end while - -The output: - -:: - - I am alive! - -The generated code: - -:: - - alive = True - while alive: - write('I am alive!\n') - alive = False - -#if ---- - -() - -The template: - -:: - - #set $size = 500 - #if $size >= 1500 - It's big - #else if $size < 1500 and $size > 0 - It's small - #else - It's not there - #end if - -The output: - -:: - - It's small - -The generated code: - -:: - - size = 500 - if size >= 1500: - write("It's big\n") - elif size < 1500 and size > 0: - write("It's small\n") - else: - write("It's not there\n") - -#unless -------- - -(flowControl.unless) - -The template: - -:: - - #set $count = 9 - #unless $count + 5 > 15 - Count is in range. - #end unless - -The output: - -:: - - Count is in range. - -The generated code: - -:: - - count = 9 - if not (count + 5 > 15): - write('Count is in range.\n') - -{ Note:} There is a bug in Cheetah 0.9.13. It's forgetting the -parentheses in the {if} expression, which could lead to it -calculating something different than it should. - -#break and #continue --------------------- - -(flowControl.break) - -The template: - -:: - - #for $i in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 'James', 'Joe', 'Snow'] - #if $i == 10 - #continue - #end if - #if $i == 'Joe' - #break - #end if - $i - #slurp - #end for - -The output: - -:: - - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 11 - 12 - James - - -The generated code: - -:: - - for i in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 'James', 'Joe', 'Snow']: - if i == 10: - write('') - continue - if i == 'Joe': - write('') - break - write(filter(i)) # generated from '$i' at line 8, col 1. - write(' - ') - -#pass ------ - -(flowControl.pass) - -The template: - -:: - - Let's check the number. - #set $size = 500 - #if $size >= 1500 - It's big - #elif $size > 0 - #pass - #else - Invalid entry - #end if - Done checking the number. - -The output: - -:: - - Let's check the number. - Done checking the number. - -The generated code: - -:: - - write("Let's check the number.\n") - size = 500 - if size >= 1500: - write("It's big\n") - elif size > 0: - pass - else: - write('Invalid entry\n') - write('Done checking the number.\n') - -#stop ------ - -(flowControl.stop) - -The template: - -:: - - A cat - #if 1 - sat on a mat - #stop - watching a rat - #end if - in a flat. - -The output: - -:: - - A cat - sat on a mat - -The generated code: - -:: - - write('A cat\n') - if 1: - write(' sat on a mat\n') - if dummyTrans: - return trans.response().getvalue() - else: - return "" - write(' watching a rat\n') - write('in a flat.\n') - -#return -------- - -(flowControl.return) - -The template: - -:: - - 1 - $test[1] - 3 - #def test - 1.5 - #if 1 - #return '123' - #else - 99999 - #end if - #end def - -The output: - -:: - - 1 - 2 - 3 - -The generated code: - -:: - - def test(self, - trans=None, - dummyTrans=False, - VFS=valueFromSearchList, - VFN=valueForName, - getmtime=getmtime, - currentTime=time.time): - - - """ - Generated from #def test at line 5, col 1. - """ - - if not trans: - trans = DummyTransaction() - dummyTrans = True - write = trans.response().write - SL = self._searchList - filter = self._currentFilter - globalSetVars = self._globalSetVars - - ######################################## - ## START - generated method body - - write('1.5\n') - if 1: - return '123' - else: - write('99999\n') - - ######################################## - ## END - generated method body - - if dummyTrans: - return trans.response().getvalue() - else: - return "" - -:: - - def respond(self, - trans=None, - dummyTrans=False, - VFS=valueFromSearchList, - VFN=valueForName, - getmtime=getmtime, - currentTime=time.time): - - - """ - This is the main method generated by Cheetah - """ - - if not trans: - trans = DummyTransaction() - dummyTrans = True - write = trans.response().write - SL = self._searchList - filter = self._currentFilter - globalSetVars = self._globalSetVars - - ######################################## - ## START - generated method body - - write('\n1\n') - write(filter(VFS(SL,"test",1)[1])) # generated from '$test[1]' at line 3, col 1. - write('\n3\n') - - ######################################## - ## END - generated method body - - if dummyTrans: - return trans.response().getvalue() - else: - return "" - - diff --git a/docs/html/_sources/dev_guide/history.rst.txt b/docs/html/_sources/dev_guide/history.rst.txt deleted file mode 100644 index d0e1ceb..0000000 --- a/docs/html/_sources/dev_guide/history.rst.txt +++ /dev/null @@ -1,88 +0,0 @@ -History of Cheetah -================== - -(history) - -In Spring 2001, several members of the webware-discuss mailing list -expressed the need for a template engine. Webware like Python is -great for organizing logic, but they both suffer when you need to -do extensive variable interpolation into large pieces of text, or -to build up a text string from its nested parts. Python's {%} -operator gets you only so far, the syntax is cumbersome, and you -have to use a separate format string for each nested part. Most of -us had used template systems from other platforms-chiefly Zope's -DTML, PHPLib's Template object and Java's Velocity-and wanted to -port something like those so it could be used both in Webware -servlets and in standalone Python programs. - -Since I (Mike Orr) am writing this history, I'll describe how I -encountered Cheetah. I had written a template module called -PlowPlate based on PHPLib's Template library. Like PHPLib, it used -regular expressions to search and destroy-er, replace-placeholders, -behaved like a dictionary to specify placeholder values, contained -no directives, but did have BEGIN and END markers which could be -used to extract a named block (subtemplate). Meanwhile, Tavis Rudd -was also on webware-discuss and interested in templates, and he -lived just a few hours away. So on 12 May 2001 we met in Vancouver -at a gelato shop on Denman Street and discussed Webware, and he -drew on a napkin the outline of a template system he was working -on. - -[Note from Tavis: Mikes got the dates and sequence of things a -little out of order, but what the hell ...] - -Instead of filling the template by search-and-replace, he wanted to -break it up into parts. This was a primitive form of template -compiling: do the time-consuming work once and put it to a state -where you can fill the template quickly multiple times. A template -without directives happens to break down naturally into a list of -alternating text/placeholder pairs. The odd subscript values are -literal strings; the even subscripts are string keys into a -dictionary of placeholder values. The project was called -TemplateServer. - -In a couple months, Tavis decided that instead of compiling to a -list, he wanted to compile to Python source code: a series of -{write} calls that would output into a file-like object. This was -the nucleus that became Cheetah. I thought that idea was stupid, -but it turned out that this not-so-stupid idea blew all the others -out of the water in terms of performance. - -Another thing Tavis pushed hard for from near the beginning was -"display logic", or simple directives like {#for}, {#if} and -{#echo}. (OK, {#echo} came later, but conceptually it belongs here. -I thought display logic was even stupider than compiling to Python -source code because it would just lead to "DTML hell"-complicated -templates that are hard to read and maintain, and for which you -have to learn (and debug) a whole new language when Python does it -just fine. But others (hi Chuck!) had templates that were -maintained by secretaries who didn't know Python, and the -secretaries needed display logic, so that was that. Finally, after -working with Cheetah templates (with display logic) and PlowPlate -templates (with just blocks rather than display logic), I realized -Tavis was smarter than I was and display logic really did belong in -the template. - -The next step was making directives for all the Python flow-control -statements: {#while}, {#try}, {#assert}, etc. Some of them we -couldn't think of a use for. Nevertheless, they were easy to code, -and "somebody" would probably need them "someday", so we may as -well implement them now. - -During all this, Chuck Esterbrook, Ian Bicking and others offered -(and still offer) their support and suggestions, and Chuck gave us -feedback about his use of Cheetah-its first deployment in a -commercial production environment. Later, Edmund Lian became our #1 -bug reporter and suggester as he used Cheetah in his web -applications. - -We were going to release 1.0 in January 2002, but we decided to -delay it until more people used it in real-world situations and -gave us feedback about what is still needed. This has led to many -refinements, and we have added (and removed) features according to -this feedback. Nevertheless, Cheetah has been changing but stable -since the late-binding rewrite in fall 2001, and anybody who keeps -up with the cheetah-discuss mailing list will know when changes -occur that require modifying one's template, and since most people -use point releases rather than CVS, they generally have a few -week's warning about any significant changes. diff --git a/docs/html/_sources/dev_guide/index.rst.txt b/docs/html/_sources/dev_guide/index.rst.txt deleted file mode 100644 index 83ff7d9..0000000 --- a/docs/html/_sources/dev_guide/index.rst.txt +++ /dev/null @@ -1,30 +0,0 @@ -Cheetah Developer's Guide -========================== - -Overview --------- -This guide needs to really be filled out more - -.. toctree:: - :maxdepth: 1 - - introduction.rst - compiler.rst - parser.rst - errorHandling.rst - placeholders.rst - patching.rst - flowControl.rst - design.rst - safeDelegation.rst - history.rst - output.rst - files.rst - cache.rst - bnf.rst - pyModules.rst - comments.rst - parserInstructions.rst - template.rst - inheritanceEtc.rst - diff --git a/docs/html/_sources/dev_guide/inheritanceEtc.rst.txt b/docs/html/_sources/dev_guide/inheritanceEtc.rst.txt deleted file mode 100644 index 0b06ab9..0000000 --- a/docs/html/_sources/dev_guide/inheritanceEtc.rst.txt +++ /dev/null @@ -1,255 +0,0 @@ -Directives: Import, Inheritance, Declaration and Assignment -=========================================================== - -(inheritanceEtc) - -#import and #from ------------------ - -(inheritanceEtc.import) - -The template: - -:: - - #import math - -This construct does not produce any output. - -The generated module, at the bottom of the import section: - -:: - - import math - -#extends --------- - -(inheritanceEtc.extends) - -The template: - -:: - - #extends SomeClass - -The generated import (skipped if {SomeClass} has already been -imported): - -:: - - from SomeClass import SomeClass - -The generated class: - -:: - - class x(SomeClass): - -#implements ------------ - -(inheritanceEtc.implements) - -The template: - -:: - - #implements doOutput - -In the generated class, the main method is {.doOutput} instead of -{.respond}, and the attribute naming this method is: - -:: - - _mainCheetahMethod_for_x2= 'doOutput' - -#set and #set global --------------------- - -(inheritanceEtc.set) - -The template: - -:: - - #set $namesList = ['Moe','Larry','Curly'] - $namesList - #set global $toes = ['eeny', 'meeny', 'miney', 'moe'] - $toes - -The output: - -:: - - ['Moe', 'Larry', 'Curly'] - ['eeny', 'meeny', 'miney', 'moe'] - -The generated code: - -:: - - 1 namesList = ['Moe','Larry','Curly'] - 2 write(filter(namesList)) # generated from '$namesList' at line 2, col 1. - 3 write('\n') - 4 globalSetVars["toes"] = ['eeny', 'meeny', 'miney', 'moe'] - 5 write(filter(VFS(SL,"toes",1))) # generated from '$toes' at line 4, col 1. - 6 write('\n') - -{globalSetVars} is a local variable referencing {.\_globalSetVars}. -Writes go into it directly, but reads take advantage of the fact -that {.\_globalSetVars} is on the searchList. (In fact, it's the -very first namespace.) - -#del ----- - -(inheritanceEtc.del) - -The template: - -:: - - #set $a = 1 - #del $a - #set $a = 2 - #set $arr = [0, 1, 2] - #del $a, $arr[1] - -In the generated class: - -:: - - 1 a = 1 - 2 del a - 3 a = 2 - 4 arr = [0, 1, 2] - 5 del a, arr[1] - -#attr ------ - -(inheritanceEtc.attr) - -The template: - -:: - - #attr $namesList = ['Moe', 'Larry', 'Curly'] - -In the generated class: - -:: - - ## GENERATED ATTRIBUTES - - namesList = ['Moe', 'Larry', 'Curly'] - -#def ----- - -(inheritanceEtc.def) - -The template: - -:: - - #def printArg($arg) - The argument is $arg. - #end def - My method returned $printArg(5). - -The output: - -:: - - My method returned The argument is 5. - . - -Hmm, not exactly what we expected. The method returns a trailing -newline because we didn't end the last line with {#slurp}. So the -second period (outside the method) appears on a separate line. - -The {#def} generates a method {.printArg} whose structure is -similar to the main method: - -:: - - def printArg(self, - arg, - trans=None, - dummyTrans=False, - VFS=valueFromSearchList, - VFN=valueForName, - getmtime=getmtime, - currentTime=time.time): - - - """ - Generated from #def printArg($arg) at line 1, col 1. - """ - - if not trans: - trans = DummyTransaction() - dummyTrans = True - write = trans.response().write - SL = self._searchList - filter = self._currentFilter - globalSetVars = self._globalSetVars - - ######################################## - ## START - generated method body - - write('The argument is ') - write(filter(arg)) # generated from '$arg' at line 2, col 17. - write('.\n') - - ######################################## - ## END - generated method body - - if dummyTrans: - return trans.response().getvalue() - else: - return "" - -When {.printArg} is called from a placeholder, only the arguments -the user supplied are passed. The other arguments retain their -default values. - -#block ------- - -(inheritanceEtc.block) - -The template: - -:: - - #block content - This page is under construction. - #end block - -The output: - -:: - - This page is under construction. - -This construct generates a method {.content} in the same structure -as {.printArg} above, containing the write code: - -:: - - write('This page is under construction.\n') - -In the main method, the write code is: - -:: - - self.content(trans=trans) # generated from ('content', '#block content') - # at line 1, col 1. - -So a block placeholder implicitly passes the current transaction to -the method. - - diff --git a/docs/html/_sources/dev_guide/introduction.rst.txt b/docs/html/_sources/dev_guide/introduction.rst.txt deleted file mode 100644 index c77e1e5..0000000 --- a/docs/html/_sources/dev_guide/introduction.rst.txt +++ /dev/null @@ -1,28 +0,0 @@ -Introduction -============ - -Who should read this Guide? ---------------------------- - -The Cheetah Developers' Guide is for those who want to learn how -Cheetah works internally, or wish to modify or extend Cheetah. It -is assumed that you've read the Cheetah Users' Guide and have an -intermediate knowledge of Python. - -Contents --------- - -This Guide takes a behaviorist approach. First we'll look at what -the Cheetah compiler generates when it compiles a template -definition, and how it compiles the various $placeholder features -and #directives. Then we'll stroll through the files in the Cheetah -source distribution and show how each file contributes to the -compilation and/or filling of templates. Then we'll list every -method/attribute inherited by a template object. Finally, we'll -describe how to submit bugfixes/enhancements to Cheetah, and how to -add to the documentation. - -Appendix A will contain a BNF syntax of the Cheetah template -language. - - diff --git a/docs/html/_sources/dev_guide/output.rst.txt b/docs/html/_sources/dev_guide/output.rst.txt deleted file mode 100644 index 55172d1..0000000 --- a/docs/html/_sources/dev_guide/output.rst.txt +++ /dev/null @@ -1,315 +0,0 @@ -Directives: Output -================== - -(output) - -#echo ------ - -(output.echo) - -The template: - -:: - - Here is my #echo ', '.join(['silly']*5) # example - -The output: - -:: - - Here is my silly, silly, silly, silly, silly example - -The generated code: - -:: - - write('Here is my ') - write(filter(', '.join(['silly']*5) )) - write(' example\n') - -#silent -------- - -(output.silent) - -The template: - -:: - - Here is my #silent ', '.join(['silly']*5) # example - -The output: - -:: - - Here is my example - -The generated code: - -:: - - write('Here is my ') - ', '.join(['silly']*5) - write(' example\n') - -OK, it's not quite covert because that extra space gives it away, -but it almost succeeds. - -#raw ----- - -(output.raw) - -The template: - -:: - - Text before raw. - #raw - Text in raw. $alligator. $croc.o['dile']. #set $a = $b + $c. - #end raw - Text after raw. - -The output: - -:: - - Text before raw. - Text in raw. $alligator. $croc.o['dile']. #set $a = $b + $c. - Text after raw. - -The generated code: - -:: - - write('''Text before raw. - Text in raw. $alligator. $croc.o['dile']. #set $a = $b + $c. - Text after raw. - ''') - -So we see that {#raw} is really like a quoting mechanism. It says -that anything inside it is ordinary text, and Cheetah joins a -{#raw} section with adjacent string literals rather than generating -a separate {write} call. - -#include --------- - -(output.include) - -The main template: - -:: - - #include "y.tmpl" - -The included template y.tmpl: - -:: - - Let's go $voom! - -The shell command and output: - -:: - - % voom="VOOM" x.py --env - Let's go VOOM! - -The generated code: - -:: - - write(self._includeCheetahSource("y.tmpl", trans=trans, includeFrom="file", - raw=0)) - -#include raw -~~~~~~~~~~~~ - -(output.include.raw) - -The main template: - -:: - - #include raw "y.tmpl" - -The shell command and output: - -:: - - % voom="VOOM" x.py --env - Let's go $voom! - -The generated code: - -:: - - write(self._includeCheetahSource("y.tmpl", trans=trans, includeFrom="fil - e", raw=1)) - -That last argument, {raw}, makes the difference. - -#include from a string or expression (eval) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -(output.include.expression) - -The template: - -:: - - #attr $y = "Let's go $voom!" - #include source=$y - #include raw source=$y - #include source="Bam! Bam!" - -The output: - -:: - - % voom="VOOM" x.py --env - Let's go VOOM!Let's go $voom!Bam! Bam! - -The generated code: - -:: - - write(self._includeCheetahSource(VFS(SL,"y",1), trans=trans, - includeFrom="str", raw=0, includeID="481020889808.74")) - write(self._includeCheetahSource(VFS(SL,"y",1), trans=trans, - includeFrom="str", raw=1, includeID="711020889808.75")) - write(self._includeCheetahSource("Bam! Bam!", trans=trans, - includeFrom="str", raw=0, includeID="1001020889808.75")) - -Later in the generated class: - -:: - - y = "Let's go $voom!" - -#slurp ------- - -(output.slurp) - -The template: - -:: - - #for $i in range(5) - $i - #end for - #for $i in range(5) - $i #slurp - #end for - Line after slurp. - -The output: - -:: - - 0 - 1 - 2 - 3 - 4 - 0 1 2 3 4 Line after slurp. - -The generated code: - -:: - - for i in range(5): - write(filter(i)) # generated from '$i' at line 2, col 1. - write('\n') - for i in range(5): - write(filter(i)) # generated from '$i' at line 5, col 1. - write(' ') - write('Line after slurp.\n') - -The space after each number is because of the space before {#slurp} -in the template definition. - -#filter -------- - -(output.filter) - -The template: - -:: - - #attr $ode = ">> Rubber Ducky, you're the one! You make bathtime so much fun! <<" - $ode - #filter WebSafe - $ode - #filter MaxLen - ${ode, maxlen=13} - #filter None - ${ode, maxlen=13} - -The output: - -:: - - >> Rubber Ducky, you're the one! You make bathtime so much fun! << - >> Rubber Ducky, you're the one! You make bathtime so much fun! << - >> Rubber Duc - >> Rubber Ducky, you're the one! You make bathtime so much fun! << - -The {WebSafe} filter escapes characters that have a special meaning -in HTML. The {MaxLen} filter chops off values at the specified -length. {#filter None} returns to the default filter, which ignores -the {maxlen} argument. - -The generated code: - -:: - - 1 write(filter(VFS(SL,"ode",1))) # generated from '$ode' at line 2, col 1. - 2 write('\n') - 3 filterName = 'WebSafe' - 4 if "WebSafe" in self._filters: - 5 filter = self._currentFilter = self._filters[filterName] - 6 else: - 7 filter = self._currentFilter = \ - 8 self._filters[filterName] = getattr(self._filtersLib, - filterName)(self).filter - 9 write(filter(VFS(SL,"ode",1))) # generated from '$ode' at line 4, col 1. - 10 write('\n') - 11 filterName = 'MaxLen' - 12 if "MaxLen" in self._filters: - 13 filter = self._currentFilter = self._filters[filterName] - 14 else: - 15 filter = self._currentFilter = \ - 16 self._filters[filterName] = getattr(self._filtersLib, - filterName)(self).filter - 17 write(filter(VFS(SL,"ode",1), maxlen=13)) # generated from - #'${ode, maxlen=13}' at line 6, col 1. - 18 write('\n') - 19 filter = self._initialFilter - 20 write(filter(VFS(SL,"ode",1), maxlen=13)) # generated from - #'${ode, maxlen=13}' at line 8, col 1. - 21 write('\n') - -As we've seen many times, Cheetah wraps all placeholder lookups in -a {filter} call. (This also applies to non-searchList lookups: -local, global and builtin variables.) The {filter} "function" is -actually an alias to the current filter object: - -:: - - filter = self._currentFilter - -as set at the top of the main method. Here in lines 3-8 and 11-16 -we see the filter being changed. Whoops, I lied. {filter} is not an -alias to the filter object itself but to that object's {.filter} -method. Line 19 switches back to the default filter. - -In line 17 we see the {maxlen} argument being passed as a keyword -argument to {filter} (not to {VFS}). In line 20 the same thing -happens although the default filter ignores the argument. - - diff --git a/docs/html/_sources/dev_guide/parser.rst.txt b/docs/html/_sources/dev_guide/parser.rst.txt deleted file mode 100644 index 802b43f..0000000 --- a/docs/html/_sources/dev_guide/parser.rst.txt +++ /dev/null @@ -1,9 +0,0 @@ -The parser -========== - -(parser) - -How templates are compiled: a walk through Parser.py's source. -(Also need to look at Lexer.py, but not too closely.) - - diff --git a/docs/html/_sources/dev_guide/parserInstructions.rst.txt b/docs/html/_sources/dev_guide/parserInstructions.rst.txt deleted file mode 100644 index 805df7c..0000000 --- a/docs/html/_sources/dev_guide/parserInstructions.rst.txt +++ /dev/null @@ -1,67 +0,0 @@ -Directives: Parser Instructions -=============================== - -(parserInstructions) - -#breakpoint ------------ - -(parserInstructions.breakpoint) - -The template: - -:: - - Text before breakpoint. - #breakpoint - Text after breakpoint. - #raise RuntimeError - -The output: - -:: - - Text before breakpoint. - -The generated code: - -:: - - write('Text before breakpoint.\n') - -Nothing after the breakpoint was compiled. - -#compiler ---------- - -(parserInstructions.compiler) - -The template: - -:: - - // Not a comment - #compiler commentStartToken = '//' - // A comment - #compiler reset - // Not a comment - -The output: - -:: - - // Not a comment - // Not a comment - -The generated code: - -:: - - write('// Not a comment\n') - # A comment - write('// Not a comment\n') - -So this didn't affect the generated program, it just affected how -the template definition was read. - - diff --git a/docs/html/_sources/dev_guide/patching.rst.txt b/docs/html/_sources/dev_guide/patching.rst.txt deleted file mode 100644 index 095d9a2..0000000 --- a/docs/html/_sources/dev_guide/patching.rst.txt +++ /dev/null @@ -1,149 +0,0 @@ -Patching Cheetah -================ - -(patching) - -How to commit changes to CVS or submit patches, how to run the test -suite. Describe distutils and how the regression tests work. - -File Requirements ------------------ - -(patching.fileRequirements) - -The code{Template} class contains not only the Cheetah -infrastructure, but also some convenience methods useful in all -templates. More methods may be added if it's generally agreed among -Cheetah developers that the method is sufficiently useful to all -types of templates, or at least to all types of HTML-output -templates. If a method is too long to fit into {Template} - -especially if it has helper methods - put it in a mixin class under -{Cheetah.Utils} and inherit it. - -Routines for a specific problem domain should be put under -{Cheetah.Tools}, so that it doesn't clutter the namespace unless -the user asks for it. - -Remember: {Cheetah.Utils} is for objects required by any part of -Cheetah's core. {Cheetah.Tools} is for completely optional objects. -It should always be possible to delete {Cheetah.Tools} without -breaking Cheetah's core services. - -If a core method needs to look up an attribute defined under -{Cheetah.Tools}, it should use {hasattr()} and gracefully provide a -default if the attribute does not exist (meaning the user has not -imported that subsystem). - -Testing Changes and Building Regression Tests ---------------------------------------------- - -(patching.testing) - -Cheetah ships with a regression test suite. To run the built-in -tests, execute at the shell prompt: - -:: - - cheetah test - -Before checking any changes in, run the tests and verify they all -pass. That way, users can check out the CVS version of Cheetah at -any time with a fairly high confidence that it will work. If you -fix a bug or add a feature, please take the time to add a test that -exploits the bug/feature. This will help in the future, to prevent -somebody else from breaking it again without realizing it. Users -can also run the test suite to verify all the features work on -their particular platform and computer. - -The general procedure for modifying Cheetah is as follows: - - -#. Write a simple Python program that exploits the bug/feature - you're working on. You can either write a regression test (see - below), or a separate program that writes the template output to - one file and put the expected output in another file; then you can - run {diff} on the two outputs. ({diff} is a utility included on all - Unix-like systems. It shows the differences between two files line - by line. A precompiled Windows version is at - http://gnuwin32.sourceforge.net/packages/diffutils.htm, and MacOS - sources at - http://perso.wanadoo.fr/gilles.depeyrot/DevTools\_en.html.) - -#. Make the change in your Cheetah CVS sandbox or in your installed - version of Cheetah. If you make it in the sandbox, you'll have to - run {python setup.py install} before testing it. If you make it in - the installed version, do { not} run the installer or it will - overwrite your changes! - -#. Run {cheetah test} to verify you didn't break anything. Then run - your little test program. - -#. Repeat steps 2-3 until everything is correct. - -#. Turn your little program into a regression test as described - below. - -#. When {cheetah test} runs cleanly with your regression test - included, update the {docs/news.rst} file and check in your changes. If - you made the changes in your installed copy of Cheetah, you'll have - to copy them back into the CVS sandbox first. If you added any - files that must be distributed, { be sure to} {cvs add} them before - committing. Otherwise Cheetah will run fine on your computer but - fail on anybody else's, and the test suite can't check for this. - -#. Announce the change on the cheetahtemplate-discuss list and - provide a tutorial if necessary. The documentation maintainer will - update the Users' Guide and Developers' Guide based on this message - and on the changelog. - - -If you add a directory to Cheetah, you have to mention it in -{setup.py} or it won't be installed. - -The tests are in the {Cheetah.Tests} package, aka the {src/Tests/} -directory of your CVS sandbox. Most of the tests are in -{SyntaxAndOutput.py}. You can either run all the tests or choose -which to run: - - Run all the tests. (Equivalent to {cheetah test}.) - - Run only the tests in that module. - - Run only the tests in the class {CGI} inside the module. The class - must be a direct or indirect subclass of - {unittest\_local\_copy.TestCase}. - - Run the tests in classes {CGI} and {Indenter}. - - Run only test {test1}, which is a method in the {CGI} class. - - -To make a SyntaxAndOutput test, first see if your test logically -fits into one of the existing classes. If so, simply add a method; -e.g., {test16}. The method should not require any arguments except -{self}, and should call {.verify(source, expectedOutput)}, where -the two arguments are a template definition string and a control -string. The tester will complain if the template output does not -match the control string. You have a wide variety of placeholder -variables to choose from, anything that's included in the -{defaultTestNameSpace} global dictionary. If that's not enough, add -items to the dictionary, but please keep it from being cluttered -with wordy esoteric items for a single test). - -If your test logically belongs in a separate class, create a -subclass of {OutputTest}. You do not need to do anything else; the -test suite will automatically find your class in the module. Having -a separate class allows you to define state variables needed by -your tests (see the {CGI} class) or override {.searchList()} (see -the {Indenter} class) to provide your own searchList. - -To modify another test module or create your own test module, -you'll have to study the existing modules, the -{unittest\_local\_copy} source, and the {unittest} documentation in -the Python Library Reference. Note that we are using a hacked -version of {unittest} to make a more convenient test structure for -Cheetah. The differences between {unittest\_local\_copy} and -Python's standard {unittest} are documented at the top of the -module. - - diff --git a/docs/html/_sources/dev_guide/placeholders.rst.txt b/docs/html/_sources/dev_guide/placeholders.rst.txt deleted file mode 100644 index 60aa0d2..0000000 --- a/docs/html/_sources/dev_guide/placeholders.rst.txt +++ /dev/null @@ -1,489 +0,0 @@ -Placeholders -============ - -(placeholders) - -Simple placeholders -------------------- - -(placeholders.simple) - -Let's add a few $placeholders to our template: - -:: - - >>> from Cheetah.Template import Template - >>> values = {'what': 'surreal', 'punctuation': '?'} - >>> t = Template("""\ - ... Hello, $what world$punctuation - ... One of Python's least-used functions is $xrange. - ... """, [values]) - >>> print t - Hello, surreal world? - One of Python's least-used functions is . - - >>> print t.generatedModuleCode() - 1 #!/usr/bin/env python - - 2 """ - 3 Autogenerated by CHEETAH: The Python-Powered Template Engine - 4 CHEETAH VERSION: 0.9.12 - 5 Generation time: Sun Apr 21 00:53:01 2002 - 6 """ - - 7 __CHEETAH_genTime__ = 'Sun Apr 21 00:53:01 2002' - 8 __CHEETAH_version__ = '0.9.12' - - 9 ################################################## - 10 ## DEPENDENCIES - - 11 import sys - 12 import os - 13 import os.path - 14 from os.path import getmtime, exists - 15 import time - 16 import types - 17 from Cheetah.Template import Template - 18 from Cheetah.DummyTransaction import DummyTransaction - 19 from Cheetah.NameMapper import NotFound, valueForName, - valueFromSearchList - 20 import Cheetah.Filters as Filters - 21 import Cheetah.ErrorCatchers as ErrorCatchers - - 22 ################################################## - 23 ## MODULE CONSTANTS - - 24 try: - 25 True, False - 26 except NameError: - 27 True, False = (1==1), (1==0) - - 28 ################################################## - 29 ## CLASSES - - 30 class GenTemplate(Template): - 31 """ - 32 - 33 Autogenerated by CHEETAH: The Python-Powered Template Engine - 34 """ - - 35 ################################################## - 36 ## GENERATED METHODS - - -:: - - 37 def __init__(self, *args, **KWs): - 38 """ - 39 - 40 """ - - 41 Template.__init__(self, *args, **KWs) - - 42 def respond(self, - 43 trans=None, - 44 dummyTrans=False, - 45 VFS=valueFromSearchList, - 46 VFN=valueForName, - 47 getmtime=getmtime, - 48 currentTime=time.time): - - - 49 """ - 50 This is the main method generated by Cheetah - 51 """ - - 52 if not trans: - 53 trans = DummyTransaction() - 54 dummyTrans = True - 55 write = trans.response().write - 56 SL = self._searchList - 57 filter = self._currentFilter - 58 globalSetVars = self._globalSetVars - 59 - 60 ######################################## - 61 ## START - generated method body - 62 - 63 write('Hello, ') - 64 write(filter(VFS(SL,"what",1))) # generated from '$what' at - # line 1, col 8. - 65 write(' world') - 66 write(filter(VFS(SL,"punctuation",1))) # generated from - # '$punctuation' at line 1, col 19. - 67 write("\nOne of Python's least-used methods is ") - 68 write(filter(xrange)) # generated from '$xrange' at line 2, - # col 39. - 69 write('.\n') - 70 - 71 ######################################## - 72 ## END - generated method body - 73 - 74 if dummyTrans: - 75 return trans.response().getvalue() - 76 else: - 77 return "" - -:: - - 78 - 79 ################################################## - 80 ## GENERATED ATTRIBUTES - - 81 __str__ = respond - 82 _mainCheetahMethod_for_GenTemplate= 'respond' - - 83 # CHEETAH was developed by Tavis Rudd, Chuck Esterbrook, Ian Bicking - # and Mike Orr; - 84 # with code, advice and input from many other volunteers. - 85 # For more information visit http://cheetahtemplate.org/ - - 86 ################################################## - 87 ## if run from command line: - 88 if __name__ == '__main__': - 89 GenTemplate().runAsMainProgram() - - -(Again, I have added line numbers and split the lines as in the -previous chapter.) - -This generated template module is different from the previous one -in several trivial respects and one important respect. Trivially, -{.\_filePath} and {.\_fileMtime} are not updated in -{.\_\_init\_\_}, so they inherit the value {None} from {Template}. -Also, that if-stanza in {.respond} that recompiles the template if -the source file changes is missing - because there is no source -file. So this module is several lines shorter than the other one. - -But the important way this module is different is that instead of -the one {write} call outputting a string literal, this module has a -series of {write} calls (lines 63-69) outputting successive chunks -of the template. Regular text has been translated into a string -literal, and placeholders into function calls. Every placeholder is -wrapped inside a {filter} call to apply the current output filter. -(The default output filter converts all objects to strings, and -{None} to {""}.) - -Placeholders referring to a Python builtin like {xrange} (line 68) -generate a bare variable name. Placeholders to be looked up in the -searchList have a nested function call; e.g., - -:: - - write(filter(VFS(SL,"what",1))) # generated from '$what' at line 1, col 8. - -{VFS}, remember, is a function imported from {Cheetah.NameMapper} -that looks up a value in a searchList. So we pass it the -searchList, the name to look up, and a boolean (1) indicating we -want autocalling. (It's {1} rather than {True} because it's -generated from an {and} expression, and that's what Python 2.2 -outputs for true {and} expressions.) - -Complex placeholders --------------------- - -(placeholders.complex) - -Placeholders can get far more complicated than that. This example -shows what kind of code the various NameMapper features produce. -The formulas are taken from Cheetah's test suite, in the -{Cheetah.Tests.SyntaxAndOutput.Placeholders} class. - -:: - - 1 placeholder: $aStr - 2 placeholders: $aStr $anInt - 2 placeholders, back-to-back: $aStr$anInt - 1 placeholder enclosed in {}: ${aStr} - 1 escaped placeholder: \$var - func placeholder - with (): $aFunc() - func placeholder - with (int): $aFunc(1234) - func placeholder - with (string): $aFunc('aoeu') - func placeholder - with ('''\nstring'\n'''): $aFunc('''\naoeu'\n''') - func placeholder - with (string*int): $aFunc('aoeu'*2) - func placeholder - with (int*float): $aFunc(2*2.0) - Python builtin values: $None $True $False - func placeholder - with ($arg=float): $aFunc($arg=4.0) - deeply nested argstring: $aFunc( $arg = $aMeth( $arg = $aFunc( 1 ) ) ): - function with None: $aFunc(None) - autocalling: $aFunc! $aFunc(). - nested autocalling: $aFunc($aFunc). - list subscription: $aList[0] - list slicing: $aList[:2] - list slicing and subcription combined: $aList[:2][0] - dict - NameMapper style: $aDict.one - dict - Python style: $aDict['one'] - dict combined with autocalled string method: $aDict.one.upper - dict combined with string method: $aDict.one.upper() - nested dict - NameMapper style: $aDict.nestedDict.two - nested dict - Python style: $aDict['nestedDict']['two'] - nested dict - alternating style: $aDict['nestedDict'].two - nested dict - NameMapper style + method: $aDict.nestedDict.two.upper - nested dict - alternating style + method: $aDict['nestedDict'].two.upper - nested dict - NameMapper style + method + slice: $aDict.nestedDict.two.upper[:4] - nested dict - Python style, variable key: $aDict[$anObj.meth('nestedDict')].two - object method: $anObj.meth1 - object method + complex slice: $anObj.meth1[0: ((4/4*2)*2)/$anObj.meth1(2) ] - very complex slice: $( anObj.meth1[0: ((4/4*2)*2)/$anObj.meth1(2) ] ) - $_('a call to gettext') - -We'll need a big program to set up the placeholder values. Here it -is: - -:: - - #!/usr/bin/env python - from ComplexExample import ComplexExample - - try: # Python >= 2.2.1 - True, False - except NameError: # Older Python - True, False = (1==1), (1==0) - - class DummyClass: - _called = False - def __str__(self): - return 'object' - - def meth(self, arg="arff"): - return str(arg) - - def meth1(self, arg="doo"): - return arg - - def meth2(self, arg1="a1", arg2="a2"): - return str(arg1) + str(arg2) - - def callIt(self, arg=1234): - self._called = True - self._callArg = arg - - def dummyFunc(arg="Scooby"): - return arg - - defaultTestNameSpace = { - 'aStr':'blarg', - 'anInt':1, - 'aFloat':1.5, - 'aList': ['item0','item1','item2'], - 'aDict': {'one':'item1', - 'two':'item2', - 'nestedDict':{1:'nestedItem1', - 'two':'nestedItem2' - }, - 'nestedFunc':dummyFunc, - }, - 'aFunc': dummyFunc, - 'anObj': DummyClass(), - 'aMeth': DummyClass().meth1, - '_': lambda x: 'translated ' + x - } - - print ComplexExample( searchList=[defaultTestNameSpace] ) - -Here's the output: - -:: - - 1 placeholder: blarg - 2 placeholders: blarg 1 - 2 placeholders, back-to-back: blarg1 - 1 placeholder enclosed in {}: blarg - 1 escaped placeholder: $var - func placeholder - with (): Scooby - func placeholder - with (int): 1234 - func placeholder - with (string): aoeu - func placeholder - with ('''\nstring'\n'''): - aoeu' - - func placeholder - with (string*int): aoeuaoeu - func placeholder - with (int*float): 4.0 - Python builtin values: 1 0 - func placeholder - with ($arg=float): 4.0 - deeply nested argstring: 1: - function with None: - autocalling: Scooby! Scooby. - nested autocalling: Scooby. - list subscription: item0 - list slicing: ['item0', 'item1'] - list slicing and subcription combined: item0 - dict - NameMapper style: item1 - dict - Python style: item1 - dict combined with autocalled string method: ITEM1 - dict combined with string method: ITEM1 - nested dict - NameMapper style: nestedItem2 - nested dict - Python style: nestedItem2 - nested dict - alternating style: nestedItem2 - nested dict - NameMapper style + method: NESTEDITEM2 - nested dict - alternating style + method: NESTEDITEM2 - nested dict - NameMapper style + method + slice: NEST - nested dict - Python style, variable key: nestedItem2 - object method: doo - object method + complex slice: do - very complex slice: do - translated a call to gettext - -And here - tada! - is the generated module. To save space, I've -included only the lines containing the {write} calls. The rest of -the module is the same as in the first example, chapter -pyModules.example. I've split some of the lines to make them fit on -the page. - -:: - - 1 write('1 placeholder: ') - 2 write(filter(VFS(SL,"aStr",1))) # generated from '$aStr' at line 1, col 16. - 3 write('\n2 placeholders: ') - 4 write(filter(VFS(SL,"aStr",1))) # generated from '$aStr' at line 2, col 17. - 5 write(' ') - 6 write(filter(VFS(SL,"anInt",1))) - # generated from '$anInt' at line 2, col 23. - 7 write('\n2 placeholders, back-to-back: ') - 8 write(filter(VFS(SL,"aStr",1))) # generated from '$aStr' at line 3, col 31. - 9 write(filter(VFS(SL,"anInt",1))) - # generated from '$anInt' at line 3, col 36. - 10 write('\n1 placeholder enclosed in {}: ') - 11 write(filter(VFS(SL,"aStr",1))) # generated from '${aStr}' at line 4, - # col 31. - 12 write('\n1 escaped placeholder: $var\nfunc placeholder - with (): ') - 13 write(filter(VFS(SL,"aFunc",0)())) # generated from '$aFunc()' at line 6, - # col 29. - 14 write('\nfunc placeholder - with (int): ') - 15 write(filter(VFS(SL,"aFunc",0)(1234))) # generated from '$aFunc(1234)' at - # line 7, col 32. - 16 write('\nfunc placeholder - with (string): ') - 17 write(filter(VFS(SL,"aFunc",0)('aoeu'))) # generated from "$aFunc('aoeu')" - # at line 8, col 35. - 18 write("\nfunc placeholder - with ('''\\nstring'\\n'''): ") - 19 write(filter(VFS(SL,"aFunc",0)('''\naoeu'\n'''))) # generated from - # "$aFunc('''\\naoeu'\\n''')" at line 9, col 46. - 20 write('\nfunc placeholder - with (string*int): ') - 21 write(filter(VFS(SL,"aFunc",0)('aoeu'*2))) # generated from - # "$aFunc('aoeu'*2)" at line 10, col 39. - 22 write('\nfunc placeholder - with (int*float): ') - 23 write(filter(VFS(SL,"aFunc",0)(2*2.0))) # generated from '$aFunc(2*2.0)' - # at line 11, col 38. - 24 write('\nPython builtin values: ') - 25 write(filter(None)) # generated from '$None' at line 12, col 24. - 26 write(' ') - 27 write(filter(True)) # generated from '$True' at line 12, col 30. - 28 write(' ') - 29 write(filter(False)) # generated from '$False' at line 12, col 36. - 30 write('\nfunc placeholder - with ($arg=float): ') - 31 write(filter(VFS(SL,"aFunc",0)(arg=4.0))) # generated from - # '$aFunc($arg=4.0)' at line 13, col 40. - 32 write('\ndeeply nested argstring: ') - 33 write(filter(VFS(SL,"aFunc",0)( - arg = VFS(SL,"aMeth",0)( arg = VFS(SL,"aFunc",0)( 1 ) ) ))) - # generated from '$aFunc( $arg = $aMeth( $arg = $aFunc( 1 ) ) )' - # at line 14, col 26. - 34 write(':\nfunction with None: ') - 35 write(filter(VFS(SL,"aFunc",0)(None))) # generated from '$aFunc(None)' at - # line 15, col 21. - 36 write('\nautocalling: ') - 37 write(filter(VFS(SL,"aFunc",1))) # generated from '$aFunc' at line 16, - # col 14. - 38 write('! ') - 39 write(filter(VFS(SL,"aFunc",0)())) # generated from '$aFunc()' at line 16, - # col 22. - -:: - - 40 write('.\nnested autocalling: ') - 41 write(filter(VFS(SL,"aFunc",0)(VFS(SL,"aFunc",1)))) # generated from - # '$aFunc($aFunc)' at line 17, col 21. - 42 write('.\nlist subscription: ') - 43 write(filter(VFS(SL,"aList",1)[0])) # generated from '$aList[0]' at line - # 18, col 20. - 44 write('\nlist slicing: ') - 45 write(filter(VFS(SL,"aList",1)[:2])) # generated from '$aList[:2]' at - # line 19, col 15. - 46 write('\nlist slicing and subcription combined: ') - 47 write(filter(VFS(SL,"aList",1)[:2][0])) # generated from '$aList[:2][0]' - # at line 20, col 40. - 48 write('\ndict - NameMapper style: ') - 49 write(filter(VFS(SL,"aDict.one",1))) # generated from '$aDict.one' at line - # 21, col 26. - 50 write('\ndict - Python style: ') - 51 write(filter(VFS(SL,"aDict",1)['one'])) # generated from "$aDict['one']" - # at line 22, col 22. - 52 write('\ndict combined with autocalled string method: ') - 53 write(filter(VFS(SL,"aDict.one.upper",1))) # generated from - # '$aDict.one.upper' at line 23, col 46. - 54 write('\ndict combined with string method: ') - 55 write(filter(VFN(VFS(SL,"aDict.one",1),"upper",0)())) # generated from - # '$aDict.one.upper()' at line 24, col 35. - 56 write('\nnested dict - NameMapper style: ') - 57 write(filter(VFS(SL,"aDict.nestedDict.two",1))) # generated from - # '$aDict.nestedDict.two' at line 25, col 33. - 58 write('\nnested dict - Python style: ') - 59 write(filter(VFS(SL,"aDict",1)['nestedDict']['two'])) # generated from - # "$aDict['nestedDict']['two']" at line 26, col 29. - 60 write('\nnested dict - alternating style: ') - 61 write(filter(VFN(VFS(SL,"aDict",1)['nestedDict'],"two",1))) # generated - # from "$aDict['nestedDict'].two" at line 27, col 34. - 62 write('\nnested dict - NameMapper style + method: ') - 63 write(filter(VFS(SL,"aDict.nestedDict.two.upper",1))) # generated from - # '$aDict.nestedDict.two.upper' at line 28, col 42. - 64 write('\nnested dict - alternating style + method: ') - 65 write(filter(VFN(VFS(SL,"aDict",1)['nestedDict'],"two.upper",1))) - # generated from "$aDict['nestedDict'].two.upper" at line 29, col 43. - 66 write('\nnested dict - NameMapper style + method + slice: ') - -:: - - 67 write(filter(VFN(VFS(SL,"aDict.nestedDict.two",1),"upper",1)[:4])) - # generated from '$aDict.nestedDict.two.upper[:4]' at line 30, col 50. - 68 write('\nnested dict - Python style, variable key: ') - 69 write(filter(VFN(VFS(SL,"aDict",1) - [VFN(VFS(SL,"anObj",1),"meth",0)('nestedDict')],"two",1))) - # generated from "$aDict[$anObj.meth('nestedDict')].two" at line 31, - # col 43. - 70 write('\nobject method: ') - 71 write(filter(VFS(SL,"anObj.meth1",1))) # generated from '$anObj.meth1' at - # line 32, col 16. - 72 write('\nobject method + complex slice: ') - 73 write(filter(VFN(VFS(SL,"anObj",1),"meth1",1) - [0: ((4/4*2)*2)/VFN(VFS(SL,"anObj",1),"meth1",0)(2) ])) - # generated from '$anObj.meth1[0: ((4/4*2)*2)/$anObj.meth1(2) ]' - # at line 33, col 32. - 74 write('\nvery complex slice: ') - 75 write(filter(VFN(VFS(SL,"anObj",1),"meth1",1) - [0: ((4/4*2)*2)/VFN(VFS(SL,"anObj",1),"meth1",0)(2) ] )) - # generated from '$( anObj.meth1[0: ((4/4*2)*2)/$anObj.meth1(2) ] )' - # at line 34, col 21. - 76 if False: - 77 _('foo') - 78 write(filter(VFS(SL,"_",0)("a call to gettext"))) - # generated from "$_('a call to gettext')" - # at line 35, col 1. - 79 write('\n') - -For each placeholder lookup, the the innermost level of nesting is -a {VFS} call, which looks up the first (leftmost) placeholder -component in the searchList. This is wrapped by zero or more {VFN} -calls, which perform Universal Dotted Notation lookup on the next -dotted component of the placeholder, looking for an attribute or -key by that name within the previous object (not in the -searchList). Autocalling is performed by {VFS} and {VFN}: that's -the reason for their third argument. - -Explicit function/method arguments, subscripts and keys (which are -all expressions) are left unchanged, besides expanding any embedded -$placeholders in them. This means they must result in valid Python -expressions, following the standard Python quoting rules. - -Built-in Python values ({None}, {True} and {False}) are converted -to {filter(None)}, etc. They use normal Python variable lookup -rather than {VFS}. (Cheetah emulates {True} and {False} using -global variables for Python < 2.2.1, when they weren't builtins -yet.) - -Notice the last line is a call to {\_} (i.e. {gettext}) which is -used for internationalization (see -http://docs.python.org/lib/module-gettext.html). The code is -converted normally, but an {if False} block is used so that gettext -can successfully mark the string for translation when parsing the -generated Python. Otherwise, the NameMapper syntax would get in the -way of this. - - diff --git a/docs/html/_sources/dev_guide/pyModules.rst.txt b/docs/html/_sources/dev_guide/pyModules.rst.txt deleted file mode 100644 index 86c95dc..0000000 --- a/docs/html/_sources/dev_guide/pyModules.rst.txt +++ /dev/null @@ -1,252 +0,0 @@ -.py Template Modules -==================== - -(pyModules) - -This chapter examines the structure of a .py template module. The -following few chapters will then show how each placeholder and -directive affects the generated Python code. - -An example ----------- - -(pyModules.example) - -Our first template follows a long noble tradition in computer -tutorials. It produces a familiar, friendly greeting. Here's the -template: - -:: - - Hello, world! - -... the output: - -:: - - Hello, world! - -... and the .py template module cheetah-compile produced, with line -numbers added: - -:: - - 1 #!/usr/bin/env python - - 2 """ - 3 Autogenerated by CHEETAH: The Python-Powered Template Engine - 4 CHEETAH VERSION: 0.9.12 - 5 Generation time: Sat Apr 20 14:27:47 2002 - 6 Source file: x.tmpl - 7 Source file last modified: Wed Apr 17 22:10:59 2002 - 8 """ - - 9 __CHEETAH_genTime__ = 'Sat Apr 20 14:27:47 2002' - 10 __CHEETAH_src__ = 'x.tmpl' - 11 __CHEETAH_version__ = '0.9.12' - - 12 ################################################## - 13 ## DEPENDENCIES - - 14 import sys - 15 import os - 16 import os.path - 17 from os.path import getmtime, exists - 18 import time - 19 import types - 20 from Cheetah.Template import Template - 21 from Cheetah.DummyTransaction import DummyTransaction - 22 from Cheetah.NameMapper import NotFound, valueForName, - valueFromSearchList - 23 import Cheetah.Filters as Filters - 24 import Cheetah.ErrorCatchers as ErrorCatchers - - 25 ################################################## - 26 ## MODULE CONSTANTS - - 27 try: - 28 True, False - 29 except NameError: - 30 True, False = (1==1), (1==0) - - 31 ################################################## - 32 ## CLASSES - - 33 class x(Template): - 34 """ - 35 - 36 Autogenerated by CHEETAH: The Python-Powered Template Engine - 37 """ - -:: - - 38 ################################################## - 39 ## GENERATED METHODS - - - 40 def __init__(self, *args, **KWs): - 41 """ - 42 - 43 """ - - 44 Template.__init__(self, *args, **KWs) - 45 self._filePath = 'x.tmpl' - 46 self._fileMtime = 1019106659 - - 47 def respond(self, - 48 trans=None, - 49 dummyTrans=False, - 50 VFS=valueFromSearchList, - 51 VFN=valueForName, - 52 getmtime=getmtime, - 53 currentTime=time.time): - - - 54 """ - 55 This is the main method generated by Cheetah - 56 """ - - 57 if not trans: - 58 trans = DummyTransaction() - 59 dummyTrans = True - 60 write = trans.response().write - 61 SL = self._searchList - 62 filter = self._currentFilter - 63 globalSetVars = self._globalSetVars - 64 - 65 ######################################## - 66 ## START - generated method body - 67 - 68 if exists(self._filePath) and getmtime(self._filePath) > \ - self._fileMtime: - 69 self.compile(file=self._filePath) - 70 write(getattr(self, self._mainCheetahMethod_for_x) - (trans=trans)) - 71 if dummyTrans: - 72 return trans.response().getvalue() - 73 else: - 74 return "" - 75 write('Hello, world!\n') - 76 - 77 ######################################## - 78 ## END - generated method body - 79 - 80 if dummyTrans: - 81 return trans.response().getvalue() - 82 else: - 83 return "" - -:: - - 84 - 85 ################################################## - 86 ## GENERATED ATTRIBUTES - - - 87 __str__ = respond - - 88 _mainCheetahMethod_for_x= 'respond' - - - 89 # CHEETAH was developed by Tavis Rudd, Chuck Esterbrook, Ian Bicking - # and Mike Orr; - 90 # with code, advice and input from many other volunteers. - 91 # For more information visit http://cheetahtemplate.org/ - - 92 ################################################## - 93 ## if run from command line: - 94 if __name__ == '__main__': - 95 x().runAsMainProgram() - - -(I added the line numbers for this Guide, and split a few lines to -fit the page width. The continuation lines don't have line numbers, -and I added indentation, backslashes and '#' as necessary to make -the result a valid Python program.) - -The examples were generated from CVS versions of Cheetah between -0.9.12 and 0.9.14. - -A walk through the example --------------------------- - -(pyModules.walk) - -Lines 20-24 are the Cheetah-specific imports. Line 33 introduces -our generated class, {x}, a subclass of {Template}. It's called x -because the source file was x.tmpl. - -Lines 40-46 are the {.\_\_init\_\_} method called when the template -is instantiated or used as a Webware servlet, or when the module is -run as a standalone program. We can see it calling its superclass -constructor and setting {.\_filePath} and {.\_fileMtime} to the -filename and modification time (in Unix ticks) of the source .tmpl -file. - -Lines 47-84 are the main method {.respond}, the one that fills the -template. Normally you call it without arguments, but Webware calls -it with a Webware {Transaction} object representing the current -request. Lines 57-59 set up the {trans} variable. If a real or -dummy transaction is passed in, the method uses it. Otherwise (if -the {trans} argument is {None}), the method creates a -{DummyTransaction} instance. {dummyTrans} is a flag that just tells -whether a dummy transaction is in effect; it'll be used at the end -of the method. - -The other four {.respond} arguments aren't anything you'd ever want -to pass in; they exist solely to speed up access to these -frequently-used global functions. This is a standard Python trick -described in question 4.7 of the Python FAQ -(http://www.python.org/cgi-bin/faqw.py). {VFS} and {VFN} are the -functions that give your template the benefits of NameMapper -lookup, such as the ability to use the searchList. - -Line 60 initializes the {write} variable. This important variable -is discussed below. - -Lines 60-63 initialize a few more local variables. {SL} is the -searchList. {filter} is the current output filter. {globalSetVars} -are the variables that have been defined with {#set global}. - -The comments at lines 65 and 78 delimit the start and end of the -code that varies with each template. The code outside this region -is identical in all template modules. That's not quite true - -{#import} for instance generates additional {import} statements at -the top of the module - but it's true enough for the most part. - -Lines 68-74 exist only if the template source was a named file -rather than a string or file object. The stanza recompiles the -template if the source file has changed. Lines 70-74 seem to be -redundant with 75-83: both fill the template and send the output. -The reason the first set of lines exists is because the second set -may become invalid when the template is recompiled. (This is for { -re} compilation only. The initial compilation happened in the -{.\_\_init\_\_} method if the template wasn't precompiled.) - -Line 75 is the most interesting line in this module. It's a direct -translation of what we put in the template definition, -"Hello, world!" Here the content is a single string literal. -{write} looks like an ordinary function call, but remember that -line 60 made it an alias to {trans.response().write}, a method in -the transaction. The next few chapters describe how the different -placeholders and directives influence this portion of the generated -class. - -Lines 80-83 finish the template filling. If {trans} is a real -Webware transaction, {write} has already sent the output to Webware -for handling, so we return {""}. If {trans} is a dummy transaction, -{write} has been accumulating the output in a Python {StringIO} -object rather than sending it anywhere, so we have to return it. - -Line 83 is the end of the {.respond} method. - -Line 87 makes code{.\_\_str\_\_} an alias for the main method, so -that you can {print} it or apply {str} to it and it will fill the -template. Line 88 gives the name of the main method, because -sometimes it's not {.respond}. - -Lines 94-95 allow the module to be run directly as a script. -Essentially, they process the command-line arguments and them make -the template fill itself. - - diff --git a/docs/html/_sources/dev_guide/safeDelegation.rst.txt b/docs/html/_sources/dev_guide/safeDelegation.rst.txt deleted file mode 100644 index 87f3dc1..0000000 --- a/docs/html/_sources/dev_guide/safeDelegation.rst.txt +++ /dev/null @@ -1,40 +0,0 @@ -Safe Delegation -=============== - -(safeDelegation) - -Safe delegation, as provided by Zope and Allaire's Spectra, is not -implemented in Cheetah. The core aim has been to help developers -and template maintainers get things done, without throwing -unnecessary complications in their way. So you should give write -access to your templates only to those whom you trust. However, -several hooks have been built into Cheetah so that safe delegation -can be implemented at a later date. - -It should be possible to implement safe delegation via a future -configuration Setting {safeDelegationLevel} (0=none, 1=semi-secure, -2-alcatraz). This is not implemented but the steps are listed here -in case somebody wants to try them out and test them. - -Of course, you would also need to benchmark your code and verify it -does not impact performance when safe delegation is off, and -impacts it only modestly when it is on." All necessary changes can -be made at compile time, so there should be no performance impact -when filling the same TO multiple times. - - -#. Only give untrusted developers access to the .tmpl files. - (Verifying what this means. Why can't trusted developers access - them?) - -#. Disable the {#attr} directive and maybe the {#set} directive. - -#. Use Cheetah's directive validation hooks to disallow references - to {self}, etc (e.g. {#if $steal(self.thePrivateVar)} ) - -#. Implement a validator for the $placeholders and use it to - disallow '\_\_' in $placeholders so that tricks like - {$obj.\_\_class\_\_.\_\_dict\_\_} are not possible. - - - diff --git a/docs/html/_sources/dev_guide/template.rst.txt b/docs/html/_sources/dev_guide/template.rst.txt deleted file mode 100644 index 8dd23d9..0000000 --- a/docs/html/_sources/dev_guide/template.rst.txt +++ /dev/null @@ -1,11 +0,0 @@ -Template -======== - -(template) - -This chapter will mainly walk through the {Cheetah.Template} -constructor and not at what point the template is compiled. - -(Also need to look at Transaction,py and Servlet.py.) - - diff --git a/docs/html/_sources/developers.rst.txt b/docs/html/_sources/developers.rst.txt deleted file mode 100644 index 7cf96e8..0000000 --- a/docs/html/_sources/developers.rst.txt +++ /dev/null @@ -1,53 +0,0 @@ -Contributing to Cheetah -======================= - -Cheetah is the work of many volunteers. If you use Cheetah, share your -experiences, tricks, customizations, and frustrations. Please visit -https://github.com/CheetahTemplate3/cheetah3 and file bug reports, feature -requests or pull requests. - - -Getting the Code ----------------- -The Cheetah source code is stored in a central **Git** repository -hosted primarily by `GitHub `_. The primary Git -repository can be found `here `_. - - -Development Process -------------------- -The typical development workflow for Cheetah revolves around -two primary branches **maint** and **next**. The **next** branch is where development -planned for the next release of Cheetah is. The **maint** branch -on the otherhand is where backported fixes and patches will be applied for -the current release of Cheetah will go, it's common for a patch -to be applied to maint and next at the same time. - -Anyone and everyone is encouraged to submit patches at any time, but as far -as bugs or feature requests go, we try to file those *first* in the `Cheetah3 Bug Tracker `_ -and then they can be organized into particular releases as is necessary. - -In addition to the bug tracker, Cheetah uses Travis CI for automating builds -and test runs (see: `Cheetah at Travis -`_). - -Prior to the tarballing of a release, **all** tests must be passing before the -**next** branch is merged down to the Git **master** branch where the release -tarball will actually be created from. - - -Filing Bugs ------------ -No software is perfect, and unfortunately no bug report is either. If you've -found yourself faced with a bug in Cheetah, or just have a good idea for a -new feature, we kindly ask that you create an issue in the `Cheetah3 Bug Tracker `_. - -Some tips for filing a *useful* bug report, try to include the following: - -* A description of what you were trying to do, and what happened (i.e. reproduction steps), the more code you can include the better. -* Any and all tracebacks or compiler errors -* The version of Cheetah you're using -* The version of Python you're using -* The operating system you're running Cheetah on -* Any other pieces of information you might think are relevant - diff --git a/docs/html/_sources/documentation.rst.txt b/docs/html/_sources/documentation.rst.txt deleted file mode 100644 index af5cc44..0000000 --- a/docs/html/_sources/documentation.rst.txt +++ /dev/null @@ -1,10 +0,0 @@ -Cheetah Recipes -================== - -.. toctree:: - :maxdepth: 2 - - recipes/inheritance.rst - recipes/precompiled.rst - recipes/staticmethod.rst - recipes/writing_a_recipe.rst diff --git a/docs/html/_sources/download.rst.txt b/docs/html/_sources/download.rst.txt deleted file mode 100644 index dc73d33..0000000 --- a/docs/html/_sources/download.rst.txt +++ /dev/null @@ -1,14 +0,0 @@ -Downloading Cheetah -=================== - -You can download wheels, eggs and tarballs of Cheetah from the `Python -Package Index `_. - -You can keep up to date with release candidates or other downloads of -Cheetah by visiting the `CheetahTemplate GitHub page -`_ - -**Note to Windows users:** You should install the compiled version of -Cheetah's NameMapper. It is dramatically faster than the pure Python -version. Installing from wheels from PyPI is the simplest way to get the -precompiled NameMapper extension. diff --git a/docs/html/_sources/index.rst.txt b/docs/html/_sources/index.rst.txt deleted file mode 100644 index 2f18cb6..0000000 --- a/docs/html/_sources/index.rst.txt +++ /dev/null @@ -1,89 +0,0 @@ -.. Cheetah Template Engine documentation master file, created by - sphinx-quickstart on Sun May 31 22:23:43 2009. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Cheetah3, the Python-Powered Template Engine -============================================ - -Introduction ------------- -Cheetah3 is a free (BSD-style) and `open source -`_ template engine and -code-generation tool written in `Python `_. Cheetah can be -used unto itself, or incorporated with other technologies and stacks regardless -of whether they're written in Python or not. - -At its core, Cheetah is a domain-specific language for markup generation and -templating which allows for full integration with existing Python code but also -offers extensions to traditional Python syntax to allow for easier text-generation. - -It's a fork of the `original `_ -CheetahTemplate library. - -Talk Cheetah -^^^^^^^^^^^^ -You can get involved and talk with Cheetah developers on the `Cheetah3 issue -tracker `_. - -Contents -^^^^^^^^^ - -.. toctree:: - :maxdepth: 2 - - authors.rst - news.rst - developers.rst - download.rst - users_guide/index.rst - documentation.rst - roadmap.rst - dev_guide/index.rst - chep.rst - - -Cheetah in a nutshell ---------------------- -Below is a simple example of some Cheetah code, as you can see it's practically -Python. You can import, inherit and define methods just like in a regular Python -module, since that's what your Cheetah templates are compiled to :) :: - - #from Cheetah.Template import Template - #extends Template - - #set $people = [{'name' : 'Tom', 'mood' : 'Happy'}, {'name' : 'Dick', - 'mood' : 'Sad'}, {'name' : 'Harry', 'mood' : 'Hairy'}] - - How are you feeling? -

    - #for $person in $people -
  • - $person['name'] is $person['mood'] -
  • - #end for -
- - -Why Cheetah? ------------- - -* Cheetah is supported by every major Python web framework. -* It is fully documented and is supported by an active user community. -* It can output/generate any text-based format. -* Cheetah compiles templates into optimized, yet readable, Python code. -* It blends the power and flexibility of Python with a simple template language that non-programmers can understand. -* It gives template authors full access to any Python data structure, module, function, object, or method in their templates. Meanwhile, it provides a way for administrators to selectively restrict access to Python when needed. -* Cheetah makes code reuse easy by providing an object-oriented interface to templates that is accessible from Python code or other Cheetah templates. One template can subclass another and selectively reimplement sections of it. Cheetah templates can be subclasses of any Python class and vice-versa. -* It provides a simple, yet powerful, caching mechanism that can dramatically improve the performance of a dynamic website. -* It encourages clean separation of content, graphic design, and program code. This leads to highly modular, flexible, and reusable site architectures, shorter development time, and HTML and program code that is easier to understand and maintain. It is particularly well suited for team efforts. -* Cheetah can be used to generate static html via its command-line tool. - - -Indices and tables ------------------- - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` - diff --git a/docs/html/_sources/news.rst.txt b/docs/html/_sources/news.rst.txt deleted file mode 100644 index 2a6ff8c..0000000 --- a/docs/html/_sources/news.rst.txt +++ /dev/null @@ -1,66 +0,0 @@ -News -==== - -Development (master) --------------------- - -3.1.0 (2018-03-03) ------------------- - -Features: - - - Fix Cheetah to work with PyPy. Pull request by Mathias Stearn. - -Minor features: - - - Code cleanup: fix code style to satisfy flake8 linter. - -Documentation: - - - Rename www directory to docs. - -Tests: - - - Run pypy tests at AppVeyor. - - Use remove-old-files.py from ppu to cleanup pip cache - at Travis and AppVeyor. - - -3.0.1 (2018-02-27) ------------------- - -Bug fixes: - - - Fix a minor bug in Compiler. - - -3.0.0 (2017-05-07) ------------------- - -Major features: - - - !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!! - - Stop supporting Python older than 2.7. - - Update code to work with Python 3.3+. Tested with 3.3, 3.4, 3.5 and 3.6. - -Minor features: - - - Use '/usr/bin/env python' for scripts; - this allows eggs/wheels to be installed into virtual environments. - -Bug fixes: - - - Fix a bug in multiple inheritance (#extend Parent1, Parent2). - Pull request by Jonathan Ross Rogers. - - Fix bugs in pure-python NameMapper.py. Bugs reported by Noah Ingham, - patches by Adam Karpierz, tests by Oleg Broytman. - -Tests: - - - Run tests at Travis (Linux) and AppVeyor (w32) with Python 2.7, 3.3, 3.4, - 3.5 and 3.6; x86 and x64. - - Fix a problem in Unicode tests - cleanup temporary files. - -`Older news`_ - -.. _`Older news`: news2.html diff --git a/docs/html/_sources/news2.rst.txt b/docs/html/_sources/news2.rst.txt deleted file mode 100644 index d295478..0000000 --- a/docs/html/_sources/news2.rst.txt +++ /dev/null @@ -1,1701 +0,0 @@ -2.4.2 (February 8th, 2010) - - Fix issue where subclasses of Template failed to pick up attributes in the - searchlist - - Remove old/outdated bundled memcached python client - - Allow for #encoding directives to exist after a comment (i.e. not the first - line in a module) - - Remove support for WebWare servlets (which caused significant performance - slowdowns on Mac OS X) - - Old/stale code pruned in preparation for Python 3 support - -2.4.1 (December 19th, 2009) - - --quiet flag added to `cheetah` to silence printing to stdout (abbeyj) - - Refactoring to minimize the amount of forked code for Python3 (rtyler) - - Template.compile() will no longer create class names with numerous leading - underscores (rtyler; reported by Kirill Uhanov) - - DirectiveAnalyzer (cheetah-analyze script) added to report directive usage in templates (rtyler) - - Older LaTeX docs converted to rst for Sphinx (rtyler) - - Prevent #raw blocks from evaluating \$-placeholders and escaped strings (karmix0) - - New tests added to verify PSP behavior and other untested internals (rtyler) - -2.4.0 (October 24th, 2009) - - Fix a major performance regression in Template.__init__() - - More graceful handling of unicode when calling .respond() to render a template - - Minor code updates - - Update the default filter (thanks mikeb!) - -2.3.0 (October 24th, 2009) (loosely equivalent to 2.4.0) - - Fix a major performance regression in Template.__init__() - - More graceful handling of unicode when calling .respond() to render a template - - Minor code updates - - Update the default filter (thanks mikeb!) - -2.2.2 (September 10th, 2009) - - Prevent _namemapper.c from segfaulting when PyImport_ImportModule fails for some reason (Bogdano Arendartchuk ) - - 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 - - Improvements to setup.py to support building for Windows (thanks abbeyj!) - - Improvements to C-based NameMapper for Windows - - Fixes for a swath of unit tests on Windows - - Re-enabling the EOL tests (whoops) - - Fix for unicode/utf-8 dynamic compilation error (thanks mikeb!) (Test.Unicode.JBQ_UTF8_Test8) - - 0000010: [Templates] Failure to execute templates on Google App Engine (rtyler) - - 0000026: [Compiler] Support multiple inheritance (rtyler) - - -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 ) - - 0000011: [Templates] Calling a function with arguments calls the function with None (rtyler) - - 0000015: [Tests] Resolve test failures in 'next' branch (rtyler) - - 0000019: [Templates] Properly warn when joining unicode and non-unicode objects in DummyTransaction (rtyler) - -2.1.2 (May 5, 2009) - - 0000006: [Templates] Support @staticmethod and @classmethod (rtyler) - -2.1.1 (April 16, 2009) - - Support __eq__() and __ne__() the way you might expect in src/Tools/RecursiveNull (patch suggested by Peter Warasin ) - - Applied patch to avoid hitting the filesystem to get the file modification time everytime a #include directive is processed (Jean-Baptiste Quenot ) - - Applied patch to fix some annoying cases when Cheetah writes to stderr instead of propagating the exception (Jean-Baptiste Quenot ) - - Added KDE editor support - - Applied patch to correct importHook behavior on Python 2.6 (reported/patched by Toshio Ernie Kuratomi ) - - Correct unicode issue when calling/embedding unicode templates inside of other templtes (testcase Tests.Unicode.JPQ_UTF8_Test3. reported by Jean-Baptiste Quenot ) - - Added --shbang option (e.g. "cheetah compile --shbang '#!/usr/bin/python2.6' ") - - Removed dependency on optik OptionParser in favor of builtin Python optparse module - - Introduction of the #transform directive for whole-document filtering - - Introduction of Cheetah.contrib.markdown and Cheetah.Filters.Markdown for outputting a markdown processed template (meant for #transform) - - Cheetah.Filters.CodeHighlighter, pygments-based code highlighting filter for use with #transform - - Addition of "useLegacyImportMode" compiler setting (defaulted to True) to allow for older (read: broken) import behavior - -2.1.0.1 (March 27, 2009) - - Fix inline import issue introduced in v2.1.0 - -2.1.0 (March 16, 2009) - - Quiet DeprecationWarnings being printed to stderr when using Cheetah on Python 2.6 and up. Patch suggested by Satoru SATOH - - Apply patch to support parallel compilation of templates courtesy of Evan Klitzke - - Corrected issue when __getattr__ calls on searchList objects raise exceptions (tyler@slide.com) - - make autocalling in valueForName correctly ignore newstyle classes and instances - that are callable, as it does for oldstyle classes and instances. Patch - from lucas@endian.com - [TR] - - made it possible to chain multiple decorators to a method #def [TR with - patch from Graham Dennis] - - fixed a bug in _eatMultiLineDef that Graham Dennis reported. [TR] - - fixed 'module.__init__() argument 1 must be string, not unicode' bug in - Template.py reported by Erwin Ambrosch [TR] - -2.0.1 (Nov 16, 2007) - - fixed a deadlock Christoph Zwerschke found in Cheetah.ImportHooks. - [TR] - -2.0 (Oct 12, 2007) - !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!! - - - fixed exception handling issue in the C implemenation of NameMapper - [patch from Eric Huss] - - - fixed filtering of #included subtemplates - [patch from Brian Bird] - - See the release notes from 2.0b1-5 and 2.0rc1-8 for other changes since - Cheetah 1.0. - - -2.0rc8 (April 11, 2007) - !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!! - Core Changes: [TR] - - - added a '#unicode ' directive to indicate that the output of the - template should be a unicode string even if the template source is a - normal byte string. - - - #unicode and #encoding are mutually exclusive. Use one or the other. - - #unicode must be on a line by itself. - - Strings in embedded code must be explictly marked as unicode if they - contain non-ascii chars:: - - #unicode latin-1 - \$f(u"") ## right - \$f("") ## wrong - - However, this works fine:: - - #unicode latin-1 - blah blah blah blah - - - fixed several unicode bugs in the compiler. - - fixed some unicode issues in the standard filters. - - fixed a few minor bugs in code that never gets called. Thanks to - Alejandro Dubrovsky for pointing them out. - - make RawOrEncodedUnicode the baseclass of all filters and remove some - unused/redudant filters - - added new compiler setting 'addTimestampsToCompilerOutput'. See Brian - Bird's post about it. He stores his cheetah generated .py files in - subversion and needed to disable the timestamp code so svn wouldn't care - when he recompiles those .py modules. - - added the #super directive, which calls the method from the parent class - which has the same as the current #def or #block method:: - - #def foo - ... child output - #super ## includes output of super(, self).foo() - ... child output - #end def - - #def bar(arg) - ... child output - #super(arg) ## includes output of super(, self).bar(arg) - ... child output - #end def - - added some unit tests for the new directives - - -2.0rc7 (July 4, 2006) - !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!! - Core Changes: [TR] - - - extended the #implements directive so an arguments list can be declared in - the same fashion as #def and #block. - - made the parser raise ParseError when \$\*placeholder, \$\*5\*placeholder, - \$(placeholder), etc. are found within expressions. They are only valid in - top-level text. - - tweaked the parser so it's possible to place a comment on the same line as - a directive without needing to explicitly close the directive first. This - works regardless of whether or not you added a colon:: - - self.verify("#if 1:\\n\$aStr\\n#end if\\n", - "blarg\\n") - - self.verify("#if 1: \\n\$aStr\\n#end if\\n", - "blarg\\n") - - self.verify("#if 1: ##comment \\n\$aStr\\n#end if\\n", - "blarg\\n") - - self.verify("#if 1 ##comment \\n\$aStr\\n#end if\\n", - "blarg\\n") - - Previously, that last test would have required an extra # to close the #if - directive before the comment directive started:: - - self.verify("#if 1 ###comment \\n\$aStr\\n#end if\\n", - "blarg\\n") - - Code that makes use of explicit directive close tokens immediately followed by - another directive will still work as expected: - #if test##for i in range(10)# foo \$i#end for##end if - - - safer handling of the baseclass arg to Template.compile(). It now does - the right thing if the user passes in an instance rather than a class. - - ImportHooks: [TR] - - - made it possible to specify a list of template filename extentions that are - looped through while searching for template modules. E.g.:: - - import Cheetah.ImportHooks - Cheetah.ImportHooks.install(templateFileExtensions=('.tmpl','.cheetah')) - - Core changes by MO: - - - Filters are now new-style classes. - - WebSafe and the other optional filters in Filters.py now use - RawOrEncodedUnicode instead of Filter as a base class. This allows them - to work with Unicode values containing non-ASCII characters. - - User-written custom filters should inherit from RawOrEncodedUnicode - and call the superclass .filter() instead of str(). str() as of - Python 2.4.2 still converts Unicode to string using ASCII codec, - which raises UnicodeEncodeError if it contains non-ASCII characters. - -2.0rc6 (Feb 4, 2006) - !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!! - Core Changes: [TR] - - - added a Cheetah version dependency check that raises an assertion if a - template was compiled with a previous version of Cheetah whose templates - must be recompiled. - - made the Cheetah compilation metadata accessible via class attributes in - addition to module globals - - major improvement to exception reporting in cases where bad Python syntax - slips past the Cheetah parser:: - - File "/usr/lib/python2.4/site-packages/Cheetah/Template.py", line 792, in compile - raise parseError - Cheetah.Parser.ParseError: - - Error in the Python code which Cheetah generated for this template: - ================================================================================ - - invalid syntax (DynamicallyCompiledCheetahTemplate.py, line 86) - - Line|Python Code - ----|------------------------------------------------------------- - 84 | - 85 | write('\\n\\n') - 86 | for i an range(10): # generated from line 4, col 1 - ^ - 87 | _v = i # '\$i' on line 5, col 3 - 88 | if _v is not None: write(_filter(_v, rawExpr='\$i')) # from line 5, col 3. - 89 | write('\\n') - - ================================================================================ - - Here is the corresponding Cheetah code: - - Line 4, column 1 - - Line|Cheetah Code - ----|------------------------------------------------------------- - 2 |#compiler useNameMapper=False - 3 | - 4 |#for i an range(10) - ^ - 5 | \$i - 6 |#end for - 7 | - -2.0rc5 (Feb 3, 2006) - !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!! - Core Changes: [TR] - - - fixed a memory leak in Template.compile(), reported by Andrea Arcangeli - - simplified concurrency locking and compile caching in Template.compile() - - The command line tool (CheetahWrapper.py): - - - added new option --settings for supplying compiler settings - - added new option --templateAPIClass to replace the environment var - CHEETAH_TEMPLATE_CLASS lookup I added in 2.0b1 - -2.0rc4 (Jan 31, 2006) - !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!! - Core Changes: [TR] - - - fixed a typo-bug in the compile hashing code in Template.compile() - - improved the macros framework and made it possible to implement macros in - Python code so they can be shared between templates - - more work on the #i18n directive. It's now a macro directive. - - added new Cheetah.Macros package - - more tests - -2.0rc3 (Jan 29, 2006) - !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!! - Core Changes: [TR] - - - added short-form single line versions of all directives that have an #end - tag, except for #errorCatcher:: - - #if, #else, #elif, #unless, - #for, #while, #repeat, - #try, #except, #finally, - #cache, #raw - #call, #capture - - The #def and #block directives already had single-line versions:: - - #if cond: foo - #elif cond2: bar - #else: blarg - - #for i, val in enumerate(vals): \$i-\$val - - Note that if you accidentally leave a colon at the end of one of these - directives but nothing else follows it, aside from whitespace, the parser - will treat it as a normal multi-line directive. - - The first leading space after the colon is discarded. Any additional - spaces will be included in the output. - - Also note, if you use the short form versions of #if/#else/#elif you must - it for all three. The following is not valid:: - - #if cond: foo - #elif cond2 - bar - #else: blarg - - - added support for \$!silentModePlaceholders. This is the same as quiet - mode in Velocity: http://jakarta.apache.org/velocity/docs/user-guide.html#Quiet%20Reference%20Notation - - added support for function/method @decorators. It also works with blocks. - As in vanilla Python, the @decorator statement must be followed with a - function/method definition (i.e. #def or #block):: - - #from xxx import aDecorator - ... - ... - #@aDecorator - #def func - foo - #end def - - #@aDecorator - #def singleLineShortFormfunc: foo - - #@aDecorator - #block func2 - bar - #end block - - - added a new callback hook 'handlerForExtendsDirective' to the compiler settings. It - can be used to customize the handling of #extends directives. The - callback can dynamically add import statements or rewrite the baseclass' - name if needed:: - - baseClassName = handler(compiler, baseClassName) - - See the discussion on the mailing list on Jan 25th for more details. - - changed the default filter to the one that doesn't try to encode Unicode - It was 'EncodeUnicode' and is now 'RawOrEncodedUnicode'. - - added optional support for parsing whitespace between the directive start - token (#) and directive names, per Christophe Eymard's request. For the - argument behind this see the mailing list archives for Jan 29th. This is - off by default. You must turn it on using the compiler setting - allowWhitespaceAfterDirectiveStartToken=True:: - - #for \$something in \$another - # for \$somethin2 in \$another2 - blahblah \$something in \$something2 - # end for - #end for - - - made the handling of Template.compile()'s preprocessors arg simpler and - fixed a bug in it. - - fixed attribute name bug in the .compile() method (it affected the feature - that allows generated module files to be cached for better exception - tracebacks) - - refactored the #cache/CacheRegions code to support abitrary backend cache - data stores. - - added MemcachedCacheStore, which allows cache data to be stored in a - memcached backend. See http://www.linuxjournal.com/article/7451 and - http://www.danga.com/memcached/. This is only appropriate for systems - running many Python server processes that need to share cached data to - reduce memory requirements. Don't bother with this unless you actually - need it. If you have a limited number of Python server processes it is - much faster, simpler, and more secure to just cache in the memory of each - process. - - KEEP MEMCACHED'S LIMITED SECURITY IN MIND!! It has no authentication or - encryption and will introduce a gaping hole in your defenses unless you - are careful. If you are caching sensitive data you should take measures - to ensure that a) untrusted local system users cannot connect to memcached - server, b) untrusted external servers cannot connect, and c) untrusted - users on trusted external servers cannot connect. Case (a) can be dealt - with via iptable's owner match module for one way to do this: "iptables -A - ... -m owner ..." Cases (b) and (c) can be handled by tunnelling - memcached network connections over stunnel and implementing stunnel - authentication with mandatory peer/client certs. - - some under-the-hood refactoring of the parser - - made it possible to add custom directives, or customize the - parsing/handling of existing ones, via the compiler settings - 'directiveNamesAndParsers' and 'endDirectiveNamesAndHandlers' - - added a compile-time macro facility to Cheetah. These macros are very - similar to macros in Lisp: - http://www.apl.jhu.edu/~hall/Lisp-Notes/Macros.html. - - As with Lisp macros, they take source code (Cheetah source) as input and - return source code (again Cheetah source) as output. They are executed at - compile-time, just like in Lisp and C. The resultant code - gets executed at run-time. - - The new #defmacro directive allows users to create macros inside the - source of their templates. Macros can also be provided via the compiler - setting 'macroDirectives'. The 'macroDirectives' setting allows you to - share common macros between templates. - - The syntax for the opening tag of #defmacro is the same as for #def and - #block. It expects a macro name followed by an optional argument list in - brackets. A `src` argument is automatically added to the beginning of - every macro's argument list. The value of the `src` is the block of - input source code that is provided during a macro call (see below):: - - #defmacro [(argspec)] - - #end defmacro - - All of Cheetah's syntax is available for use inside macros, but the - placeholderStartToken is @ instead of \$ and the - directiveStartToken/EndToken is % instead of #. Any syntax using the - standard \$/# tokens will be treated as plain text and included in the output - of the macro. - - Here are some examples:: - - #defmacro addHeaderFooter - header - @src - footer - #end defmacro - - #defmacro addHeaderFooter(header='h', footer='f') - @header - @src - @footer - #end defmacro - - There is a single-line short form like for other directives:: - - #defmacro addHeaderFooter: header @src footer - #defmacro addHeaderFooter(header='h', footer='f'): @header @src @footer - - The syntax for calling a macro is similar to the simplest usage of the - #call directive:: - - #addHeaderFooter - Source \$code to wrap - #end addHeaderFooter - - #addHeaderFooter: Source \$code to wrap - - #addHeaderFooter header='header', footer='footer: Source \$code to wrap - - In Elisp you write - (defmacro inc (var) - (list 'setq var (list '1+ var))) - to define the macro `inc` and write - (inc x) - which expands to - (setq x (1+ x)) - - In Cheetah you'd write - #defmacro inc: #set @src +=1 - #inc: \$i - which expands to - #set \$i += 1 - - print Template("""\\ - #defmacro inc: #set @src +=1 - #set i = 1 - #inc: \$i - \$i""").strip()==2 - - - fixed some bugs related to advanced usage of Template.compile(). These - were found via new unit tests. No one had actually run into them yet. - - added the initial bits of an #i18n directive. It has the same semantics - as:: - - #call self.handleI18n - Some \$var cheetah source - #end call - - but has a simpler syntax:: - - #i18n - Some \$var cheetah source - #end i18n - - ## single-line short form: - #i18n: Some \$var cheetah source - - The method it calls, self.handleI18n, is just a stub at the moment, but it - will soon be a wrapper around gettext. It currently has one required - positional argument `message`. I anticipate supporting the following - optional arguments:: - - id = msgid in the translation catalog - domain = translation domain - source = source lang - target = a specific target lang - comment = a comment to the translation team - - plural = the plural form of the message - n = a sized argument to distinguish between single and plural forms - - #i18n is executed at runtime, but it can also be used in conjunction with - a Cheetah preprocessor or macro (see above) to support compile time - translation of strings that don't have to deal with plural forms. - - added Cheetah.Utils.htmlEncode and Cheetah.Utils.htmlDecode - - more docstring text - - Unit tests: [TR] - - - extended the caching tests - - added tests for the various calling styles of Template.compile() - - added copies of all the SyntaxAndOutput tests that use a template - baseclass other than `Template`. This ensures that all syntax & core - features work with 2.0's support for arbitrary baseclasses. - - added tests for all the new directives and the new single-line short forms - -2.0rc2 (Jan 13th, 2006) - !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!! - Core Changes: [TR] - - - fixed some python 2.4isms that slipped in. All the tests pass with Python - 2.2 now - - added lots more docstring content in the Template class - - made multiline comments gobble whitespace like other directives, per JJ's - request. The rather longwinded compiler setting - gobbleWhitespaceAroundMultiLineComments can be used to go back to the old - non-gobbling behaviour if needed. - - added #capture directive to complement the #call directive. - #call executes a region of Cheetah code and passes its output into a function call - #capture executes a region of Cheetah code and assigns its output to a variable - - extended the compile caching code in Template.compile so it works with the - 'file' arg. - - added cacheModuleFilesForTracebacks and cacheDirForModuleFiles args to - Template.compile(). See the docstring for details. - - misc internal refactoring in the parser - - improved handling of keyword args in the __init__ method and fixed a - potential clash between the namespaces and searchList args - - WWW: [TR] - - - added the source for the new Cheetah website layout/content - -2.0rc1 (Jan 10, 2006) - !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!! - Core Changes: [TR] - - - made it possible nest #filter directives - - added lots more docstring content in the Template class - - added Template.subclass() classmethod for quickly creating subclasses of - existing Cheetah template classes. It takes the same args as the - .compile() classmethod and returns a template that is a subclass of the - template .subclass() is called from:: - - T1 = Template.compile(' foo - \$meth1 - bar\\n#def meth1: this is T1.meth1') - T2 = T1.subclass('#implements meth1\\n this is T2.meth1') - - - added baseclass arg to Template.compile(). It simplifies the reuse of - dynamically compiled templates:: - - # example 1, quickly subclassing a normal Python class and using its - # __init__ call signature: - dictTemplate = Template.compile('hello \$name from \$caller', baseclass=dict) - print dictTemplate(name='world', caller='me') - - # example 2, mixing a Cheetah method into a class definition:: - - class Foo(dict): - def meth1(self): - return 'foo' - def meth2(self): - return 'bar' - Foo = Template.compile('#implements meth3\\nhello \$name from \$caller', - baseclass=Foo) - print Foo(name='world', caller='me') - - A side-benefit is the possibility to use the same Cheetah source with - several baseclass, as the baseclass is orthogonal to the source code, - unlike the #extends directive. - - added 'namespaces' as an alias for 'searchList' in Template.__init__ - - made it possible to pass in a single namespace to 'searchList', which will - automatically be converted into a list. - - fixed issue with buffering and use of #call when template is used as a - webkit servlet - - added Cheetah.Utils.htmlEncode and htmlDecode - - The command line tool (CheetahWrapper.py): - - - changed insertion order for the --env and --pickle options so they match the - commandline UI of the compiled template modules themselves [TR] - -2.0b5 (Jan 7, 2006) - !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!! - Core Changes: [TR] - - - made Cheetah.Template a new-style class by inserting 'object' into its' - inheritance tree. Templates can now use super(), properties and all the - other goodies that come with new-style classes. - - removed the WebInputMixin by placing its one method directly in the - Template class. - - removed the SettingsManager Mixin. It wasn't being used by anything - anymore. - - added a framework for caching the results of compilations in - Template.compile(). This is on by default and protects against bad - performance issues that are due to programmers misguidedly compiling - templates inside tight loops. It also saves on memory usage. - - misc attr name changes to avoid namespace pollution - - more + improved docstrings - - replaced the oldstyle dynamic compile hacks with a wrapper around - Template.compile(). The old usage pattern Template(src) now benefits from - most of the recent changes:: - - Template(src).__class__ == Template.compile(src) - - - removed all the extra imports required by oldstyle dynamic compile hacks - - converted the cheetah #include mechanism to newstyle compilation and made it - more flexible - - made the #include mechanism work with file objects in addition to file names - - made the handling of args to Template.compile() more flexible. You can now - provide defaults via class attributes. - - made preprocessors for Template.compile() work with file arguments - - added support for specifying a __metaclass__ on cheetah template classes - - refactored both the class and instance initialization processes - - improved the handling of __str__ in _assignRequiredMethodsToClass - - The command line tool (CheetahWrapper.py): [TR] - - - improved error output in CheetahWrapper - - switched fill command over to new style compile usage - - Unit tests: [TR] - - - fixed format string bug in unittest_local_copy.py - -2.0b4 (Jan 6, 2006) - !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!! - Core Changes: [TR] - - - fixed up parsing of target lists in for loops. This was previously limited - to fairly simple target lists:: - - #for (\$i, \$j) in [('aa','bb'),('cc','dd')] - \$i.upper,\$j.upper - #end for" - #for (i, j) in [('aa','bb'),('cc','dd')] - \$i.upper,\$j.upper - #end for" - #for i,(j, k) in enumerate([('aa','bb'),('cc','dd')]) - \$j.upper,\$k.upper - #end for" - - - refactored the class initialization process - - improved handling of target lists in #set directive. This was previously - limited to fairly simple target lists. - #set i,j = [1,2] ... #set \$i,\$j = [1,2] - #set (i,j) = [1,2] ... #set (\$i,\$j) = [1,2] - #set i, (j,k) = [1,(2,3)] ... #set \$i, (\$j,\$k) = [1,(2,3)] - - - made it possible for the expressionFilter hooks to modify the code chunks - they are fed. Also documented the hooks in a docstring. Thus the hooks - can be used as preprocessors for expressions, 'restricted execution', or - even enforcement of style guidelines. - - - removed cheetah junk from docstrings and placed it all in comments or - __moduleVars__. Per JJ's suggestion. - - - made it possible to nest #cache directives to any level - - made it possible to nest #call directives to any level - - Unit Tests [TR] - - - extended tests for #for directive - - expanded tests for #set directive - - expanded tests for #call directive - - expanded tests for #cache directive - - added basic tests for the new \$placeholder string expressions: - c'text \$placeholder text' - -2.0b3 (Jan 5, 2006) - !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!! - Core Changes: [TR] - - - added #yield statement - - added ability to create nested scopes/functions via nested #def statements - - added new #call directive and related #arg directive, per Ian Bicking's - suggestion. - - added new expression syntax c"text \$placeholder text" - - for those basic function calling cases where you just need to pass in a - small bit of cheetah output as an argument:: - - c'a string with \$placeholders', - c'''a string with \$placeholders''', - c"a string with \$placeholders", - c"""a string with \$placeholders""" - - - They can't contain #directives, but accept any valid \$placeholder syntax - except caching placeholders. Caching placeholders don't make any sense in - this context. - - They can be used \*any\* place where a python expression is expected. - - They can be nested to any depth:: - - \$func(c'
  • \$var1-\$var2
  • ') - \$func(c'
  • \$var1-\$var2
  • ', doSomething=True) - \$func(content=c'
  • \$var1-\$var2
  • ', doSomething=True) - \$func(lambda x,y: c'
  • \$x-\$y
  • ') - \$func(callback=lambda x,y: c'
  • \$x-\$y
  • ') - \$func(lambda x,y: c'
  • \$x-\$y-\$varInSearchList
  • ') - \$func(c'
  • \$var1-\$var2-\$(var3\*10)-\$(94.3\*58)
  • ') - \$func(c'
  • \$var1-\$var2-\$func2(c"a nested expr \$var99")
  • ') - #if \$cond then c'
  • \$var1-\$var2
  • ' else c'

    \$var1-\$var2

    ' - #def foo(arg1=c'\$var1\$var2'): blah \$arg1 blah - \$foo(c'\$var1\$var2') - - - added preprocessor hooks to Template.compile() - can be used for partial completion or 'compile-time-caching' - ... more details and examples coming. It's very useful, but takes a bit - of explaining. - - added '#set module varName = expr' for adding module globals. JJ's suggestion - - improved generated docstring notes about cached vars - - fixed silly bug related to """ in docstring comments and statements like - this '#def foo: \$str("""foo""")'. Reported by JJ. - - changed the handling of single-line defs so that - '#def xxx:\\n' will be treated as a multi-line #def. - The same applies to #block. There's a compiler setting to turn this off - if you really need empty single-line #def:'s. - JJ reported that this was causing great confusion with beginners. - - improved error message for unclosed directives, per Mike Orr's suggestion. - - added optional support for passing the trans arg to methods via \*\*KWS rather - than trans=None. See the discussion on the mailing list Jan 4th (JJ's post) for - details. The purpose is to avoid a positional argument clash that - apparently is very confusing for beginners. - - Note that any existing client code that passing the trans arg in - positionally rather than as a keyword will break as a result. WebKit - does this with the .respond method so I've kept the old style there. - You can also turn this new behaviour off by either manually including - the trans arg in your method signature (see the example below) or by - using the compiler setting 'useKWsDictArgForPassingTrans'=False:: - - #def manualOverride(arg1, trans=None) - foo \$arg1 - #end def - - ImportHooks: - - - made the ImportHook more robust against compilation errors during import [TR] - - Install scripts: [TR] - - - added optional support for pje's setuptools - - added cheeseshop classifiers - - removed out of date install instructions in __init__.py - - Servlet Base Class For Webkit: [TR] - - - disabled assignment of self.application (was a webware hack) - - Unit Tests: [TR] - - - unit tests for most of the new syntax elements - - tidied up some old tests - - misc refactoring - -2.0b2 (Dec 30, 2005) - !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!! - - Core Changes: - - - In previous versions of Cheetah tracebacks from exceptions that were raised - inside dynamically compiled Cheetah templates were opaque because - Python didn't have access to a python source file to use in the traceback:: - - File "xxxx.py", line 192, in getTextiledContent - content = str(template(searchList=searchList)) - File "cheetah_yyyy.py", line 202, in __str__ - File "cheetah_yyyy.py", line 187, in respond - File "cheetah_yyyy.py", line 139, in writeBody - ZeroDivisionError: integer division or modulo by zero - - It is now possible to keep the generated source code from the python - classes returned by Template.compile() in a cache dir. Having these files - around allows Python to include the actual source lines in tracebacks and - makes them much easier to understand:: - - File "/usr/local/unsnarl/lib/python/us/ui/views/WikiPageRenderer.py", line 192, in getTextiledContent - content = str(template(searchList=searchList)) - File "/tmp/CheetahCacheDir/cheetah_yyyy.py", line 202, in __str__ - def __str__(self): return self.respond() - File "/tmp/CheetahCacheDir/cheetah_yyyy.py", line 187, in respond - self.writeBody(trans=trans) - File "/tmp/CheetahCacheDir/cheetah_yyyy.py", line 139, in writeBody - __v = 0/0 # \$(0/0) - ZeroDivisionError: integer division or modulo by zero - - This is turned off by default. To turn it on, do this:: - - class NiceTracebackTemplate(Template): - _CHEETAH_cacheModuleFilesForTracebacks = True - _CHEETAH_cacheDirForModuleFiles = '/tmp/CheetahCacheDir' # change to a dirname - - templateClass = NiceTracebackTemplate.compile(src) - - # or - templateClass = Template.compile(src, - cacheModuleFilesForTracebacks=True, cacheDirForModuleFiles='/tmp/CheetahCacheDir') - - - This only works with the new Template.compile(src) usage style! - - Note, Cheetah generated modules that are compiled on the command line have - never been affected by this issue. [TR] - - added an extra comment per \$placeholder to generated python code so it is - easier to grok. [TR] - -2.0b1 (Dec 29, 2005) - !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!! - - Core Changes: - - - enabled use of any expression in \${placeholders}. See the examples I posted to - the email list on Dec 12th. All use cases of the #echo directive can now - be handled with \${placeholders}. This came from a suggestion by Mike - Orr. [TR] - - made it possible for templates to #extend (aka subclass) any arbitrary - baseclass, including Python's new style classes. You must either compile - your classes on the command line or use the new classmethod - Template.compile() as described below. The old Template(src) interface - still works, provided you don't try to use this new arbitrary baseclass - stuff. See my messages to the email list for more details. [TR] - - made it possible to create template classes dynamically, rather than just - instances. See the new classmethod Template.compile(). See my messages - to the email list for more details. [TR] - - klass = Template.compile(src) - - made it easier to work with custom compiler settings, particularly from - the command line tool. You can now define a subclass of Template which - will compile your templates using custom compilerSettings, or even a - custom compiler class, without requiring you to manually pass in your - compilerSettings each time or define them in the template src itself via - the #compiler directive. You can make the command line tool use your - subclass by defining the environment variable CHEETAH_TEMPLATE_CLASS. It - should be in the form 'package.module:class'. See my messages - to the email list for more details. [TR] - - made it possible to pass the searchList in as an argument to #def'ined - methods. This makes all lookup that occur within the scope of that method - use the provided searchList rather than self._searchList. This does not - carry over to other methods called within the top method, unless they - explicitly accept the searchList in their signature AND you pass it to - them when calling them. This behaviour can be turned off with the - corresponding compilerSetting 'allowSearchListAsMethArg' [TR] - - added hooks for filtering / restricting dangerous stuff in cheetah source - code at compile time. These hooks can be used to enable Cheetah template - authoring by untrusted users. See my messages to the email list for more - details. Note, it filters expressions at parse/compile time, unlike Python's - old rexec module which restricted the Python environment at runtime. [TR] - - # Here are the relevant compiler settings: - # use lower case keys here!! - 'disabledDirectives':[], # list of directive keys, without the start token - 'enabledDirectives':[], # list of directive keys, without the start token - - 'disabledDirectiveHooks':[], # callable(parser, directiveKey), - # called when a disabled directive is found, prior to raising an exception - - 'preparseDirectiveHooks':[], # callable(parser, directiveKey) - 'postparseDirectiveHooks':[], # callable(parser, directiveKey) - - 'preparsePlaceholderHooks':[], # callable(parser) - 'postparsePlaceholderHooks':[], # callable(parser) - - 'expressionFilterHooks':[], - # callable(parser, expr, exprType, rawExpr=None, startPos=None) - # exprType is the name of the directive, 'psp', or 'placeholder'. - #all lowercase - - added support for a short EOLSlurpToken to supplement the #slurp - directive. It's currently re.compile('#\\s\*\\n') (i.e # followed by - arbitrary whitespace and a new line), but this is not set in stone. One - other suggestion was the backslash char, but I believe Python's own - interpretation of backslashes will lead to confusion. The compiler - setting 'EOLSlurpToken' controls this. You can turn it off completely by - setting 'EOLSlurpToken' to None. See the email list for more details. [TR] - - added '_CHEETAH_' prefix to all instance attribute names in compiled - templates. This is related to the arbitrary baseclass change. [TR] - - shifted instance attribute setup to _initCheetahAttributes() method. This - is related to the arbitrary baseclass change. [TR] - - made it possible to use full expressions in the #extends directive, rather - than just dotted names. This allows you to do things like this: - - #from xx.TemplateRepository import getTemplateClass - #extends getTemplateClass('someName') - - I don't expect this to be used much. I needed it for a wiki system in - which the baseclasses for the templates are dynamically compiled at run - time and are not available via simple imports. [TR] - - added compiler setting autoImportForExtendDirective=True, so this existing - default behaviour can be turned off when needed. [TR] - - fixed a bug in the parsing of single-line #def's and #block's when they - are enclosed within #if ... #end if. Reported by Marcin Gajda [TR] - - tweak to remove needless write('') calls in generated code [TR] - - The command line tool (CheetahWrapper.py): - - - added code to cleanup trailing slashes on path arguments (code originally - from Mike Orr) [TR] - - turned on the ImportHooks by default for the 'cheetah fill' command. See the - discussion on the email list [TR] - - ImportHooks: - - - fixed a name error bug in the ImportHooks [TR] - -1.0 (Dec 4, 2005) - !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!! - - Version bump from 1.0rc3 - -1.0rc3 (Nov 30, 2005) - !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!! - - - added useSearchList compiler setting [TR] - This defaults to True, but if false, the compiler assumes the first - portion of a \$variable (before the first dot) is a global, builtin, or local - var that doesn't need looking up in the searchlist. NameMapper's unified - dotted notation will still be used on the rest of the lookup (provide the - setting useNameMapper==True):: - - \$aLocalDictVar.aKey.somethingElse - -1.0rc2 (Nov 19, 2005) - - !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!! - - See my email to the cheetahtemplate-discuss list on Sat. Nov. 12th for more - details on these changes: - - - faster list-based buffering in DummyTrans, rather than StringIO (my - benchmarks showed it to be significantly faster. collections.deque wasn't - any faster than a simple list.) [TR] - - new CompilerSettings to tweak generated code: [TR] - \* alwaysFilterNone: filter out None immediately, before the filter is called - \* useFilters: allows you to turn them off completely and default to str() - \* includeRawExprInFilterArgs: allows you to disable this behaviour - \* autoAssignDummyTransactionToSelf: off by default - - and automatic \$trans finding without having to pass it as an arg to methods - based Jonathan Mark's suggestion. If the template's self.transaction - attribute has been set, each method of the template will use it when - called. [TR] - - applied Chris Murphy's patch to fix a bug in the #shBang directive. [TR] - -1.0rc1 (Nov 2, 2005) - - !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!! - - - added the compiler option "useStackFrames" for optionally turning off the - default lookup method which doesn't work with psyco because it uses stack - frame introspection. When useStackFrames=False, an alternative psyco - friendly lookup method is used. [TR] - - fixed treatment of None in several filters, bug reported by Daniele Varrazzo - [TR] - -0.9.18 (Aug 22, 2005) - - - version bump from 0.9.18rc1 [TR] - -0.9.18rc1 (Aug 15, 2005) - - - applied Philippe Normand's patch for extended cache support [TR] - - added filter RawOrEncodedUnicode to fix a unicode issue that was discussed - on the email list on Aug. 9th 2005 [TR] - -0.9.17 (May 30, 2005) - - - this is just 0.9.17rc1 repackaged [TR] - -0.9.17-rc1 (May 12, 2005) - - This simple bug fix release resolves some issues introduced by - under-the-hood changes in release 0.9.16a1. - - - removed the use of temp files for handling imports with dynamic - compilation. This removes a whole slew of issues, including a temp file - security issue reported on the email list by Brian Bird. [TR] - - fixed bug with handling of the searchList with dynamic inheritance, as - reported by Brian Bird. [TR] - -0.9.16 (Mar 27, 2005) - - - this is just 0.9.16b1 repackaged [TR] - -0.9.16b1 (Feb 28, 2005) - - - fixed attr error in Parser.eatEncoding [TR] - - some tweaks to Compiler.py to prevent errors with dynamically compiled - templates [TR] - - added tests for the #encoding directive [TR] - -0.9.16a1 (Jan 6, 2005) - - - fixed a unicode bug in Compiler.py [TR] - - added new EncodeUnicode filter that Rene Pijlman contributed (I optimized it - slightly) and made it the default filter for all templates. [TR] - - added test cases for handling unicode with the default filter [TR] - - fixed a caching bug related to the #include directive. Thanks to Michael - Engelhart for reporting it.[TR] - - added the new #encoding directive to handle PEP 263 - http://www.python.org/doc/2.3/whatsnew/section-encodings.html [TR] - - Tools.CGITemplate: fix bug in comment.[MO] - - Abort with a helpful error message if user runs 'cheetah test' in a - directory without write permission. (Kludge in CheetahWrapper.py; we - should probably move the temp files under the system tmp directory.) [MO] - - added better string type checking for args in Template.py, as suggested by - Terrel Shumway [TR] - - minor tweak to the class attribute lookup style in the Compiler.py - __getattr__ methods [TR] - - Fix printf format bug in "cheetah c --debug", found by Terry MacDonald. [MO] - - Disabled NameMapperDict test (in SyntaxAndOutput.py) because the - namemappers still have the dict-method bug. (Reminder: don't use - placehold names like \$update that match dict method names.) [MO] - - #repeat now uses a local variable of the form __i\$num which permits - nesting [JJ] - - implemented a modified version of Bob and JJ's patch for better parser - warnings about mismatched directives and #end directives [TR] - - lots of little cleanups and refactoring [TR] - - refactored the class tree for the Parser and Compiler. They are now - completely separate trees and the communication between them is one-way: - explicit commands from the parser to the compiler. The parser now handles - all parsing tasks by itself and delegates \*all\* code generation to the - compiler. This last bit was my original intention, but things got a bit - mixed up over time. Also, all SettingsManager stuff for handling - compiler/parser settings is now handled by ModuleCompiler. This should make - it easier to grok, maintain, and extend both. [TR] - - improved the parsing of singe-line #if directives. [TR] - - removed the old webware example of the cheetah site, as it was way out of - date and was more confusing than helpful. [TR] - - added two new lookup functions to NameMapper (valueFromFrame and - valueFromFrameOrSearchList) and synchronized the behaviour of the C and - Python versions of all functions. [TR] - - improved the exception handling of both versions of NameMapper. NotFound - exceptions now include more detail about what wasn't found. [TR] - - made NameMapper's searchList lookup functions work with any iterable - type/class rather than just with lists. [TR] - - added and updated a variety of test cases. [TR] - - checked in a patch to CheetahWrapper that improves handling of the odir - option when the path is absolute. I can't remember where the patch came - from. [TR] - - checked in a patch to Template.py for better include/import support under - Jython. Again, I've forgotten who contributed it. [TR] - - updated various bits of the user guide. [TR] - - made the Cheetah NameMapper calls in the generated code use the new function - valueFromFrameOrSearchList rather than passing locals, searchList, globals, - and __builtins__ into valueFromSearchList. This is faster, less bug prone - and simpler to read/grok. I also removed all tracking of local - variable names by the compiler. [TR] - - other misc. refactorings [TR] - -0.9.15 (Mar 25, 2003) - - - a minor tweak to the cleanup actions of one of the test cases [TR] - -0.9.15rc2 (Mar 23, 2003) - - - Fixed a python version dependency bug related to Compiler.py's use of - isinstance() [TR] - -0.9.15rc1 (Mar 21, 2003) - - This is just 0.9.15b1 renamed. - -0.9.15b1 (Mar 17, 2003) - - - The Cheetah version of unittest now prints a blank line after each - traceback to separate them. (MO) - - .webInput() now saves the cgi.FieldStorage() instance in a global - variable rather than recreating it each call. That should allow the - method to be called multiple times with POST variables outside Webware. - (MO) - - CheetahWrapper: no verbose output on stdout with --stdout/-p. (MO) - - "#indent" is now undocumented. The existing code remains intact for now. - See the TODO file for our future plans. (MO) - - Apply 2 unicode-support patches from Rodrigo B. de Oliveira (rodrigobamboo) - that affected the Template and ModuleCompiler classes. (TR) - - Template: compiling a template from a string now works if the current - directory doesn't have write permission. (MO) - - remove temporary .pyo files in addition to .py and .pyc files (TR) - -0.9.15a3 (Nov 10, 2002) - - - corrected a dictionary bug in the Python version of NameMapper (TR) - - Rewrote the "cheetah" command (CheetahWrapper.py) again and added test - cases. New options --flat and --nobackup; --stdout is now a synonym for - -p. See the "cheetah compile" section in the Users' Guide for details. - Deleted Utils.dualglob: merged into CheetahWrapper. (MO) - - .addToSearchList() and .prependToSearchList() are gone. Instead of - adding containers to the searchList after instantiation, pass all the - containers you need to the constuctor, keep another reference somewhere - to the containers, and modify the containers directly. Generic libraries - that want to add a new kind of information to the searchList (e.g., - web variables) should do "self.searchList().insert(0, myContainer)". (MO) - -0.9.15a2 (Nov 4th, 2002) - - - Filters now have access to the name of the placeholder they're filtering. - In the .filter() method, kw['rawExpr'] gives the entire placeholder name - including subscripts and arguments, exactly as it appears in the template - definition. (TR) - - Fix three bugs in "cheetah compile -R": (1) the generated class name - contained the subdirectory, (2) the destination path did not contain the - subdirectory, (3) Cheetah failed to create the destination subdirectory - if missing. All subdirectories created have an "__init__.py" file. - "cheetah fill -R" does the same thing but does not create - "__init__.py". (MO) NOTE: this is still buggy! - - New directory "attic" in source contains code that has been abandoned - for now but may come in handy someday. (MO) - - Tests.CheetahWrapper: test suite for "cheetah compile" and - "cheetah fill". If the module is run from the command line, the - option "--list PATH/CheetahWrapper.py", lists all scenarios that would be - tested; the argument is the path to the test module itself. (MO) - - made Cheetah.NameMapper.NotFound subclass the builtin LookupError (TR) - - added an initial implementation of single line #if directives - #if then else - The parsing is fairly rudimentary for now and assumes that the keywords - 'then' and 'else' won't appear any inside a string in this directive (TR) - -0.9.15a1 (Oct 6th, 2002) - - - fixed a package-relative import bug in ImportHooks.py (TR) - - set 'monitorSrcFile' to false as it was causing problems with the - ImportHooks ... This might be temporary as the problem needs more thought - (TR) - - fixed meta tag http_equiv to be http-equiv in SkeletonPage (TR) - - \$webInput (Utils.WebInputMixin) 'source' arg can be either case. (MO) - - fixed code-gen bug in MethodCompiler.commitStrConst that was leading to - triple single quotes followed immediately by another single quote if the - template def contained a '\$placeholder' surrounded in single quotes and - multiple \\n newlines ... plus added new test case.(TR) - - undocumented the '#settings' directive. The directive itself will be - removed soon. (MO) - - Utils.optik: Optik 1.3 package by Gregory P Ward, for parsing - command-line options in 'cheetah' comamnd. Copied unchanged into - Cheetah except added "Cheetah.Utils.optik." prefix to intra-package - imports. Optik's copyright and license is in an appendix in the - Cheetah Users' Guide. (MO) - - rewrite of the "cheetah" and "cheetah-compile" commands. - The command-line options have changed! Removed CheetahCompile module - removed and its test suite too; CheetahWrapper now takes its place. (MO) - - Utils.dualglob: new module to recursively generate source+destination - filenames from command-line filespecs. (MO) - - The command-line options of .py template modules have also changed - to conform with the "cheetah" command. Also a --pickle bug was - fixed. (MO) - - Utils.WebMixin: made a string type comparision backward compatible. - This was why the Cheetah test suite was failing on Python < 2.2! (MO) - - SettingsManager._createConfigFile(): bugfix in default argument. (MO) - - \$hasVar('varName') is an alias for \$varExists('varName'). (MO) - - \$_fileDirName and \$_filePath are now None rather than missing if - the template definition did not come from a named file. (MO) - - applied patch on SourceForge for "%" in default arguments of a block (TR) - - removed the _underscored attribute lookup step from NameMapper NOTE THIS - MIGHT BREAK EXISTING TEMPLATES (TR) - - Install Cheetah into site-packages/Cheetah/ rather than - site-packages/Webware/Cheetah/. Added code to automatically remove the old - dir.(TR) - - fixed the variable name resolution order bug in \$placeholders. The new - implementation uses:: - - valueFromSearchList([locals()] + searchList + [globals(), __builtin__], - rest of the args) for all lookups. (TR) - - - removed the #settings directive (TR) - - added the #del directive, for using Python's del statement (TR) - - I think I've fixed the problem with the searchList arg being discarded when a - template is generated from a .tmpl file that #extends another template. This - bug was reported by Edmund on Aug 30th - (subject: "Bug? Was: Really basic searchList question") (TR) - -0.9.14 (July 14, 2002) - - - Precompiled template Templates/SkeletonPage.py added to CVS. This file is - needed for Cheetah's regression tests. (MO) - - removed automatic recompilation of .py template in memory if the - .tmpl file has changed. (TR) - -0.9.14b1 (June 30, 2002) - - - moved the Users' Guide and the Developers' Guide into a separate CVS module, - 'CheetahDocs', so they can be distributed separately from the source distro - (TR,MO) - - added TypeType to the types that NameMapper won't do autocalling on (TR) - - in Template.py moved the global LegalKWs to Template._legalKWs (TR) - - made #set work with RVALUES that are missing the recommended \$ (TR) - - added some new test cases for the #set directive (TR) - - fixed bug in the output of the #unless directive that Mike found (TR) - - added some module constants to clear up a missing name bug that Mike found - in cases where you use \*\*KW in a Cheetah method definition (TR) - - fixed a bug in Parser.py:_LowLevelSemanticsParser.getExpression() that was - related to the default enclosures=[] argument. This arg was unintentionally - being shared between calls and thus leading to parsing errors as reported by - Greg Czajkowski (TR) - - Filter: fixed an '== None' expression (should be 'is None'). (MO) - - TemplateMisc: new base class for Template. This is for optional - convenience methods that don't require Webware. (MO) - - User's Guide: new sections "Non-Webware HTML Output" and "Non-HTML - Output". (MO) - - Expanded \$webInput() -- renamed from \$cgiImport() -- to work both with - Webware input and CGI scripts. Handles GET/POST/cookie/session vars under - Webware, and GET/POST under CGI. Defined in Cheetah.Utils.WebInputMixin, - now inherited by Template directly. (MO) - - Tools.CGITemplate has methods to output CGI headers: .isCgi, .cgiHeaders - and .cgiHeadersHook in TemplateMisc. (MO) - - New #indent directive allows you to indent block constructs in the - template definition without having that indentation in the output, and - allows you to set the output indentation per line independent of the - indentation in the template definition. This version uses Robert - Kuzelj's #indent syntax exactly. In the next few days, - Cheetah.Utils.Indenter will be refactored and - \*\*\* THE #INDENT SYNTAX WILL CHANGE! \*\*\* (MO) - - added the #return directive as requested by Robert Kulezj (TR) - - added some test cases for the #return directive (TR) - - removed buggy import statement that had been left in Servlet.py after the - CGIInputMixin changes (TR) - - -0.9.13 (May 8, 2002) - - - changed Cheetah.Servlet.isRunningFromWebKit to isWebwareInstalled (TR) - - fixed parsing bug that would exit an expression if the directiveEndToken was a - valid Python token and was found inside the directive. (TR) - - E.g.:: - - #compiler-settings - directiveStartToken = . - directiveEndToken = : - commentStartToken = # - #end compiler-settings - - .for a in [1,2,3,4][2:3]: - blag - .end for - - - fixed #include bug that was resulting in non-unique includeIDs (TR) - -0.9.13b2 (May 3, 2002) - - - fixed the bug in Cheetah.Servlet.Servlet.serverSidePath that Jeff Johnson - found. (TR) - - changed the attribute Cheetah.Servlet.ServletisRunningFromWebKit to - isControlledByWebKit and set the default to False unless the .awake method - is called. This makes a clear distinction between templates that are being - used with WebKit via the inheritance approach and the containment approach - (TR) - - -0.9.13b1 (May 1, 2002) - - - Was going to import cStringIO instead of StringIO, but it made the - DummyTransaction.py unittest fail so I undid it. Cheetah aims to provide - Unicode support, which cStringIO does not provide. (TR/MO) - - Utils.Misc.CheckKeywords(): prevent misspelled keyword arguments, - used by Template constructor. (MO) - - removed support for multiple inheritance (TR) - - added some bounds-checking code to _namemapper.c's getNameChunks function - (TR) - - changed the exceptions in _namemapper.c from the old string exceptions - to proper exception objects (TR) - - first portion of Developers' Guide written (MO) - - implemented the extended #extends directive, which does automatic importing - (MO,TR) - - added some new testcases for the extended #extends directive (TR) - - lots of work on the Users' Guide (MO) - - implemented and tested an import hook for .tmpl files (TR): - import MyTemplate # will compile and import MyTemplate.tmpl - - made my True/False declarations friendly with Python 2.2.1, which already - includes True/False as builtins (TR) - - implemented the #compiler directive that Edmund Lian suggested (TR) - e.g.: - #compiler commentStartToken = '//' - // a comment - #compiler reset - // no longer a comment - - fixed the bug that Edmund Lian found in .addSet() when useNameMapper = 0 - (TR) - - fixed bug in comment creation using lineCol that Mike found (TR) - -0.9.12 (April 3, 2002) - - - no code changes from beta 2 - - more work on the docs (MO) - -0.9.12b2 (Mar 28, 2002) - - - fixed Win32 path bug in Template._makeDummyPackageForDir() (TR) - - prettied up the format of the debug comments in the Cheetah generated - Python code (TR) - - fixed the non-unique key error in Template._includeCheetahSource (TR) - - fixed the module import bug in 'cheetah compile -w' (TR) - -0.9.12b1 (Mar 24, 2002) - - - \$request().field(args) now works, identical to \$request.field(args) - to implement this, the request object is now self.request() instead of - self.request. This provides compatibility with Webware's servlet API. - (self.session already was an accessor method). New read-only attribute - self.isRunningFromWebKit is boolean. All changes are in Servlet.py. (MO) - - fixed nested-NotFound bug in _namemapper.c's valueFromSearchList (TR) - - 'cheetah' wrapper script has abbreviation -c for the 'compile' command, - -t for 'test', and an ASCII-art cheetah face in the help message. (MO) - - CheetahCompile.py: fixed to recognize --help option and to show --help/-h - in help message. (MO) - - CheetahCompile.py: - changed the order of the VERBOSE mode printouts, as per Mike's request (TR) - - Template.py: - fixed the #include'd template searchList sharing problem, as reported by - Johannes (TR) - - corrected namemapper translation bug in - Compiler.GenUtils.genNameMapperVar() (TR) - - Utils.Misc.UseOrRaise(): convenience function to return a - value, or raise it if it's a subclass of Exception. (MO) - - Utils.CGIImportMixin replaces Tools.WebwareMixin. Servlet now - subclasses it. This adds the .cgiImport() method to all servlets, allowing - sophisticated retrieval of form fields, cookies or session variables from - one line of Cheetah or Python code. See module docstring. (MO) - - lots of updates to the docs (MO) - -0.9.11 (Mar 07, 2002) - - - fixed a careless bug in cheetah-compile (TR) - - implemented the new 'cheetah' wrapper script (TR) - - refactored the local copy of unittest a bit (TR) - -0.9.10 (Mar 06, 2002): Primarily a bug fix release - - - fixed bug in srcfile-mtime monitoring / update code (TR) - - fixed the parsing of single-line #defs and #blocks so they can have - arguments (TR) - - added test cases for single-line #defs and #blocks with args (TR) - - fixed a silly typo bug in Parser.py where a comma was left at the end of - regex definition, make it a tuple rather than a regex - - fixed the directive matching bug that Jeff Johnson reported. It was - causing #else# to not match, while #else # was matching. + added a test - for it.(TR) - - fixed bug in a regex that was preventing bare \$'s followed by whitespace - and then valid varname chars from parsing as just \$ instead of as a - placeholder (TR) - - added some code to break reference cycles after the compilation is - complete. This helps prevent memory leaks when a process in creating then - discarding lots of Templates. You also need to manually call - "template.shutdown()" to clear the remaining reference cycles. - (TR) - - fixed string formating bug in the autogenerated docstring code (TR) - - added better error message for the #attr directive (TR) - - removed some residual code that was causing a bug with cheetahvars that - started with the name of one of the imported modules, such as 'time'. (TR) - -0.9.9 (Dec 14, 2001) - - - implemented one-line #def's and #block's (TR):: - - #def aTest: This is a \$adj test ---- READ THE MANUAL FOR MORE INFO. - - NOTE: leading and trailing whitespace is stripped. These should only be - used on lines by themselves as it reads to the end of the line. - - made cheetah-compile accept input on standard input (TR) - - made sure that #def and #block work with \$'s on the method names (TR) - -0.9.9b1 (Dec 6, 2001) - - - template constructor arg 'outputFilter' now 'filter', for consistency - with #filter (MO) - - template constructor raises TypeError if bad arguments (MO) - - Cheetah.Utils.VerifyType new module containing functions for verifying the - type of an argument (MO) - - Cheetah.Utils: new package for non-Cheetah-specific modules needed by - Cheetah (MO) - - Cheetah.Filters: new filter WebSafe, several bugfixes (MO) - - more work on the Users' Guide (MO) - - fixed bug with adding Python's __builtins__ to the local vars list (TR) - - fixed bug with #echo (TR) - - fixed bug that was preventing \${a, \$b=1234} from working like \${a, b=1234} (TR) - - fixed some bugs in Template.varExists and Template.getVar() - (TR - thanks to MH for spotting them) - - made it possible to use filenames like 'spam-eggs.txt' that have invalid - characters for module names with Template(): Template(file='spam-eggs.txt') - (TR/MH) - - refactored 'cheetah-compile' a little (TR) - - Cheetah.Filters.Strip: new filter to strip leading/trailing whitespace - but preserve newlines. Suitable for #filter directive or (possible) - future #sed directive. (MO) - - Cheetah.Filters.StripSqueeze: new filter to canonicalize all whitespace - chunks to ' '. Also removes all newlines (joining multi-line input into - one long line), and leading/trailing whitespace from the final result. (MO) - - Filters can now be used standalone for debugging or for use outside - Cheetah. This works transparently; details are in Filters.py docstring. - (MO) - - Cheetah.Tools.MondoReport: new module for dividing a long list into - "pages", and for calculating statistics useful in reports. (MO) - - refactored Cheetah.Servlet.Servlet.Awake a little (TR) - - fixed an output bug in the #block generated code that turned up when you - tried to override a block method from Python rather than Cheetah. (TR) - - started preparing to shift some of the 'shared' utility classes, such as - SettingsManager, to the Webware core. Cheetah 1.0 will probably require - Webware to be installed so it can access those shared classes. (TR) - - extended the template module command line interface(TR/MO) - -0.9.9a6 (Nov 6, 2001) - - - fixed bug with quotations in longer constant string chunks (TR) - - fixed another bug in the cheetah-compile script (TR) - - fixed a bug in the file-update monitoring code that was resulting in - infinite loops when used with Template sub-classes (TR) - - extended the #filter framework according to Mike's suggestions (TR) - - added test modules for cheetah-compile and the file-update monitoring code (TR) - - extended the capabilities of cheetah-compile ... (IB) - - updated the docs (MO) - -0.9.9a5 (October 31, 2001) - - - fixed a bug I created yesterday (TR) - -0.9.9a4 (October 30, 2001) - - - added #repeat (TR implementing Chuck's suggestion) - - added #unless (TR implementing Mike's suggestion) - - updates to the Users' Guide (MO) - - fixed a small bug in the cheetah-compile script, as reported by Ian on the - list (TR) - -0.9.9a3 (October 12, 2001) - - - more in the Users Guide (TR) - - renamed #attribute as #attr (TR) - - renamed #call as #silent (TR) - - added #echo directive (TR) - -0.9.9a2 (October 11, 2001) - - - updated the example site and the SkeletonPage framework (TR) - - fixed some small bugs (TR) - - corrected some typos in the docs (TR + MO) - - added Ian's sitehiearchy class to Cheetah.Tools (TR + IB) - -0.9.9a1 (October 9, 2001) [many changes and bug-fixes] - - - a complete reimplementation of Cheetah's core (the parser and compiler - classes) (TR + IB) - - implemented the #def, #implements, #import, and #from directives - + removed #redefine and #macros - + renamed #extend as #extends (TR + IB) - - replaced #data with #settings, see the docs (TR) - - restructured and updated the docs (TR + MO + IB) - - reimplemented the cheetah-compile script, without the -g option that Ian - had added (TR) - - changed the signature of Template.__init__. See the docs. (TR) - - made #set distinguish between local and global vars. See the docs. (TR) - - added hundreds of new test cases (TR) - - added the #breakpoint and #compiler-settings directives (TR) - - started restructuring the SkeletonPage framework [not complete yet] (TR) - - started restructuring the example sites [not complete yet] (TR) - -0.9.8 (October 9, 2001) - - - added a few new language constructs (aka 'directives') to Cheetah (TR) - #while ... #end while - #try ... #except ... #else ... #finally ... #end try - - fixed a bug in the handling of local vars in #for loops that was preventing - callable local vars from being handled properly. See Chuck's post of Sept - 10. (TR) - - fixed a pointer bug in the C version of NameMapper.valueFromSearchList() - that was yielding undefined values for the NotFound exception when it was - raised (TR) - - prefaced all internal args to Template() with underscores (TR) - - fixed the problem with parsing triple quoted strings in arg lists (TR) - - updated the docs (TR) - -0.9.8a4 (September 7, 2001) - - - Added -g (appendGen function argument), which compiles x.tmpl to xGen.py, - with x.py being for non-generated Python code. Also changed option handling - a little and added a comment to the top of compiled files. (IB + MO) - - finalized the #include syntax after a lengthy discussion on the list - This is different from in 0.9.8a3 (TR): - - #include - ... uses the value of EXPR as the path of the file to include. - - #include source = - ... includes the value of the EXPR - - where is 'raw' or '' - - re-implemented the output mechanism to use streaming via Webware's - Transaction and Response objects when available and fake it with the - DummyTransaction DummyResponse classes when the Webware Transaction is not - avialable. This behaviour is roughly the same as in Webware's PSP. Will - implement output buffering PHP-style later if there is any demand. (TR) - - made #include a run-time directive rather than compile-time. This is - slower, but the semantics are better. (TR) - - various small optimizations to the generated code (TR) - - updated the docs (TR) - -0.9.8a3 (August 22, 2001) [includes changes for 0.9.8a1 and 0.9.8a2] - - - Added package ./src/Tools/ for contributed classes/functions/packages not - necessary to run Cheetah. The first such class is RecursiveNull.py by Ian - Bicking. Added package Cheetah.Tools to list in ./setup.py . (MO) - - Template.__init__ keyword arg 'searchList': no longer has to be a tuple. It - may be a list or any type that that Python's 'tuple' function accepts. (MO) - - Template.__init__ new keyword arg 'file': this may be a filename or file - object to read the Template Definition from. If you use this, you must not - pass a Template Definition string also. New instance variables - ._fileName and ._fileMtime are set if a filename was passed; otherwise they - are None. (MO) - - CodeGenerator new function 'varNotFound_KeyError': raises KeyError if a - placeholder name is missing when filling the template. Disabled by default. - (MO) NB - this change has been superceeded by 'errorCheckers' - - Template.getUnknowns (new method): returns a list of Placeholder Names - missing in the Search List. (MO) - this change has been superceeded by - 'errorCheckers' - - made changes to Template.py, CodeGenerator.py, PlaceholderProcessor.py, - and TagProcessor.py to enable customization of the placeholderStartToken so - it can be set to any character sequence, rather than just the default '\$'. - This is configurable by the Template setting 'placeholderStartToken' (TR) - - fixed a small bug in PlaceholderProcessor.processTag() that prevented - static caching (i.e. \$\*) of a value containing ''' style quotes - - added #break and #continue (TR) - - fixed the relative path problem with #include when using Cheetah with WebKit - (TR) - - implemented the #stop directive (TR) - - fixed a bug in the macro processing that prevented macros defined inside - #includes from being visible at the top level (TR) - - fixed a bug in the handling of the setting 'useAutocalling' (TR) - - fixed some bugs in the handling of macros (TR) - - completed the transition to nested template #includes (TR) - - added direct #includes (TR) - - completed the transition to run-time evaluation (TR) - - renamed the .startServer() method of Template to .compile() (TR) - - renamed the 'delayedStart' setting as 'delayedCompile' (TR) - - added .redefineTemplateBlock as an alias to Template.defineTemplateBlock - (TR) - - got relative path includes working with Webware and Cheetah.Servlet (TR) - - lots of changes in the docs (TR & MO) - - implemented a C version of NameMapper (TR + CE) - - added the 'errorCheckers' framwork (TR) - - added the 'formatters' framework and the #formatter directive - - a major restructuring of the modules and internal API (TR) - - made sure that all the #directives with start and end tags are - implemented in such a way that they won't cause 'maximum recursion' limit - errors if their content block is long. Simple regexes didn't cut it in these - cases. (TR) - - - #macro - - multiline comments - - #data - - #block - - #raw - - the parsing of the core tags (the state-dependent ones) after they have been - translated to the internal delimiters - - - made a Template.shutdown() method for cleaning up reference cycles before a - template object is deleted. (TR) - - made the parsing and processing of #macros() more robust (TR) - - implemented the file update checking mechanism (TR) - NOTE, the syntax for the #include is now:: - - #include file = - ... uses the value of EXPR as the path of the file to include. - - #include - ... includes the value of the EXPR - - where is 'raw' or 'direct' - -0.9.7 (July 13, 2001) - - - reimplemented the parsing of \$placeholders using the Python tokenize module (TR) - - - now translates into Python code instead of going through NameMapper for - each request - - supports arg lists and nested placeholders - - maintained support for autocalling of functions and methods, - will do this serially for \$func.otherFunc, etc. - - - reimplemented the #include and #raw directives using nested templates for - parsed includes and string attributes of 'Template' to store raw text - The support for file update monitoring of includes is still not implemented (TR) - - moved some stuff from __init__.py into CHANGES and TODO (TR) - - added a new command 'sdist_docs' to setup.py which rebuilds the docs - when making a source distribution (TR) - - changed the name of the ./Cheetah dir to ./src (TR) - - fixed a bug in one of the code filters that was preventing commas from - being used between \$placeholders (TR) - - generalized the line ending regex for single-line comments (TR) - - corrected the spelling of 'Delimiters' throughout Cheetah (TR) - - made insertLines in Utilities.py more robust (Chuck) - - added key argument to raising some NotFound exceptions in NameMapper (Chuck) - - fixed strange bug involving missing templateObj parameter - in PlaceholderProcessor.py(Chuck) - - expanded on the docs (Mike) - -0.9.6 (June 12, 2001) - - - fixed a bug in NameMapper that was preventing 'obj.__class__.__name__' from mapping (TR) - -0.9.5 (June 10, 2001) - - - implemented the #cache directive - see the mailing list (TR) - - reworked the handling of cached \$placeholders and set \$var to mean NO_CACHE, - \$\*var to mean STATIC_CACHE, and \$\*15\*var to mean TIMED_REFRESH_CACHE (TR) - - renamed Template._getValueForName as Template.mapName (TR) - -0.9.4 (June 9, 2001) - - - created a SettingsManager base class to handle settings for the Template class (TR) - - moved the HTML docs icons into the same dir as the HTML (TR) - -0.9.3 - - - updated the User's Guide Makefile. Builds HTML, PDF, and PS in the ./docs dir now. (TR) - - changed the refs to 'Tavis Rudd' in the docs to 'The Cheetah Development Team' (TR) - - added a few bits to the docs (TR) - - did some internal renaming so 'nameMapperTags' are referred as 'placeholderTags' (TR) - - added the #slurp directive (TR) - -0.9.2 - - - got the PSP plugin working again. It still need test cases. (TR) - -0.9.1 - - - Changed the name of the package to 'Cheetah' from TemplateServer (TR) - - Changed the name of the Server module and its TemplateServer class to 'Template' (TR) - - Changed the name of the 'TScompile' script to 'cheetah-compile' (TR) - - updated the docs (TR) - -0.9.0 - - - changed the names and behaviour of the #parse and #include directives (TR) - see the docs for more. (TR) - - changed #verbatim to #raw (TR) - - fixed a bug in Tests.py that caused an error on the first run. (TR) - - more docs (TR + MO) - - ! all tests pass with Python 2.1 and 2.0 (TR) - -0.8.4 - - - changed the #directive end tags to #end if instead of #/if and #end (TR) - macro instead of #/macro (TR) - - more work on the User's Guide (TR) - - fixed a bug in TScompile (TR) - -0.8.3 - - - fixed a problem with the regexs that caused \$vars and #directives at the (TR) - very beginning of the template string not to match in Python 2.0 (TR) - - removed some Test cases that made invalid assumptions about the order (TR) - of items in dictionaries. (TR) - -0.8.2 - - - finished half of the User's Guide (TR) - - fixed several small bugs (TR) - - added the #comment directive and removed the old <# multiline comment tag #> (TR) - - changed the explicit directive closure to /# from ;# (TR) - -0.7.6 - - - several small bug fixes (TR) - - reimplemented the #block directive to avoid maximum recursion depth errors (TR) - with large blocks. (TR) - - created many new test cases in the regression testing suite (TR) - - added an example site to the examples/ directory (TR) - - started the User's Guide (TR) - -0.7.5 - - - implemented the command-line compiler (TR) - -0.7.3-4 - - - implemented the regression testing suite (TR) - - fixed a number of small bugs (TR) - -0.7.2 - - - implemented the #longMacro directive (TR) - - -KEY TO INITIALS USED ABOVE:: - - TR - Tavis Rudd - MO - Mike Orr - JJ - Shannon 'jj' Behrens - IB - Ian Bicking - CE - Chuck Esterbrook - MH - Mike Halle diff --git a/docs/html/_sources/recipes/inheritance.rst.txt b/docs/html/_sources/recipes/inheritance.rst.txt deleted file mode 100644 index 267fa1f..0000000 --- a/docs/html/_sources/recipes/inheritance.rst.txt +++ /dev/null @@ -1,62 +0,0 @@ -Basic Inheritance -================= - -Introduction ------------- -Cheetah, like Python, is an object-oriented language if you so choose to -use it in that fashion. That is to say that you can use Cheetah in with -object-oriented principles *or* you can use Cheetah in a strictly functional -sense, like Python, Cheetah does not place restrictions on these barriers. - -While Cheetah is not strictly Python, it was designed as such to interoperate, -particularly with the notion of classes, with Python itself. In effect you can -define Python classes that inherit and extend from Cheetah-derived classes and -vice versa. For this, Cheetah defines a few **directives** (denoted with the `\#` -hash-mark) that are of some help, the most important one being the `\#extends` -directive, with others playing important roles like `\#import`, `\#attr` and `\#super` - -In this recipe/tutorial I intend to explain and define a few key inheritance -patterns with Cheetah, being: - -* A Cheetah Template inheriting from Python -* Python inheriting from a Cheetah Template -* Cheetah Templates and "*mixins*" - -This document also operates on the assumption that the reader is at least -somewhat familiar with the basic tenets of object-oriented programming in -Python. - - -Cheetah inheriting from Python ------------------------------- -Whether or not you are aware of it, Cheetah templates are always inheriting from -a Python class by default. Unless otherwise denoted, Cheetah templates are compiled -to Python classes that subclass from the `Cheetah.Template.Template` class. - -What if you would like to introduce your own Template base class? Easily acheived by -defining your own Template class in a Python module, for example:: - - import Cheetah.Template - - class CookbookTemplate(Cheetah.Template.Template): - _page = 'Cookbook' - author = 'R. Tyler Ballance' - def pageName(self): - return self._page or 'Unknown' - -**Figure 1. cookbook.py** - -For this example, I want all my subclasses of the `CookbookTemplate` to define a -page author which will be used in some shared rendering code, to accomplish this -my templates will need to subclass from `CookbookTemplate` explicitly instead of -implicitly subclassing from `Cheetah.Template.Template`:: - - #import cookbook - #extends cookbook.CookbookTemplate - #attr author = 'Tavis Rudd' - - ## The rest of my recipe template would be below - -**Figure 2. recipe1.tmpl** - - diff --git a/docs/html/_sources/recipes/precompiled.rst.txt b/docs/html/_sources/recipes/precompiled.rst.txt deleted file mode 100644 index 7705106..0000000 --- a/docs/html/_sources/recipes/precompiled.rst.txt +++ /dev/null @@ -1,59 +0,0 @@ -Precompiled Templates -===================== - -Why bother? ------------ -Since Cheetah supports two basic modes: dynamic and precompiled templates, you have -a lot of options when it comes to utilizing Cheetah, particularly in web environments. - -There is added speed to be gained by using pre-compiled templates, especially when -using mod_python with Apache. Precompiling your templates means Apache/mod_python -can load your template's generated module into memory and then execution is only -limited by the speed of the Python being executed, and not the Cheetah compiler. -You can further optimize things by then pre-compiling the generated Python files -(.py) down to Python byte-code (.pyc) so save cycles interpreting the Python. - - -Basic Pre-compilation ---------------------- -Suppose you have a template that looks something like this:: - - #attr title = "This is my Template" - - - \${title} - - - Hello \${who}! - - -**Figure 1. hello.tmpl** - -In order to compile this down to a Python file, you need to only execute the -`cheetah compile hello.tmpl` command. The results will be a Python file (.py) -which you can then treat as any other Python module in your code base. - - -Importing and lookup --------------------- -Typically for the template in *Figure 1*, I could easily import it post-compilation -as any other Python module:: - - from templates import hello - - def myMethod(): - tmpl = hello.hello(searchList=[{'who' : 'world'}]) - results = tmpl.respond() - -**Figure 2. runner.py** - -*Note:* If you use the `\#implements` directive, `respond` may not be your "main -method" for executing the Cheetah template. You can adjust the example above in -*Figure 2* by using `getattr()` to make the lookup of the main method dynamic:: - - def myMethod(): - tmpl = hello.hello(searchList=[{'who' : 'world'}]) - mainMethod = getattr(tmpl, '_mainCheetahMethod_for_%s' % tmpl.__class__.__name__) - results = getattr(tmpl, mainMethod)() - -**Figure 3. Dynamic runner.py** diff --git a/docs/html/_sources/recipes/staticmethod.rst.txt b/docs/html/_sources/recipes/staticmethod.rst.txt deleted file mode 100644 index cf55ec1..0000000 --- a/docs/html/_sources/recipes/staticmethod.rst.txt +++ /dev/null @@ -1,54 +0,0 @@ -@staticmethod and @classmethod -============================== - -Refer the Python's documentation if you're unfamiliar with either -`@staticmethod `_ or -`@classmethod `_ and their uses in Python, as they -pertain to their uses in Cheetah as well. Using `@staticmethod `_ it's -trivial to create *utility templates* which are common when using -Cheetah for web development. These *utility templates* might contain -a number of small functions which generate useful snippets of markup. - -For example:: - - #def copyright() - #import time - © CheetahCorp, Inc. $time.strftime('%Y', time.gmtime()) - #end def - -**Figure 1, util.tmpl** - -Prior to version **v2.2.0** of Cheetah, there wasn't really an easy means -of filling templates with bunches of these small utility functions. In -**v2.2.0** however, you can decorate these methods with `#@staticmethod` -and use "proper" Python syntax for calling them, **fig 1** revisited:: - - #@staticmethod - #def copyright() - #import time - © CheetahCorp, Inc. $time.strftime('%Y', time.gmtime()) - #end def - -**Figure 1.1, util.tmpl** - -With the addition of the `@staticmethod `_ decorator, the `copyright()` -function can now be used without instantiating an instance of the `util` -template class. In effect:: - - #from util import util - - This is my page -
    -
    - $util.copyright() - -**Figure 2, index.tmpl** - - -This approach is however no means to structure anything complex, -`@staticmethod `_ and `@classmethod `_ use in Cheetah is not meant as a -replacement for properly structured class hierarchies (which -Cheetah supports). That said if you are building a web application -`@staticmethod `_/`@classmethod `_ are quite useful for the little snippets -of markup, etc that are needed (Google AdSense blocks, footers, -banners, etc). diff --git a/docs/html/_sources/recipes/writing_a_recipe.rst.txt b/docs/html/_sources/recipes/writing_a_recipe.rst.txt deleted file mode 100644 index 73d146a..0000000 --- a/docs/html/_sources/recipes/writing_a_recipe.rst.txt +++ /dev/null @@ -1,4 +0,0 @@ -Writing a "Recipe" -================== - -This document isn't quite there yet ;) diff --git a/docs/html/_sources/roadmap.rst.txt b/docs/html/_sources/roadmap.rst.txt deleted file mode 100644 index 5057742..0000000 --- a/docs/html/_sources/roadmap.rst.txt +++ /dev/null @@ -1,14 +0,0 @@ -Cheetah Roadmap -=============== - -Cheetah v3.0 -^^^^^^^^^^^^ -*in development* - -Cheetah v3.0 is for support for Python 2.7 and Python 3. - - -Cheetah v2 -^^^^^^^^^^ - -Old versions of Cheetah are no longer supported. diff --git a/docs/html/_sources/users_guide/comments.rst.txt b/docs/html/_sources/users_guide/comments.rst.txt deleted file mode 100644 index 5bd45dc..0000000 --- a/docs/html/_sources/users_guide/comments.rst.txt +++ /dev/null @@ -1,101 +0,0 @@ -Comments -======== - -(comments) - -Comments are used to mark notes, explanations, and decorative text -that should not appear in the output. Cheetah maintains the -comments in the Python module it generates from the Cheetah source -code. There are two forms of the comment directive: single-line and -multi-line. - -All text in a template definition that lies between two hash -characters ({##}) and the end of the line is treated as a -single-line comment and will not show up in the output, unless the -two hash characters are escaped with a backslash. - -:: - - ##============================= this is a decorative comment-bar - $var ## this is an end-of-line comment - ##============================= - -Any text between {#\*} and {\*#} will be treated as a multi-line -comment. - -:: - - #* - Here is some multiline - comment text - *# - -If you put blank lines around method definitions or loops to -separate them, be aware that the blank lines will be output as is. -To avoid this, make sure the blank lines are enclosed in a comment. -Since you normally have a comment before the next method definition -(right?), you can just extend that comment to include the blank -lines after the previous method definition, like so: - -:: - - #def method1 - ... lines ... - #end def - #* - - - Description of method2. - $arg1, string, a phrase. - *# - #def method2($arg1) - ... lines ... - #end def - -Docstring Comments ------------------- - -(comments.docstring) - -Python modules, classes, and methods can be documented with inline -'documentation strings' (aka 'docstrings'). Docstrings, unlike -comments, are accesible at run-time. Thus, they provide a useful -hook for interactive help utilities. - -Cheetah comments can be transformed into doctrings by adding one of -the following prefixes: - -:: - - ##doc: This text will be added to the method docstring - #*doc: If your template file is MyTemplate.tmpl, running "cheetah compile" - on it will produce MyTemplate.py, with a class MyTemplate in it, - containing a method .respond(). This text will be in the .respond() - method's docstring. *# - - ##doc-method: This text will also be added to .respond()'s docstring - #*doc-method: This text will also be added to .respond()'s docstring *# - - ##doc-class: This text will be added to the MyTemplate class docstring - #*doc-class: This text will be added to the MyTemplate class docstring *# - - ##doc-module: This text will be added to the module docstring MyTemplate.py - #*doc-module: This text will be added to the module docstring MyTemplate.py*# - -Header Comments ---------------- - -(comments.headers) Cheetah comments can also be transformed into -module header comments using the following syntax: - -:: - - ##header: This text will be added to the module header comment - #*header: This text will be added to the module header comment *# - -Note the difference between {##doc-module: } and {header: }: -"cheetah-compile" puts {##doc-module: } text inside the module -docstring. {header: } makes the text go { above} the docstring, as -a set of #-prefixed comment lines. - - diff --git a/docs/html/_sources/users_guide/comparisons.rst.txt b/docs/html/_sources/users_guide/comparisons.rst.txt deleted file mode 100644 index 6886035..0000000 --- a/docs/html/_sources/users_guide/comparisons.rst.txt +++ /dev/null @@ -1,515 +0,0 @@ -Cheetah vs. Other Template Engines -================================== - -(comparisons) - -This appendix compares Cheetah with various other template/emdedded -scripting languages and Internet development frameworks. As Cheetah -is similar to Velocity at a superficial level, you may also wish to -read comparisons between Velocity and other languages at -http://jakarta.apache.org/velocity/ymtd/ymtd.html. - -Which features are unique to Cheetah ------------------------------------- - -(comparisons.unique) - - -- The { block framework} (section inheritanceEtc.block) - -- Cheetah's powerful yet simple { caching framework} (section - output.caching) - -- Cheetah's { Unified Dotted Notation} and { autocalling} - (sections language.namemapper.dict and - language.namemapper.autocalling) - -- Cheetah's searchList (section language.searchList) information. - -- Cheetah's {#raw} directive (section output.raw) - -- Cheetah's {#slurp} directive (section output.slurp) - -- Cheetah's tight integration with Webware for Python (section - webware) - -- Cheetah's { SkeletonPage framework} (section - libraries.templates.skeletonPage) - -- Cheetah's ability to mix PSP-style code with Cheetah Language - syntax (section tips.PSP) Because of Cheetah's design and Python's - flexibility it is relatively easy to extend Cheetah's syntax with - syntax elements from almost any other template or embedded - scripting language. - - -Cheetah vs. Velocity --------------------- - -(comparisons.velocity) - -For a basic introduction to Velocity, visit -http://jakarta.apache.org/velocity. - -Velocity is a Java template engine. It's older than Cheetah, has a -larger user base, and has better examples and docs at the moment. -Cheetah, however, has a number of advantages over Velocity: - - -- Cheetah is written in Python. Thus, it's easier to use and - extend. - -- Cheetah's syntax is closer to Python's syntax than Velocity's is - to Java's. - -- Cheetah has a powerful caching mechanism. Velocity has no - equivalent. - -- It's far easier to add data/objects into the namespace where - $placeholder values are extracted from in Cheetah. Velocity calls - this namespace a 'context'. Contexts are dictionaries/hashtables. - You can put anything you want into a context, BUT you have to use - the .put() method to populate the context; e.g., - - :: - - VelocityContext context1 = new VelocityContext(); - context1.put("name","Velocity"); - context1.put("project", "Jakarta"); - context1.put("duplicate", "I am in context1"); - - Cheetah takes a different approach. Rather than require you to - manually populate the 'namespace' like Velocity, Cheetah will - accept any existing Python object or dictionary AS the 'namespace'. - Furthermore, Cheetah allows you to specify a list namespaces that - will be searched in sequence to find a varname-to-value mapping. - This searchList can be extended at run-time. - - If you add a 'foo' object to the searchList and the 'foo' has an - attribute called 'bar', you can simply type {$bar} in the template. - If the second item in the searchList is dictionary 'foofoo' - containing {{'spam':1234, 'parrot':666}}, Cheetah will first look - in the 'foo' object for a 'spam' attribute. Not finding it, Cheetah - will then go to 'foofoo' (the second element in the searchList) and - look among its dictionary keys for 'spam'. Finding it, Cheetah will - select {foofoo['spam']} as {$spam}'s value. - -- In Cheetah, the tokens that are used to signal the start of - $placeholders and #directives are configurable. You can set them to - any character sequences, not just $ and #. - - -Cheetah vs. WebMacro --------------------- - -(comparisons.webmacro) - -For a basic introduction to WebMacro, visit http://webmacro.org. - -The points discussed in section comparisons.velocity also apply to -the comparison between Cheetah and WebMacro. For further -differences please refer to -http://jakarta.apache.org/velocity/differences.html. - -Cheetah vs. Zope's DTML ------------------------ - -(comparisons.dtml) - -For a basic introduction to DTML, visit -http://www.zope.org/Members/michel/ZB/DTML.dtml. - - -- Cheetah is faster than DTML. - -- Cheetah does not use HTML-style tags; DTML does. Thus, Cheetah - tags are visible in rendered HTML output if something goes wrong. - -- DTML can only be used with ZOPE for web development; Cheetah can - be used as a standalone tool for any purpose. - -- Cheetah's documentation is more complete than DTML's. - -- Cheetah's learning curve is shorter than DTML's. - -- DTML has no equivalent of Cheetah's blocks, caching framework, - unified dotted notation, and {#raw} directive. - - -Here are some examples of syntax differences between DTML and -Cheetah: - -:: - -
      - -
    • -
      -
    - -:: - -
      - #for $animal_name in $frogQuery -
    • $animal_name
    • - #end for -
    - -:: - - -

    There are too many monkeys!

    - -

    There aren't enough monkeys!

    - -

    There are just enough monkeys.

    -
    - -:: - - #if $monkeys > $monkey_limit -

    There are too many monkeys!

    - #else if $monkeys < $minimum_monkeys -

    There aren't enough monkeys!

    - #else -

    There are just enough monkeys.

    - #end if - -:: - - - - - - - - - - -
    - -
    - -:: - - - #set $evenRow = 0 - #for $file in $files('File') - #if $evenRow - - #set $evenRow = 0 - #else - - #set $evenRow = 1 - #end if - - #end for -
    - $file.title_or_id -
    - -The last example changed the name of {$objectValues} to {$files} -because that's what a Cheetah developer would write. The developer -would be responsible for ensuring {$files} returned a list (or -tuple) of objects (or dictionaries) containing the attributes (or -methods or dictionary keys) 'absolute\_url' and 'title\_or\_id'. -All these names ('objectValues', 'absolute\_url' and -'title\_or\_id') are standard parts of Zope, but in Cheetah the -developer is in charge of writing them and giving them a reasonable -behaviour. - -Some of DTML's features are being ported to Cheetah, such as -{Cheetah.Tools.MondoReport}, which is based on the {} tag. -We are also planning an output filter as flexible as the -{} formatting options. However, neither of these are -complete yet. - -Cheetah vs. Zope Page Templates -------------------------------- - -(comparisons.zpt) - -For a basic introduction to Zope Page Templates, please visit -http://www.zope.org/Documentation/Articles/ZPT2. - -Cheetah vs. PHP's Smarty templates ----------------------------------- - -(comparisons.smarty) - -PHP (http://www.php.net/) is one of the few scripting languages -expressly designed for web servlets. However, it's also a -full-fledged programming language with libraries similar to -Python's and Perl's. The syntax and functions are like a cross -between Perl and C plus some original ideas (e.g.; a single array -type serves as both a list and a dictionary, ``$arr[]="value";`` -appends to an array). - -Smarty (http://smarty.php.net/) is an advanced template engine for -PHP. ({ Note:} this comparision is based on Smarty's on-line -documentation. The author has not used Smarty. Please send -corrections or ommissions to the Cheetah mailing list.) Like -Cheetah, Smarty: - - -- compiles to the target programming language (PHP). - -- has configurable delimeters. - -- passes if-blocks directly to PHP, so you can use any PHP - expression in them. - -- allows you to embed PHP code in a template. - -- has a caching framework (although it works quite differently). - -- can read the template definition from any arbitrary source. - - -Features Smarty has that Cheetah lacks: - - -- Preprocessors, postprocessors and output filters. You can - emulate a preprocessor in Cheetah by running your template - definition through a filter program or function before Cheetah sees - it. To emulate a postprocessor, run a .py template module through a - filter program/function. To emulate a Smarty output filter, run the - template output through a filter program/function. If you want to - use "cheetah compile" or "cheetah fill" in a pipeline, use {-} as - the input file name and {-stdout} to send the result to standard - output. Note that Cheetah uses the term "output filter" differently - than Smarty: Cheetah output filters ({#filter}) operate on - placeholders, while Smarty output filters operate on the entire - template output. There has been a proposed {#sed} directive that - would operate on the entire output line by line, but it has not - been implemented. - -- Variable modifiers. In some cases, Python has equivalent string - methods ({.strip}, {.capitalize}, {.replace(SEARCH, REPL)}), but in - other cases you must wrap the result in a function call or write a - custom output filter ({#filter}). - -- Certain web-specific functions, which can be emulated with - third-party functions. - -- The ability to "plug in" new directives in a modular way. - Cheetah directives are tightly bound to the compiler. However, - third-party { functions} can be freely imported and called from - placeholders, and { methods} can be mixed in via {#extends}. Part - of this is because Cheetah distinguishes between functions and - directives, while Smarty treats them all as "functions". Cheetah's - design does not allow functions to have flow control effect outside - the function (e.g., {#if} and {#for}, which operate on template - body lines), so directives like these cannot be encoded as - functions. - -- Configuration variables read from an .ini-style file. The - {Cheetah.SettingsManager} module can parse such a file, but you'd - have to invoke it manually. (See the docstrings in the module for - details.) In Smarty, this feature is used for multilingual - applications. In Cheetah, the developers maintain that everybody - has their own preferred way to do this (such as using Python's - {gettext} module), and it's not worth blessing one particular - strategy in Cheetah since it's easy enough to integrate third-party - code around the template, or to add the resulting values to the - searchList. - - -Features Cheetah has that Smarty lacks: - - -- Saving the compilation result in a Python (PHP) module for quick - reading later. - -- Caching individual placeholders or portions of a template. - Smarty caches only the entire template output as a unit. - - -Comparisions of various Smarty constructs: - -:: - - {assign var="name" value="Bob"} (#set has better syntax in the author's opinion) - counter (looks like equivalent to #for) - eval (same as #include with variable) - fetch: insert file content into output (#include raw) - fetch: insert URL content into output (no euqivalent, user can write - function calling urllib, call as $fetchURL('URL') ) - fetch: read file into variable (no equivalent, user can write function - based on the 'open/file' builtin, or on .getFileContents() in - Template.) - fetch: read URL content into variable (no equivalent, use above - function and call as: #set $var = $fetchURL('URL') - html_options: output an HTML option list (no equivalent, user can - write custom function. Maybe FunFormKit can help.) - html_select_date: output three dropdown controls to specify a date - (no equivalent, user can write custom function) - html_select_time: output four dropdown controls to specify a time - (no equvalent, user can write custom function) - math: eval calculation and output result (same as #echo) - math: eval calculation and assign to variable (same as #set) - popup_init: library for popup windows (no equivalent, user can write - custom method outputting Javascript) - - - Other commands: - capture (no equivalent, collects output into variable. A Python - program would create a StringIO instance, set sys.stdout to - it temporarily, print the output, set sys.stdout back, then use - .getvalue() to get the result.) - config_load (roughly analagous to #settings, which was removed - from Cheetah. Use Cheetah.SettingsManager manually or write - a custom function.) - include (same as #include, but can include into variable. - Variables are apparently shared between parent and child.) - include_php: include a PHP script (e.g., functions) - (use #extends or #import instead) - insert (same as #include not in a #cache region) - {ldelim}{rdelim} (escape literal $ and # with a backslash, - use #compiler-settings to change the delimeters) - literal (#raw) - php (``<% %>'' tags) - section (#for $i in $range(...) ) - foreach (#for) - strip (like the #sed tag which was never implemented. Strips - leading/trailing whitespace from lines, joins several lines - together.) - - - Variable modifiers: - capitalize ( $STRING.capitalize() ) - count_characters ( $len(STRING) ) - count_paragraphs/sentances/words (no equivalent, user can write function) - date_format (use 'time' module or download Egenix's mx.DateTime) - default ($getVar('varName', 'default value') ) - escape: html encode ($cgi.escape(VALUE) ) - escape: url encode ($urllib.quote_plus(VALUE) ) - escape: hex encode (no equivalent? user can write function) - escape: hex entity encode (no equivalent? user can write function) - indent: indent all lines of a var's output (may be part of future - #indent directive) - lower ($STRING.lower() ) - regex_replace ('re' module) - replace ($STRING.replace(OLD, NEW, MAXSPLIT) ) - spacify (#echo "SEPARATOR".join(SEQUENCE) ) - string_format (#echo "%.2f" % FLOAT , etc.) - strip_tags (no equivalent, user can write function to strip HTML tags, - or customize the WebSafe filter) - truncate (no equivalent, user can write function) - upper ($STRING.upper() ) - wordwrap ('writer' module, or a new module coming in Python 2.3) - -Some of these modifiers could be added to the super output filter -we want to write someday. - -Cheetah vs. PHPLib's Template class ------------------------------------ - -(comparisons.php) - -PHPLib ((http://phplib.netuse.de/) is a collection of classes for -various web objects (authentication, shopping cart, sessions, etc), -but what we're interested in is the {Template} object. It's much -more primitive than Smarty, and was based on an old Perl template -class. In fact, one of the precursors to Cheetah was based on it -too. Differences from Cheetah: - - -- Templates consist of text with {{placeholders}} in braces. - -- Instead of a searchList, there is one flat namespace. Every - variable must be assigned via the {set\_var} method. However, you - can pass this method an array (dictionary) of several variables at - once. - -- You cannot embed lookups or calculations into the template. - Every placeholder must be an exact variable name. - -- There are no directives. You must do all display logic (if, for, - etc) in the calling routine. - -- There is, however, a "block" construct. A block is a portion of - text between the comment markers { ... }. The {set\_block} method extracts this text into a - namespace variable and puts a placeholder referring to it in the - template. This has a few parallels with Cheetah's {#block} - directive but is overall quite different. - -- To do the equivalent of {#if}, extract the block. Then if true, - do nothing. If false, assign the empty string to the namespace - variable. - -- To do the equivalent of {#for}, extract the block. Set any - namespace variables needed inside the loop. To parse one iteration, - use the {parse} method to fill the block variable (a mini-template) - into another namespace variable, appending to it. Refresh the - namespace variables needed inside the loop and parse again; repeat - for each iteration. You'll end up with a mini-result that will be - plugged into the main template's placeholder. - -- To read a template definition from a file, use the {set\_file} - method. This places the file's content in a namespace variable. To - read a template definition from a string, assign it to a namespace - variable. - -- Thus, for complicated templates, you are doing a lot of - recursive block filling and file reading and parsing mini-templates - all into one flat namespace as you finally build up values for the - main template. In Cheetah, all this display logic can be embedded - into the template using directives, calling out to Python methods - for the more complicated tasks. - -- Although you can nest blocks in the template, it becomes tedious - and arguably hard to read, because all blocks have identical - syntax. Unless you choose your block names carefully and put - comments around them, it's hard to tell which blocks are if-blocks - and which are for-blocks, or what their nesting order is. - -- PHPLib templates do not have caching, output filters, etc. - - -Cheetah vs. PSP, PHP, ASP, JSP, Embperl, etc. ---------------------------------------------- - -(comparisons.pspEtc) - -Webware's PSP Component - - http://webware.sourceforge.net/Webware/PSP/Docs/ - -Tomcat JSP Information - - http://jakarta.apache.org/tomcat/index.html - -ASP Information at ASP101 - - http://www.asp101.com/ - -Embperl - - http://perl.apache.org/embperl/ - - -Here's a basic Cheetah example: - -:: - - - #for $client in $service.clients - - - - - #end for -
    $client.surname, $client.firstname$client.email
    - -Compare this with PSP: - -:: - - - <% for client in service.clients(): %> - - - - - <%end%> -
    <%=client.surname()%>, <%=client.firstname()%><%=client.email()%>
    - - diff --git a/docs/html/_sources/users_guide/editors.rst.txt b/docs/html/_sources/users_guide/editors.rst.txt deleted file mode 100644 index 35bf0a5..0000000 --- a/docs/html/_sources/users_guide/editors.rst.txt +++ /dev/null @@ -1,37 +0,0 @@ -Visual Editors -============== - -(visualEditors) - -This chapter is about maintaining Cheetah templates with visual -editors, and the tradeoffs between making it friendly to both text -editors and visual editors. - -Cheetah's main developers do not use visual editors. Tavis uses -{emacs}; Mike uses {vim}. So our first priority is to make -templates easy to maintain in text editors. In particular, we don't -want to add features like Zope Page Template's -placeholder-value-with-mock-text-for-visual-editors-all-in-an-XML-tag. -The syntax is so verbose it makes for a whole lotta typing just to -insert a simple placeholder, for the benefit of editors we never -use. However, as users identify features which would help their -visual editing without making it harder to maintain templates in a -text editor, we're all for it. - -As it said in the introduction, Cheetah purposely does not use -HTML/XML tags for $placeholders or #directives. That way, when you -preview the template in an editor that interprets HTML tags, you'll -still see the placeholder and directive source definitions, which -provides some "mock text" even if it's not the size the final -values will be, and allows you to use your imagination to translate -how the directive output will look visually in the final. - -If your editor has syntax highlighting, turn it on. That makes a -big difference in terms of making the template easier to edit. -Since no "Cheetah mode" has been invented yet, set your -highlighting to Perl mode, and at least the directives/placeholders -will show up in different colors, although the editor won't -reliably guess where the directive/placeholder ends and normal text -begins. - - diff --git a/docs/html/_sources/users_guide/errorHandling.rst.txt b/docs/html/_sources/users_guide/errorHandling.rst.txt deleted file mode 100644 index 752c5b5..0000000 --- a/docs/html/_sources/users_guide/errorHandling.rst.txt +++ /dev/null @@ -1,144 +0,0 @@ -Error Handling -============== - -(errorHandling) - -There are two ways to handle runtime errors (exceptions) in -Cheetah. The first is with the Cheetah directives that mirror -Python's structured exception handling statements. The second is -with Cheetah's {ErrorCatcher} framework. These are described -below. - -#try ... #except ... #end try, #finally, and #assert ----------------------------------------------------- - -(errorHandling.directives) - -Cheetah's exception-handling directives are exact mirrors Python's -exception-handling statements. See Python's documentation for -details. The following Cheetah code demonstrates their use: - -:: - - #try - $mightFail() - #except - It failed - #end try - - #try - #assert $x == $y - #except AssertionError - They're not the same! - #end try - - #try - #raise ValueError - #except ValueError - #pass - #end try - - - #try - $mightFail() - #except ValueError - Hey, it raised a ValueError! - #except NameMapper.NotFound - Hey, it raised a NameMapper.NotFound! - #else - It didn't raise anything! - #end try - - #try - $mightFail() - #finally - $cleanup() - #end try - -Like Python, {#except} and {#finally} cannot appear in the same -try-block, but can appear in nested try-blocks. - -#errorCatcher and ErrorCatcher objects --------------------------------------- - -(errorHandling.errorCatcher) - -Syntax: - -:: - - #errorCatcher CLASS - #errorCatcher $PLACEHOLDER_TO_AN_ERROR_CATCHER_INSTANCE - -{ErrorCatcher} is a debugging tool that catches exceptions that -occur inside {$placeholder} tags and provides a customizable -warning to the developer. Normally, the first missing namespace -value raises a {NameMapper.NotFound} error and halts the filling of -the template. This requires the developer to resolve the exceptions -in order without seeing the subsequent output. When an -{ErrorCatcher} is enabled, the developer can see all the exceptions -at once as well as the template output around them. - -The {Cheetah.ErrorCatchers} module defines the base class for -ErrorCatchers: - -:: - - class ErrorCatcher: - _exceptionsToCatch = (NameMapper.NotFound,) - - def __init__(self, templateObj): - pass - - def exceptions(self): - return self._exceptionsToCatch - - def warn(self, exc_val, code, rawCode, lineCol): - return rawCode - -This ErrorCatcher catches {NameMapper.NotFound} exceptions and -leaves the offending placeholder visible in its raw form in the -template output. If the following template is executed: - -:: - - #errorCatcher Echo - #set $iExist = 'Here I am!' - Here's a good placeholder: $iExist - Here's bad placeholder: $iDontExist - -the output will be: - -:: - - Here's a good placeholder: Here I am! - Here's bad placeholder: $iDontExist - -The base class shown above is also accessible under the alias -{Cheetah.ErrorCatchers.Echo}. {Cheetah.ErrorCatchers} also provides -a number of specialized subclasses that warn about exceptions in -different ways. {Cheetah.ErrorCatchers.BigEcho} will output - -:: - - Here's a good placeholder: Here I am! - Here's bad placeholder: ===============<$iDontExist could not be found>=============== - -ErrorCatcher has a significant performance impact and is turned off -by default. It can also be turned on with the {Template} class' -{'errorCatcher'} keyword argument. The value of this argument -should either be a string specifying which of the classes in -{Cheetah.ErrorCatchers} to use, or a class that subclasses -{Cheetah.ErrorCatchers.ErrorCatcher}. The {#errorCatcher} directive -can also be used to change the errorCatcher part way through a -template. - -{Cheetah.ErrorCatchers.ListErrors} will produce the same ouput as -{Echo} while maintaining a list of the errors that can be retrieved -later. To retrieve the list, use the {Template} class' -{'errorCatcher'} method to retrieve the errorCatcher and then call -its {listErrors} method. - -ErrorCatcher doesn't catch exceptions raised inside directives. - - diff --git a/docs/html/_sources/users_guide/examples.rst.txt b/docs/html/_sources/users_guide/examples.rst.txt deleted file mode 100644 index 7304cd1..0000000 --- a/docs/html/_sources/users_guide/examples.rst.txt +++ /dev/null @@ -1,27 +0,0 @@ -Examples -======== - -(examples) - -The Cheetah distribution comes with an 'examples' directory. Browse -the files in this directory and its subdirectories for examples of -how Cheetah can be used. - -Syntax examples ---------------- - -The {Cheetah.Tests} module contains a large number of test cases -that can double as examples of how the Cheetah Language works. To -view these cases go to the base directory of your Cheetah -distribution and open the file {Cheetah/Tests/SyntaxAndOutput.py} -in a text editor. - -Webware Examples ----------------- - -For examples of Cheetah in use with Webware visit the Cheetah and -Webware wikis or use google. We used to have more examples in the -cheetah source tarball, but they were out of date and confused -people. - - diff --git a/docs/html/_sources/users_guide/flowControl.rst.txt b/docs/html/_sources/users_guide/flowControl.rst.txt deleted file mode 100644 index dbaecd3..0000000 --- a/docs/html/_sources/users_guide/flowControl.rst.txt +++ /dev/null @@ -1,436 +0,0 @@ -Flow Control -============ - -(flowControl) - -#for ... #end for ------------------ - -(flowControl.for) - -Syntax: - -:: - - #for $var in EXPR - #end for - -The {#for} directive iterates through a sequence. The syntax is the -same as Python, but remember the {$} before variables. - -Here's a simple client listing: - -:: - - - #for $client in $service.clients - - - - - #end for -
    $client.surname, $client.firstname$client.email
    - -Here's how to loop through the keys and values of a dictionary: - -:: - -
    -    #for $key, $value in $dict.items()
    -    $key: $value
    -    #end for
    -    
    - -Here's how to create list of numbers separated by hyphens. This -"#end for" tag shares the last line to avoid introducing a newline -character after each hyphen. - -:: - - #for $i in range(15) - $i - #end for - -If the location of the {#end for} offends your sense of -indentational propriety, you can do this instead: - -:: - - #for $i in $range(15) - $i - #slurp - #end for - -The previous two examples will put an extra hyphen after last -number. Here's how to get around that problem, using the {#set} -directive, which will be dealt with in more detail below. - -:: - - #set $sep = '' - #for $name in $names - $sep$name - #set $sep = ', ' - #end for - -Although to just put a separator between strings, you don't need a -for loop: - -:: - - #echo ', '.join($names) - -#repeat ... #end repeat ------------------------ - -(flowControl.repeat) - -Syntax: - -:: - - #repeat EXPR - #end repeat - -Do something a certain number of times. The argument may be any -numeric expression. If it's zero or negative, the loop will execute -zero times. - -:: - - #repeat $times + 3 - She loves me, she loves me not. - #repeat - She loves me. - -Inside the loop, there's no way to tell which iteration you're on. -If you need a counter variable, use {#for} instead with Python's -{range} function. Since Python's ranges are base 0 by default, -there are two ways to start counting at 1. Say we want to count -from 1 to 5, and that {$count} is 5. - -:: - - #for $i in $range($count) - #set $step = $i + 1 - $step. Counting from 1 to $count. - #end for - - - #for $i in $range(1, $count + 1) - $i. Counting from 1 to $count. - #end for - -A previous implementation used a local variable {$i} as the repeat -counter. However, this prevented instances of {#repeat} from being -nested. The current implementation does not have this problem as it -uses a new local variable for every instance of {#repeat}. - -#while ... #end while ---------------------- - -(flowControl.while) - -Syntax: - -:: - - #while EXPR - #end while - -{#while} is the same as Python's {while} statement. It may be -followed by any boolean expression: - -:: - - #while $someCondition('arg1', $arg2) - The condition is true. - #end while - -Be careful not to create an infinite loop. {#while 1} will loop -until the computer runs out of memory. - -#if ... #else if ... #else ... #end if --------------------------------------- - -(flowControl.if) - -Syntax: - -:: - - #if EXPR - #else if EXPR - #elif EXPR - #else - #end if - -The {#if} directive and its kin are used to display a portion of -text conditionally. {#if} and {#else if} should be followed by a -true/false expression, while {#else} should not. Any valid Python -expression is allowed. As in Python, the expression is true unless -it evaluates to 0, '', None, an empty list, or an empty dictionary. -In deference to Python, {#elif} is accepted as a synonym for {#else -if}. - -Here are some examples: - -:: - - #if $size >= 1500 - It's big - #else if $size < 1500 and $size > 0 - It's small - #else - It's not there - #end if - -:: - - #if $testItem($item) - The item $item.name is OK. - #end if - -Here's an example that combines an {#if} tag with a {#for} tag. - -:: - - #if $people - - - - - - - #for $p in $people - - - - - - #end for -
    NameAddressPhone
    $p.name$p.address$p.phone
    - #else -

    Sorry, the search did not find any people.

    - #end if - -See section output.oneLineIf for the one-line {#if} directive, -which is equivalent to Perl's and C's {?:} operator. - -#unless ... #end unless ------------------------ - -(flowControl.unless) - -Syntax: - -:: - - #unless EXPR - #end unless - -{#unless} is the opposite of {#if}: the text is executed if the -condition is { false}. Sometimes this is more convenient. {#unless -EXPR} is equivalent to {#if not (EXPR)}. - -:: - - #unless $alive - This parrot is no more! He has ceased to be! - 'E's expired and gone to meet 'is maker! ... - THIS IS AN EX-PARROT!! - #end unless - -You cannot use {#else if} or {#else} inside an {#unless} construct. -If you need those, use {#if} instead. - -#break and #continue --------------------- - -(flowControl.break) - -Syntax: - -:: - - #break - #continue - -These directives are used as in Python. {#break} will exit a {#for} -loop prematurely, while {#continue} will immediately jump to the -next iteration in the {#for} loop. - -In this example the output list will not contain "10 -". - -:: - - #for $i in range(15) - #if $i == 10 - #continue - #end if - $i - #slurp - #end for - -In this example the loop will exit if it finds a name that equals -'Joe': - -:: - - #for $name in $names - #if $name == 'Joe' - #break - #end if - $name - #slurp - #end for - -#pass ------ - -(flowControl.pass) - -Syntax: - -:: - - #pass - -The {#pass} directive is identical to Python {pass} statement: it -does nothing. It can be used when a statement is required -syntactically but the program requires no action. - -The following example does nothing if only $A is true - -:: - - #if $A and $B - do something - #elif $A - #pass - #elif $B - do something - #else - do something - #end if - -#stop ------ - -(flowControl.stop) - -Syntax: - -:: - - #stop - -The {#stop} directive is used to stop processing of a template at a -certain point. The output will show { only} what has been processed -up to that point. - -When {#stop} is called inside an {#include} it skips the rest of -the included code and continues on from after the {#include} -directive. stop the processing of the included code. Likewise, when -{#stop} is called inside a {#def} or {#block}, it stops only the -{#def} or {#block}. - -:: - - A cat - #if 1 - sat on a mat - #stop - watching a rat - #end if - in a flat. - -will print - -:: - - A cat - sat on a mat - -And - -:: - - A cat - #block action - sat on a mat - #stop - watching a rat - #end block - in a flat. - -will print - -:: - - A cat - sat on a mat - in a flat. - -#return -------- - -(flowControl.return) - -Syntax: - -:: - - #return - -This is used as in Python. {#return} will exit the current method -with a default return value of {None} or the value specified. It -may be used only inside a {#def} or a {#block}. - -Note that {#return} is different from the {#stop} directive, which -returns the sum of all text output from the method in which it is -called. The following examples illustrate this point: - -:: - - 1 - $test[1] - 3 - #def test - 1.5 - #if 1 - #return '123' - #else - 99999 - #end if - #end def - -will produce - -:: - - 1 - 2 - 3 - -while - -:: - - 1 - $test - 3 - #def test - 1.5 - #if 1 - #stop - #else - 99999 - #end if - #end def - -will produce - -:: - - 1 - 1.5 - 3 - - diff --git a/docs/html/_sources/users_guide/gettingStarted.rst.txt b/docs/html/_sources/users_guide/gettingStarted.rst.txt deleted file mode 100644 index de4159f..0000000 --- a/docs/html/_sources/users_guide/gettingStarted.rst.txt +++ /dev/null @@ -1,284 +0,0 @@ -Getting Started -=============== - -(gettingStarted) - -Requirements ------------- - -(gettingStarted.requirements) - -Cheetah requires Python release 2.7 (there are plans to support 3.4+). -It is known to run on Linux, Windows, FreeBSD and Solaris, -and should run anywhere Python runs. - -99% of Cheetah is written in Python. There is one small C module -({\_namemapper.so}) for speed, but Cheetah automatically falls back -to a Python equivalent ({NameMapper.py}) if the C module is not -available. - -Cheetah can use an additional module Markdown but it's not strictly required. - -Installation ------------- - -(gettingStarted.install) - -To install Cheetah in your system-wide Python library: - - -#. Login as a user with privileges to install system-wide Python - packages. On POSIX systems (AIX, Solaris, Linux, IRIX, etc.), the - command is normally 'su root'. On non-POSIX systems such as Windows - NT, login as an administrator. - -#. Run {pip install Cheetah3} at the command prompt. - -#. Or download source code and run {python setup.py install}. - -#. The setup program will install the wrapper script { cheetah} to - wherever it usually puts Python binaries ("/usr/bin/", "bin/" in - the Python install directory, etc.) - -#. If you cannot login as as an administrator install Cheetah as user to your - own home directory: add option {--user} to commands: either - {pip install --user Cheetah3} or {python setup.py install --user}. - -Cheetah's installation is managed by Python's Distribution -Utilities ('distutils'). There are many options for customization. -Type {python setup.py help} for more information. - -To install Cheetah in an alternate location - someplace outside -Python's {site-packages/} directory, use one of these options: - -:: - - python setup.py install --home /home/tavis - python setup.py install --install-lib /home/tavis/lib/python - -Either way installs to /home/tavis/lib/python/Cheetah/ . Of course, -/home/tavis/lib/python must be in your Python path in order for -Python to find Cheetah. - -Files ------ - -(gettingstarted.files) - -If you do the systemwide install, all Cheetah modules are installed -in the { site-packages/Cheetah/} subdirectory of your standard -library directory; e.g., -/opt/Python2.2/lib/python2.2/site-packages/Cheetah. - -Two commands are installed in Python's {bin/} directory or a system -bin directory: {cheetah} (section gettingStarted.cheetah) and -{cheetah-compile} (section howWorks.cheetah-compile). - -Uninstalling ------------- - -(gettingstarted.uninstalling) - -To uninstall Cheetah, merely delete the site-packages/Cheetah/ -directory. Then delete the "cheetah" and "cheetah-compile" commands -from whichever bin/ directory they were put in. - -The 'cheetah' command ---------------------- - -(gettingStarted.cheetah) - -Cheetah comes with a utility {cheetah} that provides a command-line -interface to various housekeeping tasks. The command's first -argument is the name of the task. The following commands are -currently supported: - -:: - - cheetah compile [options] [FILES ...] : Compile template definitions - cheetah fill [options] [FILES ...] : Fill template definitions - cheetah help : Print this help message - cheetah options : Print options help message - cheetah test : Run Cheetah's regression tests - cheetah version : Print Cheetah version number - -You only have to type the first letter of the command: {cheetah c} -is the same as {cheetah compile}. - -The test suite is described in the next section. The {compile} -command will be described in section howWorks.cheetah-compile, and -the {fill} command in section howWorks.cheetah-fill. - -The depreciated {cheetah-compile} program does the same thing as -{cheetah compile}. - -Testing your installation -------------------------- - -(gettingStarted.test) - -After installing Cheetah, you can run its self-test routine to -verify it's working properly on your system. Change directory to -any directory you have write permission in (the tests write -temporary files). Do not run the tests in the directory you -installed Cheetah from, or you'll get unnecessary errors. Type the -following at the command prompt: - -:: - - cheetah test - -The tests will run for about three minutes and print a -success/failure message. If the tests pass, start Python in -interactive mode and try the example in the next section. - -Certain test failures are insignificant: - - Python 2.3 changed the string representation of booleans, and the - tests haven't yet been updated to reflect this. - - Certain tests run "cheetah" as a subcommand. The failure may mean - the command wasn't found in your system path. (What happens if you - run "cheetah" on the command line?) The failure also happens on - some Windows systems for unknown reasons. This failure has never - been observed outside the test suite. Long term, we plan to rewrite - the tests to do a function call rather than a subcommand, which - will also make the tests run significantly faster. - - The test tried to write a temporary module in the current directory - and {import} it. Reread the first paragraph in this section about - the current directory. - - May be the same problem as SampleBaseClass; let us know if changing - the current directory doesn't work. - - -If any other tests fail, please send a message to the e-mail list -with a copy of the test output and the following details about your -installation: - - -#. your version of Cheetah - -#. your version of Python - -#. your operating system - -#. whether you have changed anything in the Cheetah installation - - -Quickstart tutorial -------------------- - -(gettingStarted.tutorial) - -This tutorial briefly introduces how to use Cheetah from the Python -prompt. The following chapters will discuss other ways to use -templates and more of Cheetah's features. - -The core of Cheetah is the {Template} class in the -{Cheetah.Template} module. The following example shows how to use -the {Template} class in an interactive Python session. {t} is the -Template instance. Lines prefixed with {>>>} and {...} are user -input. The remaining lines are Python output. - -:: - - >>> from Cheetah.Template import Template - >>> templateDef = """ - ... - ... $title - ... - ... $contents - ... ## this is a single-line Cheetah comment and won't appear in the output - ... #* This is a multi-line comment and won't appear in the output - ... blah, blah, blah - ... *# - ... - ... """ - >>> nameSpace = {'title': 'Hello World Example', 'contents': 'Hello World!'} - >>> t = Template(templateDef, searchList=[nameSpace]) - >>> print t - - - Hello World Example - - Hello World! - - - >>> print t # print it as many times as you want - [ ... same output as above ... ] - >>> nameSpace['title'] = 'Example #2' - >>> nameSpace['contents'] = 'Hiya Planet Earth!' - >>> print t # Now with different plug-in values. - - Example #2 - - Hiya Planet Earth! - - - -Since Cheetah is extremely flexible, you can achieve the same -result this way: - -:: - - >>> t2 = Template(templateDef) - >>> t2.title = 'Hello World Example!' - >>> t2.contents = 'Hello World' - >>> print t2 - [ ... same output as the first example above ... ] - >>> t2.title = 'Example #2' - >>> t2.contents = 'Hello World!' - >>> print t2 - [ ... same as Example #2 above ... ] - -Or this way: - -:: - - >>> class Template3(Template): - >>> title = 'Hello World Example!' - >>> contents = 'Hello World!' - >>> t3 = Template3(templateDef) - >>> print t3 - [ ... you get the picture ... ] - -The template definition can also come from a file instead of a -string, as we will see in section howWorks.constructing. - -The above is all fine for short templates, but for long templates -or for an application that depends on many templates in a -hierarchy, it's easier to store the templates in separate \*.tmpl -files and use the { cheetah compile} program to convert them into -Python classes in their own modules. This will be covered in -section howWorks.cheetah-compile. - -As an appetizer, we'll just briefly mention that you can store -constant values { inside} the template definition, and they will be -converted to attributes in the generated class. You can also create -methods the same way. You can even use inheritance to arrange your -templates in a hierarchy, with more specific templates overriding -certain parts of more general templates (e.g., a "page" template -overriding a sidebar in a "section" template). - -For the minimalists out there, here's a template definition, -instantiation and filling all in one Python statement: - -:: - - >>> print Template("Templates are pretty useless without placeholders.") - Templates are pretty useless without placeholders. - -You use a precompiled template the same way, except you don't -provide a template definition since it was already established: - -:: - - from MyPrecompiledTemplate import MyPrecompiledTemplate - t = MyPrecompiledTemplate() - t.name = "Fred Flintstone" - t.city = "Bedrock City" - print t - - diff --git a/docs/html/_sources/users_guide/glossary.rst.txt b/docs/html/_sources/users_guide/glossary.rst.txt deleted file mode 100644 index 62e27f9..0000000 --- a/docs/html/_sources/users_guide/glossary.rst.txt +++ /dev/null @@ -1,99 +0,0 @@ -Vocabulary -========== - -(glossary) (vocabulary) - -{ Template} is an informal term meaning a template definition, a -template instance or a template class. A { template definition} is -what the human { template maintainer} writes: a string consisting -of text, placeholders and directives. { Placeholders} are variables -that will be looked up when the template is filled. { Directives} -are commands to be executed when the template is filled, or -instructions to the Cheetah compiler. The conventional suffix for a -file containing a template definition is { .tmpl}. - -There are two things you can do with a template: compile it or fill -it. { Filling} is the reason you have a template in the first -place: to get a finished string out of it. Compiling is a necessary -prerequisite: the { Cheetah compiler} takes a template definition -and produces Python code to create the finished string. Cheetah -provides several ways to compile and fill templates, either as one -step or two. - -Cheetah's compiler produces a subclass of {Cheetah.Template} -specific to that template definition; this is called the { -generated class}. A { template instance} is an instance of a -generated class. - -If the user calls the {Template} constructor directly (rather than -a subclass constructor), s/he will get what appears to be an -instance of {Template} but is actually a subclass created -on-the-fly. - -The user can make the subclass explicit by using the -"cheetah compile" command to write the template class to a Python -module. Such a module is called a { .py template module}. - -The { Template Definition Language} - or the "Cheetah language" for -short - is the syntax rules governing placeholders and directives. -These are discussed in sections language and following in this -Guide. - -To fill a template, you call its { main method}. This is normally -{.respond()}, but it may be something else, and you can use the -{#implements} directive to choose the method name. (Section -inheritanceEtc.implements. - -A { template-servlet} is a .py template module in a Webware servlet -directory. Such templates can be filled directly through the web by -requesting the URL. "Template-servlet" can also refer to the -instance being filled by a particular web request. If a Webware -servlet that is not a template-servlet invokes a template, that -template is not a template-servlet either. - -A { placeholder tag} is the substring in the template definition -that is the placeholder, including the start and end delimeters (if -there is an end delimeter). The { placeholder name} is the same but -without the delimeters. - -Placeholders consist of one or more { identifiers} separated by -periods (e.g., {a.b}). Each identifier must follow the same rules -as Python identifiers; that is, a letter or underscore followed by -one or more letters, digits or underscores. (This is the regular -expression ``[A-Za-z_][A-Za-z0-9_]*``.) - -The first (or only) identifier of a placeholder name represents a { -variable} to be looked up. Cheetah looks up variables in various { -namespaces}: the searchList, local variables, and certain other -places. The searchList is a list of objects ({ containers}) with -attributes and/or keys: each container is a namespace. Every -template instance has exactly one searchList. Identifiers after the -first are looked up only in the parent object. The final value -after all lookups have been performed is the { placeholder value}. - -Placeholders may occur in three positions: top-level, expression -and LVALUE. { Top-level} placeholders are those in ordinary text -("top-level text"). { Expression} placeholders are those in Python -expressions. { LVALUE} placeholders are those naming a variable to -receive a value. (LVALUE is computerese for -"the left side of the equal sign".) Section -language.placeholders.positions explains the differences between -these three positions. - -The routine that does the placeholder lookups is called the { -NameMapper}. Cheetah's NameMapper supports universal dotted -notation and autocalling. { Universal dotted notation} means that -keys may be written as if they were attributes: {a.b} instead of -{a['b']}. { Autocalling} means that if any identifier's value is -found to be a function or method, Cheetah will call it without -arguments if there is no ``()`` following. More about the -NameMapper is in section language.namemapper. - -Some directives are multi-line, meaning they have a matching { -#end} tag. The lines of text between the start and end tags is the -{ body} of the directive. Arguments on the same line as the start -tag, in contrast, are considered part of the directive tag. More -details are in section language.directives.syntax (Directive Syntax -Rules). - - diff --git a/docs/html/_sources/users_guide/index.rst.txt b/docs/html/_sources/users_guide/index.rst.txt deleted file mode 100644 index efbf343..0000000 --- a/docs/html/_sources/users_guide/index.rst.txt +++ /dev/null @@ -1,28 +0,0 @@ -Cheetah User's Guide -==================== - -.. toctree:: - :maxdepth: 2 - - intro.rst - glossary.rst - gettingStarted.rst - language.rst - comments.rst - output.rst - inheritanceEtc.rst - flowControl.rst - errorHandling.rst - parserInstructions.rst - - tipsAndTricks.rst - webware.rst - otherHtml.rst - nonHtml.rst - libraries.rst - editors.rst - links.rst - examples.rst - comparisons.rst - - diff --git a/docs/html/_sources/users_guide/inheritanceEtc.rst.txt b/docs/html/_sources/users_guide/inheritanceEtc.rst.txt deleted file mode 100644 index e0bb125..0000000 --- a/docs/html/_sources/users_guide/inheritanceEtc.rst.txt +++ /dev/null @@ -1,517 +0,0 @@ -Import, Inheritance, Declaration and Assignment -=============================================== - -(inheritanceEtc) - -#import and #from directives ----------------------------- - -(inheritanceEtc.import) - -Syntax: - -:: - - #import MODULE_OR_OBJECT [as NAME] [, ...] - #from MODULE import MODULE_OR_OBJECT [as NAME] [, ...] - -The {#import} and {#from} directives are used to make external -Python modules or objects available to placeholders. The syntax is -identical to the import syntax in Python. Imported modules are -visible globally to all methods in the generated Python class. - -:: - - #import math - #import math as mathModule - #from math import sin, cos - #from math import sin as _sin - #import random, re - #from mx import DateTime # ## Part of Egenix's mx package. - -After the above imports, {$math}, {$mathModule}, {$sin}, {$cos} and -{$\_sin}, {$random}, {$re} and {$DateTime} may be used in -{$placeholders} and expressions. - -#extends --------- - -(inheritanceEtc.extends) - -Syntax: - -:: - - #extends CLASS - -All templates are subclasses of {Cheetah.Template.Template}. -However, it's possible for a template to subclass another template -or a pure Python class. This is where {#extends} steps in: it -specifies the parent class. It's equivalent to PSP's -{"@page extends="} directive. - -Cheetah imports the class mentioned in an {#extends} directive -automatically if you haven't imported it yet. The implicit -importing works like this: - -:: - - #extends Superclass - ## Implicitly does '#from Superclass import Superclass'. - - #extends Cheetah.Templates.SkeletonPage - ## Implicitly does '#from Cheetah.Templates.SkeletonPage import SkeletonPage'. - -If your superclass is in an unusual location or in a module named -differently than the class, you must import it explicitly. There is -no support for extending from a class that is not imported; e.g., -from a template dynamically created from a string. Since the most -practical way to get a parent template into a module is to -precompile it, all parent templates essentially have to be -precompiled. - -There can be only one {#extends} directive in a template and it may -list only one class. In other words, templates don't do multiple -inheritance. This is intentional: it's too hard to initialize -multiple base classes correctly from inside a template. However, -you can do multiple inheritance in your pure Python classes. - -If your pure Python class overrides any of the standard {Template} -methods such as {.\_\_init\_\_} or {.awake}, be sure to call the -superclass method in your method or things will break. Examples of -calling the superclass method are in section -tips.callingSuperclassMethods. A list of all superclass methods is -in section tips.allMethods. - -In all cases, the root superclass must be {Template}. If your -bottommost class is a template, simply omit the {#extends} in it -and it will automatically inherit from {Template}. { If your -bottommost class is a pure Python class, it must inherit from -{Template} explicitly: } - -:: - - from Cheetah.Template import Template - class MyPurePythonClass(Template): - -If you're not keen about having your Python classes inherit from -{Template}, create a tiny glue class that inherits both from your -class and from {Template}. - -Before giving any examples we'll stress that Cheetah does { not} -dictate how you should structure your inheritance tree. As long as -you follow the rules above, many structures are possible. - -Here's an example for a large web site that has not only a general -site template, but also a template for this section of the site, -and then a specific template-servlet for each URL. (This is the -"inheritance approach" discussed in the Webware chapter.) Each -template inherits from a pure Python class that contains -methods/attributes used by the template. We'll begin with the -bottommost superclass and end with the specific template-servlet: - -:: - - 1. SiteLogic.py (pure Python class containing methods for the site) - from Cheetah.Template import Template - class SiteLogic(Template): - - 2. Site.tmpl/py (template containing the general site framework; - this is the template that controls the output, - the one that contains "...", the one - that contains text outside any #def/#block.) - #from SiteLogic import SiteLogic - #extends SiteLogic - #implements respond - - 3. SectionLogic.py (pure Python class with helper code for the section) - from Site import Site - class SectionLogic(Site) - - 4. Section.tmpl/py (template with '#def' overrides etc. for the section) - #from SectionLogic import SectionLogic - #extends SectionLogic - - 5. page1Logic.py (pure Python class with helper code for the template-servlet) - from Section import Section - class indexLogic(Section): - - 6. page1.tmpl/py (template-servlet for a certain page on the site) - #from page1Logic import page1Logic - #extends page1Logic - -A pure Python classes might also contain methods/attributes that -aren't used by their immediate child template, but are available -for any descendant template to use if it wishes. For instance, the -site template might have attributes for the name and e-mail address -of the site administrator, ready to use as $placeholders in any -template that wants it. - -{ Whenever you use {#extends}, you often need {#implements} too,} -as in step 2 above. Read the next section to understand what -{#implements} is and when to use it. - -#implements ------------ - -(inheritanceEtc.implements) - -Syntax: - -:: - - #implements METHOD - -You can call any {#def} or {#block} method directly and get its -outpt. The top-level content - all the text/placeholders/directives -outside any {#def}/{#block} - gets concatenated and wrapped in a -"main method", by default {.respond()}. So if you call -{.respond()}, you get the "whole template output". When Webware -calls {.respond()}, that's what it's doing. And when you do 'print -t' or 'str(t)' on a template instance, you're taking advantage of -the fact that Cheetah makes {.\_\_str\_\_()} an alias for the main -method. - -That's all fine and dandy, but what if your application prefers to -call another method name rather than {.respond()}? What if it wants -to call, say, {.send\_output()} instead? That's where {#implements} -steps in. It lets you choose the name for the main method. Just put -this in your template definition: - -:: - - #implements send_output - -When one template extends another, every template in the -inheritance chain has its own main method. To fill the template, -you invoke exactly one of these methods and the others are ignored. -The method you call may be in any of the templates in the -inheritance chain: the base template, the leaf template, or any in -between, depending on how you structure your application. So you -have two problems: (1) calling the right method name, and (2) -preventing an undesired same-name subclass method from overriding -the one you want to call. - -Cheetah assumes the method you will call is {.respond()} because -that's what Webware calls. It further assumes the desired main -method is the one in the lowest-level base template, because that -works well with {#block} as described in the Inheritance Approach -for building Webware servlets (section webware.inheritance), which -was originally the principal use for Cheetah. So when you use -{#extends}, Cheetah changes that template's main method to -{.writeBody()} to get it out of the way and prevent it from -overriding the base template's {.respond()}. - -Unfortunately this assumption breaks down if the template is used -in other ways. For instance, you may want to use the main method in -the highest-level leaf template, and treat the base template(s) as -merely a library of methods/attributes. In that case, the leaf -template needs {#implements respond} to change its main method name -back to {.respond()} (or whatever your application desires to -call). Likewise, if your main method is in one of the intermediate -templates in an inheritance chain, that template needs {#implements -respond}. - -The other way the assumption breaks down is if the main method { -is} in the base template but that template extends a pure Python -class. Cheetah sees the {#extends} and dutifully but incorrectly -renames the method to {.writeBody()}, so you have to use -{#implements respond} to change it back. Otherwise the dummy -{.respond()} in {Cheetah.Template} is found, which outputs... -nothing. { So if you're using {#extends} and get no output, the { -first} thing you should think is, -"Do I need to add {#implements respond} somewhere?" } - -#set ----- - -(inheritanceEtc.set) - -Syntax: - -:: - - #set [global] $var = EXPR - -{#set} is used to create and update local variables at run time. -The expression may be any Python expression. Remember to preface -variable names with $ unless they're part of an intermediate result -in a list comprehension. - -Here are some examples: - -:: - - #set $size = $length * 1096 - #set $buffer = $size + 1096 - #set $area = $length * $width - #set $namesList = ['Moe','Larry','Curly'] - #set $prettyCountry = $country.replace(' ', ' ') - -{#set} variables are useful to assign a short name to a -{$deeply.nested.value}, to a calculation, or to a printable version -of a value. The last example above converts any spaces in the -'country' value into HTML non-breakable-space entities, to ensure -the entire value appears on one line in the browser. - -{#set} variables are also useful in {#if} expressions, but remember -that complex logical routines should be coded in Python, not in -Cheetah! - -:: - - #if $size > 1500 - #set $adj = 'large' - #else - #set $adj = 'small' - #end if - -Or Python's one-line equivalent, "A and B or C". Remember that in -this case, B must be a true value (not None, '', 0, [] or {}). - -:: - - #set $adj = $size > 1500 and 'large' or 'small' - -(Note: Cheetah's one-line {#if} will not work for this, since it -produces output rather than setting a variable. - -You can also use the augmented assignment operators: - -:: - - ## Increment $a by 5. - #set $a += 5 - -By default, {#set} variables are not visible in method calls or -include files unless you use the {global} attribute: {#set global -$var = EXPRESSION}. Global variables are visible in all methods, -nested templates and included files. Use this feature with care to -prevent surprises. - -#del ----- - -(inheritanceEtc.del) - -Syntax: - -:: - - #del $var - -{#del} is the opposite of {#set}. It deletes a { local} variable. -Its usage is just like Python's {del} statement: - -:: - - #del $myVar - #del $myVar, $myArray[5] - -Only local variables can be deleted. There is no directive to -delete a {#set global} variable, a searchList variable, or any -other type of variable. - -#attr ------ - -(inheritanceEtc.attr) - -Syntax: - -:: - - #attr $var = EXPR - -The {#attr} directive creates class attributes in the generated -Python class. It should be used to assign simple Python literals -such as numbers or strings. In particular, the expression must { -not} depend on searchList values or {#set} variables since those -are not known at compile time. - -:: - - #attr $title = "Rob Roy" - #attr $author = "Sir Walter Scott" - #attr $version = 123.4 - -This template or any child template can output the value thus: - -:: - - $title, by $author, version $version - -If you have a library of templates derived from etexts -(http://www.gutenberg.org/), you can extract the titles and authors -and put them in a database (assuming the templates have been -compiled into .py template modules): - -#def ----- - -(inheritanceEtc.def) - -Syntax: - -:: - - #def METHOD[(ARGUMENTS)] - #end def - -Or the one-line variation: - -:: - - #def METHOD[(ARGUMENTS)] : TEXT_AND_PLACEHOLDERS - -The {#def} directive is used to define new methods in the generated -Python class, or to override superclass methods. It is analogous to -Python's {def} statement. The directive is silent, meaning it does -not itself produce any output. However, the content of the method -will be inserted into the output (and the directives executed) -whenever the method is later called by a $placeholder. - -:: - - #def myMeth() - This is the text in my method - $a $b $c(123) ## these placeholder names have been defined elsewhere - #end def - - ## and now use it... - $myMeth() - -The arglist and parentheses can be omitted: - -:: - - #def myMeth - This is the text in my method - $a $b $c(123) - #end def - - ## and now use it... - $myMeth - -Methods can have arguments and have defaults for those arguments, -just like in Python. Remember the {$} before variable names: - -:: - - #def myMeth($a, $b=1234) - This is the text in my method - $a - $b - #end def - - ## and now use it... - $myMeth(1) - -The output from this last example will be: - -:: - - This is the text in my method - 1 - 1234 - -There is also a single line version of the {#def} directive. { -Unlike the multi-line directives, it uses a colon (:) to delimit -the method signature and body}: - -:: - - #attr $adj = 'trivial' - #def myMeth: This is the $adj method - $myMeth - -Leading and trailing whitespace is stripped from the method. This -is in contrast to: - -:: - - #def myMeth2 - This is the $adj method - #end def - -where the method includes a newline after "method". If you don't -want the newline, add {#slurp}: - -:: - - #def myMeth3 - This is the $adj method#slurp - #end def - -Because {#def} is handled at compile time, it can appear above or -below the placeholders that call it. And if a superclass -placeholder calls a method that's overridden in a subclass, it's -the subclass method that will be called. - -#block ... #end block ---------------------- - -(inheritanceEtc.block) - -The {#block} directive allows you to mark a section of your -template that can be selectively reimplemented in a subclass. It is -very useful for changing part of a template without having to -copy-paste-and-edit the entire thing. The output from a template -definition that uses blocks will be identical to the output from -the same template with the {#block ... #end block} tags removed. - -({ Note:} don't be confused by the generic word 'block'' in this -Guide, which means a section of code inside { any} {#TAG ... #end -TAG} pair. Thus, an if-block, for-block, def-block, block-block -etc. In this section we are talking only of block-blocks.) - -To reimplement the block, use the {#def} directive. The magical -effect is that it appears to go back and change the output text { -at the point the original block was defined} rather than at the -location of the reimplementation. - -:: - - #block testBlock - Text in the contents - area of the block directive - #if $testIt - $getFoo() - #end if - #end block testBlock - -You can repeat the block name in the {#end block} directive or not, -as you wish. - -{#block} directives can be nested to any depth. - -:: - - #block outerBlock - Outer block contents - - #block innerBlock1 - inner block1 contents - #end block innerBlock1 - - #block innerBlock2 - inner block2 contents - #end block innerBlock2 - - #end block outerBlock - -Note that the name of the block is optional for the {#end block} -tag. - -Technically, {#block} directive is equivalent to a {#def} directive -followed immediately by a {#placeholder} for the same name. In -fact, that's what Cheetah does. Which means you can use -{$theBlockName} elsewhere in the template to output the block -content again. - -There is a one-line {#block} syntax analagous to the one-line -{#def}. - -The block must not require arguments because the implicit -placeholder that's generated will call the block without -arguments. - - diff --git a/docs/html/_sources/users_guide/intro.rst.txt b/docs/html/_sources/users_guide/intro.rst.txt deleted file mode 100644 index 096bdef..0000000 --- a/docs/html/_sources/users_guide/intro.rst.txt +++ /dev/null @@ -1,311 +0,0 @@ -Introduction -=============== - -Who should read this Guide? ---------------------------- - -This Users' Guide provides a technical overview and reference for -the Cheetah template system. Knowledge of Python and -object-oriented programming is assumed. The emphasis in this Guide -is on features useful in a wide variety of situations. Information -on less common situations and troubleshooting tips are gradually -being moved to the Cheetah FAQ. There is also a Cheetah Developer's -Guide for those who want to know what goes on under the hood. - -What is Cheetah? ----------------- - -Cheetah is a Python-powered template engine and code generator. It -may be used as a standalone utility or combined with other tools. -Cheetah has many potential uses, but web developers looking for a -viable alternative to ASP, JSP, PHP and PSP are expected to be its -principle user group. - -Cheetah: - - -- generates HTML, SGML, XML, SQL, Postscript, form email, LaTeX, - or any other text-based format. It has also been used to produce - Python, Java and PHP source code. - -- cleanly separates content, graphic design, and program code. - This leads to highly modular, flexible, and reusable site - architectures; faster development time; and HTML and program code - that is easier to understand and maintain. It is particularly well - suited for team efforts. - -- blends the power and flexibility of Python with a simple - template language that non-programmers can understand. - -- gives template writers full access in their templates to any - Python data structure, module, function, object, or method. - -- makes code reuse easy by providing an object-oriented interface - to templates that is accessible from Python code or other Cheetah - templates. One template can subclass another and selectively - reimplement sections of it. A compiled template **is** a Python - class, so it can subclass a pure Python class and vice-versa. - -- provides a simple yet powerful caching mechanism - -Like its namesake, Cheetah is fast, flexible and powerful. - - -What is the philosophy behind Cheetah? --------------------------------------- -Cheetah's design was guided by these principles: - - -- Python for the back end, Cheetah for the front end. Cheetah was - designed to complement Python, not replace it. - -- Cheetah's core syntax should be easy for non-programmers to - learn. - -- Cheetah should make code reuse easy by providing an - object-oriented interface to templates that is accessible from - Python code or other Cheetah templates. - -- Python objects, functions, and other data structures should be - fully accessible in Cheetah. - -- Cheetah should provide flow control and error handling. Logic - that belongs in the front end shouldn't be relegated to the back - end simply because it's complex. - -- It should be easy to **separate** content, graphic design, and - program code, but also easy to **integrate** them. - - A clean separation makes it easier for a team of content writers, - HTML/graphic designers, and programmers to work together without - stepping on each other's toes and polluting each other's work. The - HTML framework and the content it contains are two separate things, - and analytical calculations (program code) is a third thing. Each - team member should be able to concentrate on their specialty and to - implement their changes without having to go through one of the - others (i.e., the dreaded "webmaster bottleneck"). - - While it should be easy to develop content, graphics and program - code separately, it should be easy to integrate them together into - a website. In particular, it should be easy: - - - - for **programmers** to create reusable components and functions - that are accessible and understandable to designers. - - - for **designers** to mark out placeholders for content and - dynamic components in their templates. - - - for **designers** to soft-code aspects of their design that are - either repeated in several places or are subject to change. - - - for **designers** to reuse and extend existing templates and thus - minimize duplication of effort and code. - - - and, of course, for **content writers** to use the templates that - designers have created. - - - -Why Cheetah doesn't use HTML-style tags -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Cheetah does not use HTML/XML-style tags like some other template -languages for the following reasons: Cheetah is not limited to -HTML, HTML-style tags are hard to distinguish from real HTML tags, -HTML-style tags are not visible in rendered HTML when something -goes wrong, HTML-style tags often lead to invalid HTML (e.g., ````), Cheetah tags are less verbose and -easier to understand than HTML-style tags, and HTML-style tags -aren't compatible with most WYSIWYG editors - -Besides being much more compact, Cheetah also has some advantages -over languages that put information inside the HTML tags, such as -Zope Page Templates or PHP: HTML or XML-bound languages do not work -well with other languages, While ZPT-like syntaxes work well in -many ways with WYSIWYG HTML editors, they also give up a -significant advantage of those editors - concrete editing of the -document. When logic is hidden away in (largely inaccessible) tags -it is hard to understand a page simply by viewing it, and it is -hard to confirm or modify that logic. - -Give me an example! -------------------- - -Here's a very simple example that illustrates some of Cheetah's -basic syntax: - -:: - - - $title - - - - #for $client in $clients - - - - - #end for -
    $client.surname, $client.firstname$client.email
    - - - - -Compare this with PSP: - -:: - - - <%=title%> - - - - <% for client in clients: %> - - - - - <%end%> -
    <%=client['surname']%>, <%=client['firstname']%><%=client['email']%>
    - - - - -Section gettingStarted.tutorial has a more typical example that -shows how to get the plug-in values **into** Cheetah, and section -howWorks.cheetah-compile explains how to turn your template -definition into an object-oriented Python module. - -Give me an example of a Webware servlet! ----------------------------------------- - -This example uses an HTML form to ask the user's name, then invokes -itself again to display a **personalized** friendly greeting. - -:: - - My Template-Servlet - #set $name = $request.field('name', None) - #if $name - Hello $name - #else -
    - Name:
    - -
    - #end if - - -To try it out for yourself on a Webware system: - - -#. copy the template definition to a file **test.tmpl** in your - Webware servlet directory. - -#. Run ``cheetah compile test.tmpl``. This produces ``test.py`` (a - .py template module) in the same directory. - -#. In your web browser, go to ``test.py``, using whatever site and - directory is appropriate. - -At the first request, field 'name' will be blank (false) so the -"#else" portion will execute and present a form. You type your name -and press submit. The form invokes the same page. Now 'name' is -true so the "#if" portion executes, which displays the greeting. -The "#set" directive creates a local variable that lasts while the -template is being filled. - -How mature is Cheetah? ----------------------- - -Cheetah is stable, production quality, post-beta code. Cheetah's -syntax, semantics and performance have been generally stable since -a performance overhaul in mid 2001. Most of the changes since -October 2001 have been in response to specific requests by -production sites, things they need that we hadn't considered. - -As of summer 2003, we are putting in the final touches before the -1.0 release. - - -Where can I get news? ---------------------- - -Cheetah releases can be obtained from the `Cheetah -website `_ - -If you encounter difficulties, or are unsure about how to do something, please -post a detailed message to the `bug tracker -`. - -How can I contribute? ---------------------- - -Cheetah is the work of many volunteers. If you use Cheetah please -share your experiences, tricks, customizations, and frustrations. - -Bug reports and patches -~~~~~~~~~~~~~~~~~~~~~~~ - -If you think there is a bug in Cheetah, send a message to the -e-mail list with the following information: - - -#. a description of what you were trying to do and what happened - -#. all tracebacks and error output - -#. your version of Cheetah - -#. your version of Python - -#. your operating system - -#. whether you have changed anything in the Cheetah installation - - -Template libraries and function libraries -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -We hope to build up a framework of Template libraries (see section -libraries.templates) to distribute with Cheetah and would -appreciate any contributions. - -Test cases -~~~~~~~~~~ - -Cheetah is packaged with a regression testing suite that is run -with each new release to ensure that everything is working as -expected and that recent changes haven't broken anything. The test -cases are in the Cheetah.Tests module. If you find a reproduceable -bug please consider writing a test case that will pass only when -the bug is fixed. Send any new test cases to the email list with -the subject-line "new test case for Cheetah." - -Publicity -~~~~~~~~~ - -Help spread the word ... recommend it to others, write articles -about it, etc. - -Acknowledgements ----------------- - -Cheetah is one of several templating frameworks that grew out of a -'templates' thread on the Webware For Python email list. Tavis -Rudd, Mike Orr, Chuck Esterbrook and Ian Bicking are the core -developers. - -We'd like to thank the following people for contributing valuable -advice, code and encouragement: Geoff Talvola, Jeff Johnson, Graham -Dumpleton, Clark C. Evans, Craig Kattner, Franz Geiger, Geir -Magnusson, Tom Schwaller, Rober Kuzelj, Jay Love, Terrel Shumway, -Sasa Zivkov, Arkaitz Bitorika, Jeremiah Bellomy, Baruch Even, Paul -Boddie, Stephan Diehl, Chui Tey, Michael Halle, Edmund Lian and -Aaron Held. - -The Velocity, WebMacro and Smarty projects provided inspiration and -design ideas. Cheetah has benefitted from the creativity and energy -of their developers. Thank you. diff --git a/docs/html/_sources/users_guide/language.rst.txt b/docs/html/_sources/users_guide/language.rst.txt deleted file mode 100644 index 679fe7b..0000000 --- a/docs/html/_sources/users_guide/language.rst.txt +++ /dev/null @@ -1,741 +0,0 @@ -.. role:: math(raw) - :format: html latex - -Language Overview -================= - -(language) - -Cheetah's basic syntax was inspired by the Java-based template -engines Velocity and WebMacro. It has two types of tags: { -$placeholders} and { #directives}. Both types are case-sensitive. - -Placeholder tags begin with a dollar sign ({$varName}) and are -similar to data fields in a form letter or to the {%(key)s} fields -on the left side of Python's {%} operator. When the template is -filled, the placeholders are replaced with the values they refer -to. - -Directive tags begin with a hash character (#) and are used for -comments, loops, conditional blocks, includes, and all other -advanced features. ({ Note:} you can customize the start and end -delimeters for placeholder and directive tags, but in this Guide -we'll assume you're using the default.) - -Placeholders and directives can be escaped by putting a backslash -before them. ``\$var`` and ``\#if`` will be output as literal -text. - -A placeholder or directive can span multiple physical lines, -following the same rules as Python source code: put a backslash -(``\``) at the end of all lines except the last line. However, if -there's an unclosed parenthesis, bracket or brace pending, you -don't need the backslash. - -:: - - #if $this_is_a_very_long_line and $has_lots_of_conditions \ - and $more_conditions: -

    bla

    - #end if - - #if $country in ('Argentina', 'Uruguay', 'Peru', 'Colombia', - 'Costa Rica', 'Venezuela', 'Mexico') -

    Hola, senorita!

    - #else -

    Hey, baby!

    - #end if - -Language Constructs - Summary ------------------------------ - -(language.constructs) - - -#. Comments and documentation strings - - - #. {## single line} - - #. {#\* multi line \*#} - - -#. Generation, caching and filtering of output - - - #. plain text - - #. look up a value: {$placeholder} - - #. evaluate an expression: {#echo} ... - - #. same but discard the output: {#silent} ... - - #. one-line if: {#if EXPR then EXPR else EXPR} - - #. gobble the EOL: {#slurp} - - #. parsed file includes: {#include} ... - - #. raw file includes: {#include raw} ... - - #. verbatim output of Cheetah code: {#raw} ... {#end raw} - - #. cached placeholders: {$\*var}, {$\*\*var} - - #. cached regions: {#cache} ... {#end cache} - - #. set the output filter: {#filter} ... - - #. control output indentation: {#indent} ... ({ not implemented - yet}) - - -#. Importing Python modules and objects: {#import} ..., {#from} - ... - -#. Inheritance - - - #. set the base class to inherit from: {#extends} - - #. set the name of the main method to implement: {#implements} - ... - - -#. Compile-time declaration - - - #. define class attributes: {#attr} ... - - #. define class methods: {#def} ... {#end def} - - #. {#block} ... {#end block} provides a simplified interface to - {#def} ... {#end def} - - -#. Run-time assignment - - - #. local vars: {#set} ... - - #. global vars: {#set global} ... - - #. deleting local vars: {#del} ... - - -#. Flow control - - - #. {#if} ... {#else} ... {#else if} (aka {#elif}) ... {#end if} - - #. {#unless} ... {#end unless} - - #. {#for} ... {#end for} - - #. {#repeat} ... {#end repeat} - - #. {#while} ... {#end while} - - #. {#break} - - #. {#continue} - - #. {#pass} - - #. {#stop} - - -#. error/exception handling - - - #. {#assert} - - #. {#raise} - - #. {#try} ... {#except} ... {#else} ... {#end try} - - #. {#try} ... {#finally} ... {#end try} - - #. {#errorCatcher} ... set a handler for exceptions raised by - $placeholder calls. - - -#. Instructions to the parser/compiler - - - #. {#breakpoint} - - #. {#compiler-settings} ... {#end compiler-settings} - - -#. Escape to pure Python code - - - #. evalute expression and print the output: {<%=} ... {%>} - - #. execute code and discard output: {<%} ... {%>} - - -#. Fine control over Cheetah-generated Python modules - - - #. set the source code encoding of compiled template modules: - {#encoding} - - #. set the sh-bang line of compiled template modules: {#shBang} - - - -The use of all these constructs will be covered in the next several -chapters. - -Placeholder Syntax Rules ------------------------- - -(language.placeholders.syntax) - - -- Placeholders follow the same syntax rules as Python variables - except that they are preceded by {$} (the short form) or enclosed - in {${}} (the long form). Examples: - - :: - - $var - ${var} - $var2.abc['def']('gh', $subplaceholder, 2) - ${var2.abc['def']('gh', $subplaceholder, 2)} - - We recommend {$} in simple cases, and {${}} when followed directly - by a letter or when Cheetah or a human template maintainer might - get confused about where the placeholder ends. You may alternately - use ``$()`` or ``$[]``, although this may confuse the (human) - template maintainer: - - :: - - $(var) - $[var] - $(var2.abc['def']('gh', $subplaceholder, 2)) - $[var2.abc['def']('gh', $subplaceholder, 2)] - - { Note:} Advanced users can change the delimiters to anything they - want via the {#compiler} directive. - - { Note 2:} The long form can be used only with top-level - placeholders, not in expressions. See section - language.placeholders.positions for an elaboration on this. - -- To reiterate Python's rules, placeholders consist of one or more - identifiers separated by periods. Each identifier must start with a - letter or an underscore, and the subsequent characters must be - letters, digits or underscores. Any identifier may be followed by - arguments enclosed in ``()`` and/or keys/subscripts in ``[]``. - -- Identifiers are case sensitive. {$var} does not equal {$Var} or - {$vAr} or {$VAR}. - -- Arguments inside ``()`` or ``[]`` are just like in Python. - Strings may be quoted using any Python quoting style. Each argument - is an expression and may use any of Python's expression operators. - Variables used in argument expressions are placeholders and should - be prefixed with {$}. This also applies to the \*arg and \*\*kw - forms. However, you do { not} need the {$} with the special Python - constants {None}, {True} and {False}. Examples: - - :: - - $hex($myVar) - $func($arg=1234) - $func2($*args, $**kw) - $func3(3.14159, $arg2, None, True) - $myList[$mySubscript] - -- Trailing periods are ignored. Cheetah will recognize that the - placeholder name in {$varName.} is {varName}, and the period will - be left alone in the template output. - -- The syntax {${placeholderName, arg1="val1"}} passes arguments to - the output filter (see {#filter}, section output.filter. The braces - and comma are required in this case. It's conventional to omit the - {$} before the keyword arguments (i.e. {arg1}) in this case. - -- Cheetah ignores all dollar signs ({$}) that are not followed by - a letter or an underscore. - - -The following are valid $placeholders: - -:: - - $a $_ $var $_var $var1 $_1var $var2_ $dict.key $list[3] - $object.method $object.method() $object.method - $nest($nest($var)) - -These are not $placeholders but are treated as literal text: - -:: - - $@var $^var $15.50 $$ - -Where can you use placeholders? -------------------------------- - -(language.placeholders.positions) - -There are three places you can use placeholders: top-level -position, expression position and LVALUE position. Each has -slightly different syntax rules. - -Top-level position means interspersed in text. This is the only -place you can use the placeholder long form: {${var}}. - -{ Expression position} means inside a Cheetah expression, which is -the same as a Python expression. The placeholder names a searchList -or other variable to be read. Expression position occurs inside () -and :math:`$[]$` arguments within placeholder tags (i.e., a -placeholder inside a placeholder), and in several directive tags. - -{ LVALUE position} means naming a variable that will be written to. -LVALUE is a computer science term meaning -"the left side of an assignment statement". The first argument of -directives {#set}, {#for}, {#def}, {#block} and {#attr} is an -LVALUE. - -This stupid example shows the three positions. Top-level position -is shown in {courier}, expression position is { italic}, and LVALUE -position is { bold}. - - #for { $count} in { $range}({ $ninetyNine}, 0, -1) - #set { $after} = { $count} - 1 - {$count} bottles of beer on the wall. {$count} bottles of beer! - Take one down, pass it around. {$after} bottles of beer on the - wall. - #end for - {$hex}({ $myVar}, { $default}={ None}) - - -The output of course is: - -:: - - 99 bottles of beer on the wall. 99 bottles of beer! - Take one down, pass it around. 98 bottles of beer on the wall. - 98 bottles of beer on the wall. 98 bottles of beer! - Take one down, pass it around. 97 bottles of beer on the wall. - ... - -Are all those dollar signs really necessary? --------------------------------------------- - -(language.placeholders.dollar-signs) - -{$} is a "smart variable prefix". When Cheetah sees {$}, it -determines both the variable's position and whether it's a -searchList value or a non-searchList value, and generates the -appropriate Python code. - -In top-level position, the {$} is { required}. Otherwise there's -nothing to distinguish the variable from ordinary text, and the -variable name is output verbatim. - -In expression position, the {$} is { required} if the value comes -from the searchList or a "#set global" variable, { recommended} for -local/global/builtin variables, and { not necessary} for the -special constants {None}, {True} and {False}. This works because -Cheetah generates a function call for a searchList placeholder, but -a bare variable name for a local/global/builtin variable. - -In LVALUE position, the {$} is { recommended}. Cheetah knows where -an LVALUE is expected, so it can handle your variable name whether -it has {$} or not. - -EXCEPTION: Do { not} use the {$} prefix for intermediate variables -in a Python list comprehensions. This is a limitation of Cheetah's -parser; it can't tell which variables in a list comprehension are -the intermediate variables, so you have to help it. For example: - -:: - - #set $theRange = [x ** 2 for x in $range(10)] - -{$theRange} is a regular {#set} variable. {$range} is a Python -built-in function. But {x} is a scratch variable internal to the -list comprehension: if you type {$x}, Cheetah will miscompile it. - -NameMapper Syntax ------------------ - -(language.namemapper) - -One of our core aims for Cheetah was to make it easy for -non-programmers to use. Therefore, Cheetah uses a simplified syntax -for mapping placeholders in Cheetah to values in Python. It's known -as the { NameMapper syntax} and allows for non-programmers to use -Cheetah without knowing (a) the difference between an instance and -a dictionary, (b) what functions and methods are, and (c) what -'self' is. A side benefit is that you can change the underlying -data structure (e.g., instance to dictionary or vice-versa) without -having to modify the templates. - -NameMapper syntax is used for all variables in Cheetah placeholders -and directives. If desired, it can be turned off via the {Template} -class' {'useNameMapper'} compiler setting. But it's doubtful you'd -ever want to turn it off. - -Example -~~~~~~~ - -(language.namemapper.example) - -Consider this scenario: - -You are building a customer information system. The designers with -you want to use information from your system on the client's -website -AND- they want to understand the display code and so they -can maintian it themselves. - -You write a UI class with a 'customers' method that returns a -dictionary of all the customer objects. Each customer object has an -'address' method that returns the a dictionary with information -about the customer's address. The designers want to be able to -access that information. - -Using PSP, the display code for the website would look something -like the following, assuming your servlet subclasses the class you -created for managing customer information: - -:: - - <%= self.customer()[ID].address()['city'] %> (42 chars) - -With Cheetah's NameMapper syntax, you can use any of the -following: - -:: - - $self.customers()[$ID].address()['city'] (39 chars) - --OR-- - $customers()[$ID].address()['city'] - --OR-- - $customers()[$ID].address().city - --OR-- - $customers()[$ID].address.city - --OR-- - $customers[$ID].address.city (27 chars) - -Which of these would you prefer to explain to the designers, who -have no programming experience? The last form is 15 characters -shorter than the PSP version and - conceptually - far more -accessible. With PHP or ASP, the code would be even messier than -with PSP. - -This is a rather extreme example and, of course, you could also -just implement {$getCustomer($ID).city} and obey the Law of Demeter -(search Google for more on that). But good object orientated design -isn't the point of this example. - -Dictionary Access -~~~~~~~~~~~~~~~~~ - -(language.namemapper.dict) - -NameMapper syntax allows access to dictionary items with the same -dotted notation used to access object attributes in Python. This -aspect of NameMapper syntax is known as 'Unified Dotted Notation'. -For example, with Cheetah it is possible to write: - -:: - - $customers()['kerr'].address() --OR-- $customers().kerr.address() - -where the second form is in NameMapper syntax. - -This works only with dictionary keys that also happen to be valid -Python identifiers. - -Autocalling -~~~~~~~~~~~ - -(language.namemapper.autocalling) - -Cheetah automatically detects functions and methods in Cheetah -$variables and calls them if the parentheses have been left off. -Our previous example can be further simplified to: - -:: - - $customers.kerr.address - -As another example, if 'a' is an object, 'b' is a method - -:: - - $a.b - -is equivalent to - -:: - - $a.b() - -If b returns a dictionary, then following variations are possible - -:: - - $a.b.c --OR-- $a.b().c --OR-- $a.b()['c'] - -where 'c' is a key in the dictionary that a.b() returns. - -Further notes: - - -- When Cheetah autocalls a function/method, it calls it without - any arguments. Thus, the function/method must have been declared - without arguments (except {self} for methods) or to provide default - values for all arguments. If the function requires arguments, you - must use the {()}. - -- Cheetah autocalls only functions and methods. Classes and other - callable objects are not autocalled. The reason is that the primary - purpose of a function/method is to call it, whereas the primary - purpose of an instance is to look up its attributes or call its - methods, not to call the instance itself. And calling a class may - allocate large sums of memory uselessly or have other side effects, - depending on the class. For instance, consider {$myInstance.fname}. - Do we want to look up {fname} in the namespace of {myInstance} or - in the namespace of whatever {myinstance} returns? It could go - either way, so Cheetah follows the principle of least surprise. If - you { do} want to call the instance, put the {()} on, or rename the - {.\_\_call\_\_()} method to {.\_\_str\_\_}. - -- Autocalling can be disabled via Cheetah's 'useAutocalling' - compiler setting. You can also disable it for one placeholder by - using the syntax {$getVar('varName', 'default value', False)}. - ({.getVar()} works only with searchList values.) - - -Namespace cascading and the searchList --------------------------------------- - -(language.searchList) - -When Cheetah maps a variable name in a template to a Python value, -it searches several namespaces in order: - - -#. { Local variables:} created by {#set}, {#for}, or predefined by - Cheetah. - -#. The { searchList}, consisting of: - - - #. {#set global} variables. - - #. The { searchList} containers you passed to the {Template} - constructor, if any. - - #. The { Template instance} ("self"). This contains any attributes - you assigned, {#def} methods and {#block methods}, - attributes/methods inherited via {#extends}, and other - attributes/methods built into {Template} or inherited by it - (there's a list of all these methods in section tips.allMethods). - - -#. { Python globals:} created by {#import}, {#from ... import}, or - otherwise predefined by Cheetah. - -#. { Python builtins:} {None}, {max}, etc. - - -The first matching name found is used. - -Remember, these namespaces apply only to the { first} identifier -after the {$}. In a placeholder like {$a.b}, only 'a' is looked up -in the searchList and other namespaces. 'b' is looked up only -inside 'a'. - -A searchList container can be any Python object with attributes or -keys: dictionaries, instances, classes or modules. If an instance -contains both attributes and keys, its attributes are searched -first, then its keys. - -Because the {Template} instance is part of the searchList, you can -access its attributes/methods without 'self': {$myAttr}. However, -use the 'self' if you want to make sure you're getting the -{Template} attribute and not a same-name variable defined in a -higher namespace: {$self.myAttr}. This works because "self" itself -is a local variable. - -The final resulting value, after all lookups and function calls -(but before the filter is applied) is called the { placeholder -value}, no matter which namespace it was found in. - -{ { Note carefully:}} if you put an object 'myObject' in the -searchList, you { cannot} look up {$myObject}! You can look up only -the attributes/keys { inside} 'myObject'. - -Earlier versions of Cheetah did not allow you to override Python -builtin names, but this was fixed in Cheetah 0.9.15. - -If your template will be used as a Webware servlet, do not override -methods 'name' and 'log' in the {Template} instance or it will -interfere with Webware's logging. However, it { is} OK to use those -variables in a higher namespace, since Webware doesn't know about -Cheetah namespaces. - -Missing Values --------------- - -(language.namemapper.missing) - -If NameMapper can not find a Python value for a Cheetah variable -name, it will raise the NameMapper.NotFound exception. You can use -the {#errorCatcher} directive (section errorHandling.errorCatcher) -or { errorCatcher} Template constructor argument (section -howWorks.constructing) to specify an alternate behaviour. BUT BE -AWARE THAT errorCatcher IS ONLY INTENDED FOR DEBUGGING! - -To provide a default value for a placeholder, write it like this: -{$getVar('varName', 'default value')}. If you don't specify a -default and the variable is missing, {NameMapper.NotFound} will be -raised. - -Directive Syntax Rules ----------------------- - -(language.directives.syntax) - -Directive tags begin with a hash character (#) and are used for -comments, loops, conditional blocks, includes, and all other -advanced features. Cheetah uses a Python-like syntax inside -directive tags and understands any valid Python expression. { -However, unlike Python, Cheetah does not use colons (:) and -indentation to mark off multi-line directives.} That doesn't work -in an environment where whitespace is significant as part of the -text. Instead, multi-line directives like {#for} have corresponding -closing tags ({#end for}). Most directives are direct mirrors of -Python statements. - -Many directives have arguments after the opening tag, which must be -in the specified syntax for the tag. All end tags have the -following syntax: - -:: - - #end TAG_NAME [EXPR] - -The expression is ignored, so it's essentially a comment. - -Directive closures and whitespace handling -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -(language.directives.closures) Directive tags can be closed -explicitly with {#}, or implicitly with the end of the line if -you're feeling lazy. - -:: - - #block testBlock # - Text in the body of the - block directive - #end block testBlock # - -is identical to: - -:: - - #block testBlock - Text in the body of the - block directive - #end block testBlock - -When a directive tag is closed explicitly, it can be followed with -other text on the same line: - -:: - - bah, bah, #if $sheep.color == 'black'# black#end if # sheep. - -When a directive tag is closed implicitly with the end of the line, -all trailing whitespace is gobbled, including the newline -character: - -:: - - """ - foo #set $x = 2 - bar - """ - outputs - """ - foo bar - """ - - while - """ - foo #set $x = 2 # - bar - """ - outputs - """ - foo - bar - """ - -When a directive tag is closed implicitly AND there is no other -text on the line, the ENTIRE line is gobbled up including any -preceeding whitespace: - -:: - - """ - foo - #set $x = 2 - bar - """ - outputs - """ - foo - bar - """ - - while - """ - foo - - #set $x = 2 - bar - """ - outputs - """ - foo - - bar - """ - -The {#slurp} directive (section output.slurp) also gobbles up -whitespace. - -Spaces outside directives are output { exactly} as written. In the -black sheep example, there's a space before "black" and another -before "sheep". So although it's legal to put multiple directives -on one line, it can be hard to read. - -:: - - #if $a# #echo $a + 1# #end if - - There's a space between each directive, - or two extra spaces total. - #if $a##echo $a + 1##end if - - No spaces, but you have to look closely - to verify none of the ``##'' are comment markers. - #if $a##echo $a + 1##end if ### A comment. - - In ``###'', the first ``#'' ends the directive, - the other two begin the comment. (This also shows - how you can add extra whitespace in the directive - tag without affecting the output.) - #if $a##echo $a + 1##end if # ## A comment. - - More readable, but now there's a space before the - comment. - - diff --git a/docs/html/_sources/users_guide/libraries.rst.txt b/docs/html/_sources/users_guide/libraries.rst.txt deleted file mode 100644 index cbdeb14..0000000 --- a/docs/html/_sources/users_guide/libraries.rst.txt +++ /dev/null @@ -1,315 +0,0 @@ -Batteries included: templates and other libraries -================================================= - -(libraries) - -Cheetah comes "batteries included" with libraries of templates, -functions, classes and other objects you can use in your own -programs. The different types are listed alphabetically below, -followed by a longer description of the SkeletonPage framework. -Some of the objects are classes for specific purposes (e.g., -filters or error catchers), while others are standalone and can be -used without Cheetah. - -If you develop any objects which are generally useful for Cheetah -sites, please consider posting them on the wiki with an -announcement on the mailing list so we can incorporate them into -the standard library. That way, all Cheetah users will benefit, and -it will encourage others to contribute their objects, which might -include something you want. - -ErrorCatchers -------------- - -(libraries.ErrorCatchers) - -Module {Cheetah.ErrorCatchers} contains error-handling classes -suitable for the {#errorCatcher} directive. These are debugging -tools that are not intended for use in production systems. See -section errorHandling.errorCatcher for a description of the error -catchers bundled with Cheetah. - -FileUtils ---------- - -(libraries.FileUtils) - -Module {Cheetah.FileUtils} contains generic functions and classes -for doing bulk search-and-replace on several files, and for finding -all the files in a directory hierarchy whose names match a glob -pattern. - -Filters -------- - -(libraries.Filters) - -Module {Filters} contains filters suitable for the {#Filter} -directive. See section output.filter for a description of the -filters bundled with Cheetah. - -SettingsManager ---------------- - -(libraries.SettingsManager) - -The {SettingsManager} class in the {Cheetah.SettingsManager} module -is a baseclass that provides facilities for managing application -settings. It facilitates the use of user-supplied configuration -files to fine tune an application. A setting is a key/value pair -that an application or component (e.g., a filter, or your own -servlets) looks up and treats as a configuration value to modify -its (the component's) behaviour. - -SettingsManager is designed to: - - -- work well with nested settings dictionaries of any depth - -- read/write {.ini style config files} (or strings) - -- read settings from Python source files (or strings) so that - complex Python objects can be stored in the application's settings - dictionary. For example, you might want to store references to - various classes that are used by the application, and plugins to - the application might want to substitute one class for another. - -- allow sections in {.ini config files} to be extended by settings - in Python src files. If a section contains a setting like - "{importSettings=mySettings.py}", {SettingsManager} will merge all - the settings defined in "{mySettings.py}" with the settings for - that section that are defined in the {.ini config file}. - -- maintain the case of setting names, unlike the ConfigParser - module - - -Cheetah uses {SettingsManager} to manage its configuration -settings. {SettingsManager} might also be useful in your own -applications. See the source code and docstrings in the file -{src/SettingsManager.py} for more information. - -Templates ---------- - -(libraries.templates) - -Package {Cheetah.Templates} contains stock templates that you can -either use as is, or extend by using the {#def} directive to -redefine specific { blocks}. Currently, the only template in here -is SkeletonPage, which is described in detail below in section -libraries.templates.skeletonPage. (Contributed by Tavis Rudd.) - -Tools ------ - -(libraries.Tools) - -Package {Cheetah.Tools} contains functions and classes contributed -by third parties. Some are Cheetah-specific but others are generic -and can be used standalone. None of them are imported by any other -Cheetah component; you can delete the Tools/ directory and Cheetah -will function fine. - -Some of the items in Tools/ are experimental and have been placed -there just to see how useful they will be, and whether they attract -enough users to make refining them worthwhile (the tools, not the -users :). - -Nothing in Tools/ is guaranteed to be: (A) tested, (B) reliable, -(C) immune from being deleted in a future Cheetah version, or (D) -immune from backwards-incompatable changes. If you depend on -something in Tools/ on a production system, consider making a copy -of it outside the Cheetah/ directory so that this version won't be -lost when you upgrade Cheetah. Also, learn enough about Python and -about the Tool so that you can maintain it and bugfix it if -necessary. - -If anything in Tools/ is found to be necessary to Cheetah's -operation (i.e., if another Cheetah component starts importing it), -it will be moved to the {Cheetah.Utils} package. - -Current Tools include: - - an ambitious class useful when iterating over records of data - ({#for} loops), displaying one pageful of records at a time (with - previous/next links), and printing summary statistics about the - records or the current page. See {MondoReportDoc.txt} in the same - directory as the module. Some features are not implemented yet. - {MondoReportTest.py} is a test suite (and it shows there are - currently some errors in MondoReport, hmm). Contributed by Mike - Orr. - - Nothing, but in a friendly way. Good for filling in for objects you - want to hide. If {$form.f1} is a RecursiveNull object, then - {$form.f1.anything["you"].might("use")} will resolve to the empty - string. You can also put a {RecursiveNull} instance at the end of - the searchList to convert missing values to '' rather than raising - a {NotFound} error or having a (less efficient) errorCatcher handle - it. Of course, maybe you prefer to get a {NotFound} error... - Contributed by Ian Bicking. - - Provides navigational links to this page's parents and children. - The constructor takes a recursive list of (url,description) pairs - representing a tree of hyperlinks to every page in the site (or - section, or application...), and also a string containing the - current URL. Two methods 'menuList' and 'crumbs' return - output-ready HTML showing an indented menu (hierarchy tree) or - crumbs list (Yahoo-style bar: home > grandparent > parent > - currentURL). Contributed by Ian Bicking. - - -Utils ------ - -(libraries.Utils) - -Package {Cheetah.Utils} contains non-Cheetah-specific functions and -classes that are imported by other Cheetah components. Many of -these utils can be used standalone in other applications too. - -Current Utils include: - - This is inherited by {Template} objects, and provides the method, - {.cgiImport} method (section webware.cgiImport). - - A catch-all module for small functions. - - Raise 'thing' if it's a subclass of Exception, otherwise return it. - Useful when one argument does double duty as a default value or an - exception to throw. Contribyted by Mike Orr. - - Verifies the dictionary does not contain any keys not listed in - 'legalKeywords'. If it does, raise TypeError. Useful for checking - the keyword arguments to a function. Contributed by Mike Orr. - - - Not implemented yet, but will contain the {.uploadFile} method (or - three methods) to "safely" copy a form-uploaded file to a local - file, to a searchList variable, or return it. When finished, this - will be inherited by {Template}, allowing all templates to do this. - If you want this feature, read the docstring in the source and let - us know on the mailing list what you'd like this method to do. - Contributed by Mike Orr. - - Functions to verify the type of a user-supplied function argument. - Contributed by Mike Orr. - - -Cheetah.Templates.SkeletonPage -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -(libraries.templates.skeletonPage) - -A stock template class that may be useful for web developers is -defined in the {Cheetah.Templates.SkeletonPage} module. The -{SkeletonPage} template class is generated from the following -Cheetah source code: - -:: - - ##doc-module: A Skeleton HTML page template, that provides basic structure and utility methods. - ################################################################################ - #extends Cheetah.Templates._SkeletonPage - #implements respond - ################################################################################ - #cache id='header' - $docType - $htmlTag - - - - #block writeHeadTag - - $title - $metaTags - $stylesheetTags - $javascriptTags - - #end block writeHeadTag - - #end cache header - ################# - - $bodyTag - - #block writeBody - This skeleton page has no flesh. Its body needs to be implemented. - #end block writeBody - - - - -You can redefine any of the blocks defined in this template by -writing a new template that {#extends} SkeletonPage. (As you -remember, using {#extends} makes your template implement the -{.writeBody()} method instead of {.respond()} - which happens to be -the same method SkeletonPage expects the page content to be (note -the writeBody block in SkeletonPage).) - -:: - - #def bodyContents - Here's my new body. I've got some flesh on my bones now. - #end def bodyContents - -All of the $placeholders used in the {SkeletonPage} template -definition are attributes or methods of the {SkeletonPage} class. -You can reimplement them as you wish in your subclass. Please read -the source code of the file {src/Templates/\_SkeletonPage.py} -before doing so. - -You'll need to understand how to use the following methods of the -{SkeletonPage} class: {$metaTags()}, {$stylesheetTags()}, -{$javascriptTags()}, and {$bodyTag()}. They take the data you -define in various attributes and renders them into HTML tags. - - -- { metaTags()} - Returns a formatted vesion of the - self.\_metaTags dictionary, using the formatMetaTags function from - {\_SkeletonPage.py}. - -- { stylesheetTags()} - Returns a formatted version of the - {self.\_stylesheetLibs} and {self.\_stylesheets} dictionaries. The - keys in {self.\_stylesheets} must be listed in the order that they - should appear in the list {self.\_stylesheetsOrder}, to ensure that - the style rules are defined in the correct order. - -- { javascriptTags()} - Returns a formatted version of the - {self.\_javascriptTags} and {self.\_javascriptLibs} dictionaries. - Each value in {self.\_javascriptTags} should be a either a code - string to include, or a list containing the JavaScript version - number and the code string. The keys can be anything. The same - applies for {self.\_javascriptLibs}, but the string should be the - SRC filename rather than a code string. - -- { bodyTag()} - Returns an HTML body tag from the entries in the - dict {self.\_bodyTagAttribs}. - - -The class also provides some convenience methods that can be used -as $placeholders in your template definitions: - - -- { imgTag(self, src, alt='', width=None, height=None, border=0)} - - Dynamically generate an image tag. Cheetah will try to convert - the "{src}" argument to a WebKit serverSidePath relative to the - servlet's location. If width and height aren't specified they are - calculated using PIL or ImageMagick if either of these tools are - available. If all your images are stored in a certain directory you - can reimplement this method to append that directory's path to the - "{src}" argument. Doing so would also insulate your template - definitions from changes in your directory structure. - - - diff --git a/docs/html/_sources/users_guide/links.rst.txt b/docs/html/_sources/users_guide/links.rst.txt deleted file mode 100644 index 1927ff8..0000000 --- a/docs/html/_sources/users_guide/links.rst.txt +++ /dev/null @@ -1,120 +0,0 @@ -Useful Web Links -================ - -(links) - -See the wiki for more links. (The wiki is also updated more often -than this chapter is.) - -Cheetah Links -------------- - -(links.cheetah) - -Home Page, issue tracker - - https://github.com/CheetahTemplate3/cheetah3 - -On-line Documentation - - http://cheetahtemplate.org/ - -Questions can also be asked and answered on `StackOverflow -`_. - - -Third-party Cheetah Stuff -------------------------- - -(links.thirdParty) - - -- Steve Howell has written a photo viewer using Python. - http://mountainwebtools.com/PicViewer/install.htm - - -Webware Links -------------- - -(links.webware) - -Home Page - - https://cito.github.io/w4py/ - -On-line Documentation - - https://webware.sf.net/Webware/Docs/ - -SourceForge Project Page - - https://sf.net/projects/webware/ - -Mailing List Subscription Page - - http://lists.sourceforge.net/lists/listinfo/webware-discuss - - -Python Links ------------- - -(links.python) - -Home Page - - http://www.python.org/ - -On-line Documentation - - http://www.python.org/doc/ - -Python Cookbook - - https://code.activestate.com/recipes/langs/python/ - - -Other Useful Links ------------------- - -(links.other) - -Python Database Modules and Open Source Databases -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -(links.database) - -Python Database Topic Guide - - http://python.org/topics/database/ - -PostgreSQL Database - - http://www.postgresql.org/index.html - -MySQL Database - - http://www.mysql.com/ - -A comparison of PostgreSQL and MySQL - - http://phpbuilder.com/columns/tim20001112.php3 - - -Other Template Systems -~~~~~~~~~~~~~~~~~~~~~~ - -(links.other.templateSystems) - -Python Wiki - - https://wiki.python.org/moin/Templating - - -Other Internet development frameworks -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -(links.internet) - -ZOPE (Z Object Publishing Environment) - - http://zope.org/ - -Server Side Java - - http://jakarta.apache.org/ - -PHP - - http://php.net/ - -IBM Websphere - - http://www.ibm.com/websphere/ - -Coldfusion and Spectra - - http://www.macromedia.com/ - - - diff --git a/docs/html/_sources/users_guide/nonHtml.rst.txt b/docs/html/_sources/users_guide/nonHtml.rst.txt deleted file mode 100644 index 19f9667..0000000 --- a/docs/html/_sources/users_guide/nonHtml.rst.txt +++ /dev/null @@ -1,16 +0,0 @@ -Non-HTML Output -=============== - -(nonHTML) - -Cheetah can also output any other text format besides HTML. - -Python source code ------------------- - -(nonHTML.python) - -To be written. We're in the middle of working on an autoindenter to -make it easier to encode Python indentation in a Cheetah template. - - diff --git a/docs/html/_sources/users_guide/otherHtml.rst.txt b/docs/html/_sources/users_guide/otherHtml.rst.txt deleted file mode 100644 index eeceaab..0000000 --- a/docs/html/_sources/users_guide/otherHtml.rst.txt +++ /dev/null @@ -1,101 +0,0 @@ -non-Webware HTML output -======================= - -(otherHTML) - -Cheetah can be used with all types of HTML output, not just with -Webware. - -Static HTML Pages ------------------ - -(otherHTML.static) - -Some sites like Linux Gazette (http://www.linuxgazette.com/) -require completely static pages because they are mirrored on -servers running completely different software from the main site. -Even dynamic sites may have one or two pages that are static for -whatever reason, and the site administrator may wish to generate -those pages from Cheetah templates. - -There's nothing special here. Just create your templates as usual. -Then compile and fill them whenever the template definition -changes, and fill them again whenever the placeholder values -change. You may need an extra step to copy the .html files to their -final location. A Makefile (chapter tips.Makefile) can help -encapsulate these steps. - -CGI scripts ------------ - -(otherHTML) - -Unlike Webware servlets, which don't have to worry about the HTTP -headers, CGI scripts must emit their own headers. To make a -template CGI aware, add this at the top: - -:: - - #extends Cheetah.Tools.CGITemplate - #implements respond - $cgiHeaders#slurp - -Or if your template is inheriting from a Python class: - -:: - - #extends MyPythonClass - #implements respond - $cgiHeaders#slurp - -A sample Python class: - -:: - - from Cheetah.Tools import CGITemplate - class MyPythonClass(CGITemplate): - def cgiHeadersHook(self): - return "Content-Type: text/html; charset=koi8-r\n\n" - -Compile the template as usual, put the .py template module in your -cgi-bin directory and give it execute permission. {.cgiHeaders()} -is a "smart" method that outputs the headers if the module is -called as a CGI script, or outputs nothing if not. Being -"called as a CGI script" means the environmental variable -{REQUEST\_METHOD} exists and {self.isControlledByWebKit} is false. -If you don't agree with that definition, override {.isCgi()} and -provide your own. - -The default header is a simple ``Content-type: text/html\n\n``, -which works with all CGI scripts. If you want to customize the -headers (e.g., to specify the character set), override -{.cgiHeadersHook()} and return a string containing all the headers. -Don't forget to include the extra newline at the end of the string: -the HTTP protocol requires this empty line to mark the end of the -headers. - -To read GET/POST variables from form input, use the {.webInput()} -method (section webware.webInput), or extract them yourself using -Python's {cgi} module or your own function. Although {.webInput()} -was originally written for Webware servlets, it now handles CGI -scripts too. There are a couple behavioral differences between CGI -scripts and Webware servlets regarding input variables: - - -#. CGI scripts, using Python's {cgi} module, believe - {REQUEST\_METHOD} and recognize { either} GET variables { or} POST - variables, not both. Webware servlets, doing additional processing, - ignore {REQUEST\_METHOD} and recognize both, like PHP does. - -#. Webware servlets can ask for cookies or session variables - instead of GET/POST variables, by passing the argument {src='c'} or - {src='s'}. CGI scripts get a {RuntimeError} if they try to do - this. - - -If you keep your .tmpl files in the same directory as your CGI -scripts, make sure they don't have execute permission. Apache at -least refuses to serve files in a {ScriptAlias} directory that -don't have execute permission. - - diff --git a/docs/html/_sources/users_guide/output.rst.txt b/docs/html/_sources/users_guide/output.rst.txt deleted file mode 100644 index d7fb8e0..0000000 --- a/docs/html/_sources/users_guide/output.rst.txt +++ /dev/null @@ -1,468 +0,0 @@ -.. role:: math(raw) - :format: html latex - -Generating, Caching and Filtering Output -======================================== - -(output) - -Output from complex expressions: #echo --------------------------------------- - -(output.echo) - -Syntax: - -:: - - #echo EXPR - -The {#echo} directive is used to echo the output from expressions -that can't be written as simple $placeholders. - -:: - - Here is my #echo ', '.join(['silly']*5) # example - -This produces: - -:: - - Here is my silly, silly, silly, silly, silly example. - -Executing expressions without output: #silent ---------------------------------------------- - -(output.silent) - -Syntax: - -:: - - #silent EXPR - -{#silent} is the opposite of {#echo}. It executes an expression but -discards the output. - -:: - - #silent $myList.reverse() - #silent $myList.sort() - Here is #silent $covertOperation() # nothing - -If your template requires some Python code to be executed at the -beginning; (e.g., to calculate placeholder values, access a -database, etc), you can put it in a "doEverything" method you -inherit, and call this method using {#silent} at the top of the -template. - -One-line #if ------------- - -(output.oneLineIf) - -Syntax: - -:: - - #if EXPR1 then EXPR2 else EXPR3# - -The {#if} flow-control directive (section flowControl.if) has a -one-line counterpart akin to Perl's and C's {?:} operator. If -{EXPR1} is true, it evaluates {EXPR2} and outputs the result (just -like {#echo EXPR2#}). Otherwise it evaluates {EXPR3} and outputs -that result. This directive is short-circuiting, meaning the -expression that isn't needed isn't evaluated. - -You MUST include both 'then' and 'else'. If this doesn't work for -you or you don't like the style use multi-line {#if} directives -(section flowControl.if). - -The trailing {#} is the normal end-of-directive character. As usual -it may be omitted if there's nothing after the directive on the -same line. - -Caching Output --------------- - -(output.caching) - -Caching individual placeholders -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -(output.caching.placeholders) - -By default, the values of each $placeholder is retrieved and -interpolated for every request. However, it's possible to cache the -values of individual placeholders if they don't change very often, -in order to speed up the template filling. - -To cache the value of a single {$placeholder}, add an asterisk -after the $; e.g., {$\*var}. The first time the template is filled, -{$var} is looked up. Then whenever the template is filled again, -the cached value is used instead of doing another lookup. - -The {$\*} format caches "forever"; that is, as long as the template -instance remains in memory. It's also possible to cache for a -certain time period using the form {$\*\*variable}, where -{} is the interval. The time interval can be specified in -seconds (5s), minutes (15m), hours (3h), days (2d) or weeks (1.5w). -The default is minutes. - -:: - - - $title - - - $var ${var} ## dynamic - will be reinterpolated for each request - $*var2 $*{var2} ## static - will be interpolated only once at start-up - $*5*var3 $*5*{var3} ## timed refresh - will be updated every five minutes. - - - - -Note that "every five minutes" in the example really means every -five minutes: the variable is looked up again when the time limit -is reached, whether the template is being filled that frequently or -not. Keep this in mind when setting refresh times for CPU-intensive -or I/O intensive operations. - -If you're using the long placeholder syntax, ``${}``, the braces go -only around the placeholder name: ``$*.5h*{var.func('arg')}``. - -Sometimes it's preferable to explicitly invalidate a cached item -whenever you say so rather than at certain time intervals. You -can't do this with individual placeholders, but you can do it with -cached regions, which will be described next. - -Caching entire regions -~~~~~~~~~~~~~~~~~~~~~~ - -(output.caching.regions) - -Syntax: - -:: - - #cache [id=EXPR] [timer=EXPR] [test=EXPR] - #end cache - -The {#cache} directive is used to cache a region of content in a -template. The region is cached as a single unit, after placeholders -and directives inside the region have been evaluated. If there are -any {$\*\*var} placholders inside the cache region, they -are refreshed only when { both} the cache region { and} the -placeholder are simultaneously due for a refresh. - -Caching regions offers more flexibility than caching individual -placeholders. You can specify the refresh interval using a -placeholder or expression, or refresh according to other criteria -rather than a certain time interval. - -{#cache} without arguments caches the region statically, the same -way as {$\*var}. The region will not be automatically refreshed. - -To refresh the region at an interval, use the {timer=EXPRESSION} -argument, equivalent to {$\*\*}. The expression should -evaluate to a number or string that is a valid interval (e.g., 0.5, -'3m', etc). - -To refresh whenever an expression is true, use {test=EXPRESSION}. -The expression can be a method/function returning true or false, a -boolean placeholder, several of these joined by {and} and/or {or}, -or any other expression. If the expression contains spaces, it's -easier to read if you enclose it in {()}, but this is not -required. - -To refresh whenever you say so, use {id=EXPRESSION}. Your program -can then call {.refreshCache(ID)} whenever it wishes. This is -useful if the cache depends on some external condition that changes -infrequently but has just changed now. - -You can combine arguments by separating them with commas. For -instance, you can specify both {id=} and {interval=}, or {id=} and -{test=}. (You can also combine interval and test although it's not -very useful.) However, repeating an argument is undefined. - -:: - - #cache - This is a static cache. It will not be refreshed. - $a $b $c - #end cache - - #cache timer='30m', id='cache1' - #for $cust in $customers - $cust.name: - $cust.street - $cust.city - #end for - #end cache - - #cache id='sidebar', test=$isDBUpdated - ... left sidebar HTML ... - #end cache - - #cache id='sidebar2', test=($isDBUpdated or $someOtherCondition) - ... right sidebar HTML ... - #end cache - -The {#cache} directive cannot be nested. - -We are planning to add a {'varyBy'} keyword argument in the future -that will allow a separate cache instances to be created for a -variety of conditions, such as different query string parameters or -browser types. This is inspired by ASP.net's varyByParam and -varyByBrowser output caching keywords. - -#raw ----- - -(output.raw) - -Syntax: - -:: - - #raw - #end raw - -Any section of a template definition that is inside a {#raw ... -#end raw} tag pair will be printed verbatim without any parsing of -$placeholders or other directives. This can be very useful for -debugging, or for Cheetah examples and tutorials. - -{#raw} is conceptually similar to HTML's {
    } tag and LaTeX's {
    -verbatim{}} tag, but unlike those tags, {#raw} does not cause the
    -body to appear in a special font or typeface. It can't, because
    -Cheetah doesn't know what a font is.
    -
    -#include
    ---------
    -
    -(output.include)
    -
    -Syntax:
    -
    -::
    -
    -    #include [raw] FILENAME_EXPR
    -    #include [raw] source=STRING_EXPR
    -
    -The {#include} directive is used to include text from outside the
    -template definition. The text can come from an external file or
    -from a {$placeholder} variable. When working with external files,
    -Cheetah will monitor for changes to the included file and update as
    -necessary.
    -
    -This example demonstrates its use with external files:
    -
    -::
    -
    -    #include "includeFileName.txt"
    -
    -The content of "includeFileName.txt" will be parsed for Cheetah
    -syntax.
    -
    -And this example demonstrates use with {$placeholder} variables:
    -
    -::
    -
    -    #include source=$myParseText
    -
    -The value of {$myParseText} will be parsed for Cheetah syntax. This
    -is not the same as simply placing the $placeholder tag
    -"{$myParseText}" in the template definition. In the latter case,
    -the value of $myParseText would not be parsed.
    -
    -By default, included text will be parsed for Cheetah tags. The
    -argument "{raw}" can be used to suppress the parsing.
    -
    -::
    -
    -    #include raw "includeFileName.txt"
    -    #include raw source=$myParseText
    -
    -Cheetah wraps each chunk of {#include} text inside a nested
    -{Template} object. Each nested template has a copy of the main
    -template's searchList. However, {#set} variables are visible across
    -includes only if the defined using the {#set global} keyword.
    -
    -All directives must be balanced in the include file. That is, if
    -you start a {#for} or {#if} block inside the include, you must end
    -it in the same include. (This is unlike PHP, which allows
    -unbalanced constructs in include files.)
    -
    -#slurp
    -------
    -
    -(output.slurp)
    -
    -Syntax:
    -
    -::
    -
    -    #slurp
    -
    -The {#slurp} directive eats up the trailing newline on the line it
    -appears in, joining the following line onto the current line.
    -
    -It is particularly useful in {#for} loops:
    -
    -::
    -
    -    #for $i in range(5)
    -    $i #slurp
    -    #end for
    -
    -outputs:
    -
    -::
    -
    -    0 1 2 3 4
    -
    -#indent
    --------
    -
    -(output.indent)
    -
    -This directive is not implemented yet. When/if it's completed, it
    -will allow you to
    -
    -
    -#. indent your template definition in a natural way (e.g., the
    -   bodies of {#if} blocks) without affecting the output
    -
    -#. add indentation to output lines without encoding it literally in
    -   the template definition. This will make it easier to use Cheetah to
    -   produce indented source code programmatically (e.g., Java or Python
    -   source code).
    -
    -
    -There is some experimental code that recognizes the {#indent}
    -directive with options, but the options are purposely undocumented
    -at this time. So pretend it doesn't exist. If you have a use for
    -this feature and would like to see it implemented sooner rather
    -than later, let us know on the mailing list.
    -
    -The latest specification for the future {#indent} directive is in
    -the TODO file in the Cheetah source distribution.
    -
    -Ouput Filtering and #filter
    ----------------------------
    -
    -(output.filter)
    -
    -Syntax:
    -
    -::
    -
    -    #filter FILTER_CLASS_NAME
    -    #filter $PLACEHOLDER_TO_A_FILTER_INSTANCE
    -    #filter None
    -
    -Output from $placeholders is passed through an ouput filter. The
    -default filter merely returns a string representation of the
    -placeholder value, unless the value is {None}, in which case the
    -filter returns an empty string. Only top-level placeholders invoke
    -the filter; placeholders inside expressions do not.
    -
    -Certain filters take optional arguments to modify their behaviour.
    -To pass arguments, use the long placeholder syntax and precede each
    -filter argument by a comma. By convention, filter arguments don't
    -take a {$} prefix, to avoid clutter in the placeholder tag which
    -already has plenty of dollar signs. For instance, the MaxLen filter
    -takes an argument 'maxlen':
    -
    -::
    -
    -    ${placeholderName, maxlen=20}
    -    ${functionCall($functionArg), maxlen=$myMaxLen}
    -
    -To change the output filter, use the {'filter'} keyword to the
    -{Template} class constructor, or the {#filter} directive at runtime
    -(details below). You may use {#filter} as often as you wish to
    -switch between several filters, if certain {$placeholders} need one
    -filter and other {$placeholders} need another.
    -
    -The standard filters are in the module {Cheetah.Filters}. Cheetah
    -currently provides:
    -
    -    The default filter, which converts None to '' and everything else
    -    to {str(whateverItIs)}. This is the base class for all other
    -    filters, and the minimum behaviour for all filters distributed with
    -    Cheetah.
    -
    -    Same.
    -
    -    Same, but truncate the value if it's longer than a certain length.
    -    Use the 'maxlen' filter argument to specify the length, as in the
    -    examples above. If you don't specify 'maxlen', the value will not
    -    be truncated.
    -
    -    Output a "pageful" of a long string. After the page, output HTML
    -    hyperlinks to the previous and next pages. This filter uses several
    -    filter arguments and environmental variables, which have not been
    -    documented yet.
    -
    -    Same as default, but convert HTML-sensitive characters
    -    (':math:`$<$`', '&', ':math:`$>$`') to HTML entities so that the
    -    browser will display them literally rather than interpreting them
    -    as HTML tags. This is useful with database values or user input
    -    that may contain sensitive characters. But if your values contain
    -    embedded HTML tags you want to preserve, you do not want this
    -    filter.
    -
    -    The filter argument 'also' may be used to specify additional
    -    characters to escape. For instance, say you want to ensure a value
    -    displays all on one line. Escape all spaces in the value with
    -    ' ', the non-breaking space:
    -
    -    ::
    -
    -        ${$country, also=' '}}
    -
    -
    -To switch filters using a class object, pass the class using the {
    -filter} argument to the Template constructor, or via a placeholder
    -to the {#filter} directive: {#filter $myFilterClass}. The class
    -must be a subclass of {Cheetah.Filters.Filter}. When passing a
    -class object, the value of { filtersLib} does not matter, and it
    -does not matter where the class was defined.
    -
    -To switch filters by name, pass the name of the class as a string
    -using the { filter} argument to the Template constructor, or as a
    -bare word (without quotes) to the {#filter} directive: {#filter
    -TheFilter}. The class will be looked up in the { filtersLib}.
    -
    -The filtersLib is a module containing filter classes, by default
    -{Cheetah.Filters}. All classes in the module that are subclasses of
    -{Cheetah.Filters.Filter} are considered filters. If your filters
    -are in another module, pass the module object as the { filtersLib}
    -argument to the Template constructor.
    -
    -Writing a custom filter is easy: just override the {.filter}
    -method.
    -
    -::
    -
    -        def filter(self, val, **kw):     # Returns a string.
    -
    -Return the { string} that should be output for 'val'. 'val' may be
    -any type. Most filters return \`' for {None}. Cheetah passes one
    -keyword argument: ``kw['rawExpr']`` is the placeholder name as it
    -appears in the template definition, including all subscripts and
    -arguments. If you use the long placeholder syntax, any options you
    -pass appear as keyword arguments. Again, the return value must be a
    -string.
    -
    -You can always switch back to the default filter this way: {#filter
    -None}. This is easy to remember because "no filter" means the
    -default filter, and because None happens to be the only object the
    -default filter treats specially.
    -
    -We are considering additional filters; see
    -http://webware.colorstudy.net/twiki/bin/view/Cheetah/MoreFilters
    -for the latest ideas.
    -
    -
    diff --git a/docs/html/_sources/users_guide/parserInstructions.rst.txt b/docs/html/_sources/users_guide/parserInstructions.rst.txt
    deleted file mode 100644
    index b187e7f..0000000
    --- a/docs/html/_sources/users_guide/parserInstructions.rst.txt
    +++ /dev/null
    @@ -1,129 +0,0 @@
    -Instructions to the Parser/Compiler
    -===================================
    -
    -(parserInstructions)
    -
    -#breakpoint
    ------------
    -
    -(parserInstructions.breakpoint)
    -
    -Syntax:
    -
    -::
    -
    -    #breakpoint
    -
    -{#breakpoint} is a debugging tool that tells the parser to stop
    -parsing at a specific point. All source code from that point on
    -will be ignored.
    -
    -The difference between {#breakpoint} and {#stop} is that {#stop}
    -occurs in normal templates (e.g., inside an {#if}) but
    -{#breakpoint} is used only when debugging Cheetah. Another
    -difference is that {#breakpoint} operates at compile time, while
    -{#stop} is executed at run time while filling the template.
    -
    -#compiler-settings
    -------------------
    -
    -(parserInstructions.compiler-settings)
    -
    -Syntax:
    -
    -::
    -
    -    #compiler-settings
    -    key = value    (no quotes)
    -    #end compiler-settings
    -
    -    #compiler-settings reset
    -
    -The {#compiler-settings} directive overrides Cheetah's standard
    -settings, changing how it parses source code and generates Python
    -code. This makes it possible to change the behaviour of Cheetah's
    -parser/compiler for a certain template, or within a portion of the
    -template.
    -
    -The {reset} argument reverts to the default settings. With {reset},
    -there's no end tag.
    -
    -Here are some examples of what you can do:
    -
    -::
    -
    -    $myVar
    -    #compiler-settings
    -    cheetahVarStartToken = @
    -    #end compiler-settings
    -    @myVar
    -    #compiler-settings reset
    -    $myVar
    -
    -::
    -
    -    ## normal comment
    -    #compiler-settings
    -    commentStartToken = //
    -    #end compiler-settings
    -
    -    // new style of comment
    -
    -    #compiler-settings reset
    -
    -    ## back to normal comments
    -
    -::
    -
    -    #slurp
    -    #compiler-settings
    -    directiveStartToken = %
    -    #end compiler-settings
    -
    -    %slurp
    -    %compiler-settings reset
    -
    -    #slurp
    -
    -Here's a partial list of the settings you can change:
    -
    -
    -#. syntax settings
    -
    -
    -   #. cheetahVarStartToken
    -
    -   #. commentStartToken
    -
    -   #. multilineCommentStartToken
    -
    -   #. multilineCommentEndToken
    -
    -   #. directiveStartToken
    -
    -   #. directiveEndToken
    -
    -
    -#. code generation settings
    -
    -
    -   #. commentOffset
    -
    -   #. outputRowColComments
    -
    -   #. defDocStrMsg
    -
    -   #. useNameMapper
    -
    -   #. useAutocalling
    -
    -   #. reprShortStrConstants
    -
    -   #. reprNewlineThreshold
    -
    -
    -
    -The meaning of these settings and their default values will be
    -documented in the future.
    -
    -
    diff --git a/docs/html/_sources/users_guide/tipsAndTricks.rst.txt b/docs/html/_sources/users_guide/tipsAndTricks.rst.txt
    deleted file mode 100644
    index 8e06952..0000000
    --- a/docs/html/_sources/users_guide/tipsAndTricks.rst.txt
    +++ /dev/null
    @@ -1,586 +0,0 @@
    -Tips, Tricks and Troubleshooting
    -================================
    -
    -(tips)
    -
    -This chapter contains short stuff that doesn't fit anywhere else.
    -
    -See the Cheetah FAQ for more specialized issues and for
    -troubleshooting tips. Check the wiki periodically for recent tips
    -contributed by users. If you get stuck and none of these resources
    -help, ask on the mailing list.
    -
    -Placeholder Tips
    -----------------
    -
    -(tips.placeholder)
    -
    -Here's how to do certain important lookups that may not be obvious.
    -For each, we show first the Cheetah expression and then the Python
    -equivalent, because you can use these either in templates or in
    -pure Python subclasses. The Cheetah examples use NameMapper
    -shortcuts (uniform dotted notation, autocalling) as much as
    -possible.
    -
    -To verify whether a variable exists in the searchList:
    -
    -::
    -
    -    $varExists('theVariable')
    -    self.varExists('theVariable')
    -
    -This is useful in {#if} or {#unless} constructs to avoid a
    -{#NameMapper.NotFound} error if the variable doesn't exist. For
    -instance, a CGI GET parameter that is normally supplied but in this
    -case the user typed the URL by hand and forgot the parameter (or
    -didn't know about it). ({.hasVar} is a synonym for {.varExists}.)
    -
    -To look up a variable in the searchList from a Python method:
    -
    -::
    -
    -    self.getVar('theVariable')
    -    self.getVar('theVariable', myDefault)
    -
    -This is the equivalent to {$theVariable} in the template. If the
    -variable is missing, it returns the second argument, {myDefault},
    -if present, or raises {NameMapper.NotFound} if there is no second
    -argument. However, it usually easier to write your method so that
    -all needed searchList values come in as method arguments. That way
    -the caller can just use a {$placeholder} to specify the argument,
    -which is less verbose than you writing a getVar call.
    -
    -To do a "safe" placeholder lookup that returns a default value if
    -the variable is missing:
    -
    -::
    -
    -    $getVar('theVariable', None)
    -    $getVar('theVariable', $myDefault)
    -
    -To get an environmental variable, put {os.environ} on the
    -searchList as a container. Or read the envvar in Python code and
    -set a placeholder variable for it.
    -
    -Remember that variables found earlier in the searchList override
    -same-name variables located in a later searchList object. Be
    -careful when adding objects containing other variables besides the
    -ones you want (e.g., {os.environ}, CGI parameters). The "other"
    -variables may override variables your application depends on,
    -leading to hard-to-find bugs. Also, users can inadvertently or
    -maliciously set an environmental variable or CGI parameter you
    -didn't expect, screwing up your program. To avoid all this, know
    -what your namespaces contain, and place the namespaces you have the
    -most control over first. For namespaces that could contain
    -user-supplied "other" variables, don't put the namespace itself in
    -the searchList; instead, copy the needed variables into your own
    -"safe" namespace.
    -
    -Diagnostic Output
    ------------------
    -
    -(tips.diagnostic)
    -
    -If you need send yourself some debugging output, you can use
    -{#silent} to output it to standard error:
    -
    -::
    -
    -    #silent $sys.stderr.write("Incorrigible var is '$incorrigible'.\n")
    -    #silent $sys.stderr.write("Is 'unknown' in the searchList? " +
    -        $getVar("unknown", "No.") + "\n" )
    -
    -(Tip contributed by Greg Czajkowski.)
    -
    -When to use Python methods
    ---------------------------
    -
    -(tips.pythonMethods)
    -
    -You always have a choice whether to code your methods as Cheetah
    -{#def} methods or Python methods (the Python methods being located
    -in a class your template inherits). So how do you choose?
    -
    -Generally, if the method consists mostly of text and placeholders,
    -use a Cheetah method (a {#def} method). That's why {#def} exists,
    -to take the tedium out of writing those kinds of methods. And if
    -you have a couple {#if} stanzas to {#set} some variables, followed
    -by a {#for} loop, no big deal. But if your method consists mostly
    -of directives and only a little text, you're better off writing it
    -in Python. Especially be on the watch for extensive use of {#set},
    -{#echo} and {#silent} in a Cheetah method-it's a sure sign you're
    -probably using the wrong language. Of course, though, you are free
    -to do so if you wish.
    -
    -Another thing that's harder to do in Cheetah is adjacent or nested
    -multiline stanzas (all those directives with an accompanying {#end}
    -directive). Python uses indentation to show the beginning and end
    -of nested stanzas, but Cheetah can't do that because any
    -indentation shows up in the output, which may not be desired. So
    -unless all those extra spaces and tabs in the output are
    -acceptable, you have to keep directives flush with the left margin
    -or the preceding text.
    -
    -The most difficult decisions come when you have conflicting goals.
    -What if a method generates its output in parts (i.e., output
    -concatenation), contains many searchList placeholders and lots of
    -text, { and} requires lots of {#if ... #set ... #else #set ... #end
    -if} stanzas. A Cheetah method would be more advantageous in some
    -ways, but a Python method in others. You'll just have to choose,
    -perhaps coding groups of methods all the same way. Or maybe you can
    -split your method into two, one Cheetah and one Python, and have
    -one method call the other. Usually this means the Cheetah method
    -calling the Python method to calculate the needed values, then the
    -Cheetah method produces the output. One snag you might run into
    -though is that {#set} currently can set only one variable per
    -statement, so if your Python method needs to return multiple values
    -to your Cheetah method, you'll have to do it another way.
    -
    -Calling superclass methods, and why you have to
    ------------------------------------------------
    -
    -(tips.callingSuperclassMethods)
    -
    -If your template or pure Python class overrides a standard method
    -or attribute of {Template} or one of its base classes, you should
    -call the superclass method in your method to prevent various things
    -from breaking. The most common methods to override are {.awake} and
    -{.\_\_init\_\_}. {.awake} is called automatically by Webware early
    -during the web transaction, so it makes a convenient place to put
    -Python initialization code your template needs. You'll definitely
    -want to call the superclass {.awake} because it sets up many
    -wonderful attributes and methods, such as those to access the CGI
    -input fields.
    -
    -There's nothing Cheetah-specific to calling superclass methods, but
    -because it's vital, we'll recap the standard Python techniques
    -here. We mention only the solution for old-style classes because
    -Cheetah classes are old-style (in other Python documentation, you
    -will find the technique for new-style classes, but they are not
    -listed here because they cannot be used with Cheetah if you use
    -dynamically-compiled templates).
    -
    -::
    -
    -    from Cheetah.Template import Template
    -    class MyClass(Template):
    -        def awake(self, trans):
    -            Template.awake(self, trans)
    -            ... great and exciting features written by me ...
    -
    -[ @@MO: Need to test this. .awake is in Servlet, which is a
    -superclass of Template. Do we really need both imports? Can we call
    -Template.awake? ]
    -
    -To avoid hardcoding the superclass name, you can use this function
    -{callbase()}, which emulates {super()} for older versions of
    -Python. It also works even {super()} does exist, so you don't have
    -to change your servlets immediately when upgrading. Note that the
    -argument sequence is different than {super} uses.
    -
    -::
    -
    -    ===========================================================================
    -    # Place this in a module SOMEWHERE.py .  Contributed by Edmund Lian.
    -    class CallbaseError(AttributeError):
    -        pass
    -
    -    def callbase(obj, base, methodname='__init__', args=(), kw={},
    -        raiseIfMissing=None):
    -        try: method = getattr(base, methodname)
    -        except AttributeError:
    -            if raiseIfMissing:
    -                raise CallbaseError, methodname
    -            return None
    -        if args is None: args = ()
    -        return method(obj, *args, **kw)
    -    ===========================================================================
    -    # Place this in your class that's overriding .awake (or any method).
    -    from SOMEWHERE import callbase
    -    class MyMixin:
    -            def awake(self, trans):
    -                    args = (trans,)
    -                    callbase(self, MyMixin, 'awake', args)
    -                    ... everything else you want to do ...
    -    ===========================================================================
    -
    -All methods
    ------------
    -
    -(tips.allMethods)
    -
    -Here is a list of all the standard methods and attributes that can
    -be accessed from a placeholder. Some of them exist for you to call,
    -others are mainly used by Cheetah internally but you can call them
    -if you wish, and others are only for internal use by Cheetah or
    -Webware. Do not use these method names in mixin classes
    -({#extends}, section inheritanceEtc.extends) unless you intend to
    -override the standard method.
    -
    -Variables with a star prefix ({ \*}) are frequently used in
    -templates or in pure Python classes.
    -
    -\*{Inherited from Cheetah.Template}
    -
    -    Compile the template. Automatically called by {.\_\_init\_\_}.
    -
    -    Return the module code the compiler generated, or {None} if no
    -    compilation took place.
    -
    -    Return the class code the compiler generated, or {None} if no
    -    compilation took place.
    -
    -    Return a reference to the underlying search list. (a list of
    -    objects). Use this to print out your searchList for debugging.
    -    Modifying the returned list will affect your placeholder searches!
    -
    -    Return a reference to the current error catcher.
    -
    -    If 'cacheKey' is not {None}, refresh that item in the cache. If
    -    {None}, delete all items in the cache so they will be recalculated
    -    the next time they are encountered.
    -
    -    Break reference cycles before discarding a servlet.
    -
    -    Look up a variable in the searchList. Same as {$varName} but allows
    -    you to specify a default value and control whether autocalling
    -    occurs.
    -
    -    Read the named file. If used as a placeholder, inserts the file's
    -    contents in the output without interpretation, like {#include raw}.
    -    If used in an expression, returns the file's content (e.g., to
    -    assign it to a variable).
    -
    -    This is what happens if you run a .py template module as a
    -    standalone program.
    -
    -
    -\*{Inherited from Cheetah.Utils.WebInputMixin}
    -
    -    Exception raised by {.webInput}.
    -
    -    Convenience method to access GET/POST variables from a Webware
    -    servlet or CGI script, or Webware cookie or session variables. See
    -    section webware.webInput for usage information.
    -
    -
    -\*{Inherited from Cheetah.SettingsManager}
    -
    -    Get a compiler setting.
    -
    -    Does this compiler setting exist?
    -
    -    Set setting 'name' to 'value'. See {#compiler-settings}, section
    -    parserInstructions.compiler-settings.
    -
    -    Return the underlying settings dictionary. (Warning: modifying this
    -    dictionary will change Cheetah's behavior.)
    -
    -    Return a copy of the underlying settings dictionary.
    -
    -    Return a deep copy of the underlying settings dictionary. See
    -    Python's {copy} module.
    -
    -    Update Cheetah's compiler settings from the 'newSettings'
    -    dictionary. If 'merge' is true, update only the names in
    -    newSettings and leave the other names alone. (The SettingsManager
    -    is smart enough to update nested dictionaries one key at a time
    -    rather than overwriting the entire old dictionary.) If 'merge' is
    -    false, delete all existing settings so that the new ones are the
    -    only settings.
    -
    -    Same, but pass a string of {name=value} pairs rather than a
    -    dictionary, the same as you would provide in a {#compiler-settings}
    -    directive, section parserInstructions.compiler-settings.
    -
    -    Same, but exec a Python source file and use the variables it
    -    contains as the new settings. (e.g.,
    -    {cheetahVarStartToken = "@"}).
    -
    -    Same, but get the new settings from a text file in ConfigParser
    -    format (similar to Windows' \*.ini file format). See Python's
    -    {ConfigParser} module.
    -
    -    Same, but read the open file object 'inFile' for the new settings.
    -
    -    Same, but read the new settings from a string in ConfigParser
    -    format.
    -
    -    Write the current compiler settings to a file named 'path' in
    -    \*.ini format.
    -
    -    Return a string containing the current compiler settings in \*.ini
    -    format.
    -
    -
    -\*{Inherited from Cheetah.Servlet}
    -
    -{ Do not override these in a subclass or assign to them as
    -attributes if your template will be used as a servlet,} otherwise
    -Webware will behave unpredictably. However, it { is} OK to put
    -same-name variables in the searchList, because Webware does not use
    -the searchList.
    -
    -EXCEPTION: It's OK to override { awake} and { sleep} as long as you
    -call the superclass methods. (See section
    -tips.callingSuperclassMethods.)
    -
    -    True if this template instance is part of a live transaction in a
    -    running WebKit servlet.
    -
    -    True if Webware is installed and the template instance inherits
    -    from WebKit.Servlet. If not, it inherits from
    -    Cheetah.Servlet.DummyServlet.
    -
    -    Called by WebKit at the beginning of the web transaction.
    -
    -    Called by WebKit at the end of the web transaction.
    -
    -    Called by WebKit to produce the web transaction content. For a
    -    template-servlet, this means filling the template.
    -
    -    Break reference cycles before deleting instance.
    -
    -    The filesystem pathname of the template-servlet (as opposed to the
    -    URL path).
    -
    -    The current Webware transaction.
    -
    -    The current Webware application.
    -
    -    The current Webware response.
    -
    -    The current Webware request.
    -
    -    The current Webware session.
    -
    -    Call this method to insert text in the filled template output.
    -
    -
    -Several other goodies are available to template-servlets under the
    -{request} attribute, see section webware.input.
    -
    -{transaction}, {response}, {request} and {session} are created from
    -the current transaction when WebKit calls {awake}, and don't exist
    -otherwise. Calling {awake} yourself (rather than letting WebKit
    -call it) will raise an exception because the {transaction} argument
    -won't have the right attributes.
    -
    -\*{Inherited from WebKit.Servlet} These are accessible only if
    -Cheetah knows Webware is installed. This listing is based on a CVS
    -snapshot of Webware dated 22 September 2002, and may not include
    -more recent changes.
    -
    -The same caveats about overriding these methods apply.
    -
    -    The simple name of the class. Used by Webware's logging and
    -    debugging routines.
    -
    -    Used by Webware's logging and debugging routines.
    -
    -    True if the servlet can be multithreaded.
    -
    -    True if the servlet can be used for another transaction after the
    -    current transaction is finished.
    -
    -    Depreciated by {.serverSidePath()}.
    -
    -
    -Optimizing templates
    ---------------------
    -
    -(tips.optimizing)
    -
    -Here are some things you can do to make your templates fill faster
    -and user fewer CPU cycles. Before you put a lot of energy into
    -this, however, make sure you really need to. In many situations,
    -templates appear to initialize and fill instantaneously, so no
    -optimization is necessary. If you do find a situation where your
    -templates are filling slowly or taking too much memory or too many
    -CPU cycles, we'd like to hear about it on the mailing list.
    -
    -Cache $placeholders whose values don't change frequently. (Section
    -output.caching).
    -
    -Use {#set} for values that are very frequently used, especially if
    -they come out of an expensive operation like a
    -deeply.nested.structure or a database lookup. {#set} variables are
    -set to Python local variables, which have a faster lookup time than
    -Python globals or values from Cheetah's searchList.
    -
    -Moving variable lookups into Python code may provide a speedup in
    -certain circumstances. If you're just reading {self} attributes,
    -there's no reason to use NameMapper lookup ($placeholders) for
    -them. NameMapper does a lot more work than simply looking up a
    -{self} attribute.
    -
    -On the other hand, if you don't know exactly where the value will
    -come from (maybe from {self}, maybe from the searchList, maybe from
    -a CGI input variable, etc), it's easier to just make that an
    -argument to your method, and then the template can handle all the
    -NameMapper lookups for you:
    -
    -::
    -
    -    #silent $myMethod($arg1, $arg2, $arg3)
    -
    -Otherwise you'd have to call {self.getVar('arg1')} etc in your
    -method, which is more wordy, and tedious.
    -
    -PSP-style tags
    ---------------
    -
    -(tips.PSP)
    -
    -{<%= ... %>} and {<% ... %>} allow an escape to Python syntax
    -inside the template. You do not need it to use Cheetah effectively,
    -and we're hard pressed to think of a case to recommend it.
    -Nevertheless, it's there in case you encounter a situation you
    -can't express adequately in Cheetah syntax. For instance, to set a
    -local variable to an elaborate initializer.
    -
    -{<%= ... %>} encloses a Python expression whose result will be
    -printed in the output.
    -
    -{<% ... %>} encloses a Python statement or expression (or set of
    -statements or expressions) that will be included as-is into the
    -generated method. The statements themselves won't produce any
    -output, but you can use the local function {write(EXPRESSION)} to
    -produce your own output. (Actually, it's a method of a file-like
    -object, but it looks like a local function.) This syntax also may
    -be used to set a local variable with a complicated initializer.
    -
    -To access Cheetah services, you must use Python code like you would
    -in an inherited Python class. For instance, use {self.getVar()} to
    -look up something in the searchList.
    -
    -{ Warning:} { No error checking is done!} If you write:
    -
    -::
    -
    -    <% break %>      ## Wrong!
    -
    -you'll get a {SyntaxError} when you fill the template, but that's
    -what you deserve.
    -
    -Note that these are PSP-{ style} tags, not PSP tags. A Cheetah
    -template is not a PSP document, and you can't use PSP commands in
    -it.
    -
    -Makefiles
    ----------
    -
    -(tips.Makefile)
    -
    -If your project has several templates and you get sick of typing
    -"cheetah compile FILENAME.tmpl" all the time-much less remembering
    -which commands to type when-and your system has the {make} command
    -available, consider building a Makefile to make your life easier.
    -
    -Here's a simple Makefile that controls two templates,
    -ErrorsTemplate and InquiryTemplate. Two external commands,
    -{inquiry} and {receive}, depend on ErrorsTemplate.py. Aditionally,
    -InquiryTemplate itself depends on ErrorsTemplate.
    -
    -::
    -
    -    all:  inquiry  receive
    -
    -    .PHONY:  all  receive  inquiry  printsource
    -
    -    printsource:
    -            a2ps InquiryTemplate.tmpl ErrorsTemplate.tmpl
    -
    -    ErrorsTemplate.py:  ErrorsTemplate.tmpl
    -            cheetah compile ErrorsTemplate.tmpl
    -
    -    InquiryTemplate.py:  InquiryTemplate.tmpl ErrorsTemplate.py
    -            cheetah compile InquiryTemplate.tmpl
    -
    -    inquiry: InquiryTemplate.py  ErrorsTemplate.py
    -
    -    receive: ErrorsTemplate.py
    -
    -Now you can type {make} anytime and it will recompile all the
    -templates that have changed, while ignoring the ones that haven't.
    -Or you can recompile all the templates {receive} needs by typing
    -{make receive}. Or you can recompile only ErrorsTemplate by typing
    -{make ErrorsTemplate}. There's also another target, "printsource":
    -this sends a Postscript version of the project's source files to
    -the printer. The .PHONY target is explained in the {make}
    -documentation; essentially, you have it depend on every target that
    -doesn't produce an output file with the same name as the target.
    -
    -Using Cheetah in a Multi-Threaded Application
    ----------------------------------------------
    -
    -(tips.threads)
    -
    -Template classes may be shared freely between threads. However,
    -template instances should not be shared unless you either:
    -
    -
    --  Use a lock (mutex) to serialize template fills, to prevent two
    -   threads from filling the template at the same time.
    -
    --  Avoid thread-unsafe features:
    -
    -
    -   -  Modifying searchList values or instance variables.
    -
    -   -  Caching ({$\*var}, {#cache}, etc).
    -
    -   -  {#set global}, {#filter}, {#errorCatcher}.
    -
    -
    -   Any changes to these in one thread will be visible in other
    -   threads, causing them to give inconsistent output.
    -
    -
    -About the only advantage in sharing a template instance is building
    -up the placeholder cache. But template instances are so low
    -overhead that it probably wouldn't take perceptibly longer to let
    -each thread instantiate its own template instance. Only if you're
    -filling templates several times a second would the time difference
    -be significant, or if some of the placeholders trigger extremely
    -slow calculations (e.g., parsing a long text file each time). The
    -biggest overhead in Cheetah is importing the {Template} module in
    -the first place, but that has to be done only once in a
    -long-running application.
    -
    -You can use Python's {mutex} module for the lock, or any similar
    -mutex. If you have to change searchList values or instance
    -variables before each fill (which is usually the case), lock the
    -mutex before doing this, and unlock it only after the fill is
    -complete.
    -
    -For Webware servlets, you're probably better off using Webware's
    -servlet caching rather than Cheetah's caching. Don't override the
    -servlet's {.canBeThreaded()} method unless you avoid the unsafe
    -operations listed above.
    -
    -Using Cheetah with gettext
    ---------------------------
    -
    -(tips.gettext)
    -
    -{ gettext} is a project for creating internationalized
    -applications. For more details, visit
    -http://docs.python.org/lib/module-gettext.html. gettext can be used
    -with Cheetah to create internationalized applications, even for CJK
    -character sets, but you must keep a couple things in mind:
    -
    -
    --  xgettext is used on compiled templates, not on the templates
    -   themselves.
    -
    --  The way the NameMapper syntax gets compiled to Python gets in
    -   the way of the syntax that xgettext recognizes. Hence, a special
    -   case exists for the functions {\_}, {N\_}, and {ngettext}. If you
    -   need to use a different set of functions for marking strings for
    -   translation, you must set the Cheetah setting {gettextTokens} to a
    -   list of strings representing the names of the functions you are
    -   using to mark strings for translation.
    -
    -
    -
    diff --git a/docs/html/_sources/users_guide/webware.rst.txt b/docs/html/_sources/users_guide/webware.rst.txt
    deleted file mode 100644
    index bc36a2b..0000000
    --- a/docs/html/_sources/users_guide/webware.rst.txt
    +++ /dev/null
    @@ -1,598 +0,0 @@
    -Using Cheetah with Webware
    -==========================
    -
    -(webware)
    -
    -{ Webware for Python} is a 'Python-Powered Internet Platform' that
    -runs servlets in a manner similar to Java servlets. { WebKit} is
    -the name of Webware's application server. For more details, please
    -visit https://cito.github.io/w4py/.
    -
    -All comments below refer to the official version of Webware, the
    -DamnSimple! offshoot at ?, and the now-abandoned
    -WebwareExperimental implementation at
    -http://sourceforge.net/projects/expwebware/, except where noted.
    -All the implementations are 95% identical to the servlet writer:
    -their differences lie in their internal structure and configuration
    -files. One difference is that the executable you run to launch
    -standard Webware is called {AppServer}, whereas in
    -WebwareExperimental it's called {webkit}. But to servlets they're
    -both "WebKit, Webware's application server", so it's one half dozen
    -to the other. In this document, we generally use the term { WebKit}
    -to refer to the currently-running application server.
    -
    -Installing Cheetah on a Webware system
    ---------------------------------------
    -
    -(webware.installing)
    -
    -Install Cheetah after you have installed Webware, following the
    -instructions in chapter gettingStarted.
    -
    -The standard Cheetah test suite ('cheetah test') does not test
    -Webware features. We plan to build a test suite that can run as a
    -Webware servlet, containing Webware-specific tests, but that has
    -not been built yet. In the meantime, you can make a simple template
    -containing something like "This is a very small template.", compile
    -it, put the \*.py template module in a servlet directory, and see
    -if Webware serves it up OK.
    -
    -{ You must not have a Webware context called "Cheetah".} If you do,
    -Webware will mistake that directory for the Cheetah module
    -directory, and all template-servlets will bomb out with a
    -"ImportError: no module named Template". (This applies only to the
    -standard Webware; WebwareExperimental does not have contexts.)
    -
    -If Webware complains that it cannot find your servlet, make sure
    -'.tmpl' is listed in 'ExtensionsToIgnore' in your
    -'Application.config' file.
    -
    -Containment vs Inheritance
    ---------------------------
    -
    -(webware.background)
    -
    -Because Cheetah's core is flexible, there are many ways to
    -integrate it with Webware servlets. There are two broad strategies:
    -the { Inheritance approach} and the { Containment approach}. The
    -difference is that in the Inheritance approach, your template
    -object { is} the servlet, whereas in the Containment approach, the
    -servlet is not a template but merely { uses} template(s) for
    -portion(s) of its work.
    -
    -The Inheritance approach is recommended for new sites because it's
    -simpler, and because it scales well for large sites with a
    -site->section->subsection->servlet hierarchy. The Containment
    -approach is better for existing servlets that you don't want to
    -restructure. For instance, you can use the Containment approach to
    -embed a discussion-forum table at the bottom of a web page.
    -
    -However, most people who use Cheetah extensively seem to prefer the
    -Inheritance approach because even the most analytical servlet needs
    -to produce { some} output, and it has to fit the site's look and
    -feel { anyway}, so you may as well use a template-servlet as the
    -place to put the output. Especially since it's so easy to add a
    -template-servlet to a site once the framework is established. So we
    -recommend you at least evaluate the effort that would be required
    -to convert your site framework to template superclasses as
    -described below, vs the greater flexibility and manageability it
    -might give the site over the long term. You don't necessarily have
    -to convert all your existing servlets right away: just build common
    -site templates that are visually and behaviorally compatible with
    -your specification, and use them for new servlets. Existing
    -servlets can be converted later, if at all.
    -
    -Edmund Liam is preparing a section on a hybrid approach, in which
    -the servlet is not a template, but still calls template(s) in an
    -inheritance chain to produce the output. The advantage of this
    -approach is that you aren't dealing with {Template} methods and
    -Webware methods in the same object.
    -
    -The Containment Approach
    -~~~~~~~~~~~~~~~~~~~~~~~~
    -
    -(webware.containment)
    -
    -In the Containment approach, your servlet is not a template.
    -Instead, it it makes its own arrangements to create and use
    -template object(s) for whatever it needs. The servlet must
    -explicitly call the template objects' {.respond()} (or
    -{.\_\_str\_\_()}) method each time it needs to fill the template.
    -This does not present the output to the user; it merely gives the
    -output to the servlet. The servlet then calls its
    -{#self.response().write()} method to send the output to the user.
    -
    -The developer has several choices for managing her templates. She
    -can store the template definition in a string, file or database and
    -call {Cheetah.Template.Template} manually on it. Or she can put the
    -template definition in a \*.tmpl file and use { cheetah compile}
    -(section howWorks.cheetah-compile) to convert it to a Python class
    -in a \*.py module, and then import it into her servlet.
    -
    -Because template objects are not thread safe, you should not store
    -one in a module variable and allow multiple servlets to fill it
    -simultaneously. Instead, each servlet should instantiate its own
    -template object. Template { classes}, however, are thread safe,
    -since they don't change once created. So it's safe to store a
    -template class in a module global variable.
    -
    -The Inheritance Approach
    -~~~~~~~~~~~~~~~~~~~~~~~~
    -
    -(webware.inheritance)
    -
    -In the Inheritance approach, your template object doubles as as
    -Webware servlet, thus these are sometimes called {
    -template-servlets}. { cheetah compile} (section
    -howWorks.cheetah-compile) automatically creates modules containing
    -valid Webware servlets. A servlet is a subclass of Webware's
    -{WebKit.HTTPServlet} class, contained in a module with the same
    -name as the servlet. WebKit uses the request URL to find the
    -module, and then instantiates the servlet/template. The servlet
    -must have a {.respond()} method (or {.respondToGet()},
    -{.respondToPut()}, etc., but the Cheetah default is {.respond()}).
    -Servlets created by {cheetah compile} meet all these requirements.
    -
    -(Cheetah has a Webware plugin that automatically converts a {.tmpl
    -servlet file} into a {.py servlet file} when the {.tmpl servlet
    -file} is requested by a browser. However, that plugin is currently
    -unavailable because it's being redesigned. For now, use {cheetah
    -compile} instead.)
    -
    -What about logic code? Cheetah promises to keep content (the
    -placeholder values), graphic design (the template definition and is
    -display logic), and algorithmic logic (complex calculations and
    -side effects) separate. How? Where do you do form processing?
    -
    -The answer is that your template class can inherit from a pure
    -Python class containing the analytical logic. You can either use
    -the {#extends} directive in Cheetah to indicate the superclass(es),
    -or write a Python {class} statement to do the same thing. See the
    -template {Cheetah.Templates.SkeletonPage.tmpl} and its pure Python
    -class {Cheetah.Templates.\_SkeletonPage.py} for an example of a
    -template inheriting logic code. (See sections
    -inheritanceEtc.extends and inheritanceEtc.implements for more
    -information about {#extends} and {#implements}. They have to be
    -used a certain right way.)
    -
    -If {#WebKit.HTTPServlet} is not available, Cheetah fakes it with a
    -dummy class to satisfy the dependency. This allows servlets to be
    -tested on the command line even on systems where Webware is not
    -installed. This works only with servlets that don't call back into
    -WebKit for information about the current web transaction, since
    -there is no web transaction. Trying to access form input, for
    -instance, will raise an exception because it depends on a live web
    -request object, and in the dummy class the request object is
    -{None}.
    -
    -Because Webware servlets must be valid Python modules, and
    -"cheetah compile" can produce only valid module names, if you're
    -converting an existing site that has .html filenames with hyphens
    -(-), extra dots (.), etc, you'll have to rename them (and possibly
    -use redirects).
    -
    -Site frameworks
    ----------------
    -
    -(webware.siteFrameworks)
    -
    -Web sites are normally arranged hierarchically, with certain
    -features common to every page on the site, other features common to
    -certain sections or subsections, and others unique to each page.
    -You can model this easily with a hierarchy of classes, with
    -specific servlets inheriting from their more general superclasses.
    -Again, you can do this two ways, using Cheetah's { Containment}
    -approach or { Inheritance} approach.
    -
    -In the Inheritance approach, parents provide {#block}s and children
    -override them using {#def}. Each child {#extend}s its immediate
    -parent. Only the leaf servlets need to be under WebKit's document
    -root directory. The superclass servlets can live anywhere in the
    -filesystem that's in the Python path. (You may want to modify your
    -WebKit startup script to add that library directory to your
    -{PYTHONPATH} before starting WebKit.)
    -
    -Section libraries.templates.skeletonPage contains information on a
    -stock template that simplifies defining the basic HTML structure of
    -your web page templates.
    -
    -In the Containment approach, your hierarchy of servlets are not
    -templates, but each uses one or more templates as it wishes.
    -Children provide callback methods to to produce the various
    -portions of the page that are their responsibility, and parents
    -call those methods. Webware's {WebKit.Page} and
    -{WebKit.SidebarPage} classes operate like this.
    -
    -Note that the two approaches are not compatible! {WebKit.Page} was
    -not designed to intermix with {Cheetah.Templates.SkeletonPage}.
    -Choose either one or the other, or expect to do some integration
    -work.
    -
    -If you come up with a different strategy you think is worth noting
    -in this chapter, let us know.
    -
    -Directory structure
    --------------------
    -
    -(webware.directoryStructure)
    -
    -Here's one way to organize your files for Webware+Cheetah.
    -
    -::
    -
    -    www/                         # Web root directory.
    -        site1.example.com/       # Site subdirectory.
    -            apache/              # Web server document root (for non-servlets).
    -            www/                 # WebKit document root.
    -               index.py          # http://site1.example.com/
    -               index.tmpl        # Source for above.
    -               servlet2.py       # http://site1.example.com/servlet2
    -               servlet2.tmpl     # Source for above.
    -            lib/                 # Directory for helper classes.
    -               Site.py           # Site superclass ("#extends Site").
    -               Site.tmpl         # Source for above.
    -               Logic.py          # Logic class inherited by some template.
    -            webkit.config        # Configuration file (for WebwareExperimental).
    -            Webware/             # Standard Webware's MakeAppWorkDir directory.
    -               AppServer         # Startup program (for standard Webware).
    -               Configs/          # Configuration directory (for standard Webware).
    -                   Application.config
    -                                 # Configuration file (for standard Webware).
    -        site2.example.org/       # Another virtual host on this computer....
    -
    -Initializing your template-servlet with Python code
    ----------------------------------------------------
    -
    -(webware.calculations)
    -
    -If you need a place to initialize variables or do calculations for
    -your template-servlet, you can put it in an {.awake()} method
    -because WebKit automatically calls that early when processing the
    -web transaction. If you do override {.awake()}, be sure to call the
    -superclass {.awake} method. You probably want to do that first so
    -that you have access to the web transaction data {Servlet.awake}
    -provides. You don't have to worry about whether your parent class
    -has its own {.awake} method, just call it anyway, and somebody up
    -the inheritance chain will respond, or at minimum {Servlet.awake}
    -will respond. Section tips.callingSuperclassMethods gives examples
    -of how to call a superclass method.
    -
    -As an alternative, you can put all your calculations in your own
    -method and call it near the top of your template. ({#silent},
    -section output.silent).
    -
    -Form processing
    ----------------
    -
    -(webware.form)
    -
    -There are many ways to display and process HTML forms with Cheetah.
    -But basically, all form processing involves two steps.
    -
    -
    -#. Display the form.
    -
    -#. In the next web request, read the parameters the user submitted,
    -   check for user errors, perform any side effects (e.g.,
    -   reading/writing a database or session data) and present the user an
    -   HTML response or another form.
    -
    -
    -The second step may involve choosing between several templates to
    -fill (or several servlets to redirect to), or a big
    -if-elif-elif-else construct to display a different portion of the
    -template depending on the situation.
    -
    -In the oldest web applications, step 1 and step 2 were handled by
    -separate objects. Step 1 was a static HTML file, and step 2 was a
    -CGI script. Frequently, a better strategy is to have a single
    -servlet handle both steps. That way, the servlet has better control
    -over the entire situation, and if the user submits unacceptable
    -data, the servlet can redisplay the form with a "try again" error
    -message at the top and and all the previous input filled in. The
    -servlet can use the presence or absence of certain CGI parameters
    -(e.g., the submit button, or a hidden mode field) to determine
    -which step to take.
    -
    -One neat way to build a servlet that can handle both the form
    -displaying and form processing is like this:
    -
    -
    -#. Put your form HTML into an ordinary template-servlet. In each
    -   input field, use a placeholder for the value of the {VALUE=}
    -   attribue. Place another placeholder next to each field, for that
    -   field's error message.
    -
    -#. Above the form, put a {$processFormData} method call.
    -
    -#. Define that method in a Python class your template {#extend}s.
    -   (Or if it's a simple method, you can define it in a {#def}.) The
    -   method should:
    -
    -
    -   #. Get the form input if any.
    -
    -   #. If the input variable corresponding to the submit field is
    -      empty, there is no form input, so we're showing the form for the
    -      first time. Initialize all VALUE= variables to their default value
    -      (usually ""), and all error variables to "". Return "", which will
    -      be the value for {$processFormData}.
    -
    -   #. If the submit variable is not empty, fill the VALUE= variables
    -      with the input data the user just submitted.
    -
    -   #. Now check the input for errors and put error messages in the
    -      error placeholders.
    -
    -   #. If there were any user errors, return a general error message
    -      string; this will be the value for {$processFormData}.
    -
    -   #. If there were no errors, do whatever the form's job is (e.g.,
    -      update a database) and return a success message; this will be the
    -      value for {$processFormData}.
    -
    -
    -#. The top of the page will show your success/failure message (or
    -   nothing the first time around), with the form below. If there are
    -   errors, the user will have a chance to correct them. After a
    -   successful submit, the form will appear again, so the user can
    -   either review their entry, or change it and submit it again.
    -   Depending on the application, this may make the servlet update the
    -   same database record again, or it may generate a new record.
    -
    -
    -{FunFormKit} is a third-party Webware package that makes it easier
    -to produce forms and handle their logic. It has been successfully
    -been used with Cheetah. You can download FunFormKit from
    -http://colorstudy.net/software/funformkit/ and try it out for
    -yourself.
    -
    -Form input, cookies, session variables and web server variables
    ----------------------------------------------------------------
    -
    -(webware.input)
    -
    -General variable tips that also apply to servlets are in section
    -tips.placeholder.
    -
    -To look up a CGI GET or POST parameter (with POST overriding):
    -
    -::
    -
    -    $request.field('myField')
    -    self.request().field('myField')
    -
    -These will fail if Webware is not available, because {$request}
    -(aka {self.request()} will be {None} rather than a Webware
    -{WebKit.Request} object. If you plan to read a lot of CGI
    -parameters, you may want to put the {.fields} method into a local
    -variable for convenience:
    -
    -::
    -
    -    #set $fields = $request.fields
    -    $fields.myField
    -
    -But remember to do complicated calculations in Python, and assign
    -the results to simple variables in the searchList for display.
    -These {$request} forms are useful only for occasions where you just
    -need one or two simple request items that going to Python for would
    -be overkill.
    -
    -To get a cookie or session parameter, subsitute "cookie" or
    -"session" for "field" above. To get a dictionary of all CGI
    -parameters, substitute "fields" (ditto for "cookies"). To verify a
    -field exists, substitute "hasField" (ditto for "hasCookie").
    -
    -Other useful request goodies:
    -
    -::
    -
    -    ## Defined in WebKit.Request
    -    $request.field('myField', 'default value')
    -    $request.time              ## Time this request began in Unix ticks.
    -    $request.timeStamp         ## Time in human-readable format ('asctime' format).
    -    ## Defined in WebKit.HTTPRequest
    -    $request.hasField.myField  ## Is a CGI parameter defined?
    -    $request.fields            ## Dictionary of all CGI parameters.
    -    $request.cookie.myCookie   ## A cookie parameter (also .hasCookie, .cookies).
    -    $request.value.myValue     ## A field or cookie variable (field overrides)
    -                               ## (also .hasValue).
    -    $request.session.mySessionVar  # A session variable.
    -    $request.extraURLPath      ## URL path components to right of servlet, if any.
    -    $request.serverDictionary  ## Dict of environmental vars from web server.
    -    $request.remoteUser        ## Authenticated username.  HTTPRequest.py source
    -                               ## suggests this is broken and always returns None.
    -    $request.remoteAddress  ## User's IP address (string).
    -    $request.remoteName     ## User's domain name, or IP address if none.
    -    $request.urlPath        ## URI of this servlet.
    -    $request.urlPathDir     ## URI of the directory containing this servlet.
    -    $request.serverSidePath ## Absolute path of this servlet on local filesystem.
    -    $request.serverURL      ## URL of this servlet, without "http://" prefix,
    -                            ## extra path info or query string.
    -    $request.serverURLDir   ## URL of this servlet's directory, without "http://".
    -    $log("message")         ## Put a message in the Webware server log.  (If you
    -                            ## define your own 'log' variable, it will override
    -                            ## this; use $self.log("message") in that case.
    -
    -.webInput()
    -~~~~~~~~~~~
    -
    -(webware.webInput)
    -
    -From the method docstring:
    -
    -::
    -
    -        def webInput(self, names, namesMulti=(), default='', src='f',
    -            defaultInt=0, defaultFloat=0.00, badInt=0, badFloat=0.00, debug=False):
    -
    -    This method places the specified GET/POST fields, cookies or session variables
    -    into a dictionary, which is both returned and put at the beginning of the
    -    searchList.  It handles:
    -        * single vs multiple values
    -        * conversion to integer or float for specified names
    -        * default values/exceptions for missing or bad values
    -        * printing a snapshot of all values retrieved for debugging
    -    All the 'default*' and 'bad*' arguments have "use or raise" behavior, meaning
    -    that if they're a subclass of Exception, they're raised.  If they're anything
    -    else, that value is substituted for the missing/bad value.
    -
    -    The simplest usage is:
    -
    -        #silent $webInput(['choice'])
    -        $choice
    -
    -        dic = self.webInput(['choice'])
    -        write(dic['choice'])
    -
    -    Both these examples retrieves the GET/POST field 'choice' and print it.  If you
    -    leave off the "#silent", all the values would be printed too.  But a better way
    -    to preview the values is
    -
    -        #silent $webInput(['name'], $debug=1)
    -
    -    because this pretty-prints all the values inside HTML 
     tags.
    -
    -    Since we didn't specify any coversions, the value is a string.  It's a "single"
    -    value because we specified it in 'names' rather than 'namesMulti'.  Single
    -    values work like this:
    -        * If one value is found, take it.
    -        * If several values are found, choose one arbitrarily and ignore the rest.
    -        * If no values are found, use or raise the appropriate 'default*' value.
    -
    -    Multi values work like this:
    -        * If one value is found, put it in a list.
    -        * If several values are found, leave them in a list.
    -        * If no values are found, use the empty list ([]).  The 'default*'
    -          arguments are *not* consulted in this case.
    -
    -    Example: assume 'days' came from a set of checkboxes or a multiple combo box
    -    on a form, and the user chose "Monday", "Tuesday" and "Thursday".
    -
    -        #silent $webInput([], ['days'])
    -        The days you chose are: #slurp
    -        #for $day in $days
    -        $day #slurp
    -        #end for
    -
    -        dic = self.webInput([], ['days'])
    -        write("The days you chose are: ")
    -        for day in dic['days']:
    -            write(day + " ")
    -
    -    Both these examples print:  "The days you chose are: Monday Tuesday Thursday".
    -
    -    By default, missing strings are replaced by "" and missing/bad numbers by zero.
    -    (A "bad number" means the converter raised an exception for it, usually because
    -    of non-numeric characters in the value.)  This mimics Perl/PHP behavior, and
    -    simplifies coding for many applications where missing/bad values *should* be
    -    blank/zero.  In those relatively few cases where you must distinguish between
    -    ""/zero on the one hand and missing/bad on the other, change the appropriate
    -    'default*' and 'bad*' arguments to something like:
    -        * None
    -        * another constant value
    -        * $NonNumericInputError/self.NonNumericInputError
    -        * $ValueError/ValueError
    -    (NonNumericInputError is defined in this class and is useful for
    -    distinguishing between bad input vs a TypeError/ValueError
    -    thrown for some other reason.)
    -
    -    Here's an example using multiple values to schedule newspaper deliveries.
    -    'checkboxes' comes from a form with checkboxes for all the days of the week.
    -    The days the user previously chose are preselected.  The user checks/unchecks
    -    boxes as desired and presses Submit.  The value of 'checkboxes' is a list of
    -    checkboxes that were checked when Submit was pressed.  Our task now is to
    -    turn on the days the user checked, turn off the days he unchecked, and leave
    -    on or off the days he didn't change.
    -
    -        dic = self.webInput([], ['dayCheckboxes'])
    -        wantedDays = dic['dayCheckboxes'] # The days the user checked.
    -        for day, on in self.getAllValues():
    -            if   not on and day in wantedDays:
    -                self.TurnOn(day)
    -                # ... Set a flag or insert a database record ...
    -            elif on and day not in wantedDays:
    -                self.TurnOff(day)
    -                # ... Unset a flag or delete a database record ...
    -
    -    'source' allows you to look up the variables from a number of different
    -    sources:
    -        'f'   fields (CGI GET/POST parameters)
    -        'c'   cookies
    -        's'   session variables
    -        'v'   "values", meaning fields or cookies
    -
    -    In many forms, you're dealing only with strings, which is why the
    -    'default' argument is third and the numeric arguments are banished to
    -    the end.  But sometimes you want automatic number conversion, so that
    -    you can do numeric comparisons in your templates without having to
    -    write a bunch of conversion/exception handling code.  Example:
    -
    -        #silent $webInput(['name', 'height:int'])
    -        $name is $height cm tall.
    -        #if $height >= 300
    -        Wow, you're tall!
    -        #else
    -        Pshaw, you're short.
    -        #end if
    -
    -        dic = self.webInput(['name', 'height:int'])
    -        name = dic[name]
    -        height = dic[height]
    -        write("%s is %s cm tall." % (name, height))
    -        if height > 300:
    -            write("Wow, you're tall!")
    -        else:
    -            write("Pshaw, you're short.")
    -
    -    To convert a value to a number, suffix ":int" or ":float" to the name.  The
    -    method will search first for a "height:int" variable and then for a "height"
    -    variable.  (It will be called "height" in the final dictionary.)  If a numeric
    -    conversion fails, use or raise 'badInt' or 'badFloat'.  Missing values work
    -    the same way as for strings, except the default is 'defaultInt' or
    -    'defaultFloat' instead of 'default'.
    -
    -    If a name represents an uploaded file, the entire file will be read into
    -    memory.  For more sophisticated file-upload handling, leave that name out of
    -    the list and do your own handling, or wait for Cheetah.Utils.UploadFileMixin.
    -
    -    This mixin class works only in a subclass that also inherits from
    -    Webware's Servlet or HTTPServlet.  Otherwise you'll get an AttributeError
    -    on 'self.request'.
    -
    -    EXCEPTIONS: ValueError if 'source' is not one of the stated characters.
    -    TypeError if a conversion suffix is not ":int" or ":float".
    -
    -More examples
    --------------
    -
    -(webware.examples)
    -
    -Example A - a standalone servlet
    -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    -
    -Example B - a servlet under a site framework
    -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    -
    -Example C - several servlets with a common template
    -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    -
    -Other Tips
    -----------
    -
    -(webware.otherTips)
    -
    -If your servlet accesses external files (e.g., via an {#include}
    -directive), remember that the current directory is not necessarily
    -directory the servlet is in. It's probably some other directory
    -WebKit chose. To find a file relative to the servlet's directory,
    -prefix the path with whatever {self.serverSidePath()} returns (from
    -{Servlet.serverSidePath()}.
    -
    -If you don't understand how {#extends} and {#implements} work, and
    -about a template's main method, read the chapter on inheritance
    -(sections inheritanceEtc.extends and inheritanceEtc.implements).
    -This may help you avoid buggy servlets.
    -
    -
    diff --git a/docs/html/_static/ajax-loader.gif b/docs/html/_static/ajax-loader.gif
    deleted file mode 100644
    index 61faf8c..0000000
    Binary files a/docs/html/_static/ajax-loader.gif and /dev/null differ
    diff --git a/docs/html/_static/basic.css b/docs/html/_static/basic.css
    deleted file mode 100644
    index 3c7223b..0000000
    --- a/docs/html/_static/basic.css
    +++ /dev/null
    @@ -1,643 +0,0 @@
    -/*
    - * basic.css
    - * ~~~~~~~~~
    - *
    - * Sphinx stylesheet -- basic theme.
    - *
    - * :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
    - * :license: BSD, see LICENSE for details.
    - *
    - */
    -
    -/* -- main layout ----------------------------------------------------------- */
    -
    -div.clearer {
    -    clear: both;
    -}
    -
    -/* -- relbar ---------------------------------------------------------------- */
    -
    -div.related {
    -    width: 100%;
    -    font-size: 90%;
    -}
    -
    -div.related h3 {
    -    display: none;
    -}
    -
    -div.related ul {
    -    margin: 0;
    -    padding: 0 0 0 10px;
    -    list-style: none;
    -}
    -
    -div.related li {
    -    display: inline;
    -}
    -
    -div.related li.right {
    -    float: right;
    -    margin-right: 5px;
    -}
    -
    -/* -- sidebar --------------------------------------------------------------- */
    -
    -div.sphinxsidebarwrapper {
    -    padding: 10px 5px 0 10px;
    -}
    -
    -div.sphinxsidebar {
    -    float: left;
    -    width: 230px;
    -    margin-left: -100%;
    -    font-size: 90%;
    -    word-wrap: break-word;
    -    overflow-wrap : break-word;
    -}
    -
    -div.sphinxsidebar ul {
    -    list-style: none;
    -}
    -
    -div.sphinxsidebar ul ul,
    -div.sphinxsidebar ul.want-points {
    -    margin-left: 20px;
    -    list-style: square;
    -}
    -
    -div.sphinxsidebar ul ul {
    -    margin-top: 0;
    -    margin-bottom: 0;
    -}
    -
    -div.sphinxsidebar form {
    -    margin-top: 10px;
    -}
    -
    -div.sphinxsidebar input {
    -    border: 1px solid #98dbcc;
    -    font-family: sans-serif;
    -    font-size: 1em;
    -}
    -
    -div.sphinxsidebar #searchbox input[type="text"] {
    -    width: 170px;
    -}
    -
    -img {
    -    border: 0;
    -    max-width: 100%;
    -}
    -
    -/* -- search page ----------------------------------------------------------- */
    -
    -ul.search {
    -    margin: 10px 0 0 20px;
    -    padding: 0;
    -}
    -
    -ul.search li {
    -    padding: 5px 0 5px 20px;
    -    background-image: url(file.png);
    -    background-repeat: no-repeat;
    -    background-position: 0 7px;
    -}
    -
    -ul.search li a {
    -    font-weight: bold;
    -}
    -
    -ul.search li div.context {
    -    color: #888;
    -    margin: 2px 0 0 30px;
    -    text-align: left;
    -}
    -
    -ul.keywordmatches li.goodmatch a {
    -    font-weight: bold;
    -}
    -
    -/* -- index page ------------------------------------------------------------ */
    -
    -table.contentstable {
    -    width: 90%;
    -    margin-left: auto;
    -    margin-right: auto;
    -}
    -
    -table.contentstable p.biglink {
    -    line-height: 150%;
    -}
    -
    -a.biglink {
    -    font-size: 1.3em;
    -}
    -
    -span.linkdescr {
    -    font-style: italic;
    -    padding-top: 5px;
    -    font-size: 90%;
    -}
    -
    -/* -- general index --------------------------------------------------------- */
    -
    -table.indextable {
    -    width: 100%;
    -}
    -
    -table.indextable td {
    -    text-align: left;
    -    vertical-align: top;
    -}
    -
    -table.indextable ul {
    -    margin-top: 0;
    -    margin-bottom: 0;
    -    list-style-type: none;
    -}
    -
    -table.indextable > tbody > tr > td > ul {
    -    padding-left: 0em;
    -}
    -
    -table.indextable tr.pcap {
    -    height: 10px;
    -}
    -
    -table.indextable tr.cap {
    -    margin-top: 10px;
    -    background-color: #f2f2f2;
    -}
    -
    -img.toggler {
    -    margin-right: 3px;
    -    margin-top: 3px;
    -    cursor: pointer;
    -}
    -
    -div.modindex-jumpbox {
    -    border-top: 1px solid #ddd;
    -    border-bottom: 1px solid #ddd;
    -    margin: 1em 0 1em 0;
    -    padding: 0.4em;
    -}
    -
    -div.genindex-jumpbox {
    -    border-top: 1px solid #ddd;
    -    border-bottom: 1px solid #ddd;
    -    margin: 1em 0 1em 0;
    -    padding: 0.4em;
    -}
    -
    -/* -- domain module index --------------------------------------------------- */
    -
    -table.modindextable td {
    -    padding: 2px;
    -    border-collapse: collapse;
    -}
    -
    -/* -- general body styles --------------------------------------------------- */
    -
    -div.body p, div.body dd, div.body li, div.body blockquote {
    -    -moz-hyphens: auto;
    -    -ms-hyphens: auto;
    -    -webkit-hyphens: auto;
    -    hyphens: auto;
    -}
    -
    -a.headerlink {
    -    visibility: hidden;
    -}
    -
    -h1:hover > a.headerlink,
    -h2:hover > a.headerlink,
    -h3:hover > a.headerlink,
    -h4:hover > a.headerlink,
    -h5:hover > a.headerlink,
    -h6:hover > a.headerlink,
    -dt:hover > a.headerlink,
    -caption:hover > a.headerlink,
    -p.caption:hover > a.headerlink,
    -div.code-block-caption:hover > a.headerlink {
    -    visibility: visible;
    -}
    -
    -div.body p.caption {
    -    text-align: inherit;
    -}
    -
    -div.body td {
    -    text-align: left;
    -}
    -
    -.first {
    -    margin-top: 0 !important;
    -}
    -
    -p.rubric {
    -    margin-top: 30px;
    -    font-weight: bold;
    -}
    -
    -img.align-left, .figure.align-left, object.align-left {
    -    clear: left;
    -    float: left;
    -    margin-right: 1em;
    -}
    -
    -img.align-right, .figure.align-right, object.align-right {
    -    clear: right;
    -    float: right;
    -    margin-left: 1em;
    -}
    -
    -img.align-center, .figure.align-center, object.align-center {
    -  display: block;
    -  margin-left: auto;
    -  margin-right: auto;
    -}
    -
    -.align-left {
    -    text-align: left;
    -}
    -
    -.align-center {
    -    text-align: center;
    -}
    -
    -.align-right {
    -    text-align: right;
    -}
    -
    -/* -- sidebars -------------------------------------------------------------- */
    -
    -div.sidebar {
    -    margin: 0 0 0.5em 1em;
    -    border: 1px solid #ddb;
    -    padding: 7px 7px 0 7px;
    -    background-color: #ffe;
    -    width: 40%;
    -    float: right;
    -}
    -
    -p.sidebar-title {
    -    font-weight: bold;
    -}
    -
    -/* -- topics ---------------------------------------------------------------- */
    -
    -div.topic {
    -    border: 1px solid #ccc;
    -    padding: 7px 7px 0 7px;
    -    margin: 10px 0 10px 0;
    -}
    -
    -p.topic-title {
    -    font-size: 1.1em;
    -    font-weight: bold;
    -    margin-top: 10px;
    -}
    -
    -/* -- admonitions ----------------------------------------------------------- */
    -
    -div.admonition {
    -    margin-top: 10px;
    -    margin-bottom: 10px;
    -    padding: 7px;
    -}
    -
    -div.admonition dt {
    -    font-weight: bold;
    -}
    -
    -div.admonition dl {
    -    margin-bottom: 0;
    -}
    -
    -p.admonition-title {
    -    margin: 0px 10px 5px 0px;
    -    font-weight: bold;
    -}
    -
    -div.body p.centered {
    -    text-align: center;
    -    margin-top: 25px;
    -}
    -
    -/* -- tables ---------------------------------------------------------------- */
    -
    -table.docutils {
    -    border: 0;
    -    border-collapse: collapse;
    -}
    -
    -table caption span.caption-number {
    -    font-style: italic;
    -}
    -
    -table caption span.caption-text {
    -}
    -
    -table.docutils td, table.docutils th {
    -    padding: 1px 8px 1px 5px;
    -    border-top: 0;
    -    border-left: 0;
    -    border-right: 0;
    -    border-bottom: 1px solid #aaa;
    -}
    -
    -table.footnote td, table.footnote th {
    -    border: 0 !important;
    -}
    -
    -th {
    -    text-align: left;
    -    padding-right: 5px;
    -}
    -
    -table.citation {
    -    border-left: solid 1px gray;
    -    margin-left: 1px;
    -}
    -
    -table.citation td {
    -    border-bottom: none;
    -}
    -
    -/* -- figures --------------------------------------------------------------- */
    -
    -div.figure {
    -    margin: 0.5em;
    -    padding: 0.5em;
    -}
    -
    -div.figure p.caption {
    -    padding: 0.3em;
    -}
    -
    -div.figure p.caption span.caption-number {
    -    font-style: italic;
    -}
    -
    -div.figure p.caption span.caption-text {
    -}
    -
    -/* -- field list styles ----------------------------------------------------- */
    -
    -table.field-list td, table.field-list th {
    -    border: 0 !important;
    -}
    -
    -.field-list ul {
    -    margin: 0;
    -    padding-left: 1em;
    -}
    -
    -.field-list p {
    -    margin: 0;
    -}
    -
    -.field-name {
    -    -moz-hyphens: manual;
    -    -ms-hyphens: manual;
    -    -webkit-hyphens: manual;
    -    hyphens: manual;
    -}
    -
    -/* -- other body styles ----------------------------------------------------- */
    -
    -ol.arabic {
    -    list-style: decimal;
    -}
    -
    -ol.loweralpha {
    -    list-style: lower-alpha;
    -}
    -
    -ol.upperalpha {
    -    list-style: upper-alpha;
    -}
    -
    -ol.lowerroman {
    -    list-style: lower-roman;
    -}
    -
    -ol.upperroman {
    -    list-style: upper-roman;
    -}
    -
    -dl {
    -    margin-bottom: 15px;
    -}
    -
    -dd p {
    -    margin-top: 0px;
    -}
    -
    -dd ul, dd table {
    -    margin-bottom: 10px;
    -}
    -
    -dd {
    -    margin-top: 3px;
    -    margin-bottom: 10px;
    -    margin-left: 30px;
    -}
    -
    -dt:target, span.highlighted {
    -    background-color: #fbe54e;
    -}
    -
    -rect.highlighted {
    -    fill: #fbe54e;
    -}
    -
    -dl.glossary dt {
    -    font-weight: bold;
    -    font-size: 1.1em;
    -}
    -
    -.optional {
    -    font-size: 1.3em;
    -}
    -
    -.sig-paren {
    -    font-size: larger;
    -}
    -
    -.versionmodified {
    -    font-style: italic;
    -}
    -
    -.system-message {
    -    background-color: #fda;
    -    padding: 5px;
    -    border: 3px solid red;
    -}
    -
    -.footnote:target  {
    -    background-color: #ffa;
    -}
    -
    -.line-block {
    -    display: block;
    -    margin-top: 1em;
    -    margin-bottom: 1em;
    -}
    -
    -.line-block .line-block {
    -    margin-top: 0;
    -    margin-bottom: 0;
    -    margin-left: 1.5em;
    -}
    -
    -.guilabel, .menuselection {
    -    font-family: sans-serif;
    -}
    -
    -.accelerator {
    -    text-decoration: underline;
    -}
    -
    -.classifier {
    -    font-style: oblique;
    -}
    -
    -abbr, acronym {
    -    border-bottom: dotted 1px;
    -    cursor: help;
    -}
    -
    -/* -- code displays --------------------------------------------------------- */
    -
    -pre {
    -    overflow: auto;
    -    overflow-y: hidden;  /* fixes display issues on Chrome browsers */
    -}
    -
    -span.pre {
    -    -moz-hyphens: none;
    -    -ms-hyphens: none;
    -    -webkit-hyphens: none;
    -    hyphens: none;
    -}
    -
    -td.linenos pre {
    -    padding: 5px 0px;
    -    border: 0;
    -    background-color: transparent;
    -    color: #aaa;
    -}
    -
    -table.highlighttable {
    -    margin-left: 0.5em;
    -}
    -
    -table.highlighttable td {
    -    padding: 0 0.5em 0 0.5em;
    -}
    -
    -div.code-block-caption {
    -    padding: 2px 5px;
    -    font-size: small;
    -}
    -
    -div.code-block-caption code {
    -    background-color: transparent;
    -}
    -
    -div.code-block-caption + div > div.highlight > pre {
    -    margin-top: 0;
    -}
    -
    -div.code-block-caption span.caption-number {
    -    padding: 0.1em 0.3em;
    -    font-style: italic;
    -}
    -
    -div.code-block-caption span.caption-text {
    -}
    -
    -div.literal-block-wrapper {
    -    padding: 1em 1em 0;
    -}
    -
    -div.literal-block-wrapper div.highlight {
    -    margin: 0;
    -}
    -
    -code.descname {
    -    background-color: transparent;
    -    font-weight: bold;
    -    font-size: 1.2em;
    -}
    -
    -code.descclassname {
    -    background-color: transparent;
    -}
    -
    -code.xref, a code {
    -    background-color: transparent;
    -    font-weight: bold;
    -}
    -
    -h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
    -    background-color: transparent;
    -}
    -
    -.viewcode-link {
    -    float: right;
    -}
    -
    -.viewcode-back {
    -    float: right;
    -    font-family: sans-serif;
    -}
    -
    -div.viewcode-block:target {
    -    margin: -1px -10px;
    -    padding: 0 10px;
    -}
    -
    -/* -- math display ---------------------------------------------------------- */
    -
    -img.math {
    -    vertical-align: middle;
    -}
    -
    -div.body div.math p {
    -    text-align: center;
    -}
    -
    -span.eqno {
    -    float: right;
    -}
    -
    -span.eqno a.headerlink {
    -    position: relative;
    -    left: 0px;
    -    z-index: 1;
    -}
    -
    -div.math:hover a.headerlink {
    -    visibility: visible;
    -}
    -
    -/* -- printout stylesheet --------------------------------------------------- */
    -
    -@media print {
    -    div.document,
    -    div.documentwrapper,
    -    div.bodywrapper {
    -        margin: 0 !important;
    -        width: 100%;
    -    }
    -
    -    div.sphinxsidebar,
    -    div.related,
    -    div.footer,
    -    #top-link {
    -        display: none;
    -    }
    -}
    \ No newline at end of file
    diff --git a/docs/html/_static/comment-bright.png b/docs/html/_static/comment-bright.png
    deleted file mode 100644
    index 15e27ed..0000000
    Binary files a/docs/html/_static/comment-bright.png and /dev/null differ
    diff --git a/docs/html/_static/comment-close.png b/docs/html/_static/comment-close.png
    deleted file mode 100644
    index 4d91bcf..0000000
    Binary files a/docs/html/_static/comment-close.png and /dev/null differ
    diff --git a/docs/html/_static/comment.png b/docs/html/_static/comment.png
    deleted file mode 100644
    index dfbc0cb..0000000
    Binary files a/docs/html/_static/comment.png and /dev/null differ
    diff --git a/docs/html/_static/contents.png b/docs/html/_static/contents.png
    deleted file mode 100644
    index 6c59aa1..0000000
    Binary files a/docs/html/_static/contents.png and /dev/null differ
    diff --git a/docs/html/_static/doctools.js b/docs/html/_static/doctools.js
    deleted file mode 100644
    index 24992e6..0000000
    --- a/docs/html/_static/doctools.js
    +++ /dev/null
    @@ -1,311 +0,0 @@
    -/*
    - * doctools.js
    - * ~~~~~~~~~~~
    - *
    - * Sphinx JavaScript utilities for all documentation.
    - *
    - * :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
    - * :license: BSD, see LICENSE for details.
    - *
    - */
    -
    -/**
    - * select a different prefix for underscore
    - */
    -$u = _.noConflict();
    -
    -/**
    - * make the code below compatible with browsers without
    - * an installed firebug like debugger
    -if (!window.console || !console.firebug) {
    -  var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
    -    "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace",
    -    "profile", "profileEnd"];
    -  window.console = {};
    -  for (var i = 0; i < names.length; ++i)
    -    window.console[names[i]] = function() {};
    -}
    - */
    -
    -/**
    - * small helper function to urldecode strings
    - */
    -jQuery.urldecode = function(x) {
    -  return decodeURIComponent(x).replace(/\+/g, ' ');
    -};
    -
    -/**
    - * small helper function to urlencode strings
    - */
    -jQuery.urlencode = encodeURIComponent;
    -
    -/**
    - * This function returns the parsed url parameters of the
    - * current request. Multiple values per key are supported,
    - * it will always return arrays of strings for the value parts.
    - */
    -jQuery.getQueryParameters = function(s) {
    -  if (typeof s === 'undefined')
    -    s = document.location.search;
    -  var parts = s.substr(s.indexOf('?') + 1).split('&');
    -  var result = {};
    -  for (var i = 0; i < parts.length; i++) {
    -    var tmp = parts[i].split('=', 2);
    -    var key = jQuery.urldecode(tmp[0]);
    -    var value = jQuery.urldecode(tmp[1]);
    -    if (key in result)
    -      result[key].push(value);
    -    else
    -      result[key] = [value];
    -  }
    -  return result;
    -};
    -
    -/**
    - * highlight a given string on a jquery object by wrapping it in
    - * span elements with the given class name.
    - */
    -jQuery.fn.highlightText = function(text, className) {
    -  function highlight(node, addItems) {
    -    if (node.nodeType === 3) {
    -      var val = node.nodeValue;
    -      var pos = val.toLowerCase().indexOf(text);
    -      if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) {
    -        var span;
    -        var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg");
    -        if (isInSVG) {
    -          span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
    -        } else {
    -          span = document.createElement("span");
    -          span.className = className;
    -        }
    -        span.appendChild(document.createTextNode(val.substr(pos, text.length)));
    -        node.parentNode.insertBefore(span, node.parentNode.insertBefore(
    -          document.createTextNode(val.substr(pos + text.length)),
    -          node.nextSibling));
    -        node.nodeValue = val.substr(0, pos);
    -        if (isInSVG) {
    -          var bbox = span.getBBox();
    -          var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
    -       	  rect.x.baseVal.value = bbox.x;
    -          rect.y.baseVal.value = bbox.y;
    -          rect.width.baseVal.value = bbox.width;
    -          rect.height.baseVal.value = bbox.height;
    -          rect.setAttribute('class', className);
    -          var parentOfText = node.parentNode.parentNode;
    -          addItems.push({
    -              "parent": node.parentNode,
    -              "target": rect});
    -        }
    -      }
    -    }
    -    else if (!jQuery(node).is("button, select, textarea")) {
    -      jQuery.each(node.childNodes, function() {
    -        highlight(this, addItems);
    -      });
    -    }
    -  }
    -  var addItems = [];
    -  var result = this.each(function() {
    -    highlight(this, addItems);
    -  });
    -  for (var i = 0; i < addItems.length; ++i) {
    -    jQuery(addItems[i].parent).before(addItems[i].target);
    -  }
    -  return result;
    -};
    -
    -/*
    - * backward compatibility for jQuery.browser
    - * This will be supported until firefox bug is fixed.
    - */
    -if (!jQuery.browser) {
    -  jQuery.uaMatch = function(ua) {
    -    ua = ua.toLowerCase();
    -
    -    var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
    -      /(webkit)[ \/]([\w.]+)/.exec(ua) ||
    -      /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
    -      /(msie) ([\w.]+)/.exec(ua) ||
    -      ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
    -      [];
    -
    -    return {
    -      browser: match[ 1 ] || "",
    -      version: match[ 2 ] || "0"
    -    };
    -  };
    -  jQuery.browser = {};
    -  jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
    -}
    -
    -/**
    - * Small JavaScript module for the documentation.
    - */
    -var Documentation = {
    -
    -  init : function() {
    -    this.fixFirefoxAnchorBug();
    -    this.highlightSearchWords();
    -    this.initIndexTable();
    -    
    -  },
    -
    -  /**
    -   * i18n support
    -   */
    -  TRANSLATIONS : {},
    -  PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; },
    -  LOCALE : 'unknown',
    -
    -  // gettext and ngettext don't access this so that the functions
    -  // can safely bound to a different name (_ = Documentation.gettext)
    -  gettext : function(string) {
    -    var translated = Documentation.TRANSLATIONS[string];
    -    if (typeof translated === 'undefined')
    -      return string;
    -    return (typeof translated === 'string') ? translated : translated[0];
    -  },
    -
    -  ngettext : function(singular, plural, n) {
    -    var translated = Documentation.TRANSLATIONS[singular];
    -    if (typeof translated === 'undefined')
    -      return (n == 1) ? singular : plural;
    -    return translated[Documentation.PLURALEXPR(n)];
    -  },
    -
    -  addTranslations : function(catalog) {
    -    for (var key in catalog.messages)
    -      this.TRANSLATIONS[key] = catalog.messages[key];
    -    this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
    -    this.LOCALE = catalog.locale;
    -  },
    -
    -  /**
    -   * add context elements like header anchor links
    -   */
    -  addContextElements : function() {
    -    $('div[id] > :header:first').each(function() {
    -      $('\u00B6').
    -      attr('href', '#' + this.id).
    -      attr('title', _('Permalink to this headline')).
    -      appendTo(this);
    -    });
    -    $('dt[id]').each(function() {
    -      $('\u00B6').
    -      attr('href', '#' + this.id).
    -      attr('title', _('Permalink to this definition')).
    -      appendTo(this);
    -    });
    -  },
    -
    -  /**
    -   * workaround a firefox stupidity
    -   * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075
    -   */
    -  fixFirefoxAnchorBug : function() {
    -    if (document.location.hash)
    -      window.setTimeout(function() {
    -        document.location.href += '';
    -      }, 10);
    -  },
    -
    -  /**
    -   * highlight the search words provided in the url in the text
    -   */
    -  highlightSearchWords : function() {
    -    var params = $.getQueryParameters();
    -    var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
    -    if (terms.length) {
    -      var body = $('div.body');
    -      if (!body.length) {
    -        body = $('body');
    -      }
    -      window.setTimeout(function() {
    -        $.each(terms, function() {
    -          body.highlightText(this.toLowerCase(), 'highlighted');
    -        });
    -      }, 10);
    -      $('')
    -          .appendTo($('#searchbox'));
    -    }
    -  },
    -
    -  /**
    -   * init the domain index toggle buttons
    -   */
    -  initIndexTable : function() {
    -    var togglers = $('img.toggler').click(function() {
    -      var src = $(this).attr('src');
    -      var idnum = $(this).attr('id').substr(7);
    -      $('tr.cg-' + idnum).toggle();
    -      if (src.substr(-9) === 'minus.png')
    -        $(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
    -      else
    -        $(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
    -    }).css('display', '');
    -    if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) {
    -        togglers.click();
    -    }
    -  },
    -
    -  /**
    -   * helper function to hide the search marks again
    -   */
    -  hideSearchWords : function() {
    -    $('#searchbox .highlight-link').fadeOut(300);
    -    $('span.highlighted').removeClass('highlighted');
    -  },
    -
    -  /**
    -   * make the url absolute
    -   */
    -  makeURL : function(relativeURL) {
    -    return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL;
    -  },
    -
    -  /**
    -   * get the current relative url
    -   */
    -  getCurrentURL : function() {
    -    var path = document.location.pathname;
    -    var parts = path.split(/\//);
    -    $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
    -      if (this === '..')
    -        parts.pop();
    -    });
    -    var url = parts.join('/');
    -    return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
    -  },
    -
    -  initOnKeyListeners: function() {
    -    $(document).keyup(function(event) {
    -      var activeElementType = document.activeElement.tagName;
    -      // don't navigate when in search box or textarea
    -      if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT') {
    -        switch (event.keyCode) {
    -          case 37: // left
    -            var prevHref = $('link[rel="prev"]').prop('href');
    -            if (prevHref) {
    -              window.location.href = prevHref;
    -              return false;
    -            }
    -          case 39: // right
    -            var nextHref = $('link[rel="next"]').prop('href');
    -            if (nextHref) {
    -              window.location.href = nextHref;
    -              return false;
    -            }
    -        }
    -      }
    -    });
    -  }
    -};
    -
    -// quick alias for translations
    -_ = Documentation.gettext;
    -
    -$(document).ready(function() {
    -  Documentation.init();
    -});
    \ No newline at end of file
    diff --git a/docs/html/_static/down-pressed.png b/docs/html/_static/down-pressed.png
    deleted file mode 100644
    index 5756c8c..0000000
    Binary files a/docs/html/_static/down-pressed.png and /dev/null differ
    diff --git a/docs/html/_static/down.png b/docs/html/_static/down.png
    deleted file mode 100644
    index 1b3bdad..0000000
    Binary files a/docs/html/_static/down.png and /dev/null differ
    diff --git a/docs/html/_static/file.png b/docs/html/_static/file.png
    deleted file mode 100644
    index a858a41..0000000
    Binary files a/docs/html/_static/file.png and /dev/null differ
    diff --git a/docs/html/_static/jquery-3.1.0.js b/docs/html/_static/jquery-3.1.0.js
    deleted file mode 100644
    index f2fc274..0000000
    --- a/docs/html/_static/jquery-3.1.0.js
    +++ /dev/null
    @@ -1,10074 +0,0 @@
    -/*eslint-disable no-unused-vars*/
    -/*!
    - * jQuery JavaScript Library v3.1.0
    - * https://jquery.com/
    - *
    - * Includes Sizzle.js
    - * https://sizzlejs.com/
    - *
    - * Copyright jQuery Foundation and other contributors
    - * Released under the MIT license
    - * https://jquery.org/license
    - *
    - * Date: 2016-07-07T21:44Z
    - */
    -( function( global, factory ) {
    -
    -	"use strict";
    -
    -	if ( typeof module === "object" && typeof module.exports === "object" ) {
    -
    -		// For CommonJS and CommonJS-like environments where a proper `window`
    -		// is present, execute the factory and get jQuery.
    -		// For environments that do not have a `window` with a `document`
    -		// (such as Node.js), expose a factory as module.exports.
    -		// This accentuates the need for the creation of a real `window`.
    -		// e.g. var jQuery = require("jquery")(window);
    -		// See ticket #14549 for more info.
    -		module.exports = global.document ?
    -			factory( global, true ) :
    -			function( w ) {
    -				if ( !w.document ) {
    -					throw new Error( "jQuery requires a window with a document" );
    -				}
    -				return factory( w );
    -			};
    -	} else {
    -		factory( global );
    -	}
    -
    -// Pass this if window is not defined yet
    -} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
    -
    -// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1
    -// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode
    -// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common
    -// enough that all such attempts are guarded in a try block.
    -"use strict";
    -
    -var arr = [];
    -
    -var document = window.document;
    -
    -var getProto = Object.getPrototypeOf;
    -
    -var slice = arr.slice;
    -
    -var concat = arr.concat;
    -
    -var push = arr.push;
    -
    -var indexOf = arr.indexOf;
    -
    -var class2type = {};
    -
    -var toString = class2type.toString;
    -
    -var hasOwn = class2type.hasOwnProperty;
    -
    -var fnToString = hasOwn.toString;
    -
    -var ObjectFunctionString = fnToString.call( Object );
    -
    -var support = {};
    -
    -
    -
    -	function DOMEval( code, doc ) {
    -		doc = doc || document;
    -
    -		var script = doc.createElement( "script" );
    -
    -		script.text = code;
    -		doc.head.appendChild( script ).parentNode.removeChild( script );
    -	}
    -/* global Symbol */
    -// Defining this global in .eslintrc would create a danger of using the global
    -// unguarded in another place, it seems safer to define global only for this module
    -
    -
    -
    -var
    -	version = "3.1.0",
    -
    -	// Define a local copy of jQuery
    -	jQuery = function( selector, context ) {
    -
    -		// The jQuery object is actually just the init constructor 'enhanced'
    -		// Need init if jQuery is called (just allow error to be thrown if not included)
    -		return new jQuery.fn.init( selector, context );
    -	},
    -
    -	// Support: Android <=4.0 only
    -	// Make sure we trim BOM and NBSP
    -	rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
    -
    -	// Matches dashed string for camelizing
    -	rmsPrefix = /^-ms-/,
    -	rdashAlpha = /-([a-z])/g,
    -
    -	// Used by jQuery.camelCase as callback to replace()
    -	fcamelCase = function( all, letter ) {
    -		return letter.toUpperCase();
    -	};
    -
    -jQuery.fn = jQuery.prototype = {
    -
    -	// The current version of jQuery being used
    -	jquery: version,
    -
    -	constructor: jQuery,
    -
    -	// The default length of a jQuery object is 0
    -	length: 0,
    -
    -	toArray: function() {
    -		return slice.call( this );
    -	},
    -
    -	// Get the Nth element in the matched element set OR
    -	// Get the whole matched element set as a clean array
    -	get: function( num ) {
    -		return num != null ?
    -
    -			// Return just the one element from the set
    -			( num < 0 ? this[ num + this.length ] : this[ num ] ) :
    -
    -			// Return all the elements in a clean array
    -			slice.call( this );
    -	},
    -
    -	// Take an array of elements and push it onto the stack
    -	// (returning the new matched element set)
    -	pushStack: function( elems ) {
    -
    -		// Build a new jQuery matched element set
    -		var ret = jQuery.merge( this.constructor(), elems );
    -
    -		// Add the old object onto the stack (as a reference)
    -		ret.prevObject = this;
    -
    -		// Return the newly-formed element set
    -		return ret;
    -	},
    -
    -	// Execute a callback for every element in the matched set.
    -	each: function( callback ) {
    -		return jQuery.each( this, callback );
    -	},
    -
    -	map: function( callback ) {
    -		return this.pushStack( jQuery.map( this, function( elem, i ) {
    -			return callback.call( elem, i, elem );
    -		} ) );
    -	},
    -
    -	slice: function() {
    -		return this.pushStack( slice.apply( this, arguments ) );
    -	},
    -
    -	first: function() {
    -		return this.eq( 0 );
    -	},
    -
    -	last: function() {
    -		return this.eq( -1 );
    -	},
    -
    -	eq: function( i ) {
    -		var len = this.length,
    -			j = +i + ( i < 0 ? len : 0 );
    -		return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
    -	},
    -
    -	end: function() {
    -		return this.prevObject || this.constructor();
    -	},
    -
    -	// For internal use only.
    -	// Behaves like an Array's method, not like a jQuery method.
    -	push: push,
    -	sort: arr.sort,
    -	splice: arr.splice
    -};
    -
    -jQuery.extend = jQuery.fn.extend = function() {
    -	var options, name, src, copy, copyIsArray, clone,
    -		target = arguments[ 0 ] || {},
    -		i = 1,
    -		length = arguments.length,
    -		deep = false;
    -
    -	// Handle a deep copy situation
    -	if ( typeof target === "boolean" ) {
    -		deep = target;
    -
    -		// Skip the boolean and the target
    -		target = arguments[ i ] || {};
    -		i++;
    -	}
    -
    -	// Handle case when target is a string or something (possible in deep copy)
    -	if ( typeof target !== "object" && !jQuery.isFunction( target ) ) {
    -		target = {};
    -	}
    -
    -	// Extend jQuery itself if only one argument is passed
    -	if ( i === length ) {
    -		target = this;
    -		i--;
    -	}
    -
    -	for ( ; i < length; i++ ) {
    -
    -		// Only deal with non-null/undefined values
    -		if ( ( options = arguments[ i ] ) != null ) {
    -
    -			// Extend the base object
    -			for ( name in options ) {
    -				src = target[ name ];
    -				copy = options[ name ];
    -
    -				// Prevent never-ending loop
    -				if ( target === copy ) {
    -					continue;
    -				}
    -
    -				// Recurse if we're merging plain objects or arrays
    -				if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
    -					( copyIsArray = jQuery.isArray( copy ) ) ) ) {
    -
    -					if ( copyIsArray ) {
    -						copyIsArray = false;
    -						clone = src && jQuery.isArray( src ) ? src : [];
    -
    -					} else {
    -						clone = src && jQuery.isPlainObject( src ) ? src : {};
    -					}
    -
    -					// Never move original objects, clone them
    -					target[ name ] = jQuery.extend( deep, clone, copy );
    -
    -				// Don't bring in undefined values
    -				} else if ( copy !== undefined ) {
    -					target[ name ] = copy;
    -				}
    -			}
    -		}
    -	}
    -
    -	// Return the modified object
    -	return target;
    -};
    -
    -jQuery.extend( {
    -
    -	// Unique for each copy of jQuery on the page
    -	expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
    -
    -	// Assume jQuery is ready without the ready module
    -	isReady: true,
    -
    -	error: function( msg ) {
    -		throw new Error( msg );
    -	},
    -
    -	noop: function() {},
    -
    -	isFunction: function( obj ) {
    -		return jQuery.type( obj ) === "function";
    -	},
    -
    -	isArray: Array.isArray,
    -
    -	isWindow: function( obj ) {
    -		return obj != null && obj === obj.window;
    -	},
    -
    -	isNumeric: function( obj ) {
    -
    -		// As of jQuery 3.0, isNumeric is limited to
    -		// strings and numbers (primitives or objects)
    -		// that can be coerced to finite numbers (gh-2662)
    -		var type = jQuery.type( obj );
    -		return ( type === "number" || type === "string" ) &&
    -
    -			// parseFloat NaNs numeric-cast false positives ("")
    -			// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
    -			// subtraction forces infinities to NaN
    -			!isNaN( obj - parseFloat( obj ) );
    -	},
    -
    -	isPlainObject: function( obj ) {
    -		var proto, Ctor;
    -
    -		// Detect obvious negatives
    -		// Use toString instead of jQuery.type to catch host objects
    -		if ( !obj || toString.call( obj ) !== "[object Object]" ) {
    -			return false;
    -		}
    -
    -		proto = getProto( obj );
    -
    -		// Objects with no prototype (e.g., `Object.create( null )`) are plain
    -		if ( !proto ) {
    -			return true;
    -		}
    -
    -		// Objects with prototype are plain iff they were constructed by a global Object function
    -		Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor;
    -		return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString;
    -	},
    -
    -	isEmptyObject: function( obj ) {
    -
    -		/* eslint-disable no-unused-vars */
    -		// See https://github.com/eslint/eslint/issues/6125
    -		var name;
    -
    -		for ( name in obj ) {
    -			return false;
    -		}
    -		return true;
    -	},
    -
    -	type: function( obj ) {
    -		if ( obj == null ) {
    -			return obj + "";
    -		}
    -
    -		// Support: Android <=2.3 only (functionish RegExp)
    -		return typeof obj === "object" || typeof obj === "function" ?
    -			class2type[ toString.call( obj ) ] || "object" :
    -			typeof obj;
    -	},
    -
    -	// Evaluates a script in a global context
    -	globalEval: function( code ) {
    -		DOMEval( code );
    -	},
    -
    -	// Convert dashed to camelCase; used by the css and data modules
    -	// Support: IE <=9 - 11, Edge 12 - 13
    -	// Microsoft forgot to hump their vendor prefix (#9572)
    -	camelCase: function( string ) {
    -		return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
    -	},
    -
    -	nodeName: function( elem, name ) {
    -		return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
    -	},
    -
    -	each: function( obj, callback ) {
    -		var length, i = 0;
    -
    -		if ( isArrayLike( obj ) ) {
    -			length = obj.length;
    -			for ( ; i < length; i++ ) {
    -				if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
    -					break;
    -				}
    -			}
    -		} else {
    -			for ( i in obj ) {
    -				if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
    -					break;
    -				}
    -			}
    -		}
    -
    -		return obj;
    -	},
    -
    -	// Support: Android <=4.0 only
    -	trim: function( text ) {
    -		return text == null ?
    -			"" :
    -			( text + "" ).replace( rtrim, "" );
    -	},
    -
    -	// results is for internal usage only
    -	makeArray: function( arr, results ) {
    -		var ret = results || [];
    -
    -		if ( arr != null ) {
    -			if ( isArrayLike( Object( arr ) ) ) {
    -				jQuery.merge( ret,
    -					typeof arr === "string" ?
    -					[ arr ] : arr
    -				);
    -			} else {
    -				push.call( ret, arr );
    -			}
    -		}
    -
    -		return ret;
    -	},
    -
    -	inArray: function( elem, arr, i ) {
    -		return arr == null ? -1 : indexOf.call( arr, elem, i );
    -	},
    -
    -	// Support: Android <=4.0 only, PhantomJS 1 only
    -	// push.apply(_, arraylike) throws on ancient WebKit
    -	merge: function( first, second ) {
    -		var len = +second.length,
    -			j = 0,
    -			i = first.length;
    -
    -		for ( ; j < len; j++ ) {
    -			first[ i++ ] = second[ j ];
    -		}
    -
    -		first.length = i;
    -
    -		return first;
    -	},
    -
    -	grep: function( elems, callback, invert ) {
    -		var callbackInverse,
    -			matches = [],
    -			i = 0,
    -			length = elems.length,
    -			callbackExpect = !invert;
    -
    -		// Go through the array, only saving the items
    -		// that pass the validator function
    -		for ( ; i < length; i++ ) {
    -			callbackInverse = !callback( elems[ i ], i );
    -			if ( callbackInverse !== callbackExpect ) {
    -				matches.push( elems[ i ] );
    -			}
    -		}
    -
    -		return matches;
    -	},
    -
    -	// arg is for internal usage only
    -	map: function( elems, callback, arg ) {
    -		var length, value,
    -			i = 0,
    -			ret = [];
    -
    -		// Go through the array, translating each of the items to their new values
    -		if ( isArrayLike( elems ) ) {
    -			length = elems.length;
    -			for ( ; i < length; i++ ) {
    -				value = callback( elems[ i ], i, arg );
    -
    -				if ( value != null ) {
    -					ret.push( value );
    -				}
    -			}
    -
    -		// Go through every key on the object,
    -		} else {
    -			for ( i in elems ) {
    -				value = callback( elems[ i ], i, arg );
    -
    -				if ( value != null ) {
    -					ret.push( value );
    -				}
    -			}
    -		}
    -
    -		// Flatten any nested arrays
    -		return concat.apply( [], ret );
    -	},
    -
    -	// A global GUID counter for objects
    -	guid: 1,
    -
    -	// Bind a function to a context, optionally partially applying any
    -	// arguments.
    -	proxy: function( fn, context ) {
    -		var tmp, args, proxy;
    -
    -		if ( typeof context === "string" ) {
    -			tmp = fn[ context ];
    -			context = fn;
    -			fn = tmp;
    -		}
    -
    -		// Quick check to determine if target is callable, in the spec
    -		// this throws a TypeError, but we will just return undefined.
    -		if ( !jQuery.isFunction( fn ) ) {
    -			return undefined;
    -		}
    -
    -		// Simulated bind
    -		args = slice.call( arguments, 2 );
    -		proxy = function() {
    -			return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
    -		};
    -
    -		// Set the guid of unique handler to the same of original handler, so it can be removed
    -		proxy.guid = fn.guid = fn.guid || jQuery.guid++;
    -
    -		return proxy;
    -	},
    -
    -	now: Date.now,
    -
    -	// jQuery.support is not used in Core but other projects attach their
    -	// properties to it so it needs to exist.
    -	support: support
    -} );
    -
    -if ( typeof Symbol === "function" ) {
    -	jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];
    -}
    -
    -// Populate the class2type map
    -jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
    -function( i, name ) {
    -	class2type[ "[object " + name + "]" ] = name.toLowerCase();
    -} );
    -
    -function isArrayLike( obj ) {
    -
    -	// Support: real iOS 8.2 only (not reproducible in simulator)
    -	// `in` check used to prevent JIT error (gh-2145)
    -	// hasOwn isn't used here due to false negatives
    -	// regarding Nodelist length in IE
    -	var length = !!obj && "length" in obj && obj.length,
    -		type = jQuery.type( obj );
    -
    -	if ( type === "function" || jQuery.isWindow( obj ) ) {
    -		return false;
    -	}
    -
    -	return type === "array" || length === 0 ||
    -		typeof length === "number" && length > 0 && ( length - 1 ) in obj;
    -}
    -var Sizzle =
    -/*!
    - * Sizzle CSS Selector Engine v2.3.0
    - * https://sizzlejs.com/
    - *
    - * Copyright jQuery Foundation and other contributors
    - * Released under the MIT license
    - * http://jquery.org/license
    - *
    - * Date: 2016-01-04
    - */
    -(function( window ) {
    -
    -var i,
    -	support,
    -	Expr,
    -	getText,
    -	isXML,
    -	tokenize,
    -	compile,
    -	select,
    -	outermostContext,
    -	sortInput,
    -	hasDuplicate,
    -
    -	// Local document vars
    -	setDocument,
    -	document,
    -	docElem,
    -	documentIsHTML,
    -	rbuggyQSA,
    -	rbuggyMatches,
    -	matches,
    -	contains,
    -
    -	// Instance-specific data
    -	expando = "sizzle" + 1 * new Date(),
    -	preferredDoc = window.document,
    -	dirruns = 0,
    -	done = 0,
    -	classCache = createCache(),
    -	tokenCache = createCache(),
    -	compilerCache = createCache(),
    -	sortOrder = function( a, b ) {
    -		if ( a === b ) {
    -			hasDuplicate = true;
    -		}
    -		return 0;
    -	},
    -
    -	// Instance methods
    -	hasOwn = ({}).hasOwnProperty,
    -	arr = [],
    -	pop = arr.pop,
    -	push_native = arr.push,
    -	push = arr.push,
    -	slice = arr.slice,
    -	// Use a stripped-down indexOf as it's faster than native
    -	// https://jsperf.com/thor-indexof-vs-for/5
    -	indexOf = function( list, elem ) {
    -		var i = 0,
    -			len = list.length;
    -		for ( ; i < len; i++ ) {
    -			if ( list[i] === elem ) {
    -				return i;
    -			}
    -		}
    -		return -1;
    -	},
    -
    -	booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
    -
    -	// Regular expressions
    -
    -	// http://www.w3.org/TR/css3-selectors/#whitespace
    -	whitespace = "[\\x20\\t\\r\\n\\f]",
    -
    -	// http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
    -	identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+",
    -
    -	// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
    -	attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
    -		// Operator (capture 2)
    -		"*([*^$|!~]?=)" + whitespace +
    -		// "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
    -		"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
    -		"*\\]",
    -
    -	pseudos = ":(" + identifier + ")(?:\\((" +
    -		// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
    -		// 1. quoted (capture 3; capture 4 or capture 5)
    -		"('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
    -		// 2. simple (capture 6)
    -		"((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
    -		// 3. anything else (capture 2)
    -		".*" +
    -		")\\)|)",
    -
    -	// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
    -	rwhitespace = new RegExp( whitespace + "+", "g" ),
    -	rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
    -
    -	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
    -	rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
    -
    -	rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
    -
    -	rpseudo = new RegExp( pseudos ),
    -	ridentifier = new RegExp( "^" + identifier + "$" ),
    -
    -	matchExpr = {
    -		"ID": new RegExp( "^#(" + identifier + ")" ),
    -		"CLASS": new RegExp( "^\\.(" + identifier + ")" ),
    -		"TAG": new RegExp( "^(" + identifier + "|[*])" ),
    -		"ATTR": new RegExp( "^" + attributes ),
    -		"PSEUDO": new RegExp( "^" + pseudos ),
    -		"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
    -			"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
    -			"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
    -		"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
    -		// For use in libraries implementing .is()
    -		// We use this for POS matching in `select`
    -		"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
    -			whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
    -	},
    -
    -	rinputs = /^(?:input|select|textarea|button)$/i,
    -	rheader = /^h\d$/i,
    -
    -	rnative = /^[^{]+\{\s*\[native \w/,
    -
    -	// Easily-parseable/retrievable ID or TAG or CLASS selectors
    -	rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
    -
    -	rsibling = /[+~]/,
    -
    -	// CSS escapes
    -	// http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
    -	runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
    -	funescape = function( _, escaped, escapedWhitespace ) {
    -		var high = "0x" + escaped - 0x10000;
    -		// NaN means non-codepoint
    -		// Support: Firefox<24
    -		// Workaround erroneous numeric interpretation of +"0x"
    -		return high !== high || escapedWhitespace ?
    -			escaped :
    -			high < 0 ?
    -				// BMP codepoint
    -				String.fromCharCode( high + 0x10000 ) :
    -				// Supplemental Plane codepoint (surrogate pair)
    -				String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
    -	},
    -
    -	// CSS string/identifier serialization
    -	// https://drafts.csswg.org/cssom/#common-serializing-idioms
    -	rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g,
    -	fcssescape = function( ch, asCodePoint ) {
    -		if ( asCodePoint ) {
    -
    -			// U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
    -			if ( ch === "\0" ) {
    -				return "\uFFFD";
    -			}
    -
    -			// Control characters and (dependent upon position) numbers get escaped as code points
    -			return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
    -		}
    -
    -		// Other potentially-special ASCII characters get backslash-escaped
    -		return "\\" + ch;
    -	},
    -
    -	// Used for iframes
    -	// See setDocument()
    -	// Removing the function wrapper causes a "Permission Denied"
    -	// error in IE
    -	unloadHandler = function() {
    -		setDocument();
    -	},
    -
    -	disabledAncestor = addCombinator(
    -		function( elem ) {
    -			return elem.disabled === true;
    -		},
    -		{ dir: "parentNode", next: "legend" }
    -	);
    -
    -// Optimize for push.apply( _, NodeList )
    -try {
    -	push.apply(
    -		(arr = slice.call( preferredDoc.childNodes )),
    -		preferredDoc.childNodes
    -	);
    -	// Support: Android<4.0
    -	// Detect silently failing push.apply
    -	arr[ preferredDoc.childNodes.length ].nodeType;
    -} catch ( e ) {
    -	push = { apply: arr.length ?
    -
    -		// Leverage slice if possible
    -		function( target, els ) {
    -			push_native.apply( target, slice.call(els) );
    -		} :
    -
    -		// Support: IE<9
    -		// Otherwise append directly
    -		function( target, els ) {
    -			var j = target.length,
    -				i = 0;
    -			// Can't trust NodeList.length
    -			while ( (target[j++] = els[i++]) ) {}
    -			target.length = j - 1;
    -		}
    -	};
    -}
    -
    -function Sizzle( selector, context, results, seed ) {
    -	var m, i, elem, nid, match, groups, newSelector,
    -		newContext = context && context.ownerDocument,
    -
    -		// nodeType defaults to 9, since context defaults to document
    -		nodeType = context ? context.nodeType : 9;
    -
    -	results = results || [];
    -
    -	// Return early from calls with invalid selector or context
    -	if ( typeof selector !== "string" || !selector ||
    -		nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
    -
    -		return results;
    -	}
    -
    -	// Try to shortcut find operations (as opposed to filters) in HTML documents
    -	if ( !seed ) {
    -
    -		if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
    -			setDocument( context );
    -		}
    -		context = context || document;
    -
    -		if ( documentIsHTML ) {
    -
    -			// If the selector is sufficiently simple, try using a "get*By*" DOM method
    -			// (excepting DocumentFragment context, where the methods don't exist)
    -			if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
    -
    -				// ID selector
    -				if ( (m = match[1]) ) {
    -
    -					// Document context
    -					if ( nodeType === 9 ) {
    -						if ( (elem = context.getElementById( m )) ) {
    -
    -							// Support: IE, Opera, Webkit
    -							// TODO: identify versions
    -							// getElementById can match elements by name instead of ID
    -							if ( elem.id === m ) {
    -								results.push( elem );
    -								return results;
    -							}
    -						} else {
    -							return results;
    -						}
    -
    -					// Element context
    -					} else {
    -
    -						// Support: IE, Opera, Webkit
    -						// TODO: identify versions
    -						// getElementById can match elements by name instead of ID
    -						if ( newContext && (elem = newContext.getElementById( m )) &&
    -							contains( context, elem ) &&
    -							elem.id === m ) {
    -
    -							results.push( elem );
    -							return results;
    -						}
    -					}
    -
    -				// Type selector
    -				} else if ( match[2] ) {
    -					push.apply( results, context.getElementsByTagName( selector ) );
    -					return results;
    -
    -				// Class selector
    -				} else if ( (m = match[3]) && support.getElementsByClassName &&
    -					context.getElementsByClassName ) {
    -
    -					push.apply( results, context.getElementsByClassName( m ) );
    -					return results;
    -				}
    -			}
    -
    -			// Take advantage of querySelectorAll
    -			if ( support.qsa &&
    -				!compilerCache[ selector + " " ] &&
    -				(!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
    -
    -				if ( nodeType !== 1 ) {
    -					newContext = context;
    -					newSelector = selector;
    -
    -				// qSA looks outside Element context, which is not what we want
    -				// Thanks to Andrew Dupont for this workaround technique
    -				// Support: IE <=8
    -				// Exclude object elements
    -				} else if ( context.nodeName.toLowerCase() !== "object" ) {
    -
    -					// Capture the context ID, setting it first if necessary
    -					if ( (nid = context.getAttribute( "id" )) ) {
    -						nid = nid.replace( rcssescape, fcssescape );
    -					} else {
    -						context.setAttribute( "id", (nid = expando) );
    -					}
    -
    -					// Prefix every selector in the list
    -					groups = tokenize( selector );
    -					i = groups.length;
    -					while ( i-- ) {
    -						groups[i] = "#" + nid + " " + toSelector( groups[i] );
    -					}
    -					newSelector = groups.join( "," );
    -
    -					// Expand context for sibling selectors
    -					newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
    -						context;
    -				}
    -
    -				if ( newSelector ) {
    -					try {
    -						push.apply( results,
    -							newContext.querySelectorAll( newSelector )
    -						);
    -						return results;
    -					} catch ( qsaError ) {
    -					} finally {
    -						if ( nid === expando ) {
    -							context.removeAttribute( "id" );
    -						}
    -					}
    -				}
    -			}
    -		}
    -	}
    -
    -	// All others
    -	return select( selector.replace( rtrim, "$1" ), context, results, seed );
    -}
    -
    -/**
    - * Create key-value caches of limited size
    - * @returns {function(string, object)} Returns the Object data after storing it on itself with
    - *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
    - *	deleting the oldest entry
    - */
    -function createCache() {
    -	var keys = [];
    -
    -	function cache( key, value ) {
    -		// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
    -		if ( keys.push( key + " " ) > Expr.cacheLength ) {
    -			// Only keep the most recent entries
    -			delete cache[ keys.shift() ];
    -		}
    -		return (cache[ key + " " ] = value);
    -	}
    -	return cache;
    -}
    -
    -/**
    - * Mark a function for special use by Sizzle
    - * @param {Function} fn The function to mark
    - */
    -function markFunction( fn ) {
    -	fn[ expando ] = true;
    -	return fn;
    -}
    -
    -/**
    - * Support testing using an element
    - * @param {Function} fn Passed the created element and returns a boolean result
    - */
    -function assert( fn ) {
    -	var el = document.createElement("fieldset");
    -
    -	try {
    -		return !!fn( el );
    -	} catch (e) {
    -		return false;
    -	} finally {
    -		// Remove from its parent by default
    -		if ( el.parentNode ) {
    -			el.parentNode.removeChild( el );
    -		}
    -		// release memory in IE
    -		el = null;
    -	}
    -}
    -
    -/**
    - * Adds the same handler for all of the specified attrs
    - * @param {String} attrs Pipe-separated list of attributes
    - * @param {Function} handler The method that will be applied
    - */
    -function addHandle( attrs, handler ) {
    -	var arr = attrs.split("|"),
    -		i = arr.length;
    -
    -	while ( i-- ) {
    -		Expr.attrHandle[ arr[i] ] = handler;
    -	}
    -}
    -
    -/**
    - * Checks document order of two siblings
    - * @param {Element} a
    - * @param {Element} b
    - * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
    - */
    -function siblingCheck( a, b ) {
    -	var cur = b && a,
    -		diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
    -			a.sourceIndex - b.sourceIndex;
    -
    -	// Use IE sourceIndex if available on both nodes
    -	if ( diff ) {
    -		return diff;
    -	}
    -
    -	// Check if b follows a
    -	if ( cur ) {
    -		while ( (cur = cur.nextSibling) ) {
    -			if ( cur === b ) {
    -				return -1;
    -			}
    -		}
    -	}
    -
    -	return a ? 1 : -1;
    -}
    -
    -/**
    - * Returns a function to use in pseudos for input types
    - * @param {String} type
    - */
    -function createInputPseudo( type ) {
    -	return function( elem ) {
    -		var name = elem.nodeName.toLowerCase();
    -		return name === "input" && elem.type === type;
    -	};
    -}
    -
    -/**
    - * Returns a function to use in pseudos for buttons
    - * @param {String} type
    - */
    -function createButtonPseudo( type ) {
    -	return function( elem ) {
    -		var name = elem.nodeName.toLowerCase();
    -		return (name === "input" || name === "button") && elem.type === type;
    -	};
    -}
    -
    -/**
    - * Returns a function to use in pseudos for :enabled/:disabled
    - * @param {Boolean} disabled true for :disabled; false for :enabled
    - */
    -function createDisabledPseudo( disabled ) {
    -	// Known :disabled false positives:
    -	// IE: *[disabled]:not(button, input, select, textarea, optgroup, option, menuitem, fieldset)
    -	// not IE: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable
    -	return function( elem ) {
    -
    -		// Check form elements and option elements for explicit disabling
    -		return "label" in elem && elem.disabled === disabled ||
    -			"form" in elem && elem.disabled === disabled ||
    -
    -			// Check non-disabled form elements for fieldset[disabled] ancestors
    -			"form" in elem && elem.disabled === false && (
    -				// Support: IE6-11+
    -				// Ancestry is covered for us
    -				elem.isDisabled === disabled ||
    -
    -				// Otherwise, assume any non-