@@ -177,14 +177,21 @@ def __init__(self, host='localhost', port=6379,
177
177
db = 0 , password = None , socket_timeout = None ,
178
178
connection_pool = None ,
179
179
charset = 'utf-8' , errors = 'strict' ):
180
- self .encoding = charset
181
- self .errors = errors
182
- self .connection = None
183
180
self .subscribed = False
184
- self .connection_pool = connection_pool and connection_pool or ConnectionPool ()
185
- self .select (db , host , port , password , socket_timeout )
186
-
187
- #### Legacty accessors of connection information ####
181
+ if connection_pool :
182
+ self .connection_pool = connection_pool
183
+ else :
184
+ self .connection_pool = ConnectionPool (
185
+ host = host ,
186
+ port = port ,
187
+ db = db ,
188
+ password = password ,
189
+ socket_timeout = socket_timeout ,
190
+ encoding = charset ,
191
+ encoding_errors = errors
192
+ )
193
+
194
+ #### Legacy accessors of connection information ####
188
195
def _get_host (self ):
189
196
return self .connection .host
190
197
host = property (_get_host )
@@ -205,12 +212,7 @@ def pipeline(self, transaction=True):
205
212
pipelines are useful for batch loading of data as they reduce the
206
213
number of back and forth network operations between client and server.
207
214
"""
208
- return Pipeline (
209
- self .connection ,
210
- transaction ,
211
- self .encoding ,
212
- self .errors
213
- )
215
+ return Pipeline (self .connection_pool , transaction )
214
216
215
217
def lock (self , name , timeout = None , sleep = 0.1 ):
216
218
"""
@@ -228,77 +230,38 @@ def lock(self, name, timeout=None, sleep=0.1):
228
230
229
231
#### COMMAND EXECUTION AND PROTOCOL PARSING ####
230
232
def execute_command (self , * args , ** options ):
231
- command_name = args [0 ]
232
- subscription_command = command_name in self .SUBSCRIPTION_COMMANDS
233
- if self .subscribed and not subscription_command :
234
- raise PubSubError ("Cannot issue commands other than SUBSCRIBE and "
235
- "UNSUBSCRIBE while channels are open" )
233
+ connection = self .connection_pool .get_connection ()
236
234
try :
237
- self .connection .send_command (* args )
238
- if subscription_command :
239
- return None
240
- return self .parse_response (command_name , ** options )
241
- except ConnectionError :
242
- self .connection .disconnect ()
243
- self .connection .send_command (* args )
244
- if subscription_command :
245
- return None
246
- return self .parse_response (command_name , ** options )
247
-
248
- def parse_response (self , command_name , ** options ):
235
+ command_name = args [0 ]
236
+ subscription_command = command_name in self .SUBSCRIPTION_COMMANDS
237
+ if self .subscribed and not subscription_command :
238
+ raise PubSubError ("Cannot issue commands other than SUBSCRIBE "
239
+ "and UNSUBSCRIBE while channels are open" )
240
+ try :
241
+ connection .send_command (* args )
242
+ if subscription_command :
243
+ return None
244
+ return self .parse_response (connection , command_name , ** options )
245
+ except ConnectionError :
246
+ connection .disconnect ()
247
+ connection .send_command (* args )
248
+ if subscription_command :
249
+ return None
250
+ return self .parse_response (connection , command_name , ** options )
251
+ finally :
252
+ self .connection_pool .release (connection )
253
+
254
+ def parse_response (self , connection , command_name , ** options ):
249
255
"Parses a response from the Redis server"
250
- response = self . connection .read_response ()
256
+ response = connection .read_response ()
251
257
if command_name in self .RESPONSE_CALLBACKS :
252
258
return self .RESPONSE_CALLBACKS [command_name ](response , ** options )
253
259
return response
254
260
255
261
#### CONNECTION HANDLING ####
256
- def get_connection (self , host , port , db , password , socket_timeout ):
257
- "Returns a connection object"
258
- conn = self .connection_pool .get_connection (
259
- host , port , db , password , socket_timeout )
260
- # if for whatever reason the connection gets a bad password, make
261
- # sure a subsequent attempt with the right password makes its way
262
- # to the connection
263
- conn .password = password
264
- return conn
265
-
266
- def _setup_connection (self ):
267
- """
268
- After successfully opening a socket to the Redis server, the
269
- connection object calls this method to authenticate and select
270
- the appropriate database.
271
- """
272
- self .subscribed = False
273
- if self .connection .password :
274
- if not self .execute_command ('AUTH' , self .connection .password ):
275
- raise AuthenticationError ("Invalid Password" )
276
- self .execute_command ('SELECT' , self .connection .db )
277
-
278
- def select (self , db , host = None , port = None , password = None ,
279
- socket_timeout = None ):
280
- """
281
- Switch to a different Redis connection.
282
-
283
- If the host and port aren't provided and there's an existing
284
- connection, use the existing connection's host and port instead.
285
-
286
- Note this method actually replaces the underlying connection object
287
- prior to issuing the SELECT command. This makes sure we protect
288
- the thread-safe connections
289
- """
290
- if host is None :
291
- if self .connection is None :
292
- raise RedisError ("A valid hostname or IP address "
293
- "must be specified" )
294
- host = self .connection .host
295
- if port is None :
296
- if self .connection is None :
297
- raise RedisError ("A valid port must be specified" )
298
- port = self .connection .port
299
-
300
- self .connection = self .get_connection (
301
- host , port , db , password , socket_timeout )
262
+ def select (self , db ):
263
+ "SELECT a differnet Redis database."
264
+ return self .execute_command ('SELECT' , db )
302
265
303
266
def shutdown (self ):
304
267
"Shutdown the server"
@@ -1246,11 +1209,9 @@ class Pipeline(Redis):
1246
1209
ResponseError exceptions, such as those raised when issuing a command
1247
1210
on a key of a different datatype.
1248
1211
"""
1249
- def __init__ (self , connection , transaction , charset , errors ):
1250
- self .connection = connection
1212
+ def __init__ (self , connection_pool , transaction ):
1213
+ self .connection_pool = connection_pool
1251
1214
self .transaction = transaction
1252
- self .encoding = charset
1253
- self .errors = errors
1254
1215
self .subscribed = False # NOTE not in use, but necessary
1255
1216
self .reset ()
1256
1217
@@ -1275,42 +1236,51 @@ def execute_command(self, *args, **options):
1275
1236
return self
1276
1237
1277
1238
def _execute_transaction (self , commands ):
1278
- all_cmds = '' .join (starmap (self .connection .pack_command ,
1279
- [args for args , options in commands ]))
1280
- self .connection .send_packed_command (all_cmds )
1281
- # we don't care about the multi/exec any longer
1282
- commands = commands [1 :- 1 ]
1283
- # parse off the response for MULTI and all commands prior to EXEC
1284
- # the only data we care about is the response the EXEC, the last command
1285
- for i in range (len (commands )+ 1 ):
1286
- _ = self .parse_response ('_' )
1287
- # parse the EXEC.
1288
- response = self .parse_response ('_' )
1289
-
1290
- if response is None :
1291
- raise WatchError ("Watched variable changed." )
1292
-
1293
- if len (response ) != len (commands ):
1294
- raise ResponseError ("Wrong number of response items from "
1295
- "pipeline execution" )
1296
- # We have to run response callbacks manually
1297
- data = []
1298
- for r , cmd in izip (response , commands ):
1299
- if not isinstance (r , Exception ):
1300
- args , options = cmd
1301
- command_name = args [0 ]
1302
- if command_name in self .RESPONSE_CALLBACKS :
1303
- r = self .RESPONSE_CALLBACKS [command_name ](r , ** options )
1304
- data .append (r )
1305
- return data
1239
+ connection = self .connection_pool .get_connection ()
1240
+ try :
1241
+ all_cmds = '' .join (starmap (connection .pack_command ,
1242
+ [args for args , options in commands ]))
1243
+ connection .send_packed_command (all_cmds )
1244
+ # we don't care about the multi/exec any longer
1245
+ commands = commands [1 :- 1 ]
1246
+ # parse off the response for MULTI and all commands prior to EXEC.
1247
+ # the only data we care about is the response the EXEC
1248
+ # which is the last command
1249
+ for i in range (len (commands )+ 1 ):
1250
+ _ = self .parse_response (connection , '_' )
1251
+ # parse the EXEC.
1252
+ response = self .parse_response (connection , '_' )
1253
+
1254
+ if response is None :
1255
+ raise WatchError ("Watched variable changed." )
1256
+
1257
+ if len (response ) != len (commands ):
1258
+ raise ResponseError ("Wrong number of response items from "
1259
+ "pipeline execution" )
1260
+ # We have to run response callbacks manually
1261
+ data = []
1262
+ for r , cmd in izip (response , commands ):
1263
+ if not isinstance (r , Exception ):
1264
+ args , options = cmd
1265
+ command_name = args [0 ]
1266
+ if command_name in self .RESPONSE_CALLBACKS :
1267
+ r = self .RESPONSE_CALLBACKS [command_name ](r , ** options )
1268
+ data .append (r )
1269
+ return data
1270
+ finally :
1271
+ self .connection_pool .release (connection )
1306
1272
1307
1273
def _execute_pipeline (self , commands ):
1308
1274
# build up all commands into a single request to increase network perf
1309
- all_cmds = '' .join (starmap (self .connection .pack_command ,
1310
- [args for args , options in commands ]))
1311
- self .connection .send_packed_command (all_cmds )
1312
- return [self .parse_response (args [0 ], ** options )
1313
- for args , options in commands ]
1275
+ connection = self .connection_pool .get_connection ()
1276
+ try :
1277
+ all_cmds = '' .join (starmap (connection .pack_command ,
1278
+ [args for args , options in commands ]))
1279
+ connection .send_packed_command (all_cmds )
1280
+ return [self .parse_response (connection , args [0 ], ** options )
1281
+ for args , options in commands ]
1282
+ finally :
1283
+ self .connection_pool .release (connection )
1314
1284
1315
1285
def execute (self ):
1316
1286
"Execute all the commands in the current pipeline"
@@ -1324,7 +1294,7 @@ def execute(self):
1324
1294
try :
1325
1295
return execute (stack )
1326
1296
except ConnectionError :
1327
- self . connection .disconnect ()
1297
+ connection .disconnect ()
1328
1298
return execute (stack )
1329
1299
1330
1300
def select (self , * args , ** kwargs ):
0 commit comments