| 707 | @pytest.mark.respx(base_url=base_url) |
| 708 | @pytest.mark.parametrize("failure_mode", ["status", "exception"]) |
| 709 | def test_retries_taken( |
| 710 | self, |
| 711 | client: Opencode, |
| 712 | failures_before_success: int, |
| 713 | failure_mode: Literal["status", "exception"], |
| 714 | respx_mock: MockRouter, |
| 715 | ) -> None: |
| 716 | client = client.with_options(max_retries=4) |
| 717 | |
| 718 | nb_retries = 0 |
| 719 | |
| 720 | def retry_handler(_request: httpx.Request) -> httpx.Response: |
| 721 | nonlocal nb_retries |
| 722 | if nb_retries < failures_before_success: |
| 723 | nb_retries += 1 |
| 724 | if failure_mode == "exception": |
| 725 | raise RuntimeError("oops") |
| 726 | return httpx.Response(500) |
| 727 | return httpx.Response(200) |
| 728 | |
| 729 | respx_mock.get("/session").mock(side_effect=retry_handler) |
| 730 | |
| 731 | response = client.session.with_raw_response.list() |
| 732 | |
| 733 | assert response.retries_taken == failures_before_success |
| 734 | assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success |
| 735 | |
| 736 | @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) |
| 737 | @mock.patch("opencode_ai._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) |