# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/02_util.ipynb.

# %% auto 0
__all__ = ['Singleton', 'RateLimiter']

# %% ../nbs/02_util.ipynb 4
import time, functools

# %% ../nbs/02_util.ipynb 5
from .cons import RATE_LIMIT

# %% ../nbs/02_util.ipynb 7
class Singleton(type):
    _exists = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._exists:
            cls._exists[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._exists[cls]

class RateLimiter:
    def __init__(self, rate: float = RATE_LIMIT):
        self.rate = rate
        self.calls = []

    def __call__(self, f):
        @functools.wraps(f)
        def wrapped(*args, **kwargs):
            now = time.time()
            self.calls = [call for call in self.calls if now - call < 1]
            
            if len(self.calls) >= self.rate:
                time.sleep(1 - (now - self.calls[0]))
            
            response = f(*args, **kwargs)
            self.calls.append(time.time())
            return response
        return wrapped
    
    def __repr__(self) -> str:
        return f'RateLimiter(rate={self.rate}, calls={len(self.calls)})'
