limits 3.11.0__py3-none-any.whl → 3.12.0__py3-none-any.whl
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.
- limits/_version.py +3 -3
- limits/aio/storage/base.py +1 -1
- limits/storage/__init__.py +2 -1
- limits/storage/mongodb.py +53 -16
- limits/typing.py +10 -1
- {limits-3.11.0.dist-info → limits-3.12.0.dist-info}/METADATA +1 -1
- {limits-3.11.0.dist-info → limits-3.12.0.dist-info}/RECORD +10 -10
- {limits-3.11.0.dist-info → limits-3.12.0.dist-info}/LICENSE.txt +0 -0
- {limits-3.11.0.dist-info → limits-3.12.0.dist-info}/WHEEL +0 -0
- {limits-3.11.0.dist-info → limits-3.12.0.dist-info}/top_level.txt +0 -0
limits/_version.py
CHANGED
|
@@ -8,11 +8,11 @@ import json
|
|
|
8
8
|
|
|
9
9
|
version_json = '''
|
|
10
10
|
{
|
|
11
|
-
"date": "2024-
|
|
11
|
+
"date": "2024-05-12T10:01:06-0700",
|
|
12
12
|
"dirty": false,
|
|
13
13
|
"error": null,
|
|
14
|
-
"full-revisionid": "
|
|
15
|
-
"version": "3.
|
|
14
|
+
"full-revisionid": "ff28751a2326de0ad6a978e316397534acf29b81",
|
|
15
|
+
"version": "3.12.0"
|
|
16
16
|
}
|
|
17
17
|
''' # END VERSION_JSON
|
|
18
18
|
|
limits/aio/storage/base.py
CHANGED
|
@@ -27,7 +27,7 @@ def _wrap_errors(
|
|
|
27
27
|
fn: Callable[P, Awaitable[R]],
|
|
28
28
|
) -> Callable[P, Awaitable[R]]:
|
|
29
29
|
@functools.wraps(fn)
|
|
30
|
-
async def inner(*args: P.args, **kwargs: P.kwargs) -> R:
|
|
30
|
+
async def inner(*args: P.args, **kwargs: P.kwargs) -> R: # type: ignore[misc]
|
|
31
31
|
try:
|
|
32
32
|
return await fn(*args, **kwargs)
|
|
33
33
|
except storage.base_exceptions as exc:
|
limits/storage/__init__.py
CHANGED
|
@@ -13,7 +13,7 @@ from .base import MovingWindowSupport, Storage
|
|
|
13
13
|
from .etcd import EtcdStorage
|
|
14
14
|
from .memcached import MemcachedStorage
|
|
15
15
|
from .memory import MemoryStorage
|
|
16
|
-
from .mongodb import MongoDBStorage
|
|
16
|
+
from .mongodb import MongoDBStorage, MongoDBStorageBase
|
|
17
17
|
from .redis import RedisStorage
|
|
18
18
|
from .redis_cluster import RedisClusterStorage
|
|
19
19
|
from .redis_sentinel import RedisSentinelStorage
|
|
@@ -68,6 +68,7 @@ __all__ = [
|
|
|
68
68
|
"Storage",
|
|
69
69
|
"MovingWindowSupport",
|
|
70
70
|
"EtcdStorage",
|
|
71
|
+
"MongoDBStorageBase",
|
|
71
72
|
"MemoryStorage",
|
|
72
73
|
"MongoDBStorage",
|
|
73
74
|
"RedisStorage",
|
limits/storage/mongodb.py
CHANGED
|
@@ -3,29 +3,33 @@ from __future__ import annotations
|
|
|
3
3
|
import calendar
|
|
4
4
|
import datetime
|
|
5
5
|
import time
|
|
6
|
-
from
|
|
6
|
+
from abc import ABC, abstractmethod
|
|
7
|
+
from typing import Any, cast
|
|
7
8
|
|
|
8
9
|
from deprecated.sphinx import versionadded
|
|
9
10
|
|
|
10
|
-
from limits.typing import
|
|
11
|
+
from limits.typing import (
|
|
12
|
+
Dict,
|
|
13
|
+
MongoClient,
|
|
14
|
+
MongoCollection,
|
|
15
|
+
MongoDatabase,
|
|
16
|
+
Optional,
|
|
17
|
+
Tuple,
|
|
18
|
+
Type,
|
|
19
|
+
Union,
|
|
20
|
+
)
|
|
11
21
|
|
|
12
22
|
from ..util import get_dependency
|
|
13
23
|
from .base import MovingWindowSupport, Storage
|
|
14
24
|
|
|
15
|
-
if TYPE_CHECKING:
|
|
16
|
-
import pymongo
|
|
17
25
|
|
|
18
|
-
|
|
19
|
-
@versionadded(version="2.1")
|
|
20
|
-
class MongoDBStorage(Storage, MovingWindowSupport):
|
|
26
|
+
class MongoDBStorageBase(Storage, MovingWindowSupport, ABC):
|
|
21
27
|
"""
|
|
22
28
|
Rate limit storage with MongoDB as backend.
|
|
23
29
|
|
|
24
30
|
Depends on :pypi:`pymongo`.
|
|
25
31
|
"""
|
|
26
32
|
|
|
27
|
-
STORAGE_SCHEME = ["mongodb", "mongodb+srv"]
|
|
28
|
-
|
|
29
33
|
DEPENDENCIES = ["pymongo"]
|
|
30
34
|
|
|
31
35
|
def __init__(
|
|
@@ -48,16 +52,39 @@ class MongoDBStorage(Storage, MovingWindowSupport):
|
|
|
48
52
|
"""
|
|
49
53
|
|
|
50
54
|
super().__init__(uri, wrap_exceptions=wrap_exceptions, **options)
|
|
51
|
-
|
|
55
|
+
self._database_name = database_name
|
|
52
56
|
self.lib = self.dependencies["pymongo"].module
|
|
53
57
|
self.lib_errors, _ = get_dependency("pymongo.errors")
|
|
58
|
+
self._storage_uri = uri
|
|
59
|
+
self._storage_options = options
|
|
60
|
+
self._storage: Optional[MongoClient] = None
|
|
54
61
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
62
|
+
@property
|
|
63
|
+
def storage(self) -> MongoClient:
|
|
64
|
+
if self._storage is None:
|
|
65
|
+
self._storage = self._init_mongo_client(
|
|
66
|
+
self._storage_uri, **self._storage_options
|
|
67
|
+
)
|
|
68
|
+
self.__initialize_database()
|
|
69
|
+
return self._storage
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def _database(self) -> MongoDatabase:
|
|
73
|
+
return self.storage[self._database_name]
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def counters(self) -> MongoCollection:
|
|
77
|
+
return self._database["counters"]
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def windows(self) -> MongoCollection:
|
|
81
|
+
return self._database["windows"]
|
|
82
|
+
|
|
83
|
+
@abstractmethod
|
|
84
|
+
def _init_mongo_client(
|
|
85
|
+
self, uri: Optional[str], **options: Union[int, str, bool]
|
|
86
|
+
) -> MongoClient:
|
|
87
|
+
raise NotImplementedError()
|
|
61
88
|
|
|
62
89
|
@property
|
|
63
90
|
def base_exceptions(
|
|
@@ -248,3 +275,13 @@ class MongoDBStorage(Storage, MovingWindowSupport):
|
|
|
248
275
|
return True
|
|
249
276
|
except self.lib.errors.DuplicateKeyError:
|
|
250
277
|
return False
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
@versionadded(version="2.1")
|
|
281
|
+
class MongoDBStorage(MongoDBStorageBase):
|
|
282
|
+
STORAGE_SCHEME = ["mongodb", "mongodb+srv"]
|
|
283
|
+
|
|
284
|
+
def _init_mongo_client(
|
|
285
|
+
self, uri: Optional[str], **options: Union[int, str, bool]
|
|
286
|
+
) -> MongoClient:
|
|
287
|
+
return cast(MongoClient, self.lib.MongoClient(uri, **options))
|
limits/typing.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from typing import (
|
|
2
2
|
TYPE_CHECKING,
|
|
3
|
+
Any,
|
|
3
4
|
Awaitable,
|
|
4
5
|
Callable,
|
|
5
6
|
Dict,
|
|
@@ -12,7 +13,7 @@ from typing import (
|
|
|
12
13
|
Union,
|
|
13
14
|
)
|
|
14
15
|
|
|
15
|
-
from typing_extensions import ClassVar, Counter, ParamSpec, Protocol
|
|
16
|
+
from typing_extensions import ClassVar, Counter, ParamSpec, Protocol, TypeAlias
|
|
16
17
|
|
|
17
18
|
Serializable = Union[int, str, float]
|
|
18
19
|
|
|
@@ -24,6 +25,7 @@ P = ParamSpec("P")
|
|
|
24
25
|
if TYPE_CHECKING:
|
|
25
26
|
import coredis
|
|
26
27
|
import coredis.commands.script
|
|
28
|
+
import pymongo
|
|
27
29
|
import redis
|
|
28
30
|
|
|
29
31
|
|
|
@@ -107,6 +109,10 @@ class ScriptP(Protocol[R_co]):
|
|
|
107
109
|
def __call__(self, keys: List[Serializable], args: List[Serializable]) -> R_co: ...
|
|
108
110
|
|
|
109
111
|
|
|
112
|
+
MongoClient: TypeAlias = "pymongo.MongoClient[Dict[str, Any]]" # type:ignore[misc]
|
|
113
|
+
MongoDatabase: TypeAlias = "pymongo.database.Database[Dict[str, Any]]" # type:ignore[misc]
|
|
114
|
+
MongoCollection: TypeAlias = "pymongo.collection.Collection[Dict[str, Any]]" # type:ignore[misc]
|
|
115
|
+
|
|
110
116
|
__all__ = [
|
|
111
117
|
"AsyncRedisClient",
|
|
112
118
|
"Awaitable",
|
|
@@ -118,6 +124,9 @@ __all__ = [
|
|
|
118
124
|
"ItemP",
|
|
119
125
|
"List",
|
|
120
126
|
"MemcachedClientP",
|
|
127
|
+
"MongoClient",
|
|
128
|
+
"MongoCollection",
|
|
129
|
+
"MongoDatabase",
|
|
121
130
|
"NamedTuple",
|
|
122
131
|
"Optional",
|
|
123
132
|
"P",
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
limits/__init__.py,sha256=j_yVhgN9pdz8o5rQjVwdJTBSq8F-CTzof9kkiYgjRbw,728
|
|
2
|
-
limits/_version.py,sha256=
|
|
2
|
+
limits/_version.py,sha256=hEL57l9rkTEoBd9jvOB4z-OkCjpEs9jAM_ocoojdL6k,498
|
|
3
3
|
limits/errors.py,sha256=xCKGOVJiD-g8FlsQQb17AW2pTUvalYSuizPpvEVoYJE,626
|
|
4
4
|
limits/limits.py,sha256=ZsXESq2e1ji7c2ZKjSkIAasCjiLdjVLPUa9oah_I8U4,4943
|
|
5
5
|
limits/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
6
|
limits/strategies.py,sha256=7pr2V34KdOEfxnYOf882Cl2qKY-KK6HwKjdYo_IsD4c,6690
|
|
7
|
-
limits/typing.py,sha256=
|
|
7
|
+
limits/typing.py,sha256=nwJLek44QIg3869AbOSvPwotfp6JR7vEHz_UgZBiqgg,3287
|
|
8
8
|
limits/util.py,sha256=xMRR5bKksYcnzY0H0xORDGvRFF5btiBognY2sSd38NE,5743
|
|
9
9
|
limits/version.py,sha256=YwkF3dtq1KGzvmL3iVGctA8NNtGlK_0arrzZkZGVjUs,47
|
|
10
10
|
limits/aio/__init__.py,sha256=IOetunwQy1c5GefzitK8lewbTzHGiE-kmE9NlqSdr3U,82
|
|
11
11
|
limits/aio/strategies.py,sha256=REaQ-lqgqkN5wrFZ26AZ3sCHO8oZBL_mWhI6nMRaBz8,6485
|
|
12
12
|
limits/aio/storage/__init__.py,sha256=CbtuSlVl1jPyN_vsEI_ApWblDblVaL46xcZ2M_oM0V8,595
|
|
13
|
-
limits/aio/storage/base.py,sha256=
|
|
13
|
+
limits/aio/storage/base.py,sha256=xdYpBBonyMjxE9iT-2oZjm6x29aDU6Xd09MeBYbZcMo,4817
|
|
14
14
|
limits/aio/storage/etcd.py,sha256=Rjb_EYKFRr4F2Z6zvAPP9vQOyXJQHaju3VjxxUs75_c,4791
|
|
15
15
|
limits/aio/storage/memcached.py,sha256=6aTlACfCtchdcZqoisnei0MOlCH7yLV9A1yCjOE5f9g,4802
|
|
16
16
|
limits/aio/storage/memory.py,sha256=DlmWluqUwBUWQIQ6XZi-mPrb15vfzBhA4iAKhBELDnE,5856
|
|
@@ -20,18 +20,18 @@ limits/resources/redis/lua_scripts/acquire_moving_window.lua,sha256=5CFJX7D6T6RG
|
|
|
20
20
|
limits/resources/redis/lua_scripts/clear_keys.lua,sha256=zU0cVfLGmapRQF9x9u0GclapM_IB2pJLszNzVQ1QRK4,184
|
|
21
21
|
limits/resources/redis/lua_scripts/incr_expire.lua,sha256=Uq9NcrrcDI-F87TDAJexoSJn2SDgeXIUEYozCp9S3oA,195
|
|
22
22
|
limits/resources/redis/lua_scripts/moving_window.lua,sha256=iAInenlVd_fFDi15APpRWbOuPUz_G3nFnVAqb7wOedA,398
|
|
23
|
-
limits/storage/__init__.py,sha256=
|
|
23
|
+
limits/storage/__init__.py,sha256=XAW1jVDMLFkPr_Tl1SXpg_p4Y3nhEatTSYq1MlnYJcA,2564
|
|
24
24
|
limits/storage/base.py,sha256=fDdYLa-RrnjhBTO1hE5aTTM8q8n3M5HD-65KyWWXBtg,4627
|
|
25
25
|
limits/storage/etcd.py,sha256=wkC_mj4Tsf2nwUKByMiHiGzA40N3mDepEwdLmvH8wmw,4484
|
|
26
26
|
limits/storage/memcached.py,sha256=bMzfZgYa_EWcZAjSZLcygpk3hpeOAErBpRE8dVwyXQs,6640
|
|
27
27
|
limits/storage/memory.py,sha256=R16E-Ccnmn1-LlolkFf-kB1-QHh8eiwFFLYVv0PuFD0,5561
|
|
28
|
-
limits/storage/mongodb.py,sha256=
|
|
28
|
+
limits/storage/mongodb.py,sha256=QWd_SW--P86SMPDrDrBQS-2xKbWY3cw9x71KsI506zY,9213
|
|
29
29
|
limits/storage/redis.py,sha256=3zJ1gDMDepT_pGN9d2aAN7Pea7tMBI49VK60IHv-Ooc,8452
|
|
30
30
|
limits/storage/redis_cluster.py,sha256=KwhWV0v3_TliRyS3OU15IlpeC8gRQr29U4FkcME01fo,5380
|
|
31
31
|
limits/storage/redis_sentinel.py,sha256=7PVB0hBl0I_enhN_h9QSJTE7zGuYtjkebotTqxm2iZo,3875
|
|
32
32
|
limits/storage/registry.py,sha256=xcBcxuu6srqmoS4WqDpkCXnRLB19ctH98v21P8S9kS8,708
|
|
33
|
-
limits-3.
|
|
34
|
-
limits-3.
|
|
35
|
-
limits-3.
|
|
36
|
-
limits-3.
|
|
37
|
-
limits-3.
|
|
33
|
+
limits-3.12.0.dist-info/LICENSE.txt,sha256=T6i7kq7F5gIPfcno9FCxU5Hcwm22Bjq0uHZV3ElcjsQ,1061
|
|
34
|
+
limits-3.12.0.dist-info/METADATA,sha256=Evty_7zeDjM5XTCfNpdERwhzmfMnOU36NdkHiQE841s,7170
|
|
35
|
+
limits-3.12.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
36
|
+
limits-3.12.0.dist-info/top_level.txt,sha256=C7g5ahldPoU2s6iWTaJayUrbGmPK1d6e9t5Nn0vQ2jM,7
|
|
37
|
+
limits-3.12.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|