@@ -140,8 +140,8 @@ def __iter__(self):
140
140
class _Throttle (object ):
141
141
"""A context manager limiting the total entries in a sliding time window.
142
142
143
- If more than ``entry_cap `` attempts are made to enter the context manager
144
- instance in the last ``time window`` seconds , the exceeding requests block
143
+ If more than ``access_limit `` attempts are made to enter the context manager
144
+ instance in the last ``time window`` interval , the exceeding requests block
145
145
until enough time elapses.
146
146
147
147
The context manager instances are thread-safe and can be shared between
@@ -150,27 +150,29 @@ class _Throttle(object):
150
150
151
151
Example::
152
152
153
- max_three_per_second = Throttle(time_window=1, entry_cap=3)
153
+ max_three_per_second = _Throttle(
154
+ access_limit=3, time_window=datetime.timedelta(seconds=1)
155
+ )
154
156
155
157
for i in range(5):
156
158
with max_three_per_second as time_waited:
157
159
print("{}: Waited {} seconds to enter".format(i, time_waited))
158
160
159
161
Args:
160
- time_window (float ): the width of the sliding time window in seconds
161
- entry_cap (int ): the maximum number of entries allowed in the time window
162
+ access_limit (int ): the maximum number of entries allowed in the time window
163
+ time_window (datetime.timedelta ): the width of the sliding time window
162
164
"""
163
165
164
- def __init__ (self , time_window , entry_cap ):
165
- if time_window <= 0.0 :
166
- raise ValueError ("time_window argument must be positive" )
166
+ def __init__ (self , access_limit , time_window ):
167
+ if access_limit < 1 :
168
+ raise ValueError ("access_limit argument must be positive" )
167
169
168
- if entry_cap < 1 :
169
- raise ValueError ("entry_cap argument must be positive" )
170
+ if time_window <= datetime . timedelta ( 0 ) :
171
+ raise ValueError ("time_window argument must be a positive timedelta " )
170
172
171
- self ._time_window = datetime . timedelta ( seconds = time_window )
172
- self ._entry_cap = entry_cap
173
- self ._past_entries = collections .deque (maxlen = entry_cap ) # least recent first
173
+ self ._time_window = time_window
174
+ self ._access_limit = access_limit
175
+ self ._past_entries = collections .deque (maxlen = access_limit ) # least recent first
174
176
self ._entry_lock = threading .Lock ()
175
177
176
178
def __enter__ (self ):
@@ -181,7 +183,7 @@ def __enter__(self):
181
183
while self ._past_entries and self ._past_entries [0 ] < cutoff_time :
182
184
self ._past_entries .popleft ()
183
185
184
- if len (self ._past_entries ) < self ._entry_cap :
186
+ if len (self ._past_entries ) < self ._access_limit :
185
187
self ._past_entries .append (datetime .datetime .now ())
186
188
return 0.0 # no waiting was needed
187
189
@@ -195,8 +197,10 @@ def __exit__(self, *_):
195
197
pass
196
198
197
199
def __repr__ (self ):
198
- return "{}(time_window={}, entry_cap={})" .format (
199
- self .__class__ .__name__ , self ._time_window .total_seconds (), self ._entry_cap
200
+ return "{}(access_limit={}, time_window={})" .format (
201
+ self .__class__ .__name__ ,
202
+ self ._access_limit ,
203
+ repr (self ._time_window ),
200
204
)
201
205
202
206
@@ -408,7 +412,9 @@ def __init__(
408
412
self ._finalize_lock = threading .Lock ()
409
413
410
414
if throttle_reopen :
411
- self ._reopen_throttle = _Throttle (entry_cap = 5 , time_window = 10 )
415
+ self ._reopen_throttle = _Throttle (
416
+ access_limit = 5 , time_window = datetime .timedelta (seconds = 10 ),
417
+ )
412
418
else :
413
419
self ._reopen_throttle = None
414
420
0 commit comments