second commit
This commit is contained in:
24
env/lib/python3.11/site-packages/ratelimit/__init__.py
vendored
Normal file
24
env/lib/python3.11/site-packages/ratelimit/__init__.py
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
'''
|
||||
Function decorator for rate limiting
|
||||
|
||||
This module provides a functon decorator that can be used to wrap a function
|
||||
such that it will raise an exception if the number of calls to that function
|
||||
exceeds a maximum within a specified time window.
|
||||
|
||||
For examples and full documentation see the README at
|
||||
https://github.com/tomasbasham/ratelimt
|
||||
'''
|
||||
from ratelimit.decorators import RateLimitDecorator, sleep_and_retry
|
||||
from ratelimit.exception import RateLimitException
|
||||
|
||||
limits = RateLimitDecorator
|
||||
rate_limited = RateLimitDecorator # For backwards compatibility
|
||||
|
||||
__all__ = [
|
||||
'RateLimitException',
|
||||
'limits',
|
||||
'rate_limited',
|
||||
'sleep_and_retry'
|
||||
]
|
||||
|
||||
__version__ = '2.2.1'
|
BIN
env/lib/python3.11/site-packages/ratelimit/__pycache__/__init__.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/ratelimit/__pycache__/__init__.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/ratelimit/__pycache__/decorators.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/ratelimit/__pycache__/decorators.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/ratelimit/__pycache__/exception.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/ratelimit/__pycache__/exception.cpython-311.pyc
vendored
Normal file
Binary file not shown.
116
env/lib/python3.11/site-packages/ratelimit/decorators.py
vendored
Normal file
116
env/lib/python3.11/site-packages/ratelimit/decorators.py
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
from functools import wraps
|
||||
from math import floor
|
||||
|
||||
import time
|
||||
import sys
|
||||
import threading
|
||||
|
||||
from ratelimit.exception import RateLimitException
|
||||
|
||||
# Use monotonic time if available, otherwise fall back to the system clock.
|
||||
now = time.monotonic if hasattr(time, 'monotonic') else time.time
|
||||
|
||||
class RateLimitDecorator(object):
|
||||
'''
|
||||
Rate limit decorator class.
|
||||
'''
|
||||
def __init__(self, calls=15, period=900, clock=now, raise_on_limit=True):
|
||||
'''
|
||||
Instantiate a RateLimitDecorator with some sensible defaults. By
|
||||
default the Twitter rate limiting window is respected (15 calls every
|
||||
15 minutes).
|
||||
|
||||
:param int calls: Maximum function invocations allowed within a time period. Must be a number greater than 0.
|
||||
:param float period: An upper bound time period (in seconds) before the rate limit resets. Must be a number greater than 0.
|
||||
:param function clock: An optional function retuning the current time. This is used primarily for testing.
|
||||
:param bool raise_on_limit: A boolean allowing the caller to avoiding rasing an exception.
|
||||
'''
|
||||
self.clamped_calls = max(1, min(sys.maxsize, floor(calls)))
|
||||
self.period = period
|
||||
self.clock = clock
|
||||
self.raise_on_limit = raise_on_limit
|
||||
|
||||
# Initialise the decorator state.
|
||||
self.last_reset = clock()
|
||||
self.num_calls = 0
|
||||
|
||||
# Add thread safety.
|
||||
self.lock = threading.RLock()
|
||||
|
||||
def __call__(self, func):
|
||||
'''
|
||||
Return a wrapped function that prevents further function invocations if
|
||||
previously called within a specified period of time.
|
||||
|
||||
:param function func: The function to decorate.
|
||||
:return: Decorated function.
|
||||
:rtype: function
|
||||
'''
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kargs):
|
||||
'''
|
||||
Extend the behaviour of the decoated function, forwarding function
|
||||
invocations previously called no sooner than a specified period of
|
||||
time. The decorator will raise an exception if the function cannot
|
||||
be called so the caller may implement a retry strategy such as an
|
||||
exponential backoff.
|
||||
|
||||
:param args: non-keyword variable length argument list to the decorated function.
|
||||
:param kargs: keyworded variable length argument list to the decorated function.
|
||||
:raises: RateLimitException
|
||||
'''
|
||||
with self.lock:
|
||||
period_remaining = self.__period_remaining()
|
||||
|
||||
# If the time window has elapsed then reset.
|
||||
if period_remaining <= 0:
|
||||
self.num_calls = 0
|
||||
self.last_reset = self.clock()
|
||||
|
||||
# Increase the number of attempts to call the function.
|
||||
self.num_calls += 1
|
||||
|
||||
# If the number of attempts to call the function exceeds the
|
||||
# maximum then raise an exception.
|
||||
if self.num_calls > self.clamped_calls:
|
||||
if self.raise_on_limit:
|
||||
raise RateLimitException('too many calls', period_remaining)
|
||||
return
|
||||
|
||||
return func(*args, **kargs)
|
||||
return wrapper
|
||||
|
||||
def __period_remaining(self):
|
||||
'''
|
||||
Return the period remaining for the current rate limit window.
|
||||
|
||||
:return: The remaing period.
|
||||
:rtype: float
|
||||
'''
|
||||
elapsed = self.clock() - self.last_reset
|
||||
return self.period - elapsed
|
||||
|
||||
def sleep_and_retry(func):
|
||||
'''
|
||||
Return a wrapped function that rescues rate limit exceptions, sleeping the
|
||||
current thread until rate limit resets.
|
||||
|
||||
:param function func: The function to decorate.
|
||||
:return: Decorated function.
|
||||
:rtype: function
|
||||
'''
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kargs):
|
||||
'''
|
||||
Call the rate limited function. If the function raises a rate limit
|
||||
exception sleep for the remaing time period and retry the function.
|
||||
|
||||
:param args: non-keyword variable length argument list to the decorated function.
|
||||
:param kargs: keyworded variable length argument list to the decorated function.
|
||||
'''
|
||||
while True:
|
||||
try:
|
||||
return func(*args, **kargs)
|
||||
except RateLimitException as exception:
|
||||
time.sleep(exception.period_remaining)
|
||||
return wrapper
|
15
env/lib/python3.11/site-packages/ratelimit/exception.py
vendored
Normal file
15
env/lib/python3.11/site-packages/ratelimit/exception.py
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
class RateLimitException(Exception):
|
||||
'''
|
||||
Rate limit exception class.
|
||||
'''
|
||||
def __init__(self, message, period_remaining):
|
||||
'''
|
||||
Custom exception raise when the number of function invocations exceeds
|
||||
that imposed by a rate limit. Additionally the exception is aware of
|
||||
the remaining time period after which the rate limit is reset.
|
||||
|
||||
:param string message: Custom exception message.
|
||||
:param float period_remaining: The time remaining until the rate limit is reset.
|
||||
'''
|
||||
super(RateLimitException, self).__init__(message)
|
||||
self.period_remaining = period_remaining
|
Reference in New Issue
Block a user