13
13
WatchError ,
14
14
)
15
15
16
-
17
- def list_or_args (command , keys , args ):
16
+ def list_or_args (keys , args ):
18
17
# returns a single list combining keys and args
19
- # if keys is not a list or args has items, issue a
20
- # deprecation warning
21
- oldapi = bool (args )
22
18
try :
23
19
i = iter (keys )
24
20
# a string can be iterated, but indicates
25
21
# keys wasn't passed as a list
26
22
if isinstance (keys , basestring ):
27
- oldapi = True
23
+ keys = [ keys ]
28
24
except TypeError :
29
- oldapi = True
30
25
keys = [keys ]
31
- if oldapi :
32
- warnings .warn (DeprecationWarning (
33
- "Passing *args to Redis.%s has been deprecated. "
34
- "Pass an iterable to ``keys`` instead" % command
35
- ))
26
+ if args :
36
27
keys .extend (args )
37
28
return keys
38
29
@@ -184,15 +175,15 @@ def __init__(self, host='localhost', port=6379,
184
175
encoding_errors = errors
185
176
)
186
177
187
- def pipeline (self , transaction = True ):
178
+ def pipeline (self , transaction = True , shard_hint = None ):
188
179
"""
189
180
Return a new pipeline object that can queue multiple commands for
190
181
later execution. ``transaction`` indicates whether all commands
191
- should be executed atomically. Apart from multiple atomic operations,
192
- pipelines are useful for batch loading of data as they reduce the
193
- number of back and forth network operations between client and server.
182
+ should be executed atomically. Apart from making a group of operations
183
+ atomic, pipelines are useful for reducing the back-and-forth overhead
184
+ between the client and server.
194
185
"""
195
- return Pipeline (self .connection_pool , transaction )
186
+ return Pipeline (self .connection_pool , transaction , shard_hint )
196
187
197
188
def lock (self , name , timeout = None , sleep = 0.1 ):
198
189
"""
@@ -208,11 +199,17 @@ def lock(self, name, timeout=None, sleep=0.1):
208
199
"""
209
200
return Lock (self , name , timeout = timeout , sleep = sleep )
210
201
211
- def pubsub (self ):
212
- return PubSub (self .connection_pool )
202
+ def pubsub (self , shard_hint = None ):
203
+ """
204
+ Return a Publish/Subscribe object. With this object, you can
205
+ subscribe to channels and listen for messages that get published to
206
+ them.
207
+ """
208
+ return PubSub (self .connection_pool , shard_hint )
213
209
214
210
#### COMMAND EXECUTION AND PROTOCOL PARSING ####
215
211
def execute_command (self , * args , ** options ):
212
+ "Execute a command and return a parsed response"
216
213
command_name = args [0 ]
217
214
connection = self .connection_pool .get_connection (command_name )
218
215
try :
@@ -261,14 +258,6 @@ def delete(self, *names):
261
258
return self .execute_command ('DEL' , * names )
262
259
__delitem__ = delete
263
260
264
- def flush (self , all_dbs = False ):
265
- warnings .warn (DeprecationWarning (
266
- "'flush' has been deprecated. "
267
- "Use Redis.flushdb() or Redis.flushall() instead" ))
268
- if all_dbs :
269
- return self .flushall ()
270
- return self .flushdb ()
271
-
272
261
def flushall (self ):
273
262
"Delete all keys in all databases on the current host"
274
263
return self .execute_command ('FLUSHALL' )
@@ -300,7 +289,13 @@ def save(self):
300
289
return self .execute_command ('SAVE' )
301
290
302
291
def select (self , db ):
303
- "Select a differnet Redis database"
292
+ """
293
+ Select a differnet Redis database.
294
+
295
+ WARNING: this could have severe consequences for pooled connections.
296
+ It's highly advised to use a separate connection pool and client
297
+ instance to work with multiple databases. Use this at your own risk.
298
+ """
304
299
return self .execute_command ('SELECT' , db )
305
300
306
301
def shutdown (self ):
@@ -370,8 +365,7 @@ def __getitem__(self, name):
370
365
value = self .get (name )
371
366
if value :
372
367
return value
373
- else :
374
- raise KeyError (name )
368
+ raise KeyError (name )
375
369
376
370
def getbit (self , name , offset ):
377
371
"Returns a boolean indicating the value of ``offset`` in ``name``"
@@ -398,10 +392,8 @@ def keys(self, pattern='*'):
398
392
def mget (self , keys , * args ):
399
393
"""
400
394
Returns a list of values ordered identically to ``keys``
401
-
402
- * Passing *args to this method has been deprecated *
403
395
"""
404
- keys = list_or_args ('mget' , keys , args )
396
+ keys = list_or_args (keys , args )
405
397
return self .execute_command ('MGET' , * keys )
406
398
407
399
def mset (self , mapping ):
@@ -433,29 +425,17 @@ def randomkey(self):
433
425
"Returns the name of a random key"
434
426
return self .execute_command ('RANDOMKEY' )
435
427
436
- def rename (self , src , dst , ** kwargs ):
428
+ def rename (self , src , dst ):
437
429
"""
438
430
Rename key ``src`` to ``dst``
439
-
440
- * The following flags have been deprecated *
441
- If ``preserve`` is True, rename the key only if the destination name
442
- doesn't already exist
443
- """
444
- if kwargs :
445
- if 'preserve' in kwargs :
446
- warnings .warn (DeprecationWarning (
447
- "preserve option to 'rename' is deprecated, "
448
- "use Redis.renamenx instead" ))
449
- if kwargs ['preserve' ]:
450
- return self .renamenx (src , dst )
431
+ """
451
432
return self .execute_command ('RENAME' , src , dst )
452
433
453
434
def renamenx (self , src , dst ):
454
435
"Rename key ``src`` to ``dst`` if ``dst`` doesn't already exist"
455
436
return self .execute_command ('RENAMENX' , src , dst )
456
437
457
-
458
- def set (self , name , value , ** kwargs ):
438
+ def set (self , name , value ):
459
439
"""
460
440
Set the value at key ``name`` to ``value``
461
441
@@ -465,19 +445,6 @@ def set(self, name, value, **kwargs):
465
445
If ``getset`` is True, set the value only if key doesn't already exist
466
446
and return the resulting value of key
467
447
"""
468
- if kwargs :
469
- if 'getset' in kwargs :
470
- warnings .warn (DeprecationWarning (
471
- "getset option to 'set' is deprecated, "
472
- "use Redis.getset() instead" ))
473
- if kwargs ['getset' ]:
474
- return self .getset (name , value )
475
- if 'preserve' in kwargs :
476
- warnings .warn (DeprecationWarning (
477
- "preserve option to 'set' is deprecated, "
478
- "use Redis.setnx() instead" ))
479
- if kwargs ['preserve' ]:
480
- return self .setnx (name , value )
481
448
return self .execute_command ('SET' , name , value )
482
449
__setitem__ = set
483
450
@@ -778,28 +745,28 @@ def scard(self, name):
778
745
779
746
def sdiff (self , keys , * args ):
780
747
"Return the difference of sets specified by ``keys``"
781
- keys = list_or_args ('sdiff' , keys , args )
748
+ keys = list_or_args (keys , args )
782
749
return self .execute_command ('SDIFF' , * keys )
783
750
784
751
def sdiffstore (self , dest , keys , * args ):
785
752
"""
786
753
Store the difference of sets specified by ``keys`` into a new
787
754
set named ``dest``. Returns the number of keys in the new set.
788
755
"""
789
- keys = list_or_args ('sdiffstore' , keys , args )
756
+ keys = list_or_args (keys , args )
790
757
return self .execute_command ('SDIFFSTORE' , dest , * keys )
791
758
792
759
def sinter (self , keys , * args ):
793
760
"Return the intersection of sets specified by ``keys``"
794
- keys = list_or_args ('sinter' , keys , args )
761
+ keys = list_or_args (keys , args )
795
762
return self .execute_command ('SINTER' , * keys )
796
763
797
764
def sinterstore (self , dest , keys , * args ):
798
765
"""
799
766
Store the intersection of sets specified by ``keys`` into a new
800
767
set named ``dest``. Returns the number of keys in the new set.
801
768
"""
802
- keys = list_or_args ('sinterstore' , keys , args )
769
+ keys = list_or_args (keys , args )
803
770
return self .execute_command ('SINTERSTORE' , dest , * keys )
804
771
805
772
def sismember (self , name , value ):
@@ -828,15 +795,15 @@ def srem(self, name, value):
828
795
829
796
def sunion (self , keys , * args ):
830
797
"Return the union of sets specifiued by ``keys``"
831
- keys = list_or_args ('sunion' , keys , args )
798
+ keys = list_or_args (keys , args )
832
799
return self .execute_command ('SUNION' , * keys )
833
800
834
801
def sunionstore (self , dest , keys , * args ):
835
802
"""
836
803
Store the union of sets specified by ``keys`` into a new
837
804
set named ``dest``. Returns the number of keys in the new set.
838
805
"""
839
- keys = list_or_args ('sunionstore' , keys , args )
806
+ keys = list_or_args (keys , args )
840
807
return self .execute_command ('SUNIONSTORE' , dest , * keys )
841
808
842
809
@@ -993,12 +960,6 @@ def zscore(self, name, value):
993
960
"Return the score of element ``value`` in sorted set ``name``"
994
961
return self .execute_command ('ZSCORE' , name , value )
995
962
996
- def zunion (self , dest , keys , aggregate = None ):
997
- warnings .warn (DeprecationWarning (
998
- "Redis.zunion has been deprecated, use Redis.zunionstore instead"
999
- ))
1000
- return self .zunionstore (dest , keys , aggregate )
1001
-
1002
963
def zunionstore (self , dest , keys , aggregate = None ):
1003
964
"""
1004
965
Union multiple sorted sets specified by ``keys`` into
@@ -1094,8 +1055,9 @@ def publish(self, channel, message):
1094
1055
1095
1056
1096
1057
class PubSub (object ):
1097
- def __init__ (self , connection_pool ):
1058
+ def __init__ (self , connection_pool , shard_hint = None ):
1098
1059
self .connection_pool = connection_pool
1060
+ self .shard_hint = shard_hint
1099
1061
self .connection = None
1100
1062
self .channels = set ()
1101
1063
self .patterns = set ()
@@ -1107,7 +1069,10 @@ def __init__(self, connection_pool):
1107
1069
def execute_command (self , * args , ** kwargs ):
1108
1070
"Execute a publish/subscribe command"
1109
1071
if self .connection is None :
1110
- self .connection = self .connection_pool .get_connection ('pubsub' )
1072
+ self .connection = self .connection_pool .get_connection (
1073
+ 'pubsub' ,
1074
+ self .shard_hint
1075
+ )
1111
1076
connection = self .connection
1112
1077
try :
1113
1078
connection .send_command (* args )
@@ -1225,9 +1190,10 @@ class Pipeline(Redis):
1225
1190
ResponseError exceptions, such as those raised when issuing a command
1226
1191
on a key of a different datatype.
1227
1192
"""
1228
- def __init__ (self , connection_pool , transaction ):
1193
+ def __init__ (self , connection_pool , transaction , shard_hint ):
1229
1194
self .connection_pool = connection_pool
1230
1195
self .transaction = transaction
1196
+ self .shard_hint = shard_hint
1231
1197
self .reset ()
1232
1198
1233
1199
def reset (self ):
@@ -1251,20 +1217,20 @@ def execute_command(self, *args, **options):
1251
1217
return self
1252
1218
1253
1219
def _execute_transaction (self , commands ):
1254
- connection = self .connection_pool .get_connection ('MULTI' )
1220
+ conn = self .connection_pool .get_connection ('MULTI' , self . shard_hint )
1255
1221
try :
1256
- all_cmds = '' .join (starmap (connection .pack_command ,
1222
+ all_cmds = '' .join (starmap (conn .pack_command ,
1257
1223
[args for args , options in commands ]))
1258
- connection .send_packed_command (all_cmds )
1224
+ conn .send_packed_command (all_cmds )
1259
1225
# we don't care about the multi/exec any longer
1260
1226
commands = commands [1 :- 1 ]
1261
1227
# parse off the response for MULTI and all commands prior to EXEC.
1262
1228
# the only data we care about is the response the EXEC
1263
1229
# which is the last command
1264
1230
for i in range (len (commands )+ 1 ):
1265
- _ = self .parse_response (connection , '_' )
1231
+ _ = self .parse_response (conn , '_' )
1266
1232
# parse the EXEC.
1267
- response = self .parse_response (connection , '_' )
1233
+ response = self .parse_response (conn , '_' )
1268
1234
1269
1235
if response is None :
1270
1236
raise WatchError ("Watched variable changed." )
@@ -1283,19 +1249,19 @@ def _execute_transaction(self, commands):
1283
1249
data .append (r )
1284
1250
return data
1285
1251
finally :
1286
- self .connection_pool .release (connection )
1252
+ self .connection_pool .release (conn )
1287
1253
1288
1254
def _execute_pipeline (self , commands ):
1289
1255
# build up all commands into a single request to increase network perf
1290
- connection = self .connection_pool .get_connection ('MULTI' )
1256
+ conn = self .connection_pool .get_connection ('MULTI' , self . shard_hint )
1291
1257
try :
1292
- all_cmds = '' .join (starmap (connection .pack_command ,
1258
+ all_cmds = '' .join (starmap (conn .pack_command ,
1293
1259
[args for args , options in commands ]))
1294
- connection .send_packed_command (all_cmds )
1295
- return [self .parse_response (connection , args [0 ], ** options )
1260
+ conn .send_packed_command (all_cmds )
1261
+ return [self .parse_response (conn , args [0 ], ** options )
1296
1262
for args , options in commands ]
1297
1263
finally :
1298
- self .connection_pool .release (connection )
1264
+ self .connection_pool .release (conn )
1299
1265
1300
1266
def execute (self ):
1301
1267
"Execute all the commands in the current pipeline"
@@ -1312,9 +1278,6 @@ def execute(self):
1312
1278
connection .disconnect ()
1313
1279
return execute (stack )
1314
1280
1315
- def select (self , * args , ** kwargs ):
1316
- raise RedisError ("Cannot select a different database from a pipeline" )
1317
-
1318
1281
class LockError (RedisError ):
1319
1282
"Errors thrown from the Lock"
1320
1283
pass
0 commit comments