[Zope-Checkins] SVN: Zope/branches/ajung-zpt-end-game/lib/python/TAL/ Deprecate TAL package and make it a facade of zope.tal.

Philipp von Weitershausen philikon at philikon.de
Sun May 28 19:07:08 EDT 2006


Log message for revision 68317:
  Deprecate TAL package and make it a facade of zope.tal.
  

Changed:
  U   Zope/branches/ajung-zpt-end-game/lib/python/TAL/DummyEngine.py
  U   Zope/branches/ajung-zpt-end-game/lib/python/TAL/HTMLTALParser.py
  U   Zope/branches/ajung-zpt-end-game/lib/python/TAL/ITALES.py
  U   Zope/branches/ajung-zpt-end-game/lib/python/TAL/TALDefs.py
  U   Zope/branches/ajung-zpt-end-game/lib/python/TAL/TALGenerator.py
  U   Zope/branches/ajung-zpt-end-game/lib/python/TAL/TALInterpreter.py
  U   Zope/branches/ajung-zpt-end-game/lib/python/TAL/TALParser.py
  U   Zope/branches/ajung-zpt-end-game/lib/python/TAL/TranslationContext.py
  U   Zope/branches/ajung-zpt-end-game/lib/python/TAL/XMLParser.py
  U   Zope/branches/ajung-zpt-end-game/lib/python/TAL/driver.py
  U   Zope/branches/ajung-zpt-end-game/lib/python/TAL/ndiff.py
  U   Zope/branches/ajung-zpt-end-game/lib/python/TAL/runtest.py
  U   Zope/branches/ajung-zpt-end-game/lib/python/TAL/talgettext.py
  U   Zope/branches/ajung-zpt-end-game/lib/python/TAL/timer.py

-=-
Modified: Zope/branches/ajung-zpt-end-game/lib/python/TAL/DummyEngine.py
===================================================================
--- Zope/branches/ajung-zpt-end-game/lib/python/TAL/DummyEngine.py	2006-05-28 22:14:02 UTC (rev 68316)
+++ Zope/branches/ajung-zpt-end-game/lib/python/TAL/DummyEngine.py	2006-05-28 23:07:07 UTC (rev 68317)
@@ -13,239 +13,14 @@
 ##############################################################################
 """
 Dummy TALES engine so that I can test out the TAL implementation.
+
+BBB 2005/05/01 -- to be removed after 12 months
 """
+import zope.deprecation
+zope.deprecation.moved('zope.tal.dummyengine', '2.12')
 
-import re
-import sys
+from zope.tal.dummyengine import DummyTranslationDomain as DummyDomain
 
-from TALDefs import NAME_RE, TALESError, ErrorInfo
-from ITALES import ITALESCompiler, ITALESEngine
-from DocumentTemplate.DT_Util import ustr
-
-class _Default:
-    pass
-Default = _Default()
-
-name_match = re.compile(r"(?s)(%s):(.*)\Z" % NAME_RE).match
-
-class CompilerError(Exception):
-    pass
-
-class DummyEngine:
-
-    position = None
-    source_file = None
-
-    __implements__ = ITALESCompiler, ITALESEngine
-
-    def __init__(self, macros=None):
-        if macros is None:
-            macros = {}
-        self.macros = macros
-        dict = {'nothing': None, 'default': Default}
-        self.locals = self.globals = dict
-        self.stack = [dict]
-        self.translationService = DummyTranslationService()
-
-    def getCompilerError(self):
-        return CompilerError
-
-    def getCompiler(self):
-        return self
-
-    def setSourceFile(self, source_file):
-        self.source_file = source_file
-
-    def setPosition(self, position):
-        self.position = position
-
-    def compile(self, expr):
-        return "$%s$" % expr
-
-    def uncompile(self, expression):
-        assert (expression.startswith("$") and expression.endswith("$"),
-            expression)
-        return expression[1:-1]
-
-    def beginScope(self):
-        self.stack.append(self.locals)
-
-    def endScope(self):
-        assert len(self.stack) > 1, "more endScope() than beginScope() calls"
-        self.locals = self.stack.pop()
-
-    def setLocal(self, name, value):
-        if self.locals is self.stack[-1]:
-            # Unmerge this scope's locals from previous scope of first set
-            self.locals = self.locals.copy()
-        self.locals[name] = value
-
-    def setGlobal(self, name, value):
-        self.globals[name] = value
-
-    def evaluate(self, expression):
-        assert (expression.startswith("$") and expression.endswith("$"),
-            expression)
-        expression = expression[1:-1]
-        m = name_match(expression)
-        if m:
-            type, expr = m.group(1, 2)
-        else:
-            type = "path"
-            expr = expression
-        if type in ("string", "str"):
-            return expr
-        if type in ("path", "var", "global", "local"):
-            return self.evaluatePathOrVar(expr)
-        if type == "not":
-            return not self.evaluate(expr)
-        if type == "exists":
-            return self.locals.has_key(expr) or self.globals.has_key(expr)
-        if type == "python":
-            try:
-                return eval(expr, self.globals, self.locals)
-            except:
-                raise TALESError("evaluation error in %s" % `expr`)
-        if type == "position":
-            # Insert the current source file name, line number,
-            # and column offset.
-            if self.position:
-                lineno, offset = self.position
-            else:
-                lineno, offset = None, None
-            return '%s (%s,%s)' % (self.source_file, lineno, offset)
-        raise TALESError("unrecognized expression: " + `expression`)
-
-    def evaluatePathOrVar(self, expr):
-        expr = expr.strip()
-        if self.locals.has_key(expr):
-            return self.locals[expr]
-        elif self.globals.has_key(expr):
-            return self.globals[expr]
-        else:
-            raise TALESError("unknown variable: %s" % `expr`)
-
-    def evaluateValue(self, expr):
-        return self.evaluate(expr)
-
-    def evaluateBoolean(self, expr):
-        return self.evaluate(expr)
-
-    def evaluateText(self, expr):
-        text = self.evaluate(expr)
-        if text is not None and text is not Default:
-            text = ustr(text)
-        return text
-
-    def evaluateStructure(self, expr):
-        # XXX Should return None or a DOM tree
-        return self.evaluate(expr)
-
-    def evaluateSequence(self, expr):
-        # XXX Should return a sequence
-        return self.evaluate(expr)
-
-    def evaluateMacro(self, macroName):
-        assert (macroName.startswith("$") and macroName.endswith("$"),
-            macroName)
-        macroName = macroName[1:-1]
-        file, localName = self.findMacroFile(macroName)
-        if not file:
-            # Local macro
-            macro = self.macros[localName]
-        else:
-            # External macro
-            import driver
-            program, macros = driver.compilefile(file)
-            macro = macros.get(localName)
-            if not macro:
-                raise TALESError("macro %s not found in file %s" %
-                                 (localName, file))
-        return macro
-
-    def findMacroDocument(self, macroName):
-        file, localName = self.findMacroFile(macroName)
-        if not file:
-            return file, localName
-        import driver
-        doc = driver.parsefile(file)
-        return doc, localName
-
-    def findMacroFile(self, macroName):
-        if not macroName:
-            raise TALESError("empty macro name")
-        i = macroName.rfind('/')
-        if i < 0:
-            # No slash -- must be a locally defined macro
-            return None, macroName
-        else:
-            # Up to last slash is the filename
-            fileName = macroName[:i]
-            localName = macroName[i+1:]
-            return fileName, localName
-
-    def setRepeat(self, name, expr):
-        seq = self.evaluateSequence(expr)
-        return Iterator(name, seq, self)
-
-    def createErrorInfo(self, err, position):
-        return ErrorInfo(err, position)
-
-    def getDefault(self):
-        return Default
-
-    def translate(self, domain, msgid, mapping, default=None):
-        return self.translationService.translate(domain, msgid, mapping,
-                                                 default=default)
-
-
-class Iterator:
-
-    # This is not an implementation of a Python iterator.  The next()
-    # method returns true or false to indicate whether another item is
-    # available; if there is another item, the iterator instance calls
-    # setLocal() on the evaluation engine passed to the constructor.
-
-    def __init__(self, name, seq, engine):
-        self.name = name
-        self.seq = seq
-        self.engine = engine
-        self.nextIndex = 0
-
-    def next(self):
-        i = self.nextIndex
-        try:
-            item = self.seq[i]
-        except IndexError:
-            return 0
-        self.nextIndex = i+1
-        self.engine.setLocal(self.name, item)
-        return 1
-
-class DummyDomain:
-
-    def translate(self, msgid, mapping=None, context=None,
-                  target_language=None, default=None):
-        # This is a fake translation service which simply uppercases non
-        # ${name} placeholder text in the message id.
-        #
-        # First, transform a string with ${name} placeholders into a list of
-        # substrings.  Then upcase everything but the placeholders, then glue
-        # things back together.
-
-        # simulate an unknown msgid by returning None
-        text = msgid
-        if msgid == "don't translate me":
-            if default is not None:
-                text = default
-        else:
-            text = msgid.upper()
-
-        def repl(m, mapping=mapping):
-            return ustr(mapping[m.group(m.lastindex).lower()])
-        cre = re.compile(r'\$(?:(%s)|\{(%s)\})' % (NAME_RE, NAME_RE))
-        return cre.sub(repl, text)
-
 class DummyTranslationService:
 
     def translate(self, domain, msgid, mapping=None, context=None,

Modified: Zope/branches/ajung-zpt-end-game/lib/python/TAL/HTMLTALParser.py
===================================================================
--- Zope/branches/ajung-zpt-end-game/lib/python/TAL/HTMLTALParser.py	2006-05-28 22:14:02 UTC (rev 68316)
+++ Zope/branches/ajung-zpt-end-game/lib/python/TAL/HTMLTALParser.py	2006-05-28 23:07:07 UTC (rev 68317)
@@ -13,303 +13,8 @@
 ##############################################################################
 """
 Parse HTML and compile to TALInterpreter intermediate code.
-"""
 
-import sys
-
-from TALGenerator import TALGenerator
-from HTMLParser import HTMLParser, HTMLParseError
-from TALDefs import \
-     ZOPE_METAL_NS, ZOPE_TAL_NS, ZOPE_I18N_NS, METALError, TALError, I18NError
-
-BOOLEAN_HTML_ATTRS = [
-    # List of Boolean attributes in HTML that may be given in
-    # minimized form (e.g. <img ismap> rather than <img ismap="">)
-    # From http://www.w3.org/TR/xhtml1/#guidelines (C.10)
-    "compact", "nowrap", "ismap", "declare", "noshade", "checked",
-    "disabled", "readonly", "multiple", "selected", "noresize",
-    "defer"
-    ]
-
-EMPTY_HTML_TAGS = [
-    # List of HTML tags with an empty content model; these are
-    # rendered in minimized form, e.g. <img />.
-    # From http://www.w3.org/TR/xhtml1/#dtds
-    "base", "meta", "link", "hr", "br", "param", "img", "area",
-    "input", "col", "basefont", "isindex", "frame",
-    ]
-
-PARA_LEVEL_HTML_TAGS = [
-    # List of HTML elements that close open paragraph-level elements
-    # and are themselves paragraph-level.
-    "h1", "h2", "h3", "h4", "h5", "h6", "p",
-    ]
-
-BLOCK_CLOSING_TAG_MAP = {
-    "tr": ("tr", "td", "th"),
-    "td": ("td", "th"),
-    "th": ("td", "th"),
-    "li": ("li",),
-    "dd": ("dd", "dt"),
-    "dt": ("dd", "dt"),
-    }
-
-BLOCK_LEVEL_HTML_TAGS = [
-    # List of HTML tags that denote larger sections than paragraphs.
-    "blockquote", "table", "tr", "th", "td", "thead", "tfoot", "tbody",
-    "noframe", "ul", "ol", "li", "dl", "dt", "dd", "div",
-    ]
-
-TIGHTEN_IMPLICIT_CLOSE_TAGS = (PARA_LEVEL_HTML_TAGS
-                               + BLOCK_CLOSING_TAG_MAP.keys())
-
-
-class NestingError(HTMLParseError):
-    """Exception raised when elements aren't properly nested."""
-
-    def __init__(self, tagstack, endtag, position=(None, None)):
-        self.endtag = endtag
-        if tagstack:
-            if len(tagstack) == 1:
-                msg = ('Open tag <%s> does not match close tag </%s>'
-                       % (tagstack[0], endtag))
-            else:
-                msg = ('Open tags <%s> do not match close tag </%s>'
-                       % ('>, <'.join(tagstack), endtag))
-        else:
-            msg = 'No tags are open to match </%s>' % endtag
-        HTMLParseError.__init__(self, msg, position)
-
-class EmptyTagError(NestingError):
-    """Exception raised when empty elements have an end tag."""
-
-    def __init__(self, tag, position=(None, None)):
-        self.tag = tag
-        msg = 'Close tag </%s> should be removed' % tag
-        HTMLParseError.__init__(self, msg, position)
-
-class OpenTagError(NestingError):
-    """Exception raised when a tag is not allowed in another tag."""
-
-    def __init__(self, tagstack, tag, position=(None, None)):
-        self.tag = tag
-        msg = 'Tag <%s> is not allowed in <%s>' % (tag, tagstack[-1])
-        HTMLParseError.__init__(self, msg, position)
-
-class HTMLTALParser(HTMLParser):
-
-    # External API
-
-    def __init__(self, gen=None):
-        HTMLParser.__init__(self)
-        if gen is None:
-            gen = TALGenerator(xml=0)
-        self.gen = gen
-        self.tagstack = []
-        self.nsstack = []
-        self.nsdict = {'tal': ZOPE_TAL_NS,
-                       'metal': ZOPE_METAL_NS,
-                       'i18n': ZOPE_I18N_NS,
-                       }
-
-    def parseFile(self, file):
-        f = open(file)
-        data = f.read()
-        f.close()
-        try:
-            self.parseString(data)
-        except TALError, e:
-            e.setFile(file)
-            raise
-
-    def parseString(self, data):
-        self.feed(data)
-        self.close()
-        while self.tagstack:
-            self.implied_endtag(self.tagstack[-1], 2)
-        assert self.nsstack == [], self.nsstack
-
-    def getCode(self):
-        return self.gen.getCode()
-
-    def getWarnings(self):
-        return ()
-
-    # Overriding HTMLParser methods
-
-    def handle_starttag(self, tag, attrs):
-        self.close_para_tags(tag)
-        self.scan_xmlns(attrs)
-        tag, attrlist, taldict, metaldict, i18ndict \
-             = self.process_ns(tag, attrs)
-        if tag in EMPTY_HTML_TAGS and taldict.get("content"):
-            raise TALError(
-                "empty HTML tags cannot use tal:content: %s" % `tag`,
-                self.getpos())
-        self.tagstack.append(tag)
-        self.gen.emitStartElement(tag, attrlist, taldict, metaldict, i18ndict,
-                                  self.getpos())
-        if tag in EMPTY_HTML_TAGS:
-            self.implied_endtag(tag, -1)
-
-    def handle_startendtag(self, tag, attrs):
-        self.close_para_tags(tag)
-        self.scan_xmlns(attrs)
-        tag, attrlist, taldict, metaldict, i18ndict \
-             = self.process_ns(tag, attrs)
-        if taldict.get("content"):
-            if tag in EMPTY_HTML_TAGS:
-                raise TALError(
-                    "empty HTML tags cannot use tal:content: %s" % `tag`,
-                    self.getpos())
-            self.gen.emitStartElement(tag, attrlist, taldict, metaldict,
-                                      i18ndict, self.getpos())
-            self.gen.emitEndElement(tag, implied=-1)
-        else:
-            self.gen.emitStartElement(tag, attrlist, taldict, metaldict,
-                                      i18ndict, self.getpos(), isend=1)
-        self.pop_xmlns()
-
-    def handle_endtag(self, tag):
-        if tag in EMPTY_HTML_TAGS:
-            # </img> etc. in the source is an error
-            raise EmptyTagError(tag, self.getpos())
-        self.close_enclosed_tags(tag)
-        self.gen.emitEndElement(tag)
-        self.pop_xmlns()
-        self.tagstack.pop()
-
-    def close_para_tags(self, tag):
-        if tag in EMPTY_HTML_TAGS:
-            return
-        close_to = -1
-        if BLOCK_CLOSING_TAG_MAP.has_key(tag):
-            blocks_to_close = BLOCK_CLOSING_TAG_MAP[tag]
-            for i in range(len(self.tagstack)):
-                t = self.tagstack[i]
-                if t in blocks_to_close:
-                    if close_to == -1:
-                        close_to = i
-                elif t in BLOCK_LEVEL_HTML_TAGS:
-                    close_to = -1
-        elif tag in PARA_LEVEL_HTML_TAGS + BLOCK_LEVEL_HTML_TAGS:
-            i = len(self.tagstack) - 1
-            while i >= 0:
-                closetag = self.tagstack[i]
-                if closetag in BLOCK_LEVEL_HTML_TAGS:
-                    break
-                if closetag in PARA_LEVEL_HTML_TAGS:
-                    if closetag != "p":
-                        raise OpenTagError(self.tagstack, tag, self.getpos())
-                    close_to = i
-                i = i - 1
-        if close_to >= 0:
-            while len(self.tagstack) > close_to:
-                self.implied_endtag(self.tagstack[-1], 1)
-
-    def close_enclosed_tags(self, tag):
-        if tag not in self.tagstack:
-            raise NestingError(self.tagstack, tag, self.getpos())
-        while tag != self.tagstack[-1]:
-            self.implied_endtag(self.tagstack[-1], 1)
-        assert self.tagstack[-1] == tag
-
-    def implied_endtag(self, tag, implied):
-        assert tag == self.tagstack[-1]
-        assert implied in (-1, 1, 2)
-        isend = (implied < 0)
-        if tag in TIGHTEN_IMPLICIT_CLOSE_TAGS:
-            # Pick out trailing whitespace from the program, and
-            # insert the close tag before the whitespace.
-            white = self.gen.unEmitWhitespace()
-        else:
-            white = None
-        self.gen.emitEndElement(tag, isend=isend, implied=implied)
-        if white:
-            self.gen.emitRawText(white)
-        self.tagstack.pop()
-        self.pop_xmlns()
-
-    def handle_charref(self, name):
-        self.gen.emitRawText("&#%s;" % name)
-
-    def handle_entityref(self, name):
-        self.gen.emitRawText("&%s;" % name)
-
-    def handle_data(self, data):
-        self.gen.emitRawText(data)
-
-    def handle_comment(self, data):
-        self.gen.emitRawText("<!--%s-->" % data)
-
-    def handle_decl(self, data):
-        self.gen.emitRawText("<!%s>" % data)
-
-    def handle_pi(self, data):
-        self.gen.emitRawText("<?%s>" % data)
-
-    # Internal thingies
-
-    def scan_xmlns(self, attrs):
-        nsnew = {}
-        for key, value in attrs:
-            if key.startswith("xmlns:"):
-                nsnew[key[6:]] = value
-        if nsnew:
-            self.nsstack.append(self.nsdict)
-            self.nsdict = self.nsdict.copy()
-            self.nsdict.update(nsnew)
-        else:
-            self.nsstack.append(self.nsdict)
-
-    def pop_xmlns(self):
-        self.nsdict = self.nsstack.pop()
-
-    def fixname(self, name):
-        if ':' in name:
-            prefix, suffix = name.split(':', 1)
-            if prefix == 'xmlns':
-                nsuri = self.nsdict.get(suffix)
-                if nsuri in (ZOPE_TAL_NS, ZOPE_METAL_NS, ZOPE_I18N_NS):
-                    return name, name, prefix
-            else:
-                nsuri = self.nsdict.get(prefix)
-                if nsuri == ZOPE_TAL_NS:
-                    return name, suffix, 'tal'
-                elif nsuri == ZOPE_METAL_NS:
-                    return name, suffix,  'metal'
-                elif nsuri == ZOPE_I18N_NS:
-                    return name, suffix, 'i18n'
-        return name, name, 0
-
-    def process_ns(self, name, attrs):
-        attrlist = []
-        taldict = {}
-        metaldict = {}
-        i18ndict = {}
-        name, namebase, namens = self.fixname(name)
-        for item in attrs:
-            key, value = item
-            key, keybase, keyns = self.fixname(key)
-            ns = keyns or namens # default to tag namespace
-            if ns and ns != 'unknown':
-                item = (key, value, ns)
-            if ns == 'tal':
-                if taldict.has_key(keybase):
-                    raise TALError("duplicate TAL attribute " +
-                                   `keybase`, self.getpos())
-                taldict[keybase] = value
-            elif ns == 'metal':
-                if metaldict.has_key(keybase):
-                    raise METALError("duplicate METAL attribute " +
-                                     `keybase`, self.getpos())
-                metaldict[keybase] = value
-            elif ns == 'i18n':
-                if i18ndict.has_key(keybase):
-                    raise I18NError("duplicate i18n attribute " +
-                                    `keybase`, self.getpos())
-                i18ndict[keybase] = value
-            attrlist.append(item)
-        if namens in ('metal', 'tal'):
-            taldict['tal tag'] = namens
-        return name, attrlist, taldict, metaldict, i18ndict
+BBB 2005/05/01 -- to be removed after 12 months
+"""
+import zope.deprecation
+zope.deprecation.moved('zope.tal.htmltalparser', '2.12')

Modified: Zope/branches/ajung-zpt-end-game/lib/python/TAL/ITALES.py
===================================================================
--- Zope/branches/ajung-zpt-end-game/lib/python/TAL/ITALES.py	2006-05-28 22:14:02 UTC (rev 68316)
+++ Zope/branches/ajung-zpt-end-game/lib/python/TAL/ITALES.py	2006-05-28 23:07:07 UTC (rev 68317)
@@ -1,156 +1,11 @@
 """Interface that a TALES engine provides to the METAL/TAL implementation."""
 
-try:
-    from Interface import Interface
-    from Interface.Attribute import Attribute
-except:
-    # Before 2.7
-    class Interface: pass
-    def Attribute(*args): pass
+import zope.deferredimport
+zope.deferredimport.deprecatedFrom(
+    "The TAL implementation has moved to zope.tal.  Import expression "
+    "interfaces from zope.tal.interfaces.  The old references will be "
+    "gone in Zope 2.12.",
+    'zope.tal.interfaces'
+    'ITALExpressionCompiler', 'ITALExpressionEngine', 'ITALExpressionErrorInfo'
+    )
 
-
-class ITALESCompiler(Interface):
-    """Compile-time interface provided by a TALES implementation.
-
-    The TAL compiler needs an instance of this interface to support
-    compilation of TALES expressions embedded in documents containing
-    TAL and METAL constructs.
-    """
-
-    def getCompilerError():
-        """Return the exception class raised for compilation errors.
-        """
-
-    def compile(expression):
-        """Return a compiled form of 'expression' for later evaluation.
-
-        'expression' is the source text of the expression.
-
-        The return value may be passed to the various evaluate*()
-        methods of the ITALESEngine interface.  No compatibility is
-        required for the values of the compiled expression between
-        different ITALESEngine implementations.
-        """
-
-
-class ITALESEngine(Interface):
-    """Render-time interface provided by a TALES implementation.
-
-    The TAL interpreter uses this interface to TALES to support
-    evaluation of the compiled expressions returned by
-    ITALESCompiler.compile().
-    """
-
-    def getCompiler():
-        """Return an object that supports ITALESCompiler."""
-
-    def getDefault():
-        """Return the value of the 'default' TALES expression.
-
-        Checking a value for a match with 'default' should be done
-        using the 'is' operator in Python.
-        """
-
-    def setPosition((lineno, offset)):
-        """Inform the engine of the current position in the source file.
-
-        This is used to allow the evaluation engine to report
-        execution errors so that site developers can more easily
-        locate the offending expression.
-        """
-
-    def setSourceFile(filename):
-        """Inform the engine of the name of the current source file.
-
-        This is used to allow the evaluation engine to report
-        execution errors so that site developers can more easily
-        locate the offending expression.
-        """
-
-    def beginScope():
-        """Push a new scope onto the stack of open scopes.
-        """
-
-    def endScope():
-        """Pop one scope from the stack of open scopes.
-        """
-
-    def evaluate(compiled_expression):
-        """Evaluate an arbitrary expression.
-
-        No constraints are imposed on the return value.
-        """
-
-    def evaluateBoolean(compiled_expression):
-        """Evaluate an expression that must return a Boolean value.
-        """
-
-    def evaluateMacro(compiled_expression):
-        """Evaluate an expression that must return a macro program.
-        """
-
-    def evaluateStructure(compiled_expression):
-        """Evaluate an expression that must return a structured
-        document fragment.
-
-        The result of evaluating 'compiled_expression' must be a
-        string containing a parsable HTML or XML fragment.  Any TAL
-        markup cnotained in the result string will be interpreted.
-        """
-
-    def evaluateText(compiled_expression):
-        """Evaluate an expression that must return text.
-
-        The returned text should be suitable for direct inclusion in
-        the output: any HTML or XML escaping or quoting is the
-        responsibility of the expression itself.
-        """
-
-    def evaluateValue(compiled_expression):
-        """Evaluate an arbitrary expression.
-
-        No constraints are imposed on the return value.
-        """
-
-    def createErrorInfo(exception, (lineno, offset)):
-        """Returns an ITALESErrorInfo object.
-
-        The returned object is used to provide information about the
-        error condition for the on-error handler.
-        """
-
-    def setGlobal(name, value):
-        """Set a global variable.
-
-        The variable will be named 'name' and have the value 'value'.
-        """
-
-    def setLocal(name, value):
-        """Set a local variable in the current scope.
-
-        The variable will be named 'name' and have the value 'value'.
-        """
-
-    def setRepeat(name, compiled_expression):
-        """
-        """
-
-    def translate(domain, msgid, mapping, default=None):
-        """
-        See ITranslationService.translate()
-        """
-
-
-class ITALESErrorInfo(Interface):
-
-    type = Attribute("type",
-                     "The exception class.")
-
-    value = Attribute("value",
-                      "The exception instance.")
-
-    lineno = Attribute("lineno",
-                       "The line number the error occurred on in the source.")
-
-    offset = Attribute("offset",
-                       "The character offset at which the error occurred.")

Modified: Zope/branches/ajung-zpt-end-game/lib/python/TAL/TALDefs.py
===================================================================
--- Zope/branches/ajung-zpt-end-game/lib/python/TAL/TALDefs.py	2006-05-28 22:14:02 UTC (rev 68316)
+++ Zope/branches/ajung-zpt-end-game/lib/python/TAL/TALDefs.py	2006-05-28 23:07:07 UTC (rev 68317)
@@ -13,179 +13,16 @@
 ##############################################################################
 """
 Common definitions used by TAL and METAL compilation an transformation.
+
+BBB 2005/05/01 -- to be removed after 12 months
 """
+import zope.deprecation
+zope.deprecation.moved('zope.tal.taldefs', '2.12')
 
-from types import ListType, TupleType
-
-from ITALES import ITALESErrorInfo
-
-TAL_VERSION = "1.5"
-
-XML_NS = "http://www.w3.org/XML/1998/namespace" # URI for XML namespace
-XMLNS_NS = "http://www.w3.org/2000/xmlns/" # URI for XML NS declarations
-
-ZOPE_TAL_NS = "http://xml.zope.org/namespaces/tal"
-ZOPE_METAL_NS = "http://xml.zope.org/namespaces/metal"
-ZOPE_I18N_NS = "http://xml.zope.org/namespaces/i18n"
-
-# This RE must exactly match the expression of the same name in the
-# zope.i18n.simpletranslationservice module:
-NAME_RE = "[a-zA-Z_][-a-zA-Z0-9_]*"
-
-KNOWN_METAL_ATTRIBUTES = [
-    "define-macro",
-    "use-macro",
-    "define-slot",
-    "fill-slot",
-    "slot",
-    ]
-
-KNOWN_TAL_ATTRIBUTES = [
-    "define",
-    "condition",
-    "content",
-    "replace",
-    "repeat",
-    "attributes",
-    "on-error",
-    "omit-tag",
-    "tal tag",
-    ]
-
-KNOWN_I18N_ATTRIBUTES = [
-    "translate",
-    "domain",
-    "target",
-    "source",
-    "attributes",
-    "data",
-    "name",
-    ]
-
-class TALError(Exception):
-
-    def __init__(self, msg, position=(None, None)):
-        assert msg != ""
-        self.msg = msg
-        self.lineno = position[0]
-        self.offset = position[1]
-        self.filename = None
-
-    def setFile(self, filename):
-        self.filename = filename
-
-    def __str__(self):
-        result = self.msg
-        if self.lineno is not None:
-            result = result + ", at line %d" % self.lineno
-        if self.offset is not None:
-            result = result + ", column %d" % (self.offset + 1)
-        if self.filename is not None:
-            result = result + ', in file %s' % self.filename
-        return result
-
-class METALError(TALError):
-    pass
-
-class TALESError(TALError):
-    pass
-
-class I18NError(TALError):
-    pass
-
-
-class ErrorInfo:
-
-    __implements__ = ITALESErrorInfo
-
-    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]
-
-
-
-import re
-_attr_re = re.compile(r"\s*([^\s]+)\s+([^\s].*)\Z", re.S)
-_subst_re = re.compile(r"\s*(?:(text|structure)\s+)?(.*)\Z", re.S)
-del re
-
-def parseAttributeReplacements(arg, xml):
-    dict = {}
-    for part in splitParts(arg):
-        m = _attr_re.match(part)
-        if not m:
-            raise TALError("Bad syntax in attributes: " + `part`)
-        name, expr = m.group(1, 2)
-        if not xml:
-            name = name.lower()
-        if dict.has_key(name):
-            raise TALError("Duplicate attribute name in attributes: " + `part`)
-        dict[name] = expr
-    return dict
-
-def parseSubstitution(arg, position=(None, None)):
-    m = _subst_re.match(arg)
-    if not m:
-        raise TALError("Bad syntax in substitution text: " + `arg`, position)
-    key, expr = m.group(1, 2)
-    if not key:
-        key = "text"
-    return key, expr
-
-def splitParts(arg):
-    # Break in pieces at undoubled semicolons and
-    # change double semicolons to singles:
-    arg = arg.replace(";;", "\0")
-    parts = arg.split(';')
-    parts = [p.replace("\0", ";") for p in parts]
-    if len(parts) > 1 and not parts[-1].strip():
-        del parts[-1] # It ended in a semicolon
-    return parts
-
-def isCurrentVersion(program):
-    version = getProgramVersion(program)
-    return version == TAL_VERSION
-
-def getProgramMode(program):
-    version = getProgramVersion(program)
-    if (version == TAL_VERSION and isinstance(program[1], TupleType) and
-        len(program[1]) == 2):
-        opcode, mode = program[1]
-        if opcode == "mode":
-            return mode
-    return None
-
-def getProgramVersion(program):
-    if (len(program) >= 2 and
-        isinstance(program[0], TupleType) and len(program[0]) == 2):
-        opcode, version = program[0]
-        if opcode == "version":
-            return version
-    return None
-
-import re
-_ent1_re = re.compile('&(?![A-Z#])', re.I)
-_entch_re = re.compile('&([A-Z][A-Z0-9]*)(?![A-Z0-9;])', re.I)
-_entn1_re = re.compile('&#(?![0-9X])', re.I)
-_entnx_re = re.compile('&(#X[A-F0-9]*)(?![A-F0-9;])', re.I)
-_entnd_re = re.compile('&(#[0-9][0-9]*)(?![0-9;])')
-del re
-
-def attrEscape(s):
-    """Replace special characters '&<>' by character entities,
-    except when '&' already begins a syntactically valid entity."""
-    s = _ent1_re.sub('&amp;', s)
-    s = _entch_re.sub(r'&amp;\1', s)
-    s = _entn1_re.sub('&amp;#', s)
-    s = _entnx_re.sub(r'&amp;\1', s)
-    s = _entnd_re.sub(r'&amp;\1', s)
-    s = s.replace('<', '&lt;')
-    s = s.replace('>', '&gt;')
-    s = s.replace('"', '&quot;')
-    return s
+import zope.deferredimport
+zope.deferredimport.deprecated(
+    "TALESError has been renamed TALExpressionError and should be "
+    "imported from zope.tal.taldefs.  This reference will be gone in "
+    "Zope 2.12.",
+    TALESError = 'zope.tal.taldefs.TALExpressionError'
+    )

Modified: Zope/branches/ajung-zpt-end-game/lib/python/TAL/TALGenerator.py
===================================================================
--- Zope/branches/ajung-zpt-end-game/lib/python/TAL/TALGenerator.py	2006-05-28 22:14:02 UTC (rev 68316)
+++ Zope/branches/ajung-zpt-end-game/lib/python/TAL/TALGenerator.py	2006-05-28 23:07:07 UTC (rev 68317)
@@ -13,880 +13,8 @@
 ##############################################################################
 """
 Code generator for TALInterpreter intermediate code.
-"""
 
-import re
-import cgi
-
-import TALDefs
-
-from TALDefs import NAME_RE, TAL_VERSION
-from TALDefs import I18NError, METALError, TALError
-from TALDefs import parseSubstitution
-from TranslationContext import TranslationContext, DEFAULT_DOMAIN
-
-I18N_REPLACE = 1
-I18N_CONTENT = 2
-I18N_EXPRESSION = 3
-
-_name_rx = re.compile(NAME_RE)
-
-
-class TALGenerator:
-
-    inMacroUse = 0
-    inMacroDef = 0
-    source_file = None
-
-    def __init__(self, expressionCompiler=None, xml=1, source_file=None):
-        if not expressionCompiler:
-            from DummyEngine import DummyEngine
-            expressionCompiler = DummyEngine()
-        self.expressionCompiler = expressionCompiler
-        self.CompilerError = expressionCompiler.getCompilerError()
-        # This holds the emitted opcodes representing the input
-        self.program = []
-        # The program stack for when we need to do some sub-evaluation for an
-        # intermediate result.  E.g. in an i18n:name tag for which the
-        # contents describe the ${name} value.
-        self.stack = []
-        # Another stack of postponed actions.  Elements on this stack are a
-        # dictionary; key/values contain useful information that
-        # emitEndElement needs to finish its calculations
-        self.todoStack = []
-        self.macros = {}
-        self.slots = {}
-        self.slotStack = []
-        self.xml = xml
-        self.emit("version", TAL_VERSION)
-        self.emit("mode", xml and "xml" or "html")
-        if source_file is not None:
-            self.source_file = source_file
-            self.emit("setSourceFile", source_file)
-        self.i18nContext = TranslationContext()
-        self.i18nLevel = 0
-
-    def getCode(self):
-        assert not self.stack
-        assert not self.todoStack
-        return self.optimize(self.program), self.macros
-
-    def optimize(self, program):
-        output = []
-        collect = []
-        cursor = 0
-        if self.xml:
-            endsep = "/>"
-        else:
-            endsep = " />"
-        for cursor in xrange(len(program)+1):
-            try:
-                item = program[cursor]
-            except IndexError:
-                item = (None, None)
-            opcode = item[0]
-            if opcode == "rawtext":
-                collect.append(item[1])
-                continue
-            if opcode == "endTag":
-                collect.append("</%s>" % item[1])
-                continue
-            if opcode == "startTag":
-                if self.optimizeStartTag(collect, item[1], item[2], ">"):
-                    continue
-            if opcode == "startEndTag":
-                if self.optimizeStartTag(collect, item[1], item[2], endsep):
-                    continue
-            if opcode in ("beginScope", "endScope"):
-                # Push *Scope instructions in front of any text instructions;
-                # this allows text instructions separated only by *Scope
-                # instructions to be joined together.
-                output.append(self.optimizeArgsList(item))
-                continue
-            if opcode == 'noop':
-                # This is a spacer for end tags in the face of i18n:name
-                # attributes.  We can't let the optimizer collect immediately
-                # following end tags into the same rawtextOffset.
-                opcode = None
-                pass
-            text = "".join(collect)
-            if text:
-                i = text.rfind("\n")
-                if i >= 0:
-                    i = len(text) - (i + 1)
-                    output.append(("rawtextColumn", (text, i)))
-                else:
-                    output.append(("rawtextOffset", (text, len(text))))
-            if opcode != None:
-                output.append(self.optimizeArgsList(item))
-            collect = []
-        return self.optimizeCommonTriple(output)
-
-    def optimizeArgsList(self, item):
-        if len(item) == 2:
-            return item
-        else:
-            return item[0], tuple(item[1:])
-
-    # These codes are used to indicate what sort of special actions
-    # are needed for each special attribute.  (Simple attributes don't
-    # get action codes.)
-    #
-    # The special actions (which are modal) are handled by
-    # TALInterpreter.attrAction() and .attrAction_tal().
-    #
-    # Each attribute is represented by a tuple:
-    #
-    # (name, value)                 -- a simple name/value pair, with
-    #                                  no special processing
-    #
-    # (name, value, action, *extra) -- attribute with special
-    #                                  processing needs, action is a
-    #                                  code that indicates which
-    #                                  branch to take, and *extra
-    #                                  contains additional,
-    #                                  action-specific information
-    #                                  needed by the processing
-    #
-    def optimizeStartTag(self, collect, name, attrlist, end):
-        # return true if the tag can be converted to plain text
-        if not attrlist:
-            collect.append("<%s%s" % (name, end))
-            return 1
-        opt = 1
-        new = ["<" + name]
-        for i in range(len(attrlist)):
-            item = attrlist[i]
-            if len(item) > 2:
-                opt = 0
-                name, value, action = item[:3]
-                attrlist[i] = (name, value, action) + item[3:]
-            else:
-                if item[1] is None:
-                    s = item[0]
-                else:
-                    s = '%s="%s"' % (item[0], TALDefs.attrEscape(item[1]))
-                attrlist[i] = item[0], s
-                new.append(" " + s)
-        # if no non-optimizable attributes were found, convert to plain text
-        if opt:
-            new.append(end)
-            collect.extend(new)
-        return opt
-
-    def optimizeCommonTriple(self, program):
-        if len(program) < 3:
-            return program
-        output = program[:2]
-        prev2, prev1 = output
-        for item in program[2:]:
-            if ( item[0] == "beginScope"
-                 and prev1[0] == "setPosition"
-                 and prev2[0] == "rawtextColumn"):
-                position = output.pop()[1]
-                text, column = output.pop()[1]
-                prev1 = None, None
-                closeprev = 0
-                if output and output[-1][0] == "endScope":
-                    closeprev = 1
-                    output.pop()
-                item = ("rawtextBeginScope",
-                        (text, column, position, closeprev, item[1]))
-            output.append(item)
-            prev2 = prev1
-            prev1 = item
-        return output
-
-    def todoPush(self, todo):
-        self.todoStack.append(todo)
-
-    def todoPop(self):
-        return self.todoStack.pop()
-
-    def compileExpression(self, expr):
-        try:
-            return self.expressionCompiler.compile(expr)
-        except self.CompilerError, err:
-            raise TALError('%s in expression %s' % (err.args[0], `expr`),
-                           self.position)
-
-    def pushProgram(self):
-        self.stack.append(self.program)
-        self.program = []
-
-    def popProgram(self):
-        program = self.program
-        self.program = self.stack.pop()
-        return self.optimize(program)
-
-    def pushSlots(self):
-        self.slotStack.append(self.slots)
-        self.slots = {}
-
-    def popSlots(self):
-        slots = self.slots
-        self.slots = self.slotStack.pop()
-        return slots
-
-    def emit(self, *instruction):
-        self.program.append(instruction)
-
-    def emitStartTag(self, name, attrlist, isend=0):
-        if isend:
-            opcode = "startEndTag"
-        else:
-            opcode = "startTag"
-        self.emit(opcode, name, attrlist)
-
-    def emitEndTag(self, name):
-        if self.xml and self.program and self.program[-1][0] == "startTag":
-            # Minimize empty element
-            self.program[-1] = ("startEndTag",) + self.program[-1][1:]
-        else:
-            self.emit("endTag", name)
-
-    def emitOptTag(self, name, optTag, isend):
-        program = self.popProgram() #block
-        start = self.popProgram() #start tag
-        if (isend or not program) and self.xml:
-            # Minimize empty element
-            start[-1] = ("startEndTag",) + start[-1][1:]
-            isend = 1
-        cexpr = optTag[0]
-        if cexpr:
-            cexpr = self.compileExpression(optTag[0])
-        self.emit("optTag", name, cexpr, optTag[1], isend, start, program)
-
-    def emitRawText(self, text):
-        self.emit("rawtext", text)
-
-    def emitText(self, text):
-        self.emitRawText(cgi.escape(text))
-
-    def emitDefines(self, defines):
-        for part in TALDefs.splitParts(defines):
-            m = re.match(
-                r"(?s)\s*(?:(global|local)\s+)?(%s)\s+(.*)\Z" % NAME_RE, part)
-            if not m:
-                raise TALError("invalid define syntax: " + `part`,
-                               self.position)
-            scope, name, expr = m.group(1, 2, 3)
-            scope = scope or "local"
-            cexpr = self.compileExpression(expr)
-            if scope == "local":
-                self.emit("setLocal", name, cexpr)
-            else:
-                self.emit("setGlobal", name, cexpr)
-
-    def emitOnError(self, name, onError, TALtag, isend):
-        block = self.popProgram()
-        key, expr = parseSubstitution(onError)
-        cexpr = self.compileExpression(expr)
-        if key == "text":
-            self.emit("insertText", cexpr, [])
-        else:
-            assert key == "structure"
-            self.emit("insertStructure", cexpr, {}, [])
-        if TALtag:
-            self.emitOptTag(name, (None, 1), isend)
-        else:
-            self.emitEndTag(name)
-        handler = self.popProgram()
-        self.emit("onError", block, handler)
-
-    def emitCondition(self, expr):
-        cexpr = self.compileExpression(expr)
-        program = self.popProgram()
-        self.emit("condition", cexpr, program)
-
-    def emitRepeat(self, arg):
-        m = re.match("(?s)\s*(%s)\s+(.*)\Z" % NAME_RE, arg)
-        if not m:
-            raise TALError("invalid repeat syntax: " + `arg`,
-                           self.position)
-        name, expr = m.group(1, 2)
-        cexpr = self.compileExpression(expr)
-        program = self.popProgram()
-        self.emit("loop", name, cexpr, program)
-
-    def emitSubstitution(self, arg, attrDict={}):
-        key, expr = parseSubstitution(arg)
-        cexpr = self.compileExpression(expr)
-        program = self.popProgram()
-        if key == "text":
-            self.emit("insertText", cexpr, program)
-        else:
-            assert key == "structure"
-            self.emit("insertStructure", cexpr, attrDict, program)
-
-    def emitI18nVariable(self, stuff):
-        # Used for i18n:name attributes.  arg is extra information describing
-        # how the contents of the variable should get filled in, and it will
-        # either be a 1-tuple or a 2-tuple.  If arg[0] is None, then the
-        # i18n:name value is taken implicitly from the contents of the tag,
-        # e.g. "I live in <span i18n:name="country">the USA</span>".  In this
-        # case, arg[1] is the opcode sub-program describing the contents of
-        # the tag.
-        #
-        # When arg[0] is not None, it contains the tal expression used to
-        # calculate the contents of the variable, e.g.
-        # "I live in <span i18n:name="country"
-        #                  tal:replace="here/countryOfOrigin" />"
-        varname, action, expression = stuff
-        m = _name_rx.match(varname)
-        if m is None or m.group() != varname:
-            raise TALError("illegal i18n:name: %r" % varname, self.position)
-        key = cexpr = None
-        program = self.popProgram()
-        if action == I18N_REPLACE:
-            # This is a tag with an i18n:name and a tal:replace (implicit or
-            # explicit).  Get rid of the first and last elements of the
-            # program, which are the start and end tag opcodes of the tag.
-            program = program[1:-1]
-        elif action == I18N_CONTENT:
-            # This is a tag with an i18n:name and a tal:content
-            # (explicit-only).  Keep the first and last elements of the
-            # program, so we keep the start and end tag output.
-            pass
-        else:
-            assert action == I18N_EXPRESSION
-            key, expr = parseSubstitution(expression)
-            cexpr = self.compileExpression(expr)
-        self.emit('i18nVariable',
-                  varname, program, cexpr, int(key == "structure"))
-
-    def emitTranslation(self, msgid, i18ndata):
-        program = self.popProgram()
-        if i18ndata is None:
-            self.emit('insertTranslation', msgid, program)
-        else:
-            key, expr = parseSubstitution(i18ndata)
-            cexpr = self.compileExpression(expr)
-            assert key == 'text'
-            self.emit('insertTranslation', msgid, program, cexpr)
-
-    def emitDefineMacro(self, macroName):
-        program = self.popProgram()
-        macroName = macroName.strip()
-        if self.macros.has_key(macroName):
-            raise METALError("duplicate macro definition: %s" % `macroName`,
-                             self.position)
-        if not re.match('%s$' % NAME_RE, macroName):
-            raise METALError("invalid macro name: %s" % `macroName`,
-                             self.position)
-        self.macros[macroName] = program
-        self.inMacroDef = self.inMacroDef - 1
-        self.emit("defineMacro", macroName, program)
-
-    def emitUseMacro(self, expr):
-        cexpr = self.compileExpression(expr)
-        program = self.popProgram()
-        self.inMacroUse = 0
-        self.emit("useMacro", expr, cexpr, self.popSlots(), program)
-
-    def emitDefineSlot(self, slotName):
-        program = self.popProgram()
-        slotName = slotName.strip()
-        if not re.match('%s$' % NAME_RE, slotName):
-            raise METALError("invalid slot name: %s" % `slotName`,
-                             self.position)
-        self.emit("defineSlot", slotName, program)
-
-    def emitFillSlot(self, slotName):
-        program = self.popProgram()
-        slotName = slotName.strip()
-        if self.slots.has_key(slotName):
-            raise METALError("duplicate fill-slot name: %s" % `slotName`,
-                             self.position)
-        if not re.match('%s$' % NAME_RE, slotName):
-            raise METALError("invalid slot name: %s" % `slotName`,
-                             self.position)
-        self.slots[slotName] = program
-        self.inMacroUse = 1
-        self.emit("fillSlot", slotName, program)
-
-    def unEmitWhitespace(self):
-        collect = []
-        i = len(self.program) - 1
-        while i >= 0:
-            item = self.program[i]
-            if item[0] != "rawtext":
-                break
-            text = item[1]
-            if not re.match(r"\A\s*\Z", text):
-                break
-            collect.append(text)
-            i = i-1
-        del self.program[i+1:]
-        if i >= 0 and self.program[i][0] == "rawtext":
-            text = self.program[i][1]
-            m = re.search(r"\s+\Z", text)
-            if m:
-                self.program[i] = ("rawtext", text[:m.start()])
-                collect.append(m.group())
-        collect.reverse()
-        return "".join(collect)
-
-    def unEmitNewlineWhitespace(self):
-        collect = []
-        i = len(self.program)
-        while i > 0:
-            i = i-1
-            item = self.program[i]
-            if item[0] != "rawtext":
-                break
-            text = item[1]
-            if re.match(r"\A[ \t]*\Z", text):
-                collect.append(text)
-                continue
-            m = re.match(r"(?s)^(.*)(\n[ \t]*)\Z", text)
-            if not m:
-                break
-            text, rest = m.group(1, 2)
-            collect.reverse()
-            rest = rest + "".join(collect)
-            del self.program[i:]
-            if text:
-                self.emit("rawtext", text)
-            return rest
-        return None
-
-    def replaceAttrs(self, attrlist, repldict):
-        # Each entry in attrlist starts like (name, value).
-        # Result is (name, value, action, expr, xlat) if there is a
-        # tal:attributes entry for that attribute.  Additional attrs
-        # defined only by tal:attributes are added here.
-        #
-        # (name, value, action, expr, xlat)
-        if not repldict:
-            return attrlist
-        newlist = []
-        for item in attrlist:
-            key = item[0]
-            if repldict.has_key(key):
-                expr, xlat, msgid = repldict[key]
-                item = item[:2] + ("replace", expr, xlat, msgid)
-                del repldict[key]
-            newlist.append(item)
-        # Add dynamic-only attributes
-        for key, (expr, xlat, msgid) in repldict.items():
-            newlist.append((key, None, "insert", expr, xlat, msgid))
-        return newlist
-
-    def emitStartElement(self, name, attrlist, taldict, metaldict, i18ndict,
-                         position=(None, None), isend=0):
-        if not taldict and not metaldict and not i18ndict:
-            # Handle the simple, common case
-            self.emitStartTag(name, attrlist, isend)
-            self.todoPush({})
-            if isend:
-                self.emitEndElement(name, isend)
-            return
-
-        self.position = position
-        for key, value in taldict.items():
-            if key not in TALDefs.KNOWN_TAL_ATTRIBUTES:
-                raise TALError("bad TAL attribute: " + `key`, position)
-            if not (value or key == 'omit-tag'):
-                raise TALError("missing value for TAL attribute: " +
-                               `key`, position)
-        for key, value in metaldict.items():
-            if key not in TALDefs.KNOWN_METAL_ATTRIBUTES:
-                raise METALError("bad METAL attribute: " + `key`,
-                                 position)
-            if not value:
-                raise TALError("missing value for METAL attribute: " +
-                               `key`, position)
-        for key, value in i18ndict.items():
-            if key not in TALDefs.KNOWN_I18N_ATTRIBUTES:
-                raise I18NError("bad i18n attribute: " + `key`, position)
-            if not value and key in ("attributes", "data", "id"):
-                raise I18NError("missing value for i18n attribute: " +
-                                `key`, position)
-        todo = {}
-        defineMacro = metaldict.get("define-macro")
-        useMacro = metaldict.get("use-macro")
-        defineSlot = metaldict.get("define-slot")
-        fillSlot = metaldict.get("fill-slot")
-        define = taldict.get("define")
-        condition = taldict.get("condition")
-        repeat = taldict.get("repeat")
-        content = taldict.get("content")
-        replace = taldict.get("replace")
-        attrsubst = taldict.get("attributes")
-        onError = taldict.get("on-error")
-        omitTag = taldict.get("omit-tag")
-        TALtag = taldict.get("tal tag")
-        i18nattrs = i18ndict.get("attributes")
-        # Preserve empty string if implicit msgids are used.  We'll generate
-        # code with the msgid='' and calculate the right implicit msgid during
-        # interpretation phase.
-        msgid = i18ndict.get("translate")
-        varname = i18ndict.get('name')
-        i18ndata = i18ndict.get('data')
-
-        if varname and not self.i18nLevel:
-            raise I18NError(
-                "i18n:name can only occur inside a translation unit",
-                position)
-
-        if i18ndata and not msgid:
-            raise I18NError("i18n:data must be accompanied by i18n:translate",
-                            position)
-
-        if len(metaldict) > 1 and (defineMacro or useMacro):
-            raise METALError("define-macro and use-macro cannot be used "
-                             "together or with define-slot or fill-slot",
-                             position)
-        if replace:
-            if content:
-                raise TALError(
-                    "tal:content and tal:replace are mutually exclusive",
-                    position)
-            if msgid is not None:
-                raise I18NError(
-                    "i18n:translate and tal:replace are mutually exclusive",
-                    position)
-
-        repeatWhitespace = None
-        if repeat:
-            # Hack to include preceding whitespace in the loop program
-            repeatWhitespace = self.unEmitNewlineWhitespace()
-        if position != (None, None):
-            # XXX at some point we should insist on a non-trivial position
-            self.emit("setPosition", position)
-        if self.inMacroUse:
-            if fillSlot:
-                self.pushProgram()
-                if self.source_file is not None:
-                    self.emit("setSourceFile", self.source_file)
-                todo["fillSlot"] = fillSlot
-                self.inMacroUse = 0
-        else:
-            if fillSlot:
-                raise METALError("fill-slot must be within a use-macro",
-                                 position)
-        if not self.inMacroUse:
-            if defineMacro:
-                self.pushProgram()
-                self.emit("version", TAL_VERSION)
-                self.emit("mode", self.xml and "xml" or "html")
-                if self.source_file is not None:
-                    self.emit("setSourceFile", self.source_file)
-                todo["defineMacro"] = defineMacro
-                self.inMacroDef = self.inMacroDef + 1
-            if useMacro:
-                self.pushSlots()
-                self.pushProgram()
-                todo["useMacro"] = useMacro
-                self.inMacroUse = 1
-            if defineSlot:
-                if not self.inMacroDef:
-                    raise METALError(
-                        "define-slot must be within a define-macro",
-                        position)
-                self.pushProgram()
-                todo["defineSlot"] = defineSlot
-
-        if defineSlot or i18ndict:
-
-            domain = i18ndict.get("domain") or self.i18nContext.domain
-            source = i18ndict.get("source") or self.i18nContext.source
-            target = i18ndict.get("target") or self.i18nContext.target
-            if (  domain != DEFAULT_DOMAIN
-                  or source is not None
-                  or target is not None):
-                self.i18nContext = TranslationContext(self.i18nContext,
-                                                      domain=domain,
-                                                      source=source,
-                                                      target=target)
-                self.emit("beginI18nContext",
-                          {"domain": domain, "source": source,
-                           "target": target})
-                todo["i18ncontext"] = 1
-        if taldict or i18ndict:
-            dict = {}
-            for item in attrlist:
-                key, value = item[:2]
-                dict[key] = value
-            self.emit("beginScope", dict)
-            todo["scope"] = 1
-        if onError:
-            self.pushProgram() # handler
-            if TALtag:
-                self.pushProgram() # start
-            self.emitStartTag(name, list(attrlist)) # Must copy attrlist!
-            if TALtag:
-                self.pushProgram() # start
-            self.pushProgram() # block
-            todo["onError"] = onError
-        if define:
-            self.emitDefines(define)
-            todo["define"] = define
-        if condition:
-            self.pushProgram()
-            todo["condition"] = condition
-        if repeat:
-            todo["repeat"] = repeat
-            self.pushProgram()
-            if repeatWhitespace:
-                self.emitText(repeatWhitespace)
-        if content:
-            if varname:
-                todo['i18nvar'] = (varname, I18N_CONTENT, None)
-                todo["content"] = content
-                self.pushProgram()
-            else:
-                todo["content"] = content
-        elif replace:
-            # tal:replace w/ i18n:name has slightly different semantics.  What
-            # we're actually replacing then is the contents of the ${name}
-            # placeholder.
-            if varname:
-                todo['i18nvar'] = (varname, I18N_EXPRESSION, replace)
-            else:
-                todo["replace"] = replace
-            self.pushProgram()
-        # i18n:name w/o tal:replace uses the content as the interpolation
-        # dictionary values
-        elif varname:
-            todo['i18nvar'] = (varname, I18N_REPLACE, None)
-            self.pushProgram()
-        if msgid is not None:
-            self.i18nLevel += 1
-            todo['msgid'] = msgid
-        if i18ndata:
-            todo['i18ndata'] = i18ndata
-        optTag = omitTag is not None or TALtag
-        if optTag:
-            todo["optional tag"] = omitTag, TALtag
-            self.pushProgram()
-        if attrsubst or i18nattrs:
-            if attrsubst:
-                repldict = TALDefs.parseAttributeReplacements(attrsubst,
-                                                              self.xml)
-            else:
-                repldict = {}
-            if i18nattrs:
-                i18nattrs = _parseI18nAttributes(i18nattrs, attrlist, repldict,
-                                                 self.position, self.xml,
-                                                 self.source_file)
-            else:
-                i18nattrs = {}
-            # Convert repldict's name-->expr mapping to a
-            # name-->(compiled_expr, translate) mapping
-            for key, value in repldict.items():
-                if i18nattrs.get(key, None):
-                    raise I18NError(
-                      ("attribute [%s] cannot both be part of tal:attributes" +
-                      " and have a msgid in i18n:attributes") % key,
-                    position)
-                ce = self.compileExpression(value)
-                repldict[key] = ce, key in i18nattrs, i18nattrs.get(key)
-            for key in i18nattrs:
-                if not repldict.has_key(key):
-                    repldict[key] = None, 1, i18nattrs.get(key)
-        else:
-            repldict = {}
-        if replace:
-            todo["repldict"] = repldict
-            repldict = {}
-        self.emitStartTag(name, self.replaceAttrs(attrlist, repldict), isend)
-        if optTag:
-            self.pushProgram()
-        if content and not varname:
-            self.pushProgram()
-        if msgid is not None:
-            self.pushProgram()
-        if content and varname:
-            self.pushProgram()
-        if todo and position != (None, None):
-            todo["position"] = position
-        self.todoPush(todo)
-        if isend:
-            self.emitEndElement(name, isend)
-
-    def emitEndElement(self, name, isend=0, implied=0):
-        todo = self.todoPop()
-        if not todo:
-            # Shortcut
-            if not isend:
-                self.emitEndTag(name)
-            return
-
-        self.position = position = todo.get("position", (None, None))
-        defineMacro = todo.get("defineMacro")
-        useMacro = todo.get("useMacro")
-        defineSlot = todo.get("defineSlot")
-        fillSlot = todo.get("fillSlot")
-        repeat = todo.get("repeat")
-        content = todo.get("content")
-        replace = todo.get("replace")
-        condition = todo.get("condition")
-        onError = todo.get("onError")
-        repldict = todo.get("repldict", {})
-        scope = todo.get("scope")
-        optTag = todo.get("optional tag")
-        msgid = todo.get('msgid')
-        i18ncontext = todo.get("i18ncontext")
-        varname = todo.get('i18nvar')
-        i18ndata = todo.get('i18ndata')
-
-        if implied > 0:
-            if defineMacro or useMacro or defineSlot or fillSlot:
-                exc = METALError
-                what = "METAL"
-            else:
-                exc = TALError
-                what = "TAL"
-            raise exc("%s attributes on <%s> require explicit </%s>" %
-                      (what, name, name), position)
-
-        # If there's no tal:content or tal:replace in the tag with the
-        # i18n:name, tal:replace is the default.
-        if content:
-            self.emitSubstitution(content, {})
-        # If we're looking at an implicit msgid, emit the insertTranslation
-        # opcode now, so that the end tag doesn't become part of the implicit
-        # msgid.  If we're looking at an explicit msgid, it's better to emit
-        # the opcode after the i18nVariable opcode so we can better handle
-        # tags with both of them in them (and in the latter case, the contents
-        # would be thrown away for msgid purposes).
-        #
-        # Still, we should emit insertTranslation opcode before i18nVariable
-        # in case tal:content, i18n:translate and i18n:name in the same tag
-        if msgid is not None:
-            if (not varname) or (
-                varname and (varname[1] == I18N_CONTENT)):
-                self.emitTranslation(msgid, i18ndata)
-            self.i18nLevel -= 1
-        if optTag:
-            self.emitOptTag(name, optTag, isend)
-        elif not isend:
-            # If we're processing the end tag for a tag that contained
-            # i18n:name, we need to make sure that optimize() won't collect
-            # immediately following end tags into the same rawtextOffset, so
-            # put a spacer here that the optimizer will recognize.
-            if varname:
-                self.emit('noop')
-            self.emitEndTag(name)
-        # If i18n:name appeared in the same tag as tal:replace then we're
-        # going to do the substitution a little bit differently.  The results
-        # of the expression go into the i18n substitution dictionary.
-        if replace:
-            self.emitSubstitution(replace, repldict)
-        elif varname:
-            # o varname[0] is the variable name
-            # o varname[1] is either
-            #   - I18N_REPLACE for implicit tal:replace
-            #   - I18N_CONTENT for tal:content
-            #   - I18N_EXPRESSION for explicit tal:replace
-            # o varname[2] will be None for the first two actions and the
-            #   replacement tal expression for the third action.  This
-            #   can include a 'text' or 'structure' indicator.
-            assert (varname[1]
-                    in [I18N_REPLACE, I18N_CONTENT, I18N_EXPRESSION])
-            self.emitI18nVariable(varname)
-        # Do not test for "msgid is not None", i.e. we only want to test for
-        # explicit msgids here.  See comment above.
-        if msgid is not None: 
-            # in case tal:content, i18n:translate and i18n:name in the
-            # same tag insertTranslation opcode has already been
-            # emitted
-            if varname and (varname[1] <> I18N_CONTENT):
-                self.emitTranslation(msgid, i18ndata)
-        if repeat:
-            self.emitRepeat(repeat)
-        if condition:
-            self.emitCondition(condition)
-        if onError:
-            self.emitOnError(name, onError, optTag and optTag[1], isend)
-        if scope:
-            self.emit("endScope")
-        if i18ncontext:
-            self.emit("endI18nContext")
-            assert self.i18nContext.parent is not None
-            self.i18nContext = self.i18nContext.parent
-        if defineSlot:
-            self.emitDefineSlot(defineSlot)
-        if fillSlot:
-            self.emitFillSlot(fillSlot)
-        if useMacro:
-            self.emitUseMacro(useMacro)
-        if defineMacro:
-            self.emitDefineMacro(defineMacro)
-
-
-def _parseI18nAttributes(i18nattrs, attrlist, repldict, position,
-                         xml, source_file):
-
-    def addAttribute(dic, attr, msgid, position, xml):
-        if not xml:
-            attr = attr.lower()
-        if attr in dic:
-            raise TALError(
-                "attribute may only be specified once in i18n:attributes: "
-                + attr,
-                position)
-        dic[attr] = msgid
-
-    d = {}
-    if ';' in i18nattrs:
-        i18nattrlist = i18nattrs.split(';')
-        i18nattrlist = [attr.strip().split() 
-                        for attr in i18nattrlist if attr.strip()]
-        for parts in i18nattrlist:
-            if len(parts) > 2:
-                raise TALError("illegal i18n:attributes specification: %r"
-                                % parts, position)
-            if len(parts) == 2:
-                attr, msgid = parts
-            else:
-                # len(parts) == 1
-                attr = parts[0]
-                msgid = None
-            addAttribute(d, attr, msgid, position, xml)
-    else:
-        i18nattrlist = i18nattrs.split()
-        if len(i18nattrlist) == 1:
-            addAttribute(d, i18nattrlist[0], None, position, xml)
-        elif len(i18nattrlist) == 2:
-            staticattrs = [attr[0] for attr in attrlist if len(attr) == 2]
-            if (not i18nattrlist[1] in staticattrs) and (
-                not i18nattrlist[1] in repldict):
-                attr, msgid = i18nattrlist
-                addAttribute(d, attr, msgid, position, xml)    
-            else:
-                import warnings
-                warnings.warn(I18N_ATTRIBUTES_WARNING
-                % (source_file, str(position), i18nattrs)
-                , DeprecationWarning)
-                msgid = None
-                for attr in i18nattrlist:
-                    addAttribute(d, attr, msgid, position, xml)    
-        else:    
-            import warnings
-            warnings.warn(I18N_ATTRIBUTES_WARNING
-            % (source_file, str(position), i18nattrs)
-            , DeprecationWarning)
-            msgid = None
-            for attr in i18nattrlist:
-                addAttribute(d, attr, msgid, position, xml)    
-    return d
-
-I18N_ATTRIBUTES_WARNING = (
-    'Space separated attributes in i18n:attributes'
-    ' are deprecated (i18n:attributes="value title"). Please use'
-    ' semicolon to separate attributes'
-    ' (i18n:attributes="value; title").'
-    '\nFile %s at row, column %s\nAttributes %s')
-
-def test():
-    t = TALGenerator()
-    t.pushProgram()
-    t.emit("bar")
-    p = t.popProgram()
-    t.emit("foo", p)
-
-if __name__ == "__main__":
-    test()
+BBB 2005/05/01 -- to be removed after 12 months
+"""
+import zope.deprecation
+zope.deprecation.moved('zope.tal.talgenerator', '2.12')

Modified: Zope/branches/ajung-zpt-end-game/lib/python/TAL/TALInterpreter.py
===================================================================
--- Zope/branches/ajung-zpt-end-game/lib/python/TAL/TALInterpreter.py	2006-05-28 22:14:02 UTC (rev 68316)
+++ Zope/branches/ajung-zpt-end-game/lib/python/TAL/TALInterpreter.py	2006-05-28 23:07:07 UTC (rev 68317)
@@ -13,828 +13,16 @@
 ##############################################################################
 """Interpreter for a pre-compiled TAL program.
 
+BBB 2005/05/01 -- to be removed after 12 months
+
 $Id$
 """
-import cgi
-import sys
-import re
+import zope.deprecation
+zope.deprecation.moved('zope.tal.talinterpreter', '2.12')
 
-# Do not use cStringIO here!  It's not unicode aware. :(
-from StringIO import StringIO
-from DocumentTemplate.DT_Util import ustr
-from ZODB.POSException import ConflictError
-
-from zope.i18nmessageid import Message
-
-from TALDefs import attrEscape, TAL_VERSION, METALError
-from TALDefs import isCurrentVersion
-from TALDefs import getProgramVersion, getProgramMode
-from TALGenerator import TALGenerator
-from TranslationContext import TranslationContext
-
-I18nMessageTypes = (Message,)
-
-# TODO: In Python 2.4 we can use frozenset() instead of dict.fromkeys()
-BOOLEAN_HTML_ATTRS = dict.fromkeys([
-    # List of Boolean attributes in HTML that should be rendered in
-    # minimized form (e.g. <img ismap> rather than <img ismap="">)
-    # From http://www.w3.org/TR/xhtml1/#guidelines (C.10)
-    # TODO: The problem with this is that this is not valid XML and
-    # can't be parsed back!
-    "compact", "nowrap", "ismap", "declare", "noshade", "checked",
-    "disabled", "readonly", "multiple", "selected", "noresize",
-    "defer"
-])
-
-_nulljoin = ''.join
-_spacejoin = ' '.join
-
-def normalize(text):
-    # Now we need to normalize the whitespace in implicit message ids and
-    # implicit $name substitution values by stripping leading and trailing
-    # whitespace, and folding all internal whitespace to a single space.
-    return _spacejoin(text.split())
-
-
-NAME_RE = r"[a-zA-Z][a-zA-Z0-9_]*"
-_interp_regex = re.compile(r'(?<!\$)(\$(?:%(n)s|{%(n)s}))' %({'n': NAME_RE}))
-_get_var_regex = re.compile(r'%(n)s' %({'n': NAME_RE}))
-
-def interpolate(text, mapping):
-    """Interpolate ${keyword} substitutions.
-
-    This is called when no translation is provided by the translation
-    service.
-    """
-    if not mapping:
-        return text
-    # Find all the spots we want to substitute.
-    to_replace = _interp_regex.findall(text)
-    # Now substitute with the variables in mapping.
-    for string in to_replace:
-        var = _get_var_regex.findall(string)[0]
-        if mapping.has_key(var):
-            # Call ustr because we may have an integer for instance.
-            subst = ustr(mapping[var])
-            try:
-                text = text.replace(string, subst)
-            except UnicodeError:
-                # subst contains high-bit chars...
-                # As we have no way of knowing the correct encoding,
-                # substitue something instead of raising an exception.
-                subst = `subst`[1:-1]
-                text = text.replace(string, subst)
-    return text
-
-
-class AltTALGenerator(TALGenerator):
-
-    def __init__(self, repldict, expressionCompiler=None, xml=0):
-        self.repldict = repldict
-        self.enabled = 1
-        TALGenerator.__init__(self, expressionCompiler, xml)
-
-    def enable(self, enabled):
-        self.enabled = enabled
-
-    def emit(self, *args):
-        if self.enabled:
-            TALGenerator.emit(self, *args)
-
-    def emitStartElement(self, name, attrlist, taldict, metaldict, i18ndict,
-                         position=(None, None), isend=0):
-        metaldict = {}
-        taldict = {}
-        i18ndict = {}
-        if self.enabled and self.repldict:
-            taldict["attributes"] = "x x"
-        TALGenerator.emitStartElement(self, name, attrlist,
-                                      taldict, metaldict, i18ndict,
-                                      position, isend)
-
-    def replaceAttrs(self, attrlist, repldict):
-        if self.enabled and self.repldict:
-            repldict = self.repldict
-            self.repldict = None
-        return TALGenerator.replaceAttrs(self, attrlist, repldict)
-
-
-class TALInterpreter:
-    """TAL interpreter.
-    """
-
-    def __init__(self, program, macros, engine, stream=None,
-                 debug=0, wrap=60, metal=1, tal=1, showtal=-1,
-                 strictinsert=1, stackLimit=100, i18nInterpolate=1):
-        """Create a TAL interpreter.
-
-        Optional arguments:
-
-            stream -- output stream (defaults to sys.stdout).
-
-            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 (TODO: why?).
-
-            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).
-
-        """
-        self.program = program
-        self.macros = macros
-        self.engine = engine # Execution engine (aka context)
-        self.Default = engine.getDefault()
-        self._currentTag = ""
-        self._stream_stack = [stream or sys.stdout]
-        self.popStream()
-        self.debug = debug
-        self.wrap = wrap
-        self.metal = metal
-        self.tal = tal
-        if tal:
-            self.dispatch = self.bytecode_handlers_tal
-        else:
-            self.dispatch = self.bytecode_handlers
-        assert showtal in (-1, 0, 1)
-        if showtal == -1:
-            showtal = (not tal)
-        self.showtal = showtal
-        self.strictinsert = strictinsert
-        self.stackLimit = stackLimit
-        self.html = 0
-        self.endsep = "/>"
-        self.endlen = len(self.endsep)
-        self.macroStack = []
-        self.position = None, None  # (lineno, offset)
-        self.col = 0
-        self.level = 0
-        self.scopeLevel = 0
-        self.sourceFile = None
-        self.i18nStack = []
-        self.i18nInterpolate = i18nInterpolate
-        self.i18nContext = TranslationContext()
-
-    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 saveState(self):
-        return (self.position, self.col, self.stream, self._stream_stack,
-                self.scopeLevel, self.level, self.i18nContext)
-
-    def restoreState(self, state):
-        (self.position, self.col, self.stream,
-         self._stream_stack, scopeLevel, level, i18n) = state
-        self._stream_write = self.stream.write
-        assert self.level == level
-        while self.scopeLevel > scopeLevel:
-            self.engine.endScope()
-            self.scopeLevel = self.scopeLevel - 1
-        self.engine.setPosition(self.position)
-        self.i18nContext = i18n
-
-    def restoreOutputState(self, state):
-        (dummy, self.col, self.stream,
-         self._stream_stack, scopeLevel, level, i18n) = state
-        self._stream_write = self.stream.write
-        assert self.level == level
-        assert self.scopeLevel == scopeLevel
-
-    def pushMacro(self, macroName, slots, entering=1):
-        if len(self.macroStack) >= self.stackLimit:
-            raise METALError("macro nesting limit (%d) exceeded "
-                             "by %s" % (self.stackLimit, `macroName`))
-        self.macroStack.append([macroName, slots, entering, self.i18nContext])
-
-    def popMacro(self):
-        return self.macroStack.pop()
-
-    def __call__(self):
-        assert self.level == 0
-        assert self.scopeLevel == 0
-        assert self.i18nContext.parent is None
-        self.interpret(self.program)
-        assert self.level == 0
-        assert self.scopeLevel == 0
-        assert self.i18nContext.parent is None
-        if self.col > 0:
-            self._stream_write("\n")
-            self.col = 0
-
-    def pushStream(self, newstream):
-        self._stream_stack.append(self.stream)
-        self.stream = newstream
-        self._stream_write = self.stream.write
-
-    def popStream(self):
-        self.stream = self._stream_stack.pop()
-        self._stream_write = self.stream.write
-
-    def stream_write(self, s,
-                     len=len):
-        self._stream_write(s)
-        i = s.rfind('\n')
-        if i < 0:
-            self.col = self.col + len(s)
-        else:
-            self.col = len(s) - (i + 1)
-
-    bytecode_handlers = {}
-
-    def interpret(self, program):
-        oldlevel = self.level
-        self.level = oldlevel + 1
-        handlers = self.dispatch
-        try:
-            if self.debug:
-                for (opcode, args) in program:
-                    s = "%sdo_%s(%s)\n" % ("    "*self.level, opcode,
-                                           repr(args))
-                    if len(s) > 80:
-                        s = s[:76] + "...\n"
-                    sys.stderr.write(s)
-                    handlers[opcode](self, args)
-            else:
-                for (opcode, args) in program:
-                    handlers[opcode](self, args)
-        finally:
-            self.level = oldlevel
-
-    def do_version(self, version):
-        assert version == TAL_VERSION
-    bytecode_handlers["version"] = do_version
-
-    def do_mode(self, mode):
-        assert mode in ("html", "xml")
-        self.html = (mode == "html")
-        if self.html:
-            self.endsep = " />"
-        else:
-            self.endsep = "/>"
-        self.endlen = len(self.endsep)
-    bytecode_handlers["mode"] = do_mode
-
-    def do_setSourceFile(self, source_file):
-        self.sourceFile = source_file
-        self.engine.setSourceFile(source_file)
-    bytecode_handlers["setSourceFile"] = do_setSourceFile
-
-    def do_setPosition(self, position):
-        self.position = position
-        self.engine.setPosition(position)
-    bytecode_handlers["setPosition"] = do_setPosition
-
-    def do_startEndTag(self, stuff):
-        self.do_startTag(stuff, self.endsep, self.endlen)
-    bytecode_handlers["startEndTag"] = do_startEndTag
-
-    def do_startTag(self, (name, attrList),
-                    end=">", endlen=1, _len=len):
-        # The bytecode generator does not cause calls to this method
-        # for start tags with no attributes; those are optimized down
-        # to rawtext events.  Hence, there is no special "fast path"
-        # for that case.
-        self._currentTag = name
-        L = ["<", name]
-        append = L.append
-        col = self.col + _len(name) + 1
-        wrap = self.wrap
-        align = col + 1
-        if align >= wrap/2:
-            align = 4  # Avoid a narrow column far to the right
-        attrAction = self.dispatch["<attrAction>"]
-        try:
-            for item in attrList:
-                if _len(item) == 2:
-                    name, s = item
-                else:
-                    # item[2] is the 'action' field:
-                    if item[2] in ('metal', 'tal', 'xmlns', 'i18n'):
-                        if not self.showtal:
-                            continue
-                        ok, name, s = self.attrAction(item)
-                    else:
-                        ok, name, s = attrAction(self, item)
-                    if not ok:
-                        continue
-                slen = _len(s)
-                if (wrap and
-                    col >= align and
-                    col + 1 + slen > wrap):
-                    append("\n")
-                    append(" "*align)
-                    col = align + slen
-                else:
-                    append(" ")
-                    col = col + 1 + slen
-                append(s)
-            append(end)
-            col = col + endlen
-        finally:
-            self._stream_write(_nulljoin(L))
-            self.col = col
-    bytecode_handlers["startTag"] = do_startTag
-
-    def attrAction(self, item):
-        name, value, action = item[:3]
-        if action == 'insert':
-            return 0, name, value
-        macs = self.macroStack
-        if action == 'metal' and self.metal and macs:
-            if len(macs) > 1 or not macs[-1][2]:
-                # Drop all METAL attributes at a use-depth above one.
-                return 0, name, value
-            # Clear 'entering' flag
-            macs[-1][2] = 0
-            # Convert or drop depth-one METAL attributes.
-            i = name.rfind(":") + 1
-            prefix, suffix = name[:i], name[i:]
-            if suffix == "define-macro":
-                # Convert define-macro as we enter depth one.
-                name = prefix + "use-macro"
-                value = macs[-1][0] # Macro name
-            elif suffix == "define-slot":
-                name = prefix + "fill-slot"
-            elif suffix == "fill-slot":
-                pass
-            else:
-                return 0, name, value
-
-        if value is None:
-            value = name
-        else:
-            value = '%s="%s"' % (name, attrEscape(value))
-        return 1, name, value
-
-    def attrAction_tal(self, item):
-        name, value, action = item[:3]
-        ok = 1
-        expr, xlat, msgid = item[3:]
-        if self.html and name.lower() in BOOLEAN_HTML_ATTRS:
-            evalue = self.engine.evaluateBoolean(item[3])
-            if evalue is self.Default:
-                if action == 'insert': # Cancelled insert
-                    ok = 0
-            elif evalue:
-                value = None
-            else:
-                ok = 0
-        elif expr is not None:
-            evalue = self.engine.evaluateText(item[3])
-            if evalue is self.Default:
-                if action == 'insert': # Cancelled insert
-                    ok = 0
-            else:
-                if evalue is None:
-                    ok = 0
-                value = evalue
-        else:
-            evalue = None
-
-        if ok:
-            if xlat:
-                translated = self.translate(msgid or value, value, {})
-                if translated is not None:
-                    value = translated
-            if value is None:
-                value = name
-            elif evalue is self.Default:
-                value = attrEscape(value)
-            else:
-                value = cgi.escape(value, quote=1)
-            value = '%s="%s"' % (name, value)
-        return ok, name, value
-    bytecode_handlers["<attrAction>"] = attrAction
-
-    def no_tag(self, start, program):
-        state = self.saveState()
-        self.stream = stream = self.StringIO()
-        self._stream_write = stream.write
-        self.interpret(start)
-        self.restoreOutputState(state)
-        self.interpret(program)
-
-    def do_optTag(self, (name, cexpr, tag_ns, isend, start, program),
-                  omit=0):
-        if tag_ns and not self.showtal:
-            return self.no_tag(start, program)
-
-        self.interpret(start)
-        if not isend:
-            self.interpret(program)
-            s = '</%s>' % name
-            self._stream_write(s)
-            self.col = self.col + len(s)
-
-    def do_optTag_tal(self, stuff):
-        cexpr = stuff[1]
-        if cexpr is not None and (cexpr == '' or
-                                  self.engine.evaluateBoolean(cexpr)):
-            self.no_tag(stuff[-2], stuff[-1])
-        else:
-            self.do_optTag(stuff)
-    bytecode_handlers["optTag"] = do_optTag
-
-    def do_rawtextBeginScope(self, (s, col, position, closeprev, dict)):
-        self._stream_write(s)
-        self.col = col
-        self.do_setPosition(position)
-        if closeprev:
-            engine = self.engine
-            engine.endScope()
-            engine.beginScope()
-        else:
-            self.engine.beginScope()
-            self.scopeLevel = self.scopeLevel + 1
-
-    def do_rawtextBeginScope_tal(self, (s, col, position, closeprev, dict)):
-        self._stream_write(s)
-        self.col = col
-        engine = self.engine
-        self.position = position
-        engine.setPosition(position)
-        if closeprev:
-            engine.endScope()
-            engine.beginScope()
-        else:
-            engine.beginScope()
-            self.scopeLevel = self.scopeLevel + 1
-        engine.setLocal("attrs", dict)
-    bytecode_handlers["rawtextBeginScope"] = do_rawtextBeginScope
-
-    def do_beginScope(self, dict):
-        self.engine.beginScope()
-        self.scopeLevel = self.scopeLevel + 1
-
-    def do_beginScope_tal(self, dict):
-        engine = self.engine
-        engine.beginScope()
-        engine.setLocal("attrs", dict)
-        self.scopeLevel = self.scopeLevel + 1
-    bytecode_handlers["beginScope"] = do_beginScope
-
-    def do_endScope(self, notused=None):
-        self.engine.endScope()
-        self.scopeLevel = self.scopeLevel - 1
-    bytecode_handlers["endScope"] = do_endScope
-
-    def do_setLocal(self, notused):
-        pass
-
-    def do_setLocal_tal(self, (name, expr)):
-        self.engine.setLocal(name, self.engine.evaluateValue(expr))
-    bytecode_handlers["setLocal"] = do_setLocal
-
-    def do_setGlobal_tal(self, (name, expr)):
-        self.engine.setGlobal(name, self.engine.evaluateValue(expr))
-    bytecode_handlers["setGlobal"] = do_setLocal
-
-    def do_beginI18nContext(self, settings):
-        get = settings.get
-        self.i18nContext = TranslationContext(self.i18nContext,
-                                              domain=get("domain"),
-                                              source=get("source"),
-                                              target=get("target"))
-    bytecode_handlers["beginI18nContext"] = do_beginI18nContext
-
-    def do_endI18nContext(self, notused=None):
-        self.i18nContext = self.i18nContext.parent
-        assert self.i18nContext is not None
-    bytecode_handlers["endI18nContext"] = do_endI18nContext
-
-    def do_insertText(self, stuff):
-        self.interpret(stuff[1])
-
-    def do_insertText_tal(self, stuff):
-        text = self.engine.evaluateText(stuff[0])
-        if text is None:
-            return
-        if text is self.Default:
-            self.interpret(stuff[1])
-            return
-        if isinstance(text, I18nMessageTypes):
-            # Translate this now.
-            text = self.engine.translate(text.domain, text, 
-                                         text.mapping, default=text.default)
-        s = cgi.escape(text)
-        self._stream_write(s)
-        i = s.rfind('\n')
-        if i < 0:
-            self.col = self.col + len(s)
-        else:
-            self.col = len(s) - (i + 1)
-    bytecode_handlers["insertText"] = do_insertText
-
-    def do_i18nVariable(self, stuff):
-        varname, program, expression, structure = stuff
-        if expression is None:
-            # The value is implicitly the contents of this tag, so we have to
-            # evaluate the mini-program to get the value of the variable.
-            state = self.saveState()
-            try:
-                tmpstream = self.StringIO()
-                self.pushStream(tmpstream)
-                try:
-                    self.interpret(program)
-                finally:
-                    self.popStream()
-                if self.html and self._currentTag == "pre":
-                    value = tmpstream.getvalue()
-                else:
-                    value = normalize(tmpstream.getvalue())
-            finally:
-                self.restoreState(state)
-        else:
-            # Evaluate the value to be associated with the variable in the
-            # i18n interpolation dictionary.
-            if structure:
-                value = self.engine.evaluateStructure(expression)
-            else:
-                value = self.engine.evaluate(expression)
-
-            # evaluate() does not do any I18n, so we do it here.
-            if isinstance(value, I18nMessageTypes):
-                # Translate this now.
-                # XXX
-                value = self.engine.translate(value.domain, value,
-                                              value.mapping, value.default)
-
-            if not structure:
-                value = cgi.escape(ustr(value))
-
-        # Either the i18n:name tag is nested inside an i18n:translate in which
-        # case the last item on the stack has the i18n dictionary and string
-        # representation, or the i18n:name and i18n:translate attributes are
-        # in the same tag, in which case the i18nStack will be empty.  In that
-        # case we can just output the ${name} to the stream
-        i18ndict, srepr = self.i18nStack[-1]
-        i18ndict[varname] = value
-        placeholder = '${%s}' % varname
-        srepr.append(placeholder)
-        self._stream_write(placeholder)
-    bytecode_handlers['i18nVariable'] = do_i18nVariable
-
-    def do_insertTranslation(self, stuff):
-        i18ndict = {}
-        srepr = []
-        obj = None
-        self.i18nStack.append((i18ndict, srepr))
-        msgid = stuff[0]
-        # We need to evaluate the content of the tag because that will give us
-        # several useful pieces of information.  First, the contents will
-        # include an implicit message id, if no explicit one was given.
-        # Second, it will evaluate any i18nVariable definitions in the body of
-        # the translation (necessary for $varname substitutions).
-        #
-        # Use a temporary stream to capture the interpretation of the
-        # subnodes, which should /not/ go to the output stream.
-        currentTag = self._currentTag
-        tmpstream = self.StringIO()
-        self.pushStream(tmpstream)
-        try:
-            self.interpret(stuff[1])
-        finally:
-            self.popStream()
-        # We only care about the evaluated contents if we need an implicit
-        # message id.  All other useful information will be in the i18ndict on
-        # the top of the i18nStack.
-        default = tmpstream.getvalue()
-        if not msgid:
-            if self.html and currentTag == "pre":
-                msgid = default
-            else:
-                msgid = normalize(default)
-        self.i18nStack.pop()
-        # See if there is was an i18n:data for msgid
-        if len(stuff) > 2:
-            obj = self.engine.evaluate(stuff[2])
-        xlated_msgid = self.translate(msgid, default, i18ndict, obj)
-        # TODO: I can't decide whether we want to cgi escape the translated
-        # string or not.  OTOH not doing this could introduce a cross-site
-        # scripting vector by allowing translators to sneak JavaScript into
-        # translations.  OTOH, for implicit interpolation values, we don't
-        # want to escape stuff like ${name} <= "<b>Timmy</b>".
-        assert xlated_msgid is not None
-        self._stream_write(xlated_msgid)
-    bytecode_handlers['insertTranslation'] = do_insertTranslation
-
-    def do_insertStructure(self, stuff):
-        self.interpret(stuff[2])
-
-    def do_insertStructure_tal(self, (expr, repldict, block)):
-        structure = self.engine.evaluateStructure(expr)
-        if structure is None:
-            return
-        if structure is self.Default:
-            self.interpret(block)
-            return
-        text = ustr(structure)
-        if not (repldict or self.strictinsert):
-            # Take a shortcut, no error checking
-            self.stream_write(text)
-            return
-        if self.html:
-            self.insertHTMLStructure(text, repldict)
-        else:
-            self.insertXMLStructure(text, repldict)
-    bytecode_handlers["insertStructure"] = do_insertStructure
-
-    def insertHTMLStructure(self, text, repldict):
-        from HTMLTALParser import HTMLTALParser
-        gen = AltTALGenerator(repldict, self.engine.getCompiler(), 0)
-        p = HTMLTALParser(gen) # Raises an exception if text is invalid
-        p.parseString(text)
-        program, macros = p.getCode()
-        self.interpret(program)
-
-    def insertXMLStructure(self, text, repldict):
-        from TALParser import TALParser
-        gen = AltTALGenerator(repldict, self.engine.getCompiler(), 0)
-        p = TALParser(gen)
-        gen.enable(0)
-        p.parseFragment('<!DOCTYPE foo PUBLIC "foo" "bar"><foo>')
-        gen.enable(1)
-        p.parseFragment(text) # Raises an exception if text is invalid
-        gen.enable(0)
-        p.parseFragment('</foo>', 1)
-        program, macros = gen.getCode()
-        self.interpret(program)
-
-    def do_loop(self, (name, expr, block)):
-        self.interpret(block)
-
-    def do_loop_tal(self, (name, expr, block)):
-        iterator = self.engine.setRepeat(name, expr)
-        while iterator.next():
-            self.interpret(block)
-    bytecode_handlers["loop"] = do_loop
-
-    def translate(self, msgid, default, i18ndict, obj=None):
-        if obj:
-            i18ndict.update(obj)
-        if not self.i18nInterpolate:
-            return msgid
-        # TODO: We need to pass in one of context or target_language
-        return self.engine.translate(self.i18nContext.domain,
-                                     msgid, i18ndict, default=default)
-
-    def do_rawtextColumn(self, (s, col)):
-        self._stream_write(s)
-        self.col = col
-    bytecode_handlers["rawtextColumn"] = do_rawtextColumn
-
-    def do_rawtextOffset(self, (s, offset)):
-        self._stream_write(s)
-        self.col = self.col + offset
-    bytecode_handlers["rawtextOffset"] = do_rawtextOffset
-
-    def do_condition(self, (condition, block)):
-        if not self.tal or self.engine.evaluateBoolean(condition):
-            self.interpret(block)
-    bytecode_handlers["condition"] = do_condition
-
-    def do_defineMacro(self, (macroName, macro)):
-        macs = self.macroStack
-        if len(macs) == 1:
-            entering = macs[-1][2]
-            if not entering:
-                macs.append(None)
-                self.interpret(macro)
-                assert macs[-1] is None
-                macs.pop()
-                return
-        self.interpret(macro)
-    bytecode_handlers["defineMacro"] = do_defineMacro
-
-    def do_useMacro(self, (macroName, macroExpr, compiledSlots, block)):
-        if not self.metal:
-            self.interpret(block)
-            return
-        macro = self.engine.evaluateMacro(macroExpr)
-        if macro is self.Default:
-            macro = block
-        else:
-            if not isCurrentVersion(macro):
-                raise METALError("macro %s has incompatible version %s" %
-                                 (`macroName`, `getProgramVersion(macro)`),
-                                 self.position)
-            mode = getProgramMode(macro)
-            if mode != (self.html and "html" or "xml"):
-                raise METALError("macro %s has incompatible mode %s" %
-                                 (`macroName`, `mode`), self.position)
-        self.pushMacro(macroName, compiledSlots)
-        prev_source = self.sourceFile
-        self.interpret(macro)
-        if self.sourceFile != prev_source:
-            self.engine.setSourceFile(prev_source)
-            self.sourceFile = prev_source
-        self.popMacro()
-    bytecode_handlers["useMacro"] = do_useMacro
-
-    def do_fillSlot(self, (slotName, block)):
-        # This is only executed if the enclosing 'use-macro' evaluates
-        # to 'default'.
-        self.interpret(block)
-    bytecode_handlers["fillSlot"] = do_fillSlot
-
-    def do_defineSlot(self, (slotName, block)):
-        if not self.metal:
-            self.interpret(block)
-            return
-        macs = self.macroStack
-        if macs and macs[-1] is not None:
-            macroName, slots = self.popMacro()[:2]
-            slot = slots.get(slotName)
-            if slot is not None:
-                prev_source = self.sourceFile
-                try:
-                    self.interpret(slot)
-                finally:
-                    if self.sourceFile != prev_source:
-                        self.engine.setSourceFile(prev_source)
-                        self.sourceFile = prev_source
-                    self.pushMacro(macroName, slots, entering=0)
-                return
-            self.pushMacro(macroName, slots)
-            # Falling out of the 'if' allows the macro to be interpreted.
-        self.interpret(block)
-    bytecode_handlers["defineSlot"] = do_defineSlot
-
-    def do_onError(self, (block, handler)):
-        self.interpret(block)
-
-    def do_onError_tal(self, (block, handler)):
-        state = self.saveState()
-        self.stream = stream = self.StringIO()
-        self._stream_write = stream.write
-        try:
-            self.interpret(block)
-        except ConflictError:
-            raise
-        except:
-            exc = sys.exc_info()[1]
-            self.restoreState(state)
-            engine = self.engine
-            engine.beginScope()
-            error = engine.createErrorInfo(exc, self.position)
-            engine.setLocal('error', error)
-            try:
-                self.interpret(handler)
-            finally:
-                engine.endScope()
-        else:
-            self.restoreOutputState(state)
-            self.stream_write(stream.getvalue())
-    bytecode_handlers["onError"] = do_onError
-
-    bytecode_handlers_tal = bytecode_handlers.copy()
-    bytecode_handlers_tal["rawtextBeginScope"] = do_rawtextBeginScope_tal
-    bytecode_handlers_tal["beginScope"] = do_beginScope_tal
-    bytecode_handlers_tal["setLocal"] = do_setLocal_tal
-    bytecode_handlers_tal["setGlobal"] = do_setGlobal_tal
-    bytecode_handlers_tal["insertStructure"] = do_insertStructure_tal
-    bytecode_handlers_tal["insertText"] = do_insertText_tal
-    bytecode_handlers_tal["loop"] = do_loop_tal
-    bytecode_handlers_tal["onError"] = do_onError_tal
-    bytecode_handlers_tal["<attrAction>"] = attrAction_tal
-    bytecode_handlers_tal["optTag"] = do_optTag_tal
-
-
-class FasterStringIO(StringIO):
-    """Append-only version of StringIO.
-
-    This let's us have a much faster write() method.
-    """
-    def close(self):
-        if not self.closed:
-            self.write = _write_ValueError
-            StringIO.close(self)
-
-    def seek(self, pos, mode=0):
-        raise RuntimeError("FasterStringIO.seek() not allowed")
-
-    def write(self, s):
-        #assert self.pos == self.len
-        self.buflist.append(s)
-        self.len = self.pos = self.pos + len(s)
-
-
-def _write_ValueError(s):
-    raise ValueError, "I/O operation on closed file"
+import zope.deferredimport
+zope.deferredimport.deprecated(
+    "'interpolate' has moved to zope.i18n.  This reference will be gone "
+    "in Zope 2.12.",
+    interpolate = 'zope.i18n:interpolate'
+    )

Modified: Zope/branches/ajung-zpt-end-game/lib/python/TAL/TALParser.py
===================================================================
--- Zope/branches/ajung-zpt-end-game/lib/python/TAL/TALParser.py	2006-05-28 22:14:02 UTC (rev 68316)
+++ Zope/branches/ajung-zpt-end-game/lib/python/TAL/TALParser.py	2006-05-28 23:07:07 UTC (rev 68317)
@@ -13,131 +13,8 @@
 ##############################################################################
 """
 Parse XML and compile to TALInterpreter intermediate code.
-"""
 
-from XMLParser import XMLParser
-from TALDefs import XML_NS, ZOPE_I18N_NS, ZOPE_METAL_NS, ZOPE_TAL_NS
-from TALGenerator import TALGenerator
-
-class TALParser(XMLParser):
-
-    ordered_attributes = 1
-
-    def __init__(self, gen=None): # Override
-        XMLParser.__init__(self)
-        if gen is None:
-            gen = TALGenerator()
-        self.gen = gen
-        self.nsStack = []
-        self.nsDict = {XML_NS: 'xml'}
-        self.nsNew = []
-
-    def getCode(self):
-        return self.gen.getCode()
-
-    def getWarnings(self):
-        return ()
-
-    def StartNamespaceDeclHandler(self, prefix, uri):
-        self.nsStack.append(self.nsDict.copy())
-        self.nsDict[uri] = prefix
-        self.nsNew.append((prefix, uri))
-
-    def EndNamespaceDeclHandler(self, prefix):
-        self.nsDict = self.nsStack.pop()
-
-    def StartElementHandler(self, name, attrs):
-        if self.ordered_attributes:
-            # attrs is a list of alternating names and values
-            attrlist = []
-            for i in range(0, len(attrs), 2):
-                key = attrs[i]
-                value = attrs[i+1]
-                attrlist.append((key, value))
-        else:
-            # attrs is a dict of {name: value}
-            attrlist = attrs.items()
-            attrlist.sort() # For definiteness
-        name, attrlist, taldict, metaldict, i18ndict \
-              = self.process_ns(name, attrlist)
-        attrlist = self.xmlnsattrs() + attrlist
-        self.gen.emitStartElement(name, attrlist, taldict, metaldict, i18ndict)
-
-    def process_ns(self, name, attrlist):
-        taldict = {}
-        metaldict = {}
-        i18ndict = {}
-        fixedattrlist = []
-        name, namebase, namens = self.fixname(name)
-        for key, value in attrlist:
-            key, keybase, keyns = self.fixname(key)
-            ns = keyns or namens # default to tag namespace
-            item = key, value
-            if ns == 'metal':
-                metaldict[keybase] = value
-                item = item + ("metal",)
-            elif ns == 'tal':
-                taldict[keybase] = value
-                item = item + ("tal",)
-            elif ns == 'i18n':
-                i18ndict[keybase] = value
-                item = item + ('i18n',)
-            fixedattrlist.append(item)
-        if namens in ('metal', 'tal', 'i18n'):
-            taldict['tal tag'] = namens
-        return name, fixedattrlist, taldict, metaldict, i18ndict
-
-    def xmlnsattrs(self):
-        newlist = []
-        for prefix, uri in self.nsNew:
-            if prefix:
-                key = "xmlns:" + prefix
-            else:
-                key = "xmlns"
-            if uri in (ZOPE_METAL_NS, ZOPE_TAL_NS, ZOPE_I18N_NS):
-                item = (key, uri, "xmlns")
-            else:
-                item = (key, uri)
-            newlist.append(item)
-        self.nsNew = []
-        return newlist
-
-    def fixname(self, name):
-        if ' ' in name:
-            uri, name = name.split(' ')
-            prefix = self.nsDict[uri]
-            prefixed = name
-            if prefix:
-                prefixed = "%s:%s" % (prefix, name)
-            ns = 'x'
-            if uri == ZOPE_TAL_NS:
-                ns = 'tal'
-            elif uri == ZOPE_METAL_NS:
-                ns = 'metal'
-            elif uri == ZOPE_I18N_NS:
-                ns = 'i18n'
-            return (prefixed, name, ns)
-        return (name, name, None)
-
-    def EndElementHandler(self, name):
-        name = self.fixname(name)[0]
-        self.gen.emitEndElement(name)
-
-    def DefaultHandler(self, text):
-        self.gen.emitRawText(text)
-
-def test():
-    import sys
-    p = TALParser()
-    file = "tests/input/test01.xml"
-    if sys.argv[1:]:
-        file = sys.argv[1]
-    p.parseFile(file)
-    program, macros = p.getCode()
-    from TALInterpreter import TALInterpreter
-    from DummyEngine import DummyEngine
-    engine = DummyEngine(macros)
-    TALInterpreter(program, macros, engine, sys.stdout, wrap=0)()
-
-if __name__ == "__main__":
-    test()
+BBB 2005/05/01 -- to be removed after 12 months
+"""
+import zope.deprecation
+zope.deprecation.moved('zope.tal.talparser', '2.12')

Modified: Zope/branches/ajung-zpt-end-game/lib/python/TAL/TranslationContext.py
===================================================================
--- Zope/branches/ajung-zpt-end-game/lib/python/TAL/TranslationContext.py	2006-05-28 22:14:02 UTC (rev 68316)
+++ Zope/branches/ajung-zpt-end-game/lib/python/TAL/TranslationContext.py	2006-05-28 23:07:07 UTC (rev 68317)
@@ -13,29 +13,9 @@
 ##############################################################################
 """Translation context object for the TALInterpreter's I18N support.
 
-The translation context provides a container for the information
-needed to perform translation of a marked string from a page template.
+BBB 2005/05/01 -- to be removed after 12 months
 
 $Id$
 """
-
-DEFAULT_DOMAIN = "default"
-
-class TranslationContext:
-    """Information about the I18N settings of a TAL processor."""
-
-    def __init__(self, parent=None, domain=None, target=None, source=None):
-        if parent:
-            if not domain:
-                domain = parent.domain
-            if not target:
-                target = parent.target
-            if not source:
-                source = parent.source
-        elif domain is None:
-            domain = DEFAULT_DOMAIN
-
-        self.parent = parent
-        self.domain = domain
-        self.target = target
-        self.source = source
+import zope.deprecation
+zope.deprecation.moved('zope.tal.translationcontext', '2.12')

Modified: Zope/branches/ajung-zpt-end-game/lib/python/TAL/XMLParser.py
===================================================================
--- Zope/branches/ajung-zpt-end-game/lib/python/TAL/XMLParser.py	2006-05-28 22:14:02 UTC (rev 68316)
+++ Zope/branches/ajung-zpt-end-game/lib/python/TAL/XMLParser.py	2006-05-28 23:07:07 UTC (rev 68317)
@@ -13,75 +13,11 @@
 ##############################################################################
 """
 Generic expat-based XML parser base class.
+
+BBB 2005/05/01 -- to be removed after 12 months
 """
+import zope.deprecation
+zope.deprecation.moved('zope.tal.xmlparser', '2.12')
 
 import xml.parsers.expat
-from logging import getLogger
-
-
-LOG = getLogger('TAL')
-
 XMLParseError = xml.parsers.expat.ExpatError
-
-
-class XMLParser:
-
-    ordered_attributes = 0
-
-    handler_names = [
-        "StartElementHandler",
-        "EndElementHandler",
-        "ProcessingInstructionHandler",
-        "CharacterDataHandler",
-        "UnparsedEntityDeclHandler",
-        "NotationDeclHandler",
-        "StartNamespaceDeclHandler",
-        "EndNamespaceDeclHandler",
-        "CommentHandler",
-        "StartCdataSectionHandler",
-        "EndCdataSectionHandler",
-        "DefaultHandler",
-        "DefaultHandlerExpand",
-        "NotStandaloneHandler",
-        "ExternalEntityRefHandler",
-        "XmlDeclHandler",
-        "StartDoctypeDeclHandler",
-        "EndDoctypeDeclHandler",
-        "ElementDeclHandler",
-        "AttlistDeclHandler"
-        ]
-
-    def __init__(self, encoding=None):
-        self.parser = p = self.createParser()
-        if self.ordered_attributes:
-            try:
-                self.parser.ordered_attributes = self.ordered_attributes
-            except AttributeError:
-                LOG.info("Can't set ordered_attributes")
-                self.ordered_attributes = 0
-        for name in self.handler_names:
-            method = getattr(self, name, None)
-            if method is not None:
-                try:
-                    setattr(p, name, method)
-                except AttributeError:
-                    LOG.error("Can't set expat handler %s" % name)
-
-    def createParser(self, encoding=None):
-        return xml.parsers.expat.ParserCreate(encoding, ' ')
-
-    def parseFile(self, filename):
-        self.parseStream(open(filename))
-
-    def parseString(self, s):
-        self.parser.Parse(s, 1)
-
-    def parseURL(self, url):
-        import urllib
-        self.parseStream(urllib.urlopen(url))
-
-    def parseStream(self, stream):
-        self.parser.ParseFile(stream)
-
-    def parseFragment(self, s, end=0):
-        self.parser.Parse(s, end)

Modified: Zope/branches/ajung-zpt-end-game/lib/python/TAL/driver.py
===================================================================
--- Zope/branches/ajung-zpt-end-game/lib/python/TAL/driver.py	2006-05-28 22:14:02 UTC (rev 68316)
+++ Zope/branches/ajung-zpt-end-game/lib/python/TAL/driver.py	2006-05-28 23:07:07 UTC (rev 68317)
@@ -34,165 +34,11 @@
         Leave TAL/METAL attributes in output
     -i
         Leave I18N substitution strings un-interpolated.
+
+BBB 2005/05/01 -- to be removed after 12 months
 """
+import zope.deprecation
+zope.deprecation.moved('zope.tal.driver', '2.12')
 
-import os
-import sys
-
-import getopt
-
 if __name__ == "__main__":
-    import setpath                      # Local hack to tweak sys.path etc.
-
-# Import local classes
-import TALDefs
-from DummyEngine import DummyEngine
-from DummyEngine import DummyTranslationService
-
-FILE = "tests/input/test01.xml"
-
-class TestTranslations(DummyTranslationService):
-    def translate(self, domain, msgid, mapping=None, context=None,
-                  target_language=None, default=None):
-        if msgid == 'timefmt':
-            return '%(minutes)s minutes after %(hours)s %(ampm)s' % mapping
-        elif msgid == 'jobnum':
-            return '%(jobnum)s is the JOB NUMBER' % mapping
-        elif msgid == 'verify':
-            s = 'Your contact email address is recorded as %(email)s'
-            return s % mapping
-        elif msgid == 'mailto:${request/submitter}':
-            return 'mailto:bperson at dom.ain'
-        elif msgid == 'origin':
-            return '%(name)s was born in %(country)s' % mapping
-        return DummyTranslationService.translate(self, domain, msgid,
-                                                 mapping, context,
-                                                 target_language,
-                                                 default=default)
-
-class TestEngine(DummyEngine):
-    def __init__(self, macros=None):
-        DummyEngine.__init__(self, macros)
-        self.translationService = TestTranslations()
-
-    def evaluatePathOrVar(self, expr):
-        if expr == 'here/currentTime':
-            return {'hours'  : 6,
-                    'minutes': 59,
-                    'ampm'   : 'PM',
-                    }
-        elif expr == 'context/@@object_name':
-            return '7'
-        elif expr == 'request/submitter':
-            return 'aperson at dom.ain'
-        return DummyEngine.evaluatePathOrVar(self, expr)
-
-
-# This is a disgusting hack so that we can use engines that actually know
-# something about certain object paths.  TimeEngine knows about
-# here/currentTime.
-ENGINES = {'test23.html': TestEngine,
-           'test24.html': TestEngine,
-           'test26.html': TestEngine,
-           'test27.html': TestEngine,
-           'test28.html': TestEngine,
-           'test29.html': TestEngine,
-           'test30.html': TestEngine,
-           'test31.html': TestEngine,
-           'test32.html': TestEngine,
-           }
-
-def usage(code, msg=''):
-    # Python 2.1 required
-    print >> sys.stderr, __doc__
-    if msg:
-        print >> sys.stderr, msg
-    sys.exit(code)
-
-def main():
-    macros = 0
-    mode = None
-    showcode = 0
-    showtal = -1
-    strictinsert = 1
-    i18nInterpolate = 1
-    try:
-        opts, args = getopt.getopt(sys.argv[1:], "hHxlmsti",
-                                   ['help', 'html', 'xml'])
-    except getopt.error, msg:
-        usage(2, msg)
-    for opt, arg in opts:
-        if opt in ('-h', '--help'):
-            usage(0)
-        if opt in ('-H', '--html'):
-            if mode == 'xml':
-                usage(1, '--html and --xml are mutually exclusive')
-            mode = "html"
-        if opt == '-l':
-            strictinsert = 0
-        if opt == '-m':
-            macros = 1
-        if opt == '-n':
-            versionTest = 0
-        if opt in ('-x', '--xml'):
-            if mode == 'html':
-                usage(1, '--html and --xml are mutually exclusive')
-            mode = "xml"
-        if opt == '-s':
-            showcode = 1
-        if opt == '-t':
-            showtal = 1
-        if opt == '-i':
-            i18nInterpolate = 0
-    if args:
-        file = args[0]
-    else:
-        file = FILE
-    it = compilefile(file, mode)
-    if showcode:
-        showit(it)
-    else:
-        # See if we need a special engine for this test
-        engine = None
-        engineClass = ENGINES.get(os.path.basename(file))
-        if engineClass is not None:
-            engine = engineClass(macros)
-        interpretit(it, engine=engine,
-                    tal=(not macros), showtal=showtal,
-                    strictinsert=strictinsert,
-                    i18nInterpolate=i18nInterpolate)
-
-def interpretit(it, engine=None, stream=None, tal=1, showtal=-1,
-                strictinsert=1, i18nInterpolate=1):
-    from TALInterpreter import TALInterpreter
-    program, macros = it
-    assert TALDefs.isCurrentVersion(program)
-    if engine is None:
-        engine = DummyEngine(macros)
-    TALInterpreter(program, macros, engine, stream, wrap=0,
-                   tal=tal, showtal=showtal, strictinsert=strictinsert,
-                   i18nInterpolate=i18nInterpolate)()
-
-def compilefile(file, mode=None):
-    assert mode in ("html", "xml", None)
-    if mode is None:
-        ext = os.path.splitext(file)[1]
-        if ext.lower() in (".html", ".htm"):
-            mode = "html"
-        else:
-            mode = "xml"
-    if mode == "html":
-        from HTMLTALParser import HTMLTALParser
-        p = HTMLTALParser()
-    else:
-        from TALParser import TALParser
-        p = TALParser()
-    p.parseFile(file)
-    return p.getCode()
-
-def showit(it):
-    from pprint import pprint
-    pprint(it)
-
-if __name__ == "__main__":
     main()

Modified: Zope/branches/ajung-zpt-end-game/lib/python/TAL/ndiff.py
===================================================================
--- Zope/branches/ajung-zpt-end-game/lib/python/TAL/ndiff.py	2006-05-28 22:14:02 UTC (rev 68316)
+++ Zope/branches/ajung-zpt-end-game/lib/python/TAL/ndiff.py	2006-05-28 23:07:07 UTC (rev 68317)
@@ -1,625 +1,8 @@
 #! /usr/bin/env python
+# BBB 2005/05/01 -- to be removed after 12 months
+import zope.deprecation
+zope.deprecation.moved('zope.tal.ndiff', '2.12')
 
-# Module ndiff version 1.6.0
-# Released to the public domain 08-Dec-2000,
-# by Tim Peters (tim.one at home.com).
-
-# Provided as-is; use at your own risk; no warranty; no promises; enjoy!
-
-"""ndiff [-q] file1 file2
-    or
-ndiff (-r1 | -r2) < ndiff_output > file1_or_file2
-
-Print a human-friendly file difference report to stdout.  Both inter-
-and intra-line differences are noted.  In the second form, recreate file1
-(-r1) or file2 (-r2) on stdout, from an ndiff report on stdin.
-
-In the first form, if -q ("quiet") is not specified, the first two lines
-of output are
-
--: file1
-+: file2
-
-Each remaining line begins with a two-letter code:
-
-    "- "    line unique to file1
-    "+ "    line unique to file2
-    "  "    line common to both files
-    "? "    line not present in either input file
-
-Lines beginning with "? " attempt to guide the eye to intraline
-differences, and were not present in either input file.  These lines can be
-confusing if the source files contain tab characters.
-
-The first file can be recovered by retaining only lines that begin with
-"  " or "- ", and deleting those 2-character prefixes; use ndiff with -r1.
-
-The second file can be recovered similarly, but by retaining only "  " and
-"+ " lines; use ndiff with -r2; or, on Unix, the second file can be
-recovered by piping the output through
-
-    sed -n '/^[+ ] /s/^..//p'
-
-See module comments for details and programmatic interface.
-"""
-
-__version__ = 1, 5, 0
-
-# SequenceMatcher tries to compute a "human-friendly diff" between
-# two sequences (chiefly picturing a file as a sequence of lines,
-# and a line as a sequence of characters, here).  Unlike e.g. UNIX(tm)
-# diff, the fundamental notion is the longest *contiguous* & junk-free
-# matching subsequence.  That's what catches peoples' eyes.  The
-# Windows(tm) windiff has another interesting notion, pairing up elements
-# that appear uniquely in each sequence.  That, and the method here,
-# appear to yield more intuitive difference reports than does diff.  This
-# method appears to be the least vulnerable to synching up on blocks
-# of "junk lines", though (like blank lines in ordinary text files,
-# or maybe "<P>" lines in HTML files).  That may be because this is
-# the only method of the 3 that has a *concept* of "junk" <wink>.
-#
-# Note that ndiff makes no claim to produce a *minimal* diff.  To the
-# contrary, minimal diffs are often counter-intuitive, because they
-# synch up anywhere possible, sometimes accidental matches 100 pages
-# apart.  Restricting synch points to contiguous matches preserves some
-# notion of locality, at the occasional cost of producing a longer diff.
-#
-# With respect to junk, an earlier version of ndiff simply refused to
-# *start* a match with a junk element.  The result was cases like this:
-#     before: private Thread currentThread;
-#     after:  private volatile Thread currentThread;
-# If you consider whitespace to be junk, the longest contiguous match
-# not starting with junk is "e Thread currentThread".  So ndiff reported
-# that "e volatil" was inserted between the 't' and the 'e' in "private".
-# While an accurate view, to people that's absurd.  The current version
-# looks for matching blocks that are entirely junk-free, then extends the
-# longest one of those as far as possible but only with matching junk.
-# So now "currentThread" is matched, then extended to suck up the
-# preceding blank; then "private" is matched, and extended to suck up the
-# following blank; then "Thread" is matched; and finally ndiff reports
-# that "volatile " was inserted before "Thread".  The only quibble
-# remaining is that perhaps it was really the case that " volatile"
-# was inserted after "private".  I can live with that <wink>.
-#
-# NOTE on junk:  the module-level names
-#    IS_LINE_JUNK
-#    IS_CHARACTER_JUNK
-# can be set to any functions you like.  The first one should accept
-# a single string argument, and return true iff the string is junk.
-# The default is whether the regexp r"\s*#?\s*$" matches (i.e., a
-# line without visible characters, except for at most one splat).
-# The second should accept a string of length 1 etc.  The default is
-# whether the character is a blank or tab (note: bad idea to include
-# newline in this!).
-#
-# After setting those, you can call fcompare(f1name, f2name) with the
-# names of the files you want to compare.  The difference report
-# is sent to stdout.  Or you can call main(args), passing what would
-# have been in sys.argv[1:] had the cmd-line form been used.
-
-TRACE = 0
-
-# define what "junk" means
-import re
-
-def IS_LINE_JUNK(line, pat=re.compile(r"\s*#?\s*$").match):
-    return pat(line) is not None
-
-def IS_CHARACTER_JUNK(ch, ws=" \t"):
-    return ch in ws
-
-del re
-
-class SequenceMatcher:
-    def __init__(self, isjunk=None, a='', b=''):
-        # Members:
-        # a
-        #      first sequence
-        # b
-        #      second sequence; differences are computed as "what do
-        #      we need to do to 'a' to change it into 'b'?"
-        # b2j
-        #      for x in b, b2j[x] is a list of the indices (into b)
-        #      at which x appears; junk elements do not appear
-        # b2jhas
-        #      b2j.has_key
-        # fullbcount
-        #      for x in b, fullbcount[x] == the number of times x
-        #      appears in b; only materialized if really needed (used
-        #      only for computing quick_ratio())
-        # matching_blocks
-        #      a list of (i, j, k) triples, where a[i:i+k] == b[j:j+k];
-        #      ascending & non-overlapping in i and in j; terminated by
-        #      a dummy (len(a), len(b), 0) sentinel
-        # opcodes
-        #      a list of (tag, i1, i2, j1, j2) tuples, where tag is
-        #      one of
-        #          'replace'   a[i1:i2] should be replaced by b[j1:j2]
-        #          'delete'    a[i1:i2] should be deleted
-        #          'insert'    b[j1:j2] should be inserted
-        #          'equal'     a[i1:i2] == b[j1:j2]
-        # isjunk
-        #      a user-supplied function taking a sequence element and
-        #      returning true iff the element is "junk" -- this has
-        #      subtle but helpful effects on the algorithm, which I'll
-        #      get around to writing up someday <0.9 wink>.
-        #      DON'T USE!  Only __chain_b uses this.  Use isbjunk.
-        # isbjunk
-        #      for x in b, isbjunk(x) == isjunk(x) but much faster;
-        #      it's really the has_key method of a hidden dict.
-        #      DOES NOT WORK for x in a!
-
-        self.isjunk = isjunk
-        self.a = self.b = None
-        self.set_seqs(a, b)
-
-    def set_seqs(self, a, b):
-        self.set_seq1(a)
-        self.set_seq2(b)
-
-    def set_seq1(self, a):
-        if a is self.a:
-            return
-        self.a = a
-        self.matching_blocks = self.opcodes = None
-
-    def set_seq2(self, b):
-        if b is self.b:
-            return
-        self.b = b
-        self.matching_blocks = self.opcodes = None
-        self.fullbcount = None
-        self.__chain_b()
-
-    # For each element x in b, set b2j[x] to a list of the indices in
-    # b where x appears; the indices are in increasing order; note that
-    # the number of times x appears in b is len(b2j[x]) ...
-    # when self.isjunk is defined, junk elements don't show up in this
-    # map at all, which stops the central find_longest_match method
-    # from starting any matching block at a junk element ...
-    # also creates the fast isbjunk function ...
-    # note that this is only called when b changes; so for cross-product
-    # kinds of matches, it's best to call set_seq2 once, then set_seq1
-    # repeatedly
-
-    def __chain_b(self):
-        # Because isjunk is a user-defined (not C) function, and we test
-        # for junk a LOT, it's important to minimize the number of calls.
-        # Before the tricks described here, __chain_b was by far the most
-        # time-consuming routine in the whole module!  If anyone sees
-        # Jim Roskind, thank him again for profile.py -- I never would
-        # have guessed that.
-        # The first trick is to build b2j ignoring the possibility
-        # of junk.  I.e., we don't call isjunk at all yet.  Throwing
-        # out the junk later is much cheaper than building b2j "right"
-        # from the start.
-        b = self.b
-        self.b2j = b2j = {}
-        self.b2jhas = b2jhas = b2j.has_key
-        for i in xrange(len(b)):
-            elt = b[i]
-            if b2jhas(elt):
-                b2j[elt].append(i)
-            else:
-                b2j[elt] = [i]
-
-        # Now b2j.keys() contains elements uniquely, and especially when
-        # the sequence is a string, that's usually a good deal smaller
-        # than len(string).  The difference is the number of isjunk calls
-        # saved.
-        isjunk, junkdict = self.isjunk, {}
-        if isjunk:
-            for elt in b2j.keys():
-                if isjunk(elt):
-                    junkdict[elt] = 1   # value irrelevant; it's a set
-                    del b2j[elt]
-
-        # Now for x in b, isjunk(x) == junkdict.has_key(x), but the
-        # latter is much faster.  Note too that while there may be a
-        # lot of junk in the sequence, the number of *unique* junk
-        # elements is probably small.  So the memory burden of keeping
-        # this dict alive is likely trivial compared to the size of b2j.
-        self.isbjunk = junkdict.has_key
-
-    def find_longest_match(self, alo, ahi, blo, bhi):
-        """Find longest matching block in a[alo:ahi] and b[blo:bhi].
-
-        If isjunk is not defined:
-
-        Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where
-            alo <= i <= i+k <= ahi
-            blo <= j <= j+k <= bhi
-        and for all (i',j',k') meeting those conditions,
-            k >= k'
-            i <= i'
-            and if i == i', j <= j'
-        In other words, of all maximal matching blocks, return one
-        that starts earliest in a, and of all those maximal matching
-        blocks that start earliest in a, return the one that starts
-        earliest in b.
-
-        If isjunk is defined, first the longest matching block is
-        determined as above, but with the additional restriction that
-        no junk element appears in the block.  Then that block is
-        extended as far as possible by matching (only) junk elements on
-        both sides.  So the resulting block never matches on junk except
-        as identical junk happens to be adjacent to an "interesting"
-        match.
-
-        If no blocks match, return (alo, blo, 0).
-        """
-
-        # CAUTION:  stripping common prefix or suffix would be incorrect.
-        # E.g.,
-        #    ab
-        #    acab
-        # Longest matching block is "ab", but if common prefix is
-        # stripped, it's "a" (tied with "b").  UNIX(tm) diff does so
-        # strip, so ends up claiming that ab is changed to acab by
-        # inserting "ca" in the middle.  That's minimal but unintuitive:
-        # "it's obvious" that someone inserted "ac" at the front.
-        # Windiff ends up at the same place as diff, but by pairing up
-        # the unique 'b's and then matching the first two 'a's.
-
-        a, b, b2j, isbjunk = self.a, self.b, self.b2j, self.isbjunk
-        besti, bestj, bestsize = alo, blo, 0
-        # find longest junk-free match
-        # during an iteration of the loop, j2len[j] = length of longest
-        # junk-free match ending with a[i-1] and b[j]
-        j2len = {}
-        nothing = []
-        for i in xrange(alo, ahi):
-            # look at all instances of a[i] in b; note that because
-            # b2j has no junk keys, the loop is skipped if a[i] is junk
-            j2lenget = j2len.get
-            newj2len = {}
-            for j in b2j.get(a[i], nothing):
-                # a[i] matches b[j]
-                if j < blo:
-                    continue
-                if j >= bhi:
-                    break
-                k = newj2len[j] = j2lenget(j-1, 0) + 1
-                if k > bestsize:
-                    besti, bestj, bestsize = i-k+1, j-k+1, k
-            j2len = newj2len
-
-        # Now that we have a wholly interesting match (albeit possibly
-        # empty!), we may as well suck up the matching junk on each
-        # side of it too.  Can't think of a good reason not to, and it
-        # saves post-processing the (possibly considerable) expense of
-        # figuring out what to do with it.  In the case of an empty
-        # interesting match, this is clearly the right thing to do,
-        # because no other kind of match is possible in the regions.
-        while besti > alo and bestj > blo and \
-              isbjunk(b[bestj-1]) and \
-              a[besti-1] == b[bestj-1]:
-            besti, bestj, bestsize = besti-1, bestj-1, bestsize+1
-        while besti+bestsize < ahi and bestj+bestsize < bhi and \
-              isbjunk(b[bestj+bestsize]) and \
-              a[besti+bestsize] == b[bestj+bestsize]:
-            bestsize = bestsize + 1
-
-        if TRACE:
-            print "get_matching_blocks", alo, ahi, blo, bhi
-            print "    returns", besti, bestj, bestsize
-        return besti, bestj, bestsize
-
-    def get_matching_blocks(self):
-        if self.matching_blocks is not None:
-            return self.matching_blocks
-        self.matching_blocks = []
-        la, lb = len(self.a), len(self.b)
-        self.__helper(0, la, 0, lb, self.matching_blocks)
-        self.matching_blocks.append( (la, lb, 0) )
-        if TRACE:
-            print '*** matching blocks', self.matching_blocks
-        return self.matching_blocks
-
-    # builds list of matching blocks covering a[alo:ahi] and
-    # b[blo:bhi], appending them in increasing order to answer
-
-    def __helper(self, alo, ahi, blo, bhi, answer):
-        i, j, k = x = self.find_longest_match(alo, ahi, blo, bhi)
-        # a[alo:i] vs b[blo:j] unknown
-        # a[i:i+k] same as b[j:j+k]
-        # a[i+k:ahi] vs b[j+k:bhi] unknown
-        if k:
-            if alo < i and blo < j:
-                self.__helper(alo, i, blo, j, answer)
-            answer.append(x)
-            if i+k < ahi and j+k < bhi:
-                self.__helper(i+k, ahi, j+k, bhi, answer)
-
-    def ratio(self):
-        """Return a measure of the sequences' similarity (float in [0,1]).
-
-        Where T is the total number of elements in both sequences, and
-        M is the number of matches, this is 2*M / T.
-        Note that this is 1 if the sequences are identical, and 0 if
-        they have nothing in common.
-        """
-
-        matches = reduce(lambda sum, triple: sum + triple[-1],
-                         self.get_matching_blocks(), 0)
-        return 2.0 * matches / (len(self.a) + len(self.b))
-
-    def quick_ratio(self):
-        """Return an upper bound on ratio() relatively quickly."""
-        # viewing a and b as multisets, set matches to the cardinality
-        # of their intersection; this counts the number of matches
-        # without regard to order, so is clearly an upper bound
-        if self.fullbcount is None:
-            self.fullbcount = fullbcount = {}
-            for elt in self.b:
-                fullbcount[elt] = fullbcount.get(elt, 0) + 1
-        fullbcount = self.fullbcount
-        # avail[x] is the number of times x appears in 'b' less the
-        # number of times we've seen it in 'a' so far ... kinda
-        avail = {}
-        availhas, matches = avail.has_key, 0
-        for elt in self.a:
-            if availhas(elt):
-                numb = avail[elt]
-            else:
-                numb = fullbcount.get(elt, 0)
-            avail[elt] = numb - 1
-            if numb > 0:
-                matches = matches + 1
-        return 2.0 * matches / (len(self.a) + len(self.b))
-
-    def real_quick_ratio(self):
-        """Return an upper bound on ratio() very quickly"""
-        la, lb = len(self.a), len(self.b)
-        # can't have more matches than the number of elements in the
-        # shorter sequence
-        return 2.0 * min(la, lb) / (la + lb)
-
-    def get_opcodes(self):
-        if self.opcodes is not None:
-            return self.opcodes
-        i = j = 0
-        self.opcodes = answer = []
-        for ai, bj, size in self.get_matching_blocks():
-            # invariant:  we've pumped out correct diffs to change
-            # a[:i] into b[:j], and the next matching block is
-            # a[ai:ai+size] == b[bj:bj+size].  So we need to pump
-            # out a diff to change a[i:ai] into b[j:bj], pump out
-            # the matching block, and move (i,j) beyond the match
-            tag = ''
-            if i < ai and j < bj:
-                tag = 'replace'
-            elif i < ai:
-                tag = 'delete'
-            elif j < bj:
-                tag = 'insert'
-            if tag:
-                answer.append( (tag, i, ai, j, bj) )
-            i, j = ai+size, bj+size
-            # the list of matching blocks is terminated by a
-            # sentinel with size 0
-            if size:
-                answer.append( ('equal', ai, i, bj, j) )
-        return answer
-
-# meant for dumping lines
-def dump(tag, x, lo, hi):
-    for i in xrange(lo, hi):
-        print tag, x[i],
-
-def plain_replace(a, alo, ahi, b, blo, bhi):
-    assert alo < ahi and blo < bhi
-    # dump the shorter block first -- reduces the burden on short-term
-    # memory if the blocks are of very different sizes
-    if bhi - blo < ahi - alo:
-        dump('+', b, blo, bhi)
-        dump('-', a, alo, ahi)
-    else:
-        dump('-', a, alo, ahi)
-        dump('+', b, blo, bhi)
-
-# When replacing one block of lines with another, this guy searches
-# the blocks for *similar* lines; the best-matching pair (if any) is
-# used as a synch point, and intraline difference marking is done on
-# the similar pair.  Lots of work, but often worth it.
-
-def fancy_replace(a, alo, ahi, b, blo, bhi):
-    if TRACE:
-        print '*** fancy_replace', alo, ahi, blo, bhi
-        dump('>', a, alo, ahi)
-        dump('<', b, blo, bhi)
-
-    # don't synch up unless the lines have a similarity score of at
-    # least cutoff; best_ratio tracks the best score seen so far
-    best_ratio, cutoff = 0.74, 0.75
-    cruncher = SequenceMatcher(IS_CHARACTER_JUNK)
-    eqi, eqj = None, None   # 1st indices of equal lines (if any)
-
-    # search for the pair that matches best without being identical
-    # (identical lines must be junk lines, & we don't want to synch up
-    # on junk -- unless we have to)
-    for j in xrange(blo, bhi):
-        bj = b[j]
-        cruncher.set_seq2(bj)
-        for i in xrange(alo, ahi):
-            ai = a[i]
-            if ai == bj:
-                if eqi is None:
-                    eqi, eqj = i, j
-                continue
-            cruncher.set_seq1(ai)
-            # computing similarity is expensive, so use the quick
-            # upper bounds first -- have seen this speed up messy
-            # compares by a factor of 3.
-            # note that ratio() is only expensive to compute the first
-            # time it's called on a sequence pair; the expensive part
-            # of the computation is cached by cruncher
-            if cruncher.real_quick_ratio() > best_ratio and \
-                  cruncher.quick_ratio() > best_ratio and \
-                  cruncher.ratio() > best_ratio:
-                best_ratio, best_i, best_j = cruncher.ratio(), i, j
-    if best_ratio < cutoff:
-        # no non-identical "pretty close" pair
-        if eqi is None:
-            # no identical pair either -- treat it as a straight replace
-            plain_replace(a, alo, ahi, b, blo, bhi)
-            return
-        # no close pair, but an identical pair -- synch up on that
-        best_i, best_j, best_ratio = eqi, eqj, 1.0
-    else:
-        # there's a close pair, so forget the identical pair (if any)
-        eqi = None
-
-    # a[best_i] very similar to b[best_j]; eqi is None iff they're not
-    # identical
-    if TRACE:
-        print '*** best_ratio', best_ratio, best_i, best_j
-        dump('>', a, best_i, best_i+1)
-        dump('<', b, best_j, best_j+1)
-
-    # pump out diffs from before the synch point
-    fancy_helper(a, alo, best_i, b, blo, best_j)
-
-    # do intraline marking on the synch pair
-    aelt, belt = a[best_i], b[best_j]
-    if eqi is None:
-        # pump out a '-', '?', '+', '?' quad for the synched lines
-        atags = btags = ""
-        cruncher.set_seqs(aelt, belt)
-        for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
-            la, lb = ai2 - ai1, bj2 - bj1
-            if tag == 'replace':
-                atags = atags + '^' * la
-                btags = btags + '^' * lb
-            elif tag == 'delete':
-                atags = atags + '-' * la
-            elif tag == 'insert':
-                btags = btags + '+' * lb
-            elif tag == 'equal':
-                atags = atags + ' ' * la
-                btags = btags + ' ' * lb
-            else:
-                raise ValueError, 'unknown tag ' + `tag`
-        printq(aelt, belt, atags, btags)
-    else:
-        # the synch pair is identical
-        print ' ', aelt,
-
-    # pump out diffs from after the synch point
-    fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
-
-def fancy_helper(a, alo, ahi, b, blo, bhi):
-    if alo < ahi:
-        if blo < bhi:
-            fancy_replace(a, alo, ahi, b, blo, bhi)
-        else:
-            dump('-', a, alo, ahi)
-    elif blo < bhi:
-        dump('+', b, blo, bhi)
-
-# Crap to deal with leading tabs in "?" output.  Can hurt, but will
-# probably help most of the time.
-
-def printq(aline, bline, atags, btags):
-    common = min(count_leading(aline, "\t"),
-                 count_leading(bline, "\t"))
-    common = min(common, count_leading(atags[:common], " "))
-    print "-", aline,
-    if count_leading(atags, " ") < len(atags):
-        print "?", "\t" * common + atags[common:]
-    print "+", bline,
-    if count_leading(btags, " ") < len(btags):
-        print "?", "\t" * common + btags[common:]
-
-def count_leading(line, ch):
-    i, n = 0, len(line)
-    while i < n and line[i] == ch:
-        i = i + 1
-    return i
-
-def fail(msg):
-    import sys
-    out = sys.stderr.write
-    out(msg + "\n\n")
-    out(__doc__)
-    return 0
-
-# open a file & return the file object; gripe and return 0 if it
-# couldn't be opened
-def fopen(fname):
-    try:
-        return open(fname, 'r')
-    except IOError, detail:
-        return fail("couldn't open " + fname + ": " + str(detail))
-
-# open two files & spray the diff to stdout; return false iff a problem
-def fcompare(f1name, f2name):
-    f1 = fopen(f1name)
-    f2 = fopen(f2name)
-    if not f1 or not f2:
-        return 0
-
-    a = f1.readlines(); f1.close()
-    b = f2.readlines(); f2.close()
-
-    cruncher = SequenceMatcher(IS_LINE_JUNK, a, b)
-    for tag, alo, ahi, blo, bhi in cruncher.get_opcodes():
-        if tag == 'replace':
-            fancy_replace(a, alo, ahi, b, blo, bhi)
-        elif tag == 'delete':
-            dump('-', a, alo, ahi)
-        elif tag == 'insert':
-            dump('+', b, blo, bhi)
-        elif tag == 'equal':
-            dump(' ', a, alo, ahi)
-        else:
-            raise ValueError, 'unknown tag ' + `tag`
-
-    return 1
-
-# crack args (sys.argv[1:] is normal) & compare;
-# return false iff a problem
-
-def main(args):
-    import getopt
-    try:
-        opts, args = getopt.getopt(args, "qr:")
-    except getopt.error, detail:
-        return fail(str(detail))
-    noisy = 1
-    qseen = rseen = 0
-    for opt, val in opts:
-        if opt == "-q":
-            qseen = 1
-            noisy = 0
-        elif opt == "-r":
-            rseen = 1
-            whichfile = val
-    if qseen and rseen:
-        return fail("can't specify both -q and -r")
-    if rseen:
-        if args:
-            return fail("no args allowed with -r option")
-        if whichfile in "12":
-            restore(whichfile)
-            return 1
-        return fail("-r value must be 1 or 2")
-    if len(args) != 2:
-        return fail("need 2 filename args")
-    f1name, f2name = args
-    if noisy:
-        print '-:', f1name
-        print '+:', f2name
-    return fcompare(f1name, f2name)
-
-def restore(which):
-    import sys
-    tag = {"1": "- ", "2": "+ "}[which]
-    prefixes = ("  ", tag)
-    for line in sys.stdin.readlines():
-        if line[:2] in prefixes:
-            print line[2:],
-
 if __name__ == '__main__':
     import sys
     args = sys.argv[1:]

Modified: Zope/branches/ajung-zpt-end-game/lib/python/TAL/runtest.py
===================================================================
--- Zope/branches/ajung-zpt-end-game/lib/python/TAL/runtest.py	2006-05-28 22:14:02 UTC (rev 68316)
+++ Zope/branches/ajung-zpt-end-game/lib/python/TAL/runtest.py	2006-05-28 23:07:07 UTC (rev 68317)
@@ -14,138 +14,11 @@
 ##############################################################################
 """
 Driver program to run METAL and TAL regression tests.
+
+BBB 2005/05/01 -- to be removed after 12 months
 """
+import zope.deprecation
+zope.deprecation.moved('zope.tal.runtest', '2.12')
 
-import sys
-import os
-from cStringIO import StringIO
-import glob
-import traceback
-
 if __name__ == "__main__":
-    import setpath                      # Local hack to tweak sys.path etc.
-
-import driver
-import tests.utils
-
-def showdiff(a, b):
-    import ndiff
-    cruncher = ndiff.SequenceMatcher(ndiff.IS_LINE_JUNK, a, b)
-    for tag, alo, ahi, blo, bhi in cruncher.get_opcodes():
-        if tag == "equal":
-            continue
-        print nicerange(alo, ahi) + tag[0] + nicerange(blo, bhi)
-        ndiff.dump('<', a, alo, ahi)
-        if a and b:
-            print '---'
-        ndiff.dump('>', b, blo, bhi)
-
-def nicerange(lo, hi):
-    if hi <= lo+1:
-        return str(lo+1)
-    else:
-        return "%d,%d" % (lo+1, hi)
-
-def main():
-    opts = []
-    args = sys.argv[1:]
-    quiet = 0
-    unittesting = 0
-    if args and args[0] == "-q":
-        quiet = 1
-        del args[0]
-    if args and args[0] == "-Q":
-        unittesting = 1
-        del args[0]
-    while args and args[0].startswith('-'):
-        opts.append(args[0])
-        del args[0]
-    if not args:
-        prefix = os.path.join("tests", "input", "test*.")
-        if tests.utils.skipxml:
-            xmlargs = []
-        else:
-            xmlargs = glob.glob(prefix + "xml")
-            xmlargs.sort()
-        htmlargs = glob.glob(prefix + "html")
-        htmlargs.sort()
-        args = xmlargs + htmlargs
-        if not args:
-             sys.stderr.write("No tests found -- please supply filenames\n")
-             sys.exit(1)
-    errors = 0
-    for arg in args:
-        locopts = []
-        if arg.find("metal") >= 0 and "-m" not in opts:
-            locopts.append("-m")
-        if not unittesting:
-            print arg,
-            sys.stdout.flush()
-        if tests.utils.skipxml and arg.endswith(".xml"):
-            print "SKIPPED (XML parser not available)"
-            continue
-        save = sys.stdout, sys.argv
-        try:
-            try:
-                sys.stdout = stdout = StringIO()
-                sys.argv = [""] + opts + locopts + [arg]
-                driver.main()
-            finally:
-                sys.stdout, sys.argv = save
-        except SystemExit:
-            raise
-        except:
-            errors = 1
-            if quiet:
-                print sys.exc_type
-                sys.stdout.flush()
-            else:
-                if unittesting:
-                    print
-                else:
-                    print "Failed:"
-                    sys.stdout.flush()
-                traceback.print_exc()
-            continue
-        head, tail = os.path.split(arg)
-        outfile = os.path.join(
-            head.replace("input", "output"),
-            tail)
-        try:
-            f = open(outfile)
-        except IOError:
-            expected = None
-            print "(missing file %s)" % outfile,
-        else:
-            expected = f.readlines()
-            f.close()
-        stdout.seek(0)
-        if hasattr(stdout, "readlines"):
-            actual = stdout.readlines()
-        else:
-            actual = readlines(stdout)
-        if actual == expected:
-            if not unittesting:
-                print "OK"
-        else:
-            if unittesting:
-                print
-            else:
-                print "not OK"
-            errors = 1
-            if not quiet and expected is not None:
-                showdiff(expected, actual)
-    if errors:
-        sys.exit(1)
-
-def readlines(f):
-    L = []
-    while 1:
-        line = f.readline()
-        if not line:
-            break
-        L.append(line)
-    return L
-
-if __name__ == "__main__":
     main()

Modified: Zope/branches/ajung-zpt-end-game/lib/python/TAL/talgettext.py
===================================================================
--- Zope/branches/ajung-zpt-end-game/lib/python/TAL/talgettext.py	2006-05-28 22:14:02 UTC (rev 68316)
+++ Zope/branches/ajung-zpt-end-game/lib/python/TAL/talgettext.py	2006-05-28 23:07:07 UTC (rev 68317)
@@ -1,318 +1,6 @@
+# BBB 2005/05/01 -- to be removed after 12 months
+import zope.deprecation
+zope.deprecation.moved('zope.tal.talgettext', '2.12')
 
-
-
-#!/usr/bin/env python
-##############################################################################
-#
-# 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.
-#
-##############################################################################
-
-"""Program to extract internationalization markup from Page Templates.
-
-Once you have marked up a Page Template file with i18n: namespace tags, use
-this program to extract GNU gettext .po file entries.
-
-Usage: talgettext.py [options] files
-Options:
-    -h / --help
-        Print this message and exit.
-    -o / --output <file>
-        Output the translation .po file to <file>.
-    -u / --update <file>
-        Update the existing translation <file> with any new translation strings
-        found.
-"""
-
-import sys
-import time
-import getopt
-import traceback
-
-from TAL.HTMLTALParser import HTMLTALParser
-from TAL.TALInterpreter import TALInterpreter
-from TAL.DummyEngine import DummyEngine
-from ITALES import ITALESEngine
-from TAL.TALDefs import TALESError
-
-__version__ = '$Revision: 1.1.2.1 $'
-
-pot_header = '''\
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR ORGANIZATION
-# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\\n"
-"POT-Creation-Date: %(time)s\\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n"
-"Last-Translator: FULL NAME <EMAIL at ADDRESS>\\n"
-"Language-Team: LANGUAGE <LL at li.org>\\n"
-"MIME-Version: 1.0\\n"
-"Content-Type: text/plain; charset=CHARSET\\n"
-"Content-Transfer-Encoding: ENCODING\\n"
-"Generated-By: talgettext.py %(version)s\\n"
-'''
-
-NLSTR = '"\n"'
-
-try:
-    True
-except NameError:
-    True=1
-    False=0
-
-def usage(code, msg=''):
-    # Python 2.1 required
-    print >> sys.stderr, __doc__
-    if msg:
-        print >> sys.stderr, msg
-    sys.exit(code)
-
-
-class POTALInterpreter(TALInterpreter):
-    def translate(self, msgid, default, i18ndict=None, obj=None):
-        # XXX is this right?
-        if i18ndict is None:
-            i18ndict = {}
-        if obj:
-            i18ndict.update(obj)
-        # XXX Mmmh, it seems that sometimes the msgid is None; is that really
-        # possible?
-        if msgid is None:
-            return None
-        # XXX We need to pass in one of context or target_language
-        return self.engine.translate(msgid, self.i18nContext.domain, i18ndict,
-                                     position=self.position, default=default)
-
-
-class POEngine(DummyEngine):
-    __implements__ = ITALESEngine
-
-    def __init__(self, macros=None):
-        self.catalog = {}
-        DummyEngine.__init__(self, macros)
-
-    def evaluate(*args):
-        return '' # who cares
-
-    def evaluatePathOrVar(*args):
-        return '' # who cares
-
-    def evaluateSequence(self, expr):
-        return (0,) # dummy
-
-    def evaluateBoolean(self, expr):
-        return True # dummy
-
-    def translate(self, msgid, domain=None, mapping=None, default=None,
-                  # XXX position is not part of the ITALESEngine
-                  #     interface
-                  position=None):
-
-        if domain not in self.catalog:
-            self.catalog[domain] = {}
-        domain = self.catalog[domain]
-
-        # ---------------------------------------------
-        # only non-empty msgids are added to dictionary
-        # (changed by heinrichbernd - 2004/09/07)
-        # ---------------------------------------------
-        if msgid:
-            if msgid not in domain:
-                domain[msgid] = []
-            domain[msgid].append((self.file, position))
-        return 'x'
-
-
-class UpdatePOEngine(POEngine):
-    """A slightly-less braindead POEngine which supports loading an existing
-    .po file first."""
-
-    def __init__ (self, macros=None, filename=None):
-        POEngine.__init__(self, macros)
-
-        self._filename = filename
-        self._loadFile()
-        self.base = self.catalog
-        self.catalog = {}
-
-    def __add(self, id, s, fuzzy):
-        "Add a non-fuzzy translation to the dictionary."
-        if not fuzzy and str:
-            # check for multi-line values and munge them appropriately
-            if '\n' in s:
-                lines = s.rstrip().split('\n')
-                s = NLSTR.join(lines)
-            self.catalog[id] = s
-
-    def _loadFile(self):
-        # shamelessly cribbed from Python's Tools/i18n/msgfmt.py
-        # 25-Mar-2003 Nathan R. Yergler (nathan at zope.org)
-        # 14-Apr-2003 Hacked by Barry Warsaw (barry at zope.com)
-
-        ID = 1
-        STR = 2
-
-        try:
-            lines = open(self._filename).readlines()
-        except IOError, msg:
-            print >> sys.stderr, msg
-            sys.exit(1)
-
-        section = None
-        fuzzy = False
-
-        # Parse the catalog
-        lno = 0
-        for l in lines:
-            lno += True
-            # If we get a comment line after a msgstr, this is a new entry
-            if l[0] == '#' and section == STR:
-                self.__add(msgid, msgstr, fuzzy)
-                section = None
-                fuzzy = False
-            # Record a fuzzy mark
-            if l[:2] == '#,' and l.find('fuzzy'):
-                fuzzy = True
-            # Skip comments
-            if l[0] == '#':
-                continue
-            # Now we are in a msgid section, output previous section
-            if l.startswith('msgid'):
-                if section == STR:
-                    self.__add(msgid, msgstr, fuzzy)
-                section = ID
-                l = l[5:]
-                msgid = msgstr = ''
-            # Now we are in a msgstr section
-            elif l.startswith('msgstr'):
-                section = STR
-                l = l[6:]
-            # Skip empty lines
-            if not l.strip():
-                continue
-            # XXX: Does this always follow Python escape semantics?
-            l = eval(l)
-            if section == ID:
-                msgid += l
-            elif section == STR:
-                msgstr += '%s\n' % l
-            else:
-                print >> sys.stderr, 'Syntax error on %s:%d' % (infile, lno), \
-                      'before:'
-                print >> sys.stderr, l
-                sys.exit(1)
-        # Add last entry
-        if section == STR:
-            self.__add(msgid, msgstr, fuzzy)
-
-    def evaluate(self, expression):
-        try:
-            return POEngine.evaluate(self, expression)
-        except TALESError:
-            pass
-
-    def evaluatePathOrVar(self, expr):
-        return 'who cares'
-
-    def translate(self, msgid, domain=None, mapping=None, default=None,
-                  position=None):
-        if msgid not in self.base:
-            POEngine.translate(self, msgid, domain, mapping, default, position)
-        return 'x'
-
-
-def main():
-    try:
-        opts, args = getopt.getopt(
-            sys.argv[1:],
-            'ho:u:',
-            ['help', 'output=', 'update='])
-    except getopt.error, msg:
-        usage(1, msg)
-
-    outfile = None
-    engine = None
-    update_mode = False
-    for opt, arg in opts:
-        if opt in ('-h', '--help'):
-            usage(0)
-        elif opt in ('-o', '--output'):
-            outfile = arg
-        elif opt in ('-u', '--update'):
-            update_mode = True
-            if outfile is None:
-                outfile = arg
-            engine = UpdatePOEngine(filename=arg)
-
-    if not args:
-        print 'nothing to do'
-        return
-
-    # We don't care about the rendered output of the .pt file
-    class Devnull:
-        def write(self, s):
-            pass
-
-    # check if we've already instantiated an engine;
-    # if not, use the stupidest one available
-    if not engine:
-        engine = POEngine()
-
-    # process each file specified
-    for filename in args:
-        try:
-            engine.file = filename
-            p = HTMLTALParser()
-            p.parseFile(filename)
-            program, macros = p.getCode()
-            POTALInterpreter(program, macros, engine, stream=Devnull(),
-                             metal=False)()
-        except: # Hee hee, I love bare excepts!
-            print 'There was an error processing', filename
-            traceback.print_exc()
-
-    # Now output the keys in the engine.  Write them to a file if --output or
-    # --update was specified; otherwise use standard out.
-    if (outfile is None):
-        outfile = sys.stdout
-    else:
-        outfile = file(outfile, update_mode and "a" or "w")
-    catalog = {}
-    for domain in engine.catalog.keys():
-        catalog.update(engine.catalog[domain])
-
-    messages = catalog.copy()
-    try:
-        messages.update(engine.base)
-    except AttributeError:
-        pass
-    if '' not in messages:
-        print >> outfile, pot_header % {'time': time.ctime(),
-                                        'version': __version__}
-
-    msgids = catalog.keys()
-    # XXX: You should not sort by msgid, but by filename and position. (SR)
-    msgids.sort()
-    for msgid in msgids:
-        positions = catalog[msgid]
-        for filename, position in positions:
-            outfile.write('#: %s:%s\n' % (filename, position[0]))
-
-        outfile.write('msgid "%s"\n' % msgid)
-        outfile.write('msgstr ""\n')
-        outfile.write('\n')
-
-
 if __name__ == '__main__':
     main()

Modified: Zope/branches/ajung-zpt-end-game/lib/python/TAL/timer.py
===================================================================
--- Zope/branches/ajung-zpt-end-game/lib/python/TAL/timer.py	2006-05-28 22:14:02 UTC (rev 68316)
+++ Zope/branches/ajung-zpt-end-game/lib/python/TAL/timer.py	2006-05-28 23:07:07 UTC (rev 68317)
@@ -14,44 +14,11 @@
 ##############################################################################
 """
 Helper program to time compilation and interpretation
+
+BBB 2005/05/01 -- to be removed after 12 months
 """
+import zope.deprecation
+zope.deprecation.moved('zope.tal.timer', '2.12')
 
-import sys
-import time
-import getopt
-from cPickle import dumps, loads
-from cStringIO import StringIO
-
-from driver import FILE, compilefile, interpretit
-
-def main():
-    count = 10
-    try:
-        opts, args = getopt.getopt(sys.argv[1:], "n:")
-    except getopt.error, msg:
-        print msg
-        sys.exit(2)
-    for o, a in opts:
-        if o == "-n":
-            count = int(a)
-    if not args:
-        args = [FILE]
-    for file in args:
-        print file
-        dummyfile = StringIO()
-        it = timefunc(count, compilefile, file)
-        timefunc(count, interpretit, it, None, dummyfile)
-
-def timefunc(count, func, *args):
-    sys.stderr.write("%-14s: " % func.__name__)
-    sys.stderr.flush()
-    t0 = time.clock()
-    for i in range(count):
-        result = func(*args)
-    t1 = time.clock()
-    sys.stderr.write("%6.3f secs for %d calls, i.e. %4.0f msecs per call\n"
-                     % ((t1-t0), count, 1000*(t1-t0)/count))
-    return result
-
 if __name__ == "__main__":
     main()



More information about the Zope-Checkins mailing list