From scoder at codespeak.net Sat Sep 9 07:17:18 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Sat, 9 Sep 2006 07:17:18 +0200 (CEST) Subject: [Lxml-checkins] r32092 - lxml/trunk/doc Message-ID: <20060909051718.6AAEB10079@code0.codespeak.net> Author: scoder Date: Sat Sep 9 07:17:16 2006 New Revision: 32092 Modified: lxml/trunk/doc/build.txt Log: Debian build hint by Pawel Palucha Modified: lxml/trunk/doc/build.txt ============================================================================== --- lxml/trunk/doc/build.txt (original) +++ lxml/trunk/doc/build.txt Sat Sep 9 07:17:16 2006 @@ -217,7 +217,8 @@ * remove the unpacked directory * tar.gz the lxml SVN version and replace the orig.tar.gz that lies in the directory -* do ``dpkg -x lxml-...dsc`` and cd into the newly created directory +* check md5sum of created tar.gz file and place new sum and size in dsc file +* do ``dpkg-source -x lxml-...dsc`` and cd into the newly created directory * run ``dch -i`` and add a comment like "use trunk version", this will increase the debian version number so apt/dpkg don't get confused * run ``dpkg-buildpackage -rfakeroot -us -uc`` to build the package From scoder at codespeak.net Sat Sep 9 07:18:53 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Sat, 9 Sep 2006 07:18:53 +0200 (CEST) Subject: [Lxml-checkins] r32093 - lxml/trunk/doc Message-ID: <20060909051853.1A0CC10079@code0.codespeak.net> Author: scoder Date: Sat Sep 9 07:18:49 2006 New Revision: 32093 Modified: lxml/trunk/doc/objectify.txt Log: doc update: show how to access children called 'text' etc. in objectify Modified: lxml/trunk/doc/objectify.txt ============================================================================== --- lxml/trunk/doc/objectify.txt (original) +++ lxml/trunk/doc/objectify.txt Sat Sep 9 07:18:49 2006 @@ -301,6 +301,18 @@ >>> print root["tag-name"][1].child.tag {ns}child +or for names that have a special meaning in lxml.objectify:: + + >>> root = objectify.XML("TEXT") + + >>> print root.text.text + Traceback (most recent call last): + ... + AttributeError: 'NoneType' object has no attribute 'text' + + >>> print root["text"].text + TEXT + ObjectPath ---------- From scoder at codespeak.net Sat Sep 9 07:19:44 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Sat, 9 Sep 2006 07:19:44 +0200 (CEST) Subject: [Lxml-checkins] r32094 - lxml/trunk/src/lxml Message-ID: <20060909051944.DF14310079@code0.codespeak.net> Author: scoder Date: Sat Sep 9 07:19:40 2006 New Revision: 32094 Modified: lxml/trunk/src/lxml/objectify.pyx Log: typo Modified: lxml/trunk/src/lxml/objectify.pyx ============================================================================== --- lxml/trunk/src/lxml/objectify.pyx (original) +++ lxml/trunk/src/lxml/objectify.pyx Sat Sep 9 07:19:40 2006 @@ -1008,7 +1008,7 @@ return ObjectifiedElement # default to string element class if type attribute is not exploitable - return _StringElement + return StringElement ################################################################################ From scoder at codespeak.net Sat Sep 9 07:20:54 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Sat, 9 Sep 2006 07:20:54 +0200 (CEST) Subject: [Lxml-checkins] r32095 - lxml/trunk/src/lxml Message-ID: <20060909052054.7CD1C10079@code0.codespeak.net> Author: scoder Date: Sat Sep 9 07:20:49 2006 New Revision: 32095 Modified: lxml/trunk/src/lxml/apihelpers.pxi lxml/trunk/src/lxml/docloader.pxi lxml/trunk/src/lxml/etree.pyx lxml/trunk/src/lxml/iterparse.pxi lxml/trunk/src/lxml/parser.pxi lxml/trunk/src/lxml/python.pxd lxml/trunk/src/lxml/relaxng.pxi lxml/trunk/src/lxml/serializer.pxi lxml/trunk/src/lxml/xmlschema.pxi lxml/trunk/src/lxml/xslt.pxi Log: fix handling of 8-bit encoded filenames Modified: lxml/trunk/src/lxml/apihelpers.pxi ============================================================================== --- lxml/trunk/src/lxml/apihelpers.pxi (original) +++ lxml/trunk/src/lxml/apihelpers.pxi Sat Sep 9 07:20:49 2006 @@ -501,6 +501,46 @@ else: raise TypeError, "Argument must be string or unicode." +cdef object _encodeFilename(object filename): + if filename is None: + return None + elif python.PyString_Check(filename): + return filename + elif python.PyUnicode_Check(filename): + return python.PyUnicode_AsEncodedString( + filename, _C_FILENAME_ENCODING, NULL) + else: + raise TypeError, "Argument must be string or unicode." + +cdef object _encodeFilenameUTF8(object filename): + """Recode filename as UTF-8. Tries ASCII, local filesystem encoding and + UTF-8 as source encoding. + """ + cdef char* c_filename + if filename is None: + return None + elif python.PyString_Check(filename): + c_filename = _cstr(filename) + if not isutf8(c_filename): + # plain ASCII! + return filename + try: + # try to decode with default encoding + filename = python.PyUnicode_Decode( + c_filename, python.PyString_GET_SIZE(filename), + _C_FILENAME_ENCODING, NULL) + except UnicodeDecodeError, decode_exc: + try: + # try if it's UTF-8 + filename = python.PyUnicode_DecodeUTF8( + c_filename, python.PyString_GET_SIZE(filename), NULL) + except UnicodeDecodeError: + raise decode_exc # otherwise re-raise original exception + if python.PyUnicode_Check(filename): + return python.PyUnicode_AsUTF8String(filename) + else: + raise TypeError, "Argument must be string or unicode." + cdef _getNsTag(tag): """Given a tag, find namespace URI and tag name. Return None for NS uri if no namespace URI available. Modified: lxml/trunk/src/lxml/docloader.pxi ============================================================================== --- lxml/trunk/src/lxml/docloader.pxi (original) +++ lxml/trunk/src/lxml/docloader.pxi Sat Sep 9 07:20:49 2006 @@ -8,7 +8,7 @@ cdef class _InputDocument: cdef _InputDocumentDataType _type - cdef object _data_utf + cdef object _data_bytes cdef object _file cdef class Resolver: @@ -28,7 +28,7 @@ cdef _InputDocument doc_ref doc_ref = _InputDocument() doc_ref._type = PARSER_DATA_STRING - doc_ref._data_utf = _utf8(string) + doc_ref._data_bytes = _utf8(string) return doc_ref def resolve_filename(self, filename, context): @@ -36,7 +36,7 @@ cdef _InputDocument doc_ref doc_ref = _ParserInput() doc_ref._type = PARSER_DATA_FILENAME - doc_ref._data_utf = _utf8(filename) + doc_ref._data_bytes = _encodeFilename(filename) return doc_ref def resolve_file(self, f, context): Modified: lxml/trunk/src/lxml/etree.pyx ============================================================================== --- lxml/trunk/src/lxml/etree.pyx (original) +++ lxml/trunk/src/lxml/etree.pyx Sat Sep 9 07:20:49 2006 @@ -68,6 +68,16 @@ # initialize parser (and threading) xmlparser.xmlInitParser() +# filename encoding +cdef object _FILENAME_ENCODING +_FILENAME_ENCODING = sys.getfilesystemencoding() +if _FILENAME_ENCODING is None: + _FILENAME_ENCODING = sys.getdefaultencoding() +if _FILENAME_ENCODING is None: + _FILENAME_ENCODING = 'ascii' +cdef char* _C_FILENAME_ENCODING +_C_FILENAME_ENCODING = _cstr(_FILENAME_ENCODING) + # Error superclass for ElementTree compatibility class Error(Exception): Modified: lxml/trunk/src/lxml/iterparse.pxi ============================================================================== --- lxml/trunk/src/lxml/iterparse.pxi (original) +++ lxml/trunk/src/lxml/iterparse.pxi Sat Sep 9 07:20:49 2006 @@ -234,10 +234,12 @@ cdef char* c_filename cdef int parse_options if not hasattr(source, 'read'): - self._filename = source - source = open(source, 'rb') + self._filename = _encodeFilename(source) + source = open(self._filename, 'rb') else: self._filename = _getFilenameForFile(source) + if self._filename is not None: + self._filename = _encodeFilename(self._filename) if self._filename is not None: c_filename = self._filename else: @@ -301,11 +303,7 @@ break if error != 0: self._source = None - if self._filename is not None: - c_filename = self._filename - else: - c_filename = NULL - _raiseParseError(self._parser_ctxt, c_filename) + _raiseParseError(self._parser_ctxt, self._filename) if python.PyList_GET_SIZE(context._events) == 0: self.root = context._root raise StopIteration Modified: lxml/trunk/src/lxml/parser.pxi ============================================================================== --- lxml/trunk/src/lxml/parser.pxi (original) +++ lxml/trunk/src/lxml/parser.pxi Sat Sep 9 07:20:49 2006 @@ -289,12 +289,12 @@ c_input = NULL data = None if doc_ref._type == PARSER_DATA_STRING: - data = doc_ref._data_utf + data = doc_ref._data_bytes c_input = xmlparser.xmlNewStringInputStream( c_context, _cstr(data)) elif doc_ref._type == PARSER_DATA_FILENAME: c_input = xmlparser.xmlNewInputFromFile( - c_context, _cstr(doc_ref._data_utf)) + c_context, _cstr(doc_ref._data_bytes)) elif doc_ref._type == PARSER_DATA_FILE: file_context = _FileParserContext(doc_ref._file, context, url) c_input = file_context._createParserInput(c_context) @@ -451,7 +451,7 @@ python.PyEval_RestoreThread(state) recover = self._parse_options & xmlparser.XML_PARSE_RECOVER - return _handleParseResult(pctxt, result, NULL, recover) + return _handleParseResult(pctxt, result, None, recover) finally: self._error_log.disconnect() self._unlockParser() @@ -482,7 +482,7 @@ python.PyEval_RestoreThread(state) recover = self._parse_options & xmlparser.XML_PARSE_RECOVER - return _handleParseResult(pctxt, result, NULL, recover) + return _handleParseResult(pctxt, result, None, recover) finally: self._error_log.disconnect() self._unlockParser() @@ -521,9 +521,7 @@ cdef char* c_filename cdef int recover if not filename: - c_filename = NULL - else: - c_filename = filename + filename = None self._lockParser() self._error_log.connect() try: @@ -534,23 +532,22 @@ pctxt, self._parse_options, self._parser_type) recover = self._parse_options & xmlparser.XML_PARSE_RECOVER - return _handleParseResult(pctxt, result, c_filename, recover) + return _handleParseResult(pctxt, result, filename, recover) finally: self._error_log.disconnect() self._unlockParser() -cdef int _raiseParseError(xmlParserCtxt* ctxt, char* c_filename) except 0: - if c_filename is not NULL and \ +cdef int _raiseParseError(xmlParserCtxt* ctxt, filename) except 0: + if filename is not None and \ ctxt.lastError.domain == xmlerror.XML_FROM_IO: if ctxt.lastError.message is not NULL: - message = "Error reading file %s: %s" % ( - funicode(c_filename), - funicode(ctxt.lastError.message).strip()) + message = "Error reading file '%s': %s" % ( + filename, (ctxt.lastError.message).strip()) else: - message = "Error reading file %s" % funicode(c_filename) + message = "Error reading file '%s'" % filename raise IOError, message elif ctxt.lastError.message is not NULL: - message = funicode(ctxt.lastError.message).strip() + message = (ctxt.lastError.message).strip() if ctxt.lastError.line >= 0: message = "line %d: %s" % (ctxt.lastError.line, message) raise XMLSyntaxError, message @@ -558,7 +555,7 @@ raise XMLSyntaxError cdef xmlDoc* _handleParseResult(xmlParserCtxt* ctxt, xmlDoc* result, - char* c_filename, int recover) except NULL: + filename, int recover) except NULL: cdef _ResolverContext context if ctxt.myDoc is not NULL: if ctxt.myDoc != result: @@ -582,9 +579,9 @@ context._raise_if_stored() if result is NULL: - _raiseParseError(ctxt, c_filename) - elif result.URL is NULL and c_filename is not NULL: - result.URL = tree.xmlStrdup(c_filename) + _raiseParseError(ctxt, filename) + elif result.URL is NULL and filename is not None: + result.URL = tree.xmlStrdup(_cstr(filename)) return result ############################################################ @@ -669,7 +666,7 @@ pctxt, c_text, NULL, NULL, options) try: recover = options & xmlparser.XML_PARSE_RECOVER - c_doc = _handleParseResult(pctxt, c_doc, NULL, recover) + c_doc = _handleParseResult(pctxt, c_doc, None, recover) finally: xmlparser.xmlFreeParserCtxt(pctxt) return c_doc @@ -689,7 +686,11 @@ pctxt, c_filename, NULL, options) try: recover = options & xmlparser.XML_PARSE_RECOVER - c_doc = _handleParseResult(pctxt, c_doc, c_filename, recover) + if c_filename is NULL: + filename = None + else: + filename = c_filename + c_doc = _handleParseResult(pctxt, c_doc, filename, recover) finally: xmlparser.xmlFreeParserCtxt(pctxt) return c_doc @@ -782,7 +783,8 @@ if not filename: c_filename = NULL else: - c_filename = _cstr(filename) + filename_utf = _encodeFilenameUTF8(filename) + c_filename = _cstr(filename_utf) if python.PyUnicode_Check(text): return (<_BaseParser>parser)._parseUnicodeDoc(text, c_filename) else: @@ -790,14 +792,13 @@ c_len = python.PyString_GET_SIZE(text) return (<_BaseParser>parser)._parseDoc(c_text, c_len, c_filename) -cdef xmlDoc* _parseDocFromFile(filename, _BaseParser parser) except NULL: +cdef xmlDoc* _parseDocFromFile(filename8, _BaseParser parser) except NULL: if parser is None: parser = __GLOBAL_PARSER_CONTEXT.getDefaultParser() - return (<_BaseParser>parser)._parseDocFromFile(_cstr(filename)) + return (<_BaseParser>parser)._parseDocFromFile(_cstr(filename8)) cdef xmlDoc* _parseDocFromFilelike(source, filename, _BaseParser parser) except NULL: - cdef char* c_filename if parser is None: parser = __GLOBAL_PARSER_CONTEXT.getDefaultParser() return (<_BaseParser>parser)._parseDocFromFilelike(source, filename) @@ -862,17 +863,19 @@ if hasattr(source, 'getvalue') and hasattr(source, 'tell'): # StringIO - reading from start? if source.tell() == 0: - return _parseMemoryDocument(source.getvalue(), filename, parser) + return _parseMemoryDocument( + source.getvalue(), _encodeFilenameUTF8(filename), parser) # Support for file-like objects (urlgrabber.urlopen, ...) if hasattr(source, 'read'): - return _parseFilelikeDocument(source, filename, parser) + return _parseFilelikeDocument( + source, _encodeFilenameUTF8(filename), parser) # Otherwise parse the file directly from the filesystem if filename is None: - filename = source + filename = _encodeFilename(source) # open filename - c_doc = _parseDocFromFile(_utf8(filename), parser) + c_doc = _parseDocFromFile(filename, parser) return _documentFactory(c_doc, parser) cdef _Document _parseMemoryDocument(text, url, _BaseParser parser): @@ -886,14 +889,14 @@ text = python.PyUnicode_AsUTF8String(text) elif not python.PyString_Check(text): raise ValueError, "can only parse strings" - if url is not None: - url = _utf8(url) + if python.PyUnicode_Check(url): + url = python.PyUnicode_AsUTF8String(url) c_doc = _parseDoc(text, url, parser) return _documentFactory(c_doc, parser) cdef _Document _parseFilelikeDocument(source, url, _BaseParser parser): cdef xmlDoc* c_doc - if url is not None: - url = _utf8(url) + if python.PyUnicode_Check(url): + url = python.PyUnicode_AsUTF8String(url) c_doc = _parseDocFromFilelike(source, url, parser) return _documentFactory(c_doc, parser) Modified: lxml/trunk/src/lxml/python.pxd ============================================================================== --- lxml/trunk/src/lxml/python.pxd (original) +++ lxml/trunk/src/lxml/python.pxd Sat Sep 9 07:20:49 2006 @@ -19,6 +19,8 @@ cdef object PyUnicode_FromEncodedObject(object s, char* encoding, char* errors) + cdef object PyUnicode_AsEncodedString(object u, char* encoding, + char* errors) cdef object PyUnicode_Decode(char* s, Py_ssize_t size, char* encoding, char* errors) cdef object PyUnicode_DecodeUTF8(char* s, Py_ssize_t size, char* errors) Modified: lxml/trunk/src/lxml/relaxng.pxi ============================================================================== --- lxml/trunk/src/lxml/relaxng.pxi (original) +++ lxml/trunk/src/lxml/relaxng.pxi Sat Sep 9 07:20:49 2006 @@ -44,6 +44,8 @@ if filename is None: # XXX assume a string object filename = file + else: + filename = _encodeFilename(filename) parser_ctxt = relaxng.xmlRelaxNGNewParserCtxt(filename) else: raise RelaxNGParseError, "No tree or file given" Modified: lxml/trunk/src/lxml/serializer.pxi ============================================================================== --- lxml/trunk/src/lxml/serializer.pxi (original) +++ lxml/trunk/src/lxml/serializer.pxi Sat Sep 9 07:20:49 2006 @@ -163,9 +163,9 @@ "unknown encoding: '%s'", c_enc) if _isString(f): - filename = _utf8(f) + filename8 = _encodeFilename(f) c_buffer = tree.xmlOutputBufferCreateFilename( - _cstr(filename), enchandler, 0) + _cstr(filename8), enchandler, 0) state = python.PyEval_SaveThread() elif hasattr(f, 'write'): writer = _FilelikeWriter(f) @@ -196,8 +196,8 @@ c_doc = _fakeRootDoc(c_base_doc, element._c_node) try: if _isString(f): - filename = _utf8(f) - c_filename = _cstr(filename) + filename8 = _encodeFilename(f) + c_filename = _cstr(filename8) state = python.PyEval_SaveThread() bytes = c14n.xmlC14NDocSave(c_doc, NULL, 0, NULL, 1, c_filename, 0) python.PyEval_RestoreThread(state) Modified: lxml/trunk/src/lxml/xmlschema.pxi ============================================================================== --- lxml/trunk/src/lxml/xmlschema.pxi (original) +++ lxml/trunk/src/lxml/xmlschema.pxi Sat Sep 9 07:20:49 2006 @@ -50,6 +50,8 @@ if filename is None: # XXX assume a string object filename = file + else: + filename = _encodeFilename(filename) parser_ctxt = xmlschema.xmlSchemaNewParserCtxt(filename) self._c_schema = xmlschema.xmlSchemaParse(parser_ctxt) xmlschema.xmlSchemaFreeParserCtxt(parser_ctxt) Modified: lxml/trunk/src/lxml/xslt.pxi ============================================================================== --- lxml/trunk/src/lxml/xslt.pxi (original) +++ lxml/trunk/src/lxml/xslt.pxi Sat Sep 9 07:20:49 2006 @@ -77,7 +77,7 @@ c_doc = _newDoc() if doc_ref._type == PARSER_DATA_STRING: c_doc = _internalParseDoc( - _cstr(doc_ref._data_utf), parse_options, + _cstr(doc_ref._data_bytes), parse_options, resolver_context) elif doc_ref._type == PARSER_DATA_FILE: data = doc_ref._file.read() @@ -86,7 +86,7 @@ resolver_context) elif doc_ref._type == PARSER_DATA_FILENAME: c_doc = _internalParseDocFromFile( - _cstr(doc_ref._data_utf), parse_options, + _cstr(doc_ref._data_bytes), parse_options, resolver_context) if c_doc is not NULL and c_doc.URL is NULL: c_doc.URL = tree.xmlStrdup(c_uri) From scoder at codespeak.net Sat Sep 9 07:25:01 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Sat, 9 Sep 2006 07:25:01 +0200 (CEST) Subject: [Lxml-checkins] r32096 - lxml/branch/lxml-1.0 Message-ID: <20060909052501.3178810079@code0.codespeak.net> Author: scoder Date: Sat Sep 9 07:24:59 2006 New Revision: 32096 Modified: lxml/branch/lxml-1.0/CHANGES.txt lxml/branch/lxml-1.0/version.txt Log: prepare release of 0.9.4 Modified: lxml/branch/lxml-1.0/CHANGES.txt ============================================================================== --- lxml/branch/lxml-1.0/CHANGES.txt (original) +++ lxml/branch/lxml-1.0/CHANGES.txt Sat Sep 9 07:24:59 2006 @@ -2,8 +2,8 @@ lxml changelog ============== -current -======= +1.0.4 (09.09.2006) +================== Features added -------------- Modified: lxml/branch/lxml-1.0/version.txt ============================================================================== --- lxml/branch/lxml-1.0/version.txt (original) +++ lxml/branch/lxml-1.0/version.txt Sat Sep 9 07:24:59 2006 @@ -1 +1 @@ -1.0.3 +1.0.4 From scoder at codespeak.net Sat Sep 9 07:49:02 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Sat, 9 Sep 2006 07:49:02 +0200 (CEST) Subject: [Lxml-checkins] r32097 - lxml/branch/lxml-1.0/doc Message-ID: <20060909054902.9B9CF10079@code0.codespeak.net> Author: scoder Date: Sat Sep 9 07:49:00 2006 New Revision: 32097 Modified: lxml/branch/lxml-1.0/doc/build.txt Log: merged in build doc update from trunk Modified: lxml/branch/lxml-1.0/doc/build.txt ============================================================================== --- lxml/branch/lxml-1.0/doc/build.txt (original) +++ lxml/branch/lxml-1.0/doc/build.txt Sat Sep 9 07:49:00 2006 @@ -187,7 +187,8 @@ * remove the unpacked directory * tar.gz the lxml SVN version and replace the orig.tar.gz that lies in the directory -* do ``dpkg -x lxml-...dsc`` and cd into the newly created directory +* check md5sum of created tar.gz file and place new sum and size in dsc file +* do ``dpkg-source -x lxml-...dsc`` and cd into the newly created directory * run ``dch -i`` and add a comment like "use trunk version", this will increase the debian version number so apt/dpkg don't get confused * run ``dpkg-buildpackage -rfakeroot -us -uc`` to build the package From scoder at codespeak.net Sat Sep 9 07:49:46 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Sat, 9 Sep 2006 07:49:46 +0200 (CEST) Subject: [Lxml-checkins] r32098 - lxml/branch/lxml-1.0/src/lxml/tests Message-ID: <20060909054946.6EADE10079@code0.codespeak.net> Author: scoder Date: Sat Sep 9 07:49:43 2006 New Revision: 32098 Added: lxml/branch/lxml-1.0/src/lxml/tests/test.dtd Modified: lxml/branch/lxml-1.0/src/lxml/tests/test.xml lxml/branch/lxml-1.0/src/lxml/tests/test_etree.py Log: merged in new test case for DTD parsing from trunk Added: lxml/branch/lxml-1.0/src/lxml/tests/test.dtd ============================================================================== --- (empty file) +++ lxml/branch/lxml-1.0/src/lxml/tests/test.dtd Sat Sep 9 07:49:43 2006 @@ -0,0 +1,9 @@ + + + + + Modified: lxml/branch/lxml-1.0/src/lxml/tests/test.xml ============================================================================== --- lxml/branch/lxml-1.0/src/lxml/tests/test.xml (original) +++ lxml/branch/lxml-1.0/src/lxml/tests/test.xml Sat Sep 9 07:49:43 2006 @@ -1 +1,2 @@ - \ No newline at end of file + + Modified: lxml/branch/lxml-1.0/src/lxml/tests/test_etree.py ============================================================================== --- lxml/branch/lxml-1.0/src/lxml/tests/test_etree.py (original) +++ lxml/branch/lxml-1.0/src/lxml/tests/test_etree.py Sat Sep 9 07:49:43 2006 @@ -48,6 +48,20 @@ self.assertEquals("TEST", root.get("attr")) self.assertRaises(TypeError, root.set, "newattr", 5) + def test_parse_file_dtd(self): + parse = self.etree.parse + parser = self.etree.XMLParser(attribute_defaults=True) + + tree = parse(fileInTestDir('test.xml'), parser) + root = tree.getroot() + + self.assertEquals( + "valueA", + root.get("default")) + self.assertEquals( + "valueB", + root[0].get("default")) + def test_parse_error(self): parse = self.etree.parse # from StringIO From scoder at codespeak.net Sat Sep 9 07:55:05 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Sat, 9 Sep 2006 07:55:05 +0200 (CEST) Subject: [Lxml-checkins] r32099 - lxml/branch/lxml-1.0/src/lxml/tests Message-ID: <20060909055505.14B7E10079@code0.codespeak.net> Author: scoder Date: Sat Sep 9 07:55:03 2006 New Revision: 32099 Modified: lxml/branch/lxml-1.0/src/lxml/tests/test_elementtree.py Log: merged in getiterator() test case from trunk Modified: lxml/branch/lxml-1.0/src/lxml/tests/test_elementtree.py ============================================================================== --- lxml/branch/lxml-1.0/src/lxml/tests/test_elementtree.py (original) +++ lxml/branch/lxml-1.0/src/lxml/tests/test_elementtree.py Sat Sep 9 07:55:03 2006 @@ -1245,6 +1245,26 @@ [d], list(d.getiterator())) + def test_getiterator_empty(self): + Element = self.etree.Element + SubElement = self.etree.SubElement + + a = Element('a') + b = SubElement(a, 'b') + c = SubElement(a, 'c') + d = SubElement(b, 'd') + e = SubElement(c, 'e') + + self.assertEquals( + [], + list(a.getiterator('none'))) + self.assertEquals( + [], + list(e.getiterator('none'))) + self.assertEquals( + [e], + list(e.getiterator())) + def test_getiterator_filter(self): Element = self.etree.Element SubElement = self.etree.SubElement From scoder at codespeak.net Sat Sep 9 07:59:01 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Sat, 9 Sep 2006 07:59:01 +0200 (CEST) Subject: [Lxml-checkins] r32100 - lxml/branch/lxml-1.0/doc Message-ID: <20060909055901.BAF0E10079@code0.codespeak.net> Author: scoder Date: Sat Sep 9 07:58:59 2006 New Revision: 32100 Modified: lxml/branch/lxml-1.0/doc/build.txt Log: merged in build doc update from trunk Modified: lxml/branch/lxml-1.0/doc/build.txt ============================================================================== --- lxml/branch/lxml-1.0/doc/build.txt (original) +++ lxml/branch/lxml-1.0/doc/build.txt Sat Sep 9 07:58:59 2006 @@ -53,8 +53,16 @@ make -If you then place lxml's ``src`` directory on your PYTHONPATH somehow, you can -import ``lxml.etree`` and play with it. +If you get errors about missing header files (e.g., ``libxml/xmlversion.h``) +then you need to add the location of that file to the include path like:: + + python setup.py build_ext -i -I /usr/include/libxml2 + +where the file is in ``/usr/include/libxml2/libxml/xmlversion.h`` + +To use lxml.etree in-place, you can place lxml's ``src`` directory on your +Python module search path (PYTHONPATH) and then import ``lxml.etree`` to play +with it. To recompile after changes, note that you may have to run ``make clean`` or delete the file ``src/lxml/etree.c``. Distutils do not automatically pick up From scoder at codespeak.net Sat Sep 9 08:17:46 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Sat, 9 Sep 2006 08:17:46 +0200 (CEST) Subject: [Lxml-checkins] r32101 - lxml/tag/lxml-1.0.4 Message-ID: <20060909061746.2D8F11007B@code0.codespeak.net> Author: scoder Date: Sat Sep 9 08:17:44 2006 New Revision: 32101 Added: lxml/tag/lxml-1.0.4/ - copied from r32100, lxml/branch/lxml-1.0/ Log: tag for 1.0.4 From scoder at codespeak.net Sat Sep 9 08:25:38 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Sat, 9 Sep 2006 08:25:38 +0200 (CEST) Subject: [Lxml-checkins] r32102 - lxml/branch/lxml-1.0/doc Message-ID: <20060909062538.781861007B@code0.codespeak.net> Author: scoder Date: Sat Sep 9 08:25:35 2006 New Revision: 32102 Modified: lxml/branch/lxml-1.0/doc/main.txt Log: updated main.txt (a bit too late, but, well...) Modified: lxml/branch/lxml-1.0/doc/main.txt ============================================================================== --- lxml/branch/lxml-1.0/doc/main.txt (original) +++ lxml/branch/lxml-1.0/doc/main.txt Sat Sep 9 08:25:35 2006 @@ -29,6 +29,8 @@ .. _`installation instructions`: installation.html +* `lxml 1.0.4`_, released 2006-09-09 (`changes for 1.0.4`_) + * `lxml 1.0.3`_, released 2006-08-08 (`changes for 1.0.3`_) * `lxml 1.0.2`_, released 2006-06-27 (`changes for 1.0.2`_) @@ -53,6 +55,7 @@ * `lxml 0.5`_, released 2005-04-08 +.. _`lxml 1.0.4`: lxml-1.0.4.tgz .. _`lxml 1.0.3`: lxml-1.0.3.tgz .. _`lxml 1.0.2`: lxml-1.0.2.tgz .. _`lxml 1.0.1`: lxml-1.0.1.tgz @@ -66,6 +69,7 @@ .. _`lxml 0.5.1`: lxml-0.5.1.tgz .. _`lxml 0.5`: lxml-0.5.tgz +.. _`CHANGES for 1.0.4`: changes-1.0.4.html .. _`CHANGES for 1.0.3`: changes-1.0.3.html .. _`CHANGES for 1.0.2`: changes-1.0.2.html .. _`CHANGES for 1.0.1`: changes-1.0.1.html From scoder at codespeak.net Sat Sep 9 08:32:43 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Sat, 9 Sep 2006 08:32:43 +0200 (CEST) Subject: [Lxml-checkins] r32103 - in lxml/trunk: . doc Message-ID: <20060909063243.B8AA91007B@code0.codespeak.net> Author: scoder Date: Sat Sep 9 08:32:40 2006 New Revision: 32103 Modified: lxml/trunk/CHANGES.txt lxml/trunk/doc/main.txt Log: merged in release doc updates from 1.0 branch Modified: lxml/trunk/CHANGES.txt ============================================================================== --- lxml/trunk/CHANGES.txt (original) +++ lxml/trunk/CHANGES.txt Sat Sep 9 08:32:40 2006 @@ -8,8 +8,6 @@ Features added -------------- -* List-like ``Element.extend()`` method - * Comments and processing instructions return '' and '' for repr() @@ -20,7 +18,7 @@ Bugs fixed ---------- -* Crash in tail handling in ``Element.replace()`` +* filenames with local 8-bit encoding were not supported * 1.1beta did not compile under Python 2.3 @@ -31,6 +29,20 @@ * objectify.ObjectPath.setattr() failed to accept Elements and Lists +1.0.4 (09.09.2006) +================== + +Features added +-------------- + +* List-like ``Element.extend()`` method + +Bugs fixed +---------- + +* Crash in tail handling in ``Element.replace()`` + + 1.1beta (2006-08-08) ==================== Modified: lxml/trunk/doc/main.txt ============================================================================== --- lxml/trunk/doc/main.txt (original) +++ lxml/trunk/doc/main.txt Sat Sep 9 08:32:40 2006 @@ -29,6 +29,8 @@ .. _`installation instructions`: installation.html +* `lxml 1.0.4`_, released 2006-09-09 (`changes for 1.0.4`_) + * `lxml 1.1beta`_, released 2006-08-08 (`changes for 1.1beta`_) * `lxml 1.0.3`_, released 2006-08-08 (`changes for 1.0.3`_) @@ -55,6 +57,7 @@ * `lxml 0.5`_, released 2005-04-08 +.. _`lxml 1.0.4`: lxml-1.0.4.tgz .. _`lxml 1.1beta`: lxml-1.1beta.tgz .. _`lxml 1.0.3`: lxml-1.0.3.tgz .. _`lxml 1.0.2`: lxml-1.0.2.tgz @@ -69,6 +72,7 @@ .. _`lxml 0.5.1`: lxml-0.5.1.tgz .. _`lxml 0.5`: lxml-0.5.tgz +.. _`CHANGES for 1.0.4`: changes-1.0.4.html .. _`CHANGES for 1.1beta`: changes-1.1beta.html .. _`CHANGES for 1.0.3`: changes-1.0.3.html .. _`CHANGES for 1.0.2`: changes-1.0.2.html From scoder at codespeak.net Sat Sep 9 20:49:06 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Sat, 9 Sep 2006 20:49:06 +0200 (CEST) Subject: [Lxml-checkins] r32115 - lxml/trunk/src/lxml Message-ID: <20060909184906.582CD10083@code0.codespeak.net> Author: scoder Date: Sat Sep 9 20:49:03 2006 New Revision: 32115 Modified: lxml/trunk/src/lxml/parser.pxi Log: fixed URL recoding in _parser_resolve_from_python(): no recoding for user originating URLs, UTF-8 for everything else Modified: lxml/trunk/src/lxml/parser.pxi ============================================================================== --- lxml/trunk/src/lxml/parser.pxi (original) +++ lxml/trunk/src/lxml/parser.pxi Sat Sep 9 20:49:03 2006 @@ -271,12 +271,16 @@ try: if c_url is NULL: url = None + elif c_context.myDoc is NULL or c_context.myDoc.URL is NULL: + # parsing a main document, so URL was passed verbatimly by user + url = c_url else: + # parsing a related document (DTD etc.) => UTF-8 encoded URL url = funicode(c_url) if c_pubid is NULL: pubid = None else: - pubid = funicode(c_pubid) + pubid = funicode(c_pubid) # always UTF-8 doc_ref = context._resolvers.resolve(url, pubid, context) if doc_ref is None: From scoder at codespeak.net Wed Sep 13 08:52:05 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Wed, 13 Sep 2006 08:52:05 +0200 (CEST) Subject: [Lxml-checkins] r32242 - lxml/trunk/src/lxml Message-ID: <20060913065205.775541007B@code0.codespeak.net> Author: scoder Date: Wed Sep 13 08:52:03 2006 New Revision: 32242 Modified: lxml/trunk/src/lxml/relaxng.pxi lxml/trunk/src/lxml/xmlschema.pxi Log: cleanup of filename encoding in RNG and XML Schema Modified: lxml/trunk/src/lxml/relaxng.pxi ============================================================================== --- lxml/trunk/src/lxml/relaxng.pxi (original) +++ lxml/trunk/src/lxml/relaxng.pxi Wed Sep 13 08:52:03 2006 @@ -44,9 +44,8 @@ if filename is None: # XXX assume a string object filename = file - else: - filename = _encodeFilename(filename) - parser_ctxt = relaxng.xmlRelaxNGNewParserCtxt(filename) + filename = _encodeFilename(filename) + parser_ctxt = relaxng.xmlRelaxNGNewParserCtxt(_cstr(filename)) else: raise RelaxNGParseError, "No tree or file given" Modified: lxml/trunk/src/lxml/xmlschema.pxi ============================================================================== --- lxml/trunk/src/lxml/xmlschema.pxi (original) +++ lxml/trunk/src/lxml/xmlschema.pxi Wed Sep 13 08:52:03 2006 @@ -50,9 +50,8 @@ if filename is None: # XXX assume a string object filename = file - else: - filename = _encodeFilename(filename) - parser_ctxt = xmlschema.xmlSchemaNewParserCtxt(filename) + filename = _encodeFilename(filename) + parser_ctxt = xmlschema.xmlSchemaNewParserCtxt(_cstr(filename)) self._c_schema = xmlschema.xmlSchemaParse(parser_ctxt) xmlschema.xmlSchemaFreeParserCtxt(parser_ctxt) else: From scoder at codespeak.net Wed Sep 13 09:32:07 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Wed, 13 Sep 2006 09:32:07 +0200 (CEST) Subject: [Lxml-checkins] r32243 - in lxml/trunk: . doc Message-ID: <20060913073207.8F5791007B@code0.codespeak.net> Author: scoder Date: Wed Sep 13 09:32:05 2006 New Revision: 32243 Modified: lxml/trunk/CHANGES.txt lxml/trunk/doc/main.txt lxml/trunk/version.txt Log: prepare release of 1.1 Modified: lxml/trunk/CHANGES.txt ============================================================================== --- lxml/trunk/CHANGES.txt (original) +++ lxml/trunk/CHANGES.txt Wed Sep 13 09:32:05 2006 @@ -2,8 +2,8 @@ lxml changelog ============== -current -======= +1.1 (2006-09-13) +================ Features added -------------- Modified: lxml/trunk/doc/main.txt ============================================================================== --- lxml/trunk/doc/main.txt (original) +++ lxml/trunk/doc/main.txt Wed Sep 13 09:32:05 2006 @@ -29,9 +29,9 @@ .. _`installation instructions`: installation.html -* `lxml 1.0.4`_, released 2006-09-09 (`changes for 1.0.4`_) +* `lxml 1.1`_, released 2006-09-13 (`changes for 1.1`_) -* `lxml 1.1beta`_, released 2006-08-08 (`changes for 1.1beta`_) +* `lxml 1.0.4`_, released 2006-09-09 (`changes for 1.0.4`_) * `lxml 1.0.3`_, released 2006-08-08 (`changes for 1.0.3`_) @@ -57,8 +57,8 @@ * `lxml 0.5`_, released 2005-04-08 +.. _`lxml 1.1`: lxml-1.1.tgz .. _`lxml 1.0.4`: lxml-1.0.4.tgz -.. _`lxml 1.1beta`: lxml-1.1beta.tgz .. _`lxml 1.0.3`: lxml-1.0.3.tgz .. _`lxml 1.0.2`: lxml-1.0.2.tgz .. _`lxml 1.0.1`: lxml-1.0.1.tgz @@ -72,8 +72,8 @@ .. _`lxml 0.5.1`: lxml-0.5.1.tgz .. _`lxml 0.5`: lxml-0.5.tgz +.. _`CHANGES for 1.1`: changes-1.1.html .. _`CHANGES for 1.0.4`: changes-1.0.4.html -.. _`CHANGES for 1.1beta`: changes-1.1beta.html .. _`CHANGES for 1.0.3`: changes-1.0.3.html .. _`CHANGES for 1.0.2`: changes-1.0.2.html .. _`CHANGES for 1.0.1`: changes-1.0.1.html Modified: lxml/trunk/version.txt ============================================================================== --- lxml/trunk/version.txt (original) +++ lxml/trunk/version.txt Wed Sep 13 09:32:05 2006 @@ -1 +1 @@ -1.1beta +1.1 From scoder at codespeak.net Wed Sep 13 18:17:39 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Wed, 13 Sep 2006 18:17:39 +0200 (CEST) Subject: [Lxml-checkins] r32272 - lxml/tag/lxml-1.1 Message-ID: <20060913161739.845D01007E@code0.codespeak.net> Author: scoder Date: Wed Sep 13 18:17:37 2006 New Revision: 32272 Added: lxml/tag/lxml-1.1/ - copied from r32271, lxml/trunk/ Log: tagged 1.1 From scoder at codespeak.net Wed Sep 13 18:18:24 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Wed, 13 Sep 2006 18:18:24 +0200 (CEST) Subject: [Lxml-checkins] r32273 - lxml/branch/lxml-1.1 Message-ID: <20060913161824.785121007E@code0.codespeak.net> Author: scoder Date: Wed Sep 13 18:18:23 2006 New Revision: 32273 Added: lxml/branch/lxml-1.1/ - copied from r32272, lxml/trunk/ Log: branch for 1.1 series From scoder at codespeak.net Wed Sep 13 18:34:12 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Wed, 13 Sep 2006 18:34:12 +0200 (CEST) Subject: [Lxml-checkins] r32279 - lxml/trunk Message-ID: <20060913163412.D557710079@code0.codespeak.net> Author: scoder Date: Wed Sep 13 18:34:11 2006 New Revision: 32279 Modified: lxml/trunk/CHANGES.txt Log: small doc fix Modified: lxml/trunk/CHANGES.txt ============================================================================== --- lxml/trunk/CHANGES.txt (original) +++ lxml/trunk/CHANGES.txt Wed Sep 13 18:34:11 2006 @@ -29,7 +29,7 @@ * objectify.ObjectPath.setattr() failed to accept Elements and Lists -1.0.4 (09.09.2006) +1.0.4 (2006-09-09) ================== Features added From scoder at codespeak.net Wed Sep 13 18:36:34 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Wed, 13 Sep 2006 18:36:34 +0200 (CEST) Subject: [Lxml-checkins] r32281 - lxml/branch/lxml-1.1 Message-ID: <20060913163634.9395010079@code0.codespeak.net> Author: scoder Date: Wed Sep 13 18:36:33 2006 New Revision: 32281 Modified: lxml/branch/lxml-1.1/CHANGES.txt Log: small doc fix Modified: lxml/branch/lxml-1.1/CHANGES.txt ============================================================================== --- lxml/branch/lxml-1.1/CHANGES.txt (original) +++ lxml/branch/lxml-1.1/CHANGES.txt Wed Sep 13 18:36:33 2006 @@ -29,7 +29,7 @@ * objectify.ObjectPath.setattr() failed to accept Elements and Lists -1.0.4 (09.09.2006) +1.0.4 (2006-09-09) ================== Features added From scoder at codespeak.net Wed Sep 13 18:37:00 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Wed, 13 Sep 2006 18:37:00 +0200 (CEST) Subject: [Lxml-checkins] r32282 - lxml/branch/lxml-1.0 Message-ID: <20060913163700.213711007E@code0.codespeak.net> Author: scoder Date: Wed Sep 13 18:36:57 2006 New Revision: 32282 Modified: lxml/branch/lxml-1.0/CHANGES.txt Log: small doc fix Modified: lxml/branch/lxml-1.0/CHANGES.txt ============================================================================== --- lxml/branch/lxml-1.0/CHANGES.txt (original) +++ lxml/branch/lxml-1.0/CHANGES.txt Wed Sep 13 18:36:57 2006 @@ -2,7 +2,7 @@ lxml changelog ============== -1.0.4 (09.09.2006) +1.0.4 (2006-09-09) ================== Features added From scoder at codespeak.net Thu Sep 14 21:51:25 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Thu, 14 Sep 2006 21:51:25 +0200 (CEST) Subject: [Lxml-checkins] r32336 - lxml/trunk Message-ID: <20060914195125.7084E1006F@code0.codespeak.net> Author: scoder Date: Thu Sep 14 21:51:23 2006 New Revision: 32336 Modified: lxml/trunk/CHANGES.txt Log: cleanup in changelog Modified: lxml/trunk/CHANGES.txt ============================================================================== --- lxml/trunk/CHANGES.txt (original) +++ lxml/trunk/CHANGES.txt Thu Sep 14 21:51:23 2006 @@ -15,69 +15,84 @@ schemes should be registered. Namespace lookup is no longer supported by default. -Bugs fixed ----------- +* Support for Python 2.5 beta -* filenames with local 8-bit encoding were not supported +* Unlock the GIL for deep copying documents and for XPath() -* 1.1beta did not compile under Python 2.3 +* New ``compact`` keyword argument for parsing read-only documents -* ignore unknown 'pyval' attribute values in objectify +* Support for parser options in iterparse() -* objectify.ObjectifiedElement.addattr() failed to accept Elements and Lists +* The ``namespace`` axis is supported in XPath and returns (prefix, URI) + tuples -* objectify.ObjectPath.setattr() failed to accept Elements and Lists +* The XPath expression "/" now returns an empty list instead of raising an + exception +* XML-Object API on top of lxml (lxml.objectify) -1.0.4 (2006-09-09) -================== +* Customizable Element class lookup: -Features added --------------- + * different pre-implemented lookup mechanisms -* List-like ``Element.extend()`` method + * support for externally provided lookup functions -Bugs fixed ----------- +* Support for processing instructions (ET-like, not compatible) -* Crash in tail handling in ``Element.replace()`` +* Public C-level API for independent extension modules +* Module level ``iterwalk()`` function as 'iterparse' for trees -1.1beta (2006-08-08) -==================== +* Module level ``iterparse()`` function similar to ElementTree (see + documentation for differences) -Features added --------------- +* Element.nsmap property returns a mapping of all namespace prefixes known at + the Element to their namespace URI -* Support for Python 2.5 beta +* Reentrant threading support in RelaxNG, XMLSchema and XSLT -* Unlock the GIL for deep copying documents and for XPath() +* Threading support in parsers and serializers: -* New ``compact`` keyword argument for parsing read-only documents + * All in-memory operations (tostring, parse(StringIO), etc.) free the GIL -* Support for parser options in iterparse() + * File operations (on file names) free the GIL -* The ``namespace`` axis is supported in XPath and returns (prefix, URI) - tuples + * Reading from file-like objects frees the GIL and reacquires it for reading -* The XPath expression "/" now returns an empty list instead of raising an - exception + * Serialisation to file-like objects is single-threaded (high lock overhead) -* XML-Object API on top of lxml (lxml.objectify) +* Element iteration over XPath axes: -* Customizable Element class lookup: + * Element.iterdescendants() iterates over the descendants of an element - * different pre-implemented lookup mechanisms + * Element.iterancestors() iterates over the ancestors of an element (from + parent to parent) - * support for externally provided lookup functions + * Element.itersiblings() iterates over either the following or preceding + siblings of an element -* Support for processing instructions (ET-like, not compatible) + * Element.iterchildren() iterates over the children of an element in either + direction -* Public C-level API for independent extension modules + * All iterators support the ``tag`` keyword argument to restrict the + generated elements + +* Element.getnext() and Element.getprevious() return the direct siblings of an + element Bugs fixed ---------- +* filenames with local 8-bit encoding were not supported + +* 1.1beta did not compile under Python 2.3 + +* ignore unknown 'pyval' attribute values in objectify + +* objectify.ObjectifiedElement.addattr() failed to accept Elements and Lists + +* objectify.ObjectPath.setattr() failed to accept Elements and Lists + * XPathSyntaxError now inherits from XPathError * Threading race conditions in RelaxNG and XMLSchema @@ -99,73 +114,38 @@ change from 1.0. -1.0.3 (2006-08-08) +1.0.4 (2006-09-09) ================== Features added -------------- -* Element.replace(old, new) method to replace a subelement by another one +* List-like ``Element.extend()`` method Bugs fixed ---------- -* Crash when mixing elements from XSLT results into other trees - -* Copying/deepcopying did not work for ElementTree objects - -* Setting an attribute to a non-string value did not raise an exception - -* Element.remove() deleted the tail text from the removed Element +* Crash in tail handling in ``Element.replace()`` -1.1alpha (2006-06-27) -===================== +1.0.3 (2006-08-08) +================== Features added -------------- -* Module level ``iterwalk()`` function as 'iterparse' for trees - -* Module level ``iterparse()`` function similar to ElementTree (see - documentation for differences) - -* Element.nsmap property returns a mapping of all namespace prefixes known at - the Element to their namespace URI - -* Reentrant threading support in RelaxNG, XMLSchema and XSLT - -* Threading support in parsers and serializers: - - * All in-memory operations (tostring, parse(StringIO), etc.) free the GIL - - * File operations (on file names) free the GIL - - * Reading from file-like objects frees the GIL and reacquires it for reading - - * Serialisation to file-like objects is single-threaded (high lock overhead) - -* Element iteration over XPath axes: - - * Element.iterdescendants() iterates over the descendants of an element - - * Element.iterancestors() iterates over the ancestors of an element (from - parent to parent) +* Element.replace(old, new) method to replace a subelement by another one - * Element.itersiblings() iterates over either the following or preceding - siblings of an element +Bugs fixed +---------- - * Element.iterchildren() iterates over the children of an element in either - direction +* Crash when mixing elements from XSLT results into other trees - * All iterators support the ``tag`` keyword argument to restrict the - generated elements +* Copying/deepcopying did not work for ElementTree objects -* Element.getnext() and Element.getprevious() return the direct siblings of an - element +* Setting an attribute to a non-string value did not raise an exception -Bugs fixed ----------- +* Element.remove() deleted the tail text from the removed Element 1.0.2 (2006-06-27) From scoder at codespeak.net Thu Sep 14 21:56:15 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Thu, 14 Sep 2006 21:56:15 +0200 (CEST) Subject: [Lxml-checkins] r32337 - lxml/trunk/src/lxml Message-ID: <20060914195615.B2DF11006F@code0.codespeak.net> Author: scoder Date: Thu Sep 14 21:56:12 2006 New Revision: 32337 Modified: lxml/trunk/src/lxml/objectify.pyx Log: various fixes in objecify, Element/DataElement factories, pytype for tree elements, configurable tree classes, ObjectifiedDataElement.__setText() Modified: lxml/trunk/src/lxml/objectify.pyx ============================================================================== --- lxml/trunk/src/lxml/objectify.pyx (original) +++ lxml/trunk/src/lxml/objectify.pyx Thu Sep 14 21:56:12 2006 @@ -67,6 +67,9 @@ PYTYPE_ATTRIBUTE = None +cdef object TREE_PYTYPE +TREE_PYTYPE = "TREE" + def setPytypeAttributeTag(attribute_tag=None): """Changes name and namespace of the XML attribute that holds Python type information. @@ -103,36 +106,6 @@ ################################################################################ -# Module level parser setup - -cdef object __DEFAULT_PARSER -__DEFAULT_PARSER = etree.XMLParser(remove_blank_text=True) -__DEFAULT_PARSER.setElementClassLookup( ObjectifyElementClassLookup() ) - -cdef object parser -parser = __DEFAULT_PARSER - -def setDefaultParser(new_parser = None): - """Replace the default parser used by objectify's Element() and - fromstring() functions. - - The new parser must be an etree.XMLParser. - - Call without arguments to reset to the original parser. - """ - global parser - if new_parser is None: - parser = __DEFAULT_PARSER - elif isinstance(new_parser, etree.XMLParser): - parser = new_parser - else: - raise TypeError, "parser must inherit from lxml.etree.XMLParser" - -cdef object _makeelement -_makeelement = parser.makeelement - - -################################################################################ # Element class for the main API cdef class ObjectifiedElement(ElementBase): @@ -499,6 +472,12 @@ def __str__(self): return textOf(self._c_node) or '' + def __setText(self, s): + """For use in subclasses only. Don't use unless you know what you are + doing. + """ + cetree.setNodeText(self._c_node, s) + cdef class NumberElement(ObjectifiedDataElement): cdef object _type def _setValueParser(self, function): @@ -760,6 +739,8 @@ def __init__(self, name, type_check, type_class): if not python._isString(name): raise TypeError, "Type name must be a string" + elif name == TREE_PYTYPE: + raise ValueError, "Invalid type name" if type_check is not None and not callable(type_check): raise TypeError, "Type check function must be callable (or None)" if not issubclass(type_class, ObjectifiedDataElement): @@ -900,11 +881,7 @@ cdef object _guessElementClass(tree.xmlNode* c_node): value = textOf(c_node) if value is None: - # if element is not a root node => default to string node - if c_node.parent is not NULL and tree._isElement(c_node.parent): - return StringElement - # default to ObjectifiedElement class - return ObjectifiedElement + return None if value == '': return StringElement errors = (ValueError, TypeError) @@ -914,8 +891,8 @@ return (pytype)._type except errors: pass + return None - return StringElement ################################################################################ # Recursive element dumping @@ -946,8 +923,10 @@ result = "%s%s = %r [%s]\n" % (indentstr, element.tag, value, type(element).__name__) xsi_ns = "{%s}" % XML_SCHEMA_INSTANCE_NS - pytype_ns = "{%s}" % _PYTYPE_NAMESPACE + pytype_ns = "{%s}" % PYTYPE_NAMESPACE for name, value in element.items(): + if name == PYTYPE_ATTRIBUTE and value == TREE_PYTYPE: + continue name = name.replace(xsi_ns, 'xsi:').replace(pytype_ns, 'py:') result = result + "%s * %s = %r\n" % (indentstr, name, value) @@ -966,14 +945,32 @@ cdef class ObjectifyElementClassLookup(ElementClassLookup): """Element class lookup method that uses the objectify classes. """ - def __init__(self): + cdef object empty_data_class + cdef object tree_class + def __init__(self, tree_class=None, empty_data_class=None): + """Lookup mechanism for objectify. + + The default Element classes can be replaced by passing subclasses of + ObjectifiedElement and ObjectifiedDataElement as keyword arguments. + 'tree_class' defines inner tree classes (defaults to + ObjectifiedElement), 'empty_data_class' defines the default class for + empty data elements (defauls to StringElement). + """ self._lookup_function = _lookupElementClass + if tree_class is None: + tree_class = ObjectifiedElement + self.tree_class = tree_class + if empty_data_class is None: + empty_data_class = StringElement + self.empty_data_class = empty_data_class cdef object _lookupElementClass(state, _Document doc, tree.xmlNode* c_node): + cdef ObjectifyElementClassLookup lookup cdef python.PyObject* dict_result + lookup = state # if element has children => no data class if cetree.findChildForwards(c_node, 0) is not NULL: - return ObjectifiedElement + return lookup.tree_class # if element is defined as xsi:nil, return NoneElement class if "true" == cetree.attributeValueFromNsName( @@ -984,6 +981,8 @@ value = cetree.attributeValueFromNsName( c_node, _PYTYPE_NAMESPACE, _PYTYPE_ATTRIBUTE_NAME) if value is not None: + if value == TREE_PYTYPE: + return lookup.tree_class dict_result = python.PyDict_GetItem(_PYTYPE_DICT, value) if dict_result is not NULL: return (dict_result)._type @@ -1003,12 +1002,11 @@ if el_class is not None: return el_class - # if element is root node => no data class + # if element is a root node => default to tree node if c_node.parent is NULL or not tree._isElement(c_node.parent): - return ObjectifiedElement + return lookup.tree_class - # default to string element class if type attribute is not exploitable - return StringElement + return lookup.empty_data_class ################################################################################ @@ -1374,7 +1372,7 @@ # check that old value is valid old_value = cetree.attributeValueFromNsName( c_node, _PYTYPE_NAMESPACE, _PYTYPE_ATTRIBUTE_NAME) - if old_value is not None: + if old_value is not None and old_value != TREE_PYTYPE: pytype = _PYTYPE_DICT.get(old_value) if pytype is not None: value = textOf(c_node) @@ -1429,6 +1427,36 @@ tree.END_FOR_EACH_ELEMENT_FROM(c_node) ################################################################################ +# Module level parser setup + +cdef object __DEFAULT_PARSER +__DEFAULT_PARSER = etree.XMLParser(remove_blank_text=True) +__DEFAULT_PARSER.setElementClassLookup( ObjectifyElementClassLookup() ) + +cdef object parser +parser = __DEFAULT_PARSER + +def setDefaultParser(new_parser = None): + """Replace the default parser used by objectify's Element() and + fromstring() functions. + + The new parser must be an etree.XMLParser. + + Call without arguments to reset to the original parser. + """ + global parser, _makeelement + if new_parser is None: + parser = __DEFAULT_PARSER + elif isinstance(new_parser, etree.XMLParser): + parser = new_parser + else: + raise TypeError, "parser must inherit from lxml.etree.XMLParser" + _makeelement = parser.makeelement + +cdef object _makeelement +_makeelement = parser.makeelement + +################################################################################ # Module level factory functions cdef object _fromstring @@ -1443,14 +1471,23 @@ XML = fromstring -def Element(*args, **kwargs): - """Objectify specific version of the lxml.etree Element() factory. +def Element(_tag, attrib=None, nsmap=None, _pytype=None, **_attributes): + """Objectify specific version of the lxml.etree Element() factory that + always creates a structural (tree) element. NOTE: requires parser based element class lookup activated in lxml.etree! """ - return _makeelement(*args, **kwargs) + if attrib is not None: + if python.PyDict_GetSize(_attributes): + attrib.update(_attributes) + _attributes = attrib + if _pytype is None: + _pytype = TREE_PYTYPE + _attributes[PYTYPE_ATTRIBUTE] = _pytype + return _makeelement(_tag, _attributes, nsmap) -def DataElement(_value, _attrib=None, _pytype=None, _xsi=None, **_attributes): +def DataElement(_value, attrib=None, nsmap=None, _pytype=None, _xsi=None, + **_attributes): """Create a new element with a Python value and XML attributes taken from keyword arguments or a dictionary passed as second argument. @@ -1459,10 +1496,10 @@ keyword arguments, they will be used instead. """ cdef _Element element - if _attrib is not None: + if attrib is not None: if python.PyDict_GetSize(_attributes): - _attrib.update(_attributes) - _attributes = _attrib + attrib.update(_attributes) + _attributes = attrib if _xsi is not None: python.PyDict_SetItem(_attributes, XML_SCHEMA_INSTANCE_TYPE_ATTR, _xsi) if _pytype is None: @@ -1495,6 +1532,6 @@ if _pytype is not None: python.PyDict_SetItem(_attributes, PYTYPE_ATTRIBUTE, _pytype) - element = _makeelement("value", _attributes) + element = _makeelement("value", _attributes, nsmap) cetree.setNodeText(element._c_node, strval) return element From scoder at codespeak.net Thu Sep 14 21:57:41 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Thu, 14 Sep 2006 21:57:41 +0200 (CEST) Subject: [Lxml-checkins] r32338 - lxml/branch/lxml-1.1/src/lxml Message-ID: <20060914195741.0A9681006F@code0.codespeak.net> Author: scoder Date: Thu Sep 14 21:57:39 2006 New Revision: 32338 Modified: lxml/branch/lxml-1.1/src/lxml/objectify.pyx Log: merged in objectify updates from trunk Modified: lxml/branch/lxml-1.1/src/lxml/objectify.pyx ============================================================================== --- lxml/branch/lxml-1.1/src/lxml/objectify.pyx (original) +++ lxml/branch/lxml-1.1/src/lxml/objectify.pyx Thu Sep 14 21:57:39 2006 @@ -67,6 +67,9 @@ PYTYPE_ATTRIBUTE = None +cdef object TREE_PYTYPE +TREE_PYTYPE = "TREE" + def setPytypeAttributeTag(attribute_tag=None): """Changes name and namespace of the XML attribute that holds Python type information. @@ -103,36 +106,6 @@ ################################################################################ -# Module level parser setup - -cdef object __DEFAULT_PARSER -__DEFAULT_PARSER = etree.XMLParser(remove_blank_text=True) -__DEFAULT_PARSER.setElementClassLookup( ObjectifyElementClassLookup() ) - -cdef object parser -parser = __DEFAULT_PARSER - -def setDefaultParser(new_parser = None): - """Replace the default parser used by objectify's Element() and - fromstring() functions. - - The new parser must be an etree.XMLParser. - - Call without arguments to reset to the original parser. - """ - global parser - if new_parser is None: - parser = __DEFAULT_PARSER - elif isinstance(new_parser, etree.XMLParser): - parser = new_parser - else: - raise TypeError, "parser must inherit from lxml.etree.XMLParser" - -cdef object _makeelement -_makeelement = parser.makeelement - - -################################################################################ # Element class for the main API cdef class ObjectifiedElement(ElementBase): @@ -499,6 +472,12 @@ def __str__(self): return textOf(self._c_node) or '' + def __setText(self, s): + """For use in subclasses only. Don't use unless you know what you are + doing. + """ + cetree.setNodeText(self._c_node, s) + cdef class NumberElement(ObjectifiedDataElement): cdef object _type def _setValueParser(self, function): @@ -760,6 +739,8 @@ def __init__(self, name, type_check, type_class): if not python._isString(name): raise TypeError, "Type name must be a string" + elif name == TREE_PYTYPE: + raise ValueError, "Invalid type name" if type_check is not None and not callable(type_check): raise TypeError, "Type check function must be callable (or None)" if not issubclass(type_class, ObjectifiedDataElement): @@ -900,11 +881,7 @@ cdef object _guessElementClass(tree.xmlNode* c_node): value = textOf(c_node) if value is None: - # if element is not a root node => default to string node - if c_node.parent is not NULL and tree._isElement(c_node.parent): - return StringElement - # default to ObjectifiedElement class - return ObjectifiedElement + return None if value == '': return StringElement errors = (ValueError, TypeError) @@ -914,8 +891,8 @@ return (pytype)._type except errors: pass + return None - return StringElement ################################################################################ # Recursive element dumping @@ -946,8 +923,10 @@ result = "%s%s = %r [%s]\n" % (indentstr, element.tag, value, type(element).__name__) xsi_ns = "{%s}" % XML_SCHEMA_INSTANCE_NS - pytype_ns = "{%s}" % _PYTYPE_NAMESPACE + pytype_ns = "{%s}" % PYTYPE_NAMESPACE for name, value in element.items(): + if name == PYTYPE_ATTRIBUTE and value == TREE_PYTYPE: + continue name = name.replace(xsi_ns, 'xsi:').replace(pytype_ns, 'py:') result = result + "%s * %s = %r\n" % (indentstr, name, value) @@ -966,14 +945,32 @@ cdef class ObjectifyElementClassLookup(ElementClassLookup): """Element class lookup method that uses the objectify classes. """ - def __init__(self): + cdef object empty_data_class + cdef object tree_class + def __init__(self, tree_class=None, empty_data_class=None): + """Lookup mechanism for objectify. + + The default Element classes can be replaced by passing subclasses of + ObjectifiedElement and ObjectifiedDataElement as keyword arguments. + 'tree_class' defines inner tree classes (defaults to + ObjectifiedElement), 'empty_data_class' defines the default class for + empty data elements (defauls to StringElement). + """ self._lookup_function = _lookupElementClass + if tree_class is None: + tree_class = ObjectifiedElement + self.tree_class = tree_class + if empty_data_class is None: + empty_data_class = StringElement + self.empty_data_class = empty_data_class cdef object _lookupElementClass(state, _Document doc, tree.xmlNode* c_node): + cdef ObjectifyElementClassLookup lookup cdef python.PyObject* dict_result + lookup = state # if element has children => no data class if cetree.findChildForwards(c_node, 0) is not NULL: - return ObjectifiedElement + return lookup.tree_class # if element is defined as xsi:nil, return NoneElement class if "true" == cetree.attributeValueFromNsName( @@ -984,6 +981,8 @@ value = cetree.attributeValueFromNsName( c_node, _PYTYPE_NAMESPACE, _PYTYPE_ATTRIBUTE_NAME) if value is not None: + if value == TREE_PYTYPE: + return lookup.tree_class dict_result = python.PyDict_GetItem(_PYTYPE_DICT, value) if dict_result is not NULL: return (dict_result)._type @@ -1003,12 +1002,11 @@ if el_class is not None: return el_class - # if element is root node => no data class + # if element is a root node => default to tree node if c_node.parent is NULL or not tree._isElement(c_node.parent): - return ObjectifiedElement + return lookup.tree_class - # default to string element class if type attribute is not exploitable - return StringElement + return lookup.empty_data_class ################################################################################ @@ -1374,7 +1372,7 @@ # check that old value is valid old_value = cetree.attributeValueFromNsName( c_node, _PYTYPE_NAMESPACE, _PYTYPE_ATTRIBUTE_NAME) - if old_value is not None: + if old_value is not None and old_value != TREE_PYTYPE: pytype = _PYTYPE_DICT.get(old_value) if pytype is not None: value = textOf(c_node) @@ -1429,6 +1427,36 @@ tree.END_FOR_EACH_ELEMENT_FROM(c_node) ################################################################################ +# Module level parser setup + +cdef object __DEFAULT_PARSER +__DEFAULT_PARSER = etree.XMLParser(remove_blank_text=True) +__DEFAULT_PARSER.setElementClassLookup( ObjectifyElementClassLookup() ) + +cdef object parser +parser = __DEFAULT_PARSER + +def setDefaultParser(new_parser = None): + """Replace the default parser used by objectify's Element() and + fromstring() functions. + + The new parser must be an etree.XMLParser. + + Call without arguments to reset to the original parser. + """ + global parser, _makeelement + if new_parser is None: + parser = __DEFAULT_PARSER + elif isinstance(new_parser, etree.XMLParser): + parser = new_parser + else: + raise TypeError, "parser must inherit from lxml.etree.XMLParser" + _makeelement = parser.makeelement + +cdef object _makeelement +_makeelement = parser.makeelement + +################################################################################ # Module level factory functions cdef object _fromstring @@ -1443,14 +1471,23 @@ XML = fromstring -def Element(*args, **kwargs): - """Objectify specific version of the lxml.etree Element() factory. +def Element(_tag, attrib=None, nsmap=None, _pytype=None, **_attributes): + """Objectify specific version of the lxml.etree Element() factory that + always creates a structural (tree) element. NOTE: requires parser based element class lookup activated in lxml.etree! """ - return _makeelement(*args, **kwargs) + if attrib is not None: + if python.PyDict_GetSize(_attributes): + attrib.update(_attributes) + _attributes = attrib + if _pytype is None: + _pytype = TREE_PYTYPE + _attributes[PYTYPE_ATTRIBUTE] = _pytype + return _makeelement(_tag, _attributes, nsmap) -def DataElement(_value, _attrib=None, _pytype=None, _xsi=None, **_attributes): +def DataElement(_value, attrib=None, nsmap=None, _pytype=None, _xsi=None, + **_attributes): """Create a new element with a Python value and XML attributes taken from keyword arguments or a dictionary passed as second argument. @@ -1459,10 +1496,10 @@ keyword arguments, they will be used instead. """ cdef _Element element - if _attrib is not None: + if attrib is not None: if python.PyDict_GetSize(_attributes): - _attrib.update(_attributes) - _attributes = _attrib + attrib.update(_attributes) + _attributes = attrib if _xsi is not None: python.PyDict_SetItem(_attributes, XML_SCHEMA_INSTANCE_TYPE_ATTR, _xsi) if _pytype is None: @@ -1495,6 +1532,6 @@ if _pytype is not None: python.PyDict_SetItem(_attributes, PYTYPE_ATTRIBUTE, _pytype) - element = _makeelement("value", _attributes) + element = _makeelement("value", _attributes, nsmap) cetree.setNodeText(element._c_node, strval) return element From scoder at codespeak.net Thu Sep 14 21:59:35 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Thu, 14 Sep 2006 21:59:35 +0200 (CEST) Subject: [Lxml-checkins] r32339 - lxml/pyrex/Pyrex/Compiler Message-ID: <20060914195935.59C571006F@code0.codespeak.net> Author: scoder Date: Thu Sep 14 21:59:33 2006 New Revision: 32339 Modified: lxml/pyrex/Pyrex/Compiler/Nodes.py Log: small fix to build under Windows Modified: lxml/pyrex/Pyrex/Compiler/Nodes.py ============================================================================== --- lxml/pyrex/Pyrex/Compiler/Nodes.py (original) +++ lxml/pyrex/Pyrex/Compiler/Nodes.py Thu Sep 14 21:59:33 2006 @@ -4149,7 +4149,7 @@ static int __Pyx_ImportModuleCApi(__Pyx_CApiTabEntry *t) { __Pyx_CApiTabEntry *api_t; while (t->s) { - if (*t->s == '\0') + if (*t->s == '\\0') continue; /* shortcut for erased string entries */ api_t = %(API_TAB)s; while ((api_t->s) && (strcmp(api_t->s, t->s) < 0)) From scoder at codespeak.net Thu Sep 14 21:59:59 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Thu, 14 Sep 2006 21:59:59 +0200 (CEST) Subject: [Lxml-checkins] r32340 - lxml/branch/lxml-1.1 Message-ID: <20060914195959.0A6E41006F@code0.codespeak.net> Author: scoder Date: Thu Sep 14 21:59:58 2006 New Revision: 32340 Modified: lxml/branch/lxml-1.1/CHANGES.txt Log: updated CHANGES.txt Modified: lxml/branch/lxml-1.1/CHANGES.txt ============================================================================== --- lxml/branch/lxml-1.1/CHANGES.txt (original) +++ lxml/branch/lxml-1.1/CHANGES.txt Thu Sep 14 21:59:58 2006 @@ -2,6 +2,29 @@ lxml changelog ============== +current +======= + +Features added +-------------- + +* Support custom elements for tree nodes in lxml.objectify + +Bugs fixed +---------- + +* Factories objectify.Element() and objectify.DataElement() were missing + ``attrib`` and ``nsmap`` keyword arguments + +* Changing the default parser in lxml.objectify did not update the factories + Element() and DataElement() + +* Let lxml.objectify.Element() always generate tree elements (not data + elements) + +* Build under Windows failed ('\0' bug in patched Pyrex version) + + 1.1 (2006-09-13) ================ From scoder at codespeak.net Thu Sep 14 22:00:56 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Thu, 14 Sep 2006 22:00:56 +0200 (CEST) Subject: [Lxml-checkins] r32341 - lxml/trunk Message-ID: <20060914200056.B55331006F@code0.codespeak.net> Author: scoder Date: Thu Sep 14 22:00:55 2006 New Revision: 32341 Modified: lxml/trunk/CHANGES.txt Log: updated CHANGES.txt Modified: lxml/trunk/CHANGES.txt ============================================================================== --- lxml/trunk/CHANGES.txt (original) +++ lxml/trunk/CHANGES.txt Thu Sep 14 22:00:55 2006 @@ -2,6 +2,29 @@ lxml changelog ============== +current +======= + +Features added +-------------- + +* Support custom elements for tree nodes in lxml.objectify + +Bugs fixed +---------- + +* Factories objectify.Element() and objectify.DataElement() were missing + ``attrib`` and ``nsmap`` keyword arguments + +* Changing the default parser in lxml.objectify did not update the factories + Element() and DataElement() + +* Let lxml.objectify.Element() always generate tree elements (not data + elements) + +* Build under Windows failed ('\0' bug in patched Pyrex version) + + 1.1 (2006-09-13) ================ From scoder at codespeak.net Thu Sep 14 22:39:48 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Thu, 14 Sep 2006 22:39:48 +0200 (CEST) Subject: [Lxml-checkins] r32342 - lxml/branch/lxml-1.1/doc Message-ID: <20060914203948.00B771006F@code0.codespeak.net> Author: scoder Date: Thu Sep 14 22:39:46 2006 New Revision: 32342 Modified: lxml/branch/lxml-1.1/doc/main.txt Log: small doc fix Modified: lxml/branch/lxml-1.1/doc/main.txt ============================================================================== --- lxml/branch/lxml-1.1/doc/main.txt (original) +++ lxml/branch/lxml-1.1/doc/main.txt Thu Sep 14 22:39:46 2006 @@ -138,7 +138,7 @@ .. _`SAX compliant API`: sax.html .. _`C-level API`: capi.html .. _`lxml.objectify`: objectify.html -.. _`objectify and etree`: FAQ.html##what-is-the-difference-between-lxml-etree-and-lxml-objectify +.. _`objectify and etree`: FAQ.html#what-is-the-difference-between-lxml-etree-and-lxml-objectify .. _XPath: http://www.w3.org/TR/xpath .. _`Relax NG`: http://www.relaxng.org/ From scoder at codespeak.net Thu Sep 14 22:40:53 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Thu, 14 Sep 2006 22:40:53 +0200 (CEST) Subject: [Lxml-checkins] r32343 - lxml/trunk/doc Message-ID: <20060914204053.33F4E1006F@code0.codespeak.net> Author: scoder Date: Thu Sep 14 22:40:52 2006 New Revision: 32343 Modified: lxml/trunk/doc/main.txt Log: small doc fix Modified: lxml/trunk/doc/main.txt ============================================================================== --- lxml/trunk/doc/main.txt (original) +++ lxml/trunk/doc/main.txt Thu Sep 14 22:40:52 2006 @@ -138,7 +138,7 @@ .. _`SAX compliant API`: sax.html .. _`C-level API`: capi.html .. _`lxml.objectify`: objectify.html -.. _`objectify and etree`: FAQ.html##what-is-the-difference-between-lxml-etree-and-lxml-objectify +.. _`objectify and etree`: FAQ.html#what-is-the-difference-between-lxml-etree-and-lxml-objectify .. _XPath: http://www.w3.org/TR/xpath .. _`Relax NG`: http://www.relaxng.org/ From scoder at codespeak.net Fri Sep 15 17:41:03 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Fri, 15 Sep 2006 17:41:03 +0200 (CEST) Subject: [Lxml-checkins] r32369 - lxml/trunk/src/lxml Message-ID: <20060915154103.4DD4910071@code0.codespeak.net> Author: scoder Date: Fri Sep 15 17:40:58 2006 New Revision: 32369 Modified: lxml/trunk/src/lxml/objectify.pyx Log: fixed wrong C function name Modified: lxml/trunk/src/lxml/objectify.pyx ============================================================================== --- lxml/trunk/src/lxml/objectify.pyx (original) +++ lxml/trunk/src/lxml/objectify.pyx Fri Sep 15 17:40:58 2006 @@ -1478,7 +1478,7 @@ NOTE: requires parser based element class lookup activated in lxml.etree! """ if attrib is not None: - if python.PyDict_GetSize(_attributes): + if python.PyDict_Size(_attributes): attrib.update(_attributes) _attributes = attrib if _pytype is None: @@ -1497,7 +1497,7 @@ """ cdef _Element element if attrib is not None: - if python.PyDict_GetSize(_attributes): + if python.PyDict_Size(_attributes): attrib.update(_attributes) _attributes = attrib if _xsi is not None: From scoder at codespeak.net Fri Sep 15 17:43:20 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Fri, 15 Sep 2006 17:43:20 +0200 (CEST) Subject: [Lxml-checkins] r32370 - lxml/branch/lxml-1.1/src/lxml Message-ID: <20060915154320.246D910071@code0.codespeak.net> Author: scoder Date: Fri Sep 15 17:43:17 2006 New Revision: 32370 Modified: lxml/branch/lxml-1.1/src/lxml/objectify.pyx Log: fixed wrong C function name Modified: lxml/branch/lxml-1.1/src/lxml/objectify.pyx ============================================================================== --- lxml/branch/lxml-1.1/src/lxml/objectify.pyx (original) +++ lxml/branch/lxml-1.1/src/lxml/objectify.pyx Fri Sep 15 17:43:17 2006 @@ -1478,7 +1478,7 @@ NOTE: requires parser based element class lookup activated in lxml.etree! """ if attrib is not None: - if python.PyDict_GetSize(_attributes): + if python.PyDict_Size(_attributes): attrib.update(_attributes) _attributes = attrib if _pytype is None: @@ -1497,7 +1497,7 @@ """ cdef _Element element if attrib is not None: - if python.PyDict_GetSize(_attributes): + if python.PyDict_Size(_attributes): attrib.update(_attributes) _attributes = attrib if _xsi is not None: From scoder at codespeak.net Fri Sep 15 19:09:47 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Fri, 15 Sep 2006 19:09:47 +0200 (CEST) Subject: [Lxml-checkins] r32372 - in lxml/trunk: . src/lxml Message-ID: <20060915170947.99C2010075@code0.codespeak.net> Author: scoder Date: Fri Sep 15 19:09:45 2006 New Revision: 32372 Modified: lxml/trunk/CHANGES.txt lxml/trunk/src/lxml/objectify.pyx Log: countchildren() method on ObjectifiedElement Modified: lxml/trunk/CHANGES.txt ============================================================================== --- lxml/trunk/CHANGES.txt (original) +++ lxml/trunk/CHANGES.txt Fri Sep 15 19:09:45 2006 @@ -8,6 +8,8 @@ Features added -------------- +* countchildren() method on objectify.ObjectifiedElement + * Support custom elements for tree nodes in lxml.objectify Bugs fixed Modified: lxml/trunk/src/lxml/objectify.pyx ============================================================================== --- lxml/trunk/src/lxml/objectify.pyx (original) +++ lxml/trunk/src/lxml/objectify.pyx Fri Sep 15 19:09:45 2006 @@ -184,6 +184,21 @@ c_node = c_node.prev return count + def countchildren(self): + """Return the number of children of this element, regardless of their + name. + """ + # copied from etree + cdef Py_ssize_t c + cdef xmlNode* c_node + c = 0 + c_node = self._c_node.children + while c_node is not NULL: + if _isElement(c_node): + c = c + 1 + c_node = c_node.next + return c + def __getattr__(self, tag): """Return the (first) child with the given tag name. If no namespace is provided, the child will be looked up in the same one as self. From scoder at codespeak.net Fri Sep 15 19:10:16 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Fri, 15 Sep 2006 19:10:16 +0200 (CEST) Subject: [Lxml-checkins] r32373 - in lxml/branch/lxml-1.1: . src/lxml Message-ID: <20060915171016.ED84110075@code0.codespeak.net> Author: scoder Date: Fri Sep 15 19:10:15 2006 New Revision: 32373 Modified: lxml/branch/lxml-1.1/CHANGES.txt lxml/branch/lxml-1.1/src/lxml/objectify.pyx Log: countchildren() method on ObjectifiedElement Modified: lxml/branch/lxml-1.1/CHANGES.txt ============================================================================== --- lxml/branch/lxml-1.1/CHANGES.txt (original) +++ lxml/branch/lxml-1.1/CHANGES.txt Fri Sep 15 19:10:15 2006 @@ -8,6 +8,8 @@ Features added -------------- +* countchildren() method on objectify.ObjectifiedElement + * Support custom elements for tree nodes in lxml.objectify Bugs fixed Modified: lxml/branch/lxml-1.1/src/lxml/objectify.pyx ============================================================================== --- lxml/branch/lxml-1.1/src/lxml/objectify.pyx (original) +++ lxml/branch/lxml-1.1/src/lxml/objectify.pyx Fri Sep 15 19:10:15 2006 @@ -184,6 +184,21 @@ c_node = c_node.prev return count + def countchildren(self): + """Return the number of children of this element, regardless of their + name. + """ + # copied from etree + cdef Py_ssize_t c + cdef xmlNode* c_node + c = 0 + c_node = self._c_node.children + while c_node is not NULL: + if _isElement(c_node): + c = c + 1 + c_node = c_node.next + return c + def __getattr__(self, tag): """Return the (first) child with the given tag name. If no namespace is provided, the child will be looked up in the same one as self. From scoder at codespeak.net Fri Sep 15 19:28:15 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Fri, 15 Sep 2006 19:28:15 +0200 (CEST) Subject: [Lxml-checkins] r32374 - lxml/branch/lxml-1.1 Message-ID: <20060915172815.933E51006F@code0.codespeak.net> Author: scoder Date: Fri Sep 15 19:28:10 2006 New Revision: 32374 Modified: lxml/branch/lxml-1.1/version.txt Log: version -> 1.1.1 Modified: lxml/branch/lxml-1.1/version.txt ============================================================================== --- lxml/branch/lxml-1.1/version.txt (original) +++ lxml/branch/lxml-1.1/version.txt Fri Sep 15 19:28:10 2006 @@ -1 +1 @@ -1.1 +1.1.1 From scoder at codespeak.net Fri Sep 15 19:44:14 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Fri, 15 Sep 2006 19:44:14 +0200 (CEST) Subject: [Lxml-checkins] r32375 - in lxml/trunk/src/lxml: . tests Message-ID: <20060915174414.CB7281006F@code0.codespeak.net> Author: scoder Date: Fri Sep 15 19:44:12 2006 New Revision: 32375 Modified: lxml/trunk/src/lxml/objectify.pyx lxml/trunk/src/lxml/tests/test_objectify.py Log: testcase and fix for OE.countchildren() Modified: lxml/trunk/src/lxml/objectify.pyx ============================================================================== --- lxml/trunk/src/lxml/objectify.pyx (original) +++ lxml/trunk/src/lxml/objectify.pyx Fri Sep 15 19:44:12 2006 @@ -190,11 +190,11 @@ """ # copied from etree cdef Py_ssize_t c - cdef xmlNode* c_node + cdef tree.xmlNode* c_node c = 0 c_node = self._c_node.children while c_node is not NULL: - if _isElement(c_node): + if tree._isElement(c_node): c = c + 1 c_node = c_node.next return c Modified: lxml/trunk/src/lxml/tests/test_objectify.py ============================================================================== --- lxml/trunk/src/lxml/tests/test_objectify.py (original) +++ lxml/trunk/src/lxml/tests/test_objectify.py Fri Sep 15 19:44:12 2006 @@ -61,6 +61,11 @@ root = self.XML(xml_str) self.assertEquals("0", root.c1.c2.text) + def test_countchildren(self): + root = self.XML(xml_str) + self.assertEquals(1, root.countchildren()) + self.assertEquals(5, root.c1.countchildren()) + def test_child_getattr(self): root = self.XML(xml_str) self.assertEquals("0", getattr(root.c1, "{objectified}c2").text) From scoder at codespeak.net Fri Sep 15 19:44:42 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Fri, 15 Sep 2006 19:44:42 +0200 (CEST) Subject: [Lxml-checkins] r32376 - in lxml/branch/lxml-1.1/src/lxml: . tests Message-ID: <20060915174442.64B7B1006F@code0.codespeak.net> Author: scoder Date: Fri Sep 15 19:44:40 2006 New Revision: 32376 Modified: lxml/branch/lxml-1.1/src/lxml/objectify.pyx lxml/branch/lxml-1.1/src/lxml/tests/test_objectify.py Log: testcase and fix for OE.countchildren() Modified: lxml/branch/lxml-1.1/src/lxml/objectify.pyx ============================================================================== --- lxml/branch/lxml-1.1/src/lxml/objectify.pyx (original) +++ lxml/branch/lxml-1.1/src/lxml/objectify.pyx Fri Sep 15 19:44:40 2006 @@ -190,11 +190,11 @@ """ # copied from etree cdef Py_ssize_t c - cdef xmlNode* c_node + cdef tree.xmlNode* c_node c = 0 c_node = self._c_node.children while c_node is not NULL: - if _isElement(c_node): + if tree._isElement(c_node): c = c + 1 c_node = c_node.next return c Modified: lxml/branch/lxml-1.1/src/lxml/tests/test_objectify.py ============================================================================== --- lxml/branch/lxml-1.1/src/lxml/tests/test_objectify.py (original) +++ lxml/branch/lxml-1.1/src/lxml/tests/test_objectify.py Fri Sep 15 19:44:40 2006 @@ -61,6 +61,11 @@ root = self.XML(xml_str) self.assertEquals("0", root.c1.c2.text) + def test_countchildren(self): + root = self.XML(xml_str) + self.assertEquals(1, root.countchildren()) + self.assertEquals(5, root.c1.countchildren()) + def test_child_getattr(self): root = self.XML(xml_str) self.assertEquals("0", getattr(root.c1, "{objectified}c2").text) From scoder at codespeak.net Fri Sep 15 21:37:51 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Fri, 15 Sep 2006 21:37:51 +0200 (CEST) Subject: [Lxml-checkins] r32377 - in lxml/trunk: . doc src/lxml src/lxml/tests Message-ID: <20060915193751.9982B10071@code0.codespeak.net> Author: scoder Date: Fri Sep 15 21:37:48 2006 New Revision: 32377 Modified: lxml/trunk/CHANGES.txt lxml/trunk/doc/resolvers.txt lxml/trunk/src/lxml/etree.pyx lxml/trunk/src/lxml/tests/test_xslt.py lxml/trunk/src/lxml/xmlerror.pxi lxml/trunk/src/lxml/xslt.pxi Log: fixed local error log for XSLT messages Modified: lxml/trunk/CHANGES.txt ============================================================================== --- lxml/trunk/CHANGES.txt (original) +++ lxml/trunk/CHANGES.txt Fri Sep 15 21:37:48 2006 @@ -15,6 +15,8 @@ Bugs fixed ---------- +* Error messages from XSLT did not reach ``XSLT.error_log`` + * Factories objectify.Element() and objectify.DataElement() were missing ``attrib`` and ``nsmap`` keyword arguments Modified: lxml/trunk/doc/resolvers.txt ============================================================================== --- lxml/trunk/doc/resolvers.txt (original) +++ lxml/trunk/doc/resolvers.txt Fri Sep 15 21:37:48 2006 @@ -196,7 +196,7 @@ >>> result = transform(normal_doc) Traceback (most recent call last): [...] - XSLTApplyError: runtime error, element 'value-of', line 6 + XSLTApplyError: xsltLoadDocument: read rights for hoi:test denied There are a few things to keep in mind: Modified: lxml/trunk/src/lxml/etree.pyx ============================================================================== --- lxml/trunk/src/lxml/etree.pyx (original) +++ lxml/trunk/src/lxml/etree.pyx Fri Sep 15 21:37:48 2006 @@ -1790,10 +1790,7 @@ include "xmlid.pxi" # XMLID and IDDict include "extensions.pxi" # XPath/XSLT extension functions include "xpath.pxi" # XPath evaluation - -# XSL transformations -# comment out to compile without libxslt -include "xslt.pxi" +include "xslt.pxi" # XSL transformations ################################################################################ Modified: lxml/trunk/src/lxml/tests/test_xslt.py ============================================================================== --- lxml/trunk/src/lxml/tests/test_xslt.py (original) +++ lxml/trunk/src/lxml/tests/test_xslt.py Fri Sep 15 21:37:48 2006 @@ -366,6 +366,25 @@ self.assertEqual('', style.tostring(result)) self.assertEqual('', str(result)) + def test_xslt_message(self): + xml = '' + xslt = ''' + + + TEST TEST TEST + + + ''' + + source = self.parse(xml) + styledoc = self.parse(xslt) + style = etree.XSLT(styledoc) + result = style.apply(source) + self.assertEqual('', style.tostring(result)) + self.assertEqual('', str(result)) + self.assert_("TEST TEST TEST" in [entry.message + for entry in style.error_log]) + def test_xslt_shortcut(self): tree = self.parse('BC') style = self.parse('''\ Modified: lxml/trunk/src/lxml/xmlerror.pxi ============================================================================== --- lxml/trunk/src/lxml/xmlerror.pxi (original) +++ lxml/trunk/src/lxml/xmlerror.pxi Fri Sep 15 21:37:48 2006 @@ -9,17 +9,24 @@ Note that this log is already bounded to a fixed size.""" __GLOBAL_ERROR_LOG.clear() -# setup functions +# dummy function: no debug output at all +cdef void _nullGenericErrorFunc(void* ctxt, char* msg, ...): + pass + +# setup for global log: cdef void _initThreadLogging(): - "Setup logging for the current thread. Called from etree.initThread()." - # switch on line number reporting - _logLibxmlErrors() - try: - _logLibxsltErrors() - except NameError: - # compiled without libxslt - pass + # disable generic error lines from libxml2 + xmlerror.xmlThrDefSetGenericErrorFunc(NULL, _nullGenericErrorFunc) + xmlerror.xmlSetGenericErrorFunc(NULL, _nullGenericErrorFunc) + + # divert error messages to the global error log + xmlerror.xmlThrDefSetStructuredErrorFunc(NULL, _receiveError) + connectErrorLog(NULL) + +cdef void connectErrorLog(void* log): + xmlerror.xmlSetStructuredErrorFunc(log, _receiveError) + xslt.xsltSetGenericErrorFunc(log, _receiveXSLTError) # Logging classes @@ -194,10 +201,10 @@ cdef void connect(self): del self._entries[:] - xmlerror.xmlSetStructuredErrorFunc(self, _receiveError) + connectErrorLog(self) cdef void disconnect(self): - xmlerror.xmlSetStructuredErrorFunc(NULL, _receiveError) + connectErrorLog(NULL) def clear(self): del self._entries[:] @@ -326,8 +333,9 @@ cdef char* c_message cdef char* c_element cdef int i, text_size, element_size - if __DEBUG == 0 or msg is NULL or cstd.strlen(msg) < 10: + if __DEBUG == 0 or msg is NULL or cstd.strcmp(msg, '\n') == 0: return + cstd.va_start(args, msg) if msg[0] == c'%' and msg[1] == c's': c_text = cstd.va_charptr(args) @@ -374,17 +382,6 @@ python.PyMem_Free(c_error.message) python.PyGILState_Release(gil_state) -# dummy function: no debug output at all -cdef void _nullGenericErrorFunc(void* ctxt, char* msg, ...): - pass - -# setup for global log: -cdef void _logLibxmlErrors(): - xmlerror.xmlThrDefSetGenericErrorFunc(NULL, _nullGenericErrorFunc) - xmlerror.xmlSetGenericErrorFunc(NULL, _nullGenericErrorFunc) - - xmlerror.xmlThrDefSetStructuredErrorFunc(NULL, _receiveError) - xmlerror.xmlSetStructuredErrorFunc(NULL, _receiveError) ################################################################################ ## CONSTANTS FROM "xmlerror.h" (or rather libxml-xmlerror.html) Modified: lxml/trunk/src/lxml/xslt.pxi ============================================================================== --- lxml/trunk/src/lxml/xslt.pxi (original) +++ lxml/trunk/src/lxml/xslt.pxi Fri Sep 15 21:37:48 2006 @@ -21,9 +21,6 @@ LIBXSLT_COMPILED_VERSION = __unpackIntVersion(xslt.LIBXSLT_VERSION) LIBXSLT_VERSION = __unpackIntVersion(xslt.xsltLibxsltVersion) -cdef void _logLibxsltErrors(): - xslt.xsltSetGenericErrorFunc(NULL, _receiveXSLTError) - ################################################################################ # Where do we store what? From scoder at codespeak.net Fri Sep 15 21:40:11 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Fri, 15 Sep 2006 21:40:11 +0200 (CEST) Subject: [Lxml-checkins] r32378 - in lxml/branch/lxml-1.1: . doc src/lxml src/lxml/tests Message-ID: <20060915194011.139F710071@code0.codespeak.net> Author: scoder Date: Fri Sep 15 21:40:08 2006 New Revision: 32378 Modified: lxml/branch/lxml-1.1/CHANGES.txt lxml/branch/lxml-1.1/doc/resolvers.txt lxml/branch/lxml-1.1/src/lxml/etree.pyx lxml/branch/lxml-1.1/src/lxml/tests/test_xslt.py lxml/branch/lxml-1.1/src/lxml/xmlerror.pxi lxml/branch/lxml-1.1/src/lxml/xslt.pxi Log: fixed local error log for XSLT messages Modified: lxml/branch/lxml-1.1/CHANGES.txt ============================================================================== --- lxml/branch/lxml-1.1/CHANGES.txt (original) +++ lxml/branch/lxml-1.1/CHANGES.txt Fri Sep 15 21:40:08 2006 @@ -15,6 +15,8 @@ Bugs fixed ---------- +* Error messages from XSLT did not reach ``XSLT.error_log`` + * Factories objectify.Element() and objectify.DataElement() were missing ``attrib`` and ``nsmap`` keyword arguments Modified: lxml/branch/lxml-1.1/doc/resolvers.txt ============================================================================== --- lxml/branch/lxml-1.1/doc/resolvers.txt (original) +++ lxml/branch/lxml-1.1/doc/resolvers.txt Fri Sep 15 21:40:08 2006 @@ -196,7 +196,7 @@ >>> result = transform(normal_doc) Traceback (most recent call last): [...] - XSLTApplyError: runtime error, element 'value-of', line 6 + XSLTApplyError: xsltLoadDocument: read rights for hoi:test denied There are a few things to keep in mind: Modified: lxml/branch/lxml-1.1/src/lxml/etree.pyx ============================================================================== --- lxml/branch/lxml-1.1/src/lxml/etree.pyx (original) +++ lxml/branch/lxml-1.1/src/lxml/etree.pyx Fri Sep 15 21:40:08 2006 @@ -1790,10 +1790,7 @@ include "xmlid.pxi" # XMLID and IDDict include "extensions.pxi" # XPath/XSLT extension functions include "xpath.pxi" # XPath evaluation - -# XSL transformations -# comment out to compile without libxslt -include "xslt.pxi" +include "xslt.pxi" # XSL transformations ################################################################################ Modified: lxml/branch/lxml-1.1/src/lxml/tests/test_xslt.py ============================================================================== --- lxml/branch/lxml-1.1/src/lxml/tests/test_xslt.py (original) +++ lxml/branch/lxml-1.1/src/lxml/tests/test_xslt.py Fri Sep 15 21:40:08 2006 @@ -366,6 +366,25 @@ self.assertEqual('', style.tostring(result)) self.assertEqual('', str(result)) + def test_xslt_message(self): + xml = '' + xslt = ''' + + + TEST TEST TEST + + + ''' + + source = self.parse(xml) + styledoc = self.parse(xslt) + style = etree.XSLT(styledoc) + result = style.apply(source) + self.assertEqual('', style.tostring(result)) + self.assertEqual('', str(result)) + self.assert_("TEST TEST TEST" in [entry.message + for entry in style.error_log]) + def test_xslt_shortcut(self): tree = self.parse('BC') style = self.parse('''\ Modified: lxml/branch/lxml-1.1/src/lxml/xmlerror.pxi ============================================================================== --- lxml/branch/lxml-1.1/src/lxml/xmlerror.pxi (original) +++ lxml/branch/lxml-1.1/src/lxml/xmlerror.pxi Fri Sep 15 21:40:08 2006 @@ -9,17 +9,24 @@ Note that this log is already bounded to a fixed size.""" __GLOBAL_ERROR_LOG.clear() -# setup functions +# dummy function: no debug output at all +cdef void _nullGenericErrorFunc(void* ctxt, char* msg, ...): + pass + +# setup for global log: cdef void _initThreadLogging(): - "Setup logging for the current thread. Called from etree.initThread()." - # switch on line number reporting - _logLibxmlErrors() - try: - _logLibxsltErrors() - except NameError: - # compiled without libxslt - pass + # disable generic error lines from libxml2 + xmlerror.xmlThrDefSetGenericErrorFunc(NULL, _nullGenericErrorFunc) + xmlerror.xmlSetGenericErrorFunc(NULL, _nullGenericErrorFunc) + + # divert error messages to the global error log + xmlerror.xmlThrDefSetStructuredErrorFunc(NULL, _receiveError) + connectErrorLog(NULL) + +cdef void connectErrorLog(void* log): + xmlerror.xmlSetStructuredErrorFunc(log, _receiveError) + xslt.xsltSetGenericErrorFunc(log, _receiveXSLTError) # Logging classes @@ -194,10 +201,10 @@ cdef void connect(self): del self._entries[:] - xmlerror.xmlSetStructuredErrorFunc(self, _receiveError) + connectErrorLog(self) cdef void disconnect(self): - xmlerror.xmlSetStructuredErrorFunc(NULL, _receiveError) + connectErrorLog(NULL) def clear(self): del self._entries[:] @@ -326,8 +333,9 @@ cdef char* c_message cdef char* c_element cdef int i, text_size, element_size - if __DEBUG == 0 or msg is NULL or cstd.strlen(msg) < 10: + if __DEBUG == 0 or msg is NULL or cstd.strcmp(msg, '\n') == 0: return + cstd.va_start(args, msg) if msg[0] == c'%' and msg[1] == c's': c_text = cstd.va_charptr(args) @@ -374,17 +382,6 @@ python.PyMem_Free(c_error.message) python.PyGILState_Release(gil_state) -# dummy function: no debug output at all -cdef void _nullGenericErrorFunc(void* ctxt, char* msg, ...): - pass - -# setup for global log: -cdef void _logLibxmlErrors(): - xmlerror.xmlThrDefSetGenericErrorFunc(NULL, _nullGenericErrorFunc) - xmlerror.xmlSetGenericErrorFunc(NULL, _nullGenericErrorFunc) - - xmlerror.xmlThrDefSetStructuredErrorFunc(NULL, _receiveError) - xmlerror.xmlSetStructuredErrorFunc(NULL, _receiveError) ################################################################################ ## CONSTANTS FROM "xmlerror.h" (or rather libxml-xmlerror.html) Modified: lxml/branch/lxml-1.1/src/lxml/xslt.pxi ============================================================================== --- lxml/branch/lxml-1.1/src/lxml/xslt.pxi (original) +++ lxml/branch/lxml-1.1/src/lxml/xslt.pxi Fri Sep 15 21:40:08 2006 @@ -21,9 +21,6 @@ LIBXSLT_COMPILED_VERSION = __unpackIntVersion(xslt.LIBXSLT_VERSION) LIBXSLT_VERSION = __unpackIntVersion(xslt.xsltLibxsltVersion) -cdef void _logLibxsltErrors(): - xslt.xsltSetGenericErrorFunc(NULL, _receiveXSLTError) - ################################################################################ # Where do we store what? From scoder at codespeak.net Sat Sep 16 08:33:23 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Sat, 16 Sep 2006 08:33:23 +0200 (CEST) Subject: [Lxml-checkins] r32381 - lxml/trunk/src/lxml/tests Message-ID: <20060916063323.2BBB810050@code0.codespeak.net> Author: scoder Date: Sat Sep 16 08:33:19 2006 New Revision: 32381 Modified: lxml/trunk/src/lxml/tests/test_xslt.py Log: test case for Modified: lxml/trunk/src/lxml/tests/test_xslt.py ============================================================================== --- lxml/trunk/src/lxml/tests/test_xslt.py (original) +++ lxml/trunk/src/lxml/tests/test_xslt.py Sat Sep 16 08:33:19 2006 @@ -385,6 +385,25 @@ self.assert_("TEST TEST TEST" in [entry.message for entry in style.error_log]) + def test_xslt_message_terminate(self): + xml = '' + xslt = ''' + + + TEST TEST TEST + + + ''' + + source = self.parse(xml) + styledoc = self.parse(xslt) + style = etree.XSLT(styledoc) + result = style.apply(source) + self.assertEqual('', style.tostring(result)) + self.assertEqual('', str(result)) + self.assert_("TEST TEST TEST" in [entry.message + for entry in style.error_log]) + def test_xslt_shortcut(self): tree = self.parse('BC') style = self.parse('''\ From scoder at codespeak.net Sat Sep 16 09:19:16 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Sat, 16 Sep 2006 09:19:16 +0200 (CEST) Subject: [Lxml-checkins] r32382 - lxml/trunk/src/lxml Message-ID: <20060916071916.171F91005A@code0.codespeak.net> Author: scoder Date: Sat Sep 16 09:19:14 2006 New Revision: 32382 Modified: lxml/trunk/src/lxml/xmlerror.pxi Log: small cleanup Modified: lxml/trunk/src/lxml/xmlerror.pxi ============================================================================== --- lxml/trunk/src/lxml/xmlerror.pxi (original) +++ lxml/trunk/src/lxml/xmlerror.pxi Sat Sep 16 09:19:14 2006 @@ -333,7 +333,7 @@ cdef char* c_message cdef char* c_element cdef int i, text_size, element_size - if __DEBUG == 0 or msg is NULL or cstd.strcmp(msg, '\n') == 0: + if __DEBUG == 0 or msg is NULL or msg[0] == c'\n': return cstd.va_start(args, msg) From scoder at codespeak.net Mon Sep 18 15:54:15 2006 From: scoder at codespeak.net (scoder at codespeak.net) Date: Mon, 18 Sep 2006 15:54:15 +0200 (CEST) Subject: [Lxml-checkins] r32444 - in lxml/trunk: . doc src/lxml Message-ID: <20060918135415.0124E10076@code0.codespeak.net> Author: scoder Date: Mon Sep 18 15:54:12 2006 New Revision: 32444 Modified: lxml/trunk/CHANGES.txt lxml/trunk/doc/api.txt lxml/trunk/src/lxml/xslt.pxd lxml/trunk/src/lxml/xslt.pxi Log: XSLT profiling support Modified: lxml/trunk/CHANGES.txt ============================================================================== --- lxml/trunk/CHANGES.txt (original) +++ lxml/trunk/CHANGES.txt Mon Sep 18 15:54:12 2006 @@ -8,6 +8,8 @@ Features added -------------- +* XSLT profiling support (``profile_run`` keyword) + * countchildren() method on objectify.ObjectifiedElement * Support custom elements for tree nodes in lxml.objectify Modified: lxml/trunk/doc/api.txt ============================================================================== --- lxml/trunk/doc/api.txt (original) +++ lxml/trunk/doc/api.txt Mon Sep 18 15:54:12 2006 @@ -689,6 +689,25 @@ .. _`document loader documentation`: resolvers.html +If you want to know how your stylesheet performed, pass the ``profile_run`` +keyword to the transform:: + + >>> result = transform(doc, a="/a/b/text()", profile_run=True) + >>> profile = result.xslt_profile + +The value of the ``xslt_profile`` property is an ElementTree with profiling +data about each template, similar to the following:: + + +