[Lxml-checkins] r49400 - in lxml/trunk: . src/lxml src/lxml/tests

scoder at codespeak.net scoder at codespeak.net
Wed Dec 5 19:30:47 CET 2007


Author: scoder
Date: Wed Dec  5 19:30:47 2007
New Revision: 49400

Modified:
   lxml/trunk/TODO.txt
   lxml/trunk/selftest.py
   lxml/trunk/src/lxml/parser.pxi
   lxml/trunk/src/lxml/tests/test_elementtree.py
   lxml/trunk/src/lxml/xmlerror.pxi
   lxml/trunk/src/lxml/xslt.pxi
Log:
properties 'position' and 'code' on ParseError exceptions, small fixes to XSLT error reporting

Modified: lxml/trunk/TODO.txt
==============================================================================
--- lxml/trunk/TODO.txt	(original)
+++ lxml/trunk/TODO.txt	Wed Dec  5 19:30:47 2007
@@ -54,6 +54,6 @@
 
 * clean support for entities (is the Entity element class enough?)
 
-* implement 'position' property on ParseError exception
-
-* rewrite iterparse() to accept a parser as argument instead of being one
+* rewrite iterparse() to accept a parser as argument instead of being
+  one (or maybe not: iterparse() can't deal with all parser options
+  anyway).

Modified: lxml/trunk/selftest.py
==============================================================================
--- lxml/trunk/selftest.py	(original)
+++ lxml/trunk/selftest.py	Wed Dec  5 19:30:47 2007
@@ -653,7 +653,7 @@
     except ET.ParseError:
         return sys.exc_value
 
-# doesn't work with lxml.etree
+# doesn't work with lxml.etree -> different positions
 del error
 
 def namespace():

Modified: lxml/trunk/src/lxml/parser.pxi
==============================================================================
--- lxml/trunk/src/lxml/parser.pxi	(original)
+++ lxml/trunk/src/lxml/parser.pxi	Wed Dec  5 19:30:47 2007
@@ -13,7 +13,10 @@
 class XMLSyntaxError(ParseError):
     """Syntax error while parsing an XML document.
     """
-    pass
+    def __init__(self, message, code, line, column):
+        ParseError.__init__(self, message)        
+        self.position = (line, column)
+        self.code = code
 
 class ParserError(LxmlError):
     """Internal lxml parser error.
@@ -449,7 +452,6 @@
         context._initParserContext(c_ctxt)
     context._error_log = _ErrorLog()
 
-
 cdef int _raiseParseError(xmlparser.xmlParserCtxt* ctxt, filename,
                           _ErrorLog error_log) except 0:
     if filename is not None and \
@@ -458,18 +460,21 @@
             message = "Error reading file '%s': %s" % (
                 filename, (ctxt.lastError.message).strip())
         else:
-            message = "Error reading file '%s'" % filename
-        raise IOError, message
+            message = "Error reading '%s'" % filename
+        raise IOError(message)
     elif error_log:
-        raise XMLSyntaxError, error_log._buildExceptionMessage(
-            "Document is not well formed")
+        raise error_log._buildParseException(
+            XMLSyntaxError, "Document is not well formed")
     elif ctxt.lastError.message is not NULL:
         message = (ctxt.lastError.message).strip()
+        code = ctxt.lastError.code
+        line = ctxt.lastError.line
+        column = ctxt.lastError.int2
         if ctxt.lastError.line > 0:
-            message = "line %d: %s" % (ctxt.lastError.line, message)
-        raise XMLSyntaxError, message
+            message = "line %d: %s" % (line, message)
+        raise XMLSyntaxError(message, code, line, column)
     else:
-        raise XMLSyntaxError
+        raise XMLSyntaxError(None, xmlerror.XML_ERR_INTERNAL_ERROR, 0, 0)
 
 cdef xmlDoc* _handleParseResult(_ParserContext context,
                                 xmlparser.xmlParserCtxt* c_ctxt,
@@ -931,7 +936,8 @@
         cdef xmlDoc* c_doc
         cdef _Document doc
         if not self._feed_parser_running:
-            raise XMLSyntaxError, "no element found"
+            raise XMLSyntaxError("no element found",
+                                 xmlerror.XML_ERR_INTERNAL_ERROR, 0, 0)
 
         context = self._getPushParserContext()
         pctxt = context._c_ctxt

Modified: lxml/trunk/src/lxml/tests/test_elementtree.py
==============================================================================
--- lxml/trunk/src/lxml/tests/test_elementtree.py	(original)
+++ lxml/trunk/src/lxml/tests/test_elementtree.py	Wed Dec  5 19:30:47 2007
@@ -3008,6 +3008,17 @@
 
         self.assertRaises(ParseError, parser.close)
 
+    def test_feed_parser_error_position(self):
+        ParseError = self.etree.ParseError
+        parser = self.etree.XMLParser()
+        try:
+            parser.close()
+        except ParseError, e:
+            self.assertNotEquals(None, e.code)
+            self.assertNotEquals(0, e.code)
+            self.assert_(isinstance(e.position, tuple))
+            self.assert_(e.position >= (0, 0))
+
     # parser target interface
 
     def test_parser_target_tag(self):

Modified: lxml/trunk/src/lxml/xmlerror.pxi
==============================================================================
--- lxml/trunk/src/lxml/xmlerror.pxi	(original)
+++ lxml/trunk/src/lxml/xmlerror.pxi	Wed Dec  5 19:30:47 2007
@@ -128,6 +128,28 @@
         if is_error:
             self.last_error = entry
 
+    cdef _buildParseException(self, exctype, default_message):
+        code = xmlerror.XML_ERR_INTERNAL_ERROR
+        if self._first_error is None:
+            return exctype(default_message, code, 0, 0)
+        if self._first_error is None or \
+                self._first_error.message is None or \
+                not self._first_error.message:
+            message = default_message
+            line = 0
+            column = 0
+        else:
+            message = self._first_error.message
+            code = self._first_error.type
+            line = self._first_error.line
+            column = self._first_error.column
+            if line > 0:
+                if column > 0:
+                    message = "%s, line %d, column %d" % (message, line, column)
+                else:
+                    message = "%s, line %d" % (message, line)
+        return exctype(message, code, line, column)
+
     cdef _buildExceptionMessage(self, default_message):
         if self._first_error is None:
             return default_message
@@ -393,7 +415,9 @@
     cdef char* c_message
     cdef char* c_element
     cdef int i, text_size, element_size
-    if __DEBUG == 0 or msg is NULL or msg[0] == c'\n':
+    if __DEBUG == 0 or msg is NULL:
+        return
+    if msg[0] == c'\n' or msg[0] == c'\0':
         return
 
     cstd.va_start(args, msg)
@@ -401,18 +425,19 @@
         c_text = cstd.va_charptr(args)
     else:
         c_text = NULL
-    if cstd.strstr(msg, 'file %s') is not NULL:
+    if cstd.strstr(msg, 'file %s'):
         c_error.file = cstd.va_charptr(args)
-        if c_error.file is not NULL and cstd.strlen(c_error.file) > 0:
-            if cstd.strncmp(c_error.file, 'XSLT:', 5) == 0:
-                c_error.file = '<xslt>'
+        if c_error.file and \
+                cstd.strncmp(c_error.file,
+                            'string://__STRING__XSLT', 23) == 0:
+            c_error.file = '<xslt>'
     else:
         c_error.file = NULL
-    if cstd.strstr(msg, 'line %d') is not NULL:
+    if cstd.strstr(msg, 'line %d'):
         c_error.line = cstd.va_int(args)
     else:
         c_error.line = -1
-    if cstd.strstr(msg, 'element %s') is not NULL:
+    if cstd.strstr(msg, 'element %s'):
         c_element = cstd.va_charptr(args)
     else:
         c_element = NULL
@@ -420,7 +445,17 @@
 
     c_message = NULL
     if c_text is NULL:
-        c_error.message = ''
+        if c_element is not NULL and \
+                cstd.strchr(msg, c'%') == cstd.strrchr(msg, c'%'):
+            # special case: a single occurrence of 'element %s'
+            text_size    = cstd.strlen(msg)
+            element_size = cstd.strlen(c_element)
+            c_message = <char*>cstd.malloc(
+                (text_size + element_size + 1) * sizeof(char))
+            cstd.sprintf(c_message, msg, c_element)
+            c_error.message = c_message
+        else:
+            c_error.message = ''
     elif c_element is NULL:
         c_error.message = c_text
     else:
@@ -439,8 +474,7 @@
     _forwardError(c_log_handler, &c_error)
 
     if c_message is not NULL:
-        cstd.free(c_error.message)
-
+        cstd.free(c_message)
 
 ################################################################################
 ## 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	Wed Dec  5 19:30:47 2007
@@ -273,10 +273,8 @@
                  access_control=None):
         cdef xslt.xsltStylesheet* c_style
         cdef xmlDoc* c_doc
-        cdef xmlDoc* fake_c_doc
         cdef _Document doc
         cdef _Element root_node
-        cdef _ExsltRegExp _regexp 
 
         doc = _documentOrRaise(xslt_input)
         root_node = _rootNodeOrRaise(xslt_input)
@@ -308,10 +306,13 @@
             tree.xmlFreeDoc(c_doc)
             self._xslt_resolver_context._raise_if_stored()
             # last error seems to be the most accurate here
-            if self._error_log.last_error is not None:
-                raise XSLTParseError, self._error_log.last_error.message
+            if self._error_log.last_error is not None and \
+                    self._error_log.last_error.message:
+                raise XSLTParseError(self._error_log.last_error.message)
             else:
-                raise XSLTParseError, "Cannot parse stylesheet"
+                raise XSLTParseError(
+                    self._error_log._buildExceptionMessage(
+                        "Cannot parse stylesheet"))
 
         c_doc._private = NULL # no longer used!
         self._c_style = c_style


More information about the lxml-checkins mailing list