27
27
PY3 = sys .version > '3'
28
28
29
29
30
+ if not PY3 :
31
+ from itertools import imap
32
+ basestring = basestring
33
+ unicode = unicode
34
+ bytes = str
35
+ long = long
36
+ b = lambda x : x
37
+ else :
38
+ imap = map
39
+
40
+ basestring = str
41
+ unicode = str
42
+ bytes = bytes
43
+ long = int
44
+ b = lambda x : x .encode ('latin-1' ) if not isinstance (x , bytes ) else x
45
+
46
+ SYM_STAR = b ('*' )
47
+ SYM_DOLLAR = b ('$' )
48
+ SYM_CRLF = b ('\r \n ' )
49
+ SYM_EMPTY = b ('' )
50
+
51
+
30
52
class CmdLine (object ):
31
53
def __init__ (self , cmd , * args , ** kwargs ):
32
54
self .cmd = cmd
@@ -136,7 +158,7 @@ def get_value(value):
136
158
sub_dict [k ] = v
137
159
return sub_dict
138
160
for line in response .splitlines ():
139
- line = line .strip ()
161
+ line = line .strip (). decode ()
140
162
if line and not line .startswith ('#' ):
141
163
key , value = line .split (':' )
142
164
try :
@@ -159,7 +181,7 @@ def reply_fn(r, *args, **kwargs):
159
181
160
182
161
183
def to_list (source ):
162
- if isinstance (source , str ):
184
+ if isinstance (source , ( bytes , str ) ):
163
185
return [source ]
164
186
else :
165
187
return list (source )
@@ -225,7 +247,7 @@ class Client(object):
225
247
226
248
def __init__ (self , host = 'localhost' , port = 6379 , unix_socket_path = None ,
227
249
password = None , selected_db = None , io_loop = None ,
228
- connection_pool = None ):
250
+ connection_pool = None , encoding = 'utf-8' , encoding_errors = 'strict' ):
229
251
self ._io_loop = io_loop or IOLoop .current ()
230
252
self ._connection_pool = connection_pool
231
253
self ._weak = weakref .proxy (self )
@@ -244,6 +266,8 @@ def __init__(self, host='localhost', port=6379, unix_socket_path=None,
244
266
self .password = password
245
267
self .selected_db = selected_db or 0
246
268
self ._pipeline = None
269
+ self .encoding = encoding
270
+ self .encoding_errors = encoding_errors
247
271
248
272
def __del__ (self ):
249
273
try :
@@ -351,24 +375,31 @@ def disconnect(self, callback=None):
351
375
if callback :
352
376
callback (False )
353
377
354
- #### formatting
355
378
def encode (self , value ):
356
- if not isinstance (value , str ):
357
- if not PY3 and isinstance (value , unicode ):
358
- value = value .encode ('utf-8' )
359
- else :
360
- value = str (value )
361
- if PY3 :
362
- value = value .encode ('utf-8' )
379
+ "Return a bytestring representation of the value"
380
+ if isinstance (value , bytes ):
381
+ return value
382
+ elif isinstance (value , (int , long )):
383
+ value = b (str (value ))
384
+ elif isinstance (value , float ):
385
+ value = b (repr (value ))
386
+ elif not isinstance (value , basestring ):
387
+ value = str (value )
388
+ if isinstance (value , unicode ):
389
+ value = value .encode (self .encoding , self .encoding_errors )
363
390
return value
364
391
365
392
def format_command (self , * tokens , ** kwargs ):
366
393
cmds = []
367
- for t in tokens :
368
- e_t = self .encode (t )
369
- e_t_s = to_basestring (e_t )
370
- cmds .append ('$%s\r \n %s\r \n ' % (len (e_t ), e_t_s ))
371
- return '*%s\r \n %s' % (len (tokens ), '' .join (cmds ))
394
+
395
+ buff = SYM_EMPTY .join ((SYM_STAR , b (str (len (tokens ))), SYM_CRLF ))
396
+
397
+ for arg in imap (self .encode , tokens ):
398
+ buff = SYM_EMPTY .join (
399
+ (buff , SYM_DOLLAR , b (str (len (arg ))), SYM_CRLF , arg , SYM_CRLF ))
400
+
401
+ return buff
402
+
372
403
373
404
def format_reply (self , cmd_line , data ):
374
405
if cmd_line .cmd not in REPLY_MAP :
@@ -458,7 +489,6 @@ def _consume_bulk(self, tail, callback=None):
458
489
if not response :
459
490
raise ResponseError ('EmptyResponse' )
460
491
else :
461
- response = to_basestring (response )
462
492
response = response [:- 2 ]
463
493
callback (response )
464
494
@@ -486,6 +516,7 @@ def process_data(self, data, cmd_line):
486
516
tail = tail [4 :]
487
517
response = ResponseError (tail , cmd_line )
488
518
else :
519
+ print ("data: {} cmd_line: {}" .format (data , cmd_line ))
489
520
raise ResponseError ('Unknown response type %s' % head ,
490
521
cmd_line )
491
522
return response
@@ -1033,14 +1064,14 @@ def psubscribe(self, channels, callback=None):
1033
1064
self ._subscribe ('PSUBSCRIBE' , channels , callback = callback )
1034
1065
1035
1066
def _subscribe (self , cmd , channels , callback = None ):
1036
- if isinstance (channels , str ) or (not PY3 and isinstance (channels , unicode )):
1067
+ if isinstance (channels , ( bytes , str ) ) or (not PY3 and isinstance (channels , unicode )):
1037
1068
channels = [channels ]
1038
1069
if not self .subscribed :
1039
1070
listen_callback = None
1040
1071
original_cb = stack_context .wrap (callback ) if callback else None
1041
1072
1042
1073
def _cb (* args , ** kwargs ):
1043
- self .on_subscribed (Message (kind = 'subscribe' ,
1074
+ self .on_subscribed (Message (kind = b 'subscribe' ,
1044
1075
channel = channels [0 ],
1045
1076
body = None ,
1046
1077
pattern = None ))
@@ -1076,7 +1107,7 @@ def punsubscribe(self, channels, callback=None):
1076
1107
self ._unsubscribe ('PUNSUBSCRIBE' , channels , callback = callback )
1077
1108
1078
1109
def _unsubscribe (self , cmd , channels , callback = None ):
1079
- if isinstance (channels , str ) or (not PY3 and isinstance (channels , unicode )):
1110
+ if isinstance (channels , ( bytes , str ) ) or (not PY3 and isinstance (channels , unicode )):
1080
1111
channels = [channels ]
1081
1112
if callback :
1082
1113
cb = stack_context .wrap (callback )
@@ -1137,7 +1168,7 @@ def error_wrapper(e):
1137
1168
self .subscribed = set ()
1138
1169
# send a message to caller:
1139
1170
# Message(kind='disconnect', channel=set(channel1, ...))
1140
- callback (reply_pubsub_message (('disconnect' , channels )))
1171
+ callback (reply_pubsub_message ((b 'disconnect' , channels )))
1141
1172
return
1142
1173
1143
1174
response = self .process_data (data , cmd_listen )
@@ -1149,7 +1180,7 @@ def error_wrapper(e):
1149
1180
1150
1181
result = self .format_reply (cmd_listen , response )
1151
1182
1152
- if result and result .kind in ('subscribe' , 'psubscribe' ):
1183
+ if result and result .kind in (b 'subscribe' , b 'psubscribe' ):
1153
1184
self .on_subscribed (result )
1154
1185
try :
1155
1186
__ , cb = self .subscribe_callbacks .popleft ()
@@ -1158,7 +1189,7 @@ def error_wrapper(e):
1158
1189
if cb :
1159
1190
cb (True )
1160
1191
1161
- if result and result .kind in ('unsubscribe' , 'punsubscribe' ):
1192
+ if result and result .kind in (b 'unsubscribe' , b 'punsubscribe' ):
1162
1193
self .on_unsubscribed ([result .channel ])
1163
1194
1164
1195
callback (result )
@@ -1275,7 +1306,7 @@ def format_replies(self, cmd_lines, responses):
1275
1306
return results
1276
1307
1277
1308
def format_pipeline_request (self , command_stack ):
1278
- return '' .join (self .format_command (c .cmd , * c .args , ** c .kwargs )
1309
+ return SYM_EMPTY .join (self .format_command (c .cmd , * c .args , ** c .kwargs )
1279
1310
for c in command_stack )
1280
1311
1281
1312
@gen .engine
0 commit comments