.. |ci| image:: https://github.com/alisaifee/limits/workflows/CI/badge.svg?branch=master
:target: https://github.com/alisaifee/limits/actions?query=branch%3Amaster+workflow%3ACI
.. |codecov| image:: https://codecov.io/gh/alisaifee/limits/branch/master/graph/badge.svg
:target: https://codecov.io/gh/alisaifee/limits
.. |pypi| image:: https://img.shields.io/pypi/v/limits.svg?style=flat-square
:target: https://pypi.python.org/pypi/limits
.. |pypi-versions| image:: https://img.shields.io/pypi/pyversions/limits?style=flat-square
:target: https://pypi.python.org/pypi/limits
.. |license| image:: https://img.shields.io/pypi/l/limits.svg?style=flat-square
:target: https://pypi.python.org/pypi/limits
.. |docs| image:: https://readthedocs.org/projects/limits/badge/?version=latest
:target: https://limits.readthedocs.org
limits
------
|docs| |ci| |codecov| |pypi| |pypi-versions| |license|
**limits** is a python library to perform rate limiting with commonly used storage backends (Redis, Memcached, MongoDB & Etcd).
Supported Strategies
====================
`Fixed Window <https://limits.readthedocs.io/en/latest/strategies.html#fixed-window>`_
This strategy resets at a fixed interval (start of minute, hour, day etc).
For example, given a rate limit of ``10/minute`` the strategy will:
- Allow 10 requests between ``00:01:00`` and ``00:02:00``
- Allow 10 requests at ``00:00:59`` and 10 more requests at ``00:01:00``
`Fixed Window (Elastic) <https://limits.readthedocs.io/en/latest/strategies.html#fixed-window-with-elastic-expiry>`_
Identical to Fixed window, except every breach of rate limit results in an extension
to the time out. For example a rate limit of `1/minute` hit twice within a minute will
result in a lock-out for two minutes.
`Moving Window <https://limits.readthedocs.io/en/latest/strategies.html#moving-window>`_
Sliding window strategy enforces a rate limit of N/(m time units)
on the **last m** time units at the second granularity.
For example, with a rate limit of ``10/minute``:
- Allow 9 requests that arrive at ``00:00:59``
- Allow another request that arrives at ``00:01:00``
- Reject the request that arrives at ``00:01:01``
Storage backends
================
- `Redis <https://limits.readthedocs.io/en/latest/storage.html#redis-storage>`_
- `Memcached <https://limits.readthedocs.io/en/latest/storage.html#memcached-storage>`_
- `MongoDB <https://limits.readthedocs.io/en/latest/storage.html#mongodb-storage>`_
- `Etcd <https://limits.readthedocs.io/en/latest/storage.html#etcd-storage>`_
- `In-Memory <https://limits.readthedocs.io/en/latest/storage.html#in-memory-storage>`_
Dive right in
=============
Initialize the storage backend
.. code-block:: python
from limits import storage
memory_storage = storage.MemoryStorage()
# or memcached
memcached_storage = storage.MemcachedStorage("memcached://localhost:11211")
# or redis
redis_storage = storage.RedisStorage("redis://localhost:6379")
# or use the factory
storage_uri = "memcached://localhost:11211"
some_storage = storage.storage_from_string(storage_uri)
Initialize a rate limiter with the Moving Window Strategy
.. code-block:: python
from limits import strategies
moving_window = strategies.MovingWindowRateLimiter(memory_storage)
Initialize a rate limit
.. code-block:: python
from limits import parse
one_per_minute = parse("1/minute")
Initialize a rate limit explicitly
.. code-block:: python
from limits import RateLimitItemPerSecond
one_per_second = RateLimitItemPerSecond(1, 1)
Test the limits
.. code-block:: python
assert True == moving_window.hit(one_per_minute, "test_namespace", "foo")
assert False == moving_window.hit(one_per_minute, "test_namespace", "foo")
assert True == moving_window.hit(one_per_minute, "test_namespace", "bar")
assert True == moving_window.hit(one_per_second, "test_namespace", "foo")
assert False == moving_window.hit(one_per_second, "test_namespace", "foo")
time.sleep(1)
assert True == moving_window.hit(one_per_second, "test_namespace", "foo")
Check specific limits without hitting them
.. code-block:: python
assert True == moving_window.hit(one_per_second, "test_namespace", "foo")
while not moving_window.test(one_per_second, "test_namespace", "foo"):
time.sleep(0.01)
assert True == moving_window.hit(one_per_second, "test_namespace", "foo")
Links
=====
* `Documentation <http://limits.readthedocs.org/en/latest>`_
* `Changelog <http://limits.readthedocs.org/en/stable/changelog.html>`_
Raw data
{
"_id": null,
"home_page": "https://limits.readthedocs.org",
"name": "limits",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.9",
"maintainer_email": null,
"keywords": null,
"author": "Ali-Akber Saifee",
"author_email": "ali@indydevs.org",
"download_url": "https://files.pythonhosted.org/packages/30/b1/3793a849765f13cf325b0c82c470e3aa7b664c57a48e44c051fd85892782/limits-3.14.0.tar.gz",
"platform": null,
"description": ".. |ci| image:: https://github.com/alisaifee/limits/workflows/CI/badge.svg?branch=master\n :target: https://github.com/alisaifee/limits/actions?query=branch%3Amaster+workflow%3ACI\n.. |codecov| image:: https://codecov.io/gh/alisaifee/limits/branch/master/graph/badge.svg\n :target: https://codecov.io/gh/alisaifee/limits\n.. |pypi| image:: https://img.shields.io/pypi/v/limits.svg?style=flat-square\n :target: https://pypi.python.org/pypi/limits\n.. |pypi-versions| image:: https://img.shields.io/pypi/pyversions/limits?style=flat-square\n :target: https://pypi.python.org/pypi/limits\n.. |license| image:: https://img.shields.io/pypi/l/limits.svg?style=flat-square\n :target: https://pypi.python.org/pypi/limits\n.. |docs| image:: https://readthedocs.org/projects/limits/badge/?version=latest\n :target: https://limits.readthedocs.org\n\nlimits\n------\n|docs| |ci| |codecov| |pypi| |pypi-versions| |license|\n\n\n**limits** is a python library to perform rate limiting with commonly used storage backends (Redis, Memcached, MongoDB & Etcd).\n\n\nSupported Strategies\n====================\n`Fixed Window <https://limits.readthedocs.io/en/latest/strategies.html#fixed-window>`_\n This strategy resets at a fixed interval (start of minute, hour, day etc).\n For example, given a rate limit of ``10/minute`` the strategy will:\n\n - Allow 10 requests between ``00:01:00`` and ``00:02:00``\n - Allow 10 requests at ``00:00:59`` and 10 more requests at ``00:01:00``\n\n\n`Fixed Window (Elastic) <https://limits.readthedocs.io/en/latest/strategies.html#fixed-window-with-elastic-expiry>`_\n Identical to Fixed window, except every breach of rate limit results in an extension\n to the time out. For example a rate limit of `1/minute` hit twice within a minute will\n result in a lock-out for two minutes.\n\n`Moving Window <https://limits.readthedocs.io/en/latest/strategies.html#moving-window>`_\n Sliding window strategy enforces a rate limit of N/(m time units)\n on the **last m** time units at the second granularity.\n\n For example, with a rate limit of ``10/minute``:\n\n - Allow 9 requests that arrive at ``00:00:59``\n - Allow another request that arrives at ``00:01:00``\n - Reject the request that arrives at ``00:01:01``\n\nStorage backends\n================\n\n- `Redis <https://limits.readthedocs.io/en/latest/storage.html#redis-storage>`_\n- `Memcached <https://limits.readthedocs.io/en/latest/storage.html#memcached-storage>`_\n- `MongoDB <https://limits.readthedocs.io/en/latest/storage.html#mongodb-storage>`_\n- `Etcd <https://limits.readthedocs.io/en/latest/storage.html#etcd-storage>`_\n- `In-Memory <https://limits.readthedocs.io/en/latest/storage.html#in-memory-storage>`_\n\nDive right in\n=============\n\nInitialize the storage backend\n\n.. code-block:: python\n\n from limits import storage\n memory_storage = storage.MemoryStorage()\n # or memcached\n memcached_storage = storage.MemcachedStorage(\"memcached://localhost:11211\")\n # or redis\n redis_storage = storage.RedisStorage(\"redis://localhost:6379\")\n # or use the factory\n storage_uri = \"memcached://localhost:11211\"\n some_storage = storage.storage_from_string(storage_uri)\n\nInitialize a rate limiter with the Moving Window Strategy\n\n.. code-block:: python\n\n from limits import strategies\n moving_window = strategies.MovingWindowRateLimiter(memory_storage)\n\n\nInitialize a rate limit\n\n.. code-block:: python\n\n from limits import parse\n one_per_minute = parse(\"1/minute\")\n\nInitialize a rate limit explicitly\n\n.. code-block:: python\n\n from limits import RateLimitItemPerSecond\n one_per_second = RateLimitItemPerSecond(1, 1)\n\nTest the limits\n\n.. code-block:: python\n\n assert True == moving_window.hit(one_per_minute, \"test_namespace\", \"foo\")\n assert False == moving_window.hit(one_per_minute, \"test_namespace\", \"foo\")\n assert True == moving_window.hit(one_per_minute, \"test_namespace\", \"bar\")\n\n assert True == moving_window.hit(one_per_second, \"test_namespace\", \"foo\")\n assert False == moving_window.hit(one_per_second, \"test_namespace\", \"foo\")\n time.sleep(1)\n assert True == moving_window.hit(one_per_second, \"test_namespace\", \"foo\")\n\nCheck specific limits without hitting them\n\n.. code-block:: python\n\n assert True == moving_window.hit(one_per_second, \"test_namespace\", \"foo\")\n while not moving_window.test(one_per_second, \"test_namespace\", \"foo\"):\n time.sleep(0.01)\n assert True == moving_window.hit(one_per_second, \"test_namespace\", \"foo\")\n\nLinks\n=====\n\n* `Documentation <http://limits.readthedocs.org/en/latest>`_\n* `Changelog <http://limits.readthedocs.org/en/stable/changelog.html>`_\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Rate limiting utilities",
"version": "3.14.0",
"project_urls": {
"Homepage": "https://limits.readthedocs.org",
"Source": "https://github.com/alisaifee/limits"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "c6bd4f717b420501f89d4ea9bb305f4b349849ff41debb136572b1243c0ac173",
"md5": "2edf21e982e77b331ab7178270752a50",
"sha256": "959685c7514481b8c91172663fece032cb4f4b9c87cc7c0e69ad253a8e5678d1"
},
"downloads": -1,
"filename": "limits-3.14.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "2edf21e982e77b331ab7178270752a50",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.9",
"size": 45655,
"upload_time": "2024-11-30T02:59:53",
"upload_time_iso_8601": "2024-11-30T02:59:53.495557Z",
"url": "https://files.pythonhosted.org/packages/c6/bd/4f717b420501f89d4ea9bb305f4b349849ff41debb136572b1243c0ac173/limits-3.14.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "30b13793a849765f13cf325b0c82c470e3aa7b664c57a48e44c051fd85892782",
"md5": "1e304f9712b576767215533da12e0c9c",
"sha256": "28f75bda2cfedbe823aa796581c352e18bdc26a2752a4842c8e92e63b0b22fac"
},
"downloads": -1,
"filename": "limits-3.14.0.tar.gz",
"has_sig": false,
"md5_digest": "1e304f9712b576767215533da12e0c9c",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9",
"size": 70315,
"upload_time": "2024-11-30T03:00:01",
"upload_time_iso_8601": "2024-11-30T03:00:01.848824Z",
"url": "https://files.pythonhosted.org/packages/30/b1/3793a849765f13cf325b0c82c470e3aa7b664c57a48e44c051fd85892782/limits-3.14.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-11-30 03:00:01",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "alisaifee",
"github_project": "limits",
"travis_ci": false,
"coveralls": true,
"github_actions": true,
"lcname": "limits"
}