Skip to content

Commit ccfaed7

Browse files
Validate client timeouts are finite
Co-authored-by: Shri Sukhani <shrisukhani@users.noreply.github.com>
1 parent ad3e469 commit ccfaed7

File tree

4 files changed

+33
-14
lines changed

4 files changed

+33
-14
lines changed

hyperbrowser/client/async_client.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
from numbers import Real
21
from typing import Mapping, Optional
32

4-
from ..exceptions import HyperbrowserError
53
from ..config import ClientConfig
64
from ..transport.async_transport import AsyncTransport
75
from .base import HyperbrowserBase
6+
from .timeout_utils import validate_timeout_seconds
87
from .managers.async_manager.web import WebManager
98
from .managers.async_manager.agents import Agents
109
from .managers.async_manager.crawl import CrawlManager
@@ -28,11 +27,7 @@ def __init__(
2827
headers: Optional[Mapping[str, str]] = None,
2928
timeout: Optional[float] = 30,
3029
):
31-
if timeout is not None:
32-
if isinstance(timeout, bool) or not isinstance(timeout, Real):
33-
raise HyperbrowserError("timeout must be a number")
34-
if timeout < 0:
35-
raise HyperbrowserError("timeout must be non-negative")
30+
validate_timeout_seconds(timeout)
3631
super().__init__(AsyncTransport, config, api_key, base_url, headers)
3732
self.transport.client.timeout = timeout
3833
self.sessions = SessionManager(self)

hyperbrowser/client/sync.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
from numbers import Real
21
from typing import Mapping, Optional
32

4-
from ..exceptions import HyperbrowserError
53
from ..config import ClientConfig
64
from ..transport.sync import SyncTransport
75
from .base import HyperbrowserBase
6+
from .timeout_utils import validate_timeout_seconds
87
from .managers.sync_manager.web import WebManager
98
from .managers.sync_manager.agents import Agents
109
from .managers.sync_manager.crawl import CrawlManager
@@ -28,11 +27,7 @@ def __init__(
2827
headers: Optional[Mapping[str, str]] = None,
2928
timeout: Optional[float] = 30,
3029
):
31-
if timeout is not None:
32-
if isinstance(timeout, bool) or not isinstance(timeout, Real):
33-
raise HyperbrowserError("timeout must be a number")
34-
if timeout < 0:
35-
raise HyperbrowserError("timeout must be non-negative")
30+
validate_timeout_seconds(timeout)
3631
super().__init__(SyncTransport, config, api_key, base_url, headers)
3732
self.transport.client.timeout = timeout
3833
self.sessions = SessionManager(self)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import math
2+
from numbers import Real
3+
from typing import Optional
4+
5+
from ..exceptions import HyperbrowserError
6+
7+
8+
def validate_timeout_seconds(timeout: Optional[float]) -> None:
9+
if timeout is None:
10+
return
11+
if isinstance(timeout, bool) or not isinstance(timeout, Real):
12+
raise HyperbrowserError("timeout must be a number")
13+
if not math.isfinite(float(timeout)):
14+
raise HyperbrowserError("timeout must be finite")
15+
if timeout < 0:
16+
raise HyperbrowserError("timeout must be non-negative")

tests/test_client_timeout.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import asyncio
2+
import math
23

34
import pytest
45

@@ -47,3 +48,15 @@ def test_sync_client_rejects_boolean_timeout():
4748
def test_async_client_rejects_boolean_timeout():
4849
with pytest.raises(HyperbrowserError, match="timeout must be a number"):
4950
AsyncHyperbrowser(api_key="test-key", timeout=False)
51+
52+
53+
@pytest.mark.parametrize("invalid_timeout", [math.inf, -math.inf, math.nan])
54+
def test_sync_client_rejects_non_finite_timeout(invalid_timeout: float):
55+
with pytest.raises(HyperbrowserError, match="timeout must be finite"):
56+
Hyperbrowser(api_key="test-key", timeout=invalid_timeout)
57+
58+
59+
@pytest.mark.parametrize("invalid_timeout", [math.inf, -math.inf, math.nan])
60+
def test_async_client_rejects_non_finite_timeout(invalid_timeout: float):
61+
with pytest.raises(HyperbrowserError, match="timeout must be finite"):
62+
AsyncHyperbrowser(api_key="test-key", timeout=invalid_timeout)

0 commit comments

Comments
 (0)