Commit e5d71456 authored by Andreas Jung's avatar Andreas Jung

getting rid of the old ZPT implementation

parent c8f81acd
##############################################################################
#
# Copyright (c) 2002 Zope Corporation 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
#
##############################################################################
"""Defer and Lazy expression handler
defer expressions can be usesd for a design pattern called deferred evaluation.
Example:
<div tal:define="xis defer:string:x is $x">
<p tal:repeat="x python:range(3)"
tal:content="xis"></p>
</div>
Output:
<div>
<p>x is 0</p>
<p>x is 1</p>
<p>x is 2</p>
</div>
A lazy expressions is implemented in a similar way but has a different result. While
a defer expression is evaluated every time it is used according to its context a lazy
expression is evaluted only the first time it is used. Lazy expression are known
under the name lazy initialization of variables, too.
A common use case for a lazy expression is a lazy binding of a costly expression.
While one could call an expression only when it's required it makes sense to define
it only one time when it could be used multiple times.
Example
<div tal:define="lazyvar lazy:here/suckMyCPU">
<div tal:condition="foo" tal:content="lazyvar" />
<div tal:condition="bar" tal:content="lazyvar" />
<div tal:condition"python: not (foo or bar)">...</div>
</div>
"""
_marker = object()
# defer expression
class DeferWrapper:
"""Wrapper for defer: expression
"""
def __init__(self, expr, econtext):
self._expr = expr
self._econtext = econtext
def __str__(self):
return str(self())
def __call__(self):
return self._expr(self._econtext)
class DeferExpr:
"""defer: expression handler for deferred evaluation of the context
"""
def __init__(self, name, expr, compiler):
self._s = expr = expr.lstrip()
self._c = compiler.compile(expr)
def __call__(self, econtext):
return DeferWrapper(self._c, econtext)
def __repr__(self):
return 'defer:%s' % `self._s`
# lazy expression
class LazyWrapper(DeferWrapper):
"""Wrapper for lazy: expression
"""
def __init__(self, expr, econtext):
DeferWrapper.__init__(self, expr, econtext)
self._result = _marker
def __call__(self):
r = self._result
if r is _marker:
self._result = r = self._expr(self._econtext)
return r
class LazyExpr(DeferExpr):
"""lazy: expression handler for lazy initialization of expressions
"""
def __call__(self, econtext):
return LazyWrapper(self._c, econtext)
def __repr__(self):
return 'lazy:%s' % `self._s`
This diff is collapsed.
##############################################################################
#
# Copyright (c) 2002 Zope Corporation 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.
#
##############################################################################
"""Global Translation Service for providing I18n to Page Templates.
$Id$
"""
import re
import Products.Five.i18n
from DocumentTemplate.DT_Util import ustr
from TAL.TALDefs import NAME_RE
class DummyTranslationService:
"""Translation service that doesn't know anything about translation."""
def translate(self, domain, msgid, mapping=None,
context=None, target_language=None, default=None):
def repl(m, mapping=mapping):
return ustr(mapping[m.group(m.lastindex)])
cre = re.compile(r'\$(?:(%s)|\{(%s)\})' % (NAME_RE, NAME_RE))
return cre.sub(repl, default or msgid)
# XXX Not all of Zope2.I18n.ITranslationService is implemented.
#
# As of Five 1.1, we're by default using Zope 3 Message Catalogs for
# translation, but we allow fallback translation services such as PTS
# and Localizer
#
Products.Five.i18n._fallback_translation_service = DummyTranslationService()
fiveTranslationService = Products.Five.i18n.FiveTranslationService()
def getGlobalTranslationService():
return fiveTranslationService
def setGlobalTranslationService(newservice):
oldservice, Products.Five.i18n._fallback_translation_service = \
Products.Five.i18n._fallback_translation_service, newservice
return oldservice
Page Template history
This file contains change information for previous versions of
PageTemplates. Change information for the current release can be found
in the file CHANGES.txt.
Version 1.4.1
Bugs Fixed
- Tracebacks were often truncated.
- __bobo_traverse__ objects, such as the root, triggered
security incorrectly when traversed.
- If a PageTemplate was owned by a missing user, or one with
insufficient permissions, the editing form broke.
- PageTemplateFiles didn't bind 'user'.
- There was no help.
Version 1.4.0
Features Added
- ZPTs are now cache-enabled
- Added property sheet to ZPT
Bugs Fixed
- Expressions with embedded newlines were broken
- History comparison tried to expand macros
- Iterator exceptions weren't converted
- 'Unauthorized' exception couldn't be handled by on-error
Version 1.3.3
Features Added
- Allow any false value in tal:repeat to act as an empty sequence.
- manage_addPageTemplate accepts optional title and text
arguments, and returns the new object if REQUEST is None.
Bugs Fixed
- The various *Python modules failed to import CompilerError.
- Security machinery changes in Zope 2.4 broke ZRPythonExpr
Version 1.3.2
Features Added
- Adopted Zope-style CHANGES.txt and HISTORY.txt
- Improved execution performance
- nocall: paths are back in.
Bugs Fixed
- TALES expressions let any string exception through, not just
Redirect and Unauthorized.
Version 1.3.1
Features Added
- Added error logging to PageTemplateFiles.
- Refactored PythonExpr, and added support for Zope 2.4
Version 1.3.0
Features Added
- New builtin variables 'default', 'user', and 'attrs'.
- Removed path modifiers.
- Added '|' operator for paths.
- Tweaked parameters passed when calling DTML.
- Expression types now have corresponding builtin functions in
Python expressions.
Version 1.2.1
Bug Fixed
- 'repeat' variable access was broken.
Version 1.2.0
Features Added
- Depends on the new ZTUtils package, which adds batching and
tree widget capabilities.
- Path expressions now have optional path modifiers. These
appear in parenthesis before the path, and include 'if',
'exists', and 'nocall'.
- Changed nocall: and exists: expressions types into path modifiers.
- The 'if' path modifier can cancel any TAL action.
Version 1.1.0
Features Added
- Changed tests to match TAL's omitted attributes.
Version 1.0.0
- Various minor bugs fixed
Version 1.0.0b1
- All functionality described in the Project Wiki is implemented
##############################################################################
#
# Copyright (c) 2002 Zope Corporation 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.
"""
__version__='$Revision: 1.31 $'[11:-2]
import sys, types
from TAL.TALParser import TALParser
from TAL.HTMLTALParser import HTMLTALParser
from TAL.TALGenerator import TALGenerator
# Do not use cStringIO here! It's not unicode aware. :(
from TAL.TALInterpreter import TALInterpreter, FasterStringIO
from Expressions import getEngine
from ExtensionClass import Base
from ComputedAttribute import ComputedAttribute
class PageTemplate(Base):
"Page Templates using TAL, TALES, and METAL"
content_type = 'text/html'
expand = 0
_v_errors = ()
_v_warnings = ()
_v_program = None
_v_macros = None
_v_cooked = 0
id = '(unknown)'
_text = ''
_error_start = '<!-- Page Template Diagnostics'
def StringIO(self):
# Third-party products wishing to provide a full Unicode-aware
# StringIO can do so by monkey-patching this method.
return FasterStringIO()
def macros(self):
return self.pt_macros()
macros = ComputedAttribute(macros, 1)
def pt_edit(self, text, content_type):
if content_type:
self.content_type = str(content_type)
if hasattr(text, 'read'):
text = text.read()
charset = getattr(self, 'management_page_charset', None)
if charset and type(text) == types.StringType:
try:
unicode(text,'us-ascii')
except UnicodeDecodeError:
text = unicode(text, charset)
self.write(text)
def pt_getContext(self):
c = {'template': self,
'options': {},
'nothing': None,
'request': None,
'modules': ModuleImporter,
}
parent = getattr(self, 'aq_parent', None)
if parent is not None:
c['here'] = parent
c['context'] = parent
c['container'] = self.aq_inner.aq_parent
while parent is not None:
self = parent
parent = getattr(self, 'aq_parent', None)
c['root'] = self
return c
def pt_render(self, source=0, extra_context={}):
"""Render this Page Template"""
if not self._v_cooked:
self._cook()
__traceback_supplement__ = (PageTemplateTracebackSupplement, self)
if self._v_errors:
e = str(self._v_errors)
raise PTRuntimeError, (
'Page Template %s has errors: %s' % (self.id, e))
output = self.StringIO()
c = self.pt_getContext()
c.update(extra_context)
TALInterpreter(self._v_program, self._v_macros,
getEngine().getContext(c),
output,
tal=not source, strictinsert=0)()
return output.getvalue()
def __call__(self, *args, **kwargs):
if not kwargs.has_key('args'):
kwargs['args'] = args
return self.pt_render(extra_context={'options': kwargs})
def pt_errors(self):
if not self._v_cooked:
self._cook()
err = self._v_errors
if err:
return err
if not self.expand: return
try:
self.pt_render(source=1)
except:
return ('Macro expansion failed', '%s: %s' % sys.exc_info()[:2])
def pt_warnings(self):
if not self._v_cooked:
self._cook()
return self._v_warnings
def pt_macros(self):
if not self._v_cooked:
self._cook()
if self._v_errors:
__traceback_supplement__ = (PageTemplateTracebackSupplement, self)
raise PTRuntimeError, (
'Page Template %s has errors: %s' % (
self.id,
self._v_errors
))
return self._v_macros
def pt_source_file(self):
return None # Unknown.
def write(self, text):
assert type(text) in types.StringTypes
if text[:len(self._error_start)] == self._error_start:
errend = text.find('-->')
if errend >= 0:
text = text[errend + 4:]
if self._text != text:
self._text = text
self._cook()
def read(self):
self._cook_check()
if not self._v_errors:
if not self.expand:
return self._text
try:
return self.pt_render(source=1)
except:
return ('%s\n Macro expansion failed\n %s\n-->\n%s' %
(self._error_start, "%s: %s" % sys.exc_info()[:2],
self._text) )
return ('%s\n %s\n-->\n%s' % (self._error_start,
'\n '.join(self._v_errors),
self._text))
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.
"""
source_file = self.pt_source_file()
if self.html():
gen = TALGenerator(getEngine(), xml=0, source_file=source_file)
parser = HTMLTALParser(gen)
else:
gen = TALGenerator(getEngine(), source_file=source_file)
parser = TALParser(gen)
self._v_errors = ()
try:
parser.parseString(self._text)
self._v_program, self._v_macros = parser.getCode()
except:
self._v_errors = ["Compilation failed",
"%s: %s" % sys.exc_info()[:2]]
self._v_warnings = parser.getWarnings()
self._v_cooked = 1
def html(self):
if not hasattr(getattr(self, 'aq_base', self), 'is_html'):
return self.content_type == 'text/html'
return self.is_html
class _ModuleImporter:
def __getitem__(self, module):
mod = __import__(module)
path = module.split('.')
for name in path[1:]:
mod = getattr(mod, name)
return mod
ModuleImporter = _ModuleImporter()
class PTRuntimeError(RuntimeError):
'''The Page Template has template errors that prevent it from rendering.'''
pass
class PageTemplateTracebackSupplement:
#__implements__ = ITracebackSupplement
def __init__(self, pt):
self.object = pt
w = pt.pt_warnings()
e = pt.pt_errors()
if e:
w = list(w) + list(e)
self.warnings = w
##############################################################################
#
# Copyright (c) 2002 Zope Corporation 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.
"""
__version__ = '$Revision: 1.30 $'[11:-2]
import os, AccessControl
from Globals import package_home, DevelopmentMode
from zLOG import LOG, ERROR
from Shared.DC.Scripts.Script import Script
from Shared.DC.Scripts.Signature import FuncCode
from AccessControl import getSecurityManager
from OFS.Traversable import Traversable
from PageTemplate import PageTemplate
from Expressions import SecureModuleImporter
from ComputedAttribute import ComputedAttribute
from Acquisition import aq_parent, aq_inner
from App.config import getConfiguration
from OFS.SimpleItem import Item_w__name__
class PageTemplateFile(Item_w__name__, Script, PageTemplate, Traversable):
"Zope wrapper for filesystem Page Template using TAL, TALES, and METAL"
meta_type = 'Page Template (File)'
func_defaults = None
func_code = FuncCode((), 0)
_v_last_read = 0
# needed by App.class_init.default__class_init__, often imported
# using the alias Globals.InitializeClass
_need__name__ = 1
_default_bindings = {'name_subpath': 'traverse_subpath'}
security = AccessControl.ClassSecurityInfo()
security.declareProtected('View management screens',
'read', 'document_src')
def __init__(self, filename, _prefix=None, **kw):
self.ZBindings_edit(self._default_bindings)
if _prefix is None:
_prefix = getConfiguration().softwarehome
elif not isinstance(_prefix, str):
_prefix = package_home(_prefix)
name = kw.get('__name__')
basepath, ext = os.path.splitext(filename)
if name:
self._need__name__ = 0
self.__name__ = name
else:
self.__name__ = os.path.basename(basepath)
if not ext:
# XXX This is pretty bogus, but can't be removed since
# it's been released this way.
filename = filename + '.zpt'
self.filename = os.path.join(_prefix, filename)
def getId(self):
"""return the ID of this object"""
return self.__name__
def pt_getContext(self):
root = self.getPhysicalRoot()
context = self._getContext()
c = {'template': self,
'here': context,
'context': context,
'container': self._getContainer(),
'nothing': None,
'options': {},
'root': root,
'request': getattr(root, 'REQUEST', None),
'modules': SecureModuleImporter,
}
return c
def _exec(self, bound_names, args, kw):
"""Call a Page Template"""
self._cook_check()
if not kw.has_key('args'):
kw['args'] = args
bound_names['options'] = kw
try:
response = self.REQUEST.RESPONSE
if not response.headers.has_key('content-type'):
response.setHeader('content-type', self.content_type)
except AttributeError:
pass
# Execute the template in a new security context.
security = getSecurityManager()
bound_names['user'] = security.getUser()
security.addContext(self)
try:
return self.pt_render(extra_context=bound_names)
finally:
security.removeContext(self)
def pt_macros(self):
self._cook_check()
return PageTemplate.pt_macros(self)
def pt_source_file(self):
"""Returns a file name to be compiled into the TAL code."""
return self.__name__ # Don't reveal filesystem paths
def _cook_check(self):
if self._v_last_read and not DevelopmentMode:
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
f = open(self.filename, "rb")
try:
text = f.read(XML_PREFIX_MAX_LENGTH)
except:
f.close()
raise
t = sniff_type(text)
if t != "text/xml":
# For HTML, we really want the file read in text mode:
f.close()
f = open(self.filename)
text = ''
text += f.read()
f.close()
self.pt_edit(text, t)
self._cook()
if self._v_errors:
LOG('PageTemplateFile', ERROR, 'Error in template',
'\n'.join(self._v_errors))
return
self._v_last_read = mtime
def document_src(self, REQUEST=None, RESPONSE=None):
"""Return expanded document source."""
if RESPONSE is not None:
# Since _cook_check() can cause self.content_type to change,
# we have to make sure we call it before setting the
# Content-Type header.
self._cook_check()
RESPONSE.setHeader('Content-Type', 'text/plain')
return self.read()
def _get__roles__(self):
imp = getattr(aq_parent(aq_inner(self)),
'%s__roles__' % self.__name__)
if hasattr(imp, '__of__'):
return imp.__of__(self)
return imp
__roles__ = ComputedAttribute(_get__roles__, 1)
def getOwner(self, info=0):
"""Gets the owner of the executable object.
This method is required of all objects that go into
the security context stack. Since this object came from the
filesystem, it is owned by no one managed by Zope.
"""
return None
def __getstate__(self):
from ZODB.POSException import StorageError
raise StorageError, ("Instance of AntiPersistent class %s "
"cannot be stored." % self.__class__.__name__)
XML_PREFIXES = [
"<?xml", # ascii, utf-8
"\xef\xbb\xbf<?xml", # utf-8 w/ byte order mark
"\0<\0?\0x\0m\0l", # utf-16 big endian
"<\0?\0x\0m\0l\0", # utf-16 little endian
"\xfe\xff\0<\0?\0x\0m\0l", # utf-16 big endian w/ byte order mark
"\xff\xfe<\0?\0x\0m\0l\0", # utf-16 little endian w/ byte order mark
]
XML_PREFIX_MAX_LENGTH = max(map(len, XML_PREFIXES))
def sniff_type(text):
for prefix in XML_PREFIXES:
if text.startswith(prefix):
return "text/xml"
return None
See <a href="http://dev.zope.org/Wikis/DevSite/Projects/ZPT">the
ZPT project Wiki</a> for more information about Page Templates, or
<a href="http://www.zope.org/Members/4am/ZPT">the download page</a>
for installation instructions and the most recent version of the software.
This Product requires the TAL and ZTUtils packages to be installed in
your Python path (not Products). See the links above for more information.
##############################################################################
#
# Copyright (c) 2002 Zope Corporation 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
#
##############################################################################
"""TALES
An implementation of a generic TALES engine
"""
__version__='$Revision: 1.39 $'[11:-2]
import re, sys, ZTUtils
from weakref import ref
from MultiMapping import MultiMapping
from DocumentTemplate.DT_Util import ustr
from GlobalTranslationService import getGlobalTranslationService
from zExceptions import Unauthorized
StringType = type('')
NAME_RE = r"[a-zA-Z][a-zA-Z0-9_]*"
_parse_expr = re.compile(r"(%s):" % NAME_RE).match
_valid_name = re.compile('%s$' % NAME_RE).match
class TALESError(Exception):
"""Error during TALES expression evaluation"""
class Undefined(TALESError):
'''Exception raised on traversal of an undefined path'''
class RegistrationError(Exception):
'''TALES Type Registration Error'''
class CompilerError(Exception):
'''TALES Compiler Error'''
class Default:
'''Retain Default'''
Default = Default()
class SafeMapping(MultiMapping):
'''Mapping with security declarations and limited method exposure.
Since it subclasses MultiMapping, this class can be used to wrap
one or more mapping objects. Restricted Python code will not be
able to mutate the SafeMapping or the wrapped mappings, but will be
able to read any value.
'''
__allow_access_to_unprotected_subobjects__ = 1
push = pop = None
_push = MultiMapping.push
_pop = MultiMapping.pop
class Iterator(ZTUtils.Iterator):
def __init__(self, name, seq, context):
ZTUtils.Iterator.__init__(self, seq)
self.name = name
self._context_ref = ref(context)
def next(self):
if ZTUtils.Iterator.next(self):
context = self._context_ref()
if context is not None:
context.setLocal(self.name, self.item)
return 1
return 0
class ErrorInfo:
"""Information about an exception passed to an on-error handler."""
__allow_access_to_unprotected_subobjects__ = 1
def __init__(self, err, position=(None, None)):
if isinstance(err, Exception):
self.type = err.__class__
self.value = err
else:
self.type = err
self.value = None
self.lineno = position[0]
self.offset = position[1]
class Engine:
'''Expression Engine
An instance of this class keeps a mutable collection of expression
type handlers. It can compile expression strings by delegating to
these handlers. It can provide an expression Context, which is
capable of holding state and evaluating compiled expressions.
'''
Iterator = Iterator
def __init__(self, Iterator=None):
self.types = {}
if Iterator is not None:
self.Iterator = Iterator
def registerType(self, name, handler):
if not _valid_name(name):
raise RegistrationError, 'Invalid Expression type "%s".' % name
types = self.types
if types.has_key(name):
raise RegistrationError, (
'Multiple registrations for Expression type "%s".' %
name)
types[name] = handler
def getTypes(self):
return self.types
def compile(self, expression):
m = _parse_expr(expression)
if m:
type = m.group(1)
expr = expression[m.end():]
else:
type = "standard"
expr = expression
try:
handler = self.types[type]
except KeyError:
raise CompilerError, (
'Unrecognized expression type "%s".' % type)
return handler(type, expr, self)
def getContext(self, contexts=None, **kwcontexts):
if contexts is not None:
if kwcontexts:
kwcontexts.update(contexts)
else:
kwcontexts = contexts
return Context(self, kwcontexts)
def getCompilerError(self):
return CompilerError
class Context:
'''Expression Context
An instance of this class holds context information that it can
use to evaluate compiled expressions.
'''
_context_class = SafeMapping
position = (None, None)
source_file = None
def __init__(self, compiler, contexts):
self._compiler = compiler
self.contexts = contexts
contexts['nothing'] = None
contexts['default'] = Default
self.repeat_vars = rv = {}
# Wrap this, as it is visible to restricted code
contexts['repeat'] = rep = self._context_class(rv)
contexts['loop'] = rep # alias
self.global_vars = gv = contexts.copy()
self.local_vars = lv = {}
self.vars = self._context_class(gv, lv)
# Keep track of what needs to be popped as each scope ends.
self._scope_stack = []
def getCompiler(self):
return self._compiler
def beginScope(self):
self._scope_stack.append([self.local_vars.copy()])
def endScope(self):
scope = self._scope_stack.pop()
self.local_vars = lv = scope[0]
v = self.vars
v._pop()
v._push(lv)
# Pop repeat variables, if any
i = len(scope) - 1
while i:
name, value = scope[i]
if value is None:
del self.repeat_vars[name]
else:
self.repeat_vars[name] = value
i = i - 1
def setLocal(self, name, value):
self.local_vars[name] = value
def setGlobal(self, name, value):
self.global_vars[name] = value
def setRepeat(self, name, expr):
expr = self.evaluate(expr)
if not expr:
return self._compiler.Iterator(name, (), self)
it = self._compiler.Iterator(name, expr, self)
old_value = self.repeat_vars.get(name)
self._scope_stack[-1].append((name, old_value))
self.repeat_vars[name] = it
return it
def evaluate(self, expression,
isinstance=isinstance, StringType=StringType):
if isinstance(expression, StringType):
expression = self._compiler.compile(expression)
__traceback_supplement__ = (
TALESTracebackSupplement, self, expression)
return expression(self)
evaluateValue = evaluate
evaluateBoolean = evaluate
def evaluateText(self, expr):
text = self.evaluate(expr)
if text is Default or text is None:
return text
return ustr(text)
def evaluateStructure(self, expr):
return self.evaluate(expr)
evaluateStructure = evaluate
def evaluateMacro(self, expr):
# XXX Should return None or a macro definition
return self.evaluate(expr)
evaluateMacro = evaluate
def createErrorInfo(self, err, position):
return ErrorInfo(err, position)
def getDefault(self):
return Default
def setSourceFile(self, source_file):
self.source_file = source_file
def setPosition(self, position):
self.position = position
def translate(self, domain, msgid, mapping=None,
context=None, target_language=None, default=None):
if context is None:
context = self.contexts.get('here')
return getGlobalTranslationService().translate(
domain, msgid, mapping=mapping,
context=context,
default=default,
target_language=target_language)
class TALESTracebackSupplement:
"""Implementation of ITracebackSupplement"""
def __init__(self, context, expression):
self.context = context
self.source_url = context.source_file
self.line = context.position[0]
self.column = context.position[1]
self.expression = repr(expression)
def getInfo(self, as_html=0):
import pprint
from cgi import escape
data = self.context.contexts.copy()
try:
s = pprint.pformat(data)
except Unauthorized, e:
s = ' - %s: %s' % (getattr(e, '__class__', type(e)), e)
if as_html:
s = escape(s)
return s
if not as_html:
return ' - Names:\n %s' % s.replace('\n', '\n ')
else:
return '<b>Names:</b><pre>%s</pre>' % (escape(s))
class SimpleExpr:
'''Simple example of an expression type handler'''
def __init__(self, name, expr, engine):
self._name = name
self._expr = expr
def __call__(self, econtext):
return self._name, self._expr
def __repr__(self):
return '<SimpleExpr %s %s>' % (self._name, `self._expr`)
##############################################################################
#
# Copyright (c) 2002 Zope Corporation 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
#
##############################################################################
"""Old Zope-specific Python Expression Handler
Handler for Python expressions, using the pre-Python 2.1 restriction
machinery from PythonScripts.
"""
__version__='$Revision: 1.8 $'[11:-2]
from AccessControl import getSecurityManager
from Products.PythonScripts.Guarded import _marker, \
GuardedBlock, theGuard, safebin, WriteGuard, ReadGuard, UntupleFunction
from TALES import CompilerError
from PythonExpr import PythonExpr
class PythonExpr(PythonExpr):
def __init__(self, name, expr, engine):
self.expr = expr = expr.strip().replace('\n', ' ')
blk = GuardedBlock('def f():\n return \\\n %s\n' % expr)
if blk.errors:
raise CompilerError, ('Python expression error:\n%s' %
'\n'.join(blk.errors) )
guards = {'$guard': theGuard, '$write_guard': WriteGuard,
'$read_guard': ReadGuard, '__debug__': __debug__}
self._f = UntupleFunction(blk.t, guards, __builtins__=safebin)
self._get_used_names()
class _SecureModuleImporter:
__allow_access_to_unprotected_subobjects__ = 1
def __getitem__(self, module):
mod = safebin['__import__'](module)
path = module.split('.')
for name in path[1:]:
mod = getattr(mod, name)
return mod
from DocumentTemplate.DT_Util import TemplateDict, InstanceDict
def validate(accessed, container, name, value, dummy):
return getSecurityManager().validate(accessed, container, name, value)
def call_with_ns(f, ns, arg=1):
td = TemplateDict()
td.validate = validate
td.this = ns['here']
td._push(ns['request'])
td._push(InstanceDict(td.this, td))
td._push(ns)
try:
if arg==2:
return f(None, td)
else:
return f(td)
finally:
td._pop(3)
##############################################################################
#
# Copyright (c) 2002 Zope Corporation 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
#
##############################################################################
"""Zope-specific Python Expression Handler
Handler for Python expressions that uses the RestrictedPython package.
"""
__version__='$Revision: 1.11 $'[11:-2]
from AccessControl import safe_builtins
from AccessControl.ZopeGuards import guarded_getattr, get_safe_globals
from RestrictedPython import compile_restricted_eval
from TALES import CompilerError
from PythonExpr import PythonExpr
class PythonExpr(PythonExpr):
_globals = get_safe_globals()
_globals['_getattr_'] = guarded_getattr
_globals['__debug__' ] = __debug__
def __init__(self, name, expr, engine):
self.expr = expr = expr.strip().replace('\n', ' ')
code, err, warn, use = compile_restricted_eval(expr, str(self))
if err:
raise CompilerError, ('Python expression error:\n%s' %
'\n'.join(err) )
self._f_varnames = use.keys()
self._code = code
def __call__(self, econtext):
__traceback_info__ = self.expr
code = self._code
g = self._bind_used_names(econtext)
g.update(self._globals)
return eval(code, g, {})
class _SecureModuleImporter:
__allow_access_to_unprotected_subobjects__ = 1
def __getitem__(self, module):
mod = safe_builtins['__import__'](module)
path = module.split('.')
for name in path[1:]:
mod = getattr(mod, name)
return mod
from DocumentTemplate.DT_Util import TemplateDict, InstanceDict
from AccessControl.DTML import RestrictedDTML
class Rtd(RestrictedDTML, TemplateDict):
this = None
def call_with_ns(f, ns, arg=1):
td = Rtd()
# prefer 'context' to 'here'; fall back to 'None'
this = ns.get('context', ns.get('here'))
td.this = this
request = ns.get('request', {})
td._push(request)
td._push(InstanceDict(td.this, td))
td._push(ns)
try:
if arg==2:
return f(None, td)
else:
return f(td)
finally:
td._pop(3)
......@@ -33,6 +33,17 @@ button.
<input type="file" name="file" size="25" value="" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-optional">
Encoding
</div>
</td>
<td align="left" valign="top">
<input type="text" name="encoding" size="25" value="utf-8" />
<em>(only used for non-XML and non-HTML content)</em>
</td>
</tr>
<tr>
<td align="left" valign="top">
</td>
......
<h1 tal:replace="structure here/manage_page_header">Header</h1>
<h1 tal:replace="structure context/manage_page_header">Header</h1>
<h2 tal:define="manage_tabs_message options/manage_tabs_message | nothing"
tal:replace="structure here/manage_tabs">Tabs</h2>
tal:replace="structure context/manage_tabs">Tabs</h2>
<tal:block define="global body request/other/text | request/form/text
| here/read" />
| context/read" />
<form action="" method="post" tal:attributes="action request/URL1">
<input type="hidden" name=":default_method" value="pt_changePrefs">
<table width="100%" cellspacing="0" cellpadding="2" border="0">
......@@ -15,57 +15,68 @@
</td>
<td align="left" valign="middle">
<input type="text" name="title" size="40"
tal:attributes="value request/title | here/title" />
tal:attributes="value request/title | context/title" />
</td>
<td align="left" valign="middle">
<div class="form-optional">
Content-Type
</div>
<div class="form-label"> Last Modified </div>
</td>
<td align="left" valign="middle">
<input type="text" name="content_type" size="14"
tal:attributes="value request/content_type | here/content_type" />
<div class="form-text"
tal:content="python:context.bobobase_modification_time().strftime('%Y-%m-%d %I:%M %p')">1/1/2000
</div>
</td>
</tr>
<tr>
<td align="left" valign="middle">
<div class="form-label">
Last Modified
Content-Type
</div>
</td>
<td align="left" valign="middle">
<div class="form-text"
tal:content="python:here.bobobase_modification_time().strftime('%Y-%m-%d %I:%M %p')">1/1/2000
</div>
<select name="content_type" size="1" tal:define="ct context/content_type">
<option value="text/html" tal:attributes="SELECTED python: ct == 'text/html'">text/html</option>
<option value="text/xml" tal:attributes="SELECTED python: ct == 'text/xml'">text/xml</option>
</select>
</td>
<td align="left" valign="top" colspan=2>
<a href="source.html" tal:condition="here/html">Browse HTML source</a>
<a href="source.xml" tal:condition="not:here/html">Browse XML source</a>
<a href="source.html" tal:condition="context/html">Browse HTML source</a>
<a href="source.xml" tal:condition="not:context/html">Browse XML source</a>
<br>
<input type="hidden" name="expand:int:default" value="0">
<input type="checkbox" value="1" name="expand:int"
tal:attributes="checked request/expand | here/expand">
tal:attributes="checked request/expand | context/expand">
Expand macros when editing
</td>
</tr>
<tr tal:define="errors here/pt_errors" tal:condition="errors">
<tal:block define="global body python:here.document_src({'raw':1})"/>
<tr>
<td align="left" valign="middle" class="form-label">Encoding</td>
<td>
<input type="text" readonly name="encoding" tal:attributes="value context/pt_encoding"/>
</td>
</tr>
<!-- XXX: check if 'None' is a proper argument for 'namespace' -->
<tr tal:define="errors python: context.pt_errors(None)" tal:condition="errors">
<tal:block define="global body python:context.document_src({'raw':1})"/>
<td align="left" valign="middle" class="form-label">Errors</td>
<td align="left" valign="middle" style="background-color: #FFDDDD"
colspan="3">
<pre tal:content="python:modules['string'].join(errors, '\n')">errors</pre>
<pre tal:content="python: '\n'.join(errors)">errors</pre>
</td>
</tr>
<tr tal:define="warnings here/pt_warnings" tal:condition="warnings">
<tr tal:define="warnings context/pt_warnings" tal:condition="warnings">
<td align="left" valign="middle" class="form-label">Warnings</td>
<td align="left" valign="middle" style="background-color: #FFEEDD"
colspan="3">
<pre tal:content="python:modules['string'].join(warnings, '\n')">errors</pre>
<pre tal:content="python: '\n'.join(warnings)">errors</pre>
</td>
</tr>
<tr>
<td align="left" valign="top" colspan="4"
tal:define="width request/dtpref_cols | string:100%;
......@@ -85,8 +96,8 @@
<tr>
<td align="left" valign="top" colspan="4">
<div class="form-element">
<em tal:condition="here/wl_isLocked">Locked by WebDAV</em>
<input tal:condition="not:here/wl_isLocked"
<em tal:condition="context/wl_isLocked">Locked by WebDAV</em>
<input tal:condition="not:context/wl_isLocked"
class="form-element" type="submit"
name="pt_editAction:method" value="Save Changes">
&nbsp;&nbsp;
......@@ -101,10 +112,10 @@
</form>
<p class="form-help">
You can upload the text for <span tal:replace="here/title_and_id" />
You can upload the text for <span tal:replace="context/title_and_id" />
using the following form.
Choose an existing HTML or XML file from your local computer by clicking
<em>browse</em>. You can also <a href="document_src">click here</a>
<em>browse</em>. You can also <a href="document_src">click context</a>
to view or download the current text.
</p>
......@@ -118,26 +129,28 @@ to view or download the current text.
</div>
</td>
<td align="left" valign="top">
<input type="file" name="file" size="25" value="">
<input type="file" name="file" size="40" value="">
</td>
</tr>
<tr tal:condition="context/management_page_charset|nothing">
<tr>
<td align="left" valign="top">
<div class="form-label">
Encoding &nbsp;
</div>
</td>
<td align="left" valign="top">
<input name="charset" value=""
tal:attributes="value here/management_page_charset|default" />
<td align="left" valign="top" colspan="2">
<input name="encoding" value="utf-8"/>
</td>
<td align="left" valign="top" colspan="1">
<em>(only used for non-XML and non-XHTML content)</em>
</td>
</tr>
<tr>
<td></td>
<td align="left" valign="top">
<div class="form-element">
<em tal:condition="here/wl_isLocked">Locked by WebDAV</em>
<input tal:condition="not:here/wl_isLocked"
<em tal:condition="context/wl_isLocked">Locked by WebDAV</em>
<input tal:condition="not:context/wl_isLocked"
class="form-element" type="submit" value="Upload File">
</div>
</td>
......@@ -145,4 +158,4 @@ to view or download the current text.
</table>
</form>
<h1 tal:replace="structure here/manage_page_footer">Footer</h1>
<h1 tal:replace="structure context/manage_page_footer">Footer</h1>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment