Browse Source

Include elementtree.

Copyright and liceneses files.
Chris McDonough 19 years ago
parent
commit
ecbfcfc00a

+ 4 - 0
COPYRIGHT.txt

@@ -0,0 +1,4 @@
+Supervisor and meld3 are Copyright (c) 2006, Chris McDonough.
+
+ElementTree is Copyright (c) 1999-2005 by Secret Labs AB, Copyright
+(c) 1999-2005 by Fredrik Lundh

+ 79 - 0
LICENSES.txt

@@ -0,0 +1,79 @@
+Supervisor and meld3 are licensed under the Zope Public License (ZPL)
+2.1 :
+
+  A copyright notice accompanies this license document that identifies
+  the copyright holders.
+
+  This license has been certified as open source. It has also been
+  designated as GPL compatible by the Free Software Foundation (FSF).
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are
+  met:
+
+  1.  Redistributions in source code must retain the accompanying
+      copyright notice, this list of conditions, and the following
+      disclaimer.
+
+  2.  Redistributions in binary form must reproduce the accompanying
+      copyright notice, this list of conditions, and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+  3.  Names of the copyright holders must not be used to endorse or
+      promote products derived from this software without prior
+      written permission from the copyright holders.
+
+  5.  The right to distribute this software or to use it for any
+      purpose does not give you the right to use Servicemarks (sm) or
+      Trademarks (tm) of the copyright holders. Use of them is covered
+      by separate agreement with the copyright holders.
+
+  6.  If any files are modified, you must cause the modified files to
+      carry prominent notices stating that you changed the files and
+      the date of any change.
+
+  Disclaimer
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND
+    ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+    TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+    HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+    TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+    ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+    SUCH DAMAGE.
+
+ElementTree, by Frederik Lundh, which ships with Supervisor as a
+convenience is licensed separately:
+
+  The ElementTree package and the cElementTree accelerator are:
+
+  Copyright (c) 1999-2005 by Secret Labs AB
+  Copyright (c) 1999-2005 by Fredrik Lundh
+
+  By obtaining, using, and/or copying this software and/or its
+  associated documentation, you agree that you have read, understood,
+  and will comply with the following terms and conditions:
+
+  Permission to use, copy, modify, and distribute this software and
+  its associated documentation for any purpose and without fee is
+  hereby granted, provided that the above copyright notice appears in
+  all copies, and that both that copyright notice and this permission
+  notice appear in supporting documentation, and that the name of
+  Secret Labs AB or the author not be used in advertising or publicity
+  pertaining to distribution of the software without specific, written
+  prior permission.
+
+  SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+  TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
+  MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR
+  THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+  DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
+  OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+  TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+  PERFORMANCE OF THIS SOFTWARE.

+ 3 - 2
README.txt

@@ -65,8 +65,9 @@ Introduction
 Supported Platforms
 
   Supervisor has been tested and is known to run on Linux (Fedora Core
-  5, Ubuntu 6), Mac OS X (10.4), and Solaris (10 for Intel).  It has
-  been reported to work on FreeBSD.
+  5, Ubuntu 6), Mac OS X (10.4), and Solaris (10 for Intel) and
+  FreeBSD 6.1.  It will likely work fine on most UNIX systems.  It
+  will not run at all under any version of Windows.
 
   Supervisor requires Python 2.3 or better.
 

+ 2 - 1
setup.py

@@ -22,7 +22,8 @@ setup(
     maintainer = "Chris McDonough",
     maintainer_email = "chrism@plope.com",
     scripts=['supervisord', 'supervisorctl'],
-    packages = ['supervisor', 'supervisor.medusa', 'supervisor.meld3'],
+    packages = ['supervisor', 'supervisor.medusa', 'supervisor.meld3',
+                'supervisor.meld3.elementtree'],
     package_dir = {'supervisor':'.'},
     package_data= {'supervisor':['ui/*.gif', 'ui/*.css', 'ui/*.html']},
     )

+ 141 - 0
src/meld3/elementtree/ElementInclude.py

@@ -0,0 +1,141 @@
+#
+# ElementTree
+# $Id$
+#
+# limited xinclude support for element trees
+#
+# history:
+# 2003-08-15 fl   created
+# 2003-11-14 fl   fixed default loader
+#
+# Copyright (c) 2003-2004 by Fredrik Lundh.  All rights reserved.
+#
+# fredrik@pythonware.com
+# http://www.pythonware.com
+#
+# --------------------------------------------------------------------
+# The ElementTree toolkit is
+#
+# Copyright (c) 1999-2004 by Fredrik Lundh
+#
+# By obtaining, using, and/or copying this software and/or its
+# associated documentation, you agree that you have read, understood,
+# and will comply with the following terms and conditions:
+#
+# Permission to use, copy, modify, and distribute this software and
+# its associated documentation for any purpose and without fee is
+# hereby granted, provided that the above copyright notice appears in
+# all copies, and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of
+# Secret Labs AB or the author not be used in advertising or publicity
+# pertaining to distribution of the software without specific, written
+# prior permission.
+#
+# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
+# ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
+# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+# --------------------------------------------------------------------
+
+##
+# Limited XInclude support for the ElementTree package.
+##
+
+import copy
+import ElementTree
+
+XINCLUDE = "{http://www.w3.org/2001/XInclude}"
+
+XINCLUDE_INCLUDE = XINCLUDE + "include"
+XINCLUDE_FALLBACK = XINCLUDE + "fallback"
+
+##
+# Fatal include error.
+
+class FatalIncludeError(SyntaxError):
+    pass
+
+##
+# Default loader.  This loader reads an included resource from disk.
+#
+# @param href Resource reference.
+# @param parse Parse mode.  Either "xml" or "text".
+# @param encoding Optional text encoding.
+# @return The expanded resource.  If the parse mode is "xml", this
+#    is an ElementTree instance.  If the parse mode is "text", this
+#    is a Unicode string.  If the loader fails, it can return None
+#    or raise an IOError exception.
+# @throws IOError If the loader fails to load the resource.
+
+def default_loader(href, parse, encoding=None):
+    file = open(href)
+    if parse == "xml":
+        data = ElementTree.parse(file).getroot()
+    else:
+        data = file.read()
+        if encoding:
+            data = data.decode(encoding)
+    file.close()
+    return data
+
+##
+# Expand XInclude directives.
+#
+# @param elem Root element.
+# @param loader Optional resource loader.  If omitted, it defaults
+#     to {@link default_loader}.  If given, it should be a callable
+#     that implements the same interface as <b>default_loader</b>.
+# @throws FatalIncludeError If the function fails to include a given
+#     resource, or if the tree contains malformed XInclude elements.
+# @throws IOError If the function fails to load a given resource.
+
+def include(elem, loader=None):
+    if loader is None:
+        loader = default_loader
+    # look for xinclude elements
+    i = 0
+    while i < len(elem):
+        e = elem[i]
+        if e.tag == XINCLUDE_INCLUDE:
+            # process xinclude directive
+            href = e.get("href")
+            parse = e.get("parse", "xml")
+            if parse == "xml":
+                node = loader(href, parse)
+                if node is None:
+                    raise FatalIncludeError(
+                        "cannot load %r as %r" % (href, parse)
+                        )
+                node = copy.copy(node)
+                if e.tail:
+                    node.tail = (node.tail or "") + e.tail
+                elem[i] = node
+            elif parse == "text":
+                text = loader(href, parse, e.get("encoding"))
+                if text is None:
+                    raise FatalIncludeError(
+                        "cannot load %r as %r" % (href, parse)
+                        )
+                if i:
+                    node = elem[i-1]
+                    node.tail = (node.tail or "") + text
+                else:
+                    elem.text = (elem.text or "") + text + (e.tail or "")
+                del elem[i]
+                continue
+            else:
+                raise FatalIncludeError(
+                    "unknown parse type in xi:include tag (%r)" % parse
+                )
+        elif e.tag == XINCLUDE_FALLBACK:
+            raise FatalIncludeError(
+                "xi:fallback tag must be child of xi:include (%r)" % e.tag
+                )
+        else:
+            include(e, loader)
+        i = i + 1
+

+ 196 - 0
src/meld3/elementtree/ElementPath.py

@@ -0,0 +1,196 @@
+#
+# ElementTree
+# $Id$
+#
+# limited xpath support for element trees
+#
+# history:
+# 2003-05-23 fl   created
+# 2003-05-28 fl   added support for // etc
+# 2003-08-27 fl   fixed parsing of periods in element names
+#
+# Copyright (c) 2003-2004 by Fredrik Lundh.  All rights reserved.
+#
+# fredrik@pythonware.com
+# http://www.pythonware.com
+#
+# --------------------------------------------------------------------
+# The ElementTree toolkit is
+#
+# Copyright (c) 1999-2004 by Fredrik Lundh
+#
+# By obtaining, using, and/or copying this software and/or its
+# associated documentation, you agree that you have read, understood,
+# and will comply with the following terms and conditions:
+#
+# Permission to use, copy, modify, and distribute this software and
+# its associated documentation for any purpose and without fee is
+# hereby granted, provided that the above copyright notice appears in
+# all copies, and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of
+# Secret Labs AB or the author not be used in advertising or publicity
+# pertaining to distribution of the software without specific, written
+# prior permission.
+#
+# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
+# ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
+# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+# --------------------------------------------------------------------
+
+##
+# Implementation module for XPath support.  There's usually no reason
+# to import this module directly; the <b>ElementTree</b> does this for
+# you, if needed.
+##
+
+import re
+
+xpath_tokenizer = re.compile(
+    "(::|\.\.|\(\)|[/.*:\[\]\(\)@=])|((?:\{[^}]+\})?[^/:\[\]\(\)@=\s]+)|\s+"
+    ).findall
+
+class xpath_descendant_or_self:
+    pass
+
+##
+# Wrapper for a compiled XPath.
+
+class Path:
+
+    ##
+    # Create an Path instance from an XPath expression.
+
+    def __init__(self, path):
+        tokens = xpath_tokenizer(path)
+        # the current version supports 'path/path'-style expressions only
+        self.path = []
+        self.tag = None
+        if tokens and tokens[0][0] == "/":
+            raise SyntaxError("cannot use absolute path on element")
+        while tokens:
+            op, tag = tokens.pop(0)
+            if tag or op == "*":
+                self.path.append(tag or op)
+            elif op == ".":
+                pass
+            elif op == "/":
+                self.path.append(xpath_descendant_or_self())
+                continue
+            else:
+                raise SyntaxError("unsupported path syntax (%s)" % op)
+            if tokens:
+                op, tag = tokens.pop(0)
+                if op != "/":
+                    raise SyntaxError(
+                        "expected path separator (%s)" % (op or tag)
+                        )
+        if self.path and isinstance(self.path[-1], xpath_descendant_or_self):
+            raise SyntaxError("path cannot end with //")
+        if len(self.path) == 1 and isinstance(self.path[0], type("")):
+            self.tag = self.path[0]
+
+    ##
+    # Find first matching object.
+
+    def find(self, element):
+        tag = self.tag
+        if tag is None:
+            nodeset = self.findall(element)
+            if not nodeset:
+                return None
+            return nodeset[0]
+        for elem in element:
+            if elem.tag == tag:
+                return elem
+        return None
+
+    ##
+    # Find text for first matching object.
+
+    def findtext(self, element, default=None):
+        tag = self.tag
+        if tag is None:
+            nodeset = self.findall(element)
+            if not nodeset:
+                return default
+            return nodeset[0].text or ""
+        for elem in element:
+            if elem.tag == tag:
+                return elem.text or ""
+        return default
+
+    ##
+    # Find all matching objects.
+
+    def findall(self, element):
+        nodeset = [element]
+        index = 0
+        while 1:
+            try:
+                path = self.path[index]
+                index = index + 1
+            except IndexError:
+                return nodeset
+            set = []
+            if isinstance(path, xpath_descendant_or_self):
+                try:
+                    tag = self.path[index]
+                    if not isinstance(tag, type("")):
+                        tag = None
+                    else:
+                        index = index + 1
+                except IndexError:
+                    tag = None # invalid path
+                for node in nodeset:
+                    new = list(node.getiterator(tag))
+                    if new and new[0] is node:
+                        set.extend(new[1:])
+                    else:
+                        set.extend(new)
+            else:
+                for node in nodeset:
+                    for node in node:
+                        if path == "*" or node.tag == path:
+                            set.append(node)
+            if not set:
+                return []
+            nodeset = set
+
+_cache = {}
+
+##
+# (Internal) Compile path.
+
+def _compile(path):
+    p = _cache.get(path)
+    if p is not None:
+        return p
+    p = Path(path)
+    if len(_cache) >= 100:
+        _cache.clear()
+    _cache[path] = p
+    return p
+
+##
+# Find first matching object.
+
+def find(element, path):
+    return _compile(path).find(element)
+
+##
+# Find text for first matching object.
+
+def findtext(element, path, default=None):
+    return _compile(path).findtext(element, default)
+
+##
+# Find all matching objects.
+
+def findall(element, path):
+    return _compile(path).findall(element)
+

File diff suppressed because it is too large
+ 1254 - 0
src/meld3/elementtree/ElementTree.py


+ 230 - 0
src/meld3/elementtree/HTMLTreeBuilder.py

@@ -0,0 +1,230 @@
+#
+# ElementTree
+# $Id$
+#
+# a simple tree builder, for HTML input
+#
+# history:
+# 2002-04-06 fl   created
+# 2002-04-07 fl   ignore IMG and HR end tags
+# 2002-04-07 fl   added support for 1.5.2 and later
+# 2003-04-13 fl   added HTMLTreeBuilder alias
+# 2004-12-02 fl   don't feed non-ASCII charrefs/entities as 8-bit strings
+# 2004-12-05 fl   don't feed non-ASCII CDATA as 8-bit strings
+#
+# Copyright (c) 1999-2004 by Fredrik Lundh.  All rights reserved.
+#
+# fredrik@pythonware.com
+# http://www.pythonware.com
+#
+# --------------------------------------------------------------------
+# The ElementTree toolkit is
+#
+# Copyright (c) 1999-2004 by Fredrik Lundh
+#
+# By obtaining, using, and/or copying this software and/or its
+# associated documentation, you agree that you have read, understood,
+# and will comply with the following terms and conditions:
+#
+# Permission to use, copy, modify, and distribute this software and
+# its associated documentation for any purpose and without fee is
+# hereby granted, provided that the above copyright notice appears in
+# all copies, and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of
+# Secret Labs AB or the author not be used in advertising or publicity
+# pertaining to distribution of the software without specific, written
+# prior permission.
+#
+# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
+# ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
+# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+# --------------------------------------------------------------------
+
+##
+# Tools to build element trees from HTML files.
+##
+
+import htmlentitydefs
+import re, string, sys
+import mimetools, StringIO
+
+import ElementTree
+
+AUTOCLOSE = "p", "li", "tr", "th", "td", "head", "body"
+IGNOREEND = "img", "hr", "meta", "link", "br"
+
+if sys.version[:3] == "1.5":
+    is_not_ascii = re.compile(r"[\x80-\xff]").search # 1.5.2
+else:
+    is_not_ascii = re.compile(eval(r'u"[\u0080-\uffff]"')).search
+
+try:
+    from HTMLParser import HTMLParser
+except ImportError:
+    from sgmllib import SGMLParser
+    # hack to use sgmllib's SGMLParser to emulate 2.2's HTMLParser
+    class HTMLParser(SGMLParser):
+        # the following only works as long as this class doesn't
+        # provide any do, start, or end handlers
+        def unknown_starttag(self, tag, attrs):
+            self.handle_starttag(tag, attrs)
+        def unknown_endtag(self, tag):
+            self.handle_endtag(tag)
+
+##
+# ElementTree builder for HTML source code.  This builder converts an
+# HTML document or fragment to an ElementTree.
+# <p>
+# The parser is relatively picky, and requires balanced tags for most
+# elements.  However, elements belonging to the following group are
+# automatically closed: P, LI, TR, TH, and TD.  In addition, the
+# parser automatically inserts end tags immediately after the start
+# tag, and ignores any end tags for the following group: IMG, HR,
+# META, and LINK.
+#
+# @keyparam builder Optional builder object.  If omitted, the parser
+#     uses the standard <b>elementtree</b> builder.
+# @keyparam encoding Optional character encoding, if known.  If omitted,
+#     the parser looks for META tags inside the document.  If no tags
+#     are found, the parser defaults to ISO-8859-1.  Note that if your
+#     document uses a non-ASCII compatible encoding, you must decode
+#     the document before parsing.
+#
+# @see elementtree.ElementTree
+
+class HTMLTreeBuilder(HTMLParser):
+
+    # FIXME: shouldn't this class be named Parser, not Builder?
+
+    def __init__(self, builder=None, encoding=None):
+        self.__stack = []
+        if builder is None:
+            builder = ElementTree.TreeBuilder()
+        self.__builder = builder
+        self.encoding = encoding or "iso-8859-1"
+        HTMLParser.__init__(self)
+
+    ##
+    # Flushes parser buffers, and return the root element.
+    #
+    # @return An Element instance.
+
+    def close(self):
+        HTMLParser.close(self)
+        return self.__builder.close()
+
+    ##
+    # (Internal) Handles start tags.
+
+    def handle_starttag(self, tag, attrs):
+        if tag == "meta":
+            # look for encoding directives
+            http_equiv = content = None
+            for k, v in attrs:
+                if k == "http-equiv":
+                    http_equiv = string.lower(v)
+                elif k == "content":
+                    content = v
+            if http_equiv == "content-type" and content:
+                # use mimetools to parse the http header
+                header = mimetools.Message(
+                    StringIO.StringIO("%s: %s\n\n" % (http_equiv, content))
+                    )
+                encoding = header.getparam("charset")
+                if encoding:
+                    self.encoding = encoding
+        if tag in AUTOCLOSE:
+            if self.__stack and self.__stack[-1] == tag:
+                self.handle_endtag(tag)
+        self.__stack.append(tag)
+        attrib = {}
+        if attrs:
+            for k, v in attrs:
+                attrib[string.lower(k)] = v
+        self.__builder.start(tag, attrib)
+        if tag in IGNOREEND:
+            self.__stack.pop()
+            self.__builder.end(tag)
+
+    ##
+    # (Internal) Handles end tags.
+
+    def handle_endtag(self, tag):
+        if tag in IGNOREEND:
+            return
+        lasttag = self.__stack.pop()
+        if tag != lasttag and lasttag in AUTOCLOSE:
+            self.handle_endtag(lasttag)
+        self.__builder.end(tag)
+
+    ##
+    # (Internal) Handles character references.
+
+    def handle_charref(self, char):
+        if char[:1] == "x":
+            char = int(char[1:], 16)
+        else:
+            char = int(char)
+        if 0 <= char < 128:
+            self.__builder.data(chr(char))
+        else:
+            self.__builder.data(unichr(char))
+
+    ##
+    # (Internal) Handles entity references.
+
+    def handle_entityref(self, name):
+        entity = htmlentitydefs.entitydefs.get(name)
+        if entity:
+            if len(entity) == 1:
+                entity = ord(entity)
+            else:
+                entity = int(entity[2:-1])
+            if 0 <= entity < 128:
+                self.__builder.data(chr(entity))
+            else:
+                self.__builder.data(unichr(entity))
+        else:
+            self.unknown_entityref(name)
+
+    ##
+    # (Internal) Handles character data.
+
+    def handle_data(self, data):
+        if isinstance(data, type('')) and is_not_ascii(data):
+            # convert to unicode, but only if necessary
+            data = unicode(data, self.encoding, "ignore")
+        self.__builder.data(data)
+
+    ##
+    # (Hook) Handles unknown entity references.  The default action
+    # is to ignore unknown entities.
+
+    def unknown_entityref(self, name):
+        pass # ignore by default; override if necessary
+
+##
+# An alias for the <b>HTMLTreeBuilder</b> class.
+
+TreeBuilder = HTMLTreeBuilder
+
+##
+# Parse an HTML document or document fragment.
+#
+# @param source A filename or file object containing HTML data.
+# @param encoding Optional character encoding, if known.  If omitted,
+#     the parser looks for META tags inside the document.  If no tags
+#     are found, the parser defaults to ISO-8859-1.
+# @return An ElementTree instance
+
+def parse(source, encoding=None):
+    return ElementTree.parse(source, HTMLTreeBuilder(encoding=encoding))
+
+if __name__ == "__main__":
+    import sys
+    ElementTree.dump(parse(open(sys.argv[1])))

+ 103 - 0
src/meld3/elementtree/SgmlopXMLTreeBuilder.py

@@ -0,0 +1,103 @@
+#
+# ElementTree
+# $Id$
+#
+# A simple XML tree builder, based on the sgmlop library.
+#
+# Note that this version does not support namespaces.  This may be
+# changed in future versions.
+#
+# history:
+# 2004-03-28 fl   created
+#
+# Copyright (c) 1999-2004 by Fredrik Lundh.  All rights reserved.
+#
+# fredrik@pythonware.com
+# http://www.pythonware.com
+#
+# --------------------------------------------------------------------
+# The ElementTree toolkit is
+#
+# Copyright (c) 1999-2004 by Fredrik Lundh
+#
+# By obtaining, using, and/or copying this software and/or its
+# associated documentation, you agree that you have read, understood,
+# and will comply with the following terms and conditions:
+#
+# Permission to use, copy, modify, and distribute this software and
+# its associated documentation for any purpose and without fee is
+# hereby granted, provided that the above copyright notice appears in
+# all copies, and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of
+# Secret Labs AB or the author not be used in advertising or publicity
+# pertaining to distribution of the software without specific, written
+# prior permission.
+#
+# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
+# ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
+# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+# --------------------------------------------------------------------
+
+##
+# Tools to build element trees from XML, based on the SGMLOP parser.
+# <p>
+# The current version does not support XML namespaces.
+# <p>
+# This tree builder requires the <b>sgmlop</b> extension module
+# (available from
+# <a href='http://effbot.org/downloads'>http://effbot.org/downloads</a>).
+##
+
+import ElementTree
+
+##
+# ElementTree builder for XML source data, based on the SGMLOP parser.
+#
+# @see elementtree.ElementTree
+
+class TreeBuilder:
+
+    def __init__(self, html=0):
+        try:
+            import sgmlop
+        except ImportError:
+            raise RuntimeError("sgmlop parser not available")
+        self.__builder = ElementTree.TreeBuilder()
+        if html:
+            import htmlentitydefs
+            self.entitydefs.update(htmlentitydefs.entitydefs)
+        self.__parser = sgmlop.XMLParser()
+        self.__parser.register(self)
+
+    ##
+    # Feeds data to the parser.
+    #
+    # @param data Encoded data.
+
+    def feed(self, data):
+        self.__parser.feed(data)
+
+    ##
+    # Finishes feeding data to the parser.
+    #
+    # @return An element structure.
+    # @defreturn Element
+
+    def close(self):
+        self.__parser.close()
+        self.__parser = None
+        return self.__builder.close()
+
+    def finish_starttag(self, tag, attrib):
+        self.__builder.start(tag, attrib)
+
+    def finish_endtag(self, tag):
+        self.__builder.end(tag)
+
+    def handle_data(self, data):
+        self.__builder.data(data)

+ 144 - 0
src/meld3/elementtree/SimpleXMLTreeBuilder.py

@@ -0,0 +1,144 @@
+#
+# ElementTree
+# $Id$
+#
+# A simple XML tree builder, based on Python's xmllib
+#
+# Note that due to bugs in xmllib, this builder does not fully support
+# namespaces (unqualified attributes are put in the default namespace,
+# instead of being left as is).  Run this module as a script to find
+# out if this affects your Python version.
+#
+# history:
+# 2001-10-20 fl   created
+# 2002-05-01 fl   added namespace support for xmllib
+# 2002-08-17 fl   added xmllib sanity test
+#
+# Copyright (c) 1999-2004 by Fredrik Lundh.  All rights reserved.
+#
+# fredrik@pythonware.com
+# http://www.pythonware.com
+#
+# --------------------------------------------------------------------
+# The ElementTree toolkit is
+#
+# Copyright (c) 1999-2004 by Fredrik Lundh
+#
+# By obtaining, using, and/or copying this software and/or its
+# associated documentation, you agree that you have read, understood,
+# and will comply with the following terms and conditions:
+#
+# Permission to use, copy, modify, and distribute this software and
+# its associated documentation for any purpose and without fee is
+# hereby granted, provided that the above copyright notice appears in
+# all copies, and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of
+# Secret Labs AB or the author not be used in advertising or publicity
+# pertaining to distribution of the software without specific, written
+# prior permission.
+#
+# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
+# ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
+# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+# --------------------------------------------------------------------
+
+##
+# Tools to build element trees from XML files, using <b>xmllib</b>.
+# This module can be used instead of the standard tree builder, for
+# Python versions where "expat" is not available (such as 1.5.2).
+# <p>
+# Note that due to bugs in <b>xmllib</b>, the namespace support is
+# not reliable (you can run the module as a script to find out exactly
+# how unreliable it is on your Python version).
+##
+
+import xmllib, string
+
+import ElementTree
+
+##
+# ElementTree builder for XML source data.
+#
+# @see elementtree.ElementTree
+
+class TreeBuilder(xmllib.XMLParser):
+
+    def __init__(self, html=0):
+        self.__builder = ElementTree.TreeBuilder()
+        if html:
+            import htmlentitydefs
+            self.entitydefs.update(htmlentitydefs.entitydefs)
+        xmllib.XMLParser.__init__(self)
+
+    ##
+    # Feeds data to the parser.
+    #
+    # @param data Encoded data.
+
+    def feed(self, data):
+        xmllib.XMLParser.feed(self, data)
+
+    ##
+    # Finishes feeding data to the parser.
+    #
+    # @return An element structure.
+    # @defreturn Element
+
+    def close(self):
+        xmllib.XMLParser.close(self)
+        return self.__builder.close()
+
+    def handle_data(self, data):
+        self.__builder.data(data)
+
+    handle_cdata = handle_data
+
+    def unknown_starttag(self, tag, attrs):
+        attrib = {}
+        for key, value in attrs.items():
+            attrib[fixname(key)] = value
+        self.__builder.start(fixname(tag), attrib)
+
+    def unknown_endtag(self, tag):
+        self.__builder.end(fixname(tag))
+
+
+def fixname(name, split=string.split):
+    # xmllib in 2.0 and later provides limited (and slightly broken)
+    # support for XML namespaces.
+    if " " not in name:
+        return name
+    return "{%s}%s" % tuple(split(name, " ", 1))
+
+
+if __name__ == "__main__":
+    import sys
+    # sanity check: look for known namespace bugs in xmllib
+    p = TreeBuilder()
+    text = """\
+    <root xmlns='default'>
+       <tag attribute='value' />
+    </root>
+    """
+    p.feed(text)
+    tree = p.close()
+    status = []
+    # check for bugs in the xmllib implementation
+    tag = tree.find("{default}tag")
+    if tag is None:
+        status.append("namespaces not supported")
+    if tag is not None and tag.get("{default}attribute"):
+        status.append("default namespace applied to unqualified attribute")
+    # report bugs
+    if status:
+        print "xmllib doesn't work properly in this Python version:"
+        for bug in status:
+            print "-", bug
+    else:
+        print "congratulations; no problems found in xmllib"
+

+ 279 - 0
src/meld3/elementtree/SimpleXMLWriter.py

@@ -0,0 +1,279 @@
+#
+# SimpleXMLWriter
+# $Id$
+#
+# a simple XML writer
+#
+# history:
+# 2001-12-28 fl   created
+# 2002-11-25 fl   fixed attribute encoding
+# 2002-12-02 fl   minor fixes for 1.5.2
+# 2004-06-17 fl   added pythondoc markup
+# 2004-07-23 fl   added flush method (from Jay Graves)
+# 2004-10-03 fl   added declaration method
+#
+# Copyright (c) 2001-2004 by Fredrik Lundh
+#
+# fredrik@pythonware.com
+# http://www.pythonware.com
+#
+# --------------------------------------------------------------------
+# The SimpleXMLWriter module is
+#
+# Copyright (c) 2001-2004 by Fredrik Lundh
+#
+# By obtaining, using, and/or copying this software and/or its
+# associated documentation, you agree that you have read, understood,
+# and will comply with the following terms and conditions:
+#
+# Permission to use, copy, modify, and distribute this software and
+# its associated documentation for any purpose and without fee is
+# hereby granted, provided that the above copyright notice appears in
+# all copies, and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of
+# Secret Labs AB or the author not be used in advertising or publicity
+# pertaining to distribution of the software without specific, written
+# prior permission.
+#
+# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
+# ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
+# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+# --------------------------------------------------------------------
+
+##
+# Tools to write XML files, without having to deal with encoding
+# issues, well-formedness, etc.
+# <p>
+# The current version does not provide built-in support for
+# namespaces. To create files using namespaces, you have to provide
+# "xmlns" attributes and explicitly add prefixes to tags and
+# attributes.
+#
+# <h3>Patterns</h3>
+#
+# The following example generates a small XHTML document.
+# <pre>
+#
+# from elementtree.SimpleXMLWriter import XMLWriter
+# import sys
+#
+# w = XMLWriter(sys.stdout)
+#
+# html = w.start("html")
+#
+# w.start("head")
+# w.element("title", "my document")
+# w.element("meta", name="generator", value="my application 1.0")
+# w.end()
+#
+# w.start("body")
+# w.element("h1", "this is a heading")
+# w.element("p", "this is a paragraph")
+#
+# w.start("p")
+# w.data("this is ")
+# w.element("b", "bold")
+# w.data(" and ")
+# w.element("i", "italic")
+# w.data(".")
+# w.end("p")
+#
+# w.close(html)
+# </pre>
+##
+
+import re, sys, string
+
+try:
+    unicode("")
+except NameError:
+    def encode(s, encoding):
+        # 1.5.2: application must use the right encoding
+        return s
+    _escape = re.compile(r"[&<>\"\x80-\xff]+") # 1.5.2
+else:
+    def encode(s, encoding):
+        return s.encode(encoding)
+    _escape = re.compile(eval(r'u"[&<>\"\u0080-\uffff]+"'))
+
+def encode_entity(text, pattern=_escape):
+    # map reserved and non-ascii characters to numerical entities
+    def escape_entities(m):
+        out = []
+        for char in m.group():
+            out.append("&#%d;" % ord(char))
+        return string.join(out, "")
+    return encode(pattern.sub(escape_entities, text), "ascii")
+
+del _escape
+
+#
+# the following functions assume an ascii-compatible encoding
+# (or "utf-16")
+
+def escape_cdata(s, encoding=None, replace=string.replace):
+    s = replace(s, "&", "&amp;")
+    s = replace(s, "<", "&lt;")
+    s = replace(s, ">", "&gt;")
+    if encoding:
+        try:
+            return encode(s, encoding)
+        except UnicodeError:
+            return encode_entity(s)
+    return s
+
+def escape_attrib(s, encoding=None, replace=string.replace):
+    s = replace(s, "&", "&amp;")
+    s = replace(s, "'", "&apos;")
+    s = replace(s, "\"", "&quot;")
+    s = replace(s, "<", "&lt;")
+    s = replace(s, ">", "&gt;")
+    if encoding:
+        try:
+            return encode(s, encoding)
+        except UnicodeError:
+            return encode_entity(s)
+    return s
+
+##
+# XML writer class.
+#
+# @param file A file or file-like object.  This object must implement
+#    a <b>write</b> method that takes an 8-bit string.
+# @param encoding Optional encoding.
+
+class XMLWriter:
+
+    def __init__(self, file, encoding="us-ascii"):
+        if not hasattr(file, "write"):
+            file = open(file, "w")
+        self.__write = file.write
+        if hasattr(file, "flush"):
+            self.flush = file.flush
+        self.__open = 0 # true if start tag is open
+        self.__tags = []
+        self.__data = []
+        self.__encoding = encoding
+
+    def __flush(self):
+        # flush internal buffers
+        if self.__open:
+            self.__write(">")
+            self.__open = 0
+        if self.__data:
+            data = string.join(self.__data, "")
+            self.__write(escape_cdata(data, self.__encoding))
+            self.__data = []
+
+    ##
+    # Writes an XML declaration.
+
+    def declaration(self):
+        encoding = self.__encoding
+        if encoding == "us-ascii" or encoding == "utf-8":
+            self.__write("<?xml version='1.0'?>\n")
+        else:
+            self.__write("<?xml version='1.0' encoding='%s'?>\n" % encoding)
+
+    ##
+    # Opens a new element.  Attributes can be given as keyword
+    # arguments, or as a string/string dictionary. You can pass in
+    # 8-bit strings or Unicode strings; the former are assumed to use
+    # the encoding passed to the constructor.  The method returns an
+    # opaque identifier that can be passed to the <b>close</b> method,
+    # to close all open elements up to and including this one.
+    #
+    # @param tag Element tag.
+    # @param attrib Attribute dictionary.  Alternatively, attributes
+    #    can be given as keyword arguments.
+    # @return An element identifier.
+
+    def start(self, tag, attrib={}, **extra):
+        self.__flush()
+        tag = escape_cdata(tag, self.__encoding)
+        self.__data = []
+        self.__tags.append(tag)
+        self.__write("<%s" % tag)
+        if attrib or extra:
+            attrib = attrib.copy()
+            attrib.update(extra)
+            attrib = attrib.items()
+            attrib.sort()
+            for k, v in attrib:
+                k = escape_cdata(k, self.__encoding)
+                v = escape_attrib(v, self.__encoding)
+                self.__write(" %s=\"%s\"" % (k, v))
+        self.__open = 1
+        return len(self.__tags)-1
+
+    ##
+    # Adds a comment to the output stream.
+    #
+    # @param comment Comment text, as an 8-bit string or Unicode string.
+
+    def comment(self, comment):
+        self.__flush()
+        self.__write("<!-- %s -->\n" % escape_cdata(comment, self.__encoding))
+
+    ##
+    # Adds character data to the output stream.
+    #
+    # @param text Character data, as an 8-bit string or Unicode string.
+
+    def data(self, text):
+        self.__data.append(text)
+
+    ##
+    # Closes the current element (opened by the most recent call to
+    # <b>start</b>).
+    #
+    # @param tag Element tag.  If given, the tag must match the start
+    #    tag.  If omitted, the current element is closed.
+
+    def end(self, tag=None):
+        if tag:
+            assert self.__tags, "unbalanced end(%s)" % tag
+            assert escape_cdata(tag, self.__encoding) == self.__tags[-1],\
+                   "expected end(%s), got %s" % (self.__tags[-1], tag)
+        else:
+            assert self.__tags, "unbalanced end()"
+        tag = self.__tags.pop()
+        if self.__data:
+            self.__flush()
+        elif self.__open:
+            self.__open = 0
+            self.__write(" />")
+            return
+        self.__write("</%s>" % tag)
+
+    ##
+    # Closes open elements, up to (and including) the element identified
+    # by the given identifier.
+    #
+    # @param id Element identifier, as returned by the <b>start</b> method.
+
+    def close(self, id):
+        while len(self.__tags) > id:
+            self.end()
+
+    ##
+    # Adds an entire element.  This is the same as calling <b>start</b>,
+    # <b>data</b>, and <b>end</b> in sequence. The <b>text</b> argument
+    # can be omitted.
+
+    def element(self, tag, text=None, attrib={}, **extra):
+        apply(self.start, (tag, attrib), extra)
+        if text:
+            self.data(text)
+        self.end()
+
+    ##
+    # Flushes the output stream.
+
+    def flush(self):
+        pass # replaced by the constructor

+ 6 - 0
src/meld3/elementtree/TidyHTMLTreeBuilder.py

@@ -0,0 +1,6 @@
+#
+# ElementTree
+# $Id$
+#
+
+from elementtidy.TidyHTMLTreeBuilder import *

+ 128 - 0
src/meld3/elementtree/TidyTools.py

@@ -0,0 +1,128 @@
+#
+# ElementTree
+# $Id$
+#
+# tools to run the "tidy" command on an HTML or XHTML file, and return
+# the contents as an XHTML element tree.
+#
+# history:
+# 2002-10-19 fl   added to ElementTree library; added getzonebody function
+#
+# Copyright (c) 1999-2004 by Fredrik Lundh.  All rights reserved.
+#
+# fredrik@pythonware.com
+# http://www.pythonware.com
+#
+
+##
+# Tools to build element trees from HTML, using the external <b>tidy</b>
+# utility.
+##
+
+import glob, string, os, sys
+
+from ElementTree import ElementTree, Element
+
+NS_XHTML = "{http://www.w3.org/1999/xhtml}"
+
+##
+# Convert an HTML or HTML-like file to XHTML, using the <b>tidy</b>
+# command line utility.
+#
+# @param file Filename.
+# @param new_inline_tags An optional list of valid but non-standard
+#     inline tags.
+# @return An element tree, or None if not successful.
+
+def tidy(file, new_inline_tags=None):
+
+    command = ["tidy", "-qn", "-asxml"]
+
+    if new_inline_tags:
+        command.append("--new-inline-tags")
+        command.append(string.join(new_inline_tags, ","))
+
+    # FIXME: support more tidy options!
+
+    # convert
+    os.system(
+        "%s %s >%s.out 2>%s.err" % (string.join(command), file, file, file)
+        )
+    # check that the result is valid XML
+    try:
+        tree = ElementTree()
+        tree.parse(file + ".out")
+    except:
+        print "*** %s:%s" % sys.exc_info()[:2]
+        print ("*** %s is not valid XML "
+               "(check %s.err for info)" % (file, file))
+        tree = None
+    else:
+        if os.path.isfile(file + ".out"):
+            os.remove(file + ".out")
+        if os.path.isfile(file + ".err"):
+            os.remove(file + ".err")
+
+    return tree
+
+##
+# Get document body from a an HTML or HTML-like file.  This function
+# uses the <b>tidy</b> function to convert HTML to XHTML, and cleans
+# up the resulting XML tree.
+#
+# @param file Filename.
+# @return A <b>body</b> element, or None if not successful.
+
+def getbody(file, **options):
+    # get clean body from text file
+
+    # get xhtml tree
+    try:
+        tree = apply(tidy, (file,), options)
+        if tree is None:
+            return
+    except IOError, v:
+        print "***", v
+        return None
+
+    NS = NS_XHTML
+
+    # remove namespace uris
+    for node in tree.getiterator():
+        if node.tag.startswith(NS):
+            node.tag = node.tag[len(NS):]
+
+    body = tree.getroot().find("body")
+
+    return body
+
+##
+# Same as <b>getbody</b>, but turns plain text at the start of the
+# document into an H1 tag.  This function can be used to parse zone
+# documents.
+#
+# @param file Filename.
+# @return A <b>body</b> element, or None if not successful.
+
+def getzonebody(file, **options):
+
+    body = getbody(file, **options)
+    if body is None:
+        return
+
+    if body.text and string.strip(body.text):
+        title = Element("h1")
+        title.text = string.strip(body.text)
+        title.tail = "\n\n"
+        body.insert(0, title)
+
+    body.text = None
+
+    return body
+
+if __name__ == "__main__":
+
+    import sys
+    for arg in sys.argv[1:]:
+        for file in glob.glob(arg):
+            print file, "...", tidy(file)

+ 113 - 0
src/meld3/elementtree/XMLTreeBuilder.py

@@ -0,0 +1,113 @@
+#
+# ElementTree
+# $Id$
+#
+# an XML tree builder
+#
+# history:
+# 2001-10-20 fl   created
+# 2002-05-01 fl   added namespace support for xmllib
+# 2002-07-27 fl   require expat (1.5.2 code can use SimpleXMLTreeBuilder)
+# 2002-08-17 fl   use tag/attribute name memo cache
+# 2002-12-04 fl   moved XMLTreeBuilder to the ElementTree module
+#
+# Copyright (c) 1999-2004 by Fredrik Lundh.  All rights reserved.
+#
+# fredrik@pythonware.com
+# http://www.pythonware.com
+#
+# --------------------------------------------------------------------
+# The ElementTree toolkit is
+#
+# Copyright (c) 1999-2004 by Fredrik Lundh
+#
+# By obtaining, using, and/or copying this software and/or its
+# associated documentation, you agree that you have read, understood,
+# and will comply with the following terms and conditions:
+#
+# Permission to use, copy, modify, and distribute this software and
+# its associated documentation for any purpose and without fee is
+# hereby granted, provided that the above copyright notice appears in
+# all copies, and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of
+# Secret Labs AB or the author not be used in advertising or publicity
+# pertaining to distribution of the software without specific, written
+# prior permission.
+#
+# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
+# ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
+# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+# --------------------------------------------------------------------
+
+##
+# Tools to build element trees from XML files.
+##
+
+import ElementTree
+
+##
+# (obsolete) ElementTree builder for XML source data, based on the
+# <b>expat</b> parser.
+# <p>
+# This class is an alias for ElementTree.XMLTreeBuilder.  New code
+# should use that version instead.
+#
+# @see elementtree.ElementTree
+
+class TreeBuilder(ElementTree.XMLTreeBuilder):
+    pass
+
+##
+# (experimental) An alternate builder that supports manipulation of
+# new elements.
+
+class FancyTreeBuilder(TreeBuilder):
+
+    def __init__(self, html=0):
+        TreeBuilder.__init__(self, html)
+        self._parser.StartNamespaceDeclHandler = self._start_ns
+        self._parser.EndNamespaceDeclHandler = self._end_ns
+        self.namespaces = []
+
+    def _start(self, tag, attrib_in):
+        elem = TreeBuilder._start(self, tag, attrib_in)
+        self.start(elem)
+
+    def _start_list(self, tag, attrib_in):
+        elem = TreeBuilder._start_list(self, tag, attrib_in)
+        self.start(elem)
+
+    def _end(self, tag):
+        elem = TreeBuilder._end(self, tag)
+        self.end(elem)
+
+    def _start_ns(self, prefix, value):
+        self.namespaces.insert(0, (prefix, value))
+
+    def _end_ns(self, prefix):
+        assert self.namespaces.pop(0)[0] == prefix, "implementation confused"
+
+    ##
+    # Hook method that's called when a new element has been opened.
+    # May access the <b>namespaces</b> attribute.
+    #
+    # @param element The new element.  The tag name and attributes are,
+    #     set, but it has no children, and the text and tail attributes
+    #     are still empty.
+
+    def start(self, element):
+        pass
+
+    ##
+    # Hook method that's called when a new element has been closed.
+    # May access the <b>namespaces</b> attribute.
+    #
+    # @param element The new element.
+
+    def end(self, element):
+        pass

+ 30 - 0
src/meld3/elementtree/__init__.py

@@ -0,0 +1,30 @@
+# $Id$
+# elementtree package
+
+# --------------------------------------------------------------------
+# The ElementTree toolkit is
+#
+# Copyright (c) 1999-2004 by Fredrik Lundh
+#
+# By obtaining, using, and/or copying this software and/or its
+# associated documentation, you agree that you have read, understood,
+# and will comply with the following terms and conditions:
+#
+# Permission to use, copy, modify, and distribute this software and
+# its associated documentation for any purpose and without fee is
+# hereby granted, provided that the above copyright notice appears in
+# all copies, and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of
+# Secret Labs AB or the author not be used in advertising or publicity
+# pertaining to distribution of the software without specific, written
+# prior permission.
+#
+# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
+# ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
+# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+# --------------------------------------------------------------------