You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
178 lines
6.7 KiB
178 lines
6.7 KiB
Metadata-Version: 2.1
|
|
Name: limits
|
|
Version: 2.8.0
|
|
Summary: Rate limiting utilities
|
|
Home-page: https://limits.readthedocs.org
|
|
Author: Ali-Akber Saifee
|
|
Author-email: ali@indydevs.org
|
|
License: MIT
|
|
Project-URL: Source, https://github.com/alisaifee/limits
|
|
Classifier: Development Status :: 5 - Production/Stable
|
|
Classifier: Intended Audience :: Developers
|
|
Classifier: License :: OSI Approved :: MIT License
|
|
Classifier: Operating System :: MacOS
|
|
Classifier: Operating System :: POSIX :: Linux
|
|
Classifier: Operating System :: OS Independent
|
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
Classifier: Programming Language :: Python :: 3.7
|
|
Classifier: Programming Language :: Python :: 3.8
|
|
Classifier: Programming Language :: Python :: 3.9
|
|
Classifier: Programming Language :: Python :: 3.10
|
|
Classifier: Programming Language :: Python :: 3.11
|
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
Requires-Python: >=3.7
|
|
License-File: LICENSE.txt
|
|
Requires-Dist: deprecated (>=1.2)
|
|
Requires-Dist: setuptools
|
|
Requires-Dist: packaging (<23,>=21)
|
|
Requires-Dist: typing-extensions
|
|
Provides-Extra: all
|
|
Requires-Dist: redis (<5.0.0,>3) ; extra == 'all'
|
|
Requires-Dist: redis (>=4.2.0) ; extra == 'all'
|
|
Requires-Dist: pymemcache (<5.0.0,>3) ; extra == 'all'
|
|
Requires-Dist: pymongo (<5,>3) ; extra == 'all'
|
|
Requires-Dist: motor (<4,>=2.5) ; extra == 'all'
|
|
Requires-Dist: emcache (>=0.6.1) ; (python_version < "3.11") and extra == 'all'
|
|
Requires-Dist: coredis (<5,>=3.4.0) ; (python_version > "3.7") and extra == 'all'
|
|
Provides-Extra: async-memcached
|
|
Requires-Dist: emcache (>=0.6.1) ; (python_version < "3.11") and extra == 'async-memcached'
|
|
Provides-Extra: async-mongodb
|
|
Requires-Dist: motor (<4,>=2.5) ; extra == 'async-mongodb'
|
|
Provides-Extra: async-redis
|
|
Requires-Dist: coredis (<5,>=3.4.0) ; (python_version > "3.7") and extra == 'async-redis'
|
|
Provides-Extra: memcached
|
|
Requires-Dist: pymemcache (<5.0.0,>3) ; extra == 'memcached'
|
|
Provides-Extra: mongodb
|
|
Requires-Dist: pymongo (<5,>3) ; extra == 'mongodb'
|
|
Provides-Extra: redis
|
|
Requires-Dist: redis (<5.0.0,>3) ; extra == 'redis'
|
|
Provides-Extra: rediscluster
|
|
Requires-Dist: redis (>=4.2.0) ; extra == 'rediscluster'
|
|
|
|
.. |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).
|
|
|
|
----
|
|
|
|
Sponsored by Zuplo - fully-managed, programmable API Management platform.
|
|
Add rate limiting and more to your public API in minutes, try it at `zuplo.com <https://zuplo.link/3DZM9Ej>`_
|
|
|
|
----
|
|
|
|
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>`_
|
|
- `Memcached <https://limits.readthedocs.io/en/latest/storage.html#memcached>`_
|
|
- `In-Memory <https://limits.readthedocs.io/en/latest/storage.html#in-memory>`_
|
|
- `MongoDB <https://limits.readthedocs.io/en/latest/storage.html#mongodb>`_
|
|
|
|
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 leave it to fate
|
|
some_storage = storage.storage.from_string(fate)
|
|
|
|
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>`_
|
|
|