@@ -758,6 +758,65 @@ def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter) -> Non
758
758
759
759
assert _get_open_connections (self .client ) == 0
760
760
761
+ @pytest .mark .parametrize ("failures_before_success" , [0 , 2 , 4 ])
762
+ @mock .patch ("openai._base_client.BaseClient._calculate_retry_timeout" , _low_retry_timeout )
763
+ @pytest .mark .respx (base_url = base_url )
764
+ def test_retries_taken (self , client : OpenAI , failures_before_success : int , respx_mock : MockRouter ) -> None :
765
+ client = client .with_options (max_retries = 4 )
766
+
767
+ nb_retries = 0
768
+
769
+ def retry_handler (_request : httpx .Request ) -> httpx .Response :
770
+ nonlocal nb_retries
771
+ if nb_retries < failures_before_success :
772
+ nb_retries += 1
773
+ return httpx .Response (500 )
774
+ return httpx .Response (200 )
775
+
776
+ respx_mock .post ("/chat/completions" ).mock (side_effect = retry_handler )
777
+
778
+ response = client .chat .completions .with_raw_response .create (
779
+ messages = [
780
+ {
781
+ "content" : "content" ,
782
+ "role" : "system" ,
783
+ }
784
+ ],
785
+ model = "gpt-4-turbo" ,
786
+ )
787
+
788
+ assert response .retries_taken == failures_before_success
789
+
790
+ @pytest .mark .parametrize ("failures_before_success" , [0 , 2 , 4 ])
791
+ @mock .patch ("openai._base_client.BaseClient._calculate_retry_timeout" , _low_retry_timeout )
792
+ @pytest .mark .respx (base_url = base_url )
793
+ def test_retries_taken_new_response_class (
794
+ self , client : OpenAI , failures_before_success : int , respx_mock : MockRouter
795
+ ) -> None :
796
+ client = client .with_options (max_retries = 4 )
797
+
798
+ nb_retries = 0
799
+
800
+ def retry_handler (_request : httpx .Request ) -> httpx .Response :
801
+ nonlocal nb_retries
802
+ if nb_retries < failures_before_success :
803
+ nb_retries += 1
804
+ return httpx .Response (500 )
805
+ return httpx .Response (200 )
806
+
807
+ respx_mock .post ("/chat/completions" ).mock (side_effect = retry_handler )
808
+
809
+ with client .chat .completions .with_streaming_response .create (
810
+ messages = [
811
+ {
812
+ "content" : "content" ,
813
+ "role" : "system" ,
814
+ }
815
+ ],
816
+ model = "gpt-4-turbo" ,
817
+ ) as response :
818
+ assert response .retries_taken == failures_before_success
819
+
761
820
762
821
class TestAsyncOpenAI :
763
822
client = AsyncOpenAI (base_url = base_url , api_key = api_key , _strict_response_validation = True )
@@ -1488,3 +1547,66 @@ async def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter)
1488
1547
)
1489
1548
1490
1549
assert _get_open_connections (self .client ) == 0
1550
+
1551
+ @pytest .mark .parametrize ("failures_before_success" , [0 , 2 , 4 ])
1552
+ @mock .patch ("openai._base_client.BaseClient._calculate_retry_timeout" , _low_retry_timeout )
1553
+ @pytest .mark .respx (base_url = base_url )
1554
+ @pytest .mark .asyncio
1555
+ async def test_retries_taken (
1556
+ self , async_client : AsyncOpenAI , failures_before_success : int , respx_mock : MockRouter
1557
+ ) -> None :
1558
+ client = async_client .with_options (max_retries = 4 )
1559
+
1560
+ nb_retries = 0
1561
+
1562
+ def retry_handler (_request : httpx .Request ) -> httpx .Response :
1563
+ nonlocal nb_retries
1564
+ if nb_retries < failures_before_success :
1565
+ nb_retries += 1
1566
+ return httpx .Response (500 )
1567
+ return httpx .Response (200 )
1568
+
1569
+ respx_mock .post ("/chat/completions" ).mock (side_effect = retry_handler )
1570
+
1571
+ response = await client .chat .completions .with_raw_response .create (
1572
+ messages = [
1573
+ {
1574
+ "content" : "content" ,
1575
+ "role" : "system" ,
1576
+ }
1577
+ ],
1578
+ model = "gpt-4-turbo" ,
1579
+ )
1580
+
1581
+ assert response .retries_taken == failures_before_success
1582
+
1583
+ @pytest .mark .parametrize ("failures_before_success" , [0 , 2 , 4 ])
1584
+ @mock .patch ("openai._base_client.BaseClient._calculate_retry_timeout" , _low_retry_timeout )
1585
+ @pytest .mark .respx (base_url = base_url )
1586
+ @pytest .mark .asyncio
1587
+ async def test_retries_taken_new_response_class (
1588
+ self , async_client : AsyncOpenAI , failures_before_success : int , respx_mock : MockRouter
1589
+ ) -> None :
1590
+ client = async_client .with_options (max_retries = 4 )
1591
+
1592
+ nb_retries = 0
1593
+
1594
+ def retry_handler (_request : httpx .Request ) -> httpx .Response :
1595
+ nonlocal nb_retries
1596
+ if nb_retries < failures_before_success :
1597
+ nb_retries += 1
1598
+ return httpx .Response (500 )
1599
+ return httpx .Response (200 )
1600
+
1601
+ respx_mock .post ("/chat/completions" ).mock (side_effect = retry_handler )
1602
+
1603
+ async with client .chat .completions .with_streaming_response .create (
1604
+ messages = [
1605
+ {
1606
+ "content" : "content" ,
1607
+ "role" : "system" ,
1608
+ }
1609
+ ],
1610
+ model = "gpt-4-turbo" ,
1611
+ ) as response :
1612
+ assert response .retries_taken == failures_before_success
0 commit comments