"""Coverage tests for security/__init__.py ImportError fallback branches. The missing statements are in try/except ImportError blocks: - PathValidator import fails → PathValidator=None, _has_path_validator=False - FileUploadValidator import fails → FileUploadValidator=None, _has_file_upload_validator=False """ import sys from unittest.mock import patch import pytest def _reload_security_with_blocked(blocked_submodule): """Re-execute security/__init__ with a submodule blocked via sys.modules[...]=None. Only the package module itself is evicted; every submodule stays cached, so the re-execution reuses the original objects (no recreated classes or enums, and install_audit_hook() no-ops instead of stacking another permanent audit hook). Only the __init__ fallback branches behave differently: the blocked submodule's None entry makes its import raise ImportError. """ saved = sys.modules.pop("local_deep_research.security", None) try: with patch.dict(sys.modules, {blocked_submodule: None}): import local_deep_research.security as sec_mod return sec_mod finally: if saved is not None: sys.modules["local_deep_research.security"] = saved @pytest.fixture(autouse=True) def _restore_security_module(): """Restore the exact pre-test security module objects after each test. Re-importing fresh copies instead would recreate classes/enums (e.g. egress classification's Sensitivity), breaking identity checks in any test that runs later in the same process against modules that imported them earlier. The `security` attribute on the parent package is restored to its exact pre-test state as well (including absent): otherwise, when security was never imported before this test, the crippled blocked module would stay reachable via `from local_deep_research import security`, silently presenting PathValidator/FileUploadValidator as None to later tests. """ saved = { k: v for k, v in sys.modules.items() if "local_deep_research.security" in k } missing = object() pkg = sys.modules.get("local_deep_research") saved_boundary = getattr(pkg, "security", missing) if pkg else missing yield for k in [ k for k in list(sys.modules) if "local_deep_research.security" in k ]: sys.modules.pop(k, None) sys.modules.update(saved) # Re-bind each restored module on its parent package: the blocked # reload replaced parent attributes (e.g. local_deep_research.security), # and `from local_deep_research import security` resolves through that # attribute, not through sys.modules. for name, module in saved.items(): parent_name, _, child = name.rpartition(".") parent = sys.modules.get(parent_name) if parent is not None and child: setattr(parent, child, module) # The blocked reload also rebinds `security` on the already-imported # parent package, and eviction from sys.modules does not undo that. If # security had never been imported before this test (empty snapshot), # the loop above cannot heal it and `from local_deep_research import # security` would keep resolving to the crippled blocked module through # the leftover attribute — restore its exact pre-test state instead. pkg = sys.modules.get("local_deep_research") if pkg is not None: if saved_boundary is missing: if hasattr(pkg, "security"): delattr(pkg, "security") else: pkg.security = saved_boundary class TestPathValidatorImportFallback: def test_path_validator_import_error(self): """When path_validator import fails, PathValidator is None.""" sec = _reload_security_with_blocked( "local_deep_research.security.path_validator" ) assert sec.PathValidator is None assert sec._has_path_validator is False class TestFileUploadValidatorImportFallback: def test_file_upload_validator_import_error(self): """When file_upload_validator import fails, FileUploadValidator is None.""" sec = _reload_security_with_blocked( "local_deep_research.security.file_upload_validator" ) assert sec.FileUploadValidator is None assert sec._has_file_upload_validator is False