0.6.7 (2010-08-04) Make compatible with Python 2.7 (patch kindly contributed by Jonathan Riboux). 0.6.6 Change download location. This really should be a setuptools package so we can upload it to PyPI. No functionality changes. 0.6.5 Apply patch for Python 2.5 compatibility from both Toshio and Anders. Create distro tarball via: rm MANIFEST USE_MELD3_EXTENSION_MODULES=1 python setup.py sdist .. in order to get the cmeld3.c file in the distribution. 0.6.4 Make the default build use the Python-based meld "helper" instead of the C-based one. Since the primary consumer of meld3 (as far as I know) is "supervisor", and since the typical supervisor consumer is likely not to have a C compiler and Python development libraries on his system, it makes more sense for the default build not to compile the C extensions. However, if the environment variable "USE_MELD3_EXTENSION_MODULES" is set when "setup.py install" is invoked, the C extensions will be built. meld3 is much slower without the C extensions, so using "USE_MELD3_EXTENSION_MODULES" is usually a good idea for performance-sensitive systems. As a result of this change, the "NO_MELD3_EXTENSION_MODULES" environment variable introduced in 0.6.1 now has no effect. 0.6.3 Fixed two more memory leaks (one in bfclonehandler, the other in findmeldhandler) in the c helper module. 0.6.2 Fixed a number of memory leaks in the C implementation of the helper module. Any use of "findmeld", "clone", "getiterator", or "content" previously leaked references. 0.6.1 Allow people to install meld3 without building extension modules. If the environment variable "NO_MELD3_EXTENSION_MODULES" is set, the meld3 setup.py file will not build any extension modules. meld3 will still work, only more slowly than if the extension modules existed. 0.6 Fixed crashbug when repeating trees with "structure" nodes in them. Symptom: bus error. Thanks to Terrence Brannon for the report. 0.5 Add 'fillmeldhtmlform' method to nodes. Fix obscure parsing bug that arose when attempting to change the URI used as a "meld id" (do not lowercase). Added three methods to element nodes: write_htmlstring write_xmlstring write_xhtmlstring These methods have the same respective argument lists as their "write_foo" cousins, except they don't accept a "file" argument. Instead of writing to a file, they return a string containing the renderering of the element. You can now use the meld3.py module to interactively try out different renderings. To do this, invoke meld3.py with a filename and a dotted-python-path name to a mutator function that accepts a single argument (the root element), e.g.: python meld3.py sample.html meld3.sample_mutator The rendering will be sent to stdout Remove unused parse method. Add __setslice__, __delslice__, remove methods that correctly update parent pointers. Don't call into superclass to do append, insert, __setitem__, etc. Internal speedups: - Avoid function call overhead in various places by inlining code. - _write_html/_write_xml now accept a callable "write" argument instead of a file argument (avoid file.write call overhead). - HTML serializer only calls _escape_cdata/_escape_attrib if necessary instead of calling it without regard to its need. - Use string.encode(encoding) instead of calling an _encode function. - Perform special-case rendering for English-centric encodings during write_html. - Ignore things that might be "QNames" during rendering. - "getiterator", "content", "clone", and "findmeld" now implemented in a C module. Experimental. Disable via changing "import cmeld3 as helper" in meld3.py to something like "import wontbehere". Fix text and attribute serialization to only quote ampersands that aren't already part of entities. Do the minimal possible thing to escape text and attribute values during rendering. For text, this is escaping ampersands that aren't parts of entities and the less-than (<) character. For attribute values, this is amps and less-than as well as the quote (") character. This was done partly because I think the spec allows it but it's also what Kid does, shrug. Change 'diffmeld()' to return a dictionary of dictionaries. The dictionary returned by diffmeld has the keys 'reduced' and 'unreduced'. the values of both 'reduced' and 'unreduced' is another dictionary. The leafmost dictionary has the keys 'added', 'removed', and 'moved. In the 'unreduced' dictionary, *all* meld tags that have been added, removed, or moved are present (this was the behavior of diffmeld previously). In the 'reduced' dictionary, the added, removed, and moved values are reduced to the smallest number of tags which share a common lineage. Add a meldprofile.py script. 0.4 The clone() method of elements copied neither the text nor the tail of the element (this is what caused markup created by "repeats" to fall all on one line). Add diffing capability to meld nodes. The file 'melddiff.py' shows an example of using the diff API. Add a 'meldid()' method to elements. This returns None if the element has no meld id, otherwise it returns the id. Add a 'fillmeld(**kw)' method to elements. This does the same thing as '__mod__' but returns meld ids (the keys of **kw) that cannot be found anywhere in the tree. Make source distro into a distutils-installable package. 0.3 Fix broken example.py file. Add ZPT-alike methods on elements: 'content', 'replace', and 'attributes'. 'content' replaces the node's content; 'replace' replaces the node itself with a text value, and 'attributes' sets the attributes of the node. Using the ElementTree API to do the same things usually causes the code to run faster, but these functions are more convenient and more easily grokked by ZPT people. Override __delitem__ on meld elements in order to relieve deleted items of their parent pointers. Strip all xhtml namespace identifiers out of XHTML output. Browsers just can't deal with this. Undocumented element API method 'remove' renamed to 'deparent' (it was shadowing an ElementTree API method). Documentation improvements and change examples to use ZPT-alike methods. Add support for HTML input files. Input files don't need to be strictly well-formed XML anymore. Remove the 'parse' top-level function in favor of explicit separate xml parsing and html parsing functions. Add 'parse_xml' and 'parse_html' top-level parsing functions. Add 'parse_xmlstring' and 'parse_htmlstring' module-scope functions which calls their respective 'parse_xxx' function with a StringIO containing the passed text. 0.2 Use a method on elements to do writing rather than requiring a user call a "write" function. The equivalent is now a method of the element named "write_xml". element.write_xml(file) performs a write of XML into the file. element.write_xml(...) includes an XML declaration in its serialization (but no doctype, at least by default). Various non-XML serialization methods have been added. The default arguments of these serialization methods are what I'm guessing are the most common cases desired for various kinds of qoutput:: element.write_html(...). This serializes the node and its children to HTML. This feature was inspired by and based on code Ian Bicking. By default, the serialization will include a 'loose' HTML DTD doctype (this can be overridden with the doctype= argument). "Empty" shortcut elements such as "
" will be converted to a balanced pair of tags e.g. "
". But some HTML tags (defined as per the HTML 4 spec as area, base, basefont, br, col, frame, hr, img, input, isindex, link, meta, param) will not be followed with a balanced ending tag; only the beginning tag will be output. Additionally, "boolean" tag attributes will not be followed with any value. The "boolean" tags are selected, checked, compact, declare, defer, disabled, ismap, multiple, nohref, noresize, noshade, and nowrap. So the XML input "" will be turned into "". Additionally, 'script' and 'style' tags will not have their contents escaped (e.g. so "&" will not be turned into & when it's iside the textual content of a script or style tag.) element.write_xhtml(...). This serializes the node and its children to XHTML. By default, the serialization will include a 'loose' XHTML doctype (this can be overridden with the doctype= argument). No XML declaration is included in the serialization by default. If you want to serialize an XML declaration, pass 'declaration=True'. All serialization methods have a number of optional arguments:: fragment: If this is true, serialize an element as a "fragment". When an element is serialized as a fragment, it will not include either a declaration nor a doctype (the declaration= and doctype= arguments will be ignored). doctype: Output a custom doctype during the writing of XML and HTML (see write, write_xml, write_xhtml, and write_html). Use the constants in meld3.doctype (xhtml, xhtml_strict, html, and html_strict) to avoid passing a literal 3-tuple of (name, pubid, system) as the doctype parameter. If fragment=True is specified for serialization, this argument has no effect. encoding: Specify a character encoding to be used during writing (see write, write_xml write_html, and write_xhtml). The encoding must be a valid Python codec name (e.g. 'utf-8'). If this is provided for write_xml and write_xhtml, and the XML declaration is serialized, the declaration will include the encoding. If an encoding is passed to write_html, no explicit encoding is included in the declaration but the serialization will be done with utf-8. XML serializations (write_xml and write_xhtml) have the aforementioned arguments but expose two additional optional arguments:: declaration: If this is true, an xml declaration header is output during the writing of XML (see write, write_xml, and write_xhtml). If the encoding is specified, and the serialization is meant to include an XML declaration (via declaration=), the declaration will include the encoding. If 'fragment=True' is specified for serialization, this argument has no effect. It doesn't matter if your input document had a declaration header; this option must be used to control declaration output. pipeline: If this is true, allow meld identifiers to be preserved during the writing of XML and XHTML (see write, write_xml and write_xhtml). meld identifiers cannot be preserved on HTML serializations because HTML doesn't understand namespaces. HTML entities can now be parsed properly (magically) when a DOCTYPE is not supplied in the source of the XML passed to 'parse'. If your source document does not contain a DOCTYPE declaration, the DOCTYPE is set to 'loose' XHTML 'by magic'. If your source document does contain a DOCTYPE declaration, the existing DOCTYPE is used (and HTML entities thus may or may not work as a result, depending on the DOCTYPE). To prevent this behavior, pass a false value to the xhtml= parameter of the 'parse' function. This in no way effects output, which is independent of parsing. This does not imply that any *non*-HTML entity can be parsed in the input stream under any circumstance without having it defined it in your source document. Comments are now preserved in output. They are also present in the ElementTree node tree (as Comment elements), so beware. Processing instructions (e.g. ) are completely thrown away at parse time and do not exist anywhere in the element tree. Avoid use of deepcopy in the clone() method of elements (much speedier to explicitly recurse). The "meld helper" namespace (e.g. element.meld) is no longer present or supported. Instead of using element.meld['foo'] to find an element with the meld:id "foo", use element.findmeld('foo'). This returns None if the node cannot be found. Instead of using element.meld.get('foo', 'somedefault'), use element.findmeld('foo', 'somedefault'). Instead of using element.meld.repeat(...), use element.repeat(...). Elements now support a __mod__ which can accept a dictionarylike operand and which causes the text of elements with meld ids which match the keys in the dictionary to be set to the key's value in the dictionary. For example, if an element contains subelements with the meld ids "foo" and "bar", you can replace those nodes' text values with the following:: element % {'foo':'foo text', 'bar':'bar text'} __mod__ will not accept a non-dictionary-like object (such as a list or tuple). __mod__ will never raise an error unless you pass it a non-dictionary-like object; if it can't find a node corresponding to a key in the dictionary, it moves on to the next key. Only the text values of the nodes which are found during this process are replaced. Using duplicate meld identifiers on separate elements in the document now causes a ValueError to be raised at parse time. 0.1 Initial release.