1515
1616try :
1717 from src .amp .loaders .base import DataLoader , LoadConfig , LoadMode , LoadResult
18+ from src .amp .streaming .types import BlockRange
1819except ImportError :
1920 # Skip tests if modules not available
2021 pytest .skip ('amp modules not available' , allow_module_level = True )
@@ -60,6 +61,28 @@ def test_failure_result_string_representation(self):
6061 assert 'Connection failed' in result_str
6162 assert 'test_table' in result_str
6263
64+ def test_reorg_result_string_representation (self ):
65+ """Test string representation of reorg LoadResult"""
66+ invalidation_ranges = [
67+ BlockRange (network = 'ethereum' , start = 100 , end = 110 ),
68+ BlockRange (network = 'polygon' , start = 200 , end = 205 ),
69+ ]
70+
71+ result = LoadResult (
72+ rows_loaded = 0 ,
73+ duration = 0.5 ,
74+ ops_per_second = 0 ,
75+ table_name = 'blocks' ,
76+ loader_type = 'postgresql' ,
77+ success = True ,
78+ is_reorg = True ,
79+ invalidation_ranges = invalidation_ranges ,
80+ )
81+
82+ result_str = str (result )
83+ assert '🔄 Reorg detected' in result_str
84+ assert '2 ranges invalidated' in result_str
85+
6386
6487@pytest .mark .unit
6588class TestLoadConfig :
@@ -177,9 +200,54 @@ def _get_method_definitions(self, loader_class: type, method_name: str) -> List[
177200
178201 return method_defs
179202
203+ def _verify_method_implementation (self , loader_name : str , loader_class : type , method_name : str ) -> None :
204+ """Verify that a method is actually implemented, not just inherited as a stub"""
205+ method = getattr (loader_class , method_name )
206+
207+ # First try to check the source code
208+ try :
209+ source = inspect .getsource (method )
210+
211+ # Check if method is inherited from base class (not defined in this specific class)
212+ # If 'class <LoaderClassName>' is NOT in source, it means method comes from base class
213+ if f'class { loader_class } ' not in source :
214+ # Method is inherited, check if it's a stub
215+ if method_name == '_handle_reorg' :
216+ # For _handle_reorg, check if it just raises NotImplementedError
217+ if 'raise NotImplementedError' in source :
218+ pytest .fail (
219+ f'{ loader_name } does not implement { method_name } () - it inherits the '
220+ f'NotImplementedError from base class. Each loader must implement '
221+ f'this method appropriately for its storage backend.'
222+ )
223+ elif (
224+ 'pass' in source
225+ and len ([line for line in source .split ('\n ' ) if line .strip () and not line .strip ().startswith ('#' )]) <= 2
226+ ):
227+ # Method is just 'pass'
228+ pytest .fail (f"{ loader_name } .{ method_name } is just 'pass' - needs implementation" )
229+
230+ except (OSError , TypeError ):
231+ # Can't get source, try runtime approach for _handle_reorg
232+ if method_name == '_handle_reorg' :
233+ try :
234+ # Create a dummy instance to test the method
235+ test_instance = loader_class ({'test' : 'config' })
236+ test_instance ._handle_reorg ([], 'test_table' )
237+ # If we get here, method didn't raise NotImplementedError - it's implemented
238+ except NotImplementedError :
239+ # Method raises NotImplementedError - not implemented
240+ pytest .fail (
241+ f'{ loader_name } does not implement { method_name } () - it raises NotImplementedError. '
242+ f'Each loader must implement this method.'
243+ )
244+ except Exception :
245+ # Some other error occurred during execution, assume it's implemented
246+ pass
247+
180248 def test_all_loaders_implement_required_methods (self ):
181- """Test that all loader implementations have required methods"""
182- required_methods = ['connect' , 'disconnect' , '_load_batch_impl' , '_create_table_from_schema' ]
249+ """Test that all loader implementations properly implement required methods (not just inherit stubs) """
250+ required_methods = ['connect' , 'disconnect' , '_load_batch_impl' , '_create_table_from_schema' , '_handle_reorg' ]
183251
184252 loaders = self ._get_loader_classes ()
185253
@@ -189,10 +257,13 @@ def test_all_loaders_implement_required_methods(self):
189257 for method_name in required_methods :
190258 assert hasattr (loader_class , method_name ), f'{ loader_name } missing required method: { method_name } '
191259
192- # Check that the method is actually implemented (not just inherited abstract )
260+ # Check that the method is actually implemented (not just inherited stub )
193261 method = getattr (loader_class , method_name )
194262 assert method is not None , f'{ loader_name } .{ method_name } is None'
195263
264+ # Verify the method is actually implemented in this class, not just a stub
265+ self ._verify_method_implementation (loader_name , loader_class , method_name )
266+
196267 def test_no_duplicate_method_definitions (self ):
197268 """Test that no loader has duplicate method definitions"""
198269 critical_methods = ['_create_table_from_schema' , '_load_batch_impl' , 'connect' , 'disconnect' ]
@@ -203,34 +274,3 @@ def test_no_duplicate_method_definitions(self):
203274 for method_name in critical_methods :
204275 definitions = self ._get_method_definitions (loader_class , method_name )
205276 assert len (definitions ) <= 1 , f'{ loader_name } has duplicate { method_name } definitions at: { definitions } '
206-
207- def test_create_table_from_schema_not_just_pass (self ):
208- """Test that _create_table_from_schema methods have meaningful implementations"""
209- loaders = self ._get_loader_classes ()
210-
211- for loader_name , loader_class in loaders .items ():
212- method = getattr (loader_class , '_create_table_from_schema' , None )
213- if method :
214- # Get source code
215- try :
216- source = inspect .getsource (method )
217- # Check if it's just 'pass' or has actual implementation
218- lines = [line .strip () for line in source .split ('\n ' ) if line .strip ()]
219-
220- # Filter out comments and docstrings
221- code_lines = []
222- for line in lines :
223- if not line .startswith ('#' ) and not line .startswith ('"""' ) and not line .startswith ("'''" ):
224- code_lines .append (line )
225-
226- # Should have more than just the method definition line and 'pass'
227- if len (code_lines ) <= 2 : # def line + pass line only
228- last_line = code_lines [- 1 ] if code_lines else ''
229- if last_line == 'pass' :
230- pytest .fail (
231- f"{ loader_name } ._create_table_from_schema is just 'pass' - needs implementation"
232- )
233-
234- except (OSError , TypeError ):
235- # Can't get source, skip this check
236- pass
0 commit comments