cpython: 47016103185f (original) (raw)
Mercurial > cpython
changeset 75411:47016103185f
Issue #14007: accept incomplete TreeBuilder objects (missing start/end/data/close) for the Python implementation as well. Add disabled tests for the doctype() method. [#14007]
Florent Xicluna florent.xicluna@gmail.com | |
---|---|
date | Mon, 05 Mar 2012 10:42:19 +0100 |
parents | 39cc025968f1 |
children | cf7b360f9971 |
files | Lib/test/test_xml_etree.py Lib/xml/etree/ElementTree.py Misc/NEWS |
diffstat | 3 files changed, 155 insertions(+), 95 deletions(-)[+] [-] Lib/test/test_xml_etree.py 165 Lib/xml/etree/ElementTree.py 81 Misc/NEWS 4 |
line wrap: on
line diff
--- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -1855,58 +1855,16 @@ def check_issue10777():
--------------------------------------------------------------------
- def init(self, quiet=False):
if sys.flags.optimize >= 2:[](#l1.12)
# under -OO, doctests cannot be run and therefore not all warnings[](#l1.13)
# will be emitted[](#l1.14)
quiet = True[](#l1.15)
deprecations = ([](#l1.16)
# Search behaviour is broken if search path starts with "/".[](#l1.17)
("This search is broken in 1.3 and earlier, and will be fixed "[](#l1.18)
"in a future version. If you rely on the current behaviour, "[](#l1.19)
"change it to '.+'", FutureWarning),[](#l1.20)
# Element.getchildren() and Element.getiterator() are deprecated.[](#l1.21)
("This method will be removed in future versions. "[](#l1.22)
"Use .+ instead.", DeprecationWarning),[](#l1.23)
("This method will be removed in future versions. "[](#l1.24)
"Use .+ instead.", PendingDeprecationWarning),[](#l1.25)
# XMLParser.doctype() is deprecated.[](#l1.26)
("This method of XMLParser is deprecated. Define doctype.. "[](#l1.27)
"method on the TreeBuilder target.", DeprecationWarning))[](#l1.28)
self.checkwarnings = support.check_warnings(*deprecations, quiet=quiet)[](#l1.29)
+class ElementTreeTest(unittest.TestCase):
- def enter(self):
from xml.etree import ElementPath[](#l1.33)
self._nsmap = ET.register_namespace._namespace_map[](#l1.34)
# Copy the default namespace mapping[](#l1.35)
self._nsmap_copy = self._nsmap.copy()[](#l1.36)
# Copy the path cache (should be empty)[](#l1.37)
self._path_cache = ElementPath._cache[](#l1.38)
ElementPath._cache = self._path_cache.copy()[](#l1.39)
self.checkwarnings.__enter__()[](#l1.40)
- def exit(self, *args):
from xml.etree import ElementPath[](#l1.43)
# Restore mapping and path cache[](#l1.44)
self._nsmap.clear()[](#l1.45)
self._nsmap.update(self._nsmap_copy)[](#l1.46)
ElementPath._cache = self._path_cache[](#l1.47)
self.checkwarnings.__exit__(*args)[](#l1.48)
- - -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')[](#l1.54)
- - -class TestElementClass(unittest.TestCase):
- def test_istype(self):
self.assertIsInstance(ET.ParseError, type)[](#l1.60)
self.assertIsInstance(ET.QName, type)[](#l1.61)
self.assertIsInstance(ET.ElementTree, type)[](#l1.62) self.assertIsInstance(ET.Element, type)[](#l1.63)
# XXX issue 14128 with C ElementTree[](#l1.64)
# self.assertIsInstance(ET.TreeBuilder, type)[](#l1.65)
# self.assertIsInstance(ET.XMLParser, type)[](#l1.66)
def test_Element_subclass_trivial(self): class MyElement(ET.Element): @@ -1936,16 +1894,115 @@ class TestElementClass(unittest.TestCase self.assertEqual(mye.newmethod(), 'joe') +class TreeBuilderTest(unittest.TestCase): +
- sample1 = ('<!DOCTYPE html PUBLIC'
' "-//W3C//DTD XHTML 1.0 Transitional//EN"'[](#l1.77)
' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'[](#l1.78)
'<html>text</html>')[](#l1.79)
- def test_dummy_builder(self):
class BaseDummyBuilder:[](#l1.82)
def close(self):[](#l1.83)
return 42[](#l1.84)
class DummyBuilder(BaseDummyBuilder):[](#l1.86)
data = start = end = lambda *a: None[](#l1.87)
parser = ET.XMLParser(target=DummyBuilder())[](#l1.89)
parser.feed(self.sample1)[](#l1.90)
self.assertEqual(parser.close(), 42)[](#l1.91)
parser = ET.XMLParser(target=BaseDummyBuilder())[](#l1.93)
parser.feed(self.sample1)[](#l1.94)
self.assertEqual(parser.close(), 42)[](#l1.95)
parser = ET.XMLParser(target=object())[](#l1.97)
parser.feed(self.sample1)[](#l1.98)
self.assertIsNone(parser.close())[](#l1.99)
- @unittest.expectedFailure # XXX issue 14007 with C ElementTree
- def test_doctype(self):
class DoctypeParser:[](#l1.104)
_doctype = None[](#l1.105)
def doctype(self, name, pubid, system):[](#l1.107)
self._doctype = (name, pubid, system)[](#l1.108)
def close(self):[](#l1.110)
return self._doctype[](#l1.111)
parser = ET.XMLParser(target=DoctypeParser())[](#l1.113)
parser.feed(self.sample1)[](#l1.114)
self.assertEqual(parser.close(),[](#l1.116)
('html', '-//W3C//DTD XHTML 1.0 Transitional//EN',[](#l1.117)
'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'))[](#l1.118)
+ + +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')[](#l1.125)
self.assertEqual(pyET.SubElement.__module__, 'xml.etree.ElementTree')[](#l1.126)
+ +# -------------------------------------------------------------------- + + +class CleanContext(object):
- def init(self, quiet=False):
if sys.flags.optimize >= 2:[](#l1.136)
# under -OO, doctests cannot be run and therefore not all warnings[](#l1.137)
# will be emitted[](#l1.138)
quiet = True[](#l1.139)
deprecations = ([](#l1.140)
# Search behaviour is broken if search path starts with "/".[](#l1.141)
("This search is broken in 1.3 and earlier, and will be fixed "[](#l1.142)
"in a future version. If you rely on the current behaviour, "[](#l1.143)
"change it to '.+'", FutureWarning),[](#l1.144)
# Element.getchildren() and Element.getiterator() are deprecated.[](#l1.145)
("This method will be removed in future versions. "[](#l1.146)
"Use .+ instead.", DeprecationWarning),[](#l1.147)
("This method will be removed in future versions. "[](#l1.148)
"Use .+ instead.", PendingDeprecationWarning))[](#l1.149)
self.checkwarnings = support.check_warnings(*deprecations, quiet=quiet)[](#l1.150)
- def enter(self):
from xml.etree import ElementPath[](#l1.153)
self._nsmap = ET.register_namespace._namespace_map[](#l1.154)
# Copy the default namespace mapping[](#l1.155)
self._nsmap_copy = self._nsmap.copy()[](#l1.156)
# Copy the path cache (should be empty)[](#l1.157)
self._path_cache = ElementPath._cache[](#l1.158)
ElementPath._cache = self._path_cache.copy()[](#l1.159)
self.checkwarnings.__enter__()[](#l1.160)
- def exit(self, *args):
from xml.etree import ElementPath[](#l1.163)
# Restore mapping and path cache[](#l1.164)
self._nsmap.clear()[](#l1.165)
self._nsmap.update(self._nsmap_copy)[](#l1.166)
ElementPath._cache = self._path_cache[](#l1.167)
self.checkwarnings.__exit__(*args)[](#l1.168)
+ + 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
- test_classes = [ElementTreeTest, TreeBuilderTest]
- if module is pyET:
# Run the tests specific to the Python implementation[](#l1.183)
test_classes += [NoAcceleratorTest][](#l1.184)
# XXX the C module should give the same warnings as the Python module with CleanContext(quiet=(module is not pyET)):
--- 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[](#l2.7)
# main callbacks[](#l2.8) parser.DefaultHandlerExpand = self._default[](#l2.9)
parser.StartElementHandler = self._start[](#l2.10)
parser.EndElementHandler = self._end[](#l2.11)
parser.CharacterDataHandler = self._data[](#l2.12)
# optional callbacks[](#l2.13)
parser.CommentHandler = self._comment[](#l2.14)
parser.ProcessingInstructionHandler = self._pi[](#l2.15)
if hasattr(target, 'start'):[](#l2.16)
parser.StartElementHandler = self._start[](#l2.17)
if hasattr(target, 'end'):[](#l2.18)
parser.EndElementHandler = self._end[](#l2.19)
if hasattr(target, 'data'):[](#l2.20)
parser.CharacterDataHandler = target.data[](#l2.21)
# miscellaneous callbacks[](#l2.22)
if hasattr(target, 'comment'):[](#l2.23)
parser.CommentHandler = target.comment[](#l2.24)
if hasattr(target, 'pi'):[](#l2.25)
parser.ProcessingInstructionHandler = target.pi[](#l2.26) # let expat do the buffering, if supported[](#l2.27) try:[](#l2.28)
self._parser.buffer_text = 1[](#l2.29)
parser.buffer_text = 1[](#l2.30) except AttributeError:[](#l2.31) pass[](#l2.32) # use new-style attribute handling, if supported[](#l2.33) try:[](#l2.34)
self._parser.ordered_attributes = 1[](#l2.35)
self._parser.specified_attributes = 1[](#l2.36)
parser.StartElementHandler = self._start_list[](#l2.37)
parser.ordered_attributes = 1[](#l2.38)
parser.specified_attributes = 1[](#l2.39)
if hasattr(target, 'start'):[](#l2.40)
parser.StartElementHandler = self._start_list[](#l2.41) except AttributeError:[](#l2.42) pass[](#l2.43) self._doctype = None[](#l2.44)
@@ -1572,44 +1578,29 @@ class XMLParser: attrib[fixname(attrib_in[i])] = attrib_in[i+1] return self.target.start(tag, attrib)
- def _end(self, tag): return self.target.end(self._fixname(tag))
- def _comment(self, data):
try:[](#l2.56)
comment = self.target.comment[](#l2.57)
except AttributeError:[](#l2.58)
pass[](#l2.59)
else:[](#l2.60)
return comment(data)[](#l2.61)
- def _pi(self, target, data):
try:[](#l2.64)
pi = self.target.pi[](#l2.65)
except AttributeError:[](#l2.66)
pass[](#l2.67)
else:[](#l2.68)
return pi(target, data)[](#l2.69)
- def _default(self, text): prefix = text[:1] if prefix == "&": # deal with undefined entities try:
self.target.data(self.entity[text[1:-1]])[](#l2.76)
data_handler = self.target.data[](#l2.77)
except AttributeError:[](#l2.78)
return[](#l2.79)
try:[](#l2.80)
data_handler(self.entity[text[1:-1]])[](#l2.81) except KeyError:[](#l2.82) from xml.parsers import expat[](#l2.83) err = expat.error([](#l2.84) "undefined entity %s: line %d, column %d" %[](#l2.85)
(text, self._parser.ErrorLineNumber,[](#l2.86)
self._parser.ErrorColumnNumber)[](#l2.87)
(text, self.parser.ErrorLineNumber,[](#l2.88)
self.parser.ErrorColumnNumber)[](#l2.89) )[](#l2.90) err.code = 11 # XML_ERROR_UNDEFINED_ENTITY[](#l2.91)
err.lineno = self._parser.ErrorLineNumber[](#l2.92)
err.offset = self._parser.ErrorColumnNumber[](#l2.93)
err.lineno = self.parser.ErrorLineNumber[](#l2.94)
err.offset = self.parser.ErrorColumnNumber[](#l2.95) raise err[](#l2.96) elif prefix == "<" and text[:9] == "<!DOCTYPE":[](#l2.97) self._doctype = [] # inside a doctype declaration[](#l2.98)
@@ -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:[](#l2.103)
elif self.doctype != self._XMLParser__doctype:[](#l2.104) # warn about deprecated call[](#l2.105) self._XMLParser__doctype(name, pubid, system[1:-1])[](#l2.106) self.doctype(name, pubid, system[1:-1])[](#l2.107)
@@ -1667,7 +1658,7 @@ class XMLParser: def feed(self, data): try:
self._parser.Parse(data, 0)[](#l2.112)
self.parser.Parse(data, 0)[](#l2.113) except self._error as v:[](#l2.114) self._raiseerror(v)[](#l2.115)
@@ -1679,12 +1670,20 @@ class XMLParser: def close(self): try:
self._parser.Parse("", 1) # end of data[](#l2.121)
self.parser.Parse("", 1) # end of data[](#l2.122) except self._error as v:[](#l2.123) self._raiseerror(v)[](#l2.124)
tree = self.target.close()[](#l2.125)
del self.target, self._parser # get rid of circular references[](#l2.126)
return tree[](#l2.127)
try:[](#l2.128)
try:[](#l2.129)
close_handler = self.target.close[](#l2.130)
except AttributeError:[](#l2.131)
pass[](#l2.132)
else:[](#l2.133)
return close_handler()[](#l2.134)
finally:[](#l2.135)
# get rid of circular references[](#l2.136)
del self.parser, self._parser[](#l2.137)
del self.target, self._target[](#l2.138)
Import the C accelerators
--- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,10 @@ Core and Builtins Library ------- +- Issue #14007: Accept incomplete TreeBuilder objects (missing start, end,