Skip to content

Commit

Permalink
Merge pull request basho#379 from basho/bch/feature/python3
Browse files Browse the repository at this point in the history
Add Support for Python 3

Reviewed-by: seancribbs
  • Loading branch information
borshop committed Dec 9, 2014
2 parents 347d691 + 533aea5 commit a630f7f
Show file tree
Hide file tree
Showing 46 changed files with 1,453 additions and 743 deletions.
1 change: 1 addition & 0 deletions THANKS
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ The following people have contributed to the Riak Python client:
Andrew Thompson
Andy Gross
Armon Dadgar
Brett Hazen
Brett Hoerner
Brian Roach
Bryan Fink
Expand Down
10 changes: 4 additions & 6 deletions commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ def _create_and_activate_type(self, name, props):
except CalledProcessError as e:
status = e.output

exists = ('not an existing bucket type' not in status)
active = ('is active' in status)
exists = ('not an existing bucket type' not in status.decode('ascii'))
active = ('is active' in status.decode('ascii'))

if exists or active:
log.info("Updating {0} bucket-type with props {1}"
Expand All @@ -146,8 +146,6 @@ def _create_and_activate_type(self, name, props):
json.dumps({'props': props},
separators=(',', ':')))
else:
print name
print props
log.info("Creating {0} bucket-type with props {1}"
.format(repr(name), repr(props)))
self.check_btype_command("create", name,
Expand Down Expand Up @@ -395,7 +393,7 @@ def _update_riak_conf(self):
https_host = self.host + ':' + self.https_port
pb_host = self.host + ':' + self.pb_port
self._backup_file(self.riak_conf)
f = open(self.riak_conf, 'r', False)
f = open(self.riak_conf, 'r', buffering=1)
conf = f.read()
f.close()
conf = re.sub(r'search\s+=\s+off', r'search = on', conf)
Expand Down Expand Up @@ -423,7 +421,7 @@ def _update_riak_conf(self):
r'listener.protobuf.internal = ' + pb_host,
conf)
conf += 'check_crl = off\n'
f = open(self.riak_conf, 'w', False)
f = open(self.riak_conf, 'w', buffering=1)
f.write(conf)
f.close()

Expand Down
8 changes: 4 additions & 4 deletions docs/query.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ process in one payload, so you can also :meth:`stream the results

for keys in bucket.stream_index("bmonth_int", 1):
# keys is a list of matching keys
print keys
print(keys)

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

The results returned by :meth:`~riak.bucket.RiakBucket.search` is a dictionary
with lots of search metadata like the number of results, the maxium
Expand Down
10 changes: 5 additions & 5 deletions riak/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,11 @@ def __init__(self, message="Object in conflict"):
super(ConflictError, self).__init__(message)


from client import RiakClient
from bucket import RiakBucket, BucketType
from node import RiakNode
from riak_object import RiakObject
from mapreduce import RiakKeyFilter, RiakMapReduce, RiakLink
from riak.client import RiakClient
from riak.bucket import RiakBucket, BucketType
from riak.node import RiakNode
from riak.riak_object import RiakObject
from riak.mapreduce import RiakKeyFilter, RiakMapReduce, RiakLink

ONE = "one"
ALL = "all"
Expand Down
22 changes: 15 additions & 7 deletions riak/benchmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
under the License.
"""

from __future__ import print_function
import os
import gc

Expand Down Expand Up @@ -104,13 +105,17 @@ def next(self):
else:
if self.rehearse:
gc.collect()
print ("-" * 59)
print
print("-" * 59)
print()
print_header()

self.count -= 1
return self

def __next__(self):
# Python 3.x Version
return self.next()

def report(self, name):
"""
Returns a report for the current step of the benchmark.
Expand All @@ -124,22 +129,25 @@ def print_rehearsal_header():
Prints the header for the rehearsal phase of a benchmark.
"""
print
print "Rehearsal -------------------------------------------------"
print("Rehearsal -------------------------------------------------")


def print_report(label, user, system, real):
"""
Prints the report of one step of a benchmark.
"""
print "{:<12s} {:12f} {:12f} ( {:12f} )".format(label, user, system, real)
print("{:<12s} {:12f} {:12f} ( {:12f} )".format(label,
user,
system,
real))


def print_header():
"""
Prints the header for the normal phase of a benchmark.
"""
print "{:<12s} {:<12s} {:<12s} ( {:<12s} )"\
.format('', 'user', 'system', 'real')
print("{:<12s} {:<12s} {:<12s} ( {:<12s} )"
.format('', 'user', 'system', 'real'))


class BenchmarkReport(object):
Expand All @@ -164,5 +172,5 @@ def __exit__(self, exc_type, exc_val, exc_tb):
elif exc_type is KeyboardInterrupt:
return False
else:
print "EXCEPTION! %r" % ((exc_type, exc_val, exc_tb),)
print("EXCEPTION! %r" % ((exc_type, exc_val, exc_tb),))
return True
36 changes: 22 additions & 14 deletions riak/bucket.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
specific language governing permissions and limitations
under the License.
"""
from six import string_types, PY2
import mimetypes
from riak.util import lazy_property

Expand Down Expand Up @@ -50,13 +51,14 @@ def __init__(self, client, name, bucket_type):
:param bucket_type: The parent bucket type of this bucket
:type bucket_type: :class:`BucketType`
"""
try:
if isinstance(name, basestring):
name = name.encode('ascii')
else:
raise TypeError('Bucket name must be a string')
except UnicodeError:
raise TypeError('Unicode bucket names are not supported.')
if PY2:
try:
if isinstance(name, string_types):
name = name.encode('ascii')
else:
raise TypeError('Bucket name must be a string')
except UnicodeError:
raise TypeError('Unicode bucket names are not supported.')

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

try:
if isinstance(data, basestring):
data = data.encode('ascii')
except UnicodeError:
raise TypeError('Unicode data values are not supported.')
if PY2:
try:
if isinstance(data, string_types):
data = data.encode('ascii')
except UnicodeError:
raise TypeError('Unicode data values are not supported.')

obj = RiakObject(self._client, self, key)
obj.content_type = content_type
Expand Down Expand Up @@ -411,7 +414,12 @@ def new_from_file(self, key, filename):
binary_data = bytearray(binary_data)
if not mimetype:
mimetype = 'application/octet-stream'
return self.new(key, encoded_data=binary_data, content_type=mimetype)
if PY2:
return self.new(key, encoded_data=binary_data,
content_type=mimetype)
else:
return self.new(key, encoded_data=bytes(binary_data),
content_type=mimetype)

def search_enabled(self):
"""
Expand Down Expand Up @@ -730,5 +738,5 @@ def __ne__(self, other):
return True


from riak_object import RiakObject
from riak.riak_object import RiakObject
from riak.datatypes import TYPES
69 changes: 55 additions & 14 deletions riak/client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,46 @@
from riak.transports.http import RiakHttpPool
from riak.transports.pbc import RiakPbcPool
from riak.security import SecurityCreds
from riak.util import lazy_property
from riak.util import lazy_property, bytes_to_str, str_to_bytes
from six import string_types, PY2


def default_encoder(obj):
"""
Default encoder for JSON datatypes, which returns UTF-8 encoded
json instead of the default bloated \uXXXX escaped ASCII strings.
json instead of the default bloated backslash u XXXX escaped ASCII strings.
"""
return json.dumps(obj, ensure_ascii=False).encode("utf-8")
if isinstance(obj, bytes):
return json.dumps(bytes_to_str(obj),
ensure_ascii=False).encode("utf-8")
else:
return json.dumps(obj, ensure_ascii=False).encode("utf-8")


def binary_json_encoder(obj):
"""
Default encoder for JSON datatypes, which returns UTF-8 encoded
json instead of the default bloated backslash u XXXX escaped ASCII strings.
"""
if isinstance(obj, bytes):
return json.dumps(bytes_to_str(obj),
ensure_ascii=False).encode("utf-8")
else:
return json.dumps(obj, ensure_ascii=False).encode("utf-8")


def binary_json_decoder(obj):
"""
Default decoder from JSON datatypes.
"""
return json.loads(bytes_to_str(obj))


def binary_encoder_decoder(obj):
"""
Assumes value is already in binary format, so passes unchanged.
"""
return obj


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

self._encoders = {'application/json': default_encoder,
'text/json': default_encoder,
'text/plain': str}
self._decoders = {'application/json': json.loads,
'text/json': json.loads,
'text/plain': str}
if PY2:
self._encoders = {'application/json': default_encoder,
'text/json': default_encoder,
'text/plain': str}
self._decoders = {'application/json': json.loads,
'text/json': json.loads,
'text/plain': str}
else:
self._encoders = {'application/json': binary_json_encoder,
'text/json': binary_json_encoder,
'text/plain': str_to_bytes,
'binary/octet-stream': binary_encoder_decoder}
self._decoders = {'application/json': binary_json_decoder,
'text/json': binary_json_decoder,
'text/plain': bytes_to_str,
'binary/octet-stream': binary_encoder_decoder}
self._buckets = WeakValueDictionary()
self._bucket_types = WeakValueDictionary()

Expand Down Expand Up @@ -167,7 +208,7 @@ def set_encoder(self, content_type, encoder):
:param content_type: the requested media type
:type content_type: str
:param encoder: an encoding function, takes a single object
argument and returns a string
argument and returns encoded data
:type encoder: function
"""
self._encoders[content_type] = encoder
Expand All @@ -188,7 +229,7 @@ def set_decoder(self, content_type, decoder):
:param content_type: the requested media type
:type content_type: str
:param decoder: a decoding function, takes a string and
:param decoder: a decoding function, takes encoded data and
returns a Python type
:type decoder: function
"""
Expand Down Expand Up @@ -217,10 +258,10 @@ def bucket(self, name, bucket_type='default'):
:rtype: :class:`RiakBucket <riak.bucket.RiakBucket>`
"""
if not isinstance(name, basestring):
if not isinstance(name, string_types):
raise TypeError('Bucket name must be a string')

if isinstance(bucket_type, basestring):
if isinstance(bucket_type, string_types):
bucket_type = self.bucket_type(bucket_type)
elif not isinstance(bucket_type, BucketType):
raise TypeError('bucket_type must be a string '
Expand All @@ -243,7 +284,7 @@ def bucket_type(self, name):
:type name: str
:rtype: :class:`BucketType <riak.bucket.BucketType>`
"""
if not isinstance(name, basestring):
if not isinstance(name, string_types):
raise TypeError('Bucket name must be a string')

if name in self._bucket_types:
Expand Down
19 changes: 12 additions & 7 deletions riak/client/multiget.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,15 @@
under the License.
"""

from __future__ import print_function
from collections import namedtuple
from Queue import Queue
from threading import Thread, Lock, Event
from multiprocessing import cpu_count
from six import PY2
if PY2:
from Queue import Queue
else:
from queue import Queue

__all__ = ['multiget', 'MultiGetPool']

Expand Down Expand Up @@ -202,15 +207,15 @@ def multiget(client, keys, **options):
from riak import RiakClient
import riak.benchmark as benchmark
client = RiakClient(protocol='pbc')
bkeys = [('default', 'multiget', str(key)) for key in xrange(10000)]
bkeys = [('default', 'multiget', str(key)) for key in range(10000)]

data = open(__file__).read()

print "Benchmarking multiget:"
print " CPUs: {0}".format(cpu_count())
print " Threads: {0}".format(POOL_SIZE)
print " Keys: {0}".format(len(bkeys))
print
print("Benchmarking multiget:")
print(" CPUs: {0}".format(cpu_count()))
print(" Threads: {0}".format(POOL_SIZE))
print(" Keys: {0}".format(len(bkeys)))
print()

with benchmark.measure() as b:
with b.report('populate'):
Expand Down
Loading

0 comments on commit a630f7f

Please sign in to comment.