Skip to content
This repository has been archived by the owner on May 13, 2020. It is now read-only.

Commit

Permalink
Update to zope.pagetemplate 3.6.x which provides a means of plugging …
Browse files Browse the repository at this point in the history
…in the template engine implementation via utility component.
  • Loading branch information
malthe committed Sep 21, 2011
1 parent f44fcbf commit 981c07f
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 163 deletions.
6 changes: 4 additions & 2 deletions CHANGES.txt
@@ -1,8 +1,10 @@
Changelog
=========

2.1.6 (unreleased)
~~~~~~~~~~~~~~~~~~
2.2 (unreleased)
~~~~~~~~~~~~~~~~
- Update implementation to use component-based template engine
configuration, plugging directly into the Zope Toolkit framework.

- Declare RepeatItem as public object with allowed subobjects
[leorochael]
Expand Down
5 changes: 3 additions & 2 deletions setup.py
@@ -1,6 +1,6 @@
from setuptools import setup, find_packages

version = '2.1.5'
version = '2.2-dev'

setup(name='five.pt',
version=version,
Expand All @@ -25,8 +25,9 @@
zip_safe=False,
install_requires=[
'setuptools',
'z3c.pt>=2.1.4',
'sourcecodegen>=0.6.14',
'z3c.pt>=2.1.4',
'zope.pagetemplate>=3.6.2',
],
entry_points="""
[z3c.autoinclude.plugin]
Expand Down
4 changes: 3 additions & 1 deletion src/five/pt/configure.zcml
Expand Up @@ -3,6 +3,8 @@
xmlns:five="http://namespaces.zope.org/five">

<include package="z3c.pt" />
<include package=".patches" />
<include package=".engine" />

<utility component=".engine.Program" />

</configure>
108 changes: 108 additions & 0 deletions src/five/pt/engine.py
@@ -0,0 +1,108 @@
"""Patch legacy template classes.
We patch the ``TALInterpreter`` class as well as the cook-method on
the pagetemplate base class (which produces the input for the TAL
interpreter).
"""

import sys

from zope.tal.talinterpreter import TALInterpreter
from zope.interface import implements
from zope.interface import classProvides

from zope.pagetemplate.pagetemplate import PageTemplate
from zope.pagetemplate.interfaces import IPageTemplateEngine
from zope.pagetemplate.interfaces import IPageTemplateProgram

from z3c.pt.pagetemplate import PageTemplate as ChameleonPageTemplate
from z3c.pt.pagetemplate import PageTemplateFile as ChameleonPageTemplateFile

from AccessControl.SecurityInfo import ClassSecurityInfo
from App.class_init import InitializeClass
from Products.PageTemplates.Expressions import getEngine
from Products.PageTemplates import ZRPythonExpr

from chameleon.tales import StringExpr
from chameleon.tales import NotExpr
from chameleon.tal import RepeatDict

from z3c.pt.expressions import PythonExpr

from .expressions import PathExpr
from .expressions import TrustedPathExpr
from .expressions import ProviderExpr
from .expressions import NocallExpr
from .expressions import ExistsExpr
from .expressions import UntrustedPythonExpr


# Declare Chameleon's repeat dictionary public
RepeatDict.security = ClassSecurityInfo()
RepeatDict.security.declareObjectPublic()
RepeatDict.__allow_access_to_unprotected_subobjects__ = True

InitializeClass(RepeatDict)


class Program(object):
implements(IPageTemplateProgram)
classProvides(IPageTemplateEngine)

# Zope 2 Page Template expressions
secure_expression_types = {
'python': UntrustedPythonExpr,
'string': StringExpr,
'not': NotExpr,
'exists': ExistsExpr,
'path': PathExpr,
'provider': ProviderExpr,
'nocall': NocallExpr,
}

# Zope 3 Page Template expressions
expression_types = {
'python': PythonExpr,
'string': StringExpr,
'not': NotExpr,
'exists': ExistsExpr,
'path': TrustedPathExpr,
'provider': ProviderExpr,
'nocall': NocallExpr,
}

extra_builtins = {
'modules': ZRPythonExpr._SecureModuleImporter()
}

def __init__(self, template):
self.template = template

def __call__(self, context, macros, tal=True, **options):
if tal is False:
return self.template.body

# Swap out repeat dictionary for Chameleon implementation
# and store wrapped dictionary in new variable -- this is
# in turn used by the secure Python expression
# implementation whenever a 'repeat' symbol is found
kwargs = context.vars
kwargs['wrapped_repeat'] = kwargs['repeat']
kwargs['repeat'] = RepeatDict(context.repeat_vars)

return self.template.render(**kwargs)

@classmethod
def cook(cls, source_file, text, engine, content_type):
if engine is getEngine():
expression_types = cls.secure_expression_types
else:
expression_types = cls.expression_types

template = ChameleonPageTemplate(
text, filename=source_file, keep_body=True,
expression_types=expression_types,
encoding='utf-8', extra_builtins=cls.extra_builtins,
)

return cls(template), template.macros
139 changes: 0 additions & 139 deletions src/five/pt/patches.py

This file was deleted.

Expand Up @@ -26,8 +26,7 @@ def test_pagetemplate(self):

# test arguments
template.write(open(os.path.join(path, "options.pt")).read())
self.assertTrue('Hello world' in template(
greeting='Hello world'))
self.assertTrue('Hello world' in template(greeting='Hello world'))

def test_pagetemplatefile(self):
from Products.PageTemplates.PageTemplateFile import PageTemplateFile
Expand Down
24 changes: 7 additions & 17 deletions src/five/pt/tests/test_persistenttemplate.py
Expand Up @@ -159,23 +159,13 @@ def test_pt_render_with_macro(self):

def test_avoid_recompilation(self):
template = self._makeOne('foo', simple_i18n)
macro_template = self._makeOne('macro_outer', macro_outer)
# templates are only compiled after the first call
self.assertEqual(getattr(template, '_v_template', _marker), _marker)
template()
# or the first fetching of macros
self.assertEqual(getattr(macro_template, '_v_template', _marker),
_marker)
macro_template.macros

template_compiled = template._v_program
macro_template_compiled = macro_template._v_program

# but they should not be recompiled afterwards
template()
macro_template.macros
self.assertTrue(template_compiled is template._v_program)
self.assertTrue(macro_template_compiled is macro_template._v_program)

# Template is already cooked
program = template._v_program
template.pt_render({})

# The program does not change
self.assertEqual(program, template._v_program)

def test_repeat_object_security(self):
template = self._makeOne('foo', repeat_object)
Expand Down

0 comments on commit 981c07f

Please sign in to comment.