Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions Lib/test/test_xml_dom_domreg.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import sys
import unittest
from unittest import mock

from xml.dom import domreg


class BrokenModule:
"""Fake DOM implementation module whose factory is genuinely buggy."""

@staticmethod
def getDOMImplementation():
raise RuntimeError("bug in implementation factory")


class MissingFactoryModule:
"""Fake DOM implementation module without a factory (AttributeError)."""


class GetDOMImplementationFallbackTests(unittest.TestCase):
"""The nameless getDOMImplementation() call tries each well-known
implementation and skips the unavailable ones.
"""

def _patch_implementations(self, module):
self.enterContext(
mock.patch.dict(sys.modules, {"test_fake_dom": module})
)
self.enterContext(
mock.patch.dict(
domreg.well_known_implementations,
{"test_fake_dom": "test_fake_dom"},
clear=True,
)
)
self.enterContext(mock.patch.dict(domreg.registered, clear=True))

def test_fallback_skips_unavailable_implementations(self):
# A missing factory (AttributeError) means "not available": skipped,
# and with no other implementation the lookup fails cleanly.
self._patch_implementations(MissingFactoryModule)
with self.assertRaises(ImportError):
domreg.getDOMImplementation()

def test_fallback_propagates_unexpected_errors(self):
# gh-155944: a genuine bug in a candidate's factory must propagate,
# not be silently treated as "implementation not available".
self._patch_implementations(BrokenModule)
with self.assertRaises(RuntimeError):
domreg.getDOMImplementation()


if __name__ == "__main__":
unittest.main()
3 changes: 2 additions & 1 deletion Lib/xml/dom/domreg.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ def getDOMImplementation(name=None, features=()):
for creator in well_known_implementations.keys():
try:
dom = getDOMImplementation(name = creator)
except Exception: # typically ImportError, or AttributeError
except (ImportError, AttributeError):
# The implementation is not installed or lacks the factory.
continue
if _good_enough(dom, features):
return dom
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
:func:`xml.dom.getDOMImplementation` no longer masks genuine errors raised by a well-known implementation's factory during fallback discovery. Only :exc:`ImportError` and :exc:`AttributeError` are treated as "implementation not available".
Loading