diff -r b504dd372717 Doc/library/pyexpat.rst --- a/Doc/library/pyexpat.rst Wed Jan 05 12:00:25 2011 +0100 +++ b/Doc/library/pyexpat.rst Wed Jan 05 17:55:33 2011 +0100 @@ -153,6 +153,13 @@ :attr:`ordered_attributes` and :attr:`specified_attributes` set to the values of this parser. +.. method:: xmlparser.SetParamEntityParsing(flag) + + Controls parsing of parameter entities (including the external DTD subset). + Possible *flag* values are :const:`XML_PARAM_ENTITY_PARSING_NEVER`, + :const:`XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE` and + :const:`XML_PARAM_ENTITY_PARSING_ALWAYS`. Returns true if setting the flag + was successful. .. method:: xmlparser.UseForeignDTD([flag]) diff -r b504dd372717 Lib/test/test_pyexpat.py --- a/Lib/test/test_pyexpat.py Wed Jan 05 12:00:25 2011 +0100 +++ b/Lib/test/test_pyexpat.py Wed Jan 05 17:55:33 2011 +0100 @@ -155,6 +155,14 @@ 'ElementDeclHandler', 'AttlistDeclHandler', 'SkippedEntityHandler', ] + def _hookup_callbacks(self, parser, handler): + """ + Set each of the callbacks defined on handler and named in + self.handler_names on the given parser. + """ + for name in self.handler_names: + setattr(parser, name, getattr(handler, name)) + def _verify_parse_output(self, operations): expected_operations = [ ('XML declaration', ('1.0', 'iso-8859-1', 0)), @@ -196,8 +204,7 @@ # Try the parse again, this time producing Unicode output out = self.Outputter() parser = expat.ParserCreate(namespace_separator='!') - for name in self.handler_names: - setattr(parser, name, getattr(out, name)) + self._hookup_callbacks(parser, out) parser.Parse(data, 1) @@ -210,8 +217,7 @@ # Try parsing a file out = self.Outputter() parser = expat.ParserCreate(namespace_separator='!') - for name in self.handler_names: - setattr(parser, name, getattr(out, name)) + self._hookup_callbacks(parser, out) file = BytesIO(data) parser.ParseFile(file) @@ -613,6 +619,48 @@ errors.codes[errors.XML_ERROR_UNCLOSED_TOKEN]) +class ForeignDTDTests(unittest.TestCase): + """ + Tests for the UseForeignDTD method of expat parser objects. + """ + def test_use_foreign_dtd(self): + """ + If UseForeignDTD is passed True and a document without an external + entity reference is parsed, ExternalEntityRefHandler is first called + with None for the public and system ids. + """ + handler_call_args = [] + def resolve_entity(context, base, system_id, public_id): + handler_call_args.append((public_id, system_id)) + return 1 + + parser = expat.ParserCreate() + parser.UseForeignDTD(True) + parser.SetParamEntityParsing(expat.XML_PARAM_ENTITY_PARSING_ALWAYS) + parser.ExternalEntityRefHandler = resolve_entity + parser.Parse("") + self.assertEquals(handler_call_args, [(None, None)]) + + def test_ignore_use_foreign_dtd(self): + """ + If UseForeignDTD is passed True and a document with an external + entity reference is parsed, ExternalEntityRefHandler is called with + the public and system ids from the document. + """ + handler_call_args = [] + def resolve_entity(context, base, system_id, public_id): + handler_call_args.append((public_id, system_id)) + return 1 + + parser = expat.ParserCreate() + parser.UseForeignDTD(True) + parser.SetParamEntityParsing(expat.XML_PARAM_ENTITY_PARSING_ALWAYS) + parser.ExternalEntityRefHandler = resolve_entity + parser.Parse( + "") + self.assertEquals(handler_call_args, [("bar", "baz")]) + + def test_main(): run_unittest(SetAttributeTest, ParseTest, @@ -624,7 +672,8 @@ sf1296433Test, ChardataBufferTest, MalformedInputTest, - ErrorMessageTest) + ErrorMessageTest, + ForeignDTDTests) if __name__ == "__main__": test_main()