@@ -165,7 +165,15 @@ def test_empty_list_to_bytes():
165
165
def test_conversion_with_various_dtypes (dtype ):
166
166
"""Test conversion of a list of floats to bytes with various dtypes"""
167
167
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
+
169
177
assert array_to_buffer (array , dtype = dtype ) == expected
170
178
171
179
@@ -541,6 +549,26 @@ def test_import_standard_library(self):
541
549
assert "json" in sys .modules
542
550
assert result == '{"key": "value"}'
543
551
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
+
544
572
def test_import_already_imported_module (self ):
545
573
"""Test lazy importing of an already imported module"""
546
574
# Make sure the module is imported
@@ -610,6 +638,17 @@ def test_import_nonexistent_module(self):
610
638
611
639
assert "Failed to lazily import nonexistent_module_xyz" in str (excinfo .value )
612
640
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
+
613
652
def test_import_nonexistent_attribute (self ):
614
653
"""Test lazy importing of a nonexistent attribute"""
615
654
# Lazy import a nonexistent attribute
@@ -623,6 +662,19 @@ def test_import_nonexistent_attribute(self):
623
662
excinfo .value
624
663
)
625
664
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
+
626
678
def test_import_noncallable (self ):
627
679
"""Test calling a non-callable lazy imported object"""
628
680
# Lazy import a non-callable attribute
@@ -646,3 +698,62 @@ def test_attribute_error(self):
646
698
assert "module 'math' has no attribute 'nonexistent_attribute'" in str (
647
699
excinfo .value
648
700
)
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