@@ -15,11 +15,12 @@ def make_connection_key(self, host, port, db):
15
15
"Create a unique key for the specified host, port and db"
16
16
return '%s:%s:%s' % (host , port , db )
17
17
18
- def get_connection (self , host , port , db , password ):
18
+ def get_connection (self , host , port , db , password , socket_timeout ):
19
19
"Return a specific connection for the specified host, port and db"
20
20
key = self .make_connection_key (host , port , db )
21
21
if key not in self .connections :
22
- self .connections [key ] = Connection (host , port , db , password )
22
+ self .connections [key ] = Connection (
23
+ host , port , db , password , socket_timeout )
23
24
return self .connections [key ]
24
25
25
26
def get_all_connections (self ):
@@ -30,11 +31,13 @@ def get_all_connections(self):
30
31
31
32
class Connection (object ):
32
33
"Manages TCP communication to and from a Redis server"
33
- def __init__ (self , host = 'localhost' , port = 6379 , db = 0 , password = None ):
34
+ def __init__ (self , host = 'localhost' , port = 6379 , db = 0 , password = None ,
35
+ socket_timeout = None ):
34
36
self .host = host
35
37
self .port = port
36
38
self .db = db
37
39
self .password = password
40
+ self .socket_timeout = socket_timeout
38
41
self ._sock = None
39
42
self ._fp = None
40
43
@@ -49,6 +52,7 @@ def connect(self, redis_instance):
49
52
raise ConnectionError ("Error %s connecting to %s:%s. %s." % \
50
53
(e .args [0 ], self .host , self .port , e .args [1 ]))
51
54
sock .setsockopt (socket .SOL_TCP , socket .TCP_NODELAY , 1 )
55
+ sock .settimeout (self .socket_timeout )
52
56
self ._sock = sock
53
57
self ._fp = sock .makefile ('r' )
54
58
redis_instance ._setup_connection ()
@@ -179,13 +183,13 @@ class Redis(threading.local):
179
183
"""
180
184
RESPONSE_CALLBACKS = dict_merge (
181
185
string_keys_to_dict (
182
- 'AUTH DEL EXISTS EXPIRE HDEL MOVE MSETNX RENAMENX '
186
+ 'AUTH DEL EXISTS EXPIRE HDEL HEXISTS MOVE MSETNX RENAMENX '
183
187
'SADD SISMEMBER SMOVE SETNX SREM ZADD ZREM' ,
184
188
bool
185
189
),
186
190
string_keys_to_dict (
187
- 'DECRBY INCRBY LLEN SCARD SDIFFSTORE SINTERSTORE SUNIONSTORE '
188
- 'ZCARD ZRANK ZREMRANGEBYSCORE ZREVRANK' ,
191
+ 'DECRBY HLEN INCRBY LLEN SCARD SDIFFSTORE SINTERSTORE '
192
+ 'SUNIONSTORE ZCARD ZRANK ZREMRANGEBYSCORE ZREVRANK' ,
189
193
int
190
194
),
191
195
string_keys_to_dict (
@@ -216,11 +220,11 @@ class Redis(threading.local):
216
220
)
217
221
218
222
def __init__ (self , host = 'localhost' , port = 6379 ,
219
- db = 0 , password = None ,
223
+ db = 0 , password = None , socket_timeout = None ,
220
224
charset = 'utf-8' , errors = 'strict' ):
221
225
self .encoding = charset
222
226
self .errors = errors
223
- self .select (host , port , db , password )
227
+ self .select (host , port , db , password , socket_timeout )
224
228
225
229
#### Legacty accessors of connection information ####
226
230
def _get_host (self ):
@@ -350,9 +354,10 @@ def format_multi_bulk(self, *args, **options):
350
354
)
351
355
352
356
#### CONNECTION HANDLING ####
353
- def get_connection (self , host , port , db , password ):
357
+ def get_connection (self , host , port , db , password , socket_timeout ):
354
358
"Returns a connection object"
355
- conn = connection_manager .get_connection (host , port , db , password )
359
+ conn = connection_manager .get_connection (
360
+ host , port , db , password , socket_timeout )
356
361
# if for whatever reason the connection gets a bad password, make
357
362
# sure a subsequent attempt with the right password makes its way
358
363
# to the connection
@@ -370,15 +375,16 @@ def _setup_connection(self):
370
375
raise AuthenticationError ("Invalid Password" )
371
376
self .format_inline ('SELECT' , self .connection .db )
372
377
373
- def select (self , host , port , db , password = None ):
378
+ def select (self , host , port , db , password = None , socket_timeout = None ):
374
379
"""
375
380
Switch to a different database on the current host/port
376
381
377
382
Note this method actually replaces the underlying connection object
378
383
prior to issuing the SELECT command. This makes sure we protect
379
384
the thread-safe connections
380
385
"""
381
- self .connection = self .get_connection (host , port , db , password )
386
+ self .connection = self .get_connection (
387
+ host , port , db , password , socket_timeout )
382
388
383
389
#### SERVER INFORMATION ####
384
390
def bgsave (self ):
@@ -920,6 +926,10 @@ def zscore(self, name, value):
920
926
def hdel (self , name , key ):
921
927
"Delete ``key`` from hash ``name``"
922
928
return self .format_bulk ('HDEL' , name , key )
929
+
930
+ def hexists (self , name , key ):
931
+ "Returns a boolean indicating if ``key`` exists within hash ``name``"
932
+ return self .format_bulk ('HEXISTS' , name , key )
923
933
924
934
def hget (self , name , key ):
925
935
"Return the value of ``key`` within the hash ``name``"
@@ -933,6 +943,10 @@ def hkeys(self, name):
933
943
"Return the list of keys within hash ``name``"
934
944
return self .format_inline ('HKEYS' , name )
935
945
946
+ def hlen (self , name ):
947
+ "Return the number of elements in hash ``name``"
948
+ return self .format_inline ('HLEN' , name )
949
+
936
950
def hset (self , name , key , value ):
937
951
"""
938
952
Set ``key`` to ``value`` within hash ``name``
0 commit comments