@@ -990,37 +990,44 @@ def summary_failures_short(tr):
990990    config .option .tbstyle  =  orig_tbstyle 
991991
992992
993- # Copied from https://github.com/huggingface/transformers/blob/000e52aec8850d3fe2f360adc6fd256e5b47fe4c/src/transformers/testing_utils.py#L1905 
994- def  is_flaky (max_attempts : int  =  5 , wait_before_retry : Optional [float ] =  None , description : Optional [str ] =  None ):
993+ # Adapted from https://github.com/huggingface/transformers/blob/000e52aec8850d3fe2f360adc6fd256e5b47fe4c/src/transformers/testing_utils.py#L1905 
994+ def  is_flaky (
995+     max_attempts : int  =  5 ,
996+     wait_before_retry : Optional [float ] =  None ,
997+     description : Optional [str ] =  None ,
998+ ):
995999    """ 
996-     To decorate flaky tests. They will be retried on failures. 
997- 
998-     Args: 
999-         max_attempts (`int`, *optional*, defaults to 5): 
1000-             The maximum number of attempts to retry the flaky test. 
1001-         wait_before_retry (`float`, *optional*): 
1002-             If provided, will wait that number of seconds before retrying the test. 
1003-         description (`str`, *optional*): 
1004-             A string to describe the situation (what / where / why is flaky, link to GH issue/PR comments, errors, 
1005-             etc.) 
1000+     To decorate flaky tests (methods or entire classes). They will be retried on failures. 
10061001    """ 
10071002
1008-     def  decorator (test_func_ref ):
1009-         @functools .wraps (test_func_ref ) 
1003+     def  decorator (obj ):
1004+         # If decorating a class, wrap each test method on it 
1005+         if  inspect .isclass (obj ):
1006+             for  attr_name , attr_value  in  list (obj .__dict__ .items ()):
1007+                 if  callable (attr_value ) and  attr_name .startswith ("test" ):
1008+                     # recursively decorate the method 
1009+                     setattr (obj , attr_name , decorator (attr_value ))
1010+             return  obj 
1011+ 
1012+         # Otherwise we're decorating a single test function / method 
1013+         @functools .wraps (obj ) 
10101014        def  wrapper (* args , ** kwargs ):
10111015            retry_count  =  1 
1012- 
10131016            while  retry_count  <  max_attempts :
10141017                try :
1015-                     return  test_func_ref (* args , ** kwargs )
1016- 
1018+                     return  obj (* args , ** kwargs )
10171019                except  Exception  as  err :
1018-                     print (f"Test failed with { err } { retry_count } { max_attempts }  , file = sys .stderr )
1020+                     msg  =  (
1021+                         f"[FLAKY] { description  or  obj .__name__ !r}  
1022+                         f"failed on attempt { retry_count } { max_attempts } { err }  
1023+                     )
1024+                     print (msg , file = sys .stderr )
10191025                    if  wait_before_retry  is  not None :
10201026                        time .sleep (wait_before_retry )
10211027                    retry_count  +=  1 
10221028
1023-             return  test_func_ref (* args , ** kwargs )
1029+             # final attempt, let any exception bubble up 
1030+             return  obj (* args , ** kwargs )
10241031
10251032        return  wrapper 
10261033
0 commit comments