Commit 49ab14f4 authored by Stefan Krah's avatar Stefan Krah

Merge.

parents fcbb4169 682c9798
...@@ -3651,6 +3651,8 @@ class TimedRotatingFileHandlerTest(BaseFileTest): ...@@ -3651,6 +3651,8 @@ class TimedRotatingFileHandlerTest(BaseFileTest):
def test_rollover(self): def test_rollover(self):
fh = logging.handlers.TimedRotatingFileHandler(self.fn, 'S', fh = logging.handlers.TimedRotatingFileHandler(self.fn, 'S',
backupCount=1) backupCount=1)
fmt = logging.Formatter('%(asctime)s %(message)s')
fh.setFormatter(fmt)
r = logging.makeLogRecord({'msg': 'testing'}) r = logging.makeLogRecord({'msg': 'testing'})
fh.emit(r) fh.emit(r)
self.assertLogFile(self.fn) self.assertLogFile(self.fn)
......
...@@ -1855,6 +1855,102 @@ def check_issue10777(): ...@@ -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): class CleanContext(object):
"""Provide default namespace mapping and path cache.""" """Provide default namespace mapping and path cache."""
checkwarnings = None checkwarnings = None
...@@ -1873,10 +1969,7 @@ class CleanContext(object): ...@@ -1873,10 +1969,7 @@ class CleanContext(object):
("This method will be removed in future versions. " ("This method will be removed in future versions. "
"Use .+ instead.", DeprecationWarning), "Use .+ instead.", DeprecationWarning),
("This method will be removed in future versions. " ("This method will be removed in future versions. "
"Use .+ instead.", PendingDeprecationWarning), "Use .+ instead.", PendingDeprecationWarning))
# XMLParser.doctype() is deprecated.
("This method of XMLParser is deprecated. Define doctype.. "
"method on the TreeBuilder target.", DeprecationWarning))
self.checkwarnings = support.check_warnings(*deprecations, quiet=quiet) self.checkwarnings = support.check_warnings(*deprecations, quiet=quiet)
def __enter__(self): def __enter__(self):
...@@ -1898,54 +1991,18 @@ class CleanContext(object): ...@@ -1898,54 +1991,18 @@ class CleanContext(object):
self.checkwarnings.__exit__(*args) 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): def test_main(module=pyET):
from test import test_xml_etree 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 # The same doctests are used for both the Python and the C implementations
test_xml_etree.ET = module 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 # XXX the C module should give the same warnings as the Python module
with CleanContext(quiet=(module is not pyET)): with CleanContext(quiet=(module is not pyET)):
......
...@@ -1511,24 +1511,30 @@ class XMLParser: ...@@ -1511,24 +1511,30 @@ class XMLParser:
self.target = self._target = target self.target = self._target = target
self._error = expat.error self._error = expat.error
self._names = {} # name memo cache self._names = {} # name memo cache
# callbacks # main callbacks
parser.DefaultHandlerExpand = self._default parser.DefaultHandlerExpand = self._default
parser.StartElementHandler = self._start if hasattr(target, 'start'):
parser.EndElementHandler = self._end parser.StartElementHandler = self._start
parser.CharacterDataHandler = self._data if hasattr(target, 'end'):
# optional callbacks parser.EndElementHandler = self._end
parser.CommentHandler = self._comment if hasattr(target, 'data'):
parser.ProcessingInstructionHandler = self._pi 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 # let expat do the buffering, if supported
try: try:
self._parser.buffer_text = 1 parser.buffer_text = 1
except AttributeError: except AttributeError:
pass pass
# use new-style attribute handling, if supported # use new-style attribute handling, if supported
try: try:
self._parser.ordered_attributes = 1 parser.ordered_attributes = 1
self._parser.specified_attributes = 1 parser.specified_attributes = 1
parser.StartElementHandler = self._start_list if hasattr(target, 'start'):
parser.StartElementHandler = self._start_list
except AttributeError: except AttributeError:
pass pass
self._doctype = None self._doctype = None
...@@ -1572,44 +1578,29 @@ class XMLParser: ...@@ -1572,44 +1578,29 @@ class XMLParser:
attrib[fixname(attrib_in[i])] = attrib_in[i+1] attrib[fixname(attrib_in[i])] = attrib_in[i+1]
return self.target.start(tag, attrib) return self.target.start(tag, attrib)
def _data(self, text):
return self.target.data(text)
def _end(self, tag): def _end(self, tag):
return self.target.end(self._fixname(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): def _default(self, text):
prefix = text[:1] prefix = text[:1]
if prefix == "&": if prefix == "&":
# deal with undefined entities # deal with undefined entities
try: 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: except KeyError:
from xml.parsers import expat from xml.parsers import expat
err = expat.error( err = expat.error(
"undefined entity %s: line %d, column %d" % "undefined entity %s: line %d, column %d" %
(text, self._parser.ErrorLineNumber, (text, self.parser.ErrorLineNumber,
self._parser.ErrorColumnNumber) self.parser.ErrorColumnNumber)
) )
err.code = 11 # XML_ERROR_UNDEFINED_ENTITY err.code = 11 # XML_ERROR_UNDEFINED_ENTITY
err.lineno = self._parser.ErrorLineNumber err.lineno = self.parser.ErrorLineNumber
err.offset = self._parser.ErrorColumnNumber err.offset = self.parser.ErrorColumnNumber
raise err raise err
elif prefix == "<" and text[:9] == "<!DOCTYPE": elif prefix == "<" and text[:9] == "<!DOCTYPE":
self._doctype = [] # inside a doctype declaration self._doctype = [] # inside a doctype declaration
...@@ -1636,7 +1627,7 @@ class XMLParser: ...@@ -1636,7 +1627,7 @@ class XMLParser:
pubid = pubid[1:-1] pubid = pubid[1:-1]
if hasattr(self.target, "doctype"): if hasattr(self.target, "doctype"):
self.target.doctype(name, pubid, system[1:-1]) 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 # warn about deprecated call
self._XMLParser__doctype(name, pubid, system[1:-1]) self._XMLParser__doctype(name, pubid, system[1:-1])
self.doctype(name, pubid, system[1:-1]) self.doctype(name, pubid, system[1:-1])
...@@ -1667,7 +1658,7 @@ class XMLParser: ...@@ -1667,7 +1658,7 @@ class XMLParser:
def feed(self, data): def feed(self, data):
try: try:
self._parser.Parse(data, 0) self.parser.Parse(data, 0)
except self._error as v: except self._error as v:
self._raiseerror(v) self._raiseerror(v)
...@@ -1679,12 +1670,20 @@ class XMLParser: ...@@ -1679,12 +1670,20 @@ class XMLParser:
def close(self): def close(self):
try: try:
self._parser.Parse("", 1) # end of data self.parser.Parse("", 1) # end of data
except self._error as v: except self._error as v:
self._raiseerror(v) self._raiseerror(v)
tree = self.target.close() try:
del self.target, self._parser # get rid of circular references try:
return tree 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 # Import the C accelerators
......
...@@ -13,6 +13,10 @@ Core and Builtins ...@@ -13,6 +13,10 @@ Core and Builtins
Library 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? What's New in Python 3.3.0 Alpha 1?
=================================== ===================================
......
...@@ -1698,13 +1698,6 @@ treebuilder_dealloc(TreeBuilderObject* self) ...@@ -1698,13 +1698,6 @@ treebuilder_dealloc(TreeBuilderObject* self)
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* handlers */ /* handlers */
LOCAL(PyObject*)
treebuilder_handle_xml(TreeBuilderObject* self, PyObject* encoding,
PyObject* standalone)
{
Py_RETURN_NONE;
}
LOCAL(PyObject*) LOCAL(PyObject*)
treebuilder_handle_start(TreeBuilderObject* self, PyObject* tag, treebuilder_handle_start(TreeBuilderObject* self, PyObject* tag,
PyObject* attrib) PyObject* attrib)
...@@ -1976,22 +1969,10 @@ treebuilder_start(TreeBuilderObject* self, PyObject* args) ...@@ -1976,22 +1969,10 @@ treebuilder_start(TreeBuilderObject* self, PyObject* args)
return treebuilder_handle_start(self, tag, attrib); 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[] = { static PyMethodDef treebuilder_methods[] = {
{"data", (PyCFunction) treebuilder_data, METH_VARARGS}, {"data", (PyCFunction) treebuilder_data, METH_VARARGS},
{"start", (PyCFunction) treebuilder_start, METH_VARARGS}, {"start", (PyCFunction) treebuilder_start, METH_VARARGS},
{"end", (PyCFunction) treebuilder_end, METH_VARARGS}, {"end", (PyCFunction) treebuilder_end, METH_VARARGS},
{"xml", (PyCFunction) treebuilder_xml, METH_VARARGS},
{"close", (PyCFunction) treebuilder_close, METH_VARARGS}, {"close", (PyCFunction) treebuilder_close, METH_VARARGS},
{NULL, NULL} {NULL, NULL}
}; };
...@@ -2052,8 +2033,6 @@ typedef struct { ...@@ -2052,8 +2033,6 @@ typedef struct {
PyObject* names; PyObject* names;
PyObject* handle_xml;
PyObject* handle_start; PyObject* handle_start;
PyObject* handle_data; PyObject* handle_data;
PyObject* handle_end; PyObject* handle_end;
...@@ -2506,7 +2485,6 @@ xmlparser(PyObject* self_, PyObject* args, PyObject* kw) ...@@ -2506,7 +2485,6 @@ xmlparser(PyObject* self_, PyObject* args, PyObject* kw)
Py_INCREF(target); Py_INCREF(target);
self->target = target; self->target = target;
self->handle_xml = PyObject_GetAttrString(target, "xml");
self->handle_start = PyObject_GetAttrString(target, "start"); self->handle_start = PyObject_GetAttrString(target, "start");
self->handle_data = PyObject_GetAttrString(target, "data"); self->handle_data = PyObject_GetAttrString(target, "data");
self->handle_end = PyObject_GetAttrString(target, "end"); self->handle_end = PyObject_GetAttrString(target, "end");
...@@ -2562,7 +2540,6 @@ xmlparser_dealloc(XMLParserObject* self) ...@@ -2562,7 +2540,6 @@ xmlparser_dealloc(XMLParserObject* self)
Py_XDECREF(self->handle_end); Py_XDECREF(self->handle_end);
Py_XDECREF(self->handle_data); Py_XDECREF(self->handle_data);
Py_XDECREF(self->handle_start); Py_XDECREF(self->handle_start);
Py_XDECREF(self->handle_xml);
Py_DECREF(self->target); Py_DECREF(self->target);
Py_DECREF(self->entity); Py_DECREF(self->entity);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment