[Zope-Checkins] CVS: Zope3/lib/python/Zope/PageTemplate - PageTemplate.py:1.1.2.12
Shane Hathaway
shane@cvs.zope.org
Wed, 13 Mar 2002 22:55:36 -0500
Update of /cvs-repository/Zope3/lib/python/Zope/PageTemplate
In directory cvs.zope.org:/tmp/cvs-serv11107
Modified Files:
Tag: Zope-3x-branch
PageTemplate.py
Log Message:
- Made use of new EngineConfig. You can use a specific expression engine
by setting the _engine_name attribute.
- Improved reliability of delayed cooking.
- Removed dependency on ModuleImporter; the expression engine now provides
a dictionary of base names and it should include the "module" name.
- Added __traceback_supplement__, which doesn't do anything yet, but will
soon provide the detailed exception information that TALESErrors tried to
provide.
- Removed a shadow of a dependency on implicit acquisition.
=== Zope3/lib/python/Zope/PageTemplate/PageTemplate.py 1.1.2.11 => 1.1.2.12 ===
__version__ = '$Revision$'[11:-2]
-import os, sys, traceback, pprint
+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 Expressions import getEngine
+from EngineConfig import getEngine
from cStringIO import StringIO
from types import StringType
-Z_DEBUG_MODE = os.environ.get('Z_DEBUG_MODE') == '1'
-
class MacroCollection(object):
def __get__(self, parent, type=None):
parent._cook_check()
return parent._v_macros
+
class PageTemplate(object):
"""Page Templates using TAL, TALES, and METAL.
@@ -60,7 +59,11 @@
expand = 1
_v_errors = ()
_v_warnings = ()
+ _v_program = None
+ _v_macros = None
+ _v_cooked = 0
_text = ''
+ _engine_name = 'default'
_error_start = '<!-- Page Template Diagnostics'
macros = MacroCollection()
@@ -73,35 +76,32 @@
self.write(text)
def pt_getContext(self, args=(), options={}, **ignored):
- return {'template': self,
+ rval = {'template': self,
'options': options,
'args': args,
'nothing': None,
- 'modules': ModuleImporter,
}
+ rval.update(getEngine(self._engine_name).getBaseNames())
+ return rval
def pt_render(self, namespace, source=0):
"""Render this Page Template"""
+ self._cook_check()
+ __traceback_supplement__ = (PageTemplateTracebackSupplement, self)
if self._v_errors:
- raise PTRuntimeError(
- '''Page Template %s has errors.
- %s
- ''' % ('', #XXX self.id
- self._v_errors))
+ raise PTRuntimeError(str(self._v_errors))
output = StringIO()
- if Z_DEBUG_MODE:
- __traceback_info__ = pprint.pformat(namespace)
+ context = getEngine(self._engine_name).getContext(namespace)
TALInterpreter(self._v_program, self._v_macros,
- getEngine().getContext(namespace),
- output,
- tal=not source, strictinsert=0)()
+ context, output, tal=not source, strictinsert=0)()
return output.getvalue()
def __call__(self, *args, **kwargs):
return self.pt_render(self.pt_getContext(*args, **kwargs))
def pt_errors(self):
+ self._cook_check()
err = self._v_errors
if err:
return err
@@ -109,8 +109,9 @@
self.pt_render(source=1)
except:
return ('Macro expansion failed', '%s: %s' % sys.exc_info()[:2])
-
+
def pt_warnings(self):
+ self._cook_check()
return self._v_warnings
def write(self, text):
@@ -124,6 +125,8 @@
self._cook()
def read(self):
+ """Gets the source, sometimes with macros expanded."""
+ self._cook_check()
if not self._v_errors:
if not self.expand:
return self._text
@@ -133,22 +136,31 @@
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 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.
- A Page Template must always be cooked, and cooking must not
- fail due to user input.
+ Cooking must not fail due to compilation errors in templates.
"""
+ engine = getEngine(self._engine_name)
+ source_file = self.pt_source_file()
if self.html():
- gen = TALGenerator(getEngine(), xml=0)
+ gen = TALGenerator(engine, xml=0, source_file=source_file)
parser = HTMLTALParser(gen)
else:
- gen = TALGenerator(getEngine())
+ gen = TALGenerator(engine, source_file=source_file)
parser = TALParser(gen)
self._v_errors = ()
@@ -160,24 +172,39 @@
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'):
+ if not hasattr(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.manageable_object = pt
+ try:
+ errors = pt.pt_errors()
+ except: # We're already trying to report an error, don't make another.
+ errors = None
+ self.errors = errors
+
+ def getInfo(self, as_html=0):
+ errors = self.errors
+ if not errors:
+ return None
+ if not as_html:
+ return ' - Errors:\n %s' % '\n '.join(errors)
+ else:
+ from cgi import escape
+ s = '<br />'.join(map(escape, errors))
+ return '<b>Errors:</b><br />%s' % s
+