zope.pagetemplate-4.0.1/0000775000175000017500000000000012100037354015041 5ustar tseavertseaverzope.pagetemplate-4.0.1/setup.cfg0000664000175000017500000000007312100037354016662 0ustar tseavertseaver[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 zope.pagetemplate-4.0.1/buildout.cfg0000664000175000017500000000113312100036656017353 0ustar tseavertseaver[buildout] develop = . parts = py test testcompat coverage-test coverage-report [test] recipe = zc.recipe.testrunner eggs = zope.pagetemplate [test] [testcompat] recipe = zc.recipe.testrunner eggs = zope.pagetemplate [test] z3c.pt z3c.ptcompat Chameleon [py] recipe = zc.recipe.egg eggs = zope.pagetemplate interpreter = py [coverage-test] recipe = zc.recipe.testrunner eggs = zope.pagetemplate [test] defaults = ['--coverage', '../../coverage'] [coverage-report] recipe = zc.recipe.egg eggs = z3c.coverage scripts = coverage=coverage-report arguments = ('coverage', 'coverage/report') zope.pagetemplate-4.0.1/PKG-INFO0000664000175000017500000002263412100037354016145 0ustar tseavertseaverMetadata-Version: 1.0 Name: zope.pagetemplate Version: 4.0.1 Summary: Zope Page Templates Home-page: http://pypi.python.org/pypi/zope.pagetemplate Author: Zope Foundation and Contributors Author-email: zope-dev@zope.org License: ZPL 2.1 Description: Page Templates provide an elegant templating mechanism that achieves a clean separation of presentation and application logic while allowing for designers to work with templates in their visual editing tools (FrontPage, Dreamweaver, GoLive, etc.). Detailed Documentation ---------------------- ===================================== ZPT (Zope Page-Template) Architecture ===================================== There are a number of major components that make up the page-template architecture: - The TAL *compiler* and *interpreter*. This is responsible for compiling source files and for executing compiled templates. See the `zope.tal` package for more information. - An *expression engine* is responsible for compiling expressions and for creating expression execution contexts. It is common for applications to override expression engines to provide custom expression support or to change the way expressions are implemented. The `zope.app.pagetemplate` package uses this to implement trusted and untrusted evaluation; a different engine is used for each, with different implementations of the same type of expressions. Expression contexts support execution of expressions and provide APIs for setting up variable scopes and setting variables. The expression contexts are passed to the TAL interpreter at execution time. The most commonly used expression implementation is that found in `zope.tales`. - Page templates tie everything together. They assemble an expression engine with the TAL interpreter and orchestrate management of source and compiled template data. See `zope.pagetemplate.interfaces`. ============== Page Templates ============== Introduction ------------ Page Templates provide an elegant templating mechanism that achieves a clean separation of presentation and application logic while allowing for designers to work with templates in their visual editing tools (FrontPage, Dreamweaver, GoLive, etc.). This document focuses on usage of Page Templates outside of a Zope context, it does *not* explain how to write page templates as there are several resources on the web which do so. Simple Usage ------------ Using Page Templates outside of Zope3 is very easy and straight forward. A quick example:: >>> from zope.pagetemplate.pagetemplatefile import PageTemplateFile >>> my_pt = PageTemplateFile('hello_world.pt') >>> my_pt() u'Hello World' Subclassing PageTemplates ------------------------- Lets say we want to alter page templates such that keyword arguments appear as top level items in the namespace. We can subclass `PageTemplate` and alter the default behavior of `pt_getContext()` to add them in:: from zope.pagetemplate.pagetemplate import PageTemplate class mypt(PageTemplate): def pt_getContext(self, args=(), options={}, **kw): rval = PageTemplate.pt_getContext(self, args=args) options.update(rval) return options class foo: def getContents(self): return 'hi' So now we can bind objects in a more arbitrary fashion, like the following:: template = """ Good Stuff Here """ pt = mypt() pt.write(template) pt(das_object=foo()) See `interfaces.py`. ======= CHANGES ======= 4.0.1 (2012-01-23) ------------------ - LP#732972: PageTemplateTracebackSupplement no longer passes ``check_macro_expansion=False`` to old templates which do not accept this argument. 4.0.0 (2012-12-13) ------------------ - Replaced deprecated ``zope.interface.classProvides`` usage with equivalent ``zope.interface.provider`` decorator. - Replaced deprecated ``zope.interface.implements`` usage with equivalent ``zope.interface.implementer`` decorator. - Dropped support for Python 2.4 and 2.5. - PageTemplate.pt_render() has a new argument, check_macro_expansion, defaulting to True. - PageTemplateTracebackSupplement passes check_macro_expansion=False, to avoid LP#732972. 3.6.3 (2011-09-21) ------------------ - Fixed test assertions to be compatible with zope.tal 3.6. 3.6.2 (2011-09-21) ------------------ - Change interface for engine and program such that the return type of the ``cook`` method is a tuple ``(program, macros)``. This follows the interface for the TAL parser's ``getCode`` method. This fixes a legacy compatibility issue where code would expect an ``_v_macros`` volatile attribute which was missing. 3.6.1 (2011-08-23) ------------------ - Fixed issue with missing default value for ``strictinsert``. 3.6.0 (2011-08-20) ------------------ - Replaced StringIO stream class with a faster list-based implementation. - Abstract out the template engine and program interfaces and allow implementation replacement via a utility registration. - Removed ancient copyright from test files (LP: #607228) 3.5.2 (2010-07-08) ------------------ - Fixed PTRuntimeError exception messages to be consistent across Python versions, and compatibile with the output under Python 2.4. (More readable than the previous output under Python 2.6 as well.) 3.5.1 (2010-04-30) ------------------ - Removed use of 'zope.testing.doctestunit' in favor of stdlib's doctest. - Added dependency on "zope.security [untrustedpython]" because the 'engine' module uses it. 3.5.0 (2009-05-25) ------------------ - Added test coverage reporting support. - Moved 'engine' module and related test scaffolding here from ``zope.app.pagetemplate`` package. 3.4.2 (2009-03-17) ------------------ - Remove old zpkg-related DEPENDENCIES.cfg file. - Change package's mailing list address to zope-dev at zope.org, as zope3-dev at zope.org is now retired. - Change `cheeseshop` to `pypi` in the packages' homepage url. 3.4.1 (2009-01-27) ------------------ - Fix test due to recent changes in zope.tal. 3.4.0 (2007-10-02) ------------------ - Initial release independent of the Zope 3 tree. 3.2.0 (2006-01-05) ------------------ - Corresponds to the version of the zope.pagetemplate package shipped as part of the Zope 3.2.0 release. - ZPTPage macro expansion: changed label text to match the corresponding label in Zope 2 and activated the name spaces for macro expansion in 'read'. See http://www.zope.org/Collectors/Zope3-dev/199 - Coding style cleanups. 3.1.0 (2005-10-03) ------------------ - Corresponds to the version of the zope.pagetemplate package shipped as part of the Zope 3.1.0 release. - Fixed apidoc and Cookie, which were using wrong descriptor class (changed to 'property'). See http://www.zope.org/Collectors/Zope3-dev/387 - Documentation / style / testing cleanups. 3.0.0 (2004-11-07) ------------------ - Corresponds to the version of the zope.pagetemplate package shipped as part of the Zope X3.0.0 release. Keywords: zope3 page template Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Zope Public License Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Classifier: Topic :: Internet :: WWW/HTTP Classifier: Framework :: Zope3 zope.pagetemplate-4.0.1/tox.ini0000664000175000017500000000027012100036656016357 0ustar tseavertseaver[tox] envlist = # py32 needs a py3k-compatible zope.security at the very least py26,py27 [testenv] deps = zope.pagetemplate[test] commands = python setup.py test -q zope.pagetemplate-4.0.1/setup.py0000664000175000017500000001022612100037203016545 0ustar tseavertseaver############################################################################## # # Copyright (c) 2006 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## # This package is developed by the Zope Toolkit project, documented here: # http://docs.zope.org/zopetoolkit # When developing and releasing this package, please follow the documented # Zope Toolkit policies as described by this documentation. ############################################################################## """Setup for zope.pagetemplate package """ import os from setuptools import setup, find_packages def read(*rnames): return open(os.path.join(os.path.dirname(__file__), *rnames)).read() def _modname(path, base, name=''): if path == base: return name dirname, basename = os.path.split(path) return _modname(dirname, base, basename + '.' + name) def alltests(): import logging import pkg_resources import unittest class NullHandler(logging.Handler): level = 50 def emit(self, record): pass logging.getLogger().addHandler(NullHandler()) suite = unittest.TestSuite() base = pkg_resources.working_set.find( pkg_resources.Requirement.parse('zope.pagetemplate')).location for dirpath, dirnames, filenames in os.walk(base): if os.path.basename(dirpath) == 'tests': for filename in filenames: if ( filename.endswith('.py') and filename.startswith('test') ): mod = __import__( _modname(dirpath, base, os.path.splitext(filename)[0]), {}, {}, ['*']) suite.addTest(mod.test_suite()) return suite TESTS_REQUIRE = [ 'zope.testing', 'zope.proxy', 'zope.security', ] setup(name='zope.pagetemplate', version='4.0.1', author='Zope Foundation and Contributors', author_email='zope-dev@zope.org', description='Zope Page Templates', long_description=( read('README.txt') + '\n\n' + 'Detailed Documentation\n' + '----------------------' + '\n\n' + read('src', 'zope', 'pagetemplate', 'architecture.txt') + '\n\n' + read('src', 'zope', 'pagetemplate', 'readme.txt') + '\n\n' + read('CHANGES.txt')), keywords="zope3 page template", classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Web Environment', 'Intended Audience :: Developers', 'License :: OSI Approved :: Zope Public License', 'Programming Language :: Python', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Natural Language :: English', 'Operating System :: OS Independent', 'Topic :: Internet :: WWW/HTTP', 'Framework :: Zope3'], url='http://pypi.python.org/pypi/zope.pagetemplate', license='ZPL 2.1', packages=find_packages('src'), package_dir={'': 'src'}, namespace_packages=['zope'], extras_require=dict( test=TESTS_REQUIRE, ), install_requires=['setuptools', 'zope.interface', 'zope.component', 'zope.security [untrustedpython]', 'zope.tales', 'zope.tal', 'zope.i18n', 'zope.i18nmessageid', 'zope.traversing', ], include_package_data=True, zip_safe=False, tests_require=TESTS_REQUIRE, test_suite='__main__.alltests', ) zope.pagetemplate-4.0.1/bootstrap.py0000664000175000017500000000733012100036656017437 0ustar tseavertseaver############################################################################## # # Copyright (c) 2006 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Bootstrap a buildout-based project Simply run this script in a directory containing a buildout.cfg. The script accepts buildout command-line options, so you can use the -c option to specify an alternate configuration file. """ import os, shutil, sys, tempfile, urllib2 from optparse import OptionParser tmpeggs = tempfile.mkdtemp() is_jython = sys.platform.startswith('java') # parsing arguments parser = OptionParser() parser.add_option("-v", "--version", dest="version", help="use a specific zc.buildout version") parser.add_option("-d", "--distribute", action="store_true", dest="distribute", default=False, help="Use Disribute rather than Setuptools.") parser.add_option("-c", None, action="store", dest="config_file", help=("Specify the path to the buildout configuration " "file to be used.")) options, args = parser.parse_args() # if -c was provided, we push it back into args for buildout' main function if options.config_file is not None: args += ['-c', options.config_file] if options.version is not None: VERSION = '==%s' % options.version else: VERSION = '' USE_DISTRIBUTE = options.distribute args = args + ['bootstrap'] to_reload = False try: import pkg_resources if not hasattr(pkg_resources, '_distribute'): to_reload = True raise ImportError except ImportError: ez = {} if USE_DISTRIBUTE: exec urllib2.urlopen('http://python-distribute.org/distribute_setup.py' ).read() in ez ez['use_setuptools'](to_dir=tmpeggs, download_delay=0, no_fake=True) else: exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py' ).read() in ez ez['use_setuptools'](to_dir=tmpeggs, download_delay=0) if to_reload: reload(pkg_resources) else: import pkg_resources if sys.platform == 'win32': def quote(c): if ' ' in c: return '"%s"' % c # work around spawn lamosity on windows else: return c else: def quote (c): return c cmd = 'from setuptools.command.easy_install import main; main()' ws = pkg_resources.working_set if USE_DISTRIBUTE: requirement = 'distribute' else: requirement = 'setuptools' if is_jython: import subprocess assert subprocess.Popen([sys.executable] + ['-c', quote(cmd), '-mqNxd', quote(tmpeggs), 'zc.buildout' + VERSION], env=dict(os.environ, PYTHONPATH= ws.find(pkg_resources.Requirement.parse(requirement)).location ), ).wait() == 0 else: assert os.spawnle( os.P_WAIT, sys.executable, quote (sys.executable), '-c', quote (cmd), '-mqNxd', quote (tmpeggs), 'zc.buildout' + VERSION, dict(os.environ, PYTHONPATH= ws.find(pkg_resources.Requirement.parse(requirement)).location ), ) == 0 ws.add_entry(tmpeggs) ws.require('zc.buildout' + VERSION) import zc.buildout.buildout zc.buildout.buildout.main(args) shutil.rmtree(tmpeggs) zope.pagetemplate-4.0.1/src/0000775000175000017500000000000012100037354015630 5ustar tseavertseaverzope.pagetemplate-4.0.1/src/zope.pagetemplate.egg-info/0000775000175000017500000000000012100037354022746 5ustar tseavertseaverzope.pagetemplate-4.0.1/src/zope.pagetemplate.egg-info/top_level.txt0000664000175000017500000000000512100037353025472 0ustar tseavertseaverzope zope.pagetemplate-4.0.1/src/zope.pagetemplate.egg-info/SOURCES.txt0000664000175000017500000000554312100037354024641 0ustar tseavertseaverCHANGES.txt COPYRIGHT.txt LICENSE.txt MANIFEST.in README.txt bootstrap.py buildout.cfg setup.py tox.ini src/zope/__init__.py src/zope.pagetemplate.egg-info/PKG-INFO src/zope.pagetemplate.egg-info/SOURCES.txt src/zope.pagetemplate.egg-info/dependency_links.txt src/zope.pagetemplate.egg-info/namespace_packages.txt src/zope.pagetemplate.egg-info/not-zip-safe src/zope.pagetemplate.egg-info/requires.txt src/zope.pagetemplate.egg-info/top_level.txt src/zope/pagetemplate/__init__.py src/zope/pagetemplate/architecture.txt src/zope/pagetemplate/engine.py src/zope/pagetemplate/i18n.py src/zope/pagetemplate/interfaces.py src/zope/pagetemplate/pagetemplate.py src/zope/pagetemplate/pagetemplatefile.py src/zope/pagetemplate/readme.txt src/zope/pagetemplate/tests/__init__.py src/zope/pagetemplate/tests/batch.py src/zope/pagetemplate/tests/test_basictemplate.py src/zope/pagetemplate/tests/test_engine.py src/zope/pagetemplate/tests/test_htmltests.py src/zope/pagetemplate/tests/test_ptfile.py src/zope/pagetemplate/tests/trusted.py src/zope/pagetemplate/tests/util.py src/zope/pagetemplate/tests/input/__init__.py src/zope/pagetemplate/tests/input/checknotexpression.html src/zope/pagetemplate/tests/input/checknothing.html src/zope/pagetemplate/tests/input/checkpathalt.html src/zope/pagetemplate/tests/input/checkpathnothing.html src/zope/pagetemplate/tests/input/checkwithxmlheader.html src/zope/pagetemplate/tests/input/dtml1.html src/zope/pagetemplate/tests/input/dtml3.html src/zope/pagetemplate/tests/input/globalsshadowlocals.html src/zope/pagetemplate/tests/input/loop1.html src/zope/pagetemplate/tests/input/recursive.html src/zope/pagetemplate/tests/input/stringexpression.html src/zope/pagetemplate/tests/input/teeshop1.html src/zope/pagetemplate/tests/input/teeshop2.html src/zope/pagetemplate/tests/input/teeshoplaf.html src/zope/pagetemplate/tests/input/translation.html src/zope/pagetemplate/tests/output/__init__.py src/zope/pagetemplate/tests/output/checknotexpression.html src/zope/pagetemplate/tests/output/checknothing.html src/zope/pagetemplate/tests/output/checkpathalt.html src/zope/pagetemplate/tests/output/checkpathnothing.html src/zope/pagetemplate/tests/output/checkwithxmlheader.html src/zope/pagetemplate/tests/output/dtml1a.html src/zope/pagetemplate/tests/output/dtml1b.html src/zope/pagetemplate/tests/output/dtml3.html src/zope/pagetemplate/tests/output/globalsshadowlocals.html src/zope/pagetemplate/tests/output/loop1.html src/zope/pagetemplate/tests/output/recursive.html src/zope/pagetemplate/tests/output/stringexpression.html src/zope/pagetemplate/tests/output/teeshop1.html src/zope/pagetemplate/tests/output/teeshop2.html src/zope/pagetemplate/tests/output/teeshoplaf.html src/zope/pagetemplate/tests/output/translation.html src/zope/pagetemplate/tests/testpackage/__init__.py src/zope/pagetemplate/tests/testpackage/content.py src/zope/pagetemplate/tests/testpackage/view.ptzope.pagetemplate-4.0.1/src/zope.pagetemplate.egg-info/PKG-INFO0000664000175000017500000002263412100037353024051 0ustar tseavertseaverMetadata-Version: 1.0 Name: zope.pagetemplate Version: 4.0.1 Summary: Zope Page Templates Home-page: http://pypi.python.org/pypi/zope.pagetemplate Author: Zope Foundation and Contributors Author-email: zope-dev@zope.org License: ZPL 2.1 Description: Page Templates provide an elegant templating mechanism that achieves a clean separation of presentation and application logic while allowing for designers to work with templates in their visual editing tools (FrontPage, Dreamweaver, GoLive, etc.). Detailed Documentation ---------------------- ===================================== ZPT (Zope Page-Template) Architecture ===================================== There are a number of major components that make up the page-template architecture: - The TAL *compiler* and *interpreter*. This is responsible for compiling source files and for executing compiled templates. See the `zope.tal` package for more information. - An *expression engine* is responsible for compiling expressions and for creating expression execution contexts. It is common for applications to override expression engines to provide custom expression support or to change the way expressions are implemented. The `zope.app.pagetemplate` package uses this to implement trusted and untrusted evaluation; a different engine is used for each, with different implementations of the same type of expressions. Expression contexts support execution of expressions and provide APIs for setting up variable scopes and setting variables. The expression contexts are passed to the TAL interpreter at execution time. The most commonly used expression implementation is that found in `zope.tales`. - Page templates tie everything together. They assemble an expression engine with the TAL interpreter and orchestrate management of source and compiled template data. See `zope.pagetemplate.interfaces`. ============== Page Templates ============== Introduction ------------ Page Templates provide an elegant templating mechanism that achieves a clean separation of presentation and application logic while allowing for designers to work with templates in their visual editing tools (FrontPage, Dreamweaver, GoLive, etc.). This document focuses on usage of Page Templates outside of a Zope context, it does *not* explain how to write page templates as there are several resources on the web which do so. Simple Usage ------------ Using Page Templates outside of Zope3 is very easy and straight forward. A quick example:: >>> from zope.pagetemplate.pagetemplatefile import PageTemplateFile >>> my_pt = PageTemplateFile('hello_world.pt') >>> my_pt() u'Hello World' Subclassing PageTemplates ------------------------- Lets say we want to alter page templates such that keyword arguments appear as top level items in the namespace. We can subclass `PageTemplate` and alter the default behavior of `pt_getContext()` to add them in:: from zope.pagetemplate.pagetemplate import PageTemplate class mypt(PageTemplate): def pt_getContext(self, args=(), options={}, **kw): rval = PageTemplate.pt_getContext(self, args=args) options.update(rval) return options class foo: def getContents(self): return 'hi' So now we can bind objects in a more arbitrary fashion, like the following:: template = """ Good Stuff Here """ pt = mypt() pt.write(template) pt(das_object=foo()) See `interfaces.py`. ======= CHANGES ======= 4.0.1 (2012-01-23) ------------------ - LP#732972: PageTemplateTracebackSupplement no longer passes ``check_macro_expansion=False`` to old templates which do not accept this argument. 4.0.0 (2012-12-13) ------------------ - Replaced deprecated ``zope.interface.classProvides`` usage with equivalent ``zope.interface.provider`` decorator. - Replaced deprecated ``zope.interface.implements`` usage with equivalent ``zope.interface.implementer`` decorator. - Dropped support for Python 2.4 and 2.5. - PageTemplate.pt_render() has a new argument, check_macro_expansion, defaulting to True. - PageTemplateTracebackSupplement passes check_macro_expansion=False, to avoid LP#732972. 3.6.3 (2011-09-21) ------------------ - Fixed test assertions to be compatible with zope.tal 3.6. 3.6.2 (2011-09-21) ------------------ - Change interface for engine and program such that the return type of the ``cook`` method is a tuple ``(program, macros)``. This follows the interface for the TAL parser's ``getCode`` method. This fixes a legacy compatibility issue where code would expect an ``_v_macros`` volatile attribute which was missing. 3.6.1 (2011-08-23) ------------------ - Fixed issue with missing default value for ``strictinsert``. 3.6.0 (2011-08-20) ------------------ - Replaced StringIO stream class with a faster list-based implementation. - Abstract out the template engine and program interfaces and allow implementation replacement via a utility registration. - Removed ancient copyright from test files (LP: #607228) 3.5.2 (2010-07-08) ------------------ - Fixed PTRuntimeError exception messages to be consistent across Python versions, and compatibile with the output under Python 2.4. (More readable than the previous output under Python 2.6 as well.) 3.5.1 (2010-04-30) ------------------ - Removed use of 'zope.testing.doctestunit' in favor of stdlib's doctest. - Added dependency on "zope.security [untrustedpython]" because the 'engine' module uses it. 3.5.0 (2009-05-25) ------------------ - Added test coverage reporting support. - Moved 'engine' module and related test scaffolding here from ``zope.app.pagetemplate`` package. 3.4.2 (2009-03-17) ------------------ - Remove old zpkg-related DEPENDENCIES.cfg file. - Change package's mailing list address to zope-dev at zope.org, as zope3-dev at zope.org is now retired. - Change `cheeseshop` to `pypi` in the packages' homepage url. 3.4.1 (2009-01-27) ------------------ - Fix test due to recent changes in zope.tal. 3.4.0 (2007-10-02) ------------------ - Initial release independent of the Zope 3 tree. 3.2.0 (2006-01-05) ------------------ - Corresponds to the version of the zope.pagetemplate package shipped as part of the Zope 3.2.0 release. - ZPTPage macro expansion: changed label text to match the corresponding label in Zope 2 and activated the name spaces for macro expansion in 'read'. See http://www.zope.org/Collectors/Zope3-dev/199 - Coding style cleanups. 3.1.0 (2005-10-03) ------------------ - Corresponds to the version of the zope.pagetemplate package shipped as part of the Zope 3.1.0 release. - Fixed apidoc and Cookie, which were using wrong descriptor class (changed to 'property'). See http://www.zope.org/Collectors/Zope3-dev/387 - Documentation / style / testing cleanups. 3.0.0 (2004-11-07) ------------------ - Corresponds to the version of the zope.pagetemplate package shipped as part of the Zope X3.0.0 release. Keywords: zope3 page template Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Zope Public License Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Classifier: Topic :: Internet :: WWW/HTTP Classifier: Framework :: Zope3 zope.pagetemplate-4.0.1/src/zope.pagetemplate.egg-info/dependency_links.txt0000664000175000017500000000000112100037353027013 0ustar tseavertseaver zope.pagetemplate-4.0.1/src/zope.pagetemplate.egg-info/not-zip-safe0000664000175000017500000000000112100037324025171 0ustar tseavertseaver zope.pagetemplate-4.0.1/src/zope.pagetemplate.egg-info/namespace_packages.txt0000664000175000017500000000000512100037353027273 0ustar tseavertseaverzope zope.pagetemplate-4.0.1/src/zope.pagetemplate.egg-info/requires.txt0000664000175000017500000000026712100037353025352 0ustar tseavertseaversetuptools zope.interface zope.component zope.security [untrustedpython] zope.tales zope.tal zope.i18n zope.i18nmessageid zope.traversing [test] zope.testing zope.proxy zope.securityzope.pagetemplate-4.0.1/src/zope/0000775000175000017500000000000012100037354016605 5ustar tseavertseaverzope.pagetemplate-4.0.1/src/zope/__init__.py0000664000175000017500000000007012100036656020717 0ustar tseavertseaver__import__('pkg_resources').declare_namespace(__name__) zope.pagetemplate-4.0.1/src/zope/pagetemplate/0000775000175000017500000000000012100037354021255 5ustar tseavertseaverzope.pagetemplate-4.0.1/src/zope/pagetemplate/__init__.py0000664000175000017500000000123012100036656023366 0ustar tseavertseaver############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Page Templates """ zope.pagetemplate-4.0.1/src/zope/pagetemplate/i18n.py0000664000175000017500000000157212100036656022417 0ustar tseavertseaver############################################################################## # # Copyright (c) 2003 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Customization of zope.i18n for the Zope application server """ __docformat__ = 'restructuredtext' # import this as _ to create i18n messages in the zope domain from zope.i18nmessageid import MessageFactory ZopeMessageFactory = MessageFactory('zope') zope.pagetemplate-4.0.1/src/zope/pagetemplate/architecture.txt0000664000175000017500000000252212100036656024505 0ustar tseavertseaver===================================== ZPT (Zope Page-Template) Architecture ===================================== There are a number of major components that make up the page-template architecture: - The TAL *compiler* and *interpreter*. This is responsible for compiling source files and for executing compiled templates. See the `zope.tal` package for more information. - An *expression engine* is responsible for compiling expressions and for creating expression execution contexts. It is common for applications to override expression engines to provide custom expression support or to change the way expressions are implemented. The `zope.app.pagetemplate` package uses this to implement trusted and untrusted evaluation; a different engine is used for each, with different implementations of the same type of expressions. Expression contexts support execution of expressions and provide APIs for setting up variable scopes and setting variables. The expression contexts are passed to the TAL interpreter at execution time. The most commonly used expression implementation is that found in `zope.tales`. - Page templates tie everything together. They assemble an expression engine with the TAL interpreter and orchestrate management of source and compiled template data. See `zope.pagetemplate.interfaces`. zope.pagetemplate-4.0.1/src/zope/pagetemplate/interfaces.py0000664000175000017500000001256512100036656023767 0ustar tseavertseaver############################################################################## # # Copyright (c) 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Interface that describes the 'macros' attribute of a PageTemplate. """ from zope.interface import Interface, Attribute class IPageTemplate(Interface): """Objects that can render page templates """ def __call__(*args, **kw): """Render a page template The argument handling is specific to particular implementations. Normally, however, positional arguments are bound to the top-level `args` variable and keyword arguments are bound to the top-level `options` variable. """ def pt_edit(source, content_type): """Set the source and content type """ def pt_errors(namespace): """Return a sequence of strings that describe errors in the template. The errors may occur when the template is compiled or rendered. `namespace` is the set of names passed to the TALES expression evaluator, similar to what's returned by pt_getContext(). This can be used to let a template author know what went wrong when an attempt was made to render the template. """ def read(): """Get the template source """ macros = Attribute("An object that implements the __getitem__ " "protocol, containing page template macros.") class IPageTemplateSubclassing(IPageTemplate): """Behavior that may be overridden or used by subclasses """ def pt_getContext(**kw): """Compute a dictionary of top-level template names Responsible for returning the set of top-level names supported in path expressions """ def pt_getEngine(): """Returns the TALES expression evaluator. """ def pt_getEngineContext(namespace): """Return an execution context from the expression engine.""" def __call__(*args, **kw): """Render a page template This is sometimes overridden to provide additional argument binding. """ def pt_source_file(): """return some text describing where a bit of ZPT code came from. This could be a file path, a object path, etc. """ def _cook(): """Compile the source Results are saved in the variables: _v_errors, _v_warnings, _v_program, and _v_macros, and the flag _v_cooked is set. """ def _cook_check(): """Compiles the source if necessary Subclasses might override this to influence the decision about whether compilation is necessary. """ content_type = Attribute("The content-type of the generated output") expand = Attribute( "Flag indicating whether the read method should expand macros") class IPageTemplateEngine(Interface): """Template engine implementation. The engine must provide a ``cook`` method to return a cooked template program from a source input. """ def cook(source_file, text, engine, content_type): """Parse text and return prepared template program and macros. Note that while ``source_file`` is provided to name the source of the input ``text``, it should not be relied on to be an actual filename (it may be an application-specific, virtual path). The return type is a tuple ``(program, macros)``. """ class IPageTemplateProgram(Interface): """Cooked template program.""" def __call__( context, macros, debug=0, wrap=60, metal=1, tal=1, showtal=-1, strictinsert=1, stackLimit=100, i18nInterpolate=1, sourceAnnotations=0): """Render template in the provided template ``context``. Optional arguments: debug -- enable debugging output to sys.stderr (off by default). wrap -- try to wrap attributes on opening tags to this number of column (default: 60). metal -- enable METAL macro processing (on by default). tal -- enable TAL processing (on by default). showtal -- do not strip away TAL directives. A special value of -1 (which is the default setting) enables showtal when TAL processing is disabled, and disables showtal when TAL processing is enabled. Note that you must use 0, 1, or -1; true boolean values are not supported (for historical reasons). strictinsert -- enable TAL processing and stricter HTML/XML checking on text produced by structure inserts (on by default). Note that Zope turns this value off by default. stackLimit -- set macro nesting limit (default: 100). i18nInterpolate -- enable i18n translations (default: on). sourceAnnotations -- enable source annotations with HTML comments (default: off). """ zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/0000775000175000017500000000000012100037354022417 5ustar tseavertseaverzope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/output/0000775000175000017500000000000012100037354023757 5ustar tseavertseaverzope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/output/checkwithxmlheader.html0000664000175000017500000000007212100036656030513 0ustar tseavertseaver Hello! zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/output/globalsshadowlocals.html0000664000175000017500000000023012100036656030673 0ustar tseavertseaver
2
1
3
zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/output/recursive.html0000664000175000017500000000026312100036656026661 0ustar tseavertseaver zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/output/__init__.py0000664000175000017500000000007512100036656026076 0ustar tseavertseaver# # This file is necessary to make this directory a package. zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/output/teeshop1.html0000664000175000017500000000656312100036656026413 0ustar tseavertseaver Zope Stuff

apparel mugs toys misc


Description: This is the tee for those who LOVE Zope. Show your heart on your tee.

Price:12.99
Description: This is the tee for Jim Fulton. He's the Zope Pope!

Price:11.99
zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/output/dtml1a.html0000664000175000017500000000134512100036656026036 0ustar tseavertseaver Test of documentation templates
The arguments to this test program were:
And thats da trooth. zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/output/translation.html0000664000175000017500000000010512100036656027203 0ustar tseavertseaver

Define and translate message id in ZPT

Translate this!

zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/output/teeshop2.html0000664000175000017500000000206412100036656026404 0ustar tseavertseaver Zope Stuff

apparel mugs toys misc


Body
zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/output/checknothing.html0000664000175000017500000000010012100036656027304 0ustar tseavertseaver zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/output/dtml3.html0000664000175000017500000000141012100036656025670 0ustar tseavertseaverTest of documentation templates
The arguments were:
one.
Argument 1 was one
two.
Argument 2 was two
three.
Argument 3 was three
four.
Argument 4 was four
five.
Argument 5 was five
(six-ten)
And I am 100% sure! zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/output/checkpathalt.html0000664000175000017500000000025712100036656027310 0ustar tseavertseaver

X

X

X

X

X

Z

Z

Z

c

zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/output/teeshoplaf.html0000664000175000017500000000363012100036656027005 0ustar tseavertseaver Zope Stuff

apparel mugs toys misc



This is the tee for those who LOVE Zope. Show your heart on your tee.

zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/output/checknotexpression.html0000664000175000017500000000010712100036656030565 0ustar tseavertseaver
not:python:0
zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/output/checkpathnothing.html0000664000175000017500000000010012100036656030161 0ustar tseavertseaver zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/output/loop1.html0000664000175000017500000000043612100036656025706 0ustar tseavertseaver Loop doc

Choose your type:

zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/output/stringexpression.html0000664000175000017500000000011412100036656030273 0ustar tseavertseaver Hello World! zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/output/dtml1b.html0000664000175000017500000000024712100036656026037 0ustar tseavertseaver Test of documentation templates

No arguments were given.

And thats da trooth. zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/testpackage/0000775000175000017500000000000012100037354024712 5ustar tseavertseaverzope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/testpackage/__init__.py0000664000175000017500000000007512100036656027031 0ustar tseavertseaver# # This file is necessary to make this directory a package. zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/testpackage/content.py0000664000175000017500000000160212100036656026741 0ustar tseavertseaver############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Content """ class Content(object): def getSomething(self): return 42 class PTComponent(object): def __init__(self, content, request): self.content = content index = PageTemplateFile("view.pt", engine_name="unrestricted") zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/testpackage/view.pt0000664000175000017500000000005312100036656026233 0ustar tseavertseaver zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/__init__.py0000664000175000017500000000007512100036656024536 0ustar tseavertseaver# # This file is necessary to make this directory a package. zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/test_htmltests.py0000664000175000017500000001250712100036656026070 0ustar tseavertseaver############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Page Template HTML Tests """ import unittest from zope.pagetemplate.tests import util from zope.pagetemplate.pagetemplate import PageTemplate class Folder(object): context = property(lambda self: self) class HTMLTests(unittest.TestCase): def setUp(self): self.folder = f = Folder() f.laf = PageTemplate() f.t = PageTemplate() def getProducts(self): return [ {'description': 'This is the tee for those who LOVE Zope. ' 'Show your heart on your tee.', 'price': 12.99, 'image': 'smlatee.jpg' }, {'description': 'This is the tee for Jim Fulton. ' 'He\'s the Zope Pope!', 'price': 11.99, 'image': 'smpztee.jpg' }, ] def test_1(self): laf = self.folder.laf laf.write(util.read_input('teeshoplaf.html')) expect = util.read_output('teeshoplaf.html') util.check_html(expect, laf()) def test_2(self): self.folder.laf.write(util.read_input('teeshoplaf.html')) t = self.folder.t t.write(util.read_input('teeshop2.html')) expect = util.read_output('teeshop2.html') out = t(laf = self.folder.laf, getProducts = self.getProducts) util.check_html(expect, out) def test_3(self): self.folder.laf.write(util.read_input('teeshoplaf.html')) t = self.folder.t t.write(util.read_input('teeshop1.html')) expect = util.read_output('teeshop1.html') out = t(laf = self.folder.laf, getProducts = self.getProducts) util.check_html(expect, out) def test_SimpleLoop(self): t = self.folder.t t.write(util.read_input('loop1.html')) expect = util.read_output('loop1.html') out = t() util.check_html(expect, out) def test_GlobalsShadowLocals(self): t = self.folder.t t.write(util.read_input('globalsshadowlocals.html')) expect = util.read_output('globalsshadowlocals.html') out = t() util.check_html(expect, out) def test_StringExpressions(self): t = self.folder.t t.write(util.read_input('stringexpression.html')) expect = util.read_output('stringexpression.html') out = t() util.check_html(expect, out) def test_ReplaceWithNothing(self): t = self.folder.t t.write(util.read_input('checknothing.html')) expect = util.read_output('checknothing.html') out = t() util.check_html(expect, out) def test_WithXMLHeader(self): t = self.folder.t t.write(util.read_input('checkwithxmlheader.html')) expect = util.read_output('checkwithxmlheader.html') out = t() util.check_html(expect, out) def test_NotExpression(self): t = self.folder.t t.write(util.read_input('checknotexpression.html')) expect = util.read_output('checknotexpression.html') out = t() util.check_html(expect, out) def test_PathNothing(self): t = self.folder.t t.write(util.read_input('checkpathnothing.html')) expect = util.read_output('checkpathnothing.html') out = t() util.check_html(expect, out) def test_PathAlt(self): t = self.folder.t t.write(util.read_input('checkpathalt.html')) expect = util.read_output('checkpathalt.html') out = t() util.check_html(expect, out) def test_translation(self): from zope.i18nmessageid import MessageFactory _ = MessageFactory('pttest') msg = _("Translate this!") t = self.folder.t t.write(util.read_input('translation.html')) expect = util.read_output('translation.html') out = t(msg=msg) util.check_html(expect, out) def test_recursion(self): t = self.folder.t t.write(util.read_input('recursive.html')) expect = util.read_output('recursive.html') context = dict(name='root', children=[dict(name='first', children=[]), dict(name='second', children=[])]) namespace = dict(template=t, options={}, args=(), nothing=None, context=context) out = t.pt_render(namespace) # crude way of normalizing whitespace expect = expect.replace(' ', '').replace('\n\n', '\n') out = out.replace(' ', '').replace('\n\n', '\n') util.check_html(expect, out) # https://bugs.launchpad.net/zope.pagetemplate/+bug/732972 errors = t.pt_errors(namespace, check_macro_expansion=False) self.assertFalse(errors) def test_suite(): return unittest.makeSuite(HTMLTests) if __name__=='__main__': unittest.TextTestRunner().run(test_suite()) zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/util.py0000664000175000017500000000576312100036656023765 0ustar tseavertseaver############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Utilities """ import os import re import sys class Bruce(object): __allow_access_to_unprotected_subobjects__=1 def __str__(self): return 'bruce' def __int__(self): return 42 def __float__(self): return 42.0 def keys(self): return ['bruce']*7 def values(self): return [self]*7 def items(self): return [('bruce',self)]*7 def __len__(self): return 7 def __getitem__(self,index): if ininstance(index, int) and (index < 0 or index > 6): raise IndexError(index) return self isDocTemp = 0 def __getattr__(self,name): if name.startswith('_'): raise AttributeError(name) return self bruce = Bruce() class arg(object): __allow_access_to_unprotected_subobjects__ = 1 def __init__(self,nn,aa): self.num, self.arg = nn, aa def __str__(self): return str(self.arg) class argv(object): __allow_access_to_unprotected_subobjects__ = 1 def __init__(self, argv=sys.argv[1:]): args = self.args = [] for aa in argv: args.append(arg(len(args)+1,aa)) def items(self): return map(lambda a: ('spam%d' % a.num, a), self.args) def values(self): return self.args def getRoot(self): return self context = property(lambda self: self) def nicerange(lo, hi): if hi <= lo+1: return str(lo+1) else: return "%d,%d" % (lo+1, hi) def dump(tag, x, lo, hi): for i in xrange(lo, hi): print '%s %s' % (tag, x[i]), def check_html(s1, s2): s1 = normalize_html(s1) s2 = normalize_html(s2) assert s1==s2, (s1, s2, "HTML Output Changed") def check_xml(s1, s2): s1 = normalize_xml(s1) s2 = normalize_xml(s2) assert s1==s2, ("XML Output Changed:\n%r\n\n%r" % (s1, s2)) def normalize_html(s): s = re.sub(r"[ \t]+", " ", s) s = re.sub(r"/>", ">", s) return s def normalize_xml(s): s = re.sub(r"\s+", " ", s) s = re.sub(r"(?s)\s+<", "<", s) s = re.sub(r"(?s)>\s+", ">", s) return s import zope.pagetemplate.tests dir = os.path.dirname(zope.pagetemplate.tests.__file__) input_dir = os.path.join(dir, 'input') output_dir = os.path.join(dir, 'output') def read_input(filename): filename = os.path.join(input_dir, filename) return open(filename, 'r').read() def read_output(filename): filename = os.path.join(output_dir, filename) return open(filename, 'r').read() zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/test_basictemplate.py0000664000175000017500000001643012100036656026655 0ustar tseavertseaver############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Basic Page Template tests """ import unittest from zope.pagetemplate.tests import util import zope.pagetemplate.pagetemplate import zope.component.testing class BasicTemplateTests(unittest.TestCase): def setUp(self): zope.component.testing.setUp(self) self.t = zope.pagetemplate.pagetemplate.PageTemplate() def tearDown(self): zope.component.testing.tearDown(self) def test_if_in_var(self): # DTML test 1: if, in, and var: pass # for unittest """ %(comment)[ blah %(comment)] Test of documentation templates %(if args)[
The arguments to this test program were:

    %(in args)[
  • Argument number %(num)d was %(arg)s %(in args)]

%(if args)] %(else args)[ No arguments were given.

%(else args)] And thats da trooth. """ tal = util.read_input('dtml1.html') self.t.write(tal) aa = util.argv(('one', 'two', 'three', 'cha', 'cha', 'cha')) o = self.t(content=aa) expect = util.read_output('dtml1a.html') util.check_xml(expect, o) aa = util.argv(()) o = self.t(content=aa) expect = util.read_output('dtml1b.html') util.check_xml(expect, o) def test_pt_runtime_error(self): self.t.write("xyz") try: self.t.pt_render({}) except zope.pagetemplate.pagetemplate.PTRuntimeError, e: self.assertEquals( str(e), "['Compilation failed', 'zope.tal.taldefs.TALError:" " TAL attributes on require explicit" " , at line 1, column 1']") else: self.fail("expected PTRuntimeError") def test_engine_utility_registration(self): self.t.write("foo") output = self.t.pt_render({}) self.assertEqual(output, 'foo') from zope.pagetemplate.interfaces import IPageTemplateEngine from zope.component import provideUtility class DummyProgram(object): def __init__(*args): self.args = args def __call__(*args, **kwargs): return self.args, args, kwargs class DummyEngine(object): @staticmethod def cook(*args): return DummyProgram(*args), "macros" provideUtility(DummyEngine, IPageTemplateEngine) self.t._cook() self.assertTrue(isinstance(self.t._v_program, DummyProgram)) self.assertEqual(self.t._v_macros, "macros") # "Render" and unpack arguments passed for verification ((cls, source_file, text, engine, content_type), (program, context, macros), options) = \ self.t.pt_render({}) self.assertEqual(source_file, None) self.assertEqual(text, 'foo') self.assertEqual(content_type, 'text/html') self.assertTrue(isinstance(program, DummyProgram)) self.assertEqual(options, { 'tal': True, 'showtal': False, 'sourceAnnotations': False, 'strictinsert': 0, }) def test_batches_and_formatting(self): # DTML test 3: batches and formatting: pass # for unittest """ Test of documentation templates The arguments were: (- )

.
Argument was
(- )
No arguments were given.

And I\'m 100% sure! """ tal = util.read_input('dtml3.html') self.t.write(tal) aa = util.argv(('one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen', 'twenty', )) from zope.pagetemplate.tests import batch o = self.t(content=aa, batch=batch.batch(aa.args, 5)) expect = util.read_output('dtml3.html') util.check_xml(expect, o) def test_on_error_in_slot_filler(self): # The `here` isn't defined, so the macro definition is # expected to catch the error that gets raised. text = '''\

cool

''' self.t.write(text) self.t() def test_on_error_in_slot_default(self): # The `here` isn't defined, so the macro definition is # expected to catch the error that gets raised. text = '''\
''' self.t.write(text) self.t() def test_unicode_html(self): text = u'

\xe4\xf6\xfc\xdf

' # test with HTML parser self.t.pt_edit(text, 'text/html') self.assertEquals(self.t().strip(), text) # test with XML parser self.t.pt_edit(text, 'text/xml') self.assertEquals(self.t().strip(), text) def test_suite(): return unittest.makeSuite(BasicTemplateTests) if __name__ == '__main__': unittest.TextTestRunner().run(test_suite()) zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/trusted.py0000664000175000017500000000143112100036656024466 0ustar tseavertseaver############################################################################## # # Copyright (c) 2004 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Sample of a module imported by a trusted module. This module won't be imported by an untrusted template using a path:modules/... expression. """ x = 42 zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/input/0000775000175000017500000000000012100037354023556 5ustar tseavertseaverzope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/input/checkwithxmlheader.html0000664000175000017500000000012112100036656030305 0ustar tseavertseaver zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/input/globalsshadowlocals.html0000664000175000017500000000051612100036656030501 0ustar tseavertseaver
Should be 2 here!
Should be 1 here!
Should be 3 here!
zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/input/recursive.html0000664000175000017500000000036612100036656026464 0ustar tseavertseaver
    zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/input/__init__.py0000664000175000017500000000007512100036656025675 0ustar tseavertseaver# # This file is necessary to make this directory a package. zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/input/teeshop1.html0000664000175000017500000000561212100036656026204 0ustar tseavertseaver Zope Stuff

    apparel mugs toys misc


    Description: This is the tee for those who LOVE Zope. Show your heart on your tee.

    Price:12.99
    zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/input/translation.html0000664000175000017500000000017412100036656027010 0ustar tseavertseaver

    Define and translate message id in ZPT

    Insert Message object here

    zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/input/teeshop2.html0000664000175000017500000000014212100036656026176 0ustar tseavertseaver
    Body
    zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/input/checknothing.html0000664000175000017500000000014212100036656027111 0ustar tseavertseaver Hello World! zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/input/dtml3.html0000664000175000017500000000243612100036656025500 0ustar tseavertseaverTest of documentation templates
    The arguments were: (previous start item-previous end item)
    ??.
    Argument 99 was ??
    (next start item-next end item)

    No arguments were given.

    And I am 100% sure! zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/input/checkpathalt.html0000664000175000017500000000073112100036656027104 0ustar tseavertseaver

    1

    2

    3

    4

    5

    Z

    Z

    Z

    Z

    zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/input/teeshoplaf.html0000664000175000017500000000371312100036656026606 0ustar tseavertseaver Zope Stuff

    apparel mugs toys misc



    This is the tee for those who LOVE Zope. Show your heart on your tee.

    zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/input/checknotexpression.html0000664000175000017500000000042612100036656030370 0ustar tseavertseaver
    not:python:0
    not:python:1
    not: python:1
    not:python:range(1,20)
    zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/input/checkpathnothing.html0000664000175000017500000000014712100036656027773 0ustar tseavertseaver Hello World! zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/input/dtml1.html0000664000175000017500000000124212100036656025470 0ustar tseavertseaver Test of documentation templates blah
    The arguments to this test program were:
    • Argument number 99 is default

    No arguments were given.

    And thats da trooth. zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/input/loop1.html0000664000175000017500000000051712100036656025505 0ustar tseavertseaver Loop doc

    Choose your type:

    zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/input/stringexpression.html0000664000175000017500000000016312100036656030076 0ustar tseavertseaver This is the title zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/test_ptfile.py0000664000175000017500000001530112100036656025317 0ustar tseavertseaver############################################################################## # # Copyright (c) 2004 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Tests of PageTemplateFile. """ import os import tempfile import unittest from zope.pagetemplate.pagetemplatefile import PageTemplateFile class TypeSniffingTestCase(unittest.TestCase): TEMPFILENAME = tempfile.mktemp() def tearDown(self): if os.path.exists(self.TEMPFILENAME): os.unlink(self.TEMPFILENAME) def get_pt(self, text): f = open(self.TEMPFILENAME, "wb") f.write(text) f.close() pt = PageTemplateFile(self.TEMPFILENAME) pt.read() return pt def check_content_type(self, text, expected_type): pt = self.get_pt(text) self.assertEqual(pt.content_type, expected_type) def test_sniffer_xml_ascii(self): self.check_content_type( "", "text/xml") self.check_content_type( "", "text/xml") def test_sniffer_xml_utf8(self): # w/out byte order mark self.check_content_type( "", "text/xml") self.check_content_type( "", "text/xml") # with byte order mark self.check_content_type( "\xef\xbb\xbf", "text/xml") self.check_content_type( "\xef\xbb\xbf", "text/xml") def test_sniffer_xml_utf16_be(self): # w/out byte order mark self.check_content_type( "\0<\0?\0x\0m\0l\0 \0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'" "\0 \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>" "\0<\0d\0o\0c\0/\0>", "text/xml") self.check_content_type( "\0<\0?\0x\0m\0l\0\t\0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'" "\0 \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>" "\0<\0d\0o\0c\0/\0>", "text/xml") # with byte order mark self.check_content_type( "\xfe\xff" "\0<\0?\0x\0m\0l\0 \0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'" "\0 \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>" "\0<\0d\0o\0c\0/\0>", "text/xml") self.check_content_type( "\xfe\xff" "\0<\0?\0x\0m\0l\0\t\0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'" "\0 \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>" "\0<\0d\0o\0c\0/\0>", "text/xml") def test_sniffer_xml_utf16_le(self): # w/out byte order mark self.check_content_type( "<\0?\0x\0m\0l\0 \0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'\0" " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>\0" "<\0d\0o\0c\0/\0>\n", "text/xml") self.check_content_type( "<\0?\0x\0m\0l\0\t\0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'\0" " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>\0" "<\0d\0o\0c\0/\0>\0", "text/xml") # with byte order mark self.check_content_type( "\xff\xfe" "<\0?\0x\0m\0l\0 \0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'\0" " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>\0" "<\0d\0o\0c\0/\0>\0", "text/xml") self.check_content_type( "\xff\xfe" "<\0?\0x\0m\0l\0\t\0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'\0" " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>\0" "<\0d\0o\0c\0/\0>\0", "text/xml") HTML_PUBLIC_ID = "-//W3C//DTD HTML 4.01 Transitional//EN" HTML_SYSTEM_ID = "http://www.w3.org/TR/html4/loose.dtd" def test_sniffer_html_ascii(self): self.check_content_type( "" % self.HTML_SYSTEM_ID, "text/html") self.check_content_type( "sample document", "text/html") # TODO: This reflects a case that simply isn't handled by the # sniffer; there are many, but it gets it right more often than # before. def donttest_sniffer_xml_simple(self): self.check_content_type("", "text/xml") def test_html_default_encoding(self): pt = self.get_pt( "" # 'Test' in russian (utf-8) "\xd0\xa2\xd0\xb5\xd1\x81\xd1\x82" "") rendered = pt() self.failUnless(isinstance(rendered, unicode)) self.failUnlessEqual(rendered.strip(), u"" u"\u0422\u0435\u0441\u0442" u"") def test_html_encoding_by_meta(self): pt = self.get_pt( "" # 'Test' in russian (windows-1251) "\xd2\xe5\xf1\xf2" '' "") rendered = pt() self.failUnless(isinstance(rendered, unicode)) self.failUnlessEqual(rendered.strip(), u"" u"\u0422\u0435\u0441\u0442" u"") def test_xhtml(self): pt = self.get_pt( "" # 'Test' in russian (windows-1251) "\xd2\xe5\xf1\xf2" '' "") rendered = pt() self.failUnless(isinstance(rendered, unicode)) self.failUnlessEqual(rendered.strip(), u"" u"\u0422\u0435\u0441\u0442" u"") def test_suite(): return unittest.makeSuite(TypeSniffingTestCase) if __name__ == "__main__": unittest.main(defaultTest="test_suite") zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/batch.py0000664000175000017500000000725112100036656024063 0ustar tseavertseaver############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Batching support tests """ class batch(object): """Create a sequence batch""" def __init__(self, sequence, size, start=0, end=0, orphan=3, overlap=0): start=start+1 start,end,sz=opt(start,end,size,orphan,sequence) self._last=end-1 self._first=start-1 self._sequence=sequence self._size=size self._start=start self._end=end self._orphan=orphan self._overlap=overlap def previous_sequence(self): return self._first def previous_sequence_end_number(self): start,end,spam=opt(0, self._start-1+self._overlap, self._size, self._orphan, self._sequence) return end def previous_sequence_start_number(self): start,end,spam=opt(0, self._start-1+self._overlap, self._size, self._orphan, self._sequence) return start def previous_sequence_end_item(self): start,end,spam=opt(0, self._start-1+self._overlap, self._size, self._orphan, self._sequence) return self._sequence[end-1] def previous_sequence_start_item(self): start,end,spam=opt(0, self._start-1+self._overlap, self._size, self._orphan, self._sequence) return self._sequence[start-1] def next_sequence_end_number(self): start,end,spam=opt(self._end+1-self._overlap, 0, self._size, self._orphan, self._sequence) return end def next_sequence_start_number(self): start,end,spam=opt(self._end+1-self._overlap, 0, self._size, self._orphan, self._sequence) return start def next_sequence_end_item(self): start,end,spam=opt(self._end+1-self._overlap, 0, self._size, self._orphan, self._sequence) return self._sequence[end-1] def next_sequence_start_item(self): start,end,spam=opt(self._end+1-self._overlap, 0, self._size, self._orphan, self._sequence) return self._sequence[start-1] def next_sequence(self): try: self._sequence[self._end] except IndexError: return 0 else: return 1 def __getitem__(self, index): if index > self._last: raise IndexError(index) return self._sequence[index+self._first] def opt(start,end,size,orphan,sequence): if size < 1: if start > 0 and end > 0 and end >= start: size=end+1-start else: size=7 if start > 0: try: sequence[start-1] except: start=len(sequence) if end > 0: if end < start: end=start else: end=start+size-1 try: sequence[end+orphan-1] except: end=len(sequence) elif end > 0: try: sequence[end-1] except: end=len(sequence) start=end+1-size if start - 1 < orphan: start=1 else: start=1 end=start+size-1 try: sequence[end+orphan-1] except: end=len(sequence) return start,end,size zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/test_engine.py0000664000175000017500000000615412100036656025307 0ustar tseavertseaver############################################################################## # # Copyright (c) 2004-2009 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Doc tests for the pagetemplate's 'engine' module """ import unittest class DummyNamespace(object): def __init__(self, context): self.context = context class EngineTests(unittest.TestCase): def setUp(self): from zope.component.testing import setUp setUp() def tearDown(self): from zope.component.testing import tearDown tearDown() def test_function_namespaces_return_secured_proxies(self): # See https://bugs.launchpad.net/zope3/+bug/98323 from zope.component import provideAdapter from zope.traversing.interfaces import IPathAdapter from zope.pagetemplate.engine import _Engine from zope.proxy import isProxy provideAdapter(DummyNamespace, (None,), IPathAdapter, name='test') engine = _Engine() namespace = engine.getFunctionNamespace('test') self.failUnless(isProxy(namespace)) class DummyEngine(object): def getTypes(self): return {} class DummyContext(object): _engine = DummyEngine() def __init__(self, **kw): self.vars = kw class ZopePythonExprTests(unittest.TestCase): def test_simple(self): from zope.pagetemplate.engine import ZopePythonExpr expr = ZopePythonExpr('python', 'max(a,b)', DummyEngine()) self.assertEqual(expr(DummyContext(a=1, b=2)), 2) def test_allowed_module_name(self): from zope.pagetemplate.engine import ZopePythonExpr expr = ZopePythonExpr('python', '__import__("sys").__name__', DummyEngine()) self.assertEqual(expr(DummyContext()), 'sys') def test_forbidden_module_name(self): from zope.pagetemplate.engine import ZopePythonExpr from zope.security.interfaces import Forbidden expr = ZopePythonExpr('python', '__import__("sys").exit', DummyEngine()) self.assertRaises(Forbidden, expr, DummyContext()) def test_disallowed_builtin(self): from zope.pagetemplate.engine import ZopePythonExpr expr = ZopePythonExpr('python', 'open("x", "w")', DummyEngine()) self.assertRaises(NameError, expr, DummyContext()) def test_suite(): from doctest import DocTestSuite suite = unittest.TestSuite() suite.addTest(DocTestSuite('zope.pagetemplate.engine')) suite.addTest(unittest.makeSuite(EngineTests)) suite.addTest(unittest.makeSuite(ZopePythonExprTests)) return suite if __name__ == '__main__': unittest.main(defaultTest='test_suite') zope.pagetemplate-4.0.1/src/zope/pagetemplate/readme.txt0000664000175000017500000000320212100036656023254 0ustar tseavertseaver============== Page Templates ============== Introduction ------------ Page Templates provide an elegant templating mechanism that achieves a clean separation of presentation and application logic while allowing for designers to work with templates in their visual editing tools (FrontPage, Dreamweaver, GoLive, etc.). This document focuses on usage of Page Templates outside of a Zope context, it does *not* explain how to write page templates as there are several resources on the web which do so. Simple Usage ------------ Using Page Templates outside of Zope3 is very easy and straight forward. A quick example:: >>> from zope.pagetemplate.pagetemplatefile import PageTemplateFile >>> my_pt = PageTemplateFile('hello_world.pt') >>> my_pt() u'Hello World' Subclassing PageTemplates ------------------------- Lets say we want to alter page templates such that keyword arguments appear as top level items in the namespace. We can subclass `PageTemplate` and alter the default behavior of `pt_getContext()` to add them in:: from zope.pagetemplate.pagetemplate import PageTemplate class mypt(PageTemplate): def pt_getContext(self, args=(), options={}, **kw): rval = PageTemplate.pt_getContext(self, args=args) options.update(rval) return options class foo: def getContents(self): return 'hi' So now we can bind objects in a more arbitrary fashion, like the following:: template = """ Good Stuff Here """ pt = mypt() pt.write(template) pt(das_object=foo()) See `interfaces.py`. zope.pagetemplate-4.0.1/src/zope/pagetemplate/pagetemplate.py0000664000175000017500000002075712100036656024316 0ustar tseavertseaver############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Page Template module HTML- and XML-based template objects using TAL, TALES, and METAL. """ import sys from zope.tal.talparser import TALParser from zope.tal.htmltalparser import HTMLTALParser from zope.tal.talgenerator import TALGenerator from zope.tal.talinterpreter import TALInterpreter from zope.tales.engine import Engine from zope.component import queryUtility from zope.pagetemplate.interfaces import IPageTemplateSubclassing from zope.pagetemplate.interfaces import IPageTemplateEngine from zope.pagetemplate.interfaces import IPageTemplateProgram from zope.interface import implementer from zope.interface import provider _default_options = {} _error_start = '') if errend >= 0: text = text[errend + 3:] if text[:1] == "\n": text = text[1:] if self._text != text: self._text = text # Always cook on an update, even if the source is the same; # the content-type might have changed. self._cook() def read(self, request=None): """Gets the source, sometimes with macros expanded.""" self._cook_check() if not self._v_errors: if not self.expand: return self._text try: # This gets called, if macro expansion is turned on. # Note that an empty dictionary is fine for the context at # this point, since we are not evaluating the template. context = self.pt_getContext(self, request) return self.pt_render(context, source=1) except: return ('%s\n Macro expansion failed\n %s\n-->\n%s' % (_error_start, "%s: %s" % sys.exc_info()[:2], self._text) ) return ('%s\n %s\n-->\n%s' % (_error_start, '\n'.join(self._v_errors), self._text)) def pt_source_file(self): """To be overridden.""" return None def _cook_check(self): if not self._v_cooked: self._cook() def _cook(self): """Compile the TAL and METAL statments. Cooking must not fail due to compilation errors in templates. """ pt_engine = self.pt_getEngine() source_file = self.pt_source_file() self._v_errors = () try: engine = queryUtility( IPageTemplateEngine, default=PageTemplateEngine ) self._v_program, self._v_macros = engine.cook( source_file, self._text, pt_engine, self.content_type) except: etype, e = sys.exc_info()[:2] self._v_errors = [ "Compilation failed", "%s.%s: %s" % (etype.__module__, etype.__name__, e) ] self._v_cooked = 1 class PTRuntimeError(RuntimeError): '''The Page Template has template errors that prevent it from rendering.''' pass @implementer(IPageTemplateProgram) @provider(IPageTemplateEngine) class PageTemplateEngine(object): """Page template engine that uses the TAL interpreter to render.""" def __init__(self, program): self.program = program def __call__(self, context, macros, **options): output = StringIO(u'') interpreter = TALInterpreter( self.program, macros, context, stream=output, **options ) interpreter() return output.getvalue() @classmethod def cook(cls, source_file, text, engine, content_type): if content_type == 'text/html': gen = TALGenerator(engine, xml=0, source_file=source_file) parser = HTMLTALParser(gen) else: gen = TALGenerator(engine, source_file=source_file) parser = TALParser(gen) parser.parseString(text) program, macros = parser.getCode() return cls(program), macros #@implementer(ITracebackSupplement) class PageTemplateTracebackSupplement(object): def __init__(self, pt, namespace): self.manageable_object = pt self.warnings = [] try: e = pt.pt_errors(namespace, check_macro_expansion=False) except TypeError: # Old page template. e = pt.pt_errors(namespace) if e: self.warnings.extend(e) zope.pagetemplate-4.0.1/src/zope/pagetemplate/engine.py0000664000175000017500000003561412100036656023111 0ustar tseavertseaver############################################################################## # # Copyright (c) 2002-2009 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE # ############################################################################## """Expression engine configuration and registration. Each expression engine can have its own expression types and base names. """ __docformat__ = 'restructuredtext' import sys from zope import component from zope.interface import implementer from zope.component.interfaces import ComponentLookupError from zope.traversing.interfaces import IPathAdapter, ITraversable from zope.traversing.interfaces import TraversalError from zope.traversing.adapters import traversePathElement from zope.security.untrustedpython import rcompile from zope.security.proxy import ProxyFactory, removeSecurityProxy from zope.security.untrustedpython.builtins import SafeBuiltins from zope.i18n import translate from zope.tales.expressions import PathExpr, StringExpr, NotExpr, DeferExpr from zope.tales.expressions import SimpleModuleImporter from zope.tales.pythonexpr import PythonExpr from zope.tales.tales import ExpressionEngine, Context from zope.pagetemplate.i18n import ZopeMessageFactory as _ class InlineCodeError(Exception): pass class ZopeTraverser(object): def __init__(self, proxify=None): if proxify is None: self.proxify = lambda x: x else: self.proxify = proxify def __call__(self, object, path_items, econtext): """Traverses a sequence of names, first trying attributes then items. """ request = getattr(econtext, 'request', None) path_items = list(path_items) path_items.reverse() while path_items: name = path_items.pop() # special-case dicts for performance reasons if getattr(object, '__class__', None) == dict: object = object[name] else: object = traversePathElement(object, name, path_items, request=request) object = self.proxify(object) return object zopeTraverser = ZopeTraverser(ProxyFactory) class ZopePathExpr(PathExpr): def __init__(self, name, expr, engine): super(ZopePathExpr, self).__init__(name, expr, engine, zopeTraverser) trustedZopeTraverser = ZopeTraverser() class TrustedZopePathExpr(PathExpr): def __init__(self, name, expr, engine): super(TrustedZopePathExpr, self).__init__(name, expr, engine, trustedZopeTraverser) # Create a version of the restricted built-ins that uses a safe # version of getattr() that wraps values in security proxies where # appropriate: class ZopePythonExpr(PythonExpr): def __call__(self, econtext): __traceback_info__ = self.text vars = self._bind_used_names(econtext, SafeBuiltins) return eval(self._code, vars) def _compile(self, text, filename): return rcompile.compile(text, filename, 'eval') class ZopeContextBase(Context): """Base class for both trusted and untrusted evaluation contexts.""" def translate(self, msgid, domain=None, mapping=None, default=None): return translate(msgid, domain, mapping, context=self.request, default=default) evaluateInlineCode = False def evaluateCode(self, lang, code): if not self.evaluateInlineCode: raise InlineCodeError( _('Inline Code Evaluation is deactivated, which means that ' 'you cannot have inline code snippets in your Page ' 'Template. Activate Inline Code Evaluation and try again.')) # TODO This is only needed when self.evaluateInlineCode is true, # so should only be needed for zope.app.pythonpage. from zope.app.interpreter.interfaces import IInterpreter interpreter = component.queryUtility(IInterpreter, lang) if interpreter is None: error = _('No interpreter named "${lang_name}" was found.', mapping={'lang_name': lang}) raise InlineCodeError(error) globals = self.vars.copy() result = interpreter.evaluateRawCode(code, globals) # Add possibly new global variables. old_names = self.vars.keys() for name, value in globals.items(): if name not in old_names: self.setGlobal(name, value) return result class ZopeContext(ZopeContextBase): """Evaluation context for untrusted programs.""" def evaluateMacro(self, expr): """evaluateMacro gets security-proxied macro programs when this is run with the zopeTraverser, and in other untrusted situations. This will cause evaluation to fail in zope.tal.talinterpreter, which knows nothing of security proxies. Therefore, this method removes any proxy from the evaluated expression. >>> output = [('version', 'xxx'), ('mode', 'html'), ('other', 'things')] >>> def expression(context): ... return ProxyFactory(output) ... >>> zc = ZopeContext(ExpressionEngine, {}) >>> out = zc.evaluateMacro(expression) >>> type(out) The method does some trivial checking to make sure we are getting back a macro like we expect: it must be a sequence of sequences, in which the first sequence must start with 'version', and the second must start with 'mode'. >>> del output[0] >>> zc.evaluateMacro(expression) # doctest: +ELLIPSIS Traceback (most recent call last): ... ValueError: ('unexpected result from macro evaluation.', ...) >>> del output[:] >>> zc.evaluateMacro(expression) # doctest: +ELLIPSIS Traceback (most recent call last): ... ValueError: ('unexpected result from macro evaluation.', ...) >>> output = None >>> zc.evaluateMacro(expression) # doctest: +ELLIPSIS Traceback (most recent call last): ... ValueError: ('unexpected result from macro evaluation.', ...) """ macro = removeSecurityProxy(Context.evaluateMacro(self, expr)) # we'll do some basic checks that it is the sort of thing we expect problem = False try: problem = macro[0][0] != 'version' or macro[1][0] != 'mode' except (TypeError, IndexError): problem = True if problem: raise ValueError('unexpected result from macro evaluation.', macro) return macro def setContext(self, name, value): # Hook to allow subclasses to do things like adding security proxies Context.setContext(self, name, ProxyFactory(value)) class TrustedZopeContext(ZopeContextBase): """Evaluation context for trusted programs.""" class AdapterNamespaces(object): """Simulate tales function namespaces with adapter lookup. When we are asked for a namespace, we return an object that actually computes an adapter when called: To demonstrate this, we need to register an adapter: >>> from zope.component.testing import setUp, tearDown >>> setUp() >>> from zope.component import provideAdapter >>> def adapter1(ob): ... return 1 >>> adapter1.__component_adapts__ = (None,) >>> provideAdapter(adapter1, None, IPathAdapter, 'a1') Now, with this adapter in place, we can try out the namespaces: >>> ob = object() >>> namespaces = AdapterNamespaces() >>> namespace = namespaces['a1'] >>> namespace(ob) 1 >>> namespace = namespaces['a2'] >>> namespace(ob) Traceback (most recent call last): ... KeyError: 'a2' Cleanup: >>> tearDown() """ def __init__(self): self.namespaces = {} def __getitem__(self, name): namespace = self.namespaces.get(name) if namespace is None: def namespace(object): try: return component.getAdapter(object, IPathAdapter, name) except ComponentLookupError: raise KeyError(name) self.namespaces[name] = namespace return namespace class ZopeBaseEngine(ExpressionEngine): _create_context = ZopeContext def __init__(self): ExpressionEngine.__init__(self) self.namespaces = AdapterNamespaces() def getContext(self, __namespace=None, **namespace): if __namespace: if namespace: namespace.update(__namespace) else: namespace = __namespace context = self._create_context(self, namespace) # Put request into context so path traversal can find it if 'request' in namespace: context.request = namespace['request'] # Put context into context so path traversal can find it if 'context' in namespace: context.context = namespace['context'] return context class ZopeEngine(ZopeBaseEngine): """Untrusted expression engine. This engine does not allow modules to be imported; only modules already available may be accessed:: >>> modname = 'zope.pagetemplate.tests.trusted' >>> engine = _Engine() >>> context = engine.getContext(engine.getBaseNames()) >>> modname in sys.modules False >>> context.evaluate('modules/' + modname) Traceback (most recent call last): ... KeyError: 'zope.pagetemplate.tests.trusted' (The use of ``KeyError`` is an unfortunate implementation detail; I think this should be a ``TraversalError``.) Modules which have already been imported by trusted code are available, wrapped in security proxies:: >>> m = context.evaluate('modules/sys') >>> m.__name__ 'sys' >>> m._getframe Traceback (most recent call last): ... ForbiddenAttribute: ('_getframe', ) The results of Python expressions evaluated by this engine are wrapped in security proxies:: >>> r = context.evaluate('python: {12: object()}.values') >>> type(r) >>> r = context.evaluate('python: {12: object()}.values()[0].__class__') >>> type(r) General path expressions provide objects that are wrapped in security proxies as well:: >>> from zope.component.testing import setUp, tearDown >>> from zope.security.checker import NamesChecker, defineChecker >>> @implementer(ITraversable) ... class Container(dict): ... def traverse(self, name, further_path): ... return self[name] >>> setUp() >>> defineChecker(Container, NamesChecker(['traverse'])) >>> d = engine.getBaseNames() >>> foo = Container() >>> foo.__name__ = 'foo' >>> d['foo'] = ProxyFactory(foo) >>> foo['bar'] = bar = Container() >>> bar.__name__ = 'bar' >>> bar.__parent__ = foo >>> bar['baz'] = baz = Container() >>> baz.__name__ = 'baz' >>> baz.__parent__ = bar >>> context = engine.getContext(d) >>> o1 = context.evaluate('foo/bar') >>> o1.__name__ 'bar' >>> type(o1) >>> o2 = context.evaluate('foo/bar/baz') >>> o2.__name__ 'baz' >>> type(o2) >>> o3 = o2.__parent__ >>> type(o3) >>> o1 == o3 True >>> o1 is o2 False Note that this engine special-cases dicts during path traversal: it traverses only to their items, but not to their attributes (e.g. methods on dicts), because of performance reasons: >>> d = engine.getBaseNames() >>> d['adict'] = {'items': 123} >>> d['anotherdict'] = {} >>> context = engine.getContext(d) >>> context.evaluate('adict/items') 123 >>> context.evaluate('anotherdict/keys') Traceback (most recent call last): ... KeyError: 'keys' >>> tearDown() """ def getFunctionNamespace(self, namespacename): """ Returns the function namespace """ return ProxyFactory( super(ZopeEngine, self).getFunctionNamespace(namespacename)) class TrustedZopeEngine(ZopeBaseEngine): """Trusted expression engine. This engine allows modules to be imported:: >>> modname = 'zope.pagetemplate.tests.trusted' >>> engine = _TrustedEngine() >>> context = engine.getContext(engine.getBaseNames()) >>> modname in sys.modules False >>> m = context.evaluate('modules/' + modname) >>> m.__name__ == modname True >>> modname in sys.modules True Since this is trusted code, we can look at whatever is in the module, not just __name__ or what's declared in a security assertion:: >>> m.x 42 Clean up after ourselves:: >>> del sys.modules[modname] """ _create_context = TrustedZopeContext @implementer(ITraversable) class TraversableModuleImporter(SimpleModuleImporter): def traverse(self, name, further_path): try: return self[name] except KeyError: raise TraversalError(self, name) def _Engine(engine=None): if engine is None: engine = ZopeEngine() engine = _create_base_engine(engine, ZopePathExpr) engine.registerType('python', ZopePythonExpr) # Using a proxy around sys.modules allows page templates to use # modules for which security declarations have been made, but # disallows execution of any import-time code for modules, which # should not be allowed to happen during rendering. engine.registerBaseName('modules', ProxyFactory(sys.modules)) return engine def _TrustedEngine(engine=None): if engine is None: engine = TrustedZopeEngine() engine = _create_base_engine(engine, TrustedZopePathExpr) engine.registerType('python', PythonExpr) engine.registerBaseName('modules', TraversableModuleImporter()) return engine def _create_base_engine(engine, pathtype): for pt in pathtype._default_type_names: engine.registerType(pt, pathtype) engine.registerType('string', StringExpr) engine.registerType('not', NotExpr) engine.registerType('defer', DeferExpr) return engine Engine = _Engine() TrustedEngine = _TrustedEngine() class AppPT(object): def pt_getEngine(self): return Engine class TrustedAppPT(object): def pt_getEngine(self): return TrustedEngine zope.pagetemplate-4.0.1/src/zope/pagetemplate/pagetemplatefile.py0000664000175000017500000001032312100036656025142 0ustar tseavertseaver############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Filesystem Page Template module Zope object encapsulating a Page Template from the filesystem. """ __all__ = ("PageTemplateFile",) import os import sys import re import logging from zope.pagetemplate.pagetemplate import PageTemplate DEFAULT_ENCODING = "utf-8" meta_pattern = re.compile( r'\s*\s*', re.IGNORECASE) def package_home(gdict): filename = gdict["__file__"] return os.path.dirname(filename) class PageTemplateFile(PageTemplate): "Zope wrapper for filesystem Page Template using TAL, TALES, and METAL" _v_last_read = 0 def __init__(self, filename, _prefix=None): path = self.get_path_from_prefix(_prefix) self.filename = os.path.join(path, filename) if not os.path.isfile(self.filename): raise ValueError("No such file", self.filename) def get_path_from_prefix(self, _prefix): if isinstance(_prefix, str): path = _prefix else: if _prefix is None: _prefix = sys._getframe(2).f_globals path = package_home(_prefix) return path def _prepare_html(self, text): match = meta_pattern.search(text) if match is not None: type_, encoding = match.groups() # TODO: Shouldn't / stripping # be in PageTemplate.__call__()? text = meta_pattern.sub("", text) else: type_ = None encoding = DEFAULT_ENCODING return unicode(text, encoding), type_ def _read_file(self): __traceback_info__ = self.filename f = open(self.filename, "rb") try: text = f.read(XML_PREFIX_MAX_LENGTH) except: f.close() raise type_ = sniff_type(text) if type_ == "text/xml": text += f.read() else: # For HTML, we really want the file read in text mode: f.close() f = open(self.filename) text = f.read() text, type_ = self._prepare_html(text) f.close() return text, type_ def _cook_check(self): if self._v_last_read and not __debug__: return __traceback_info__ = self.filename try: mtime = os.path.getmtime(self.filename) except OSError: mtime = 0 if self._v_program is not None and mtime == self._v_last_read: return text, type_ = self._read_file() self.pt_edit(text, type_) assert self._v_cooked if self._v_errors: logging.error('PageTemplateFile: Error in template %s: %s', self.filename, '\n'.join(self._v_errors)) return self._v_last_read = mtime def pt_source_file(self): return self.filename def __getstate__(self): raise TypeError("non-picklable object") XML_PREFIXES = [ "