File: throttler.py

package info (click to toggle)
python-throttler 1.2.2-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 180 kB
  • sloc: python: 473; makefile: 4; sh: 2
file content (41 lines) | stat: -rw-r--r-- 1,327 bytes parent folder | download
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
import asyncio
import time
from collections import deque
from typing import Union


class Throttler:
    """
    Context manager for limiting rate of accessing to context block.

    Example usages:
        - https://github.com/uburuntu/throttler/blob/master/examples/example_throttlers.py
        - https://github.com/uburuntu/throttler/blob/master/examples/example_throttlers_aiohttp.py
    """
    __slots__ = ('_rate_limit', '_period', '_times',)

    def __init__(self, rate_limit: int, period: Union[int, float] = 1.0):
        if not (isinstance(rate_limit, int) and rate_limit > 0):
            raise ValueError('`rate_limit` should be positive integer')

        if not (isinstance(period, (int, float)) and period > 0.):
            raise ValueError('`period` should be positive float')

        self._rate_limit = float(rate_limit)
        self._period = float(period)

        self._times = deque(0. for _ in range(rate_limit))

    async def __aenter__(self):
        while True:
            curr_ts = time.monotonic()
            diff = curr_ts - (self._times[0] + self._period)
            if diff > 0.:
                self._times.popleft()
                break
            await asyncio.sleep(-diff)

        self._times.append(curr_ts)

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        pass