summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCoprDistGit <infra@openeuler.org>2023-05-05 08:44:40 +0000
committerCoprDistGit <infra@openeuler.org>2023-05-05 08:44:40 +0000
commit0e97a29faeb6f2e544b7fd4bf3e7fb66f0679676 (patch)
treec1edeb07e9012fdb36e639ca9ea80835eff09cbb
parentfc5cb8dab03333ad0ab86e72d300c71e335d6f80 (diff)
automatic import of python-limiteropeneuler20.03
-rw-r--r--.gitignore1
-rw-r--r--python-limiter.spec686
-rw-r--r--sources1
3 files changed, 688 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index e69de29..160aa92 100644
--- a/.gitignore
+++ b/.gitignore
@@ -0,0 +1 @@
+/limiter-0.3.1.tar.gz
diff --git a/python-limiter.spec b/python-limiter.spec
new file mode 100644
index 0000000..75c99cc
--- /dev/null
+++ b/python-limiter.spec
@@ -0,0 +1,686 @@
+%global _empty_manifest_terminate_build 0
+Name: python-limiter
+Version: 0.3.1
+Release: 1
+Summary: ⏲️ Easy rate limiting for Python. Rate limiting async and thread-safe decorators and context managers that use a token bucket algorithm.
+License: AGPL-3.0
+URL: https://github.com/alexdelorenzo/limiter
+Source0: https://mirrors.nju.edu.cn/pypi/web/packages/93/14/cf5fc005b55a8678fb2553cf132217ccb120c319f5975b2bee86b4381e4f/limiter-0.3.1.tar.gz
+BuildArch: noarch
+
+Requires: python3-strenum
+Requires: python3-token-bucket
+
+%description
+# ⏲️ Easy rate limiting for Python
+
+`limiter` makes it easy to add [rate limiting](https://en.wikipedia.org/wiki/Rate_limiting) to Python projects, using a [token bucket](https://en.wikipedia.org/wiki/Token_bucket) algorithm. `limiter` can provide Python projects and scripts with:
+ - Rate limiting thread-safe [decorators](https://www.python.org/dev/peps/pep-0318/)
+ - Rate limiting async decorators
+ - Rate limiting thread-safe [context managers](https://www.python.org/dev/peps/pep-0343/)
+ - Rate limiting [async context managers](https://www.python.org/dev/peps/pep-0492/#asynchronous-context-managers-and-async-with)
+
+Here are some features and benefits of using `limiter`:
+ - Easily control burst and average request rates
+ - It is [thread-safe, with no need for a timer thread](https://en.wikipedia.org/wiki/Generic_cell_rate_algorithm#Comparison_with_the_token_bucket)
+ - It adds [jitter](https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/) to help with contention
+ - It has a simple API that takes advantage of Python's features, idioms and [type hinting](https://www.python.org/dev/peps/pep-0483/)
+
+## Example
+Here's an example of using a limiter as a decorator and context manager:
+```python
+from aiohttp import ClientSession
+from limiter import Limiter
+
+
+limit_downloads = Limiter(rate=2, capacity=5, consume=2)
+
+
+@limit_downloads
+async def download_image(url: str) -> bytes:
+ async with ClientSession() as session, session.get(url) as response:
+ return await response.read()
+
+
+async def download_page(url: str) -> str:
+ async with (
+ ClientSession() as session,
+ limit_downloads,
+ session.get(url) as response
+ ):
+ return await response.text()
+```
+
+# Usage
+You can define limiters and use them dynamically across your project.
+
+**Note**: If you're using Python version `3.9.x` or below, check out [the documentation for version `0.2.0` of `limiter` here](https://github.com/alexdelorenzo/limiter/blob/master/README-0.2.0.md).
+
+### Limiting blocks of code
+`limiter` can rate limit all Python callables, and limiters can be used as context managers.
+
+You can define a limiter with a set refresh `rate` and total token `capacity`. You can set the amount of tokens to consume dynamically with `consume`, and the `bucket` parameter sets the bucket to consume tokens from:
+```python3
+from limiter import Limiter
+
+
+REFRESH_RATE: int = 2
+BURST_RATE: int = 3
+MSG_BUCKET: str = 'messages'
+
+
+limiter: Limiter = Limiter(rate=REFRESH_RATE, capacity=BURST_RATE)
+limit_msgs: Limiter = limiter(bucket=MSG_BUCKET)
+
+
+@limiter
+def download_page(url: str) -> bytes:
+ ...
+
+
+@limiter(consume=2)
+async def download_page(url: str) -> bytes:
+ ...
+
+
+def send_page(page: bytes):
+ with limiter(consume=1.5, bucket=MSG_BUCKET):
+ ...
+
+
+async def send_page(page: bytes):
+ async with limit_msgs:
+ ...
+
+
+@limit_msgs(consume=3)
+def send_email(to: str):
+ ...
+
+
+async def send_email(to: str):
+ async with limiter(bucket=MSG_BUCKET):
+ ...
+```
+
+In the example above, both `limiter` and `limit_msgs` share the same limiter. The only difference is that `limit_msgs` will take tokens from the `MSG_BUCKET` bucket by default.
+
+```python3
+assert limiter.limiter is limit_msgs.limiter
+assert limiter.bucket != limit_msgs.bucket
+assert limiter != limit_msgs
+```
+
+### Creating new limiters
+You can reuse existing limiters in your code, and you can create new limiters from the parameters of an existing limiter using the `new()` method.
+
+Or, you can define a new limiter entirely:
+```python
+# you can reuse existing limiters
+limit_downloads: Limiter = limiter(consume=2)
+
+# you can use the settings from an existing limiter in a new limiter
+limit_downloads: Limiter = limiter.new(consume=2)
+
+# or you can simply define a new limiter
+limit_downloads: Limiter = Limiter(REFRESH_RATE, BURST_RATE, consume=2)
+
+
+@limit_downloads
+def download_page(url: str) -> bytes:
+ ...
+
+
+@limit_downloads
+async def download_page(url: str) -> bytes:
+ ...
+
+
+def download_image(url: str) -> bytes:
+ with limit_downloads:
+ ...
+
+
+async def download_image(url: str) -> bytes:
+ async with limit_downloads:
+ ...
+```
+
+Let's look at the difference between reusing an existing limiter, and creating new limiters with the `new()` method:
+```python3
+limiter_a: Limiter = limiter(consume=2)
+limiter_b: Limiter = limiter.new(consume=2)
+limiter_c: Limiter = Limiter(REFRESH_RATE, BURST_RATE, consume=2)
+
+assert limiter_a != limiter
+assert limiter_a != limiter_b != limiter_c
+
+assert limiter_a != limiter_b
+assert limiter_a.limiter is limiter.limiter
+assert limiter_a.limiter is not limiter_b.limiter
+
+assert limiter_a.attrs == limiter_b.attrs == limiter_c.attrs
+```
+
+The only things that are equivalent between the three new limiters above are the limiters' attributes, like the `rate`, `capacity`, and `consume` attributes.
+
+### Creating anonymous, or single-use, limiters
+You don't have to assign `Limiter` objects to variables. Anonymous limiters don't share a token bucket like named limiters can. They work well when you don't have a reason to share a limiter between two or more blocks of code, and when a limiter has a single or independent purpose.
+
+`limiter`, after version `v0.3.0`, ships with a `limit` type alias for `Limiter`:
+```python3
+from limiter import limit
+
+
+@limit(capacity=2, consume=2)
+async def send_message():
+ ...
+
+
+async def upload_image():
+ async with limit(capacity=3) as limiter:
+ ...
+```
+
+The above is equivalent to the below:
+```python3
+from limiter import Limiter
+
+
+@Limiter(capacity=2, consume=2)
+async def send_message():
+ ...
+
+
+async def upload_image():
+ async with Limiter(capacity=3) as limiter:
+ ...
+```
+
+Both `limit` and `Limiter` are the same object:
+```python3
+assert limit is Limiter
+```
+
+# Installation
+## Requirements
+ - Python 3.10+ for versions `0.3.0` and up
+ - [Python 3.7+ for versions below `0.3.0`](https://github.com/alexdelorenzo/limiter/blob/master/README-0.2.0.md)
+
+## Install via PyPI
+```bash
+$ python3 -m pip install limiter
+```
+
+# License
+See [`LICENSE`](/LICENSE). If you'd like to use this project with a different license, please get in touch.
+
+
+
+
+%package -n python3-limiter
+Summary: ⏲️ Easy rate limiting for Python. Rate limiting async and thread-safe decorators and context managers that use a token bucket algorithm.
+Provides: python-limiter
+BuildRequires: python3-devel
+BuildRequires: python3-setuptools
+BuildRequires: python3-pip
+%description -n python3-limiter
+# ⏲️ Easy rate limiting for Python
+
+`limiter` makes it easy to add [rate limiting](https://en.wikipedia.org/wiki/Rate_limiting) to Python projects, using a [token bucket](https://en.wikipedia.org/wiki/Token_bucket) algorithm. `limiter` can provide Python projects and scripts with:
+ - Rate limiting thread-safe [decorators](https://www.python.org/dev/peps/pep-0318/)
+ - Rate limiting async decorators
+ - Rate limiting thread-safe [context managers](https://www.python.org/dev/peps/pep-0343/)
+ - Rate limiting [async context managers](https://www.python.org/dev/peps/pep-0492/#asynchronous-context-managers-and-async-with)
+
+Here are some features and benefits of using `limiter`:
+ - Easily control burst and average request rates
+ - It is [thread-safe, with no need for a timer thread](https://en.wikipedia.org/wiki/Generic_cell_rate_algorithm#Comparison_with_the_token_bucket)
+ - It adds [jitter](https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/) to help with contention
+ - It has a simple API that takes advantage of Python's features, idioms and [type hinting](https://www.python.org/dev/peps/pep-0483/)
+
+## Example
+Here's an example of using a limiter as a decorator and context manager:
+```python
+from aiohttp import ClientSession
+from limiter import Limiter
+
+
+limit_downloads = Limiter(rate=2, capacity=5, consume=2)
+
+
+@limit_downloads
+async def download_image(url: str) -> bytes:
+ async with ClientSession() as session, session.get(url) as response:
+ return await response.read()
+
+
+async def download_page(url: str) -> str:
+ async with (
+ ClientSession() as session,
+ limit_downloads,
+ session.get(url) as response
+ ):
+ return await response.text()
+```
+
+# Usage
+You can define limiters and use them dynamically across your project.
+
+**Note**: If you're using Python version `3.9.x` or below, check out [the documentation for version `0.2.0` of `limiter` here](https://github.com/alexdelorenzo/limiter/blob/master/README-0.2.0.md).
+
+### Limiting blocks of code
+`limiter` can rate limit all Python callables, and limiters can be used as context managers.
+
+You can define a limiter with a set refresh `rate` and total token `capacity`. You can set the amount of tokens to consume dynamically with `consume`, and the `bucket` parameter sets the bucket to consume tokens from:
+```python3
+from limiter import Limiter
+
+
+REFRESH_RATE: int = 2
+BURST_RATE: int = 3
+MSG_BUCKET: str = 'messages'
+
+
+limiter: Limiter = Limiter(rate=REFRESH_RATE, capacity=BURST_RATE)
+limit_msgs: Limiter = limiter(bucket=MSG_BUCKET)
+
+
+@limiter
+def download_page(url: str) -> bytes:
+ ...
+
+
+@limiter(consume=2)
+async def download_page(url: str) -> bytes:
+ ...
+
+
+def send_page(page: bytes):
+ with limiter(consume=1.5, bucket=MSG_BUCKET):
+ ...
+
+
+async def send_page(page: bytes):
+ async with limit_msgs:
+ ...
+
+
+@limit_msgs(consume=3)
+def send_email(to: str):
+ ...
+
+
+async def send_email(to: str):
+ async with limiter(bucket=MSG_BUCKET):
+ ...
+```
+
+In the example above, both `limiter` and `limit_msgs` share the same limiter. The only difference is that `limit_msgs` will take tokens from the `MSG_BUCKET` bucket by default.
+
+```python3
+assert limiter.limiter is limit_msgs.limiter
+assert limiter.bucket != limit_msgs.bucket
+assert limiter != limit_msgs
+```
+
+### Creating new limiters
+You can reuse existing limiters in your code, and you can create new limiters from the parameters of an existing limiter using the `new()` method.
+
+Or, you can define a new limiter entirely:
+```python
+# you can reuse existing limiters
+limit_downloads: Limiter = limiter(consume=2)
+
+# you can use the settings from an existing limiter in a new limiter
+limit_downloads: Limiter = limiter.new(consume=2)
+
+# or you can simply define a new limiter
+limit_downloads: Limiter = Limiter(REFRESH_RATE, BURST_RATE, consume=2)
+
+
+@limit_downloads
+def download_page(url: str) -> bytes:
+ ...
+
+
+@limit_downloads
+async def download_page(url: str) -> bytes:
+ ...
+
+
+def download_image(url: str) -> bytes:
+ with limit_downloads:
+ ...
+
+
+async def download_image(url: str) -> bytes:
+ async with limit_downloads:
+ ...
+```
+
+Let's look at the difference between reusing an existing limiter, and creating new limiters with the `new()` method:
+```python3
+limiter_a: Limiter = limiter(consume=2)
+limiter_b: Limiter = limiter.new(consume=2)
+limiter_c: Limiter = Limiter(REFRESH_RATE, BURST_RATE, consume=2)
+
+assert limiter_a != limiter
+assert limiter_a != limiter_b != limiter_c
+
+assert limiter_a != limiter_b
+assert limiter_a.limiter is limiter.limiter
+assert limiter_a.limiter is not limiter_b.limiter
+
+assert limiter_a.attrs == limiter_b.attrs == limiter_c.attrs
+```
+
+The only things that are equivalent between the three new limiters above are the limiters' attributes, like the `rate`, `capacity`, and `consume` attributes.
+
+### Creating anonymous, or single-use, limiters
+You don't have to assign `Limiter` objects to variables. Anonymous limiters don't share a token bucket like named limiters can. They work well when you don't have a reason to share a limiter between two or more blocks of code, and when a limiter has a single or independent purpose.
+
+`limiter`, after version `v0.3.0`, ships with a `limit` type alias for `Limiter`:
+```python3
+from limiter import limit
+
+
+@limit(capacity=2, consume=2)
+async def send_message():
+ ...
+
+
+async def upload_image():
+ async with limit(capacity=3) as limiter:
+ ...
+```
+
+The above is equivalent to the below:
+```python3
+from limiter import Limiter
+
+
+@Limiter(capacity=2, consume=2)
+async def send_message():
+ ...
+
+
+async def upload_image():
+ async with Limiter(capacity=3) as limiter:
+ ...
+```
+
+Both `limit` and `Limiter` are the same object:
+```python3
+assert limit is Limiter
+```
+
+# Installation
+## Requirements
+ - Python 3.10+ for versions `0.3.0` and up
+ - [Python 3.7+ for versions below `0.3.0`](https://github.com/alexdelorenzo/limiter/blob/master/README-0.2.0.md)
+
+## Install via PyPI
+```bash
+$ python3 -m pip install limiter
+```
+
+# License
+See [`LICENSE`](/LICENSE). If you'd like to use this project with a different license, please get in touch.
+
+
+
+
+%package help
+Summary: Development documents and examples for limiter
+Provides: python3-limiter-doc
+%description help
+# ⏲️ Easy rate limiting for Python
+
+`limiter` makes it easy to add [rate limiting](https://en.wikipedia.org/wiki/Rate_limiting) to Python projects, using a [token bucket](https://en.wikipedia.org/wiki/Token_bucket) algorithm. `limiter` can provide Python projects and scripts with:
+ - Rate limiting thread-safe [decorators](https://www.python.org/dev/peps/pep-0318/)
+ - Rate limiting async decorators
+ - Rate limiting thread-safe [context managers](https://www.python.org/dev/peps/pep-0343/)
+ - Rate limiting [async context managers](https://www.python.org/dev/peps/pep-0492/#asynchronous-context-managers-and-async-with)
+
+Here are some features and benefits of using `limiter`:
+ - Easily control burst and average request rates
+ - It is [thread-safe, with no need for a timer thread](https://en.wikipedia.org/wiki/Generic_cell_rate_algorithm#Comparison_with_the_token_bucket)
+ - It adds [jitter](https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/) to help with contention
+ - It has a simple API that takes advantage of Python's features, idioms and [type hinting](https://www.python.org/dev/peps/pep-0483/)
+
+## Example
+Here's an example of using a limiter as a decorator and context manager:
+```python
+from aiohttp import ClientSession
+from limiter import Limiter
+
+
+limit_downloads = Limiter(rate=2, capacity=5, consume=2)
+
+
+@limit_downloads
+async def download_image(url: str) -> bytes:
+ async with ClientSession() as session, session.get(url) as response:
+ return await response.read()
+
+
+async def download_page(url: str) -> str:
+ async with (
+ ClientSession() as session,
+ limit_downloads,
+ session.get(url) as response
+ ):
+ return await response.text()
+```
+
+# Usage
+You can define limiters and use them dynamically across your project.
+
+**Note**: If you're using Python version `3.9.x` or below, check out [the documentation for version `0.2.0` of `limiter` here](https://github.com/alexdelorenzo/limiter/blob/master/README-0.2.0.md).
+
+### Limiting blocks of code
+`limiter` can rate limit all Python callables, and limiters can be used as context managers.
+
+You can define a limiter with a set refresh `rate` and total token `capacity`. You can set the amount of tokens to consume dynamically with `consume`, and the `bucket` parameter sets the bucket to consume tokens from:
+```python3
+from limiter import Limiter
+
+
+REFRESH_RATE: int = 2
+BURST_RATE: int = 3
+MSG_BUCKET: str = 'messages'
+
+
+limiter: Limiter = Limiter(rate=REFRESH_RATE, capacity=BURST_RATE)
+limit_msgs: Limiter = limiter(bucket=MSG_BUCKET)
+
+
+@limiter
+def download_page(url: str) -> bytes:
+ ...
+
+
+@limiter(consume=2)
+async def download_page(url: str) -> bytes:
+ ...
+
+
+def send_page(page: bytes):
+ with limiter(consume=1.5, bucket=MSG_BUCKET):
+ ...
+
+
+async def send_page(page: bytes):
+ async with limit_msgs:
+ ...
+
+
+@limit_msgs(consume=3)
+def send_email(to: str):
+ ...
+
+
+async def send_email(to: str):
+ async with limiter(bucket=MSG_BUCKET):
+ ...
+```
+
+In the example above, both `limiter` and `limit_msgs` share the same limiter. The only difference is that `limit_msgs` will take tokens from the `MSG_BUCKET` bucket by default.
+
+```python3
+assert limiter.limiter is limit_msgs.limiter
+assert limiter.bucket != limit_msgs.bucket
+assert limiter != limit_msgs
+```
+
+### Creating new limiters
+You can reuse existing limiters in your code, and you can create new limiters from the parameters of an existing limiter using the `new()` method.
+
+Or, you can define a new limiter entirely:
+```python
+# you can reuse existing limiters
+limit_downloads: Limiter = limiter(consume=2)
+
+# you can use the settings from an existing limiter in a new limiter
+limit_downloads: Limiter = limiter.new(consume=2)
+
+# or you can simply define a new limiter
+limit_downloads: Limiter = Limiter(REFRESH_RATE, BURST_RATE, consume=2)
+
+
+@limit_downloads
+def download_page(url: str) -> bytes:
+ ...
+
+
+@limit_downloads
+async def download_page(url: str) -> bytes:
+ ...
+
+
+def download_image(url: str) -> bytes:
+ with limit_downloads:
+ ...
+
+
+async def download_image(url: str) -> bytes:
+ async with limit_downloads:
+ ...
+```
+
+Let's look at the difference between reusing an existing limiter, and creating new limiters with the `new()` method:
+```python3
+limiter_a: Limiter = limiter(consume=2)
+limiter_b: Limiter = limiter.new(consume=2)
+limiter_c: Limiter = Limiter(REFRESH_RATE, BURST_RATE, consume=2)
+
+assert limiter_a != limiter
+assert limiter_a != limiter_b != limiter_c
+
+assert limiter_a != limiter_b
+assert limiter_a.limiter is limiter.limiter
+assert limiter_a.limiter is not limiter_b.limiter
+
+assert limiter_a.attrs == limiter_b.attrs == limiter_c.attrs
+```
+
+The only things that are equivalent between the three new limiters above are the limiters' attributes, like the `rate`, `capacity`, and `consume` attributes.
+
+### Creating anonymous, or single-use, limiters
+You don't have to assign `Limiter` objects to variables. Anonymous limiters don't share a token bucket like named limiters can. They work well when you don't have a reason to share a limiter between two or more blocks of code, and when a limiter has a single or independent purpose.
+
+`limiter`, after version `v0.3.0`, ships with a `limit` type alias for `Limiter`:
+```python3
+from limiter import limit
+
+
+@limit(capacity=2, consume=2)
+async def send_message():
+ ...
+
+
+async def upload_image():
+ async with limit(capacity=3) as limiter:
+ ...
+```
+
+The above is equivalent to the below:
+```python3
+from limiter import Limiter
+
+
+@Limiter(capacity=2, consume=2)
+async def send_message():
+ ...
+
+
+async def upload_image():
+ async with Limiter(capacity=3) as limiter:
+ ...
+```
+
+Both `limit` and `Limiter` are the same object:
+```python3
+assert limit is Limiter
+```
+
+# Installation
+## Requirements
+ - Python 3.10+ for versions `0.3.0` and up
+ - [Python 3.7+ for versions below `0.3.0`](https://github.com/alexdelorenzo/limiter/blob/master/README-0.2.0.md)
+
+## Install via PyPI
+```bash
+$ python3 -m pip install limiter
+```
+
+# License
+See [`LICENSE`](/LICENSE). If you'd like to use this project with a different license, please get in touch.
+
+
+
+
+%prep
+%autosetup -n limiter-0.3.1
+
+%build
+%py3_build
+
+%install
+%py3_install
+install -d -m755 %{buildroot}/%{_pkgdocdir}
+if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi
+if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi
+if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi
+if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi
+pushd %{buildroot}
+if [ -d usr/lib ]; then
+ find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/lib64 ]; then
+ find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/bin ]; then
+ find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/sbin ]; then
+ find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+touch doclist.lst
+if [ -d usr/share/man ]; then
+ find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst
+fi
+popd
+mv %{buildroot}/filelist.lst .
+mv %{buildroot}/doclist.lst .
+
+%files -n python3-limiter -f filelist.lst
+%dir %{python3_sitelib}/*
+
+%files help -f doclist.lst
+%{_docdir}/*
+
+%changelog
+* Fri May 05 2023 Python_Bot <Python_Bot@openeuler.org> - 0.3.1-1
+- Package Spec generated
diff --git a/sources b/sources
new file mode 100644
index 0000000..33ea8fe
--- /dev/null
+++ b/sources
@@ -0,0 +1 @@
+649545ba807aac18c0d5f74be6af48ab limiter-0.3.1.tar.gz