valkey-glide 2.1.0rc2__cp39-cp39-macosx_10_7_x86_64.whl → 2.2.1rc3__cp39-cp39-macosx_10_7_x86_64.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.
- glide/__init__.py +58 -0
- glide/async_commands/cluster_commands.py +18 -3
- glide/async_commands/core.py +84 -21
- glide/async_commands/standalone_commands.py +1 -40
- glide/glide.cpython-39-darwin.so +0 -0
- glide/glide_client.py +15 -2
- glide/py.typed +0 -0
- glide_shared/__init__.py +4 -0
- glide_shared/commands/batch.py +30 -22
- glide_shared/config.py +274 -37
- glide_shared/protobuf/command_request_pb2.py +11 -9
- glide_shared/protobuf/connection_request_pb2.py +29 -25
- {valkey_glide-2.1.0rc2.dist-info → valkey_glide-2.2.1rc3.dist-info}/METADATA +1 -1
- {valkey_glide-2.1.0rc2.dist-info → valkey_glide-2.2.1rc3.dist-info}/RECORD +15 -14
- {valkey_glide-2.1.0rc2.dist-info → valkey_glide-2.2.1rc3.dist-info}/WHEEL +0 -0
glide/__init__.py
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
|
|
2
2
|
|
|
3
|
+
import sys
|
|
4
|
+
import types
|
|
5
|
+
import warnings
|
|
6
|
+
|
|
3
7
|
from glide.glide import (
|
|
4
8
|
ClusterScanCursor,
|
|
5
9
|
OpenTelemetryConfig,
|
|
@@ -78,6 +82,7 @@ from glide_shared import (
|
|
|
78
82
|
GlideClusterClientConfiguration,
|
|
79
83
|
GlideError,
|
|
80
84
|
HashFieldConditionalChange,
|
|
85
|
+
IamAuthConfig,
|
|
81
86
|
IdBound,
|
|
82
87
|
InfBound,
|
|
83
88
|
InfoSection,
|
|
@@ -112,6 +117,7 @@ from glide_shared import (
|
|
|
112
117
|
ScoreBoundary,
|
|
113
118
|
ScoreFilter,
|
|
114
119
|
ServerCredentials,
|
|
120
|
+
ServiceType,
|
|
115
121
|
SignedEncoding,
|
|
116
122
|
SlotIdRoute,
|
|
117
123
|
SlotKeyRoute,
|
|
@@ -159,6 +165,56 @@ from .glide_client import GlideClient, GlideClusterClient, TGlideClient
|
|
|
159
165
|
from .logger import Level as LogLevel
|
|
160
166
|
from .logger import Logger
|
|
161
167
|
|
|
168
|
+
_glide_module = sys.modules[__name__]
|
|
169
|
+
|
|
170
|
+
_legacy_modules = [
|
|
171
|
+
"glide.exceptions",
|
|
172
|
+
"glide.config",
|
|
173
|
+
"glide.constants",
|
|
174
|
+
"glide.routes",
|
|
175
|
+
"glide.async_commands",
|
|
176
|
+
"glide.async_commands.batch",
|
|
177
|
+
"glide.async_commands.batch_options",
|
|
178
|
+
"glide.async_commands.bitmap",
|
|
179
|
+
"glide.async_commands.command_args",
|
|
180
|
+
"glide.async_commands.server_modules",
|
|
181
|
+
"glide.async_commands.server_modules.ft_options",
|
|
182
|
+
"glide.async_commands.server_modules.ft_options.ft_aggregate_options",
|
|
183
|
+
"glide.async_commands.server_modules.ft_options.ft_create_options",
|
|
184
|
+
"glide.async_commands.server_modules.ft_options.ft_profile_options",
|
|
185
|
+
"glide.async_commands.server_modules.ft_options.ft_search_options",
|
|
186
|
+
"glide.async_commands.server_modules.glide_json",
|
|
187
|
+
"glide.async_commands.sorted_set",
|
|
188
|
+
"glide.async_commands.stream",
|
|
189
|
+
]
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
class _LegacyModule(types.ModuleType):
|
|
193
|
+
"""Proxy for a deprecated module that warns when first accessed."""
|
|
194
|
+
|
|
195
|
+
def __init__(self, name):
|
|
196
|
+
super().__init__(name)
|
|
197
|
+
self._warned = False
|
|
198
|
+
|
|
199
|
+
def __getattr__(self, name):
|
|
200
|
+
if not self._warned:
|
|
201
|
+
warnings.warn(
|
|
202
|
+
f"Importing from '{self.__name__}' is deprecated. "
|
|
203
|
+
f"Please import directly from 'glide' instead.",
|
|
204
|
+
DeprecationWarning,
|
|
205
|
+
stacklevel=2,
|
|
206
|
+
)
|
|
207
|
+
self._warned = True
|
|
208
|
+
|
|
209
|
+
# Access the attribute from the real top-level glide module
|
|
210
|
+
return getattr(_glide_module, name)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
# Replace old modules with lazy proxy modules
|
|
214
|
+
for old_name in _legacy_modules:
|
|
215
|
+
if old_name not in sys.modules:
|
|
216
|
+
sys.modules[old_name] = _LegacyModule(old_name)
|
|
217
|
+
|
|
162
218
|
__all__ = [
|
|
163
219
|
# Client
|
|
164
220
|
"TGlideClient",
|
|
@@ -181,6 +237,8 @@ __all__ = [
|
|
|
181
237
|
"BackoffStrategy",
|
|
182
238
|
"ReadFrom",
|
|
183
239
|
"ServerCredentials",
|
|
240
|
+
"ServiceType",
|
|
241
|
+
"IamAuthConfig",
|
|
184
242
|
"NodeAddress",
|
|
185
243
|
"OpenTelemetryConfig",
|
|
186
244
|
"OpenTelemetryMetricsConfig",
|
|
@@ -1066,11 +1066,17 @@ class ClusterCommands(CoreCommands):
|
|
|
1066
1066
|
self,
|
|
1067
1067
|
source: TEncodable,
|
|
1068
1068
|
destination: TEncodable,
|
|
1069
|
+
# TODO next major release the arguments replace and destinationDB must have their order
|
|
1070
|
+
# swapped to align with the standalone order.
|
|
1071
|
+
# At the moment of the patch release 2.1.1. we can't have a breaking change
|
|
1069
1072
|
replace: Optional[bool] = None,
|
|
1073
|
+
destinationDB: Optional[int] = None,
|
|
1070
1074
|
) -> bool:
|
|
1071
1075
|
"""
|
|
1072
|
-
Copies the value stored at the `source` to the `destination` key.
|
|
1073
|
-
|
|
1076
|
+
Copies the value stored at the `source` to the `destination` key. If `destinationDB`
|
|
1077
|
+
is specified, the value will be copied to the database specified by `destinationDB`,
|
|
1078
|
+
otherwise the current database will be used. When `replace` is True, removes the
|
|
1079
|
+
`destination` key first if it already exists, otherwise performs no action.
|
|
1074
1080
|
|
|
1075
1081
|
See [valkey.io](https://valkey.io/commands/copy) for more details.
|
|
1076
1082
|
|
|
@@ -1081,6 +1087,7 @@ class ClusterCommands(CoreCommands):
|
|
|
1081
1087
|
source (TEncodable): The key to the source value.
|
|
1082
1088
|
destination (TEncodable): The key where the value should be copied to.
|
|
1083
1089
|
replace (Optional[bool]): If the destination key should be removed before copying the value to it.
|
|
1090
|
+
destinationDB (Optional[int]): The alternative logical database index for the destination key.
|
|
1084
1091
|
|
|
1085
1092
|
Returns:
|
|
1086
1093
|
bool: True if the source was copied. Otherwise, returns False.
|
|
@@ -1089,12 +1096,20 @@ class ClusterCommands(CoreCommands):
|
|
|
1089
1096
|
>>> await client.set("source", "sheep")
|
|
1090
1097
|
>>> await client.copy(b"source", b"destination")
|
|
1091
1098
|
True # Source was copied
|
|
1099
|
+
>>> await client.copy(b"source", b"destination", destinationDB=1)
|
|
1100
|
+
True # Source was copied to DB 1
|
|
1101
|
+
>>> await client.select(1)
|
|
1092
1102
|
>>> await client.get("destination")
|
|
1093
1103
|
b"sheep"
|
|
1094
1104
|
|
|
1095
1105
|
Since: Valkey version 6.2.0.
|
|
1106
|
+
The destinationDB argument is available since Valkey 9.0.0
|
|
1096
1107
|
"""
|
|
1108
|
+
|
|
1109
|
+
# Build command arguments
|
|
1097
1110
|
args: List[TEncodable] = [source, destination]
|
|
1111
|
+
if destinationDB is not None:
|
|
1112
|
+
args.extend(["DB", str(destinationDB)])
|
|
1098
1113
|
if replace is True:
|
|
1099
1114
|
args.append("REPLACE")
|
|
1100
1115
|
return cast(
|
|
@@ -1141,7 +1156,7 @@ class ClusterCommands(CoreCommands):
|
|
|
1141
1156
|
args.extend(["VERSION", str(version)])
|
|
1142
1157
|
if parameters:
|
|
1143
1158
|
for var in parameters:
|
|
1144
|
-
args.
|
|
1159
|
+
args.append(str(var))
|
|
1145
1160
|
return cast(
|
|
1146
1161
|
TClusterResponse[bytes],
|
|
1147
1162
|
await self._execute_command(RequestType.Lolwut, args, route),
|
glide/async_commands/core.py
CHANGED
|
@@ -139,6 +139,27 @@ class CoreCommands(Protocol):
|
|
|
139
139
|
TOK, await self._update_connection_password(password, immediate_auth)
|
|
140
140
|
)
|
|
141
141
|
|
|
142
|
+
async def _refresh_iam_token(self) -> TResult: ...
|
|
143
|
+
|
|
144
|
+
async def refresh_iam_token(self) -> TOK:
|
|
145
|
+
"""
|
|
146
|
+
Manually refresh the IAM token for the current connection.
|
|
147
|
+
|
|
148
|
+
This method is only available if the client was created with IAM authentication.
|
|
149
|
+
It triggers an immediate refresh of the IAM token and updates the connection.
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
TOK: A simple OK response on success.
|
|
153
|
+
|
|
154
|
+
Raises:
|
|
155
|
+
ConfigurationError: If the client is not using IAM authentication.
|
|
156
|
+
|
|
157
|
+
Example:
|
|
158
|
+
>>> await client.refresh_iam_token()
|
|
159
|
+
'OK'
|
|
160
|
+
"""
|
|
161
|
+
return cast(TOK, await self._refresh_iam_token())
|
|
162
|
+
|
|
142
163
|
async def set(
|
|
143
164
|
self,
|
|
144
165
|
key: TEncodable,
|
|
@@ -430,6 +451,34 @@ class CoreCommands(Protocol):
|
|
|
430
451
|
"""
|
|
431
452
|
return cast(int, await self._execute_command(RequestType.Del, keys))
|
|
432
453
|
|
|
454
|
+
async def move(self, key: TEncodable, db_index: int) -> bool:
|
|
455
|
+
"""
|
|
456
|
+
Move key from the currently selected database to the specified destination database.
|
|
457
|
+
|
|
458
|
+
Note:
|
|
459
|
+
For cluster mode move command is supported since Valkey 9.0.0
|
|
460
|
+
|
|
461
|
+
See [valkey.io](https://valkey.io/commands/move/) for more details.
|
|
462
|
+
|
|
463
|
+
Args:
|
|
464
|
+
key (TEncodable): The key to move.
|
|
465
|
+
db_index (int): The destination database number.
|
|
466
|
+
|
|
467
|
+
Returns:
|
|
468
|
+
bool: True if the key was moved successfully, False if the key does not exist
|
|
469
|
+
or was already present in the destination database.
|
|
470
|
+
|
|
471
|
+
Examples:
|
|
472
|
+
>>> await client.move("some_key", 1)
|
|
473
|
+
True # The key was successfully moved to database 1
|
|
474
|
+
>>> await client.move("nonexistent_key", 1)
|
|
475
|
+
False # The key does not exist
|
|
476
|
+
"""
|
|
477
|
+
return cast(
|
|
478
|
+
bool,
|
|
479
|
+
await self._execute_command(RequestType.Move, [key, str(db_index)]),
|
|
480
|
+
)
|
|
481
|
+
|
|
433
482
|
async def incr(self, key: TEncodable) -> int:
|
|
434
483
|
"""
|
|
435
484
|
Increments the number stored at `key` by one. If the key does not exist, it is set to 0 before performing the
|
|
@@ -1120,7 +1169,7 @@ class CoreCommands(Protocol):
|
|
|
1120
1169
|
- `-2`: field does not exist or key does not exist
|
|
1121
1170
|
|
|
1122
1171
|
Examples:
|
|
1123
|
-
>>> await client.hsetex("my_hash", {"field1": "value1", "field2": "value2"}, expiry=ExpirySet(ExpiryType.
|
|
1172
|
+
>>> await client.hsetex("my_hash", {"field1": "value1", "field2": "value2"}, expiry=ExpirySet(ExpiryType.SEC, 10))
|
|
1124
1173
|
>>> await client.httl("my_hash", ["field1", "field2", "non_existent_field"])
|
|
1125
1174
|
[9, 9, -2] # field1 and field2 have ~9 seconds left, non_existent_field doesn't exist
|
|
1126
1175
|
|
|
@@ -1150,7 +1199,7 @@ class CoreCommands(Protocol):
|
|
|
1150
1199
|
- `-2`: field does not exist or key does not exist
|
|
1151
1200
|
|
|
1152
1201
|
Examples:
|
|
1153
|
-
>>> await client.hsetex("my_hash", {"field1": "value1", "field2": "value2"}, expiry=ExpirySet(ExpiryType.
|
|
1202
|
+
>>> await client.hsetex("my_hash", {"field1": "value1", "field2": "value2"}, expiry=ExpirySet(ExpiryType.MILLSEC, 10000))
|
|
1154
1203
|
>>> await client.hpttl("my_hash", ["field1", "field2", "non_existent_field"])
|
|
1155
1204
|
[9500, 9500, -2] # field1 and field2 have ~9500 milliseconds left, non_existent_field doesn't exist
|
|
1156
1205
|
|
|
@@ -1182,7 +1231,7 @@ class CoreCommands(Protocol):
|
|
|
1182
1231
|
Examples:
|
|
1183
1232
|
>>> import time
|
|
1184
1233
|
>>> future_timestamp = int(time.time()) + 60 # 60 seconds from now
|
|
1185
|
-
>>> await client.hsetex("my_hash", {"field1": "value1", "field2": "value2"}, expiry=ExpirySet(ExpiryType.
|
|
1234
|
+
>>> await client.hsetex("my_hash", {"field1": "value1", "field2": "value2"}, expiry=ExpirySet(ExpiryType.UNIX_SEC, future_timestamp))
|
|
1186
1235
|
>>> await client.hexpiretime("my_hash", ["field1", "field2", "non_existent_field"])
|
|
1187
1236
|
[future_timestamp, future_timestamp, -2] # field1 and field2 expire at future_timestamp, non_existent_field doesn't exist
|
|
1188
1237
|
|
|
@@ -1216,7 +1265,7 @@ class CoreCommands(Protocol):
|
|
|
1216
1265
|
Examples:
|
|
1217
1266
|
>>> import time
|
|
1218
1267
|
>>> future_timestamp_ms = int(time.time() * 1000) + 60000 # 60 seconds from now in milliseconds
|
|
1219
|
-
>>> await client.hsetex("my_hash", {"field1": "value1", "field2": "value2"}, expiry=ExpirySet(ExpiryType.
|
|
1268
|
+
>>> await client.hsetex("my_hash", {"field1": "value1", "field2": "value2"}, expiry=ExpirySet(ExpiryType.UNIX_MILLSEC, future_timestamp_ms))
|
|
1220
1269
|
>>> await client.hpexpiretime("my_hash", ["field1", "field2", "non_existent_field"])
|
|
1221
1270
|
[future_timestamp_ms, future_timestamp_ms, -2] # field1 and field2 expire at future_timestamp_ms, non_existent_field doesn't exist
|
|
1222
1271
|
|
|
@@ -1249,17 +1298,17 @@ class CoreCommands(Protocol):
|
|
|
1249
1298
|
- ONLY_IF_ALL_EXIST (FXX): Only set fields if all of them already exist.
|
|
1250
1299
|
- ONLY_IF_NONE_EXIST (FNX): Only set fields if none of them already exist.
|
|
1251
1300
|
expiry (Optional[ExpirySet]): Expiration options for the fields:
|
|
1252
|
-
- EX: Expiration time in seconds.
|
|
1253
|
-
- PX: Expiration time in milliseconds.
|
|
1254
|
-
- EXAT: Absolute expiration time in seconds (Unix timestamp).
|
|
1255
|
-
- PXAT: Absolute expiration time in milliseconds (Unix timestamp).
|
|
1256
|
-
- KEEPTTL: Retain existing TTL.
|
|
1301
|
+
- SEC (EX): Expiration time in seconds.
|
|
1302
|
+
- MILLSEC (PX): Expiration time in milliseconds.
|
|
1303
|
+
- UNIX_SEC (EXAT): Absolute expiration time in seconds (Unix timestamp).
|
|
1304
|
+
- UNIX_MILLSEC (PXAT): Absolute expiration time in milliseconds (Unix timestamp).
|
|
1305
|
+
- KEEP_TTL (KEEPTTL): Retain existing TTL.
|
|
1257
1306
|
|
|
1258
1307
|
Returns:
|
|
1259
1308
|
int: 1 if all fields were set successfully, 0 if none were set due to conditional constraints.
|
|
1260
1309
|
|
|
1261
1310
|
Examples:
|
|
1262
|
-
>>> await client.hsetex("my_hash", {"field1": "value1", "field2": "value2"}, expiry=ExpirySet(ExpiryType.
|
|
1311
|
+
>>> await client.hsetex("my_hash", {"field1": "value1", "field2": "value2"}, expiry=ExpirySet(ExpiryType.SEC, 10))
|
|
1263
1312
|
1 # All fields set with 10 second expiration
|
|
1264
1313
|
>>> await client.hsetex("my_hash", {"field3": "value3"}, field_conditional_change=HashFieldConditionalChange.ONLY_IF_ALL_EXIST)
|
|
1265
1314
|
1 # Field set because field already exists
|
|
@@ -1305,10 +1354,10 @@ class CoreCommands(Protocol):
|
|
|
1305
1354
|
key (TEncodable): The key of the hash.
|
|
1306
1355
|
fields (List[TEncodable]): The list of fields to retrieve from the hash.
|
|
1307
1356
|
expiry (Optional[ExpiryGetEx]): Expiration options for the retrieved fields:
|
|
1308
|
-
- EX: Expiration time in seconds.
|
|
1309
|
-
- PX: Expiration time in milliseconds.
|
|
1310
|
-
- EXAT: Absolute expiration time in seconds (Unix timestamp).
|
|
1311
|
-
- PXAT: Absolute expiration time in milliseconds (Unix timestamp).
|
|
1357
|
+
- SEC (EX): Expiration time in seconds.
|
|
1358
|
+
- MILLSEC (PX): Expiration time in milliseconds.
|
|
1359
|
+
- UNIX_SEC (EXAT): Absolute expiration time in seconds (Unix timestamp).
|
|
1360
|
+
- UNIX_MILLSEC (PXAT): Absolute expiration time in milliseconds (Unix timestamp).
|
|
1312
1361
|
- PERSIST: Remove expiration from the fields.
|
|
1313
1362
|
|
|
1314
1363
|
Returns:
|
|
@@ -1317,10 +1366,10 @@ class CoreCommands(Protocol):
|
|
|
1317
1366
|
If `key` does not exist, it is treated as an empty hash, and the function returns a list of null values.
|
|
1318
1367
|
|
|
1319
1368
|
Examples:
|
|
1320
|
-
>>> await client.hsetex("my_hash", {"field1": "value1", "field2": "value2"}, expiry=ExpirySet(ExpiryType.
|
|
1369
|
+
>>> await client.hsetex("my_hash", {"field1": "value1", "field2": "value2"}, expiry=ExpirySet(ExpiryType.SEC, 10))
|
|
1321
1370
|
>>> await client.hgetex("my_hash", ["field1", "field2"])
|
|
1322
1371
|
[b"value1", b"value2"]
|
|
1323
|
-
>>> await client.hgetex("my_hash", ["field1"], expiry=ExpiryGetEx(ExpiryTypeGetEx.
|
|
1372
|
+
>>> await client.hgetex("my_hash", ["field1"], expiry=ExpiryGetEx(ExpiryTypeGetEx.SEC, 20))
|
|
1324
1373
|
[b"value1"] # field1 now has 20 second expiration
|
|
1325
1374
|
>>> await client.hgetex("my_hash", ["field1"], expiry=ExpiryGetEx(ExpiryTypeGetEx.PERSIST, None))
|
|
1326
1375
|
[b"value1"] # field1 expiration removed
|
|
@@ -1374,7 +1423,7 @@ class CoreCommands(Protocol):
|
|
|
1374
1423
|
- `2`: Field was deleted immediately (when seconds is 0 or timestamp is in the past).
|
|
1375
1424
|
|
|
1376
1425
|
Examples:
|
|
1377
|
-
>>> await client.hsetex("my_hash", {"field1": "value1", "field2": "value2"}, expiry=ExpirySet(ExpiryType.
|
|
1426
|
+
>>> await client.hsetex("my_hash", {"field1": "value1", "field2": "value2"}, expiry=ExpirySet(ExpiryType.SEC, 10))
|
|
1378
1427
|
>>> await client.hexpire("my_hash", 20, ["field1", "field2"])
|
|
1379
1428
|
[1, 1] # Both fields' expiration set to 20 seconds
|
|
1380
1429
|
>>> await client.hexpire("my_hash", 30, ["field1"], option=ExpireOptions.NewExpiryGreaterThanCurrent)
|
|
@@ -1420,7 +1469,7 @@ class CoreCommands(Protocol):
|
|
|
1420
1469
|
- `-2`: Field does not exist or key does not exist.
|
|
1421
1470
|
|
|
1422
1471
|
Examples:
|
|
1423
|
-
>>> await client.hsetex("my_hash", {"field1": "value1", "field2": "value2"}, expiry=ExpirySet(ExpiryType.
|
|
1472
|
+
>>> await client.hsetex("my_hash", {"field1": "value1", "field2": "value2"}, expiry=ExpirySet(ExpiryType.SEC, 10))
|
|
1424
1473
|
>>> await client.hpersist("my_hash", ["field1", "field2"])
|
|
1425
1474
|
[1, 1] # Both fields made persistent
|
|
1426
1475
|
>>> await client.hpersist("my_hash", ["field1"])
|
|
@@ -1467,7 +1516,7 @@ class CoreCommands(Protocol):
|
|
|
1467
1516
|
- `2`: Field was deleted immediately (when milliseconds is 0 or timestamp is in the past).
|
|
1468
1517
|
|
|
1469
1518
|
Examples:
|
|
1470
|
-
>>> await client.hsetex("my_hash", {"field1": "value1", "field2": "value2"}, expiry=ExpirySet(ExpiryType.
|
|
1519
|
+
>>> await client.hsetex("my_hash", {"field1": "value1", "field2": "value2"}, expiry=ExpirySet(ExpiryType.MILLSEC, 10000))
|
|
1471
1520
|
>>> await client.hpexpire("my_hash", 20000, ["field1", "field2"])
|
|
1472
1521
|
[1, 1] # Both fields' expiration set to 20000 milliseconds
|
|
1473
1522
|
>>> await client.hpexpire("my_hash", 30000, ["field1"], option=ExpireOptions.NewExpiryGreaterThanCurrent)
|
|
@@ -1528,7 +1577,7 @@ class CoreCommands(Protocol):
|
|
|
1528
1577
|
Examples:
|
|
1529
1578
|
>>> import time
|
|
1530
1579
|
>>> future_timestamp = int(time.time()) + 60 # 60 seconds from now
|
|
1531
|
-
>>> await client.hsetex("my_hash", {"field1": "value1", "field2": "value2"}, expiry=ExpirySet(ExpiryType.
|
|
1580
|
+
>>> await client.hsetex("my_hash", {"field1": "value1", "field2": "value2"}, expiry=ExpirySet(ExpiryType.SEC, 10))
|
|
1532
1581
|
>>> await client.hexpireat("my_hash", future_timestamp, ["field1", "field2"])
|
|
1533
1582
|
[1, 1] # Both fields' expiration set to future_timestamp
|
|
1534
1583
|
>>> past_timestamp = int(time.time()) - 60 # 60 seconds ago
|
|
@@ -1588,7 +1637,7 @@ class CoreCommands(Protocol):
|
|
|
1588
1637
|
Examples:
|
|
1589
1638
|
>>> import time
|
|
1590
1639
|
>>> future_timestamp_ms = int(time.time() * 1000) + 60000 # 60 seconds from now in milliseconds
|
|
1591
|
-
>>> await client.hsetex("my_hash", {"field1": "value1", "field2": "value2"}, expiry=ExpirySet(ExpiryType.
|
|
1640
|
+
>>> await client.hsetex("my_hash", {"field1": "value1", "field2": "value2"}, expiry=ExpirySet(ExpiryType.MILLSEC, 10000))
|
|
1592
1641
|
>>> await client.hpexpireat("my_hash", future_timestamp_ms, ["field1", "field2"])
|
|
1593
1642
|
[1, 1] # Both fields' expiration set to future_timestamp_ms
|
|
1594
1643
|
>>> past_timestamp_ms = int(time.time() * 1000) - 60000 # 60 seconds ago in milliseconds
|
|
@@ -2242,6 +2291,20 @@ class CoreCommands(Protocol):
|
|
|
2242
2291
|
"""
|
|
2243
2292
|
return cast(int, await self._execute_command(RequestType.SAdd, [key] + members))
|
|
2244
2293
|
|
|
2294
|
+
async def select(self, index: int) -> TOK:
|
|
2295
|
+
"""
|
|
2296
|
+
Change the currently selected database.
|
|
2297
|
+
|
|
2298
|
+
See [valkey.io](https://valkey.io/commands/select/) for details.
|
|
2299
|
+
|
|
2300
|
+
Args:
|
|
2301
|
+
index (int): The index of the database to select.
|
|
2302
|
+
|
|
2303
|
+
Returns:
|
|
2304
|
+
A simple OK response.
|
|
2305
|
+
"""
|
|
2306
|
+
return cast(TOK, await self._execute_command(RequestType.Select, [str(index)]))
|
|
2307
|
+
|
|
2245
2308
|
async def srem(self, key: TEncodable, members: List[TEncodable]) -> int:
|
|
2246
2309
|
"""
|
|
2247
2310
|
Remove specified members from the set stored at `key`.
|
|
@@ -162,20 +162,6 @@ class StandaloneCommands(CoreCommands):
|
|
|
162
162
|
timeout=timeout,
|
|
163
163
|
)
|
|
164
164
|
|
|
165
|
-
async def select(self, index: int) -> TOK:
|
|
166
|
-
"""
|
|
167
|
-
Change the currently selected database.
|
|
168
|
-
|
|
169
|
-
See [valkey.io](https://valkey.io/commands/select/) for details.
|
|
170
|
-
|
|
171
|
-
Args:
|
|
172
|
-
index (int): The index of the database to select.
|
|
173
|
-
|
|
174
|
-
Returns:
|
|
175
|
-
A simple OK response.
|
|
176
|
-
"""
|
|
177
|
-
return cast(TOK, await self._execute_command(RequestType.Select, [str(index)]))
|
|
178
|
-
|
|
179
165
|
async def config_resetstat(self) -> TOK:
|
|
180
166
|
"""
|
|
181
167
|
Resets the statistics reported by the server using the INFO and LATENCY HISTOGRAM commands.
|
|
@@ -629,31 +615,6 @@ class StandaloneCommands(CoreCommands):
|
|
|
629
615
|
await self._execute_command(RequestType.LastSave, []),
|
|
630
616
|
)
|
|
631
617
|
|
|
632
|
-
async def move(self, key: TEncodable, db_index: int) -> bool:
|
|
633
|
-
"""
|
|
634
|
-
Move `key` from the currently selected database to the database specified by `db_index`.
|
|
635
|
-
|
|
636
|
-
See [valkey.io](https://valkey.io/commands/move/) for more details.
|
|
637
|
-
|
|
638
|
-
Args:
|
|
639
|
-
key (TEncodable): The key to move.
|
|
640
|
-
db_index (int): The index of the database to move `key` to.
|
|
641
|
-
|
|
642
|
-
Returns:
|
|
643
|
-
bool: `True` if `key` was moved.
|
|
644
|
-
|
|
645
|
-
`False` if the `key` already exists in the destination database
|
|
646
|
-
or does not exist in the source database.
|
|
647
|
-
|
|
648
|
-
Example:
|
|
649
|
-
>>> await client.move("some_key", 1)
|
|
650
|
-
True
|
|
651
|
-
"""
|
|
652
|
-
return cast(
|
|
653
|
-
bool,
|
|
654
|
-
await self._execute_command(RequestType.Move, [key, str(db_index)]),
|
|
655
|
-
)
|
|
656
|
-
|
|
657
618
|
async def publish(self, message: TEncodable, channel: TEncodable) -> int:
|
|
658
619
|
"""
|
|
659
620
|
Publish a message on pubsub channel.
|
|
@@ -806,7 +767,7 @@ class StandaloneCommands(CoreCommands):
|
|
|
806
767
|
args.extend(["VERSION", str(version)])
|
|
807
768
|
if parameters:
|
|
808
769
|
for var in parameters:
|
|
809
|
-
args.
|
|
770
|
+
args.append(str(var))
|
|
810
771
|
return cast(
|
|
811
772
|
bytes,
|
|
812
773
|
await self._execute_command(RequestType.Lolwut, args),
|
glide/glide.cpython-39-darwin.so
CHANGED
|
Binary file
|
glide/glide_client.py
CHANGED
|
@@ -48,6 +48,7 @@ from glide_shared.exceptions import (
|
|
|
48
48
|
from glide_shared.protobuf.command_request_pb2 import (
|
|
49
49
|
Command,
|
|
50
50
|
CommandRequest,
|
|
51
|
+
RefreshIamToken,
|
|
51
52
|
RequestType,
|
|
52
53
|
)
|
|
53
54
|
from glide_shared.protobuf.connection_request_pb2 import ConnectionRequest
|
|
@@ -338,7 +339,7 @@ class BaseClient(CoreCommands):
|
|
|
338
339
|
request.callback_idx if isinstance(request, CommandRequest) else 0
|
|
339
340
|
)
|
|
340
341
|
res_future = self._available_futures.pop(callback_idx, None)
|
|
341
|
-
if res_future:
|
|
342
|
+
if res_future and not res_future.done():
|
|
342
343
|
res_future.set_exception(e)
|
|
343
344
|
else:
|
|
344
345
|
ClientLogger.log(
|
|
@@ -355,7 +356,10 @@ class BaseClient(CoreCommands):
|
|
|
355
356
|
b_arr = bytearray()
|
|
356
357
|
for request in requests:
|
|
357
358
|
ProtobufCodec.encode_delimited(b_arr, request)
|
|
358
|
-
|
|
359
|
+
try:
|
|
360
|
+
await self._stream.send(b_arr)
|
|
361
|
+
except (anyio.ClosedResourceError, anyio.EndOfStream):
|
|
362
|
+
raise ClosingError("The communication layer was unexpectedly closed.")
|
|
359
363
|
|
|
360
364
|
def _encode_arg(self, arg: TEncodable) -> bytes:
|
|
361
365
|
"""
|
|
@@ -754,6 +758,15 @@ class BaseClient(CoreCommands):
|
|
|
754
758
|
self.config.credentials.password = password or ""
|
|
755
759
|
return response
|
|
756
760
|
|
|
761
|
+
async def _refresh_iam_token(self) -> TResult:
|
|
762
|
+
request = CommandRequest()
|
|
763
|
+
request.callback_idx = self._get_callback_index()
|
|
764
|
+
request.refresh_iam_token.CopyFrom(
|
|
765
|
+
RefreshIamToken()
|
|
766
|
+
) # Empty message, just triggers the refresh
|
|
767
|
+
response = await self._write_request_await_response(request)
|
|
768
|
+
return response
|
|
769
|
+
|
|
757
770
|
|
|
758
771
|
class GlideClusterClient(BaseClient, ClusterCommands):
|
|
759
772
|
"""
|
glide/py.typed
ADDED
|
File without changes
|
glide_shared/__init__.py
CHANGED
|
@@ -119,12 +119,14 @@ from .config import (
|
|
|
119
119
|
BackoffStrategy,
|
|
120
120
|
GlideClientConfiguration,
|
|
121
121
|
GlideClusterClientConfiguration,
|
|
122
|
+
IamAuthConfig,
|
|
122
123
|
NodeAddress,
|
|
123
124
|
PeriodicChecksManualInterval,
|
|
124
125
|
PeriodicChecksStatus,
|
|
125
126
|
ProtocolVersion,
|
|
126
127
|
ReadFrom,
|
|
127
128
|
ServerCredentials,
|
|
129
|
+
ServiceType,
|
|
128
130
|
TlsAdvancedConfiguration,
|
|
129
131
|
)
|
|
130
132
|
from .constants import (
|
|
@@ -186,6 +188,8 @@ __all__ = [
|
|
|
186
188
|
"BackoffStrategy",
|
|
187
189
|
"ReadFrom",
|
|
188
190
|
"ServerCredentials",
|
|
191
|
+
"ServiceType",
|
|
192
|
+
"IamAuthConfig",
|
|
189
193
|
"NodeAddress",
|
|
190
194
|
"ProtocolVersion",
|
|
191
195
|
"PeriodicChecksManualInterval",
|
glide_shared/commands/batch.py
CHANGED
|
@@ -403,6 +403,27 @@ class BaseBatch:
|
|
|
403
403
|
"""
|
|
404
404
|
return self.append_command(RequestType.ConfigResetStat, [])
|
|
405
405
|
|
|
406
|
+
def move(self: TBatch, key: TEncodable, db_index: int) -> "TBatch":
|
|
407
|
+
"""
|
|
408
|
+
Move `key` from the currently selected database to the database specified by `db_index`.
|
|
409
|
+
|
|
410
|
+
Note:
|
|
411
|
+
For cluster mode move command is supported since Valkey 9.0.0
|
|
412
|
+
|
|
413
|
+
See [valkey.io](https://valkey.io/commands/move/) for more details.
|
|
414
|
+
|
|
415
|
+
Args:
|
|
416
|
+
key (TEncodable): The key to move.
|
|
417
|
+
db_index (int): The index of the database to move `key` to.
|
|
418
|
+
|
|
419
|
+
Commands response:
|
|
420
|
+
bool: True if `key` was moved.
|
|
421
|
+
|
|
422
|
+
False if the `key` already exists in the destination database
|
|
423
|
+
or does not exist in the source database.
|
|
424
|
+
"""
|
|
425
|
+
return self.append_command(RequestType.Move, [key, str(db_index)])
|
|
426
|
+
|
|
406
427
|
def mset(self: TBatch, key_value_map: Mapping[TEncodable, TEncodable]) -> TBatch:
|
|
407
428
|
"""
|
|
408
429
|
Set multiple keys to multiple values in a single atomic operation.
|
|
@@ -5070,7 +5091,7 @@ class BaseBatch:
|
|
|
5070
5091
|
args.extend(["VERSION", str(version)])
|
|
5071
5092
|
if parameters:
|
|
5072
5093
|
for var in parameters:
|
|
5073
|
-
args.
|
|
5094
|
+
args.append(str(var))
|
|
5074
5095
|
return self.append_command(RequestType.Lolwut, args)
|
|
5075
5096
|
|
|
5076
5097
|
def random_key(self: TBatch) -> TBatch:
|
|
@@ -5754,25 +5775,6 @@ class Batch(BaseBatch):
|
|
|
5754
5775
|
|
|
5755
5776
|
"""
|
|
5756
5777
|
|
|
5757
|
-
# TODO: add SLAVEOF and all SENTINEL commands
|
|
5758
|
-
def move(self, key: TEncodable, db_index: int) -> "Batch":
|
|
5759
|
-
"""
|
|
5760
|
-
Move `key` from the currently selected database to the database specified by `db_index`.
|
|
5761
|
-
|
|
5762
|
-
See [valkey.io](https://valkey.io/commands/move/) for more details.
|
|
5763
|
-
|
|
5764
|
-
Args:
|
|
5765
|
-
key (TEncodable): The key to move.
|
|
5766
|
-
db_index (int): The index of the database to move `key` to.
|
|
5767
|
-
|
|
5768
|
-
Commands response:
|
|
5769
|
-
bool: True if `key` was moved.
|
|
5770
|
-
|
|
5771
|
-
False if the `key` already exists in the destination database
|
|
5772
|
-
or does not exist in the source database.
|
|
5773
|
-
"""
|
|
5774
|
-
return self.append_command(RequestType.Move, [key, str(db_index)])
|
|
5775
|
-
|
|
5776
5778
|
def select(self, index: int) -> "Batch":
|
|
5777
5779
|
"""
|
|
5778
5780
|
Change the currently selected database.
|
|
@@ -5883,7 +5885,11 @@ class ClusterBatch(BaseBatch):
|
|
|
5883
5885
|
self,
|
|
5884
5886
|
source: TEncodable,
|
|
5885
5887
|
destination: TEncodable,
|
|
5888
|
+
# TODO next major release the arguments replace and destinationDB must have their order
|
|
5889
|
+
# swapped to align with the standalone order.
|
|
5890
|
+
# At the moment of the patch release 2.1.1. we can't have a breaking change
|
|
5886
5891
|
replace: Optional[bool] = None,
|
|
5892
|
+
destinationDB: Optional[int] = None,
|
|
5887
5893
|
) -> "ClusterBatch":
|
|
5888
5894
|
"""
|
|
5889
5895
|
Copies the value stored at the `source` to the `destination` key. When `replace` is True,
|
|
@@ -5895,15 +5901,17 @@ class ClusterBatch(BaseBatch):
|
|
|
5895
5901
|
source (TEncodable): The key to the source value.
|
|
5896
5902
|
destination (TEncodable): The key where the value should be copied to.
|
|
5897
5903
|
replace (Optional[bool]): If the destination key should be removed before copying the value to it.
|
|
5898
|
-
|
|
5904
|
+
destinationDB (Optional[int]): The alternative logical database index for the destination key.
|
|
5899
5905
|
Command response:
|
|
5900
5906
|
bool: True if the source was copied.
|
|
5901
5907
|
|
|
5902
5908
|
Otherwise, return False.
|
|
5903
5909
|
|
|
5904
|
-
Since: Valkey version
|
|
5910
|
+
Since: Valkey version 9.0.0.
|
|
5905
5911
|
"""
|
|
5906
5912
|
args = [source, destination]
|
|
5913
|
+
if destinationDB is not None:
|
|
5914
|
+
args.extend(["DB", str(destinationDB)])
|
|
5907
5915
|
if replace is not None:
|
|
5908
5916
|
args.append("REPLACE")
|
|
5909
5917
|
|