1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
"""Tests for lazy import behavior of optional dependencies."""
import sys
import unittest
from io import StringIO
import importlib
import pytest
try:
import semantic_kernel
has_semantic_kernel = True
except ImportError:
has_semantic_kernel = False
class TestLazyImports(unittest.TestCase):
"""Test lazy import behavior for optional dependencies."""
@pytest.mark.unittest
@pytest.mark.skipif(has_semantic_kernel, reason="semantic-kernel is installed")
def test_no_messages_during_module_import(self):
"""Test that no messages are printed when importing the main module."""
# Capture stderr to check for unwanted messages
captured_stderr = StringIO()
original_stderr = sys.stderr
sys.stderr = captured_stderr
try:
# Test imports that would normally fail with missing dependencies
# Since we can't easily control the dependency availability in the test environment,
# we test the lazy import setup directly
# This should not print any messages during setup
_lazy_imports = {}
_patch_all = []
def _create_lazy_import(class_name, module_path, dependency_name):
"""Create a lazy import function for optional dependencies."""
def lazy_import():
try:
module = __import__(module_path, fromlist=[class_name])
cls = getattr(module, class_name)
_patch_all.append(class_name)
return cls
except ImportError:
raise ImportError(
f"Could not import {class_name}. Please install the dependency with `pip install {dependency_name}`."
)
return lazy_import
# Setting up lazy imports should not print any messages
_lazy_imports["SKAgentConverter"] = _create_lazy_import(
"SKAgentConverter",
"azure.ai.evaluation._converters._sk_services",
"semantic-kernel",
)
# Check that no messages were printed during setup
stderr_output = captured_stderr.getvalue()
self.assertEqual(
stderr_output,
"",
"No messages should be printed during lazy import setup",
)
finally:
sys.stderr = original_stderr
@pytest.mark.unittest
@pytest.mark.skipif(has_semantic_kernel, reason="semantic-kernel is installed")
def test_message_shown_when_accessing_missing_dependency(self):
"""Test that appropriate message is shown when accessing a class with missing dependency."""
# Test the __getattr__ functionality
_lazy_imports = {}
def _create_lazy_import(class_name, module_path, dependency_name):
"""Create a lazy import function for optional dependencies."""
def lazy_import():
try:
# This should fail in most test environments
module = __import__(module_path, fromlist=[class_name])
cls = getattr(module, class_name)
return cls
except ImportError:
raise ImportError(
f"Could not import {class_name}. Please install the dependency with `pip install {dependency_name}`."
)
return lazy_import
_lazy_imports["SKAgentConverter"] = _create_lazy_import(
"SKAgentConverter",
"azure.ai.evaluation._converters._sk_services",
"semantic-kernel",
)
def mock_getattr(name):
"""Mock __getattr__ function like the one in __init__.py"""
if name in _lazy_imports:
return _lazy_imports[name]()
raise AttributeError(f"module has no attribute '{name}'")
# This should raise ImportError directly
with self.assertRaises(ImportError) as cm:
mock_getattr("SKAgentConverter")
# Check that the ImportError message contains the expected information
error_message = str(cm.exception)
self.assertIn("Could not import SKAgentConverter", error_message)
self.assertIn("pip install semantic-kernel", error_message)
@pytest.mark.unittest
def test_getattr_with_non_existent_attribute(self):
"""Test __getattr__ behavior with non-existent attributes."""
_lazy_imports = {}
def mock_getattr(name):
"""Mock __getattr__ function like the one in __init__.py"""
if name in _lazy_imports:
return _lazy_imports[name]()
raise AttributeError(f"module has no attribute '{name}'")
# Test with a non-existent attribute
with self.assertRaises(AttributeError) as cm:
mock_getattr("NonExistentClass")
self.assertIn("has no attribute 'NonExistentClass'", str(cm.exception))
if __name__ == "__main__":
unittest.main()
|