zope.pagetemplate-4.0.1/ 0000775 0001750 0001750 00000000000 12100037354 015041 5 ustar tseaver tseaver zope.pagetemplate-4.0.1/setup.cfg 0000664 0001750 0001750 00000000073 12100037354 016662 0 ustar tseaver tseaver [egg_info]
tag_build =
tag_date = 0
tag_svn_revision = 0
zope.pagetemplate-4.0.1/buildout.cfg 0000664 0001750 0001750 00000001133 12100036656 017353 0 ustar tseaver tseaver [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-INFO 0000664 0001750 0001750 00000022634 12100037354 016145 0 ustar tseaver tseaver Metadata-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.ini 0000664 0001750 0001750 00000000270 12100036656 016357 0 ustar tseaver tseaver [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.py 0000664 0001750 0001750 00000010226 12100037203 016545 0 ustar tseaver tseaver ##############################################################################
#
# 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.py 0000664 0001750 0001750 00000007330 12100036656 017437 0 ustar tseaver tseaver ##############################################################################
#
# 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/ 0000775 0001750 0001750 00000000000 12100037354 015630 5 ustar tseaver tseaver zope.pagetemplate-4.0.1/src/zope.pagetemplate.egg-info/ 0000775 0001750 0001750 00000000000 12100037354 022746 5 ustar tseaver tseaver zope.pagetemplate-4.0.1/src/zope.pagetemplate.egg-info/top_level.txt 0000664 0001750 0001750 00000000005 12100037353 025472 0 ustar tseaver tseaver zope
zope.pagetemplate-4.0.1/src/zope.pagetemplate.egg-info/SOURCES.txt 0000664 0001750 0001750 00000005543 12100037354 024641 0 ustar tseaver tseaver CHANGES.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.pt zope.pagetemplate-4.0.1/src/zope.pagetemplate.egg-info/PKG-INFO 0000664 0001750 0001750 00000022634 12100037353 024051 0 ustar tseaver tseaver Metadata-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.txt 0000664 0001750 0001750 00000000001 12100037353 027013 0 ustar tseaver tseaver
zope.pagetemplate-4.0.1/src/zope.pagetemplate.egg-info/not-zip-safe 0000664 0001750 0001750 00000000001 12100037324 025171 0 ustar tseaver tseaver
zope.pagetemplate-4.0.1/src/zope.pagetemplate.egg-info/namespace_packages.txt 0000664 0001750 0001750 00000000005 12100037353 027273 0 ustar tseaver tseaver zope
zope.pagetemplate-4.0.1/src/zope.pagetemplate.egg-info/requires.txt 0000664 0001750 0001750 00000000267 12100037353 025352 0 ustar tseaver tseaver setuptools
zope.interface
zope.component
zope.security [untrustedpython]
zope.tales
zope.tal
zope.i18n
zope.i18nmessageid
zope.traversing
[test]
zope.testing
zope.proxy
zope.security zope.pagetemplate-4.0.1/src/zope/ 0000775 0001750 0001750 00000000000 12100037354 016605 5 ustar tseaver tseaver zope.pagetemplate-4.0.1/src/zope/__init__.py 0000664 0001750 0001750 00000000070 12100036656 020717 0 ustar tseaver tseaver __import__('pkg_resources').declare_namespace(__name__)
zope.pagetemplate-4.0.1/src/zope/pagetemplate/ 0000775 0001750 0001750 00000000000 12100037354 021255 5 ustar tseaver tseaver zope.pagetemplate-4.0.1/src/zope/pagetemplate/__init__.py 0000664 0001750 0001750 00000001230 12100036656 023366 0 ustar tseaver tseaver ##############################################################################
#
# 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.py 0000664 0001750 0001750 00000001572 12100036656 022417 0 ustar tseaver tseaver ##############################################################################
#
# 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.txt 0000664 0001750 0001750 00000002522 12100036656 024505 0 ustar tseaver tseaver =====================================
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.py 0000664 0001750 0001750 00000012565 12100036656 023767 0 ustar tseaver tseaver ##############################################################################
#
# 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/ 0000775 0001750 0001750 00000000000 12100037354 022417 5 ustar tseaver tseaver zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/output/ 0000775 0001750 0001750 00000000000 12100037354 023757 5 ustar tseaver tseaver zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/output/checkwithxmlheader.html 0000664 0001750 0001750 00000000072 12100036656 030513 0 ustar tseaver tseaver
Hello!
zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/output/globalsshadowlocals.html 0000664 0001750 0001750 00000000230 12100036656 030673 0 ustar tseaver tseaver
And thats da trooth.
zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/testpackage/ 0000775 0001750 0001750 00000000000 12100037354 024712 5 ustar tseaver tseaver zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/testpackage/__init__.py 0000664 0001750 0001750 00000000075 12100036656 027031 0 ustar tseaver tseaver #
# This file is necessary to make this directory a package.
zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/testpackage/content.py 0000664 0001750 0001750 00000001602 12100036656 026741 0 ustar tseaver tseaver ##############################################################################
#
# 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.pt 0000664 0001750 0001750 00000000053 12100036656 026233 0 ustar tseaver tseaver
zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/__init__.py 0000664 0001750 0001750 00000000075 12100036656 024536 0 ustar tseaver tseaver #
# This file is necessary to make this directory a package.
zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/test_htmltests.py 0000664 0001750 0001750 00000012507 12100036656 026070 0 ustar tseaver tseaver ##############################################################################
#
# 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.py 0000664 0001750 0001750 00000005763 12100036656 023765 0 ustar tseaver tseaver ##############################################################################
#
# 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.py 0000664 0001750 0001750 00000016430 12100036656 026655 0 ustar tseaver tseaver ##############################################################################
#
# 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.py 0000664 0001750 0001750 00000001431 12100036656 024466 0 ustar tseaver tseaver ##############################################################################
#
# 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/ 0000775 0001750 0001750 00000000000 12100037354 023556 5 ustar tseaver tseaver zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/input/checkwithxmlheader.html 0000664 0001750 0001750 00000000121 12100036656 030305 0 ustar tseaver tseaver
zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/input/globalsshadowlocals.html 0000664 0001750 0001750 00000000516 12100036656 030501 0 ustar tseaver tseaver
zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/input/stringexpression.html 0000664 0001750 0001750 00000000163 12100036656 030076 0 ustar tseaver tseaver
This is the title
zope.pagetemplate-4.0.1/src/zope/pagetemplate/tests/test_ptfile.py 0000664 0001750 0001750 00000015301 12100036656 025317 0 ustar tseaver tseaver ##############################################################################
#
# 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.py 0000664 0001750 0001750 00000007251 12100036656 024063 0 ustar tseaver tseaver ##############################################################################
#
# 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.py 0000664 0001750 0001750 00000006154 12100036656 025307 0 ustar tseaver tseaver ##############################################################################
#
# 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.txt 0000664 0001750 0001750 00000003202 12100036656 023254 0 ustar tseaver tseaver ==============
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.py 0000664 0001750 0001750 00000020757 12100036656 024316 0 ustar tseaver tseaver ##############################################################################
#
# 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.py 0000664 0001750 0001750 00000035614 12100036656 023111 0 ustar tseaver tseaver ##############################################################################
#
# 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.py 0000664 0001750 0001750 00000010323 12100036656 025142 0 ustar tseaver tseaver ##############################################################################
#
# 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 = [
"