Skip to content

Commit ba46b57

Browse files
author
Brett Hazen
committed
Add support for Python 3.x (especially 3.4.2+)
1 parent d0fbfc0 commit ba46b57

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1362
-756
lines changed

THANKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ The following people have contributed to the Riak Python client:
33
Andrew Thompson
44
Andy Gross
55
Armon Dadgar
6+
Brett Hazen
67
Brett Hoerner
78
Brian Roach
89
Bryan Fink

docs/query.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ process in one payload, so you can also :meth:`stream the results
4343

4444
for keys in bucket.stream_index("bmonth_int", 1):
4545
# keys is a list of matching keys
46-
print keys
46+
print(keys)
4747

4848
Both the regular :meth:`~riak.bucket.RiakBucket.get_index` method and
4949
the :meth:`~riak.bucket.RiakBucket.stream_index` method allow you to
@@ -369,15 +369,15 @@ Here is a brief example of loading and querying data:::
369369
"scoville_high_i": 350000}).store()
370370
results = bucket.search("name_s:/c.*/", index='jalapeno')
371371
# Yields single document 'chipotle'
372-
print results['docs'][0]['name_s']
372+
print(results['docs'][0]['name_s'])
373373
results = bucket.search("scoville_high_i:[20000 TO 500000]")
374374
# Yields two documents
375375
for result in results['docs']:
376-
print result['name_s']
376+
print(result['name_s'])
377377
results = bucket.search('name_s:*', index='jalapeno',
378378
sort="scoville_low_i desc")
379379
# Yields all documents, sorted in descending order. We take the top one
380-
print "The hottest pepper is {0}".format(results['docs'][0]['name_s'])
380+
print("The hottest pepper is {0}".format(results['docs'][0]['name_s']))
381381

382382
The results returned by :meth:`~riak.bucket.RiakBucket.search` is a dictionary
383383
with lots of search metadata like the number of results, the maxium

riak/__init__.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,11 @@ def __init__(self, message="Object in conflict"):
5656
super(ConflictError, self).__init__(message)
5757

5858

59-
from client import RiakClient
60-
from bucket import RiakBucket, BucketType
61-
from node import RiakNode
62-
from riak_object import RiakObject
63-
from mapreduce import RiakKeyFilter, RiakMapReduce, RiakLink
59+
from riak.client import RiakClient
60+
from riak.bucket import RiakBucket, BucketType
61+
from riak.node import RiakNode
62+
from riak.riak_object import RiakObject
63+
from riak.mapreduce import RiakKeyFilter, RiakMapReduce, RiakLink
6464

6565
ONE = "one"
6666
ALL = "all"

riak/benchmark.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,17 @@ def next(self):
104104
else:
105105
if self.rehearse:
106106
gc.collect()
107-
print ("-" * 59)
108-
print
107+
print("-" * 59)
108+
print()
109109
print_header()
110110

111111
self.count -= 1
112112
return self
113113

114+
def __next__(self):
115+
# Python 3.x Version
116+
self.next()
117+
114118
def report(self, name):
115119
"""
116120
Returns a report for the current step of the benchmark.
@@ -124,22 +128,25 @@ def print_rehearsal_header():
124128
Prints the header for the rehearsal phase of a benchmark.
125129
"""
126130
print
127-
print "Rehearsal -------------------------------------------------"
131+
print("Rehearsal -------------------------------------------------")
128132

129133

130134
def print_report(label, user, system, real):
131135
"""
132136
Prints the report of one step of a benchmark.
133137
"""
134-
print "{:<12s} {:12f} {:12f} ( {:12f} )".format(label, user, system, real)
138+
print("{:<12s} {:12f} {:12f} ( {:12f} )".format(label,
139+
user,
140+
system,
141+
real))
135142

136143

137144
def print_header():
138145
"""
139146
Prints the header for the normal phase of a benchmark.
140147
"""
141-
print "{:<12s} {:<12s} {:<12s} ( {:<12s} )"\
142-
.format('', 'user', 'system', 'real')
148+
print("{:<12s} {:<12s} {:<12s} ( {:<12s} )"
149+
.format('', 'user', 'system', 'real'))
143150

144151

145152
class BenchmarkReport(object):
@@ -164,5 +171,5 @@ def __exit__(self, exc_type, exc_val, exc_tb):
164171
elif exc_type is KeyboardInterrupt:
165172
return False
166173
else:
167-
print "EXCEPTION! %r" % ((exc_type, exc_val, exc_tb),)
174+
print("EXCEPTION! %r" % ((exc_type, exc_val, exc_tb),))
168175
return True

riak/bucket.py

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
specific language governing permissions and limitations
1818
under the License.
1919
"""
20+
from six import string_types, PY2
2021
import mimetypes
2122
from riak.util import lazy_property
2223

@@ -50,13 +51,14 @@ def __init__(self, client, name, bucket_type):
5051
:param bucket_type: The parent bucket type of this bucket
5152
:type bucket_type: :class:`BucketType`
5253
"""
53-
try:
54-
if isinstance(name, basestring):
55-
name = name.encode('ascii')
56-
else:
57-
raise TypeError('Bucket name must be a string')
58-
except UnicodeError:
59-
raise TypeError('Unicode bucket names are not supported.')
54+
if PY2:
55+
try:
56+
if isinstance(name, string_types):
57+
name = name.encode('ascii')
58+
else:
59+
raise TypeError('Bucket name must be a string')
60+
except UnicodeError:
61+
raise TypeError('Unicode bucket names are not supported.')
6062

6163
if not isinstance(bucket_type, BucketType):
6264
raise TypeError('Parent bucket type must be a BucketType instance')
@@ -173,11 +175,12 @@ def new(self, key=None, data=None, content_type='application/json',
173175
if self.bucket_type.datatype:
174176
return TYPES[self.bucket_type.datatype](bucket=self, key=key)
175177

176-
try:
177-
if isinstance(data, basestring):
178-
data = data.encode('ascii')
179-
except UnicodeError:
180-
raise TypeError('Unicode data values are not supported.')
178+
if PY2:
179+
try:
180+
if isinstance(data, string_types):
181+
data = data.encode('ascii')
182+
except UnicodeError:
183+
raise TypeError('Unicode data values are not supported.')
181184

182185
obj = RiakObject(self._client, self, key)
183186
obj.content_type = content_type
@@ -411,7 +414,12 @@ def new_from_file(self, key, filename):
411414
binary_data = bytearray(binary_data)
412415
if not mimetype:
413416
mimetype = 'application/octet-stream'
414-
return self.new(key, encoded_data=binary_data, content_type=mimetype)
417+
if PY2:
418+
return self.new(key, encoded_data=binary_data,
419+
content_type=mimetype)
420+
else:
421+
return self.new(key, encoded_data=bytes(binary_data),
422+
content_type=mimetype)
415423

416424
def search_enabled(self):
417425
"""
@@ -730,5 +738,5 @@ def __ne__(self, other):
730738
return True
731739

732740

733-
from riak_object import RiakObject
741+
from riak.riak_object import RiakObject
734742
from riak.datatypes import TYPES

riak/client/__init__.py

Lines changed: 55 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,46 @@
3434
from riak.transports.http import RiakHttpPool
3535
from riak.transports.pbc import RiakPbcPool
3636
from riak.security import SecurityCreds
37-
from riak.util import lazy_property
37+
from riak.util import lazy_property, bytes_to_str, str_to_bytes
38+
from six import string_types, PY2
3839

3940

4041
def default_encoder(obj):
4142
"""
4243
Default encoder for JSON datatypes, which returns UTF-8 encoded
43-
json instead of the default bloated \uXXXX escaped ASCII strings.
44+
json instead of the default bloated backslash u XXXX escaped ASCII strings.
4445
"""
45-
return json.dumps(obj, ensure_ascii=False).encode("utf-8")
46+
if type(obj) == bytes:
47+
return json.dumps(bytes_to_str(obj),
48+
ensure_ascii=False).encode("utf-8")
49+
else:
50+
return json.dumps(obj, ensure_ascii=False).encode("utf-8")
51+
52+
53+
def binary_json_encoder(obj):
54+
"""
55+
Default encoder for JSON datatypes, which returns UTF-8 encoded
56+
json instead of the default bloated backslash u XXXX escaped ASCII strings.
57+
"""
58+
if type(obj) == bytes:
59+
return json.dumps(bytes_to_str(obj),
60+
ensure_ascii=False).encode("utf-8")
61+
else:
62+
return json.dumps(obj, ensure_ascii=False).encode("utf-8")
63+
64+
65+
def binary_json_decoder(obj):
66+
"""
67+
Default decoder from JSON datatypes.
68+
"""
69+
return json.loads(bytes_to_str(obj))
70+
71+
72+
def binary_encoder_decoder(obj):
73+
"""
74+
Assumes value is already in binary format, so passes unchanged.
75+
"""
76+
return obj
4677

4778

4879
class RiakClient(RiakMapReduceChain, RiakClientOperations):
@@ -90,12 +121,22 @@ def __init__(self, protocol='pbc', transport_options={}, nodes=None,
90121
self._http_pool = RiakHttpPool(self, **transport_options)
91122
self._pb_pool = RiakPbcPool(self, **transport_options)
92123

93-
self._encoders = {'application/json': default_encoder,
94-
'text/json': default_encoder,
95-
'text/plain': str}
96-
self._decoders = {'application/json': json.loads,
97-
'text/json': json.loads,
98-
'text/plain': str}
124+
if PY2:
125+
self._encoders = {'application/json': default_encoder,
126+
'text/json': default_encoder,
127+
'text/plain': str}
128+
self._decoders = {'application/json': json.loads,
129+
'text/json': json.loads,
130+
'text/plain': str}
131+
else:
132+
self._encoders = {'application/json': binary_json_encoder,
133+
'text/json': binary_json_encoder,
134+
'text/plain': str_to_bytes,
135+
'binary/octet-stream': binary_encoder_decoder}
136+
self._decoders = {'application/json': binary_json_decoder,
137+
'text/json': binary_json_decoder,
138+
'text/plain': bytes_to_str,
139+
'binary/octet-stream': binary_encoder_decoder}
99140
self._buckets = WeakValueDictionary()
100141
self._bucket_types = WeakValueDictionary()
101142

@@ -167,7 +208,7 @@ def set_encoder(self, content_type, encoder):
167208
:param content_type: the requested media type
168209
:type content_type: str
169210
:param encoder: an encoding function, takes a single object
170-
argument and returns a string
211+
argument and returns encoded data
171212
:type encoder: function
172213
"""
173214
self._encoders[content_type] = encoder
@@ -188,7 +229,7 @@ def set_decoder(self, content_type, decoder):
188229
189230
:param content_type: the requested media type
190231
:type content_type: str
191-
:param decoder: a decoding function, takes a string and
232+
:param decoder: a decoding function, takes encoded data and
192233
returns a Python type
193234
:type decoder: function
194235
"""
@@ -217,10 +258,10 @@ def bucket(self, name, bucket_type='default'):
217258
:rtype: :class:`RiakBucket <riak.bucket.RiakBucket>`
218259
219260
"""
220-
if not isinstance(name, basestring):
261+
if not isinstance(name, string_types):
221262
raise TypeError('Bucket name must be a string')
222263

223-
if isinstance(bucket_type, basestring):
264+
if isinstance(bucket_type, string_types):
224265
bucket_type = self.bucket_type(bucket_type)
225266
elif not isinstance(bucket_type, BucketType):
226267
raise TypeError('bucket_type must be a string '
@@ -243,7 +284,7 @@ def bucket_type(self, name):
243284
:type name: str
244285
:rtype: :class:`BucketType <riak.bucket.BucketType>`
245286
"""
246-
if not isinstance(name, basestring):
287+
if not isinstance(name, string_types):
247288
raise TypeError('Bucket name must be a string')
248289

249290
if name in self._bucket_types:

riak/client/multiget.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,13 @@
1717
"""
1818

1919
from collections import namedtuple
20-
from Queue import Queue
2120
from threading import Thread, Lock, Event
2221
from multiprocessing import cpu_count
22+
from six import PY2
23+
if PY2:
24+
from Queue import Queue
25+
else:
26+
from queue import Queue
2327

2428
__all__ = ['multiget', 'MultiGetPool']
2529

@@ -202,15 +206,15 @@ def multiget(client, keys, **options):
202206
from riak import RiakClient
203207
import riak.benchmark as benchmark
204208
client = RiakClient(protocol='pbc')
205-
bkeys = [('default', 'multiget', str(key)) for key in xrange(10000)]
209+
bkeys = [('default', 'multiget', str(key)) for key in range(10000)]
206210

207211
data = open(__file__).read()
208212

209-
print "Benchmarking multiget:"
210-
print " CPUs: {0}".format(cpu_count())
211-
print " Threads: {0}".format(POOL_SIZE)
212-
print " Keys: {0}".format(len(bkeys))
213-
print
213+
print("Benchmarking multiget:")
214+
print(" CPUs: {0}".format(cpu_count()))
215+
print(" Threads: {0}".format(POOL_SIZE))
216+
print(" Keys: {0}".format(len(bkeys)))
217+
print()
214218

215219
with benchmark.measure() as b:
216220
with b.report('populate'):

0 commit comments

Comments
 (0)