core-https 2.0.2__tar.gz → 2.0.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. {core_https-2.0.2 → core_https-2.0.3}/PKG-INFO +7 -4
  2. core_https-2.0.3/core_https/requesters/aiohttp_rate_limit.py +60 -0
  3. core_https-2.0.3/core_https/requesters/aiohttp_throttle.py +54 -0
  4. {core_https-2.0.2 → core_https-2.0.3}/core_https.egg-info/PKG-INFO +7 -4
  5. {core_https-2.0.2 → core_https-2.0.3}/core_https.egg-info/SOURCES.txt +2 -0
  6. {core_https-2.0.2 → core_https-2.0.3}/core_https.egg-info/requires.txt +5 -3
  7. {core_https-2.0.2 → core_https-2.0.3}/pyproject.toml +9 -4
  8. {core_https-2.0.2 → core_https-2.0.3}/LICENSE +0 -0
  9. {core_https-2.0.2 → core_https-2.0.3}/README.rst +0 -0
  10. {core_https-2.0.2 → core_https-2.0.3}/core_https/__init__.py +0 -0
  11. {core_https-2.0.2 → core_https-2.0.3}/core_https/exceptions.py +0 -0
  12. {core_https-2.0.2 → core_https-2.0.3}/core_https/py.typed +0 -0
  13. {core_https-2.0.2 → core_https-2.0.3}/core_https/requesters/__init__.py +0 -0
  14. {core_https-2.0.2 → core_https-2.0.3}/core_https/requesters/aiohttp_.py +0 -0
  15. {core_https-2.0.2 → core_https-2.0.3}/core_https/requesters/base.py +0 -0
  16. {core_https-2.0.2 → core_https-2.0.3}/core_https/requesters/requests_.py +0 -0
  17. {core_https-2.0.2 → core_https-2.0.3}/core_https/requesters/urllib3_.py +0 -0
  18. {core_https-2.0.2 → core_https-2.0.3}/core_https/tests/__init__.py +0 -0
  19. {core_https-2.0.2 → core_https-2.0.3}/core_https/tests/aiohttp_.py +0 -0
  20. {core_https-2.0.2 → core_https-2.0.3}/core_https/tests/base.py +0 -0
  21. {core_https-2.0.2 → core_https-2.0.3}/core_https/tests/decorators.py +0 -0
  22. {core_https-2.0.2 → core_https-2.0.3}/core_https/tests/requests_.py +0 -0
  23. {core_https-2.0.2 → core_https-2.0.3}/core_https/tests/urllib3_.py +0 -0
  24. {core_https-2.0.2 → core_https-2.0.3}/core_https/utils.py +0 -0
  25. {core_https-2.0.2 → core_https-2.0.3}/core_https.egg-info/dependency_links.txt +0 -0
  26. {core_https-2.0.2 → core_https-2.0.3}/core_https.egg-info/top_level.txt +0 -0
  27. {core_https-2.0.2 → core_https-2.0.3}/setup.cfg +0 -0
  28. {core_https-2.0.2 → core_https-2.0.3}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: core-https
3
- Version: 2.0.2
3
+ Version: 2.0.3
4
4
  Summary: This project/library contains common elements related to HTTP & API services...
5
5
  Author-email: Alejandro Cora González <alek.cora.glez@gmail.com>
6
6
  Maintainer: Alejandro Cora González
@@ -24,14 +24,17 @@ Classifier: Programming Language :: Python :: 3.13
24
24
  Requires-Python: >=3.9
25
25
  Description-Content-Type: text/x-rst
26
26
  License-File: LICENSE
27
- Requires-Dist: aiohttp<4.0.0,>=3.12.0; python_version >= "3.9"
27
+ Requires-Dist: aiohttp<4.0.0,>=3.12.0
28
28
  Requires-Dist: core-mixins>=2.2.2
29
- Requires-Dist: requests<3.0.0,>=2.32.3; python_version >= "3.9"
30
- Requires-Dist: urllib3<3.0.0,>=2.2.3; python_version >= "3.9"
29
+ Requires-Dist: requests<3.0.0,>=2.32.3
30
+ Requires-Dist: urllib3<3.0.0,>=2.2.3
31
31
  Provides-Extra: dev
32
+ Requires-Dist: aiolimiter<2.0.0,>=1.2.1; extra == "dev"
32
33
  Requires-Dist: core-dev-tools>=1.0.1; extra == "dev"
33
34
  Requires-Dist: core-tests>=2.0.2; extra == "dev"
34
35
  Requires-Dist: types-requests>=2.32.0.20250602; extra == "dev"
36
+ Provides-Extra: extras
37
+ Requires-Dist: aiolimiter<2.0.0,>=1.2.1; extra == "extras"
35
38
  Dynamic: license-file
36
39
 
37
40
  core-https
@@ -0,0 +1,60 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from aiohttp import ClientResponse
4
+ from aiolimiter import AsyncLimiter
5
+
6
+ from core_https.requesters.aiohttp_throttle import AioHttpThrottleRequester
7
+
8
+
9
+ class AioHttpRateLimitRequester(AioHttpThrottleRequester):
10
+ """
11
+ An HTTP requester that enforces a simple *rate limit* using
12
+ :class:`aiolimiter.AsyncLimiter`. This class restricts how many
13
+ requests may be *started* within a given time window. It does **not**
14
+ limit concurrency; multiple requests may still run in parallel
15
+ if they acquire permission within the same window.
16
+ """
17
+
18
+ def __init__(
19
+ self,
20
+ max_concurrency: int,
21
+ max_rate: int,
22
+ time_period: float,
23
+ **kwargs
24
+ ) -> None:
25
+ """
26
+ Initialize the rate-limited requester.
27
+
28
+ :param max_rate: Maximum number of requests allowed within the time window.
29
+ :param time_period: Duration (in seconds) of the rate-limiting window.
30
+ :param kwargs: Additional keyword arguments passed to :class:`AioHttpRequester`.
31
+ """
32
+
33
+ if max_rate <= 0:
34
+ raise ValueError("`max_rate` must be positive!")
35
+
36
+ if time_period <= 0:
37
+ raise ValueError("`time_period` must be positive!")
38
+
39
+ super().__init__(max_concurrency=max_concurrency, **kwargs)
40
+
41
+ self.max_rate = max_rate
42
+ self.time_period = time_period
43
+
44
+ self._limiter = AsyncLimiter(
45
+ max_rate=self.max_rate,
46
+ time_period=self.time_period,
47
+ )
48
+
49
+ async def request(self, *args, **kwargs) -> ClientResponse:
50
+ """
51
+ Execute an HTTP request subject to the configured rate limit. The
52
+ coroutine will wait (non-blocking) until a rate slot becomes available,
53
+ and then delegate the call to the base :class:`AioHttpRequester`.
54
+
55
+ :return: The HTTP response object.
56
+ :raises Exception: Any exception raised by the underlying HTTP client.
57
+ """
58
+
59
+ async with self._limiter:
60
+ return await super().request(*args, **kwargs)
@@ -0,0 +1,54 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ import asyncio
4
+
5
+ from aiohttp import ClientResponse
6
+
7
+ from core_https.requesters.aiohttp_ import AioHttpRequester
8
+
9
+
10
+ class AioHttpThrottleRequester(AioHttpRequester):
11
+ """
12
+ An `AioHttpRequester` implementation that limits the number of
13
+ concurrent in-flight HTTP requests using an `asyncio.Semaphore`. This
14
+ throttler enforces *max_concurrency* at the coroutine level within a
15
+ single event loop. Each call to :meth:`request` must acquire a semaphore
16
+ permit before dispatching the actual HTTP request.
17
+
18
+ **Notes:**
19
+
20
+ - The throttling mechanism limits only concurrent *coroutine execution*. It
21
+ does not enforce rate limiting (requests per second).
22
+ - If you override :meth:`request` in a subclass, be aware that
23
+ `await super().request(...)` calls the parent implementation (so the parent
24
+ semaphore *will* be used for the actual HTTP call). However, any code you
25
+ run **before** or **after** that `super()` call executes outside the parent's
26
+ semaphore (and therefore is not throttled).
27
+ """
28
+
29
+ def __init__(self, max_concurrency: int, **kwargs) -> None:
30
+ """
31
+ :param max_concurrency: Maximum number of concurrent requests allowed.
32
+ :param kwargs: Passed through to :class:`AioHttpRequester`.
33
+ """
34
+
35
+ super().__init__(**kwargs)
36
+ self.max_concurrency = max_concurrency
37
+ self._semaphore = asyncio.Semaphore(self.max_concurrency)
38
+
39
+ @classmethod
40
+ def registration_key(cls) -> str:
41
+ return cls.__name__
42
+
43
+ async def request(self, *args, **kwargs) -> ClientResponse:
44
+ """
45
+ Execute an HTTP request with concurrency throttling. It acquires
46
+ a semaphore permit before delegating the actual request to the
47
+ underlying :class:`AioHttpRequester` implementation.
48
+
49
+ :returns: The aiohttp response object.
50
+ :raises: Any exception raised by the underlying session.
51
+ """
52
+
53
+ async with self._semaphore:
54
+ return await super().request(*args, **kwargs)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: core-https
3
- Version: 2.0.2
3
+ Version: 2.0.3
4
4
  Summary: This project/library contains common elements related to HTTP & API services...
5
5
  Author-email: Alejandro Cora González <alek.cora.glez@gmail.com>
6
6
  Maintainer: Alejandro Cora González
@@ -24,14 +24,17 @@ Classifier: Programming Language :: Python :: 3.13
24
24
  Requires-Python: >=3.9
25
25
  Description-Content-Type: text/x-rst
26
26
  License-File: LICENSE
27
- Requires-Dist: aiohttp<4.0.0,>=3.12.0; python_version >= "3.9"
27
+ Requires-Dist: aiohttp<4.0.0,>=3.12.0
28
28
  Requires-Dist: core-mixins>=2.2.2
29
- Requires-Dist: requests<3.0.0,>=2.32.3; python_version >= "3.9"
30
- Requires-Dist: urllib3<3.0.0,>=2.2.3; python_version >= "3.9"
29
+ Requires-Dist: requests<3.0.0,>=2.32.3
30
+ Requires-Dist: urllib3<3.0.0,>=2.2.3
31
31
  Provides-Extra: dev
32
+ Requires-Dist: aiolimiter<2.0.0,>=1.2.1; extra == "dev"
32
33
  Requires-Dist: core-dev-tools>=1.0.1; extra == "dev"
33
34
  Requires-Dist: core-tests>=2.0.2; extra == "dev"
34
35
  Requires-Dist: types-requests>=2.32.0.20250602; extra == "dev"
36
+ Provides-Extra: extras
37
+ Requires-Dist: aiolimiter<2.0.0,>=1.2.1; extra == "extras"
35
38
  Dynamic: license-file
36
39
 
37
40
  core-https
@@ -13,6 +13,8 @@ core_https.egg-info/requires.txt
13
13
  core_https.egg-info/top_level.txt
14
14
  core_https/requesters/__init__.py
15
15
  core_https/requesters/aiohttp_.py
16
+ core_https/requesters/aiohttp_rate_limit.py
17
+ core_https/requesters/aiohttp_throttle.py
16
18
  core_https/requesters/base.py
17
19
  core_https/requesters/requests_.py
18
20
  core_https/requesters/urllib3_.py
@@ -1,11 +1,13 @@
1
- core-mixins>=2.2.2
2
-
3
- [:python_version >= "3.9"]
4
1
  aiohttp<4.0.0,>=3.12.0
2
+ core-mixins>=2.2.2
5
3
  requests<3.0.0,>=2.32.3
6
4
  urllib3<3.0.0,>=2.2.3
7
5
 
8
6
  [dev]
7
+ aiolimiter<2.0.0,>=1.2.1
9
8
  core-dev-tools>=1.0.1
10
9
  core-tests>=2.0.2
11
10
  types-requests>=2.32.0.20250602
11
+
12
+ [extras]
13
+ aiolimiter<2.0.0,>=1.2.1
@@ -9,7 +9,7 @@ build-backend = "setuptools.build_meta"
9
9
  [project]
10
10
  name = "core-https"
11
11
  description = "This project/library contains common elements related to HTTP & API services..."
12
- version = "2.0.2"
12
+ version = "2.0.3"
13
13
 
14
14
  authors = [
15
15
  {name = "Alejandro Cora González", email = "alek.cora.glez@gmail.com"}
@@ -39,19 +39,24 @@ classifiers = [
39
39
  ]
40
40
 
41
41
  dependencies = [
42
- "aiohttp>=3.12.0,<4.0.0; python_version >= '3.9'",
42
+ "aiohttp>=3.12.0,<4.0.0",
43
43
  "core-mixins>=2.2.2",
44
- "requests>=2.32.3,<3.0.0; python_version >= '3.9'",
45
- "urllib3>=2.2.3,<3.0.0; python_version >= '3.9'",
44
+ "requests>=2.32.3,<3.0.0",
45
+ "urllib3>=2.2.3,<3.0.0",
46
46
  ]
47
47
 
48
48
  [project.optional-dependencies]
49
49
  dev = [
50
+ "aiolimiter>=1.2.1,<2.0.0",
50
51
  "core-dev-tools>=1.0.1",
51
52
  "core-tests>=2.0.2",
52
53
  "types-requests>=2.32.0.20250602",
53
54
  ]
54
55
 
56
+ extras = [
57
+ "aiolimiter>=1.2.1,<2.0.0",
58
+ ]
59
+
55
60
  [project.urls]
56
61
  Homepage = "https://gitlab.com/bytecode-solutions/core/core-https"
57
62
  Repository = "https://gitlab.com/bytecode-solutions/core/core-https"
File without changes
File without changes
File without changes
File without changes