Skip to content

Commit 5e84187

Browse files
Merge pull request #113 from askui/fix/multiple-retry
fix(retry): update on_exception_types type hint and add support for m…
2 parents c574a44 + 34fd546 commit 5e84187

2 files changed

Lines changed: 35 additions & 3 deletions

File tree

‎src/askui/retry.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class ConfigurableRetry(Retry):
6060
parameters for delay and retry count.
6161
6262
Args:
63-
on_exception_types (Tuple[Type[Exception]]): Tuple of exception types that should trigger a retry
63+
on_exception_types (Tuple[Type[Exception],...]): Tuple of exception types that should trigger a retry
6464
strategy (Literal["Exponential", "Fixed", "Linear"]): The retry strategy to use:
6565
- `"Exponential"`: Delay increases exponentially between retries
6666
- `"Fixed"`: Constant delay between retries
@@ -83,7 +83,7 @@ class ConfigurableRetry(Retry):
8383
@validate_call(config=ConfigDict(arbitrary_types_allowed=True))
8484
def __init__(
8585
self,
86-
on_exception_types: Tuple[Type[Exception]],
86+
on_exception_types: Tuple[Type[Exception], ...],
8787
strategy: Literal["Exponential", "Fixed", "Linear"],
8888
base_delay: Annotated[int, Field(gt=0)] = 1000,
8989
retry_count: Annotated[int, Field(gt=0)] = 3,

‎tests/integration/agent/test_retry.py‎

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
from typing import Optional, Tuple, Union
22

33
import pytest
4+
from httpx import HTTPStatusError
45

56
from askui import ConfigurableRetry, LocateModel, VisionAgent
67
from askui.locators.locators import Locator
78
from askui.models import ModelComposition
8-
from askui.models.exceptions import ElementNotFoundError
9+
from askui.models.exceptions import ElementNotFoundError, ModelNotFoundError
910
from askui.tools.toolbox import AgentToolbox
1011
from askui.utils.image_utils import ImageSource
1112

@@ -52,6 +53,26 @@ def vision_agent_with_retry(
5253
)
5354

5455

56+
@pytest.fixture
57+
def vision_agent_with_retry_on_multiple_exceptions(
58+
failing_model: FailingLocateModel, agent_toolbox_mock: AgentToolbox
59+
) -> VisionAgent:
60+
return VisionAgent(
61+
models={"failing-locate": failing_model},
62+
tools=agent_toolbox_mock,
63+
retry=ConfigurableRetry(
64+
on_exception_types=(
65+
ElementNotFoundError,
66+
HTTPStatusError,
67+
ModelNotFoundError,
68+
),
69+
strategy="Fixed",
70+
retry_count=3,
71+
base_delay=1,
72+
),
73+
)
74+
75+
5576
@pytest.fixture
5677
def vision_agent_always_fail(
5778
always_failing_model: FailingLocateModel, agent_toolbox_mock: AgentToolbox
@@ -78,6 +99,17 @@ def test_locate_retries_and_succeeds(
7899
assert failing_model.calls == 3 # 2 fails + 1 success
79100

80101

102+
def test_locate_retries_on_multiple_exceptions_and_succeeds(
103+
vision_agent_with_retry_on_multiple_exceptions: VisionAgent,
104+
failing_model: FailingLocateModel,
105+
) -> None:
106+
result = vision_agent_with_retry_on_multiple_exceptions.locate(
107+
"something", screenshot=None, model="failing-locate"
108+
)
109+
assert result == (10, 10)
110+
assert failing_model.calls == 3
111+
112+
81113
def test_locate_retries_and_fails(
82114
vision_agent_always_fail: VisionAgent, always_failing_model: FailingLocateModel
83115
) -> None:

0 commit comments

Comments
 (0)