redis-lua-py 0.1.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.
- redis_lua_py/__init__.py +87 -0
- redis_lua_py/_compile.py +787 -0
- redis_lua_py/_lua.py +308 -0
- redis_lua_py/_runtime.py +72 -0
- redis_lua_py/_script.py +151 -0
- redis_lua_py/errors.py +53 -0
- redis_lua_py/py.typed +0 -0
- redis_lua_py-0.1.0.dist-info/METADATA +320 -0
- redis_lua_py-0.1.0.dist-info/RECORD +11 -0
- redis_lua_py-0.1.0.dist-info/WHEEL +4 -0
- redis_lua_py-0.1.0.dist-info/licenses/LICENSE +21 -0
redis_lua_py/__init__.py
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""Write Redis Lua scripts as real Python functions, not strings.
|
|
2
|
+
|
|
3
|
+
from redis_lua_py import Key, redis, script
|
|
4
|
+
|
|
5
|
+
@script
|
|
6
|
+
def rate_limit(key: Key, limit: int, ttl: int) -> int:
|
|
7
|
+
current = redis.incr(key)
|
|
8
|
+
if current == 1:
|
|
9
|
+
redis.expire(key, ttl)
|
|
10
|
+
if current > limit:
|
|
11
|
+
return -1
|
|
12
|
+
return limit - current
|
|
13
|
+
|
|
14
|
+
remaining = rate_limit(client, key="u:42", limit=10, ttl=60)
|
|
15
|
+
|
|
16
|
+
The body is never executed by Python: it is read as source at import time and
|
|
17
|
+
compiled to Lua, which you can inspect at ``rate_limit.lua``.
|
|
18
|
+
|
|
19
|
+
The ``redis`` namespace above is resolved by value, not by spelling, so import
|
|
20
|
+
it under whatever name suits the module::
|
|
21
|
+
|
|
22
|
+
from redis_lua_py import redis as r # frees the name for redis-py
|
|
23
|
+
|
|
24
|
+
Binding a client once is often tidier than passing it to every call::
|
|
25
|
+
|
|
26
|
+
limiter = rate_limit.bind(client)
|
|
27
|
+
limiter(key="u:42", limit=10, ttl=60)
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
from __future__ import annotations
|
|
31
|
+
|
|
32
|
+
from collections.abc import Callable
|
|
33
|
+
from typing import Any, overload
|
|
34
|
+
|
|
35
|
+
from ._compile import compile_function
|
|
36
|
+
from ._runtime import Key, call, cjson, redis
|
|
37
|
+
from ._script import BoundScript, CompiledScript
|
|
38
|
+
from .errors import (
|
|
39
|
+
CompileError,
|
|
40
|
+
RedisLuaError,
|
|
41
|
+
ScriptArgumentError,
|
|
42
|
+
UnsupportedSyntax,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
__all__ = [
|
|
46
|
+
"BoundScript",
|
|
47
|
+
"CompileError",
|
|
48
|
+
"CompiledScript",
|
|
49
|
+
"Key",
|
|
50
|
+
"RedisLuaError",
|
|
51
|
+
"ScriptArgumentError",
|
|
52
|
+
"UnsupportedSyntax",
|
|
53
|
+
"call",
|
|
54
|
+
"cjson",
|
|
55
|
+
"redis",
|
|
56
|
+
"script",
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
__version__ = "0.1.0" # x-release-please-version
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@overload
|
|
63
|
+
def script(func: Callable[..., Any], /) -> CompiledScript: ...
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@overload
|
|
67
|
+
def script(*, name: str | None = ...) -> Callable[[Callable[..., Any]], CompiledScript]: ...
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def script(
|
|
71
|
+
func: Callable[..., Any] | None = None, /, *, name: str | None = None
|
|
72
|
+
) -> CompiledScript | Callable[[Callable[..., Any]], CompiledScript]:
|
|
73
|
+
"""Compile a function into a Redis Lua script.
|
|
74
|
+
|
|
75
|
+
Parameters annotated :class:`Key` become ``KEYS``, in declaration order;
|
|
76
|
+
every other parameter becomes ``ARGV``. An ``int`` or ``float`` annotation
|
|
77
|
+
additionally wraps the argument in ``tonumber``, since ARGV always arrives
|
|
78
|
+
as a string.
|
|
79
|
+
|
|
80
|
+
Raises :class:`UnsupportedSyntax` at decoration time, pointing at the line
|
|
81
|
+
at fault, if the body strays outside the supported subset.
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
def wrap(target: Callable[..., Any]) -> CompiledScript:
|
|
85
|
+
return compile_function(target, name=name)
|
|
86
|
+
|
|
87
|
+
return wrap if func is None else wrap(func)
|