@@ -165,7 +165,15 @@ def test_empty_list_to_bytes():
165165def test_conversion_with_various_dtypes (dtype ):
166166 """Test conversion of a list of floats to bytes with various dtypes"""
167167 array = [1.0 , - 2.0 , 3.5 ]
168- expected = np .array (array , dtype = dtype ).tobytes ()
168+
169+ # Special handling for bfloat16 which requires explicit import from ml_dtypes
170+ if dtype == "bfloat16" :
171+ from ml_dtypes import bfloat16 as bf16
172+
173+ expected = np .array (array , dtype = bf16 ).tobytes ()
174+ else :
175+ expected = np .array (array , dtype = dtype ).tobytes ()
176+
169177 assert array_to_buffer (array , dtype = dtype ) == expected
170178
171179
@@ -541,6 +549,26 @@ def test_import_standard_library(self):
541549 assert "json" in sys .modules
542550 assert result == '{"key": "value"}'
543551
552+ def test_cached_module_import (self ):
553+ """Test that _import_module returns the cached module if it exists"""
554+ # Remove the module from sys.modules if it's already imported
555+ if "json" in sys .modules :
556+ del sys .modules ["json" ]
557+
558+ # Lazy import the module
559+ json = lazy_import ("json" )
560+
561+ # Access an attribute to trigger the import
562+ json .dumps
563+
564+ # The module should now be cached
565+ # We need to access the private _import_module method directly
566+ # to test the cached path
567+ module = json ._import_module ()
568+
569+ # Verify that the cached module was returned
570+ assert module is json ._module
571+
544572 def test_import_already_imported_module (self ):
545573 """Test lazy importing of an already imported module"""
546574 # Make sure the module is imported
@@ -610,6 +638,17 @@ def test_import_nonexistent_module(self):
610638
611639 assert "Failed to lazily import nonexistent_module_xyz" in str (excinfo .value )
612640
641+ def test_call_nonexistent_module (self ):
642+ """Test calling a nonexistent module"""
643+ # Lazy import a nonexistent module
644+ nonexistent = lazy_import ("nonexistent_module_xyz" )
645+
646+ # Calling the nonexistent module should raise ImportError
647+ with pytest .raises (ImportError ) as excinfo :
648+ nonexistent ()
649+
650+ assert "Failed to lazily import nonexistent_module_xyz" in str (excinfo .value )
651+
613652 def test_import_nonexistent_attribute (self ):
614653 """Test lazy importing of a nonexistent attribute"""
615654 # Lazy import a nonexistent attribute
@@ -623,6 +662,19 @@ def test_import_nonexistent_attribute(self):
623662 excinfo .value
624663 )
625664
665+ def test_getattr_on_nonexistent_attribute_path (self ):
666+ """Test accessing an attribute on a nonexistent attribute path"""
667+ # Lazy import a nonexistent attribute path
668+ nonexistent_attr = lazy_import ("math.nonexistent_attribute" )
669+
670+ # Accessing an attribute on the nonexistent attribute should raise AttributeError
671+ with pytest .raises (AttributeError ) as excinfo :
672+ nonexistent_attr .some_attribute
673+
674+ assert "module 'math' has no attribute 'nonexistent_attribute'" in str (
675+ excinfo .value
676+ )
677+
626678 def test_import_noncallable (self ):
627679 """Test calling a non-callable lazy imported object"""
628680 # Lazy import a non-callable attribute
@@ -646,3 +698,62 @@ def test_attribute_error(self):
646698 assert "module 'math' has no attribute 'nonexistent_attribute'" in str (
647699 excinfo .value
648700 )
701+
702+ def test_attribute_error_after_import (self ):
703+ """Test accessing a nonexistent attribute on a module after it's been imported"""
704+ # Create a simple module with a known attribute
705+ import types
706+
707+ test_module = types .ModuleType ("test_module" )
708+ test_module .existing_attr = "exists"
709+
710+ # Add it to sys.modules so lazy_import can find it
711+ sys .modules ["test_module" ] = test_module
712+
713+ try :
714+ # Lazy import the module
715+ lazy_mod = lazy_import ("test_module" )
716+
717+ # Access the existing attribute to trigger the import
718+ assert lazy_mod .existing_attr == "exists"
719+
720+ # Now access a nonexistent attribute
721+ with pytest .raises (AttributeError ) as excinfo :
722+ lazy_mod .nonexistent_attribute
723+
724+ assert (
725+ "module 'test_module' has no attribute 'nonexistent_attribute'"
726+ in str (excinfo .value )
727+ )
728+ finally :
729+ # Clean up
730+ if "test_module" in sys .modules :
731+ del sys .modules ["test_module" ]
732+
733+ def test_attribute_error_with_direct_module_access (self ):
734+ """Test accessing a nonexistent attribute by directly setting the _module attribute"""
735+ # Get the lazy_import function
736+ from redisvl .utils .utils import lazy_import
737+
738+ # Create a lazy import for a module that doesn't exist yet
739+ lazy_mod = lazy_import ("test_direct_module" )
740+
741+ # Create a simple object with no __getattr__ method
742+ class SimpleObject :
743+ pass
744+
745+ obj = SimpleObject ()
746+
747+ # Directly set the _module attribute to our simple object
748+ # This bypasses the normal import mechanism
749+ lazy_mod ._module = obj
750+
751+ # Now access a nonexistent attribute
752+ # This should go through our LazyModule.__getattr__ and hit line 332
753+ with pytest .raises (AttributeError ) as excinfo :
754+ lazy_mod .nonexistent_attribute
755+
756+ assert (
757+ "module 'test_direct_module' has no attribute 'nonexistent_attribute'"
758+ in str (excinfo .value )
759+ )
0 commit comments