Skip to content

Commit 667662c

Browse files
committed
simpler dataclass
1 parent a13c052 commit 667662c

File tree

2 files changed

+16
-16
lines changed

2 files changed

+16
-16
lines changed

src/huggingface_hub/utils/_http.py

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -56,16 +56,15 @@ class RateLimitInfo:
5656
Parsed rate limit information from HTTP response headers.
5757
"""
5858

59-
endpoint_group: str
6059
remaining: int
6160
reset_in_seconds: int
6261
limit: Optional[int] = None
6362
window_seconds: Optional[int] = None
6463

6564

6665
# Regex patterns for parsing rate limit headers
67-
# e.g.: "api";r=0;t=55 --> endpoint_group="api", r=0, t=55
68-
_RATELIMIT_HEADER_REGEX = re.compile(r'"([^"]+)"\s*;\s*r\s*=\s*(\d+)\s*;\s*t\s*=\s*(\d+)')
66+
# e.g.: "api";r=0;t=55 --> r=0, t=55
67+
_RATELIMIT_HEADER_REGEX = re.compile(r"r\s*=\s*(\d+)\s*;\s*t\s*=\s*(\d+)")
6968
# e.g.: "fixed window";"api";q=500;w=300 --> q=500, w=300
7069
_RATELIMIT_POLICY_REGEX = re.compile(r"q\s*=\s*(\d+).*?w\s*=\s*(\d+)")
7170

@@ -91,9 +90,8 @@ def parse_ratelimit_headers(headers: httpx.Headers) -> Optional[RateLimitInfo]:
9190
if not match:
9291
return None
9392

94-
endpoint_group = match.group(1)
95-
remaining = int(match.group(2))
96-
reset_in_seconds = int(match.group(3))
93+
remaining = int(match.group(1))
94+
reset_in_seconds = int(match.group(2))
9795

9896
limit: Optional[int] = None
9997
window_seconds: Optional[int] = None
@@ -106,7 +104,6 @@ def parse_ratelimit_headers(headers: httpx.Headers) -> Optional[RateLimitInfo]:
106104
window_seconds = int(policy_match.group(2))
107105

108106
return RateLimitInfo(
109-
endpoint_group=endpoint_group,
110107
remaining=remaining,
111108
reset_in_seconds=reset_in_seconds,
112109
limit=limit,
@@ -688,15 +685,17 @@ def hf_raise_for_status(response: httpx.Response, endpoint_name: Optional[str] =
688685
elif response.status_code == 429:
689686
ratelimit_info = parse_ratelimit_headers(response.headers)
690687
if ratelimit_info is not None:
691-
message = f"\n\n429 Too Many Requests. Rate limited on '{ratelimit_info.endpoint_group}' endpoint."
692-
message += f"\nRetry after {ratelimit_info.reset_in_seconds} seconds."
688+
message = f"\n\n429 Too Many Requests for url: {response.url}."
689+
message += f"\nRetry after {ratelimit_info.reset_in_seconds} seconds"
693690
if ratelimit_info.limit is not None and ratelimit_info.window_seconds is not None:
694691
message += (
695-
f" {ratelimit_info.remaining}/{ratelimit_info.limit} requests remaining"
696-
f" in current {ratelimit_info.window_seconds}s window."
692+
f" ({ratelimit_info.remaining}/{ratelimit_info.limit} requests remaining"
693+
f" in current {ratelimit_info.window_seconds}s window)."
697694
)
695+
else:
696+
message += "."
698697
else:
699-
message = "\n\n429 Too Many Requests."
698+
message = f"\n\n429 Too Many Requests for url: {response.url}."
700699
raise _format(HfHubHTTPError, message, response) from e
701700

702701
elif response.status_code == 416:

tests/test_utils_http.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,6 @@ def test_parse_full_headers(self):
462462
)
463463
info = parse_ratelimit_headers(headers)
464464
assert info == RateLimitInfo(
465-
endpoint_group="api",
466465
remaining=0,
467466
reset_in_seconds=55,
468467
limit=500,
@@ -474,7 +473,6 @@ def test_parse_ratelimit_only(self):
474473
headers = httpx.Headers({"ratelimit": '"api";r=489;t=189'})
475474
info = parse_ratelimit_headers(headers)
476475
assert info is not None
477-
assert info.endpoint_group == "api"
478476
assert info.remaining == 489
479477
assert info.reset_in_seconds == 189
480478
assert info.limit is None
@@ -496,6 +494,7 @@ def test_429_with_ratelimit_headers(self):
496494
"""Test 429 error includes rate limit info when headers present."""
497495
response = Mock(spec=httpx.Response)
498496
response.status_code = 429
497+
response.url = "https://huggingface.co/api/models/username/reponame"
499498
response.headers = httpx.Headers(
500499
{
501500
"ratelimit": '"api";r=0;t=55',
@@ -509,15 +508,16 @@ def test_429_with_ratelimit_headers(self):
509508
hf_raise_for_status(response)
510509

511510
error_msg = str(exc_info.value)
512-
assert "429" in error_msg
513-
assert "api" in error_msg
511+
assert "429 Too Many Requests" in error_msg
512+
assert "api/models/username/reponame" in error_msg
514513
assert "55 seconds" in error_msg
515514
assert "0/500" in error_msg
516515

517516
def test_429_without_ratelimit_headers(self):
518517
"""Test 429 error fallback when headers missing."""
519518
response = Mock(spec=httpx.Response)
520519
response.status_code = 429
520+
response.url = "https://huggingface.co/api/models"
521521
response.headers = httpx.Headers({})
522522
response.raise_for_status.side_effect = httpx.HTTPStatusError("429", request=Mock(), response=response)
523523
response.json.return_value = {}
@@ -526,3 +526,4 @@ def test_429_without_ratelimit_headers(self):
526526
hf_raise_for_status(response)
527527

528528
assert "429 Too Many Requests" in str(exc_info.value)
529+
assert "api/models" in str(exc_info.value)

0 commit comments

Comments
 (0)