Skip to content

Commit 2d0f5c6

Browse files
committed
Reword comments about replacing handlers within a callback
1 parent 5354cef commit 2d0f5c6

2 files changed

Lines changed: 22 additions & 16 deletions

File tree

‎Lib/test/test_pyexpat.py‎

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -836,9 +836,10 @@ def handler(text):
836836

837837

838838
class DefaultHandlerExceptionTest(unittest.TestCase):
839-
# Expat delivers a token that needs encoding conversion to the default
840-
# handler in pieces of at most 1024 bytes, re-reading the handler in
841-
# between. Removing the handler from within the callback must not crash.
839+
# In a document that is not UTF-8, Expat passes a long piece of text such
840+
# as this comment to the default handler in chunks of at most 1024 bytes,
841+
# re-reading the handler between chunks. Clearing the handler from within
842+
# the callback, by raising or by setting it to None, must not crash.
842843
xml = ("<?xml version='1.0' encoding='iso8859'?><s><!--%s--></s>"
843844
% ('a' * 2000)).encode('iso8859')
844845

@@ -872,8 +873,10 @@ def handler(text):
872873
self.assertTrue(calls[-1].startswith('<!--'), calls)
873874

874875
def test_CharacterDataHandler_with_buffer_text(self):
875-
# An exception in the CharacterDataHandler while the default
876-
# handler trampoline flushes the text buffer.
876+
# With buffer_text, buffered character data is passed to the
877+
# CharacterDataHandler just before the default handler is called;
878+
# an exception there clears the handlers while Expat is still
879+
# passing the comment to the default handler.
877880
def handler(text):
878881
raise self.SpecificException
879882

‎Modules/pyexpat.c‎

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -293,12 +293,13 @@ error_external_entity_ref_handler(XML_Parser parser,
293293

294294
/* Dummy character data handler used when an error (exception) has
295295
been detected, and the actual parsing can be terminated early.
296-
This is needed since character data handler can't be safely removed
297-
from within the character data handler, but can be replaced. It is
298-
used from the character data handler trampoline, and must be
299-
used right after `flag_error()` is called. It is also installed as
300-
the default handler (same signature) by clear_handlers(), since Expat
301-
can't cope with that one being removed from within a callback either. */
296+
This is needed since the character data and default handlers can't be
297+
safely removed from within a callback, only replaced: Expat may call
298+
them several times for one piece of text (a long comment in a document
299+
that is not UTF-8, for example). The default handler has the same
300+
signature, so this function serves for both. clear_handlers() installs
301+
it after `flag_error()`, and the handler setter installs it when a
302+
handler is set to None from within a callback. */
302303
static void
303304
noop_character_data_handler(void *userData, const XML_Char *data, int len)
304305
{
@@ -1841,8 +1842,9 @@ xmlparse_handler_setter(PyObject *op, PyObject *v, void *closure)
18411842
otherwise would, but that's really an odd case. A more
18421843
elaborate system of handlers and state could remove the
18431844
C handler more effectively. The same applies to the
1844-
default handler, which Expat calls repeatedly for a single
1845-
token that needs encoding conversion. */
1845+
default handler, which Expat can call several times for one
1846+
piece of text, such as a long comment in a document that is
1847+
not UTF-8. */
18461848
if (self->in_callback
18471849
&& (handlernum == CharacterData
18481850
|| handlernum == Default
@@ -2796,9 +2798,10 @@ clear_handlers(xmlparseobject *self, int initial)
27962798
xmlhandler c_handler = NULL;
27972799
if (i == Default || i == DefaultHandlerExpand) {
27982800
/* Like the character data handler, the default handler
2799-
can't be safely removed from within a callback: Expat's
2800-
reportDefault() re-reads it between the pieces of a
2801-
converted token. Replace it with a no-op instead. */
2801+
can't be removed from within a callback: for a document
2802+
that is not UTF-8, Expat passes a long piece of text to
2803+
it in several calls and re-reads the handler before each
2804+
one (reportDefault() in xmlparse.c). */
28022805
c_handler = (xmlhandler)noop_character_data_handler;
28032806
}
28042807
CALL_XML_HANDLER_SETTER(&handler_info[i], self->itself, c_handler);

0 commit comments

Comments
 (0)