@@ -6847,3 +6847,146 @@ def test_retry_operation_sanitizes_control_characters_in_errors():
68476847 max_attempts = 1 ,
68486848 retry_delay_seconds = 0.0 ,
68496849 )
6850+
6851+
6852+ def _run_retry_operation_sync_with_name (operation_name : str ) -> None :
6853+ retry_operation (
6854+ operation_name = operation_name ,
6855+ operation = lambda : "ok" ,
6856+ max_attempts = 1 ,
6857+ retry_delay_seconds = 0.0 ,
6858+ )
6859+
6860+
6861+ def _run_retry_operation_async_with_name (operation_name : str ) -> None :
6862+ async def _run () -> None :
6863+ async def _operation () -> str :
6864+ return "ok"
6865+
6866+ await retry_operation_async (
6867+ operation_name = operation_name ,
6868+ operation = lambda : _operation (),
6869+ max_attempts = 1 ,
6870+ retry_delay_seconds = 0.0 ,
6871+ )
6872+
6873+ asyncio .run (_run ())
6874+
6875+
6876+ @pytest .mark .parametrize (
6877+ "runner" ,
6878+ [_run_retry_operation_sync_with_name , _run_retry_operation_async_with_name ],
6879+ )
6880+ def test_retry_operation_wraps_operation_name_strip_runtime_errors (runner ):
6881+ class _BrokenOperationName (str ):
6882+ def strip (self , chars = None ): # type: ignore[override]
6883+ _ = chars
6884+ raise RuntimeError ("operation_name strip exploded" )
6885+
6886+ with pytest .raises (
6887+ HyperbrowserError , match = "Failed to normalize operation_name"
6888+ ) as exc_info :
6889+ runner (_BrokenOperationName ("poll operation" ))
6890+
6891+ assert isinstance (exc_info .value .original_error , RuntimeError )
6892+
6893+
6894+ @pytest .mark .parametrize (
6895+ "runner" ,
6896+ [_run_retry_operation_sync_with_name , _run_retry_operation_async_with_name ],
6897+ )
6898+ def test_retry_operation_preserves_operation_name_strip_hyperbrowser_errors (runner ):
6899+ class _BrokenOperationName (str ):
6900+ def strip (self , chars = None ): # type: ignore[override]
6901+ _ = chars
6902+ raise HyperbrowserError ("custom operation_name strip failure" )
6903+
6904+ with pytest .raises (
6905+ HyperbrowserError , match = "custom operation_name strip failure"
6906+ ) as exc_info :
6907+ runner (_BrokenOperationName ("poll operation" ))
6908+
6909+ assert exc_info .value .original_error is None
6910+
6911+
6912+ @pytest .mark .parametrize (
6913+ "runner" ,
6914+ [_run_retry_operation_sync_with_name , _run_retry_operation_async_with_name ],
6915+ )
6916+ def test_retry_operation_wraps_non_string_operation_name_strip_results (runner ):
6917+ class _BrokenOperationName (str ):
6918+ def strip (self , chars = None ): # type: ignore[override]
6919+ _ = chars
6920+ return object ()
6921+
6922+ with pytest .raises (
6923+ HyperbrowserError , match = "Failed to normalize operation_name"
6924+ ) as exc_info :
6925+ runner (_BrokenOperationName ("poll operation" ))
6926+
6927+ assert isinstance (exc_info .value .original_error , TypeError )
6928+
6929+
6930+ @pytest .mark .parametrize (
6931+ "runner" ,
6932+ [_run_retry_operation_sync_with_name , _run_retry_operation_async_with_name ],
6933+ )
6934+ def test_retry_operation_wraps_operation_name_length_runtime_errors (runner ):
6935+ class _BrokenOperationName (str ):
6936+ def strip (self , chars = None ): # type: ignore[override]
6937+ _ = chars
6938+ return "poll operation"
6939+
6940+ def __len__ (self ):
6941+ raise RuntimeError ("operation_name length exploded" )
6942+
6943+ with pytest .raises (
6944+ HyperbrowserError , match = "Failed to validate operation_name length"
6945+ ) as exc_info :
6946+ runner (_BrokenOperationName ("poll operation" ))
6947+
6948+ assert isinstance (exc_info .value .original_error , RuntimeError )
6949+
6950+
6951+ @pytest .mark .parametrize (
6952+ "runner" ,
6953+ [_run_retry_operation_sync_with_name , _run_retry_operation_async_with_name ],
6954+ )
6955+ def test_retry_operation_wraps_operation_name_character_validation_failures (runner ):
6956+ class _BrokenOperationName (str ):
6957+ def strip (self , chars = None ): # type: ignore[override]
6958+ _ = chars
6959+ return "poll operation"
6960+
6961+ def __iter__ (self ):
6962+ raise RuntimeError ("operation_name iteration exploded" )
6963+
6964+ with pytest .raises (
6965+ HyperbrowserError , match = "Failed to validate operation_name characters"
6966+ ) as exc_info :
6967+ runner (_BrokenOperationName ("poll operation" ))
6968+
6969+ assert isinstance (exc_info .value .original_error , RuntimeError )
6970+
6971+
6972+ @pytest .mark .parametrize (
6973+ "runner" ,
6974+ [_run_retry_operation_sync_with_name , _run_retry_operation_async_with_name ],
6975+ )
6976+ def test_retry_operation_preserves_operation_name_character_validation_hyperbrowser_errors (
6977+ runner ,
6978+ ):
6979+ class _BrokenOperationName (str ):
6980+ def strip (self , chars = None ): # type: ignore[override]
6981+ _ = chars
6982+ return "poll operation"
6983+
6984+ def __iter__ (self ):
6985+ raise HyperbrowserError ("custom operation_name character failure" )
6986+
6987+ with pytest .raises (
6988+ HyperbrowserError , match = "custom operation_name character failure"
6989+ ) as exc_info :
6990+ runner (_BrokenOperationName ("poll operation" ))
6991+
6992+ assert exc_info .value .original_error is None
0 commit comments