"""Deep coverage tests for security/__init__.py. The __init__.py conditionally imports several optional components: - PathValidator (requires werkzeug) - FileUploadValidator (requires pdfplumber) Tests cover: - All required imports are present - Conditional flag values - __all__ completeness - Individual security re-exports callable/usable """ MODULE = "local_deep_research.security" class TestRequiredImportsAlwaysPresent: """These symbols must always be importable regardless of optional deps.""" def test_sanitize_data_present(self): from local_deep_research.security import sanitize_data assert callable(sanitize_data) def test_redact_data_present(self): from local_deep_research.security import redact_data assert callable(redact_data) def test_filter_research_metadata_present(self): from local_deep_research.security import filter_research_metadata assert callable(filter_research_metadata) def test_safe_get_present(self): from local_deep_research.security import safe_get assert callable(safe_get) def test_safe_post_present(self): from local_deep_research.security import safe_post assert callable(safe_post) def test_validate_url_present(self): from local_deep_research.security import validate_url assert callable(validate_url) def test_is_ip_blocked_present(self): from local_deep_research.security import is_ip_blocked assert callable(is_ip_blocked) def test_get_account_lockout_manager_present(self): from local_deep_research.security import get_account_lockout_manager assert callable(get_account_lockout_manager) def test_sanitize_for_log_present(self): from local_deep_research.security import sanitize_for_log assert callable(sanitize_for_log) def test_strip_control_chars_present(self): from local_deep_research.security import strip_control_chars assert callable(strip_control_chars) def test_get_safe_module_class_present(self): from local_deep_research.security import get_safe_module_class assert callable(get_safe_module_class) def test_module_not_allowed_error_present(self): from local_deep_research.security import ModuleNotAllowedError assert issubclass(ModuleNotAllowedError, Exception) def test_allowed_modules_present(self): from local_deep_research.security import ALLOWED_MODULES assert isinstance(ALLOWED_MODULES, (set, frozenset, dict, list)) def test_get_safe_url_present(self): from local_deep_research.security import get_safe_url assert callable(get_safe_url) def test_strip_settings_snapshot_present(self): from local_deep_research.security import strip_settings_snapshot assert callable(strip_settings_snapshot) def test_get_security_default_present(self): from local_deep_research.security import get_security_default assert callable(get_security_default) def test_notification_url_validation_error_present(self): from local_deep_research.security import NotificationURLValidationError assert issubclass(NotificationURLValidationError, Exception) class TestConditionalFlags: def test_has_path_validator_flag_is_bool(self): import local_deep_research.security as sec assert isinstance(sec._has_path_validator, bool) def test_has_file_upload_validator_flag_is_bool(self): import local_deep_research.security as sec assert isinstance(sec._has_file_upload_validator, bool) def test_path_validator_is_class_or_none(self): from local_deep_research.security import PathValidator assert PathValidator is None or isinstance(PathValidator, type) def test_file_upload_validator_is_class_or_none(self): from local_deep_research.security import FileUploadValidator assert FileUploadValidator is None or isinstance( FileUploadValidator, type ) def test_path_validator_flag_consistent_with_object(self): import local_deep_research.security as sec if sec._has_path_validator: assert sec.PathValidator is not None else: assert sec.PathValidator is None class TestDunderAll: def test_all_is_list(self): import local_deep_research.security as sec assert isinstance(sec.__all__, list) def test_all_contains_key_symbols(self): import local_deep_research.security as sec must_have = { "DataSanitizer", "sanitize_data", "safe_get", "safe_post", "validate_url", "PasswordValidator", "AccountLockoutManager", "sanitize_for_log", "PathValidator", "SecurityHeaders", "URLValidator", } for sym in must_have: assert sym in sec.__all__, f"{sym} missing from __all__" def test_all_symbols_defined_as_attributes(self): """Every symbol in __all__ must be defined as an attribute (may be None).""" import local_deep_research.security as sec for name in sec.__all__: assert hasattr(sec, name), f"{name} in __all__ but not defined" def test_no_duplicates_in_all(self): import local_deep_research.security as sec assert len(sec.__all__) == len(set(sec.__all__))