1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
|
==========
Quickstart
==========
.. note:: In an async context, simply substitute the imports
from :mod:`limits` to :mod:`limits.aio` and use ``await`` in
the storage and limiter methods.
Initialize the strategy & storage
=================================
Initialize the storage backend
------------------------------
.. tab:: In Memory
.. code::
from limits import storage
limits_storage = storage.MemoryStorage()
.. tab:: Memcached
.. code::
from limits import storage
limits_storage = storage.MemcachedStorage(
"memcached://localhost:11211"
)
.. tab:: Redis
.. code::
from limits import storage
limits_storage = storage.RedisStorage("redis://localhost:6379/1")
Initialize a rate limiter
--------------------------
.. tab:: With the Fixed window strategy
.. code::
from limits import strategies
limiter = strategies.FixedWindowRateLimiter(limits_storage)
.. tab:: With the Moving window strategy
.. caution:: If the storage used does not support the moving window
strategy, :exc:`NotImplementedError` will be raised
.. code::
from limits import strategies
limiter = strategies.MovingWindowRateLimiter(limits_storage)
.. tab:: With the Sliding window counter strategy
.. caution:: If the storage used does not support the sliding window
counter strategy, :exc:`NotImplementedError` will be raised
.. code::
from limits import strategies
limiter = strategies.SlidingWindowCounterRateLimiter(limits_storage)
Describe the rate limit
=======================
Initialize a rate limit using the :ref:`string notation<quickstart:rate limit string notation>`
-----------------------------------------------------------------------------------------------
.. code::
from limits import parse
one_per_minute = parse("1/minute")
Initialize a rate limit explicitly using a subclass of :class:`~limits.RateLimitItem`
-------------------------------------------------------------------------------------
.. code::
from limits import RateLimitItemPerSecond
one_per_second = RateLimitItemPerSecond(1, 1)
Test the limits
===============
Consume the limits
------------------
.. code::
assert True == limiter.hit(one_per_minute, "test_namespace", "foo")
assert False == limiter.hit(one_per_minute, "test_namespace", "foo")
assert True == limiter.hit(one_per_minute, "test_namespace", "bar")
assert True == limiter.hit(one_per_second, "test_namespace", "foo")
assert False == limiter.hit(one_per_second, "test_namespace", "foo")
time.sleep(1)
assert True == limiter.hit(one_per_second, "test_namespace", "foo")
Check without consuming
-----------------------
.. code::
assert True == limiter.hit(one_per_second, "test_namespace", "foo")
while not limiter.test(one_per_second, "test_namespace", "foo"):
time.sleep(0.01)
assert True == limiter.hit(one_per_second, "test_namespace", "foo")
Query available capacity and reset time
-----------------------------------------
.. code::
assert True == limiter.hit(one_per_minute, "test_namespace", "foo")
window = limiter.get_window_stats(one_per_minute, "test_namespace", "foo")
assert window.remaining == 0
assert False == limiter.hit(one_per_minute, "test_namespace", "foo")
time.sleep(window.reset_time - time.time())
assert True == limiter.hit(one_per_minute, "test_namespace", "foo")
Clear a limit
=============
.. code::
assert True == limiter.hit(one_per_minute, "test_namespace", "foo")
assert False == limiter.hit(one_per_minute, "test_namespace", "foo")
limiter.clear(one_per_minute, "test_namespace", "foo")
assert True == limiter.hit(one_per_minute, "test_namespace", "foo")
.. _ratelimit-string:
==========================
Rate limit string notation
==========================
Instead of manually constructing instances of :class:`~limits.RateLimitItem`
you can instead use the following :ref:`api:parsing functions`.
- :func:`~limits.parse`
- :func:`~limits.parse_many`
These functions accept rate limits specified as strings following the format::
[count] [per|/] [n (optional)] [second|minute|hour|day|month|year]
You can combine rate limits by separating them with a delimiter of your
choice.
Examples
========
* ``10 per hour``
* ``10/hour``
* ``10/hour;100/day;2000 per year``
* ``100/day, 500/7days``
|