# allow: no-sut-import — exercises loader_registry via importlib reload with a patched import hook (dynamic import) """ Import-guard tests for loader_registry module. Covers the ImportError branches on optional loader imports (lines 36-38, 44-46, 52-54, 60-62, 68-70, 78-80 in loader_registry.py) and the conditional registry-population branches they gate (148->155, 165->172, 172->179, 185->192, 192->199, 227->235). Existing tests in test_loader_registry_full_coverage.py only assert consistency between the HAS_* flags and the registry given whatever the current environment happens to have installed; they never force the ImportError path. This file simulates the missing-optional-dep case by reloading the module with a patched import hook. """ import builtins import importlib from unittest.mock import patch import pytest MODULE_NAME = "local_deep_research.document_loaders.loader_registry" def _reload_with_blocked_symbol(blocked_name): """Reload loader_registry while raising ImportError for a specific symbol. Only raises for `from langchain_community.document_loaders import ` where the fromlist is exactly a single-item tuple matching blocked_name. Leaves the bulk import at the top of loader_registry (16-item fromlist) untouched. """ original_import = builtins.__import__ def fake_import(name, globals=None, locals=None, fromlist=(), level=0): if ( name == "langchain_community.document_loaders" and fromlist is not None and len(fromlist) == 1 and fromlist[0] == blocked_name ): raise ImportError(f"simulated ImportError for {blocked_name}") return original_import(name, globals, locals, fromlist, level) module = importlib.import_module(MODULE_NAME) with patch.object(builtins, "__import__", side_effect=fake_import): return importlib.reload(module) @pytest.fixture def restore_module(): """Restore loader_registry to its pre-test state after each test. The tests in this file force ImportError on specific loader imports via module reload. Restoring the snapshot puts back the original module objects without re-executing the module — a teardown reload would recreate every class and registry entry, breaking identity with references bound elsewhere in the process. """ module = importlib.import_module(MODULE_NAME) snapshot = dict(module.__dict__) yield module.__dict__.clear() module.__dict__.update(snapshot) class TestOptionalLoaderImportErrors: """When each optional loader import fails, its flag goes False and the corresponding extensions are absent from the registry.""" def test_odt_importerror_disables_flag_and_registry_entry( self, restore_module ): reloaded = _reload_with_blocked_symbol("UnstructuredODTLoader") assert reloaded.HAS_ODT_LOADER is False assert ".odt" not in reloaded.LOADER_REGISTRY def test_epub_importerror_disables_flag_and_registry_entry( self, restore_module ): reloaded = _reload_with_blocked_symbol("UnstructuredEPubLoader") assert reloaded.HAS_EPUB_LOADER is False assert ".epub" not in reloaded.LOADER_REGISTRY def test_rtf_importerror_disables_flag_and_registry_entry( self, restore_module ): reloaded = _reload_with_blocked_symbol("UnstructuredRTFLoader") assert reloaded.HAS_RTF_LOADER is False assert ".rtf" not in reloaded.LOADER_REGISTRY def test_rst_importerror_disables_flag_and_registry_entry( self, restore_module ): reloaded = _reload_with_blocked_symbol("UnstructuredRSTLoader") assert reloaded.HAS_RST_LOADER is False assert ".rst" not in reloaded.LOADER_REGISTRY def test_org_importerror_disables_flag_and_registry_entry( self, restore_module ): reloaded = _reload_with_blocked_symbol("UnstructuredOrgModeLoader") assert reloaded.HAS_ORG_LOADER is False assert ".org" not in reloaded.LOADER_REGISTRY def test_image_importerror_disables_flag_and_all_image_extensions( self, restore_module ): reloaded = _reload_with_blocked_symbol("UnstructuredImageLoader") assert reloaded.HAS_IMAGE_LOADER is False for ext in (".png", ".jpg", ".jpeg", ".tiff", ".tif", ".bmp", ".heic"): assert ext not in reloaded.LOADER_REGISTRY