-
Notifications
You must be signed in to change notification settings - Fork 37
Expand file tree
/
Copy pathratelimits.py
More file actions
88 lines (71 loc) · 2.48 KB
/
ratelimits.py
File metadata and controls
88 lines (71 loc) · 2.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
"""Core rate limit utilities."""
import datetime
import time
class RateLimitsInfo:
"""Data for rate limits."""
interval = None
limit = None
remaining = None
reset = None
throttled = None
def __str__(self):
"""Get rate limit information as text."""
return (
"Throttled: %(throttled)s, Remaining: %(remaining)d/%(limit)d, "
"Interval: %(interval)f, Reset: %(reset)s"
% {
"throttled": "Yes" if self.throttled else "No",
"remaining": self.remaining,
"limit": self.limit,
"interval": self.interval,
"reset": self.reset,
}
)
@classmethod
def from_dict(cls, data):
"""Create RateLimitsInfo from a dictionary."""
info = RateLimitsInfo()
if "interval" in data:
info.interval = float(data["interval"])
if "limit" in data:
info.limit = int(data["limit"])
if "remaining" in data:
info.remaining = int(data["remaining"])
if "reset" in data:
info.reset = datetime.datetime.utcfromtimestamp(int(data["reset"]))
if "throttled" in data:
info.throttled = bool(data["throttled"])
else:
info.throttled = info.remaining == 0
return info
@classmethod
def from_headers(cls, headers):
"""Create RateLimitsInfo from HTTP headers."""
try:
data = {
"interval": headers["X-RateLimit-Interval"],
"limit": headers["X-RateLimit-Limit"],
"remaining": headers["X-RateLimit-Remaining"],
"reset": headers["X-RateLimit-Reset"],
}
except KeyError:
data = {}
return cls.from_dict(data)
def maybe_rate_limit(client, headers):
"""Optionally pause the process based on suggested rate interval."""
rate_limit(client, headers)
def rate_limit(client, headers):
"""Pause the process based on suggested rate interval."""
if not client or not headers:
return False
if not getattr(client.config, "rate_limit", False):
return False
rate_info = RateLimitsInfo.from_headers(headers)
if not rate_info or not rate_info.interval:
return False
if rate_info.interval:
cb = getattr(client.config, "rate_limit_callback", None)
if cb and callable(cb):
cb(rate_info)
time.sleep(rate_info.interval)
return True