Skip to content

Commit d637146

Browse files
author
Samuel Charron
committed
Conflicts: redis/connection.py tests/__init__.py tests/server_commands.py
2 parents d7678e0 + ffb0881 commit d637146

File tree

6 files changed

+139
-45
lines changed

6 files changed

+139
-45
lines changed

redis/client.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,16 @@
22
import datetime
33
import time
44
import warnings
5-
from itertools import imap, izip, starmap
5+
from itertools import starmap
6+
from redis.compat import (
7+
basestring,
8+
bytes,
9+
imap,
10+
izip,
11+
long,
12+
MAJOR_VERSION,
13+
unicode,
14+
)
615
from redis.connection import ConnectionPool, UnixDomainSocketConnection
716
from redis.exceptions import (
817
ConnectionError,
@@ -109,7 +118,7 @@ def zset_score_pairs(response, **options):
109118
return response
110119
score_cast_func = options.get('score_cast_func', float)
111120
it = iter(response)
112-
return zip(it, imap(score_cast_func, it))
121+
return list(zip(it, imap(score_cast_func, it)))
113122

114123
def int_or_none(response):
115124
if response is None:
@@ -463,7 +472,7 @@ def mget(self, keys, *args):
463472
def mset(self, mapping):
464473
"Sets each key in the ``mapping`` dict to its corresponding value"
465474
items = []
466-
for pair in mapping.iteritems():
475+
for pair in mapping.items():
467476
items.extend(pair)
468477
return self.execute_command('MSET', *items)
469478

@@ -473,7 +482,7 @@ def msetnx(self, mapping):
473482
none of the keys are already set
474483
"""
475484
items = []
476-
for pair in mapping.iteritems():
485+
for pair in mapping.items():
477486
items.extend(pair)
478487
return self.execute_command('MSETNX', *items)
479488

@@ -857,7 +866,7 @@ def zadd(self, name, *args, **kwargs):
857866
raise RedisError("ZADD requires an equal number of "
858867
"values and scores")
859868
pieces.extend(args)
860-
for pair in kwargs.iteritems():
869+
for pair in kwargs.items():
861870
pieces.append(pair[1])
862871
pieces.append(pair[0])
863872
return self.execute_command('ZADD', name, *pieces)
@@ -1085,7 +1094,7 @@ def hmset(self, name, mapping):
10851094
if not mapping:
10861095
raise DataError("'hmset' with 'mapping' of length 0")
10871096
items = []
1088-
for pair in mapping.iteritems():
1097+
for pair in mapping.items():
10891098
items.extend(pair)
10901099
return self.execute_command('HMSET', name, *items)
10911100

@@ -1180,7 +1189,7 @@ def zadd(self, name, *args, **kwargs):
11801189
raise RedisError("ZADD requires an equal number of "
11811190
"values and scores")
11821191
pieces.extend(reversed(args))
1183-
for pair in kwargs.iteritems():
1192+
for pair in kwargs.items():
11841193
pieces.append(pair[1])
11851194
pieces.append(pair[0])
11861195
return self.execute_command('ZADD', name, *pieces)

redis/compat.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import sys
2+
3+
__all__ = ['basestring', 'bytes', 'imap', 'izip', 'long', 'unicode', 'unichr', 'xrange']
4+
5+
MAJOR_VERSION = sys.version_info.major
6+
7+
if MAJOR_VERSION >= 3:
8+
basestring = str
9+
bytes = bytes
10+
imap = map
11+
izip = zip
12+
long = int
13+
unichr = chr
14+
unicode = str
15+
xrange = range
16+
else:
17+
from itertools import imap, izip
18+
19+
basestring = basestring
20+
try:
21+
bytes = bytes
22+
except NameError:
23+
bytes = str
24+
long = long
25+
unichr = unichr
26+
unicode = unicode
27+
xrange = xrange

redis/connection.py

Lines changed: 64 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
import socket
2-
from itertools import chain, imap
2+
import sys
3+
from itertools import chain
4+
from redis.compat import (
5+
bytes,
6+
imap,
7+
long,
8+
unicode,
9+
xrange,
10+
MAJOR_VERSION
11+
)
312
from redis.exceptions import (
413
RedisError,
514
ConnectionError,
@@ -8,10 +17,13 @@
817
AuthenticationError
918
)
1019

11-
try:
12-
from cStringIO import StringIO
13-
except ImportError:
14-
from StringIO import StringIO
20+
if MAJOR_VERSION >= 3:
21+
from io import StringIO
22+
else:
23+
try:
24+
from cStringIO import StringIO
25+
except ImportError:
26+
from StringIO import StringIO
1527

1628
try:
1729
import hiredis
@@ -34,7 +46,11 @@ def __del__(self):
3446

3547
def on_connect(self, connection):
3648
"Called when the socket connects"
37-
self._fp = connection._sock.makefile('r')
49+
if MAJOR_VERSION >= 3:
50+
fmode = 'rb'
51+
else:
52+
fmode = 'r'
53+
self._fp = connection._sock.makefile(fmode)
3854

3955
def on_disconnect(self):
4056
"Called when the socket disconnects"
@@ -44,7 +60,7 @@ def on_disconnect(self):
4460

4561
def read(self, length=None):
4662
"""
47-
Read a line from the socket is no length is specified,
63+
Read a line from the socket if no length is specified,
4864
otherwise read ``length`` bytes. Always strip away the newlines.
4965
"""
5066
try:
@@ -59,17 +75,28 @@ def read(self, length=None):
5975
buf = StringIO()
6076
while bytes_left > 0:
6177
read_len = min(bytes_left, self.MAX_READ_LENGTH)
62-
buf.write(self._fp.read(read_len))
78+
if MAJOR_VERSION >= 3:
79+
buf.write(self._fp.read(read_len).decode("utf-8"))
80+
else:
81+
buf.write(self._fp.read(read_len))
6382
bytes_left -= read_len
6483
buf.seek(0)
65-
return buf.read(length)
84+
result = buf.read(length)
85+
return result
6686
finally:
6787
buf.close()
68-
return self._fp.read(bytes_left)[:-2]
88+
result = self._fp.read(bytes_left)[:-2]
89+
if MAJOR_VERSION >= 3:
90+
result = result.decode()
91+
return result
6992

7093
# no length, read a full line
71-
return self._fp.readline()[:-2]
72-
except (socket.error, socket.timeout), e:
94+
result = self._fp.readline()[:-2]
95+
if MAJOR_VERSION >= 3:
96+
result = result.decode()
97+
return result
98+
except (socket.error, socket.timeout):
99+
e = sys.exc_info()[1]
73100
raise ConnectionError("Error while reading from socket: %s" % \
74101
(e.args,))
75102

@@ -139,7 +166,8 @@ def read_response(self):
139166
while response is False:
140167
try:
141168
buffer = self._sock.recv(4096)
142-
except (socket.error, socket.timeout), e:
169+
except (socket.error, socket.timeout):
170+
e = sys.exc_info()[1]
143171
raise ConnectionError("Error while reading from socket: %s" % \
144172
(e.args,))
145173
if not buffer:
@@ -185,7 +213,8 @@ def connect(self):
185213
return
186214
try:
187215
sock = self._connect()
188-
except socket.error, e:
216+
except socket.error:
217+
e = sys.exc_info()[1]
189218
raise ConnectionError(self._error_message(e))
190219

191220
self._sock = sock
@@ -240,8 +269,11 @@ def send_packed_command(self, command):
240269
if not self._sock:
241270
self.connect()
242271
try:
272+
if MAJOR_VERSION >= 3:
273+
command = command.encode()
243274
self._sock.sendall(command)
244-
except socket.error, e:
275+
except socket.error:
276+
e = sys.exc_info()[1]
245277
self.disconnect()
246278
if len(e.args) == 1:
247279
_errno, errmsg = 'UNKNOWN', e.args[0]
@@ -276,9 +308,23 @@ def encode(self, value):
276308

277309
def pack_command(self, *args):
278310
"Pack a series of arguments into a value Redis command"
279-
command = ['$%s\r\n%s\r\n' % (len(enc_value), enc_value)
280-
for enc_value in imap(self.encode, args)]
281-
return '*%s\r\n%s' % (len(command), ''.join(command))
311+
312+
cmds = []
313+
if MAJOR_VERSION >= 3:
314+
for enc_value in imap(self.encode, args):
315+
if isinstance(enc_value, bytes):
316+
cmds += ['$%s\r\n%s\r\n' % (len(enc_value),
317+
enc_value.decode())]
318+
else:
319+
cmds += ['$%s\r\n%s\r\n' % (len(enc_value),
320+
enc_value)]
321+
else:
322+
for enc_value in imap(self.encode, args):
323+
cmds += ['$%s\r\n%s\r\n' % (len(enc_value),
324+
enc_value)]
325+
326+
return '*%s\r\n%s' % (len(cmds), ''.join(cmds))
327+
282328

283329
class UnixDomainSocketConnection(Connection):
284330
def __init__(self, path='', db=0, password=None,

tests/__init__.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import unittest
2-
from server_commands import ServerCommandsTestCase
3-
from connection_pool import ConnectionPoolTestCase
4-
from pipeline import PipelineTestCase
5-
from lock import LockTestCase
6-
from pubsub import PubSubTestCase, PubSubRedisDownTestCase
2+
from tests.server_commands import ServerCommandsTestCase
3+
from tests.connection_pool import ConnectionPoolTestCase
4+
from tests.pipeline import PipelineTestCase
5+
from tests.lock import LockTestCase
6+
from tests.pubsub import PubSubTestCase, PubSubRedisDownTestCase
77

88
use_hiredis = False
99
try:

tests/pubsub.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def test_channel_subscribe(self):
1919
)
2020
self.assertEquals(self.client.publish('foo', 'hello foo'), 1)
2121
self.assertEquals(
22-
self.pubsub.listen().next(),
22+
next(self.pubsub.listen()),
2323
{
2424
'type': 'message',
2525
'pattern': None,
@@ -39,7 +39,7 @@ def test_pattern_subscribe(self):
3939
)
4040
self.assertEquals(self.client.publish('foo', 'hello foo'), 1)
4141
self.assertEquals(
42-
self.pubsub.listen().next(),
42+
next(self.pubsub.listen()),
4343
{
4444
'type': 'pmessage',
4545
'pattern': 'fo*',

tests/server_commands.py

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,17 @@
22
import unittest
33
import datetime
44
import time
5-
from string import letters
65
from distutils.version import StrictVersion
76
from redis.client import parse_info
7+
from redis.compat import (
8+
unichr,
9+
unicode,
10+
MAJOR_VERSION
11+
)
12+
if MAJOR_VERSION >= 3:
13+
from string import ascii_letters as letters
14+
else:
15+
from string import letters
816

917
class ServerCommandsTestCase(unittest.TestCase):
1018

@@ -41,15 +49,19 @@ def test_get_and_set(self):
4149
self.assertEquals(self.client.get('a'), None)
4250
byte_string = 'value'
4351
integer = 5
44-
unicode_string = unichr(3456) + u'abcd' + unichr(3421)
52+
unicode_string = unichr(3456) + unicode('abcd') + unichr(3421)
4553
self.assert_(self.client.set('byte_string', byte_string))
4654
self.assert_(self.client.set('integer', 5))
4755
self.assert_(self.client.set('unicode_string', unicode_string))
4856
self.assertEquals(self.client.get('byte_string'), byte_string)
4957
self.assertEquals(self.client.get('integer'), str(integer))
50-
self.assertEquals(
51-
self.client.get('unicode_string').decode('utf-8'),
52-
unicode_string)
58+
if MAJOR_VERSION >= 3:
59+
self.assertEquals(self.client.get("unicode_string"),
60+
unicode_string)
61+
else:
62+
self.assertEquals(
63+
self.client.get('unicode_string').decode('utf-8'),
64+
unicode_string)
5365

5466
def test_getitem_and_setitem(self):
5567
self.client['a'] = 'bar'
@@ -122,7 +134,7 @@ def test_append(self):
122134
# real logic
123135
self.assertEquals(self.client.append('a', 'a1'), 2)
124136
self.assertEquals(self.client['a'], 'a1')
125-
self.assert_(self.client.append('a', 'a2'), 4)
137+
self.assertEqual(self.client.append('a', 'a2'), 4)
126138
self.assertEquals(self.client['a'], 'a1a2')
127139

128140
def test_decr(self):
@@ -202,15 +214,15 @@ def test_mget(self):
202214
def test_mset(self):
203215
d = {'a': '1', 'b': '2', 'c': '3'}
204216
self.assert_(self.client.mset(d))
205-
for k, v in d.iteritems():
217+
for k,v in d.items():
206218
self.assertEquals(self.client[k], v)
207219

208220
def test_msetnx(self):
209221
d = {'a': '1', 'b': '2', 'c': '3'}
210222
self.assert_(self.client.msetnx(d))
211223
d2 = {'a': 'x', 'd': '4'}
212224
self.assert_(not self.client.msetnx(d2))
213-
for k, v in d.iteritems():
225+
for k,v in d.items():
214226
self.assertEquals(self.client[k], v)
215227
self.assertEquals(self.client.get('d'), None)
216228

@@ -957,7 +969,7 @@ def test_zunionstore(self):
957969

958970
# HASHES
959971
def make_hash(self, key, d):
960-
for k, v in d.iteritems():
972+
for k,v in d.items():
961973
self.client.hset(key, k, v)
962974

963975
def test_hget_and_hset(self):
@@ -1081,7 +1093,7 @@ def test_hkeys(self):
10811093
h = {'a1': '1', 'a2': '2', 'a3': '3'}
10821094
self.make_hash('a', h)
10831095
keys = h.keys()
1084-
keys.sort()
1096+
keys = sorted(keys)
10851097
remote_keys = self.client.hkeys('a')
10861098
remote_keys.sort()
10871099
self.assertEquals(keys, remote_keys)
@@ -1110,7 +1122,7 @@ def test_hvals(self):
11101122
h = {'a1': '1', 'a2': '2', 'a3': '3'}
11111123
self.make_hash('a', h)
11121124
vals = h.values()
1113-
vals.sort()
1125+
vals = sorted(vals)
11141126
remote_vals = self.client.hvals('a')
11151127
remote_vals.sort()
11161128
self.assertEquals(vals, remote_vals)
@@ -1253,7 +1265,7 @@ def test_binary_lists(self):
12531265
'foo\tbar\x07': '789',
12541266
}
12551267
# fill in lists
1256-
for key, value in mapping.iteritems():
1268+
for key, value in mapping.items():
12571269
for c in value:
12581270
self.assertTrue(self.client.rpush(key, c))
12591271

@@ -1301,7 +1313,7 @@ def test_large_responses(self):
13011313
"The PythonParser has some special cases for return values > 1MB"
13021314
# load up 5MB of data into a key
13031315
data = []
1304-
for i in range(5000000/len(letters)):
1316+
for i in range(5000000//len(letters)):
13051317
data.append(letters)
13061318
data = ''.join(data)
13071319
self.client.set('a', data)

0 commit comments

Comments
 (0)