diff options
author | Stefan Krah <skrah@bytereef.org> | 2012-03-05 09:50:11 (GMT) |
---|---|---|
committer | Stefan Krah <skrah@bytereef.org> | 2012-03-05 09:50:11 (GMT) |
commit | 49ab14f4529e06ecd7d6804ea80f62ab6094a386 (patch) | |
tree | 6513842dc27e55937c2a0fcb91e1d22213137e72 | |
parent | fcbb4169b982ce06c5701ad18898084dfa569598 (diff) | |
parent | 682c979871b42cd21856735c5900f9bee832bfb1 (diff) | |
download | cpython-49ab14f4529e06ecd7d6804ea80f62ab6094a386.zip cpython-49ab14f4529e06ecd7d6804ea80f62ab6094a386.tar.gz cpython-49ab14f4529e06ecd7d6804ea80f62ab6094a386.tar.bz2 |
Merge.
-rw-r--r-- | Lib/test/test_logging.py | 2 | ||||
-rw-r--r-- | Lib/test/test_xml_etree.py | 149 | ||||
-rw-r--r-- | Lib/xml/etree/ElementTree.py | 81 | ||||
-rw-r--r-- | Misc/NEWS | 4 | ||||
-rw-r--r-- | Modules/_elementtree.c | 23 |
5 files changed, 149 insertions, 110 deletions
diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 92e6994..b490b6e 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -3651,6 +3651,8 @@ class TimedRotatingFileHandlerTest(BaseFileTest): def test_rollover(self): fh = logging.handlers.TimedRotatingFileHandler(self.fn, 'S', backupCount=1) + fmt = logging.Formatter('%(asctime)s %(message)s') + fh.setFormatter(fmt) r = logging.makeLogRecord({'msg': 'testing'}) fh.emit(r) self.assertLogFile(self.fn) diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py index 869a159..b9230b7 100644 --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -1855,6 +1855,102 @@ def check_issue10777(): # -------------------------------------------------------------------- +class ElementTreeTest(unittest.TestCase): + + def test_istype(self): + self.assertIsInstance(ET.ParseError, type) + self.assertIsInstance(ET.QName, type) + self.assertIsInstance(ET.ElementTree, type) + self.assertIsInstance(ET.Element, type) + # XXX issue 14128 with C ElementTree + # self.assertIsInstance(ET.TreeBuilder, type) + # self.assertIsInstance(ET.XMLParser, type) + + def test_Element_subclass_trivial(self): + class MyElement(ET.Element): + pass + + mye = MyElement('foo') + self.assertIsInstance(mye, ET.Element) + self.assertIsInstance(mye, MyElement) + self.assertEqual(mye.tag, 'foo') + + def test_Element_subclass_constructor(self): + class MyElement(ET.Element): + def __init__(self, tag, attrib={}, **extra): + super(MyElement, self).__init__(tag + '__', attrib, **extra) + + mye = MyElement('foo', {'a': 1, 'b': 2}, c=3, d=4) + self.assertEqual(mye.tag, 'foo__') + self.assertEqual(sorted(mye.items()), + [('a', 1), ('b', 2), ('c', 3), ('d', 4)]) + + def test_Element_subclass_new_method(self): + class MyElement(ET.Element): + def newmethod(self): + return self.tag + + mye = MyElement('joe') + self.assertEqual(mye.newmethod(), 'joe') + + +class TreeBuilderTest(unittest.TestCase): + + sample1 = ('<!DOCTYPE html PUBLIC' + ' "-//W3C//DTD XHTML 1.0 Transitional//EN"' + ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' + '<html>text</html>') + + def test_dummy_builder(self): + class BaseDummyBuilder: + def close(self): + return 42 + + class DummyBuilder(BaseDummyBuilder): + data = start = end = lambda *a: None + + parser = ET.XMLParser(target=DummyBuilder()) + parser.feed(self.sample1) + self.assertEqual(parser.close(), 42) + + parser = ET.XMLParser(target=BaseDummyBuilder()) + parser.feed(self.sample1) + self.assertEqual(parser.close(), 42) + + parser = ET.XMLParser(target=object()) + parser.feed(self.sample1) + self.assertIsNone(parser.close()) + + + @unittest.expectedFailure # XXX issue 14007 with C ElementTree + def test_doctype(self): + class DoctypeParser: + _doctype = None + + def doctype(self, name, pubid, system): + self._doctype = (name, pubid, system) + + def close(self): + return self._doctype + + parser = ET.XMLParser(target=DoctypeParser()) + parser.feed(self.sample1) + + self.assertEqual(parser.close(), + ('html', '-//W3C//DTD XHTML 1.0 Transitional//EN', + 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd')) + + +class NoAcceleratorTest(unittest.TestCase): + + # Test that the C accelerator was not imported for pyET + def test_correct_import_pyET(self): + self.assertEqual(pyET.Element.__module__, 'xml.etree.ElementTree') + self.assertEqual(pyET.SubElement.__module__, 'xml.etree.ElementTree') + +# -------------------------------------------------------------------- + + class CleanContext(object): """Provide default namespace mapping and path cache.""" checkwarnings = None @@ -1873,10 +1969,7 @@ class CleanContext(object): ("This method will be removed in future versions. " "Use .+ instead.", DeprecationWarning), ("This method will be removed in future versions. " - "Use .+ instead.", PendingDeprecationWarning), - # XMLParser.doctype() is deprecated. - ("This method of XMLParser is deprecated. Define doctype.. " - "method on the TreeBuilder target.", DeprecationWarning)) + "Use .+ instead.", PendingDeprecationWarning)) self.checkwarnings = support.check_warnings(*deprecations, quiet=quiet) def __enter__(self): @@ -1898,54 +1991,18 @@ class CleanContext(object): self.checkwarnings.__exit__(*args) -class TestAcceleratorNotImported(unittest.TestCase): - # Test that the C accelerator was not imported for pyET - def test_correct_import_pyET(self): - self.assertEqual(pyET.SubElement.__module__, 'xml.etree.ElementTree') - - -class TestElementClass(unittest.TestCase): - def test_Element_is_a_type(self): - self.assertIsInstance(ET.Element, type) - - def test_Element_subclass_trivial(self): - class MyElement(ET.Element): - pass - - mye = MyElement('foo') - self.assertIsInstance(mye, ET.Element) - self.assertIsInstance(mye, MyElement) - self.assertEqual(mye.tag, 'foo') - - def test_Element_subclass_constructor(self): - class MyElement(ET.Element): - def __init__(self, tag, attrib={}, **extra): - super(MyElement, self).__init__(tag + '__', attrib, **extra) - - mye = MyElement('foo', {'a': 1, 'b': 2}, c=3, d=4) - self.assertEqual(mye.tag, 'foo__') - self.assertEqual(sorted(mye.items()), - [('a', 1), ('b', 2), ('c', 3), ('d', 4)]) - - def test_Element_subclass_new_method(self): - class MyElement(ET.Element): - def newmethod(self): - return self.tag - - mye = MyElement('joe') - self.assertEqual(mye.newmethod(), 'joe') - - def test_main(module=pyET): from test import test_xml_etree - # Run the tests specific to the Python implementation - support.run_unittest(TestAcceleratorNotImported) - # The same doctests are used for both the Python and the C implementations test_xml_etree.ET = module - support.run_unittest(TestElementClass) + test_classes = [ElementTreeTest, TreeBuilderTest] + if module is pyET: + # Run the tests specific to the Python implementation + test_classes += [NoAcceleratorTest] + + support.run_unittest(*test_classes) # XXX the C module should give the same warnings as the Python module with CleanContext(quiet=(module is not pyET)): diff --git a/Lib/xml/etree/ElementTree.py b/Lib/xml/etree/ElementTree.py index a864fa5..1a25f9a 100644 --- a/Lib/xml/etree/ElementTree.py +++ b/Lib/xml/etree/ElementTree.py @@ -1511,24 +1511,30 @@ class XMLParser: self.target = self._target = target self._error = expat.error self._names = {} # name memo cache - # callbacks + # main callbacks parser.DefaultHandlerExpand = self._default - parser.StartElementHandler = self._start - parser.EndElementHandler = self._end - parser.CharacterDataHandler = self._data - # optional callbacks - parser.CommentHandler = self._comment - parser.ProcessingInstructionHandler = self._pi + if hasattr(target, 'start'): + parser.StartElementHandler = self._start + if hasattr(target, 'end'): + parser.EndElementHandler = self._end + if hasattr(target, 'data'): + parser.CharacterDataHandler = target.data + # miscellaneous callbacks + if hasattr(target, 'comment'): + parser.CommentHandler = target.comment + if hasattr(target, 'pi'): + parser.ProcessingInstructionHandler = target.pi # let expat do the buffering, if supported try: - self._parser.buffer_text = 1 + parser.buffer_text = 1 except AttributeError: pass # use new-style attribute handling, if supported try: - self._parser.ordered_attributes = 1 - self._parser.specified_attributes = 1 - parser.StartElementHandler = self._start_list + parser.ordered_attributes = 1 + parser.specified_attributes = 1 + if hasattr(target, 'start'): + parser.StartElementHandler = self._start_list except AttributeError: pass self._doctype = None @@ -1572,44 +1578,29 @@ class XMLParser: attrib[fixname(attrib_in[i])] = attrib_in[i+1] return self.target.start(tag, attrib) - def _data(self, text): - return self.target.data(text) - def _end(self, tag): return self.target.end(self._fixname(tag)) - def _comment(self, data): - try: - comment = self.target.comment - except AttributeError: - pass - else: - return comment(data) - - def _pi(self, target, data): - try: - pi = self.target.pi - except AttributeError: - pass - else: - return pi(target, data) - def _default(self, text): prefix = text[:1] if prefix == "&": # deal with undefined entities try: - self.target.data(self.entity[text[1:-1]]) + data_handler = self.target.data + except AttributeError: + return + try: + data_handler(self.entity[text[1:-1]]) except KeyError: from xml.parsers import expat err = expat.error( "undefined entity %s: line %d, column %d" % - (text, self._parser.ErrorLineNumber, - self._parser.ErrorColumnNumber) + (text, self.parser.ErrorLineNumber, + self.parser.ErrorColumnNumber) ) err.code = 11 # XML_ERROR_UNDEFINED_ENTITY - err.lineno = self._parser.ErrorLineNumber - err.offset = self._parser.ErrorColumnNumber + err.lineno = self.parser.ErrorLineNumber + err.offset = self.parser.ErrorColumnNumber raise err elif prefix == "<" and text[:9] == "<!DOCTYPE": self._doctype = [] # inside a doctype declaration @@ -1636,7 +1627,7 @@ class XMLParser: pubid = pubid[1:-1] if hasattr(self.target, "doctype"): self.target.doctype(name, pubid, system[1:-1]) - elif self.doctype is not self._XMLParser__doctype: + elif self.doctype != self._XMLParser__doctype: # warn about deprecated call self._XMLParser__doctype(name, pubid, system[1:-1]) self.doctype(name, pubid, system[1:-1]) @@ -1667,7 +1658,7 @@ class XMLParser: def feed(self, data): try: - self._parser.Parse(data, 0) + self.parser.Parse(data, 0) except self._error as v: self._raiseerror(v) @@ -1679,12 +1670,20 @@ class XMLParser: def close(self): try: - self._parser.Parse("", 1) # end of data + self.parser.Parse("", 1) # end of data except self._error as v: self._raiseerror(v) - tree = self.target.close() - del self.target, self._parser # get rid of circular references - return tree + try: + try: + close_handler = self.target.close + except AttributeError: + pass + else: + return close_handler() + finally: + # get rid of circular references + del self.parser, self._parser + del self.target, self._target # Import the C accelerators @@ -13,6 +13,10 @@ Core and Builtins Library ------- +- Issue #14007: Accept incomplete TreeBuilder objects (missing start, end, + data or close method) for the Python implementation as well. + Drop the no-op TreeBuilder().xml() method from the C implementation. + What's New in Python 3.3.0 Alpha 1? =================================== diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 179cadc..348fefc 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -1699,13 +1699,6 @@ treebuilder_dealloc(TreeBuilderObject* self) /* handlers */ LOCAL(PyObject*) -treebuilder_handle_xml(TreeBuilderObject* self, PyObject* encoding, - PyObject* standalone) -{ - Py_RETURN_NONE; -} - -LOCAL(PyObject*) treebuilder_handle_start(TreeBuilderObject* self, PyObject* tag, PyObject* attrib) { @@ -1976,22 +1969,10 @@ treebuilder_start(TreeBuilderObject* self, PyObject* args) return treebuilder_handle_start(self, tag, attrib); } -static PyObject* -treebuilder_xml(TreeBuilderObject* self, PyObject* args) -{ - PyObject* encoding; - PyObject* standalone; - if (!PyArg_ParseTuple(args, "OO:xml", &encoding, &standalone)) - return NULL; - - return treebuilder_handle_xml(self, encoding, standalone); -} - static PyMethodDef treebuilder_methods[] = { {"data", (PyCFunction) treebuilder_data, METH_VARARGS}, {"start", (PyCFunction) treebuilder_start, METH_VARARGS}, {"end", (PyCFunction) treebuilder_end, METH_VARARGS}, - {"xml", (PyCFunction) treebuilder_xml, METH_VARARGS}, {"close", (PyCFunction) treebuilder_close, METH_VARARGS}, {NULL, NULL} }; @@ -2052,8 +2033,6 @@ typedef struct { PyObject* names; - PyObject* handle_xml; - PyObject* handle_start; PyObject* handle_data; PyObject* handle_end; @@ -2506,7 +2485,6 @@ xmlparser(PyObject* self_, PyObject* args, PyObject* kw) Py_INCREF(target); self->target = target; - self->handle_xml = PyObject_GetAttrString(target, "xml"); self->handle_start = PyObject_GetAttrString(target, "start"); self->handle_data = PyObject_GetAttrString(target, "data"); self->handle_end = PyObject_GetAttrString(target, "end"); @@ -2562,7 +2540,6 @@ xmlparser_dealloc(XMLParserObject* self) Py_XDECREF(self->handle_end); Py_XDECREF(self->handle_data); Py_XDECREF(self->handle_start); - Py_XDECREF(self->handle_xml); Py_DECREF(self->target); Py_DECREF(self->entity); |