summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_xml_etree.py33
-rw-r--r--Misc/NEWS.d/next/Library/2017-09-13-19-55-35.bpo-31544.beTh6t.rst2
-rw-r--r--Modules/_elementtree.c35
3 files changed, 68 insertions, 2 deletions
diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py
index e466867b7c..c75d55f05c 100644
--- a/Lib/test/test_xml_etree.py
+++ b/Lib/test/test_xml_etree.py
@@ -136,6 +136,13 @@ def python_only(test):
return test(*args)
return wrapper
+def cet_only(test):
+ def wrapper(*args):
+ if ET is pyET:
+ raise unittest.SkipTest('only for the C version')
+ return test(*args)
+ return wrapper
+
# --------------------------------------------------------------------
# element tree tests
@@ -2229,6 +2236,32 @@ class TreeBuilderTest(unittest.TestCase):
('html', '-//W3C//DTD XHTML 1.0 Transitional//EN',
'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'))
+ @cet_only # PyET does not look up the attributes in XMLParser().__init__()
+ def test_builder_lookup_errors(self):
+ class RaisingBuilder(object):
+ def __init__(self, raise_in=None, what=ValueError):
+ self.raise_in = raise_in
+ self.what = what
+
+ def __getattr__(self, name):
+ if name == self.raise_in:
+ raise self.what(self.raise_in)
+ def handle(*args):
+ pass
+ return handle
+
+ ET.XMLParser(target=RaisingBuilder())
+ # cET also checks for 'close' and 'doctype', PyET does it only at need
+ for event in ('start', 'data', 'end', 'comment', 'pi'):
+ with self.assertRaises(ValueError):
+ ET.XMLParser(target=RaisingBuilder(event))
+
+ ET.XMLParser(target=RaisingBuilder(what=AttributeError))
+ for event in ('start', 'data', 'end', 'comment', 'pi'):
+ parser = ET.XMLParser(target=RaisingBuilder(event, what=AttributeError))
+ parser.feed(self.sample1)
+ self.assertIsNone(parser.close())
+
class XMLParserTest(unittest.TestCase):
sample1 = b'<file><line>22</line></file>'
diff --git a/Misc/NEWS.d/next/Library/2017-09-13-19-55-35.bpo-31544.beTh6t.rst b/Misc/NEWS.d/next/Library/2017-09-13-19-55-35.bpo-31544.beTh6t.rst
new file mode 100644
index 0000000000..9ea3599ee0
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2017-09-13-19-55-35.bpo-31544.beTh6t.rst
@@ -0,0 +1,2 @@
+The C accelerator module of ElementTree ignored exceptions raised when
+looking up TreeBuilder target methods in XMLParser().
diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c
index 574559c631..7f0e609340 100644
--- a/Modules/_elementtree.c
+++ b/Modules/_elementtree.c
@@ -2510,6 +2510,18 @@ expat_unknown_encoding_handler(XMLParserObject *self, const XML_Char *name,
/* -------------------------------------------------------------------- */
/* constructor and destructor */
+static int
+ignore_attribute_error(PyObject *value)
+{
+ if (value == NULL) {
+ if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
+ return -1;
+ }
+ PyErr_Clear();
+ }
+ return 0;
+}
+
static PyObject*
xmlparser(PyObject* self_, PyObject* args, PyObject* kw)
{
@@ -2578,14 +2590,33 @@ xmlparser(PyObject* self_, PyObject* args, PyObject* kw)
self->target = target;
self->handle_xml = PyObject_GetAttrString(target, "xml");
+ if (ignore_attribute_error(self->handle_xml)) {
+ return NULL;
+ }
self->handle_start = PyObject_GetAttrString(target, "start");
+ if (ignore_attribute_error(self->handle_start)) {
+ return NULL;
+ }
self->handle_data = PyObject_GetAttrString(target, "data");
+ if (ignore_attribute_error(self->handle_data)) {
+ return NULL;
+ }
self->handle_end = PyObject_GetAttrString(target, "end");
+ if (ignore_attribute_error(self->handle_end)) {
+ return NULL;
+ }
self->handle_comment = PyObject_GetAttrString(target, "comment");
+ if (ignore_attribute_error(self->handle_comment)) {
+ return NULL;
+ }
self->handle_pi = PyObject_GetAttrString(target, "pi");
+ if (ignore_attribute_error(self->handle_pi)) {
+ return NULL;
+ }
self->handle_close = PyObject_GetAttrString(target, "close");
-
- PyErr_Clear();
+ if (ignore_attribute_error(self->handle_close)) {
+ return NULL;
+ }
/* configure parser */
EXPAT(SetUserData)(self->parser, self);