Commit 0a68cd0d authored by Evan Simpson's avatar Evan Simpson

Improve error reporting.

parent 4e3ab31c
...@@ -89,7 +89,7 @@ Page Template-specific implementation of TALES, with handlers ...@@ -89,7 +89,7 @@ Page Template-specific implementation of TALES, with handlers
for Python expressions, string literals, and paths. for Python expressions, string literals, and paths.
""" """
__version__='$Revision: 1.20 $'[11:-2] __version__='$Revision: 1.21 $'[11:-2]
import re, sys import re, sys
from TALES import Engine, CompilerError, _valid_name, NAME_RE, \ from TALES import Engine, CompilerError, _valid_name, NAME_RE, \
...@@ -114,6 +114,7 @@ def installHandlers(engine): ...@@ -114,6 +114,7 @@ def installHandlers(engine):
reg('string', StringExpr) reg('string', StringExpr)
reg('python', PythonExpr) reg('python', PythonExpr)
reg('not', NotExpr) reg('not', NotExpr)
reg('defer', DeferExpr)
if sys.modules.has_key('Zope'): if sys.modules.has_key('Zope'):
import AccessControl import AccessControl
...@@ -194,10 +195,14 @@ class PathExpr: ...@@ -194,10 +195,14 @@ class PathExpr:
ob = econtext.contexts ob = econtext.contexts
else: else:
ob = vars[base] ob = vars[base]
if isinstance(ob, DeferWrapper):
ob = ob()
if path: if path:
ob = restrictedTraverse(ob, path, securityManager) ob = restrictedTraverse(ob, path, securityManager)
exists = 1 exists = 1
break break
except Undefined, e:
ob = e
except (AttributeError, KeyError, TypeError, IndexError, except (AttributeError, KeyError, TypeError, IndexError,
'Unauthorized'), e: 'Unauthorized'), e:
ob = Undefined(self._s, sys.exc_info()) ob = Undefined(self._s, sys.exc_info())
...@@ -214,10 +219,10 @@ class PathExpr: ...@@ -214,10 +219,10 @@ class PathExpr:
return self._eval(econtext, getSecurityManager()) return self._eval(econtext, getSecurityManager())
def __str__(self): def __str__(self):
return '%s expression "%s"' % (self._name, self._s) return '%s expression %s' % (self._name, `self._s`)
def __repr__(self): def __repr__(self):
return '<PathExpr %s:%s>' % (self._name, self._s) return '%s:%s' % (self._name, `self._s`)
_interp = re.compile(r'\$(%(n)s)|\${(%(n)s(?:/%(n)s)*)}' % {'n': NAME_RE}) _interp = re.compile(r'\$(%(n)s)|\${(%(n)s(?:/%(n)s)*)}' % {'n': NAME_RE})
...@@ -242,8 +247,7 @@ class StringExpr: ...@@ -242,8 +247,7 @@ class StringExpr:
m = _interp.search(exp) m = _interp.search(exp)
if '$' in exp: if '$' in exp:
raise CompilerError, ( raise CompilerError, (
'$ must be doubled or followed by a variable name ' '$ must be doubled or followed by a simple path')
'in string expression "%s"' % expr)
parts.append(exp) parts.append(exp)
expr = join(parts, '') expr = join(parts, '')
self._expr = expr self._expr = expr
...@@ -261,7 +265,7 @@ class StringExpr: ...@@ -261,7 +265,7 @@ class StringExpr:
return 'string expression %s' % `self._s` return 'string expression %s' % `self._s`
def __repr__(self): def __repr__(self):
return '<StringExpr %s>' % `self._s` return 'string:%s' % `self._s`
class NotExpr: class NotExpr:
def __init__(self, name, expr, compiler): def __init__(self, name, expr, compiler):
...@@ -272,7 +276,29 @@ class NotExpr: ...@@ -272,7 +276,29 @@ class NotExpr:
return not econtext.evaluateBoolean(self._c) return not econtext.evaluateBoolean(self._c)
def __repr__(self): def __repr__(self):
return '<NotExpr %s>' % `self._s` return 'not:%s' % `self._s`
class DeferWrapper:
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:
def __init__(self, name, expr, compiler):
self._s = expr = lstrip(expr)
self._c = compiler.compile(expr)
def __call__(self, econtext):
return DeferWrapper(self._c, econtext)
def __repr__(self):
return 'defer:%s' % `self._s`
def restrictedTraverse(self, path, securityManager, def restrictedTraverse(self, path, securityManager,
......
...@@ -87,7 +87,7 @@ ...@@ -87,7 +87,7 @@
HTML- and XML-based template objects using TAL, TALES, and METAL. HTML- and XML-based template objects using TAL, TALES, and METAL.
""" """
__version__='$Revision: 1.14 $'[11:-2] __version__='$Revision: 1.15 $'[11:-2]
import os, sys, traceback, pprint import os, sys, traceback, pprint
from TAL.TALParser import TALParser from TAL.TALParser import TALParser
...@@ -111,6 +111,7 @@ class PageTemplate(Base): ...@@ -111,6 +111,7 @@ class PageTemplate(Base):
content_type = 'text/html' content_type = 'text/html'
expand = 1 expand = 1
_v_errors = () _v_errors = ()
_v_warnings = ()
_text = '' _text = ''
_error_start = '<!-- Page Template Diagnostics' _error_start = '<!-- Page Template Diagnostics'
...@@ -162,7 +163,16 @@ class PageTemplate(Base): ...@@ -162,7 +163,16 @@ class PageTemplate(Base):
return self.pt_render(extra_context={'options': kwargs}) return self.pt_render(extra_context={'options': kwargs})
def pt_errors(self): def pt_errors(self):
return self._v_errors err = self._v_errors
if err:
return err
try:
self.pt_render(source=1)
except:
return ('Macro expansion failed', '%s: %s' % sys.exc_info()[:2])
def pt_warnings(self):
return self._v_warnings
def write(self, text): def write(self, text):
assert type(text) is type('') assert type(text) is type('')
...@@ -209,6 +219,7 @@ class PageTemplate(Base): ...@@ -209,6 +219,7 @@ class PageTemplate(Base):
except: except:
self._v_errors = ["Compilation failed", self._v_errors = ["Compilation failed",
"%s: %s" % sys.exc_info()[:2]] "%s: %s" % sys.exc_info()[:2]]
self._v_warnings = parser.getWarnings()
def html(self): def html(self):
return self.content_type == 'text/html' return self.content_type == 'text/html'
......
...@@ -87,7 +87,7 @@ ...@@ -87,7 +87,7 @@
Zope object encapsulating a Page Template from the filesystem. Zope object encapsulating a Page Template from the filesystem.
""" """
__version__='$Revision: 1.3 $'[11:-2] __version__='$Revision: 1.4 $'[11:-2]
import os, AccessControl, Acquisition, sys import os, AccessControl, Acquisition, sys
from Globals import package_home, DevelopmentMode from Globals import package_home, DevelopmentMode
...@@ -157,6 +157,7 @@ class PageTemplateFile(Script, PageTemplate, Traversable): ...@@ -157,6 +157,7 @@ class PageTemplateFile(Script, PageTemplate, Traversable):
# Execute the template in a new security context. # Execute the template in a new security context.
security=getSecurityManager() security=getSecurityManager()
bound_names['user'] = security.getUser()
security.addContext(self) security.addContext(self)
try: try:
return self.pt_render(extra_context=bound_names) return self.pt_render(extra_context=bound_names)
......
...@@ -87,7 +87,7 @@ ...@@ -87,7 +87,7 @@
An implementation of a generic TALES engine An implementation of a generic TALES engine
""" """
__version__='$Revision: 1.21 $'[11:-2] __version__='$Revision: 1.22 $'[11:-2]
import re, sys, ZTUtils import re, sys, ZTUtils
from MultiMapping import MultiMapping from MultiMapping import MultiMapping
...@@ -100,24 +100,41 @@ _valid_name = re.compile('%s$' % NAME_RE).match ...@@ -100,24 +100,41 @@ _valid_name = re.compile('%s$' % NAME_RE).match
class TALESError(Exception): class TALESError(Exception):
__allow_access_to_unprotected_subobjects__ = 1 __allow_access_to_unprotected_subobjects__ = 1
def __init__(self, expression, info=(None, None, None)): def __init__(self, expression, info=(None, None, None),
position=(None, None)):
self.type, self.value, self.traceback = info self.type, self.value, self.traceback = info
self.expression = expression self.expression = expression
self.setPosition(position)
def setPosition(self, position):
self.lineno = position[0]
self.offset = position[1]
def __str__(self): def __str__(self):
if self.type is not None: if self.type is None:
return '%s on %s in "%s"' % (self.type, self.value, s = self.expression
self.expression) else:
return self.expression s = '%s on %s in %s' % (self.type, self.value,
`self.expression`)
if self.lineno is not None:
s = "%s, at line %d" % (s, self.lineno)
if self.offset is not None:
s = "%s, column %d" % (s, self.offset + 1)
return s
def __nonzero__(self): def __nonzero__(self):
return 0 return 0
class Undefined(TALESError): class Undefined(TALESError):
'''Exception raised on traversal of an undefined path''' '''Exception raised on traversal of an undefined path'''
def __str__(self): def __str__(self):
if self.type is not None: if self.type is None:
return '"%s" not found in "%s"' % (self.value, s = self.expression
self.expression) else:
return self.expression s = '%s not found in %s' % (self.value,
`self.expression`)
if self.lineno is not None:
s = "%s, at line %d" % (s, self.lineno)
if self.offset is not None:
s = "%s, column %d" % (s, self.offset + 1)
return s
class RegistrationError(Exception): class RegistrationError(Exception):
'''TALES Type Registration Error''' '''TALES Type Registration Error'''
...@@ -221,6 +238,8 @@ class Engine: ...@@ -221,6 +238,8 @@ class Engine:
kwcontexts = contexts kwcontexts = contexts
return Context(self, kwcontexts) return Context(self, kwcontexts)
def getCompilerError(self):
return CompilerError
class Context: class Context:
'''Expression Context '''Expression Context
...@@ -231,6 +250,7 @@ class Context: ...@@ -231,6 +250,7 @@ class Context:
_context_class = SafeMapping _context_class = SafeMapping
_nocatch = TALESError _nocatch = TALESError
position = (None, None)
def __init__(self, engine, contexts): def __init__(self, engine, contexts):
self._engine = engine self._engine = engine
...@@ -297,10 +317,14 @@ class Context: ...@@ -297,10 +317,14 @@ class Context:
if hasattr(v, 'traceback'): if hasattr(v, 'traceback'):
raise v, None, v.traceback raise v, None, v.traceback
raise v raise v
except TALESError, err:
err.setPosition(self.position)
raise err, None, sys.exc_info()[2]
except self._nocatch: except self._nocatch:
raise raise
except: except:
raise TALESError, (`expression`, sys.exc_info()), sys.exc_info()[2] raise TALESError, (`expression`, sys.exc_info(),
self.position), sys.exc_info()[2]
else: else:
return v return v
...@@ -330,6 +354,9 @@ class Context: ...@@ -330,6 +354,9 @@ class Context:
def getDefault(self): def getDefault(self):
return Default return Default
def setPosition(self, position):
self.position = position
class SimpleExpr: class SimpleExpr:
'''Simple example of an expression type handler''' '''Simple example of an expression type handler'''
def __init__(self, name, expr, engine): def __init__(self, name, expr, engine):
......
...@@ -87,7 +87,7 @@ ...@@ -87,7 +87,7 @@
Zope object encapsulating a Page Template. Zope object encapsulating a Page Template.
""" """
__version__='$Revision: 1.18 $'[11:-2] __version__='$Revision: 1.19 $'[11:-2]
import os, AccessControl, Acquisition, sys import os, AccessControl, Acquisition, sys
from Globals import DTMLFile, MessageDialog, package_home from Globals import DTMLFile, MessageDialog, package_home
...@@ -160,7 +160,7 @@ class ZopePageTemplate(Script, PageTemplate, Historical, Cacheable, ...@@ -160,7 +160,7 @@ class ZopePageTemplate(Script, PageTemplate, Historical, Cacheable,
security.declareProtected('View management screens', security.declareProtected('View management screens',
'pt_editForm', 'manage_main', 'read', 'pt_editForm', 'manage_main', 'read',
'ZScriptHTML_tryForm', 'PrincipiaSearchSource', 'ZScriptHTML_tryForm', 'PrincipiaSearchSource',
'document_src') 'document_src', 'source.html', 'source.xml')
security.declareProtected('Change Page Templates', security.declareProtected('Change Page Templates',
'pt_editAction', 'pt_setTitle', 'pt_edit', 'pt_editAction', 'pt_setTitle', 'pt_edit',
...@@ -310,6 +310,8 @@ class ZopePageTemplate(Script, PageTemplate, Historical, Cacheable, ...@@ -310,6 +310,8 @@ class ZopePageTemplate(Script, PageTemplate, Historical, Cacheable,
if RESPONSE is not None: if RESPONSE is not None:
RESPONSE.setHeader('Content-Type', self.content_type) RESPONSE.setHeader('Content-Type', self.content_type)
if REQUEST.get('raw'):
return self._text
return self.read() return self.read()
def __setstate__(self, state): def __setstate__(self, state):
......
...@@ -2,9 +2,9 @@ ...@@ -2,9 +2,9 @@
<h2 tal:define="manage_tabs_message options/manage_tabs_message | nothing" <h2 tal:define="manage_tabs_message options/manage_tabs_message | nothing"
tal:replace="structure here/manage_tabs">Tabs</h2> tal:replace="structure here/manage_tabs">Tabs</h2>
<form action="" method="post" <tal:block define="global body request/other/text | request/form/text
tal:define="body request/other/text | request/form/text | here/read" | here/read" />
tal:attributes="action request/URL1"> <form action="" method="post" tal:attributes="action request/URL1">
<input type="hidden" name=":default_method" value="pt_changePrefs"> <input type="hidden" name=":default_method" value="pt_changePrefs">
<table width="100%" cellspacing="0" cellpadding="2" border="0"> <table width="100%" cellspacing="0" cellpadding="2" border="0">
<tr> <tr>
...@@ -48,6 +48,24 @@ ...@@ -48,6 +48,24 @@
Expand macros when editing Expand macros when editing
</td> </td>
</tr> </tr>
<tr tal:define="errors here/pt_errors" tal:condition="errors">
<tal:block define="global body python:here.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>
</td>
</tr>
<tr tal:define="warnings here/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>
</td>
</tr>
<tr> <tr>
<td align="left" valign="top" colspan="4"> <td align="left" valign="top" colspan="4">
<div style="width: 100%;"> <div style="width: 100%;">
......
...@@ -188,6 +188,9 @@ class HTMLTALParser(HTMLParser): ...@@ -188,6 +188,9 @@ class HTMLTALParser(HTMLParser):
def getCode(self): def getCode(self):
return self.gen.getCode() return self.gen.getCode()
def getWarnings(self):
return ()
# Overriding HTMLParser methods # Overriding HTMLParser methods
def handle_starttag(self, tag, attrs): def handle_starttag(self, tag, attrs):
......
...@@ -102,6 +102,7 @@ class TALGenerator: ...@@ -102,6 +102,7 @@ class TALGenerator:
from DummyEngine import DummyEngine from DummyEngine import DummyEngine
expressionCompiler = DummyEngine() expressionCompiler = DummyEngine()
self.expressionCompiler = expressionCompiler self.expressionCompiler = expressionCompiler
self.CompilerError = expressionCompiler.getCompilerError()
self.program = [] self.program = []
self.stack = [] self.stack = []
self.todoStack = [] self.todoStack = []
...@@ -229,7 +230,11 @@ class TALGenerator: ...@@ -229,7 +230,11 @@ class TALGenerator:
return self.todoStack.pop() return self.todoStack.pop()
def compileExpression(self, expr): def compileExpression(self, expr):
try:
return self.expressionCompiler.compile(expr) return self.expressionCompiler.compile(expr)
except self.CompilerError, err:
raise TALError('%s in expression %s' % (err.args[0], `expr`),
self.position)
def pushProgram(self): def pushProgram(self):
self.stack.append(self.program) self.stack.append(self.program)
...@@ -284,12 +289,13 @@ class TALGenerator: ...@@ -284,12 +289,13 @@ class TALGenerator:
def emitText(self, text): def emitText(self, text):
self.emitRawText(cgi.escape(text)) self.emitRawText(cgi.escape(text))
def emitDefines(self, defines, position): def emitDefines(self, defines):
for part in splitParts(defines): for part in splitParts(defines):
m = re.match( m = re.match(
r"(?s)\s*(?:(global|local)\s+)?(%s)\s+(.*)\Z" % NAME_RE, part) r"(?s)\s*(?:(global|local)\s+)?(%s)\s+(.*)\Z" % NAME_RE, part)
if not m: if not m:
raise TALError("invalid define syntax: " + `part`, position) raise TALError("invalid define syntax: " + `part`,
self.position)
scope, name, expr = m.group(1, 2, 3) scope, name, expr = m.group(1, 2, 3)
scope = scope or "local" scope = scope or "local"
cexpr = self.compileExpression(expr) cexpr = self.compileExpression(expr)
...@@ -298,9 +304,9 @@ class TALGenerator: ...@@ -298,9 +304,9 @@ class TALGenerator:
else: else:
self.emit("setGlobal", name, cexpr) self.emit("setGlobal", name, cexpr)
def emitOnError(self, name, onError, position): def emitOnError(self, name, onError):
block = self.popProgram() block = self.popProgram()
key, expr = parseSubstitution(onError, position) key, expr = parseSubstitution(onError)
cexpr = self.compileExpression(expr) cexpr = self.compileExpression(expr)
if key == "text": if key == "text":
self.emit("insertText", cexpr, []) self.emit("insertText", cexpr, [])
...@@ -316,17 +322,18 @@ class TALGenerator: ...@@ -316,17 +322,18 @@ class TALGenerator:
program = self.popProgram() program = self.popProgram()
self.emit("condition", cexpr, program) self.emit("condition", cexpr, program)
def emitRepeat(self, arg, position=(None, None)): def emitRepeat(self, arg):
m = re.match("(?s)\s*(%s)\s+(.*)\Z" % NAME_RE, arg) m = re.match("(?s)\s*(%s)\s+(.*)\Z" % NAME_RE, arg)
if not m: if not m:
raise TALError("invalid repeat syntax: " + `arg`, position) raise TALError("invalid repeat syntax: " + `arg`,
self.position)
name, expr = m.group(1, 2) name, expr = m.group(1, 2)
cexpr = self.compileExpression(expr) cexpr = self.compileExpression(expr)
program = self.popProgram() program = self.popProgram()
self.emit("loop", name, cexpr, program) self.emit("loop", name, cexpr, program)
def emitSubstitution(self, arg, attrDict={}, position=(None, None)): def emitSubstitution(self, arg, attrDict={}):
key, expr = parseSubstitution(arg, position) key, expr = parseSubstitution(arg)
cexpr = self.compileExpression(expr) cexpr = self.compileExpression(expr)
program = self.popProgram() program = self.popProgram()
if key == "text": if key == "text":
...@@ -335,14 +342,15 @@ class TALGenerator: ...@@ -335,14 +342,15 @@ class TALGenerator:
assert key == "structure" assert key == "structure"
self.emit("insertStructure", cexpr, attrDict, program) self.emit("insertStructure", cexpr, attrDict, program)
def emitDefineMacro(self, macroName, position=(None, None)): def emitDefineMacro(self, macroName):
program = self.popProgram() program = self.popProgram()
macroName = string.strip(macroName) macroName = string.strip(macroName)
if self.macros.has_key(macroName): if self.macros.has_key(macroName):
raise METALError("duplicate macro definition: %s" % `macroName`, raise METALError("duplicate macro definition: %s" % `macroName`,
position) self.position)
if not re.match('%s$' % NAME_RE, macroName): if not re.match('%s$' % NAME_RE, macroName):
raise METALError("invalid macro name: %s" % `macroName`, position) raise METALError("invalid macro name: %s" % `macroName`,
self.position)
self.macros[macroName] = program self.macros[macroName] = program
self.inMacroDef = self.inMacroDef - 1 self.inMacroDef = self.inMacroDef - 1
self.emit("defineMacro", macroName, program) self.emit("defineMacro", macroName, program)
...@@ -353,21 +361,23 @@ class TALGenerator: ...@@ -353,21 +361,23 @@ class TALGenerator:
self.inMacroUse = 0 self.inMacroUse = 0
self.emit("useMacro", expr, cexpr, self.popSlots(), program) self.emit("useMacro", expr, cexpr, self.popSlots(), program)
def emitDefineSlot(self, slotName, position=(None, None)): def emitDefineSlot(self, slotName):
program = self.popProgram() program = self.popProgram()
slotName = string.strip(slotName) slotName = string.strip(slotName)
if not re.match('%s$' % NAME_RE, slotName): if not re.match('%s$' % NAME_RE, slotName):
raise METALError("invalid slot name: %s" % `slotName`, position) raise METALError("invalid slot name: %s" % `slotName`,
self.position)
self.emit("defineSlot", slotName, program) self.emit("defineSlot", slotName, program)
def emitFillSlot(self, slotName, position=(None, None)): def emitFillSlot(self, slotName):
program = self.popProgram() program = self.popProgram()
slotName = string.strip(slotName) slotName = string.strip(slotName)
if self.slots.has_key(slotName): if self.slots.has_key(slotName):
raise METALError("duplicate fill-slot name: %s" % `slotName`, raise METALError("duplicate fill-slot name: %s" % `slotName`,
position) self.position)
if not re.match('%s$' % NAME_RE, slotName): if not re.match('%s$' % NAME_RE, slotName):
raise METALError("invalid slot name: %s" % `slotName`, position) raise METALError("invalid slot name: %s" % `slotName`,
self.position)
self.slots[slotName] = program self.slots[slotName] = program
self.inMacroUse = 1 self.inMacroUse = 1
self.emit("fillSlot", slotName, program) self.emit("fillSlot", slotName, program)
...@@ -443,6 +453,7 @@ class TALGenerator: ...@@ -443,6 +453,7 @@ class TALGenerator:
self.emitEndElement(name, isend) self.emitEndElement(name, isend)
return return
self.position = position
for key, value in taldict.items(): for key, value in taldict.items():
if key not in KNOWN_TAL_ATTRIBUTES: if key not in KNOWN_TAL_ATTRIBUTES:
raise TALError("bad TAL attribute: " + `key`, position) raise TALError("bad TAL attribute: " + `key`, position)
...@@ -527,7 +538,7 @@ class TALGenerator: ...@@ -527,7 +538,7 @@ class TALGenerator:
self.pushProgram() # block self.pushProgram() # block
todo["onError"] = onError todo["onError"] = onError
if define: if define:
self.emitDefines(define, position) self.emitDefines(define)
todo["define"] = define todo["define"] = define
if condition: if condition:
self.pushProgram() self.pushProgram()
...@@ -574,7 +585,7 @@ class TALGenerator: ...@@ -574,7 +585,7 @@ class TALGenerator:
self.emitEndTag(name) self.emitEndTag(name)
return return
position = todo.get("position", (None, None)) self.position = position = todo.get("position", (None, None))
defineMacro = todo.get("defineMacro") defineMacro = todo.get("defineMacro")
useMacro = todo.get("useMacro") useMacro = todo.get("useMacro")
defineSlot = todo.get("defineSlot") defineSlot = todo.get("defineSlot")
...@@ -600,29 +611,29 @@ class TALGenerator: ...@@ -600,29 +611,29 @@ class TALGenerator:
(what, name, name), position) (what, name, name), position)
if content: if content:
self.emitSubstitution(content, {}, position) self.emitSubstitution(content, {})
if optTag: if optTag:
self.emitOptTag(name, optTag, isend) self.emitOptTag(name, optTag, isend)
elif not isend: elif not isend:
self.emitEndTag(name) self.emitEndTag(name)
if replace: if replace:
self.emitSubstitution(replace, repldict, position) self.emitSubstitution(replace, repldict)
if repeat: if repeat:
self.emitRepeat(repeat, position) self.emitRepeat(repeat)
if condition: if condition:
self.emitCondition(condition) self.emitCondition(condition)
if onError: if onError:
self.emitOnError(name, onError, position) self.emitOnError(name, onError)
if scope: if scope:
self.emit("endScope") self.emit("endScope")
if defineSlot: if defineSlot:
self.emitDefineSlot(defineSlot, position) self.emitDefineSlot(defineSlot)
if fillSlot: if fillSlot:
self.emitFillSlot(fillSlot, position) self.emitFillSlot(fillSlot)
if useMacro: if useMacro:
self.emitUseMacro(useMacro) self.emitUseMacro(useMacro)
if defineMacro: if defineMacro:
self.emitDefineMacro(defineMacro, position) self.emitDefineMacro(defineMacro)
def test(): def test():
t = TALGenerator() t = TALGenerator()
......
...@@ -201,6 +201,7 @@ class TALInterpreter: ...@@ -201,6 +201,7 @@ class TALInterpreter:
while self.scopeLevel > scopeLevel: while self.scopeLevel > scopeLevel:
self.engine.endScope() self.engine.endScope()
self.scopeLevel = self.scopeLevel - 1 self.scopeLevel = self.scopeLevel - 1
self.engine.setPosition(self.position)
def restoreOutputState(self, state): def restoreOutputState(self, state):
(dummy, self.col, self.stream, scopeLevel, level) = state (dummy, self.col, self.stream, scopeLevel, level) = state
...@@ -279,6 +280,7 @@ class TALInterpreter: ...@@ -279,6 +280,7 @@ class TALInterpreter:
def do_setPosition(self, position): def do_setPosition(self, position):
self.position = position self.position = position
self.engine.setPosition(position)
bytecode_handlers["setPosition"] = do_setPosition bytecode_handlers["setPosition"] = do_setPosition
def do_startEndTag(self, stuff): def do_startEndTag(self, stuff):
......
...@@ -107,6 +107,9 @@ class TALParser(XMLParser): ...@@ -107,6 +107,9 @@ class TALParser(XMLParser):
def getCode(self): def getCode(self):
return self.gen.getCode() return self.gen.getCode()
def getWarnings(self):
return ()
def StartNamespaceDeclHandler(self, prefix, uri): def StartNamespaceDeclHandler(self, prefix, uri):
self.nsStack.append(self.nsDict.copy()) self.nsStack.append(self.nsDict.copy())
self.nsDict[uri] = prefix self.nsDict[uri] = prefix
......
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