@@ -143,6 +143,26 @@ def get_status() -> str:
143143 assert attempts ["count" ] == 1
144144
145145
146+ def test_poll_until_terminal_status_does_not_retry_generator_reentrancy_errors ():
147+ attempts = {"count" : 0 }
148+
149+ def get_status () -> str :
150+ attempts ["count" ] += 1
151+ raise ValueError ("generator already executing" )
152+
153+ with pytest .raises (ValueError , match = "generator already executing" ):
154+ poll_until_terminal_status (
155+ operation_name = "sync poll generator-reentrancy passthrough" ,
156+ get_status = get_status ,
157+ is_terminal_status = lambda value : value == "completed" ,
158+ poll_interval_seconds = 0.0001 ,
159+ max_wait_seconds = 1.0 ,
160+ max_status_failures = 5 ,
161+ )
162+
163+ assert attempts ["count" ] == 1
164+
165+
146166def test_poll_until_terminal_status_does_not_retry_timeout_or_polling_errors ():
147167 timeout_attempts = {"count" : 0 }
148168
@@ -514,6 +534,24 @@ def operation() -> str:
514534 assert attempts ["count" ] == 1
515535
516536
537+ def test_retry_operation_does_not_retry_generator_reentrancy_errors ():
538+ attempts = {"count" : 0 }
539+
540+ def operation () -> str :
541+ attempts ["count" ] += 1
542+ raise ValueError ("generator already executing" )
543+
544+ with pytest .raises (ValueError , match = "generator already executing" ):
545+ retry_operation (
546+ operation_name = "sync retry generator-reentrancy passthrough" ,
547+ operation = operation ,
548+ max_attempts = 5 ,
549+ retry_delay_seconds = 0.0001 ,
550+ )
551+
552+ assert attempts ["count" ] == 1
553+
554+
517555def test_retry_operation_does_not_retry_timeout_or_polling_errors ():
518556 timeout_attempts = {"count" : 0 }
519557
@@ -806,6 +844,29 @@ async def get_status() -> str:
806844 asyncio .run (run ())
807845
808846
847+ def test_poll_until_terminal_status_async_does_not_retry_generator_reentrancy_errors ():
848+ async def run () -> None :
849+ attempts = {"count" : 0 }
850+
851+ async def get_status () -> str :
852+ attempts ["count" ] += 1
853+ raise ValueError ("generator already executing" )
854+
855+ with pytest .raises (ValueError , match = "generator already executing" ):
856+ await poll_until_terminal_status_async (
857+ operation_name = "async poll generator-reentrancy passthrough" ,
858+ get_status = get_status ,
859+ is_terminal_status = lambda value : value == "completed" ,
860+ poll_interval_seconds = 0.0001 ,
861+ max_wait_seconds = 1.0 ,
862+ max_status_failures = 5 ,
863+ )
864+
865+ assert attempts ["count" ] == 1
866+
867+ asyncio .run (run ())
868+
869+
809870def test_poll_until_terminal_status_async_does_not_retry_timeout_or_polling_errors ():
810871 async def run () -> None :
811872 timeout_attempts = {"count" : 0 }
@@ -962,6 +1023,27 @@ async def operation() -> str:
9621023 asyncio .run (run ())
9631024
9641025
1026+ def test_retry_operation_async_does_not_retry_generator_reentrancy_errors ():
1027+ async def run () -> None :
1028+ attempts = {"count" : 0 }
1029+
1030+ async def operation () -> str :
1031+ attempts ["count" ] += 1
1032+ raise ValueError ("generator already executing" )
1033+
1034+ with pytest .raises (ValueError , match = "generator already executing" ):
1035+ await retry_operation_async (
1036+ operation_name = "async retry generator-reentrancy passthrough" ,
1037+ operation = operation ,
1038+ max_attempts = 5 ,
1039+ retry_delay_seconds = 0.0001 ,
1040+ )
1041+
1042+ assert attempts ["count" ] == 1
1043+
1044+ asyncio .run (run ())
1045+
1046+
9651047def test_retry_operation_async_does_not_retry_timeout_or_polling_errors ():
9661048 async def run () -> None :
9671049 timeout_attempts = {"count" : 0 }
@@ -1981,6 +2063,28 @@ def get_next_page(page: int) -> dict:
19812063 assert attempts ["count" ] == 1
19822064
19832065
2066+ def test_collect_paginated_results_does_not_retry_generator_reentrancy_errors ():
2067+ attempts = {"count" : 0 }
2068+
2069+ def get_next_page (page : int ) -> dict :
2070+ attempts ["count" ] += 1
2071+ raise ValueError ("generator already executing" )
2072+
2073+ with pytest .raises (ValueError , match = "generator already executing" ):
2074+ collect_paginated_results (
2075+ operation_name = "sync paginated generator-reentrancy passthrough" ,
2076+ get_next_page = get_next_page ,
2077+ get_current_page_batch = lambda response : response ["current" ],
2078+ get_total_page_batches = lambda response : response ["total" ],
2079+ on_page_success = lambda response : None ,
2080+ max_wait_seconds = 1.0 ,
2081+ max_attempts = 5 ,
2082+ retry_delay_seconds = 0.0001 ,
2083+ )
2084+
2085+ assert attempts ["count" ] == 1
2086+
2087+
19842088def test_collect_paginated_results_does_not_retry_timeout_errors ():
19852089 attempts = {"count" : 0 }
19862090
@@ -2316,6 +2420,31 @@ async def get_next_page(page: int) -> dict:
23162420 asyncio .run (run ())
23172421
23182422
2423+ def test_collect_paginated_results_async_does_not_retry_generator_reentrancy_errors ():
2424+ async def run () -> None :
2425+ attempts = {"count" : 0 }
2426+
2427+ async def get_next_page (page : int ) -> dict :
2428+ attempts ["count" ] += 1
2429+ raise ValueError ("generator already executing" )
2430+
2431+ with pytest .raises (ValueError , match = "generator already executing" ):
2432+ await collect_paginated_results_async (
2433+ operation_name = "async paginated generator-reentrancy passthrough" ,
2434+ get_next_page = get_next_page ,
2435+ get_current_page_batch = lambda response : response ["current" ],
2436+ get_total_page_batches = lambda response : response ["total" ],
2437+ on_page_success = lambda response : None ,
2438+ max_wait_seconds = 1.0 ,
2439+ max_attempts = 5 ,
2440+ retry_delay_seconds = 0.0001 ,
2441+ )
2442+
2443+ assert attempts ["count" ] == 1
2444+
2445+ asyncio .run (run ())
2446+
2447+
23192448def test_collect_paginated_results_async_does_not_retry_timeout_errors ():
23202449 async def run () -> None :
23212450 attempts = {"count" : 0 }
0 commit comments