@@ -419,7 +419,7 @@ def test_disable_entities_true_rejects_xmlbomb():
419419 ]>
420420 <bomb>&c;</bomb>
421421 """
422- with pytest .raises (expat . ExpatError , match = "entities are disabled" ):
422+ with pytest .raises (ValueError , match = "entities are disabled" ):
423423 parse (xml , disable_entities = True )
424424
425425
@@ -437,39 +437,57 @@ def test_disable_entities_false_returns_xmlbomb():
437437 assert parse (xml , disable_entities = False ) == expectedResult
438438
439439
440- def test_disable_entities_true_rejects_external_dtd ():
440+ def test_external_entity ():
441441 xml = """
442442 <!DOCTYPE external [
443443 <!ENTITY ee SYSTEM "http://www.python.org/">
444444 ]>
445445 <root>ⅇ</root>
446446 """
447- with pytest .raises (expat .ExpatError , match = "entities are disabled" ):
448- parse (xml , disable_entities = True )
447+ with pytest .raises (ValueError , match = "entities are disabled" ):
448+ parse (xml )
449+ assert parse (xml , disable_entities = False ) == {"root" : None }
449450
450451
451- def test_disable_entities_true_attempts_external_dtd ():
452+ def test_external_entity_with_custom_expat ():
452453 xml = """
453454 <!DOCTYPE external [
454455 <!ENTITY ee SYSTEM "http://www.python.org/">
455456 ]>
456457 <root>ⅇ</root>
457458 """
458459
459- def raising_external_ref_handler (* args , ** kwargs ):
460- parser = ParserCreate (* args , ** kwargs )
461- parser .ExternalEntityRefHandler = lambda * x : 0
462- return parser
463- expat .ParserCreate = raising_external_ref_handler
464- # Using this try/catch because a TypeError is thrown before
465- # the ExpatError.
466- try :
467- parse (xml , disable_entities = False , expat = expat )
468- except expat .ExpatError :
469- assert True
470- else :
471- assert False
472- expat .ParserCreate = ParserCreate
460+ class CustomExpat :
461+ def __init__ (self , external_entity_result ):
462+ self .external_entity_result = external_entity_result
463+
464+ def ParserCreate (self , * args , ** kwargs ):
465+ parser = ParserCreate (* args , ** kwargs )
466+
467+ def _handler (* args , ** kwargs ):
468+ return self .external_entity_result
469+
470+ parser .ExternalEntityRefHandler = _handler
471+ return parser
472+
473+ ExpatError = expat .ExpatError
474+
475+ with pytest .raises (expat .ExpatError ):
476+ parse (xml , disable_entities = False , expat = CustomExpat (0 ))
477+ assert parse (xml , disable_entities = False , expat = CustomExpat (1 )) == {"root" : None }
478+ with pytest .raises (ValueError ):
479+ assert parse (xml , disable_entities = True , expat = CustomExpat (1 ))
480+ with pytest .raises (ValueError ):
481+ assert parse (xml , disable_entities = True , expat = CustomExpat (0 ))
482+
483+
484+ def test_disable_entities_true_allows_doctype_without_entities ():
485+ xml = """<?xml version='1.0' encoding='UTF-8'?>
486+ <!DOCTYPE data SYSTEM "diagram.dtd">
487+ <foo>bar</foo>
488+ """
489+ assert parse (xml , disable_entities = True ) == {"foo" : "bar" }
490+ assert parse (xml , disable_entities = False ) == {"foo" : "bar" }
473491
474492
475493def test_disable_entities_allows_comments_by_default ():
0 commit comments