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::
+
+
+
+
+
+Note that this is a read-only document. You must not move any of its elements
+to other documents. Please deep-copy the document if you need to modify it.
+If you want to free it from memory, just do::
+
+ >>> del result.xslt_profile
+
RelaxNG
-------
Modified: lxml/trunk/src/lxml/xslt.pxd
==============================================================================
--- lxml/trunk/src/lxml/xslt.pxd (original)
+++ lxml/trunk/src/lxml/xslt.pxd Mon Sep 18 15:54:12 2006
@@ -21,6 +21,7 @@
xsltDocument* document
void* _private
xmlDict* dict
+ int profile
cdef xsltStylesheet* xsltParseStylesheetDoc(xmlDoc* doc)
cdef void xsltFreeStylesheet(xsltStylesheet* sheet)
@@ -97,6 +98,7 @@
xsltSecurityCheck func)
cdef int xsltSetCtxtSecurityPrefs(xsltSecurityPrefs* sec,
xsltTransformContext* ctxt)
+ cdef xmlDoc* xsltGetProfileInformation(xsltTransformContext* ctxt)
cdef extern from "libxslt/extra.h":
cdef char* XSLT_LIBXSLT_NAMESPACE
Modified: lxml/trunk/src/lxml/xslt.pxi
==============================================================================
--- lxml/trunk/src/lxml/xslt.pxi (original)
+++ lxml/trunk/src/lxml/xslt.pxi Mon Sep 18 15:54:12 2006
@@ -337,12 +337,14 @@
def __get__(self):
return self._error_log.copy()
- def __call__(self, _input, **_kw):
+ def __call__(self, _input, profile_run=False, **_kw):
cdef python.PyThreadState* state
cdef _XSLTContext context
cdef _Document input_doc
cdef _NodeBase root_node
cdef _Document result_doc
+ cdef _Document profile_doc
+ cdef xmlDoc* c_profile_doc
cdef _XSLTResolverContext resolver_context
cdef xslt.xsltTransformContext* transform_ctxt
cdef xmlDoc* c_result
@@ -375,6 +377,9 @@
if self._access_control is not None:
self._access_control._register_in_context(transform_ctxt)
+ if profile_run:
+ transform_ctxt.profile = 1
+
transform_ctxt._private = self._xslt_resolver_context
kw_count = python.PyDict_Size(_kw)
@@ -411,6 +416,11 @@
# deallocate space for parameters
python.PyMem_Free(params)
+ if transform_ctxt.profile:
+ c_profile_doc = xslt.xsltGetProfileInformation(transform_ctxt)
+ if c_profile_doc is not NULL:
+ profile_doc = _documentFactory(c_profile_doc, input_doc._parser)
+
context.free_context()
_destroyFakeDoc(input_doc._c_doc, c_doc)
@@ -434,10 +444,10 @@
raise XSLTApplyError, message
result_doc = _documentFactory(c_result, input_doc._parser)
- return _xsltResultTreeFactory(result_doc, self)
+ return _xsltResultTreeFactory(result_doc, self, profile_doc)
- def apply(self, _input, **_kw):
- return self.__call__(_input, **_kw)
+ def apply(self, _input, profile_run=False, **_kw):
+ return self.__call__(_input, profile_run, **_kw)
def tostring(self, _ElementTree result_tree):
"""Save result doc to string based on stylesheet output method.
@@ -446,6 +456,7 @@
cdef class _XSLTResultTree(_ElementTree):
cdef XSLT _xslt
+ cdef _Document _profile
cdef _saveToStringAndSize(self, char** s, int* l):
cdef _Document doc
cdef int r
@@ -489,10 +500,26 @@
tree.xmlFree(s)
return _stripEncodingDeclaration(result)
-cdef _xsltResultTreeFactory(_Document doc, XSLT xslt):
+ property xslt_profile:
+ """Return an ElementTree with profiling data for the stylesheet run.
+ """
+ def __get__(self):
+ cdef _Element root
+ if self._profile is None:
+ return None
+ root = self._profile.getroot()
+ if root is None:
+ return None
+ return ElementTree(root)
+
+ def __del__(self):
+ self._profile = None
+
+cdef _xsltResultTreeFactory(_Document doc, XSLT xslt, _Document profile):
cdef _XSLTResultTree result
result = <_XSLTResultTree>_newElementTree(doc, None, _XSLTResultTree)
result._xslt = xslt
+ result._profile = profile
return result
# functions like "output" and "write" are a potential security risk, but we
From scoder at codespeak.net Mon Sep 18 15:54:43 2006
From: scoder at codespeak.net (scoder at codespeak.net)
Date: Mon, 18 Sep 2006 15:54:43 +0200 (CEST)
Subject: [Lxml-checkins] r32445 - lxml/branch/lxml-1.1/src/lxml/tests
Message-ID: <20060918135443.3B4EA10076@code0.codespeak.net>
Author: scoder
Date: Mon Sep 18 15:54:41 2006
New Revision: 32445
Modified:
lxml/branch/lxml-1.1/src/lxml/tests/test_xslt.py
Log:
new test case for xsl:message
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 Mon Sep 18 15:54:41 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 faassen at codespeak.net Mon Sep 18 18:23:40 2006
From: faassen at codespeak.net (faassen at codespeak.net)
Date: Mon, 18 Sep 2006 18:23:40 +0200 (CEST)
Subject: [Lxml-checkins] r32460 - lxml/trunk/doc
Message-ID: <20060918162340.18D2610082@code0.codespeak.net>
Author: faassen
Date: Mon Sep 18 18:23:39 2006
New Revision: 32460
Modified:
lxml/trunk/doc/build.txt
Log:
Add some instructions so I won't forget this again.
Modified: lxml/trunk/doc/build.txt
==============================================================================
--- lxml/trunk/doc/build.txt (original)
+++ lxml/trunk/doc/build.txt Mon Sep 18 18:23:39 2006
@@ -122,6 +122,25 @@
.. _`mailing list`: http://codespeak.net/mailman/listinfo/lxml-dev
+Contributing an egg
+-------------------
+
+This is the procedure to make an lxml egg for your platform:
+
+* download the lxml-x.y.tgz release. This contains the pregenerated C so
+ we don't run into any Pyrex issues. Unpack it and cd into it.
+
+* python setup.py build
+
+* if you're on a unixy platform, cd into build/lib.your.platform and
+ strip any .so file you find there. This reduces the size of the egg.
+
+* python setup.py bdist_egg upload
+
+The last 'upload' step only works if you have access to the lxml
+cheeseshop entry. If not, you can just make an egg with bdist_egg and
+mail it to the lxml maintainer.
+
Static linking on Windows
-------------------------
From scoder at codespeak.net Tue Sep 19 08:33:33 2006
From: scoder at codespeak.net (scoder at codespeak.net)
Date: Tue, 19 Sep 2006 08:33:33 +0200 (CEST)
Subject: [Lxml-checkins] r32472 - in lxml/branch/lxml-1.1: . doc src/lxml
Message-ID: <20060919063333.4C96410075@code0.codespeak.net>
Author: scoder
Date: Tue Sep 19 08:33:28 2006
New Revision: 32472
Modified:
lxml/branch/lxml-1.1/CHANGES.txt
lxml/branch/lxml-1.1/doc/api.txt
lxml/branch/lxml-1.1/src/lxml/xslt.pxd
lxml/branch/lxml-1.1/src/lxml/xslt.pxi
Log:
XSLT profiling support
Modified: lxml/branch/lxml-1.1/CHANGES.txt
==============================================================================
--- lxml/branch/lxml-1.1/CHANGES.txt (original)
+++ lxml/branch/lxml-1.1/CHANGES.txt Tue Sep 19 08:33:28 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/branch/lxml-1.1/doc/api.txt
==============================================================================
--- lxml/branch/lxml-1.1/doc/api.txt (original)
+++ lxml/branch/lxml-1.1/doc/api.txt Tue Sep 19 08:33:28 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::
+
+
+
+
+
+Note that this is a read-only document. You must not move any of its elements
+to other documents. Please deep-copy the document if you need to modify it.
+If you want to free it from memory, just do::
+
+ >>> del result.xslt_profile
+
RelaxNG
-------
Modified: lxml/branch/lxml-1.1/src/lxml/xslt.pxd
==============================================================================
--- lxml/branch/lxml-1.1/src/lxml/xslt.pxd (original)
+++ lxml/branch/lxml-1.1/src/lxml/xslt.pxd Tue Sep 19 08:33:28 2006
@@ -21,6 +21,7 @@
xsltDocument* document
void* _private
xmlDict* dict
+ int profile
cdef xsltStylesheet* xsltParseStylesheetDoc(xmlDoc* doc)
cdef void xsltFreeStylesheet(xsltStylesheet* sheet)
@@ -97,6 +98,7 @@
xsltSecurityCheck func)
cdef int xsltSetCtxtSecurityPrefs(xsltSecurityPrefs* sec,
xsltTransformContext* ctxt)
+ cdef xmlDoc* xsltGetProfileInformation(xsltTransformContext* ctxt)
cdef extern from "libxslt/extra.h":
cdef char* XSLT_LIBXSLT_NAMESPACE
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 Tue Sep 19 08:33:28 2006
@@ -337,12 +337,14 @@
def __get__(self):
return self._error_log.copy()
- def __call__(self, _input, **_kw):
+ def __call__(self, _input, profile_run=False, **_kw):
cdef python.PyThreadState* state
cdef _XSLTContext context
cdef _Document input_doc
cdef _NodeBase root_node
cdef _Document result_doc
+ cdef _Document profile_doc
+ cdef xmlDoc* c_profile_doc
cdef _XSLTResolverContext resolver_context
cdef xslt.xsltTransformContext* transform_ctxt
cdef xmlDoc* c_result
@@ -375,6 +377,9 @@
if self._access_control is not None:
self._access_control._register_in_context(transform_ctxt)
+ if profile_run:
+ transform_ctxt.profile = 1
+
transform_ctxt._private = self._xslt_resolver_context
kw_count = python.PyDict_Size(_kw)
@@ -411,6 +416,11 @@
# deallocate space for parameters
python.PyMem_Free(params)
+ if transform_ctxt.profile:
+ c_profile_doc = xslt.xsltGetProfileInformation(transform_ctxt)
+ if c_profile_doc is not NULL:
+ profile_doc = _documentFactory(c_profile_doc, input_doc._parser)
+
context.free_context()
_destroyFakeDoc(input_doc._c_doc, c_doc)
@@ -434,10 +444,10 @@
raise XSLTApplyError, message
result_doc = _documentFactory(c_result, input_doc._parser)
- return _xsltResultTreeFactory(result_doc, self)
+ return _xsltResultTreeFactory(result_doc, self, profile_doc)
- def apply(self, _input, **_kw):
- return self.__call__(_input, **_kw)
+ def apply(self, _input, profile_run=False, **_kw):
+ return self.__call__(_input, profile_run, **_kw)
def tostring(self, _ElementTree result_tree):
"""Save result doc to string based on stylesheet output method.
@@ -446,6 +456,7 @@
cdef class _XSLTResultTree(_ElementTree):
cdef XSLT _xslt
+ cdef _Document _profile
cdef _saveToStringAndSize(self, char** s, int* l):
cdef _Document doc
cdef int r
@@ -489,10 +500,26 @@
tree.xmlFree(s)
return _stripEncodingDeclaration(result)
-cdef _xsltResultTreeFactory(_Document doc, XSLT xslt):
+ property xslt_profile:
+ """Return an ElementTree with profiling data for the stylesheet run.
+ """
+ def __get__(self):
+ cdef _Element root
+ if self._profile is None:
+ return None
+ root = self._profile.getroot()
+ if root is None:
+ return None
+ return ElementTree(root)
+
+ def __del__(self):
+ self._profile = None
+
+cdef _xsltResultTreeFactory(_Document doc, XSLT xslt, _Document profile):
cdef _XSLTResultTree result
result = <_XSLTResultTree>_newElementTree(doc, None, _XSLTResultTree)
result._xslt = xslt
+ result._profile = profile
return result
# functions like "output" and "write" are a potential security risk, but we
From scoder at codespeak.net Wed Sep 20 16:54:26 2006
From: scoder at codespeak.net (scoder at codespeak.net)
Date: Wed, 20 Sep 2006 16:54:26 +0200 (CEST)
Subject: [Lxml-checkins] r32529 - in lxml/trunk: . benchmark doc
Message-ID: <20060920145426.D559910075@code0.codespeak.net>
Author: scoder
Date: Wed Sep 20 16:54:24 2006
New Revision: 32529
Modified:
lxml/trunk/MANIFEST.in
lxml/trunk/benchmark/benchbase.py
lxml/trunk/doc/performance.txt
Log:
cleanup in benchmarks
Modified: lxml/trunk/MANIFEST.in
==============================================================================
--- lxml/trunk/MANIFEST.in (original)
+++ lxml/trunk/MANIFEST.in Wed Sep 20 16:54:24 2006
@@ -1,5 +1,5 @@
exclude *.py
-include setup.py test.py selftest.py selftest2.py bench.py
+include setup.py test.py selftest.py selftest2.py
include update-error-constants.py
include MANIFEST.in version.txt
include CHANGES.txt CREDITS.txt INSTALL.txt LICENSES.txt README.txt TODO.txt
Modified: lxml/trunk/benchmark/benchbase.py
==============================================================================
--- lxml/trunk/benchmark/benchbase.py (original)
+++ lxml/trunk/benchmark/benchbase.py Wed Sep 20 16:54:24 2006
@@ -6,8 +6,8 @@
TREE_FACTOR = 1 # increase tree size with '-l / '-L' cmd option
-TEXT = "some ASCII text" * TREE_FACTOR
-UTEXT = u"some klingon: \F8D2" * TREE_FACTOR
+_TEXT = "some ASCII text" * TREE_FACTOR
+_UTEXT = u"some klingon: \F8D2" * TREE_FACTOR
_ATTRIBUTES = {
'{attr}test1' : _TEXT,
'{attr}test2' : _TEXT,
Modified: lxml/trunk/doc/performance.txt
==============================================================================
--- lxml/trunk/doc/performance.txt (original)
+++ lxml/trunk/doc/performance.txt Wed Sep 20 16:54:24 2006
@@ -19,7 +19,7 @@
1.0 (with libxml2 2.6.24), ElementTree 1.2.6 and cElementTree 1.0.5 under
CPython 2.4.2 on a 1.6GHz AMD64 machine.
-.. _`bench.py`: http://codespeak.net/svn/lxml/trunk/bench.py
+.. _`bench.py`: http://codespeak.net/svn/lxml/branch/lxml-1.0/bench.py
The ``bench.py`` script runs a number of simple tests on the different
libraries, using different XML tree configurations: different tree sizes, with
From scoder at codespeak.net Wed Sep 20 16:56:07 2006
From: scoder at codespeak.net (scoder at codespeak.net)
Date: Wed, 20 Sep 2006 16:56:07 +0200 (CEST)
Subject: [Lxml-checkins] r32530 - in lxml/branch/lxml-1.1: . benchmark doc
Message-ID: <20060920145607.D014F10075@code0.codespeak.net>
Author: scoder
Date: Wed Sep 20 16:56:06 2006
New Revision: 32530
Modified:
lxml/branch/lxml-1.1/MANIFEST.in
lxml/branch/lxml-1.1/benchmark/benchbase.py
lxml/branch/lxml-1.1/doc/performance.txt
Log:
merge from trunk: benchmark cleanup
Modified: lxml/branch/lxml-1.1/MANIFEST.in
==============================================================================
--- lxml/branch/lxml-1.1/MANIFEST.in (original)
+++ lxml/branch/lxml-1.1/MANIFEST.in Wed Sep 20 16:56:06 2006
@@ -1,5 +1,5 @@
exclude *.py
-include setup.py test.py selftest.py selftest2.py bench.py
+include setup.py test.py selftest.py selftest2.py
include update-error-constants.py
include MANIFEST.in version.txt
include CHANGES.txt CREDITS.txt INSTALL.txt LICENSES.txt README.txt TODO.txt
Modified: lxml/branch/lxml-1.1/benchmark/benchbase.py
==============================================================================
--- lxml/branch/lxml-1.1/benchmark/benchbase.py (original)
+++ lxml/branch/lxml-1.1/benchmark/benchbase.py Wed Sep 20 16:56:06 2006
@@ -6,8 +6,8 @@
TREE_FACTOR = 1 # increase tree size with '-l / '-L' cmd option
-TEXT = "some ASCII text" * TREE_FACTOR
-UTEXT = u"some klingon: \F8D2" * TREE_FACTOR
+_TEXT = "some ASCII text" * TREE_FACTOR
+_UTEXT = u"some klingon: \F8D2" * TREE_FACTOR
_ATTRIBUTES = {
'{attr}test1' : _TEXT,
'{attr}test2' : _TEXT,
Modified: lxml/branch/lxml-1.1/doc/performance.txt
==============================================================================
--- lxml/branch/lxml-1.1/doc/performance.txt (original)
+++ lxml/branch/lxml-1.1/doc/performance.txt Wed Sep 20 16:56:06 2006
@@ -19,7 +19,7 @@
1.0 (with libxml2 2.6.24), ElementTree 1.2.6 and cElementTree 1.0.5 under
CPython 2.4.2 on a 1.6GHz AMD64 machine.
-.. _`bench.py`: http://codespeak.net/svn/lxml/trunk/bench.py
+.. _`bench.py`: http://codespeak.net/svn/lxml/branch/lxml-1.0/bench.py
The ``bench.py`` script runs a number of simple tests on the different
libraries, using different XML tree configurations: different tree sizes, with
From scoder at codespeak.net Wed Sep 20 17:31:09 2006
From: scoder at codespeak.net (scoder at codespeak.net)
Date: Wed, 20 Sep 2006 17:31:09 +0200 (CEST)
Subject: [Lxml-checkins] r32532 - lxml/trunk/src/lxml
Message-ID: <20060920153109.00BC51007B@code0.codespeak.net>
Author: scoder
Date: Wed Sep 20 17:31:08 2006
New Revision: 32532
Modified:
lxml/trunk/src/lxml/objectify.pyx
Log:
make Python longs (1L) parsable
Modified: lxml/trunk/src/lxml/objectify.pyx
==============================================================================
--- lxml/trunk/src/lxml/objectify.pyx (original)
+++ lxml/trunk/src/lxml/objectify.pyx Wed Sep 20 17:31:08 2006
@@ -845,7 +845,7 @@
"int", "unsignedInt", "short", "unsignedShort")
pytype.register()
- pytype = PyType('long', None, LongElement)
+ pytype = PyType('long', long, LongElement)
pytype.xmlSchemaTypes = ("long", "unsignedLong")
pytype.register()
From scoder at codespeak.net Wed Sep 20 17:34:04 2006
From: scoder at codespeak.net (scoder at codespeak.net)
Date: Wed, 20 Sep 2006 17:34:04 +0200 (CEST)
Subject: [Lxml-checkins] r32533 - lxml/trunk/doc
Message-ID: <20060920153404.9C0571007F@code0.codespeak.net>
Author: scoder
Date: Wed Sep 20 17:34:03 2006
New Revision: 32533
Modified:
lxml/trunk/doc/mkhtml.py
Log:
patch by Holger: accept non-default Python interpreter for mkhtml.py
Modified: lxml/trunk/doc/mkhtml.py
==============================================================================
--- lxml/trunk/doc/mkhtml.py (original)
+++ lxml/trunk/doc/mkhtml.py Wed Sep 20 17:34:03 2006
@@ -33,8 +33,8 @@
os.path.join(dirname, 'index.html'))
def rest2html(script, source_path, dest_path, stylesheet_url):
- command = ('%s --stylesheet=%s --link-stylesheet %s > %s' %
- (script, stylesheet_url, source_path, dest_path))
+ command = ('%s %s --stylesheet=%s --link-stylesheet %s > %s' %
+ (sys.executable, script, stylesheet_url, source_path, dest_path))
os.system(command)
if __name__ == '__main__':
From scoder at codespeak.net Wed Sep 20 17:38:21 2006
From: scoder at codespeak.net (scoder at codespeak.net)
Date: Wed, 20 Sep 2006 17:38:21 +0200 (CEST)
Subject: [Lxml-checkins] r32534 - lxml/trunk/doc
Message-ID: <20060920153821.C64261007F@code0.codespeak.net>
Author: scoder
Date: Wed Sep 20 17:38:20 2006
New Revision: 32534
Modified:
lxml/trunk/doc/objectify.txt
Log:
doc updates, mainly from Holger
Modified: lxml/trunk/doc/objectify.txt
==============================================================================
--- lxml/trunk/doc/objectify.txt (original)
+++ lxml/trunk/doc/objectify.txt Wed Sep 20 17:38:20 2006
@@ -559,7 +559,7 @@
['test']
If you need to run sequence operations on data types, you must ask the API for
-the *real* Python value. The string value is always available throught the
+the *real* Python value. The string value is always available through the
normal ElementTree ``.text`` attribute. Additionally, all data classes
provide a ``.pyval`` attribute that returns the value as plain Python type::
@@ -591,13 +591,48 @@
>>> print root.a
25
+In other words, objectify data elements behave like immutable Python types.
+
How data types are matched
--------------------------
-Objectify determines data types by trial and error, unless it finds an
-attribute named ``lxml.objectify.PYTYPE_ATTRIBUTE``, which must contain any of
-the following string values: int, long, float, str, unicode, none::
+Objectify uses two different types of Elements. Structural Elements (or tree
+Elements) represent the object tree structure. Data Elements represent the
+data containers at the leafs. You can explicitly create tree Elements with
+the ``objectify.Element()`` factory and data Elements with the
+``objectify.DataElement()`` factory.
+
+When Element objects are created, lxml.objectify must determine which
+implementation class to use for them. This is relatively easy for tree
+Elements and less so for data Elements. The algorithm is as follows:
+
+1. If an element has children, use the default tree class.
+
+2. If an element is defined as xsi:nil, use the NoneElement class.
+
+3. If a "Python type hint" attribute is given, use this to determine the element
+ class, see below.
+
+4. If an XML Schema xsi:type hint is given, use this to determine the element
+ class, see below.
+
+5. Try to determine the element class from the text content type by trial and
+ error.
+
+6. If the element is a root node then use the default tree class.
+
+7. Otherwise, use the default class for empty data classes.
+
+You can change the default classes for tree Elements and empty data Elements
+at setup time. The ``ObjectifyElementClassLookup()`` call accepts two keyword
+arguments, ``tree_class`` and ``empty_data_class``, that determine the Element
+classes used in these cases. By default, ``tree_class`` is a class called
+``ObjectifiedElement`` and ``empty_data_class`` is a ``StringElement``.
+
+The "type hint" mechanism deploys an XML attribute defined as
+``lxml.objectify.PYTYPE_ATTRIBUTE``. It may contain any of the following
+string values: int, long, float, str, unicode, none::
>>> print objectify.PYTYPE_ATTRIBUTE
{http://codespeak.net/lxml/objectify/pytype}pytype
@@ -658,9 +693,9 @@
s = '5' [StringElement]
* xsi:type = 'string'
-For convenience, there is a special factory ``DataElement()`` that supports
-creating an Element with a Python value in one step. You can pass the
-required Python type name or the XSI type name::
+For convenience, the ``DataElement()`` factory creates an Element with a
+Python value in one step. You can pass the required Python type name or the
+XSI type name::
>>> root = objectify.Element("root")
>>> root.x = objectify.DataElement(5, _pytype="long")
@@ -683,16 +718,38 @@
* py:pytype = 'int'
* xsi:type = 'integer'
+There is a side effect of the type lookup. If you assign a string value using
+attribute assignment and that string value turns out to be valid for any of
+the type checks, you will end up with the resolved type instead of a
+StringElement::
+
+ >>> root = objectify.Element("root")
+ >>> root.s = "5"
+ >>> print objectify.dump(root)
+ root = None [ObjectifiedElement]
+ s = 5 [IntElement]
+
+You can use the ``DataElement()`` factory to avoid this behaviour and thus
+provide the type of a data element by hand::
+
+ >>> root = objectify.Element("root")
+ >>> root.s = objectify.DataElement(5, _pytype="str")
+ >>> print objectify.dump(root)
+ root = None [ObjectifiedElement]
+ s = '5' [StringElement]
+ * py:pytype = 'str'
+
Defining additional data classes
--------------------------------
-Data classes can either inherit from ``ObjectifiedDataElement`` directly or
-from one of the specialised classes like ``NumberElement`` or ``BoolElement``.
-The numeric types require an initial call to the NumberElement method
-``self._setValueParser(function)`` to set their type conversion funtion
-(string -> numeric Python type). This call should be placed into the element
-``_init()`` method.
+You can plug additional data classes into objectify that will be used in
+exactly the same way as the predefined types. Data classes can either inherit
+from ``ObjectifiedDataElement`` directly or from one of the specialised
+classes like ``NumberElement`` or ``BoolElement``. The numeric types require
+an initial call to the NumberElement method ``self._setValueParser(function)``
+to set their type conversion function (string -> numeric Python type). This
+call should be placed into the element ``_init()`` method.
The registration of data classes uses the ``PyType`` class::
@@ -706,6 +763,16 @@
>>> xmas_type = objectify.PyType('date', checkChristmasDate, ChristmasDate)
+The PyType constructor takes a string type name, an (optional) callable type
+check and the custom data class. If a type check is provided it must accept a
+string as argument and raise ValueError or TypeError if it cannot handle the
+string value.
+
+PyTypes are used if an element carries a ``py:pytype`` attribute denoting its
+data type or, in absence of such an attribute, if the given type check callable
+does not raise a ValueError/TypeError exception when applied to the element
+text.
+
If you want, you can also register this type under an XML Schema type name::
>>> xmas_type.xmlSchemaTypes = ("date",)
@@ -805,6 +872,10 @@
Such a different Element API obviously implies some side effects to the normal
behaviour of the rest of the API.
+* len() returns the sibling count, not the number of children of
+ . You can retrieve the number of children with the
+ ``countchildren()`` method.
+
* Iteration over elements does not yield the children, but the siblings. You
can access all children with the ``iterchildren()`` method on elements or
retrieve a list by calling the ``getchildren()`` method.
From scoder at codespeak.net Wed Sep 20 17:41:12 2006
From: scoder at codespeak.net (scoder at codespeak.net)
Date: Wed, 20 Sep 2006 17:41:12 +0200 (CEST)
Subject: [Lxml-checkins] r32535 - lxml/trunk
Message-ID: <20060920154112.CB5041007F@code0.codespeak.net>
Author: scoder
Date: Wed Sep 20 17:41:11 2006
New Revision: 32535
Modified:
lxml/trunk/CHANGES.txt
Log:
updated changelog
Modified: lxml/trunk/CHANGES.txt
==============================================================================
--- lxml/trunk/CHANGES.txt (original)
+++ lxml/trunk/CHANGES.txt Wed Sep 20 17:41:11 2006
@@ -17,6 +17,8 @@
Bugs fixed
----------
+* lxml.objectify failed to support long data values (e.g., "123L")
+
* Error messages from XSLT did not reach ``XSLT.error_log``
* Factories objectify.Element() and objectify.DataElement() were missing
From scoder at codespeak.net Wed Sep 20 17:41:32 2006
From: scoder at codespeak.net (scoder at codespeak.net)
Date: Wed, 20 Sep 2006 17:41:32 +0200 (CEST)
Subject: [Lxml-checkins] r32536 - in lxml/branch/lxml-1.1: . doc src/lxml
Message-ID: <20060920154132.871A01007F@code0.codespeak.net>
Author: scoder
Date: Wed Sep 20 17:41:29 2006
New Revision: 32536
Modified:
lxml/branch/lxml-1.1/CHANGES.txt
lxml/branch/lxml-1.1/doc/mkhtml.py
lxml/branch/lxml-1.1/doc/objectify.txt
lxml/branch/lxml-1.1/src/lxml/objectify.pyx
Log:
merge from trunk: objectify fixes by Holger
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 20 17:41:29 2006
@@ -17,6 +17,8 @@
Bugs fixed
----------
+* lxml.objectify failed to support long data values (e.g., "123L")
+
* Error messages from XSLT did not reach ``XSLT.error_log``
* Factories objectify.Element() and objectify.DataElement() were missing
Modified: lxml/branch/lxml-1.1/doc/mkhtml.py
==============================================================================
--- lxml/branch/lxml-1.1/doc/mkhtml.py (original)
+++ lxml/branch/lxml-1.1/doc/mkhtml.py Wed Sep 20 17:41:29 2006
@@ -33,8 +33,8 @@
os.path.join(dirname, 'index.html'))
def rest2html(script, source_path, dest_path, stylesheet_url):
- command = ('%s --stylesheet=%s --link-stylesheet %s > %s' %
- (script, stylesheet_url, source_path, dest_path))
+ command = ('%s %s --stylesheet=%s --link-stylesheet %s > %s' %
+ (sys.executable, script, stylesheet_url, source_path, dest_path))
os.system(command)
if __name__ == '__main__':
Modified: lxml/branch/lxml-1.1/doc/objectify.txt
==============================================================================
--- lxml/branch/lxml-1.1/doc/objectify.txt (original)
+++ lxml/branch/lxml-1.1/doc/objectify.txt Wed Sep 20 17:41:29 2006
@@ -559,7 +559,7 @@
['test']
If you need to run sequence operations on data types, you must ask the API for
-the *real* Python value. The string value is always available throught the
+the *real* Python value. The string value is always available through the
normal ElementTree ``.text`` attribute. Additionally, all data classes
provide a ``.pyval`` attribute that returns the value as plain Python type::
@@ -591,13 +591,48 @@
>>> print root.a
25
+In other words, objectify data elements behave like immutable Python types.
+
How data types are matched
--------------------------
-Objectify determines data types by trial and error, unless it finds an
-attribute named ``lxml.objectify.PYTYPE_ATTRIBUTE``, which must contain any of
-the following string values: int, long, float, str, unicode, none::
+Objectify uses two different types of Elements. Structural Elements (or tree
+Elements) represent the object tree structure. Data Elements represent the
+data containers at the leafs. You can explicitly create tree Elements with
+the ``objectify.Element()`` factory and data Elements with the
+``objectify.DataElement()`` factory.
+
+When Element objects are created, lxml.objectify must determine which
+implementation class to use for them. This is relatively easy for tree
+Elements and less so for data Elements. The algorithm is as follows:
+
+1. If an element has children, use the default tree class.
+
+2. If an element is defined as xsi:nil, use the NoneElement class.
+
+3. If a "Python type hint" attribute is given, use this to determine the element
+ class, see below.
+
+4. If an XML Schema xsi:type hint is given, use this to determine the element
+ class, see below.
+
+5. Try to determine the element class from the text content type by trial and
+ error.
+
+6. If the element is a root node then use the default tree class.
+
+7. Otherwise, use the default class for empty data classes.
+
+You can change the default classes for tree Elements and empty data Elements
+at setup time. The ``ObjectifyElementClassLookup()`` call accepts two keyword
+arguments, ``tree_class`` and ``empty_data_class``, that determine the Element
+classes used in these cases. By default, ``tree_class`` is a class called
+``ObjectifiedElement`` and ``empty_data_class`` is a ``StringElement``.
+
+The "type hint" mechanism deploys an XML attribute defined as
+``lxml.objectify.PYTYPE_ATTRIBUTE``. It may contain any of the following
+string values: int, long, float, str, unicode, none::
>>> print objectify.PYTYPE_ATTRIBUTE
{http://codespeak.net/lxml/objectify/pytype}pytype
@@ -658,9 +693,9 @@
s = '5' [StringElement]
* xsi:type = 'string'
-For convenience, there is a special factory ``DataElement()`` that supports
-creating an Element with a Python value in one step. You can pass the
-required Python type name or the XSI type name::
+For convenience, the ``DataElement()`` factory creates an Element with a
+Python value in one step. You can pass the required Python type name or the
+XSI type name::
>>> root = objectify.Element("root")
>>> root.x = objectify.DataElement(5, _pytype="long")
@@ -683,16 +718,38 @@
* py:pytype = 'int'
* xsi:type = 'integer'
+There is a side effect of the type lookup. If you assign a string value using
+attribute assignment and that string value turns out to be valid for any of
+the type checks, you will end up with the resolved type instead of a
+StringElement::
+
+ >>> root = objectify.Element("root")
+ >>> root.s = "5"
+ >>> print objectify.dump(root)
+ root = None [ObjectifiedElement]
+ s = 5 [IntElement]
+
+You can use the ``DataElement()`` factory to avoid this behaviour and thus
+provide the type of a data element by hand::
+
+ >>> root = objectify.Element("root")
+ >>> root.s = objectify.DataElement(5, _pytype="str")
+ >>> print objectify.dump(root)
+ root = None [ObjectifiedElement]
+ s = '5' [StringElement]
+ * py:pytype = 'str'
+
Defining additional data classes
--------------------------------
-Data classes can either inherit from ``ObjectifiedDataElement`` directly or
-from one of the specialised classes like ``NumberElement`` or ``BoolElement``.
-The numeric types require an initial call to the NumberElement method
-``self._setValueParser(function)`` to set their type conversion funtion
-(string -> numeric Python type). This call should be placed into the element
-``_init()`` method.
+You can plug additional data classes into objectify that will be used in
+exactly the same way as the predefined types. Data classes can either inherit
+from ``ObjectifiedDataElement`` directly or from one of the specialised
+classes like ``NumberElement`` or ``BoolElement``. The numeric types require
+an initial call to the NumberElement method ``self._setValueParser(function)``
+to set their type conversion function (string -> numeric Python type). This
+call should be placed into the element ``_init()`` method.
The registration of data classes uses the ``PyType`` class::
@@ -706,6 +763,16 @@
>>> xmas_type = objectify.PyType('date', checkChristmasDate, ChristmasDate)
+The PyType constructor takes a string type name, an (optional) callable type
+check and the custom data class. If a type check is provided it must accept a
+string as argument and raise ValueError or TypeError if it cannot handle the
+string value.
+
+PyTypes are used if an element carries a ``py:pytype`` attribute denoting its
+data type or, in absence of such an attribute, if the given type check callable
+does not raise a ValueError/TypeError exception when applied to the element
+text.
+
If you want, you can also register this type under an XML Schema type name::
>>> xmas_type.xmlSchemaTypes = ("date",)
@@ -805,6 +872,10 @@
Such a different Element API obviously implies some side effects to the normal
behaviour of the rest of the API.
+* len() returns the sibling count, not the number of children of
+ . You can retrieve the number of children with the
+ ``countchildren()`` method.
+
* Iteration over elements does not yield the children, but the siblings. You
can access all children with the ``iterchildren()`` method on elements or
retrieve a list by calling the ``getchildren()`` method.
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 Wed Sep 20 17:41:29 2006
@@ -845,7 +845,7 @@
"int", "unsignedInt", "short", "unsignedShort")
pytype.register()
- pytype = PyType('long', None, LongElement)
+ pytype = PyType('long', long, LongElement)
pytype.xmlSchemaTypes = ("long", "unsignedLong")
pytype.register()
From scoder at codespeak.net Thu Sep 21 10:34:45 2006
From: scoder at codespeak.net (scoder at codespeak.net)
Date: Thu, 21 Sep 2006 10:34:45 +0200 (CEST)
Subject: [Lxml-checkins] r32551 - in lxml/branch/lxml-1.1: . doc
Message-ID: <20060921083445.BDB9D10078@code0.codespeak.net>
Author: scoder
Date: Thu Sep 21 10:34:44 2006
New Revision: 32551
Modified:
lxml/branch/lxml-1.1/CHANGES.txt
lxml/branch/lxml-1.1/doc/main.txt
Log:
prepare release of 1.1.1
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 21 10:34:44 2006
@@ -2,8 +2,8 @@
lxml changelog
==============
-current
-=======
+1.1.1 (2006-09-21)
+==================
Features added
--------------
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 21 10:34:44 2006
@@ -29,6 +29,8 @@
.. _`installation instructions`: installation.html
+* `lxml 1.1.1`_, released 2006-09-21 (`changes for 1.1.1`_)
+
* `lxml 1.1`_, released 2006-09-13 (`changes for 1.1`_)
* `lxml 1.0.4`_, released 2006-09-09 (`changes for 1.0.4`_)
@@ -57,6 +59,7 @@
* `lxml 0.5`_, released 2005-04-08
+.. _`lxml 1.1.1`: lxml-1.1.1.tgz
.. _`lxml 1.1`: lxml-1.1.tgz
.. _`lxml 1.0.4`: lxml-1.0.4.tgz
.. _`lxml 1.0.3`: lxml-1.0.3.tgz
@@ -72,6 +75,7 @@
.. _`lxml 0.5.1`: lxml-0.5.1.tgz
.. _`lxml 0.5`: lxml-0.5.tgz
+.. _`CHANGES for 1.1.1`: changes-1.1.1.html
.. _`CHANGES for 1.1`: changes-1.1.html
.. _`CHANGES for 1.0.4`: changes-1.0.4.html
.. _`CHANGES for 1.0.3`: changes-1.0.3.html
From scoder at codespeak.net Thu Sep 21 10:40:20 2006
From: scoder at codespeak.net (scoder at codespeak.net)
Date: Thu, 21 Sep 2006 10:40:20 +0200 (CEST)
Subject: [Lxml-checkins] r32552 - in lxml/trunk: . doc src/lxml
Message-ID: <20060921084020.7A22410076@code0.codespeak.net>
Author: scoder
Date: Thu Sep 21 10:40:17 2006
New Revision: 32552
Modified:
lxml/trunk/CHANGES.txt
lxml/trunk/doc/main.txt
lxml/trunk/src/lxml/etree.pyx
Log:
merged in 1.1.1 release changes from branch
Modified: lxml/trunk/CHANGES.txt
==============================================================================
--- lxml/trunk/CHANGES.txt (original)
+++ lxml/trunk/CHANGES.txt Thu Sep 21 10:40:17 2006
@@ -2,8 +2,8 @@
lxml changelog
==============
-current
-=======
+1.1.1 (2006-09-21)
+==================
Features added
--------------
Modified: lxml/trunk/doc/main.txt
==============================================================================
--- lxml/trunk/doc/main.txt (original)
+++ lxml/trunk/doc/main.txt Thu Sep 21 10:40:17 2006
@@ -29,6 +29,8 @@
.. _`installation instructions`: installation.html
+* `lxml 1.1.1`_, released 2006-09-21 (`changes for 1.1.1`_)
+
* `lxml 1.1`_, released 2006-09-13 (`changes for 1.1`_)
* `lxml 1.0.4`_, released 2006-09-09 (`changes for 1.0.4`_)
@@ -57,6 +59,7 @@
* `lxml 0.5`_, released 2005-04-08
+.. _`lxml 1.1.1`: lxml-1.1.1.tgz
.. _`lxml 1.1`: lxml-1.1.tgz
.. _`lxml 1.0.4`: lxml-1.0.4.tgz
.. _`lxml 1.0.3`: lxml-1.0.3.tgz
@@ -72,6 +75,7 @@
.. _`lxml 0.5.1`: lxml-0.5.1.tgz
.. _`lxml 0.5`: lxml-0.5.tgz
+.. _`CHANGES for 1.1.1`: changes-1.1.1.html
.. _`CHANGES for 1.1`: changes-1.1.html
.. _`CHANGES for 1.0.4`: changes-1.0.4.html
.. _`CHANGES for 1.0.3`: changes-1.0.3.html
Modified: lxml/trunk/src/lxml/etree.pyx
==============================================================================
--- lxml/trunk/src/lxml/etree.pyx (original)
+++ lxml/trunk/src/lxml/etree.pyx Thu Sep 21 10:40:17 2006
@@ -542,7 +542,7 @@
evaluator = XPathDocumentEvaluator(self, namespaces, extensions)
return evaluator.evaluate(_path, **_variables)
- def xslt(self, _xslt, extensions=None, **_kw):
+ def xslt(self, _xslt, extensions=None, access_control=None, **_kw):
"""Transform this document using other document.
xslt is a tree that should be XSLT
@@ -555,7 +555,8 @@
class directly.
"""
self._assertHasRoot()
- style = XSLT(_xslt, extensions)
+ style = XSLT(_xslt, extensions=extensions,
+ access_control=access_control)
return style(self, **_kw)
def relaxng(self, relaxng):
From scoder at codespeak.net Fri Sep 22 18:48:13 2006
From: scoder at codespeak.net (scoder at codespeak.net)
Date: Fri, 22 Sep 2006 18:48:13 +0200 (CEST)
Subject: [Lxml-checkins] r32595 - in lxml/trunk: . src/lxml src/lxml/tests
Message-ID: <20060922164813.537271006E@code0.codespeak.net>
Author: scoder
Date: Fri Sep 22 18:48:09 2006
New Revision: 32595
Modified:
lxml/trunk/CHANGES.txt
lxml/trunk/src/lxml/classlookup.pxi
lxml/trunk/src/lxml/parser.pxi
lxml/trunk/src/lxml/tests/test_xslt.py
lxml/trunk/src/lxml/tree.pxd
lxml/trunk/src/lxml/xslt.pxi
Log:
special class implementation for XSLT processing instructions
Modified: lxml/trunk/CHANGES.txt
==============================================================================
--- lxml/trunk/CHANGES.txt (original)
+++ lxml/trunk/CHANGES.txt Fri Sep 22 18:48:09 2006
@@ -2,6 +2,18 @@
lxml changelog
==============
+current
+=======
+
+Features added
+--------------
+
+* Simplified support for handling XSLT processing instructions
+
+Bugs fixed
+----------
+
+
1.1.1 (2006-09-21)
==================
Modified: lxml/trunk/src/lxml/classlookup.pxi
==============================================================================
--- lxml/trunk/src/lxml/classlookup.pxi (original)
+++ lxml/trunk/src/lxml/classlookup.pxi Fri Sep 22 18:48:09 2006
@@ -120,6 +120,12 @@
return (state).comment_class
elif c_node.type == tree.XML_PI_NODE:
if state is None:
+ # special case XSLT-PI
+ if c_node.name is not NULL and c_node.content is not NULL:
+ if cstd.strcmp(c_node.name, "xml-stylesheet") == 0:
+ if cstd.strstr(c_node.content, "text/xsl") is not NULL or \
+ cstd.strstr(c_node.content, "text/xml") is not NULL:
+ return _XSLTProcessingInstruction
return _ProcessingInstruction
else:
return (state).pi_class
Modified: lxml/trunk/src/lxml/parser.pxi
==============================================================================
--- lxml/trunk/src/lxml/parser.pxi (original)
+++ lxml/trunk/src/lxml/parser.pxi Fri Sep 22 18:48:09 2006
@@ -862,7 +862,6 @@
############################################################
cdef _Document _parseDocument(source, _BaseParser parser):
- cdef xmlDoc* c_doc
filename = _getFilenameForFile(source)
if hasattr(source, 'getvalue') and hasattr(source, 'tell'):
# StringIO - reading from start?
@@ -879,7 +878,11 @@
if filename is None:
filename = _encodeFilename(source)
# open filename
- c_doc = _parseDocFromFile(filename, parser)
+ return _parseDocumentFromURL(filename, parser)
+
+cdef _Document _parseDocumentFromURL(url, _BaseParser parser):
+ cdef xmlDoc* c_doc
+ c_doc = _parseDocFromFile(url, parser)
return _documentFactory(c_doc, parser)
cdef _Document _parseMemoryDocument(text, url, _BaseParser parser):
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 22 18:48:09 2006
@@ -573,6 +573,69 @@
result = xslt(root[0])
root[:] = result.getroot()[:]
del root # segfaulted before
+
+ def test_xslt_pi_embedded_xmlid(self):
+ # test xml:id dictionary lookup mechanism
+ tree = self.parse('''\
+
+
+
+ B
+ C
+
+
+
+
+
+
+''')
+
+ style = tree.getroot().getprevious().parseXSL()
+ self.assertEquals("{http://www.w3.org/1999/XSL/Transform}stylesheet",
+ style.tag)
+
+ st = etree.XSLT(style)
+ res = st.apply(tree)
+ self.assertEquals('''\
+
+B
+''',
+ st.tostring(res))
+
+ def test_xslt_pi_embedded_id(self):
+ # test XPath lookup mechanism
+ tree = self.parse('''\
+
+
+
+ B
+ C
+''')
+
+ style = self.parse('''\
+
+
+
+
+
+
+''')
+
+ tree.getroot().append(style.getroot())
+
+ style = tree.getroot().getprevious().parseXSL()
+ self.assertEquals("{http://www.w3.org/1999/XSL/Transform}stylesheet",
+ style.tag)
+
+ st = etree.XSLT(style)
+ res = st.apply(tree)
+ self.assertEquals('''\
+
+B
+''',
+ st.tostring(res))
def test_exslt_regexp_test(self):
xslt = etree.XSLT(etree.XML("""\
Modified: lxml/trunk/src/lxml/tree.pxd
==============================================================================
--- lxml/trunk/src/lxml/tree.pxd (original)
+++ lxml/trunk/src/lxml/tree.pxd Fri Sep 22 18:48:09 2006
@@ -210,7 +210,12 @@
cdef char* xmlBufferContent(xmlBuffer* buf)
cdef int xmlBufferLength(xmlBuffer* buf)
cdef int xmlKeepBlanksDefault(int val)
-
+ cdef char* xmlNodeGetBase(xmlDoc* doc, xmlNode* node)
+ cdef char* xmlBuildURI(char* href, char* base)
+
+cdef extern from "libxml/valid.h":
+ cdef xmlAttr* xmlGetID(xmlDoc* doc, char* ID)
+
cdef extern from "libxml/xmlIO.h":
cdef int xmlOutputBufferWriteString(xmlOutputBuffer* out, char* str)
cdef int xmlOutputBufferFlush(xmlOutputBuffer* out)
Modified: lxml/trunk/src/lxml/xslt.pxi
==============================================================================
--- lxml/trunk/src/lxml/xslt.pxi (original)
+++ lxml/trunk/src/lxml/xslt.pxi Fri Sep 22 18:48:09 2006
@@ -545,10 +545,64 @@
################################################################################
-# EXSLT regexp implementation
+# XSLT PI support
+
+cdef object _FIND_PI_HREF
+_FIND_PI_HREF = re.compile('href\s*=\s*["\']([^"\']+)["\']').findall
+
+cdef XPath _findStylesheetByID
+_findStylesheetByID = XPath(
+ "//xsl:stylesheet[@xml:id = $id]",
+ {"xsl":"http://www.w3.org/1999/XSL/Transform"})
+
+cdef class _XSLTProcessingInstruction(PIBase):
+ def parseXSL(self, parser=None):
+ """Try to parse the stylesheet referenced by this PI and return its
+ root node. If the stylesheet is embedded in the same document
+ (referenced via xml:id), find and return the stylesheet Element.
+
+ The optional ``parser`` keyword argument can be passed to specify the
+ parser used to read from external stylesheet URLs.
+ """
+ cdef _Document result_doc
+ cdef char* c_href
+ cdef xmlAttr* c_attr
+ if self._c_node.content is NULL:
+ raise ValueError, "PI lacks content"
+ hrefs_utf = _FIND_PI_HREF(self._c_node.content)
+ if len(hrefs_utf) != 1:
+ raise ValueError, "malformed PI attributes"
+ href_utf = hrefs_utf[0]
+ c_href = _cstr(href_utf)
+
+ if c_href[0] != c'#':
+ # normal URL, try to parse from it
+ c_href = tree.xmlBuildURI(
+ c_href,
+ tree.xmlNodeGetBase(self._c_node.doc, self._c_node))
+ if c_href is NULL:
+ c_href = _cstr(href_utf)
+ result_doc = _parseDocument(funicode(c_href), parser)
+ return _elementTreeFactory(result_doc, None)
+
+ # ID reference to embedded stylesheet
+ # try XML:ID lookup
+ c_href = c_href+1 # skip leading '#'
+ c_attr = tree.xmlGetID(self._c_node.doc, c_href)
+ if c_attr is not NULL and c_attr.doc is self._c_node.doc:
+ return _elementFactory(self._doc, c_attr.parent)
+
+ # try XPath search
+ root = _findStylesheetByID(self._doc, id=funicode(c_href))
+ if not root:
+ raise ValueError, "reference to non-existing embedded stylesheet"
+ elif len(root) > 1:
+ raise ValueError, "ambiguous reference to embedded stylesheet"
+ return root[0]
-cdef object RE_COMPILE
-RE_COMPILE = re.compile
+
+################################################################################
+# EXSLT regexp implementation
cdef class _ExsltRegExp:
cdef object _compile_map
@@ -571,7 +625,7 @@
py_flags = re.UNICODE
if ignore_case:
py_flags = py_flags | re.IGNORECASE
- rexp_compiled = RE_COMPILE(rexp, py_flags)
+ rexp_compiled = re.compile(rexp, py_flags)
python.PyDict_SetItem(self._compile_map, key, rexp_compiled)
return rexp_compiled
From scoder at codespeak.net Sat Sep 23 07:59:31 2006
From: scoder at codespeak.net (scoder at codespeak.net)
Date: Sat, 23 Sep 2006 07:59:31 +0200 (CEST)
Subject: [Lxml-checkins] r32600 - in lxml/trunk/src/lxml: . tests
Message-ID: <20060923055931.B47C410063@code0.codespeak.net>
Author: scoder
Date: Sat Sep 23 07:59:28 2006
New Revision: 32600
Modified:
lxml/trunk/src/lxml/objectify.pyx
lxml/trunk/src/lxml/tests/test_objectify.py
Log:
'x * StringElement' operation
Modified: lxml/trunk/src/lxml/objectify.pyx
==============================================================================
--- lxml/trunk/src/lxml/objectify.pyx (original)
+++ lxml/trunk/src/lxml/objectify.pyx Sat Sep 23 07:59:28 2006
@@ -635,6 +635,8 @@
def __mul__(self, other):
if isinstance(self, StringElement):
return textOf((self)._c_node) * _numericValueOf(other)
+ elif isinstance(other, StringElement):
+ return _numericValueOf(self) * textOf((other)._c_node)
else:
raise TypeError, "invalid types for * operator"
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 Sat Sep 23 07:59:28 2006
@@ -273,6 +273,28 @@
root.none = "test"
self.assert_(isinstance(root.none, objectify.StringElement))
+ def test_type_str_mul(self):
+ Element = self.Element
+ SubElement = self.etree.SubElement
+ root = Element("{objectified}root")
+ root.none = "test"
+
+ self.assertEquals("test" * 5, root.none * 5)
+ self.assertEquals(5 * "test", 5 * root.none)
+
+ self.assertRaises(TypeError, operator.mul, root.none, "honk")
+ self.assertRaises(TypeError, operator.mul, "honk", root.none)
+
+ def test_type_str_add(self):
+ Element = self.Element
+ SubElement = self.etree.SubElement
+ root = Element("{objectified}root")
+ root.none = "test"
+
+ s = "toast"
+ self.assertEquals("test" + s, root.none + s)
+ self.assertEquals(s + "test", s + root.none)
+
def test_data_element_str(self):
value = objectify.DataElement("test")
self.assert_(isinstance(value, objectify.StringElement))
From scoder at codespeak.net Sat Sep 23 08:00:47 2006
From: scoder at codespeak.net (scoder at codespeak.net)
Date: Sat, 23 Sep 2006 08:00:47 +0200 (CEST)
Subject: [Lxml-checkins] r32601 - lxml/trunk
Message-ID: <20060923060047.382BB10063@code0.codespeak.net>
Author: scoder
Date: Sat Sep 23 08:00:43 2006
New Revision: 32601
Modified:
lxml/trunk/CHANGES.txt
Log:
'x * StringElement' operation
Modified: lxml/trunk/CHANGES.txt
==============================================================================
--- lxml/trunk/CHANGES.txt (original)
+++ lxml/trunk/CHANGES.txt Sat Sep 23 08:00:43 2006
@@ -13,6 +13,8 @@
Bugs fixed
----------
+* 'integer * objectify.StringElement' operation was not supported
+
1.1.1 (2006-09-21)
==================
From scoder at codespeak.net Sat Sep 23 08:01:57 2006
From: scoder at codespeak.net (scoder at codespeak.net)
Date: Sat, 23 Sep 2006 08:01:57 +0200 (CEST)
Subject: [Lxml-checkins] r32602 - in lxml/branch/lxml-1.1: . src/lxml
src/lxml/tests
Message-ID: <20060923060157.21AE310063@code0.codespeak.net>
Author: scoder
Date: Sat Sep 23 08:01:53 2006
New Revision: 32602
Modified:
lxml/branch/lxml-1.1/CHANGES.txt
lxml/branch/lxml-1.1/src/lxml/objectify.pyx
lxml/branch/lxml-1.1/src/lxml/tests/test_objectify.py
Log:
'x * StringElement' operation
Modified: lxml/branch/lxml-1.1/CHANGES.txt
==============================================================================
--- lxml/branch/lxml-1.1/CHANGES.txt (original)
+++ lxml/branch/lxml-1.1/CHANGES.txt Sat Sep 23 08:01:53 2006
@@ -2,6 +2,19 @@
lxml changelog
==============
+=======
+current
+=======
+
+Features added
+--------------
+
+Bugs fixed
+----------
+
+* 'integer * objectify.StringElement' operation was not supported
+
+
1.1.1 (2006-09-21)
==================
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 Sat Sep 23 08:01:53 2006
@@ -635,6 +635,8 @@
def __mul__(self, other):
if isinstance(self, StringElement):
return textOf((self)._c_node) * _numericValueOf(other)
+ elif isinstance(other, StringElement):
+ return _numericValueOf(self) * textOf((other)._c_node)
else:
raise TypeError, "invalid types for * operator"
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 Sat Sep 23 08:01:53 2006
@@ -273,6 +273,28 @@
root.none = "test"
self.assert_(isinstance(root.none, objectify.StringElement))
+ def test_type_str_mul(self):
+ Element = self.Element
+ SubElement = self.etree.SubElement
+ root = Element("{objectified}root")
+ root.none = "test"
+
+ self.assertEquals("test" * 5, root.none * 5)
+ self.assertEquals(5 * "test", 5 * root.none)
+
+ self.assertRaises(TypeError, operator.mul, root.none, "honk")
+ self.assertRaises(TypeError, operator.mul, "honk", root.none)
+
+ def test_type_str_add(self):
+ Element = self.Element
+ SubElement = self.etree.SubElement
+ root = Element("{objectified}root")
+ root.none = "test"
+
+ s = "toast"
+ self.assertEquals("test" + s, root.none + s)
+ self.assertEquals(s + "test", s + root.none)
+
def test_data_element_str(self):
value = objectify.DataElement("test")
self.assert_(isinstance(value, objectify.StringElement))
From scoder at codespeak.net Mon Sep 25 11:14:38 2006
From: scoder at codespeak.net (scoder at codespeak.net)
Date: Mon, 25 Sep 2006 11:14:38 +0200 (CEST)
Subject: [Lxml-checkins] r32622 - in lxml/trunk: . src/lxml src/lxml/tests
Message-ID: <20060925091438.5C86B10074@code0.codespeak.net>
Author: scoder
Date: Mon Sep 25 11:14:35 2006
New Revision: 32622
Modified:
lxml/trunk/CHANGES.txt
lxml/trunk/src/lxml/apihelpers.pxi
lxml/trunk/src/lxml/tests/test_etree.py
Log:
fix: skip over xinclude nodes when collecting text nodes
Modified: lxml/trunk/CHANGES.txt
==============================================================================
--- lxml/trunk/CHANGES.txt (original)
+++ lxml/trunk/CHANGES.txt Mon Sep 25 11:14:35 2006
@@ -13,6 +13,8 @@
Bugs fixed
----------
+* Show text xincluded between text nodes correctly in .text and .tail
+
* 'integer * objectify.StringElement' operation was not supported
Modified: lxml/trunk/src/lxml/apihelpers.pxi
==============================================================================
--- lxml/trunk/src/lxml/apihelpers.pxi (original)
+++ lxml/trunk/src/lxml/apihelpers.pxi Mon Sep 25 11:14:35 2006
@@ -233,12 +233,12 @@
# check for multiple text nodes
scount = 0
text = NULL
- c_node_cur = c_node
- while c_node_cur is not NULL and c_node_cur.type == tree.XML_TEXT_NODE:
+ c_node_cur = c_node = _textNodeOrSkip(c_node)
+ while c_node_cur is not NULL:
if c_node_cur.content[0] != c'\0':
text = c_node_cur.content
scount = scount + 1
- c_node_cur = c_node_cur.next
+ c_node_cur = _textNodeOrSkip(c_node_cur.next)
# handle two most common cases first
if text is NULL:
@@ -251,9 +251,9 @@
# the rest is not performance critical anymore
result = ''
- while c_node is not NULL and c_node.type == tree.XML_TEXT_NODE:
+ while c_node is not NULL:
result = result + c_node.content
- c_node = c_node.next
+ c_node = _textNodeOrSkip(c_node.next)
return funicode(result)
cdef void _removeText(xmlNode* c_node):
@@ -262,10 +262,10 @@
Start removing at c_node.
"""
cdef xmlNode* c_next
- while c_node is not NULL and c_node.type == tree.XML_TEXT_NODE:
- c_next = c_node.next
+ c_node = _textNodeOrSkip(c_node)
+ while c_node is not NULL:
+ c_next = _textNodeOrSkip(c_node.next)
tree.xmlUnlinkNode(c_node)
- # XXX cannot safely free in case of direct text node proxies..
tree.xmlFreeNode(c_node)
c_node = c_next
@@ -333,6 +333,23 @@
c_child = c_child.prev
return NULL
+cdef xmlNode* _textNodeOrSkip(xmlNode* c_node):
+ """Return the node if it's a text node. Skip over ignorable nodes in a
+ series of text nodes. Return NULL if a non-ignorable node is found.
+
+ This is used to skip over XInclude nodes when collecting adjacent text
+ nodes.
+ """
+ while c_node is not NULL:
+ if c_node.type == tree.XML_TEXT_NODE:
+ return c_node
+ elif c_node.type == tree.XML_XINCLUDE_START or \
+ c_node.type == tree.XML_XINCLUDE_END:
+ c_node = c_node.next
+ else:
+ return NULL
+ return NULL
+
cdef xmlNode* _nextElement(xmlNode* c_node):
"""Given a node, find the next sibling that is an element.
"""
@@ -410,8 +427,9 @@
cdef xmlNode* c_next
# tail support: look for any text nodes trailing this node and
# move them too
- while c_tail is not NULL and c_tail.type == tree.XML_TEXT_NODE:
- c_next = c_tail.next
+ c_tail = _textNodeOrSkip(c_tail)
+ while c_tail is not NULL:
+ c_next = _textNodeOrSkip(c_tail.next)
tree.xmlUnlinkNode(c_tail)
tree.xmlAddNextSibling(c_target, c_tail)
c_target = c_tail
@@ -421,14 +439,15 @@
cdef xmlNode* c_new_tail
# tail copying support: look for any text nodes trailing this node and
# copy it to the target node
- while c_tail is not NULL and c_tail.type == tree.XML_TEXT_NODE:
+ c_tail = _textNodeOrSkip(c_tail)
+ while c_tail is not NULL:
if c_target.doc is not c_tail.doc:
c_new_tail = tree.xmlDocCopyNode(c_tail, c_target.doc, 0)
else:
c_new_tail = tree.xmlCopyNode(c_tail, 0)
tree.xmlAddNextSibling(c_target, c_new_tail)
c_target = c_new_tail
- c_tail = c_tail.next
+ c_tail = _textNodeOrSkip(c_tail.next)
cdef xmlNode* _deleteSlice(xmlNode* c_node, Py_ssize_t start, Py_ssize_t stop):
"""Delete slice, starting with c_node, start counting at start, end at stop.
Modified: lxml/trunk/src/lxml/tests/test_etree.py
==============================================================================
--- lxml/trunk/src/lxml/tests/test_etree.py (original)
+++ lxml/trunk/src/lxml/tests/test_etree.py Mon Sep 25 11:14:35 2006
@@ -1195,6 +1195,22 @@
self.assertEquals(
'a',
tree.getroot()[1].tag)
+
+ def test_xinclude_text(self):
+ filename = fileInTestDir('test_broken.xml')
+ root = etree.XML('''\
+
+
+
+ ''' % filename)
+ old_text = root.text
+ content = open(filename).read()
+ old_tail = root[0].tail
+
+ etree.ElementTree(root).xinclude()
+ self.assertEquals(old_text + content + old_tail,
+ root.text)
+
class ETreeC14NTestCase(HelperTestCase):
def test_c14n(self):
From scoder at codespeak.net Mon Sep 25 11:15:15 2006
From: scoder at codespeak.net (scoder at codespeak.net)
Date: Mon, 25 Sep 2006 11:15:15 +0200 (CEST)
Subject: [Lxml-checkins] r32623 - in lxml/branch/lxml-1.1: . src/lxml
src/lxml/tests
Message-ID: <20060925091515.4CE4110074@code0.codespeak.net>
Author: scoder
Date: Mon Sep 25 11:15:13 2006
New Revision: 32623
Modified:
lxml/branch/lxml-1.1/CHANGES.txt
lxml/branch/lxml-1.1/src/lxml/apihelpers.pxi
lxml/branch/lxml-1.1/src/lxml/tests/test_etree.py
Log:
fix: skip over xinclude nodes when collecting text nodes
Modified: lxml/branch/lxml-1.1/CHANGES.txt
==============================================================================
--- lxml/branch/lxml-1.1/CHANGES.txt (original)
+++ lxml/branch/lxml-1.1/CHANGES.txt Mon Sep 25 11:15:13 2006
@@ -12,6 +12,8 @@
Bugs fixed
----------
+* Show text xincluded between text nodes correctly in .text and .tail
+
* 'integer * objectify.StringElement' operation was not supported
Modified: lxml/branch/lxml-1.1/src/lxml/apihelpers.pxi
==============================================================================
--- lxml/branch/lxml-1.1/src/lxml/apihelpers.pxi (original)
+++ lxml/branch/lxml-1.1/src/lxml/apihelpers.pxi Mon Sep 25 11:15:13 2006
@@ -233,12 +233,12 @@
# check for multiple text nodes
scount = 0
text = NULL
- c_node_cur = c_node
- while c_node_cur is not NULL and c_node_cur.type == tree.XML_TEXT_NODE:
+ c_node_cur = c_node = _textNodeOrSkip(c_node)
+ while c_node_cur is not NULL:
if c_node_cur.content[0] != c'\0':
text = c_node_cur.content
scount = scount + 1
- c_node_cur = c_node_cur.next
+ c_node_cur = _textNodeOrSkip(c_node_cur.next)
# handle two most common cases first
if text is NULL:
@@ -251,9 +251,9 @@
# the rest is not performance critical anymore
result = ''
- while c_node is not NULL and c_node.type == tree.XML_TEXT_NODE:
+ while c_node is not NULL:
result = result + c_node.content
- c_node = c_node.next
+ c_node = _textNodeOrSkip(c_node.next)
return funicode(result)
cdef void _removeText(xmlNode* c_node):
@@ -262,10 +262,10 @@
Start removing at c_node.
"""
cdef xmlNode* c_next
- while c_node is not NULL and c_node.type == tree.XML_TEXT_NODE:
- c_next = c_node.next
+ c_node = _textNodeOrSkip(c_node)
+ while c_node is not NULL:
+ c_next = _textNodeOrSkip(c_node.next)
tree.xmlUnlinkNode(c_node)
- # XXX cannot safely free in case of direct text node proxies..
tree.xmlFreeNode(c_node)
c_node = c_next
@@ -333,6 +333,23 @@
c_child = c_child.prev
return NULL
+cdef xmlNode* _textNodeOrSkip(xmlNode* c_node):
+ """Return the node if it's a text node. Skip over ignorable nodes in a
+ series of text nodes. Return NULL if a non-ignorable node is found.
+
+ This is used to skip over XInclude nodes when collecting adjacent text
+ nodes.
+ """
+ while c_node is not NULL:
+ if c_node.type == tree.XML_TEXT_NODE:
+ return c_node
+ elif c_node.type == tree.XML_XINCLUDE_START or \
+ c_node.type == tree.XML_XINCLUDE_END:
+ c_node = c_node.next
+ else:
+ return NULL
+ return NULL
+
cdef xmlNode* _nextElement(xmlNode* c_node):
"""Given a node, find the next sibling that is an element.
"""
@@ -410,8 +427,9 @@
cdef xmlNode* c_next
# tail support: look for any text nodes trailing this node and
# move them too
- while c_tail is not NULL and c_tail.type == tree.XML_TEXT_NODE:
- c_next = c_tail.next
+ c_tail = _textNodeOrSkip(c_tail)
+ while c_tail is not NULL:
+ c_next = _textNodeOrSkip(c_tail.next)
tree.xmlUnlinkNode(c_tail)
tree.xmlAddNextSibling(c_target, c_tail)
c_target = c_tail
@@ -421,14 +439,15 @@
cdef xmlNode* c_new_tail
# tail copying support: look for any text nodes trailing this node and
# copy it to the target node
- while c_tail is not NULL and c_tail.type == tree.XML_TEXT_NODE:
+ c_tail = _textNodeOrSkip(c_tail)
+ while c_tail is not NULL:
if c_target.doc is not c_tail.doc:
c_new_tail = tree.xmlDocCopyNode(c_tail, c_target.doc, 0)
else:
c_new_tail = tree.xmlCopyNode(c_tail, 0)
tree.xmlAddNextSibling(c_target, c_new_tail)
c_target = c_new_tail
- c_tail = c_tail.next
+ c_tail = _textNodeOrSkip(c_tail.next)
cdef xmlNode* _deleteSlice(xmlNode* c_node, Py_ssize_t start, Py_ssize_t stop):
"""Delete slice, starting with c_node, start counting at start, end at stop.
Modified: lxml/branch/lxml-1.1/src/lxml/tests/test_etree.py
==============================================================================
--- lxml/branch/lxml-1.1/src/lxml/tests/test_etree.py (original)
+++ lxml/branch/lxml-1.1/src/lxml/tests/test_etree.py Mon Sep 25 11:15:13 2006
@@ -1195,6 +1195,22 @@
self.assertEquals(
'a',
tree.getroot()[1].tag)
+
+ def test_xinclude_text(self):
+ filename = fileInTestDir('test_broken.xml')
+ root = etree.XML('''\
+
+
+
+ ''' % filename)
+ old_text = root.text
+ content = open(filename).read()
+ old_tail = root[0].tail
+
+ etree.ElementTree(root).xinclude()
+ self.assertEquals(old_text + content + old_tail,
+ root.text)
+
class ETreeC14NTestCase(HelperTestCase):
def test_c14n(self):
From scoder at codespeak.net Wed Sep 27 08:45:34 2006
From: scoder at codespeak.net (scoder at codespeak.net)
Date: Wed, 27 Sep 2006 08:45:34 +0200 (CEST)
Subject: [Lxml-checkins] r32660 - lxml/trunk/doc
Message-ID: <20060927064534.644D210075@code0.codespeak.net>
Author: scoder
Date: Wed Sep 27 08:45:32 2006
New Revision: 32660
Modified:
lxml/trunk/doc/build.txt
Log:
mention possible requirement of wsock32.dll for objectify build on windows
Modified: lxml/trunk/doc/build.txt
==============================================================================
--- lxml/trunk/doc/build.txt (original)
+++ lxml/trunk/doc/build.txt Wed Sep 27 08:45:32 2006
@@ -215,7 +215,11 @@
The ``_a`` part of the library names means that we are linking statically
against the named library files. If you want to use dynamic libraries, you
-need to link against the DLL version of the libraries.
+need to link against the DLL version of the libraries. As `Ashish Kulkarni`_
+notes, you might have to add the standard Windows library ``wsock32.dll`` to
+the above list of libraries to make ``lxml.objectify`` compile.
+
+.. _`Ashish Kulkarni`:
Now you should be able to pass the ``--static`` option to setup.py and
everything should work well. Try calling::
From scoder at codespeak.net Wed Sep 27 08:45:47 2006
From: scoder at codespeak.net (scoder at codespeak.net)
Date: Wed, 27 Sep 2006 08:45:47 +0200 (CEST)
Subject: [Lxml-checkins] r32661 - lxml/trunk/src/lxml
Message-ID: <20060927064547.0000D10075@code0.codespeak.net>
Author: scoder
Date: Wed Sep 27 08:45:46 2006
New Revision: 32661
Modified:
lxml/trunk/src/lxml/etree.pyx
Log:
doc typo
Modified: lxml/trunk/src/lxml/etree.pyx
==============================================================================
--- lxml/trunk/src/lxml/etree.pyx (original)
+++ lxml/trunk/src/lxml/etree.pyx Wed Sep 27 08:45:46 2006
@@ -583,7 +583,7 @@
Returns True or False, depending on whether validation
succeeded.
- Note: If you are going to applyt he same XML Schema against
+ Note: If you are going to apply the same XML Schema against
multiple documents, it is more efficient to use the XMLSchema
class directly.
"""
From scoder at codespeak.net Wed Sep 27 08:46:55 2006
From: scoder at codespeak.net (scoder at codespeak.net)
Date: Wed, 27 Sep 2006 08:46:55 +0200 (CEST)
Subject: [Lxml-checkins] r32662 - in lxml/trunk/src/lxml: . tests
Message-ID: <20060927064655.49E6010075@code0.codespeak.net>
Author: scoder
Date: Wed Sep 27 08:46:53 2006
New Revision: 32662
Modified:
lxml/trunk/src/lxml/parser.pxi
lxml/trunk/src/lxml/tests/test_htmlparser.py
lxml/trunk/src/lxml/xmlparser.pxd
Log:
prevent CDATA sections from appearing in HTML tree
Modified: lxml/trunk/src/lxml/parser.pxi
==============================================================================
--- lxml/trunk/src/lxml/parser.pxi (original)
+++ lxml/trunk/src/lxml/parser.pxi Wed Sep 27 08:46:53 2006
@@ -368,6 +368,9 @@
self._parser_ctxt = pctxt
if pctxt is NULL:
raise ParserError, "Failed to create parser context"
+ if pctxt.sax != NULL:
+ # hard switch-off for CDATA nodes => makes them plain text
+ pctxt.sax.cdataBlock = NULL
if thread is None or self._parser_type == LXML_ITERPARSE_PARSER:
# no threading
self._lockParser = self.__dummy
Modified: lxml/trunk/src/lxml/tests/test_htmlparser.py
==============================================================================
--- lxml/trunk/src/lxml/tests/test_htmlparser.py (original)
+++ lxml/trunk/src/lxml/tests/test_htmlparser.py Wed Sep 27 08:46:53 2006
@@ -51,6 +51,12 @@
self.assertEqual(self.etree.tostring(element),
self.html_str)
+ def test_module_HTML_cdata(self):
+ # by default, libxml2 generates CDATA nodes for