Skip to content

Commit ef53ab1

Browse files
committed
Make the usage documentation more clear
1 parent bd26cb3 commit ef53ab1

File tree

4 files changed

+55
-17
lines changed

4 files changed

+55
-17
lines changed

README.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ To use this package you simply have to declare the decorator before the method y
3737

3838
.. code:: python
3939
40-
from ratelimit import *
40+
from ratelimit import rate_limited
4141
import requests
4242
4343
@rate_limited(1)
@@ -49,14 +49,14 @@ To use this package you simply have to declare the decorator before the method y
4949
5050
return response
5151
52-
This method makes a call to our API. Note that this method has been implemented with a decorator that dictates that this method may only be called once per second.
52+
This method makes a call to our API. Note that this method has been implemented with a decorator enforcing that it may only be called once per second.
5353

54-
The argument passed into the decorator imposes the time that must elapse before a method can be called again.
54+
The argument passed into the decorator imposes the number of method invocation allowed over a time period specified (in seconds). If no time period is specified then it default to 1 second.
5555

5656
Contributing
5757
------------
5858

59-
1. Fork it ( https://github.com/tomasbasham/ratelimit/fork )
59+
1. Fork it (https://github.com/tomasbasham/ratelimit/fork)
6060
2. Create your feature branch (`git checkout -b my-new-feature`)
6161
3. Commit your changes (`git commit -am 'Add some feature'`)
6262
4. Push to the branch (`git push origin my-new-feature`)

ratelimit/__init__.py

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,52 @@
1+
from math import floor
2+
13
import time
4+
import sys
25

3-
def rate_limited(period, damping = 1.0):
6+
def rate_limited(period = 1, every = 1.0):
47
'''
58
Prevent a method from being called
69
if it was previously called before
710
a time widows has elapsed.
811
9-
:param period: The time window after which method invocations can continue.
10-
:param damping: A factor by which to dampen the time window.
12+
:param period: The number of method invocation allowed over a time period. Must be greater than or equal to 1.
13+
:param every: A factor by which to dampen the time window (in seconds). Can be any number greater than 0.
1114
:return function: Decorated function that will forward method invocations if the time window has elapsed.
1215
'''
13-
frequency = damping / float(period)
14-
def decorate(func):
16+
frequency = abs(every) / float(clamp(period))
17+
def decorator(func):
18+
19+
# To get around issues with function local scope
20+
# and reassigning variables, we wrap the time
21+
# within a list. When updating the value we're
22+
# not reassigning `last_called`, which would not
23+
# work, but instead reassigning the value at a
24+
# particular index.
1525
last_called = [0.0]
16-
def func_wrapper(*args, **kargs):
26+
27+
def wrapper(*args, **kargs):
1728
elapsed = time.clock() - last_called[0]
1829
left_to_wait = frequency - elapsed
1930
if left_to_wait > 0:
2031
time.sleep(left_to_wait)
2132
ret = func(*args, **kargs)
2233
last_called[0] = time.clock()
2334
return ret
24-
return func_wrapper
25-
return decorate
35+
return wrapper
36+
return decorator
37+
38+
def clamp(value):
39+
'''
40+
There must be at least 1 method invocation
41+
made over the time period. Make sure the
42+
value passed is at least one and it not
43+
a fraction of an invocation (wtf, like???)
44+
45+
:param value: The number of method invocations.
46+
:return int: Clamped number of invocations.
47+
'''
48+
return max(1, min(sys.maxsize, floor(value)))
49+
50+
__all__ = [
51+
'rate_limited'
52+
]

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ def readme():
66
return file.read()
77

88
setup(name='ratelimit',
9-
version=Version('1.1.0').number,
9+
version=Version('1.2.0').number,
1010
description='API rate limit decorator',
1111
long_description=readme().strip(),
1212
author='Tomas Basham',

tests/unit/decorator_test.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
1-
from ratelimit import *
1+
from ratelimit import rate_limited
22
from tests import *
33

44
class TestDecorator(unittest.TestCase):
55

6+
@rate_limited(1, 2)
7+
def increment(self):
8+
'''
9+
Increment the counter at most once
10+
every 2 seconds.
11+
'''
12+
self.count += 1
13+
14+
def setUp(self):
15+
self.count = 0
16+
617
def test_decorator(self):
7-
limiter = rate_limited(1)
8-
decorated = limiter(lambda: 'None')
9-
self.assertEqual(decorated(), 'None')
18+
self.assertEqual(self.count, 0)
19+
self.increment()
20+
self.assertEqual(self.count, 1)

0 commit comments

Comments
 (0)