from contextlib import contextmanager
from threading import Timer, Semaphore
from functools import wraps
from weakref import WeakSet

class Limiter():
    def __init__(self, limit, every):
        self.semaphore = Semaphore(limit)
        self.timers = WeakSet()
        self.limit = limit
        self.every = every

    @contextmanager
    def wait(self):
        self.semaphore.acquire()
        yield
        timer = Timer(self.every, self.semaphore.release)
        self.timers.add(timer)
        timer.start()

    def __del__(self):
        for timer in self.timers:
            timer.cancel()


def ratelimit(limit, every):
    """Decorator to limit invocations. *limit* calls per *every* seconds."""
    def limitdecorator(fn):
        limiter = Limiter(limit, every)
        @wraps(fn)
        def wrapper(*args, **kwargs):
            with limiter.wait():
                return fn(*args, **kwargs)
        return wrapper
    return limitdecorator


@@ -127,16 +127,17 @@
 eakSet%0A%0A
+%0A
 class Li
@@ -153,41 +153,174 @@
     
-def __init__(self, limit, every):
+%22%22%22Class used to limit the rate of something. See method wait.%22%22%22%0A%0A    def __init__(self, limit, every):%0A        %22%22%22Initialize the limiter to limit/every requests.%22%22%22
 %0A   
@@ -477,32 +477,106 @@
 def wait(self):%0A
+        %22%22%22Block until the rate is compliant. Use with with statement.%22%22%22%0A
         self.sem
@@ -733,32 +733,76 @@
  __del__(self):%0A
+        %22%22%22Cancel all the active timers.%22%22%22%0A
         for time

Add docstrings to rate.py