diff --git a/.gitignore b/.gitignore index f313b284..e2a2f0ab 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,4 @@ -riak/*.pyc -riak/tests/*.pyc -riak/transports/*.pyc +*.pyc docs/_build diff --git a/README.rst b/README.rst index e9a651ce..f0e5397b 100644 --- a/README.rst +++ b/README.rst @@ -6,12 +6,12 @@ Python Client for Riak Documentation ============== -`Documentation for the Riak Python Client Library `_ is available here. -The documentation source is found in `docs/ subdirectory -`_ and can be +`Documentation for the Riak Python Client Library `_ is available here. +The documentation source is found in `docs/ subdirectory +`_ and can be built with `Sphinx `_. -Documentation for Riak is available at http://wiki.basho.com/display/RIAK/Riak +Documentation for Riak is available at http://wiki.basho.com/How-Things-Work.html Install ======= @@ -35,7 +35,7 @@ This tutorial assumes basic working knowledge of how Riak works & what it can do. If you need a more comprehensive overview how to use Riak, please check out the `Riak Fast Track`_. -.. _`Riak Fast Track`: http://wiki.basho.com/display/RIAK/The+Riak+Fast+Track +.. _`Riak Fast Track`: http://wiki.basho.com/The-Riak-Fast-Track.html Quick Start @@ -45,14 +45,14 @@ For the impatient, simple usage of the official Python binding for Riak looks like:: import riak - + # Connect to Riak. client = riak.RiakClient() - + # Choose the bucket to store data in. bucket = client.bucket('test') - - + + # Supply a key to store data under. # The ``data`` can be any data Python's ``json`` encoder can handle. person = bucket.new('riak_developer_1', data={ @@ -85,7 +85,7 @@ To use the HTTP interface and connecting to a local Riak on the default port, no arguments are needed:: import riak - + client = riak.RiakClient() The constructor also configuration options such as ``host``, ``port`` & @@ -94,7 +94,7 @@ The constructor also configuration options such as ``host``, ``port`` & To use the Protocol Buffers interface:: import riak - + client = riak.RiakClient(port=8087, transport_class=riak.RiakPbcTransport) .. warning: @@ -231,12 +231,12 @@ in either the JSON-decoded form or a binary blob. Getting the JSON-decoded data out looks like:: import riak - + client = riak.RiakClient() user_bucket = client.bucket('user') - + johndoe = user_bucket.get('johndoe') - + # You've now got a ``RiakObject``. To get at the values in a dictionary # form, call: johndoe_dict = johndoe.get_data() @@ -244,31 +244,31 @@ data out looks like:: Getting binary data out looks like:: import riak - + client = riak.RiakClient() user_photo_bucket = client.bucket('user_photo') - + johndoe = user_photo_bucket.get_binary('johndoe') - + # You've now got a ``RiakObject``. To get at the binary data, call: johndoe_headshot = johndoe.get_data() Manually fetching data is also possible:: import riak - + client = riak.RiakClient() status_bucket = client.bucket('status') - + # We're using the UUID generated from the above section. first_post_status = riak.RiakObject(client, status_bucket, post_uuid) first_post_status._encode_data = True r = status_bucket.get_r() - + # Calling ``reload`` will cause the ``RiakObject`` instance to load fresh # data/metadata from Riak. first_post_status.reload(r) - + # Finally, pull out the data. message = first_post_status.get_data()['message'] @@ -281,23 +281,23 @@ disposal is MapReduce_. This technique iterates over all of the data, returning data from the map phase & combining all the different maps in the reduce phase(s). -.. _MapReduce: http://wiki.basho.com/display/RIAK/MapReduce +.. _MapReduce: http://wiki.basho.com/MapReduce.html To perform a map operation, such as returning all active users, you can do something like:: import riak - + client = riak.RiakClient() # First, you need to ``add`` the bucket you want to MapReduce on. query = client.add('user') # Then, you supply a Javascript map function as the code to be executed. query.map("function(v) { var data = JSON.parse(v.values[0].data); if(data.is_active == true) { return [[v.key, data]]; } return []; }") - + for result in query.run(): # Print the key (``v.key``) and the value for that key (``data``). print "%s - %s" % (result[0], result[1]) - + # Results in something like: # # mr_smith - {'first_name': 'Mister', 'last_name': 'Smith', 'is_active': True} @@ -307,27 +307,27 @@ something like:: You can also do this manually:: import riak - + client = riak.RiakClient() query = riak.RiakMapReduce(client).add('user') query.map("function(v) { var data = JSON.parse(v.values[0].data); if(data.is_active == true) { return [[v.key, data]]; } return []; }") - + for result in query.run(): print "%s - %s" % (result[0], result[1]) Adding a reduce phase, say to sort by username (key), looks almost identical:: import riak - + client = riak.RiakClient() query = client.add('user') query.map("function(v) { var data = JSON.parse(v.values[0].data); if(data.is_active == true) { return [[v.key, data]]; } return []; }") query.reduce("function(values) { return values.sort(); }") - + for result in query.run(): # Print the key (``v.key``) and the value for that key (``data``). print "%s - %s" % (result[0], result[1]) - + # Results in something like: # # annabody - {'first_name': 'Anna', 'last_name': 'Body', 'is_active': True} @@ -341,20 +341,20 @@ Working With Related Data Via Links Links_ are powerful concept in Riak that allow, within the key/value pair's metadata, relations between objects. -.. _Links: http://wiki.basho.com/display/RIAK/Links +.. _Links: http://wiki.basho.com/Links.html Adding them to your data is relatively trivial. For instance, we'll link a user's statuses to their user data:: import riak import uuid - + client = riak.RiakClient() user_bucket = client.bucket('user') status_bucket = client.bucket('status') - + johndoe = user_bucket.get('johndoe') - + new_status = status_bucket.new(uuid.uuid1().hex, data={ 'message': 'First post!', 'created': time.time(), @@ -363,7 +363,7 @@ user's statuses to their user data:: # Add one direction (from status to user)... new_status.add_link(johndoe) new_status.store() - + # ... Then add the other direction. johndoe.add_link(new_status) johndoe.store() @@ -371,12 +371,12 @@ user's statuses to their user data:: Fetching the data is equally simple:: import riak - + client = riak.RiakClient() user_bucket = client.bucket('user') - + johndoe = user_bucket.get('johndoe') - + for status_link in johndoe.get_links(): # Since what we get back are lightweight ``RiakLink`` objects, we need to # get the associated ``RiakObject`` to access its data. @@ -394,23 +394,23 @@ a Solr-like interface into Riak. The setup of this is outside the realm of this tutorial, but usage of this feature looks like:: import riak - + client = riak.RiakClient() - + # First parameter is the bucket we want to search within, the second # is the query we want to perform. search_query = client.search('user', 'first_name:[Anna TO John]') - + for result in search_query.run(): # You get ``RiakLink`` objects back. user = result.get() user_data = user.get_data() print "%s %s" % (user_data['first_name'], user_data['last_name']) - + # Results in something like: # # John Doe # Anna Body -.. _`Riak Search`: http://wiki.basho.com/display/RIAK/Riak+Search +.. _`Riak Search`: http://wiki.basho.com/Riak-Search.html .. _Lucene: http://lucene.apache.org/ diff --git a/docs/index.rst b/docs/index.rst index ad67744e..40449224 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -21,9 +21,9 @@ Contents: .. toctree:: :maxdepth: 2 - + tutorial - + client bucket riak_object diff --git a/docs/tutorial.rst b/docs/tutorial.rst index 51906ced..825e9ac3 100644 --- a/docs/tutorial.rst +++ b/docs/tutorial.rst @@ -8,7 +8,7 @@ This tutorial assumes basic working knowledge of how Riak works & what it can do. If you need a more comprehensive overview how to use Riak, please check out the `Riak Fast Track`_. -.. _`Riak Fast Track`: http://wiki.basho.com/display/RIAK/The+Riak+Fast+Track +.. _`Riak Fast Track`: http://wiki.basho.com/The-Riak-Fast-Track.html Quick Start @@ -18,14 +18,14 @@ For the impatient, simple usage of the official Python binding for Riak looks like:: import riak - + # Connect to Riak. client = riak.RiakClient() - + # Choose the bucket to store data in. bucket = client.bucket('test') - - + + # Supply a key to store data under. # The ``data`` can be any data Python's ``json`` encoder can handle. person = bucket.new('riak_developer_1', data={ @@ -58,7 +58,7 @@ To use the HTTP interface and connecting to a local Riak on the default port, no arguments are needed:: import riak - + client = riak.RiakClient() The constructor also configuration options such as ``host``, ``port`` & @@ -67,7 +67,7 @@ The constructor also configuration options such as ``host``, ``port`` & To use the Protocol Buffers interface:: import riak - + client = riak.RiakClient(port=8087, transport_class=riak.RiakPbcTransport) .. warning: @@ -204,12 +204,12 @@ in either the JSON-decoded form or a binary blob. Getting the JSON-decoded data out looks like:: import riak - + client = riak.RiakClient() user_bucket = client.bucket('user') - + johndoe = user_bucket.get('johndoe') - + # You've now got a ``RiakObject``. To get at the values in a dictionary # form, call: johndoe_dict = johndoe.get_data() @@ -217,31 +217,31 @@ data out looks like:: Getting binary data out looks like:: import riak - + client = riak.RiakClient() user_photo_bucket = client.bucket('user_photo') - + johndoe = user_photo_bucket.get_binary('johndoe') - + # You've now got a ``RiakObject``. To get at the binary data, call: johndoe_headshot = johndoe.get_data() Manually fetching data is also possible:: import riak - + client = riak.RiakClient() status_bucket = client.bucket('status') - + # We're using the UUID generated from the above section. first_post_status = riak.RiakObject(client, status_bucket, post_uuid) first_post_status._encode_data = True r = status_bucket.get_r() - + # Calling ``reload`` will cause the ``RiakObject`` instance to load fresh # data/metadata from Riak. first_post_status.reload(r) - + # Finally, pull out the data. message = first_post_status.get_data()['message'] @@ -254,23 +254,23 @@ disposal is MapReduce_. This technique iterates over all of the data, returning data from the map phase & combining all the different maps in the reduce phase(s). -.. _MapReduce: http://wiki.basho.com/display/RIAK/MapReduce +.. _MapReduce: http://wiki.basho.com/MapReduce.html To perform a map operation, such as returning all active users, you can do something like:: import riak - + client = riak.RiakClient() # First, you need to ``add`` the bucket you want to MapReduce on. query = client.add('user') # Then, you supply a Javascript map function as the code to be executed. query.map("function(v) { var data = JSON.parse(v.values[0].data); if(data.is_active == true) { return [[v.key, data]]; } return []; }") - + for result in query.run(): # Print the key (``v.key``) and the value for that key (``data``). print "%s - %s" % (result[0], result[1]) - + # Results in something like: # # mr_smith - {'first_name': 'Mister', 'last_name': 'Smith', 'is_active': True} @@ -280,27 +280,27 @@ something like:: You can also do this manually:: import riak - + client = riak.RiakClient() query = riak.RiakMapReduce(client).add('user') query.map("function(v) { var data = JSON.parse(v.values[0].data); if(data.is_active == true) { return [[v.key, data]]; } return []; }") - + for result in query.run(): print "%s - %s" % (result[0], result[1]) Adding a reduce phase, say to sort by username (key), looks almost identical:: import riak - + client = riak.RiakClient() query = client.add('user') query.map("function(v) { var data = JSON.parse(v.values[0].data); if(data.is_active == true) { return [[v.key, data]]; } return []; }") query.reduce("function(values) { return values.sort(); }") - + for result in query.run(): # Print the key (``v.key``) and the value for that key (``data``). print "%s - %s" % (result[0], result[1]) - + # Results in something like: # # annabody - {'first_name': 'Anna', 'last_name': 'Body', 'is_active': True} @@ -314,20 +314,20 @@ Working With Related Data Via Links Links_ are powerful concept in Riak that allow, within the key/value pair's metadata, relations between objects. -.. _Links: http://wiki.basho.com/display/RIAK/Links +.. _Links: http://wiki.basho.com/Links.html Adding them to your data is relatively trivial. For instance, we'll link a user's statuses to their user data:: import riak import uuid - + client = riak.RiakClient() user_bucket = client.bucket('user') status_bucket = client.bucket('status') - + johndoe = user_bucket.get('johndoe') - + new_status = status_bucket.new(uuid.uuid1().hex, data={ 'message': 'First post!', 'created': time.time(), @@ -336,7 +336,7 @@ user's statuses to their user data:: # Add one direction (from status to user)... new_status.add_link(johndoe) new_status.store() - + # ... Then add the other direction. johndoe.add_link(new_status) johndoe.store() @@ -344,12 +344,12 @@ user's statuses to their user data:: Fetching the data is equally simple:: import riak - + client = riak.RiakClient() user_bucket = client.bucket('user') - + johndoe = user_bucket.get('johndoe') - + for status_link in johndoe.get_links(): # Since what we get back are lightweight ``RiakLink`` objects, we need to # get the associated ``RiakObject`` to access its data. @@ -367,23 +367,23 @@ a Solr-like interface into Riak. The setup of this is outside the realm of this tutorial, but usage of this feature looks like:: import riak - + client = riak.RiakClient() - + # First parameter is the bucket we want to search within, the second # is the query we want to perform. search_query = client.search('user', 'first_name:[Anna TO John]') - + for result in search_query.run(): # You get ``RiakLink`` objects back. user = result.get() user_data = user.get_data() print "%s %s" % (user_data['first_name'], user_data['last_name']) - + # Results in something like: # # John Doe # Anna Body -.. _`Riak Search`: http://wiki.basho.com/display/RIAK/Riak+Search +.. _`Riak Search`: http://wiki.basho.com/Riak-Search.html .. _Lucene: http://lucene.apache.org/ diff --git a/riak/__init__.py b/riak/__init__.py index 0b968ab0..841e4e27 100644 --- a/riak/__init__.py +++ b/riak/__init__.py @@ -37,7 +37,7 @@ def __str__(self): return repr(self.value) from riak_object import RiakObject -from bucket import RiakBucket +from bucket import RiakBucket from client import RiakClient from mapreduce import RiakMapReduce, RiakMapReducePhase, RiakLinkPhase from transports.pbc import RiakPbcTransport diff --git a/riak/mapreduce.py b/riak/mapreduce.py index 44e6fb14..ae1829c1 100644 --- a/riak/mapreduce.py +++ b/riak/mapreduce.py @@ -47,7 +47,7 @@ def add(self, arg1, arg2=None, arg3=None): @param mixed arg3 - Arg or blank @return RiakMapReduce """ - if (arg2 == None) and (arg3 == None): + if (arg2 is None) and (arg3 is None): if isinstance(arg1, RiakObject): return self.add_object(arg1) else: @@ -74,17 +74,17 @@ def add_bucket(self, bucket) : def search(self, bucket, query): """ - Begin a map/reduce operation using a Search. This command will + Begin a map/reduce operation using a Search. This command will return an error unless executed against a Riak Search cluster. @param bucket - The bucket over which to perform the search. @param query - The search query. """ self._input_mode = 'search' - self._inputs = {'module':'riak_search', + self._inputs = {'module':'riak_search', 'function':'mapred_search', 'arg':[bucket, query]} return self - + def link(self, bucket='_', tag='_', keep=False): """ @@ -349,7 +349,7 @@ def get_tag(self): Get the tag of this link. @return string """ - if (self._tag == None): + if (self._tag is None): return self._bucket else: return self._tag diff --git a/riak/riak_object.py b/riak/riak_object.py index a04e81fe..4be1228e 100644 --- a/riak/riak_object.py +++ b/riak/riak_object.py @@ -108,7 +108,7 @@ def get_encoded_data(self): if self._encode_data == True: content_type = self.get_content_type() encoder = self._bucket.get_encoder(content_type) - if encoder == None: + if encoder is None: if isinstance(self._data, basestring): return self._data.encode() else: @@ -128,7 +128,7 @@ def set_encoded_data(self, data): if self._encode_data == True: content_type = self.get_content_type() decoder = self._bucket.get_decoder(content_type) - if decoder == None: + if decoder is None: # if no decoder, just set as string data for application to handle self._data = data else: @@ -352,7 +352,7 @@ def populate(self, Result) : sibling that need to be retrieved with get. """ self.clear() - if Result == None: + if Result is None: return self elif type(Result) == types.ListType: self.set_siblings(Result) diff --git a/riak/tests/test_all.py b/riak/tests/test_all.py index 6bd18719..06f05272 100644 --- a/riak/tests/test_all.py +++ b/riak/tests/test_all.py @@ -362,7 +362,7 @@ def test_link_walking(self): def test_store_of_missing_object(self): bucket = self.client.bucket("bucket") - # for json objects + # for json objects o = bucket.get("nonexistent_key_json") self.assertEqual(o.exists(), False) o.set_data({"foo" : "bar"}) @@ -426,7 +426,7 @@ def test_store_binary_object_from_file_should_fail_if_file_not_found(self): obj = bucket.get_binary('not_found_from_file') self.assertEqual(obj.get_data(), None) - + class RiakPbcTransportTestCase(BaseTestCase, unittest.TestCase): def setUp(self): @@ -457,7 +457,7 @@ def test_no_returnbody(self): bucket = self.client.bucket("bucket") o = bucket.new("foo", "bar").store(return_body=False) self.assertEqual(o.vclock(), None) - + if __name__ == '__main__': unittest.main() diff --git a/riak/transports/http.py b/riak/transports/http.py index 0af3b277..d9d0bd3c 100644 --- a/riak/transports/http.py +++ b/riak/transports/http.py @@ -63,7 +63,7 @@ def __init__(self, host='127.0.0.1', port=8098, prefix='riak', self._client_id = self.make_random_client_id() def __copy__(self): - return RiakHttpTransport(self._host, self._port, self._prefix, + return RiakHttpTransport(self._host, self._port, self._prefix, self._mapred_prefix) """ @@ -145,7 +145,7 @@ def get_keys(self, bucket): return props['keys'] else: raise Exception('Error getting bucket properties.') - + def get_bucket_props(self, bucket, keys=False): # Run the request... params = {'props' : 'True', 'keys' : 'False'} @@ -173,7 +173,7 @@ def set_bucket_props(self, bucket, props): response = self.http_request('PUT', host, port, url, headers, content) # Handle the response... - if (response == None): + if (response is None): raise Exception('Error setting bucket properties.') # Check the response value... @@ -213,7 +213,7 @@ def parse_body(self, response, expected_statuses): @return self """ # If no response given, then return. - if (response == None): + if (response is None): return self # Make sure expected code came back @@ -433,7 +433,7 @@ def parse_http_headers(self, headers) : fields = headers.split("\n") for field in fields: matches = re.match("([^:]+):(.+)", field) - if (matches == None): continue + if (matches is None): continue key = matches.group(1).lower() value = matches.group(2).strip() if (key in retVal.keys()): diff --git a/riak/transports/pbc.py b/riak/transports/pbc.py index 98f18bd1..99429a40 100644 --- a/riak/transports/pbc.py +++ b/riak/transports/pbc.py @@ -74,7 +74,7 @@ class RiakPbcTransport(RiakTransport): 'default' : RIAKC_RW_DEFAULT, 'all' : RIAKC_RW_ALL, 'quorum' : RIAKC_RW_QUORUM, - 'one' : RIAKC_RW_ONE + 'one' : RIAKC_RW_ONE } def __init__(self, host='127.0.0.1', port=8087, client_id=None): """ @@ -128,7 +128,7 @@ def set_client_id(self, client_id): """ req = riakclient_pb2.RpbSetClientIdReq() req.client_id = client_id - + self.maybe_connect() self.send_msg(MSG_CODE_SET_CLIENT_ID_REQ, req) msg_code, resp = self.recv_msg() @@ -170,7 +170,7 @@ def put(self, robj, w = None, dw = None, return_body = True): Serialize get request and deserialize response """ bucket = robj.get_bucket() - + req = riakclient_pb2.RpbPutReq() req.w = self.translate_rw_val(w) req.dw = self.translate_rw_val(dw) @@ -214,7 +214,7 @@ def delete(self, robj, rw = None): if msg_code != MSG_CODE_DEL_RESP: raise RiakError("unexpected protocol buffer message code: ", msg_code) return self - + def get_keys(self, bucket): """ Lists all keys within a bucket. diff --git a/riak/transports/riakclient.proto b/riak/transports/riakclient.proto index e8150d6d..6acd0842 100644 --- a/riak/transports/riakclient.proto +++ b/riak/transports/riakclient.proto @@ -26,7 +26,7 @@ ** Lowest Common Denominator Protocol Buffers Client ** - no ENUM (protobuffs_erlang does not support) ** -** Protocol +** Protocol ** ** The protocol encodes requests and responses as protocol buffer messages. ** Each request message results in one or more response messages. @@ -49,7 +49,7 @@ ** ** The client should be prepared to handle messages without any pbmsg ** (i.e. length==1) for requests like ping or a put without return_body set. -** +** ** RpbGetClientIdReq -> RpbGetClientIdResp ** RpbSetClientIdReq -> RpbSetClientIdResp ** RpbGetServerInfoReq -> RpbGetServerInfoResp @@ -72,11 +72,11 @@ ** 6 - RpbSetClientIdResp ** 7 - RpbGetServerInfoReq ** 8 - RpbGetServerInfoResp -** 9 - RpbGetReq +** 9 - RpbGetReq ** 10 - RpbGetResp -** 11 - RpbPutReq +** 11 - RpbPutReq ** 12 - RpbPutResp - 0 length -** 13 - RpbDelReq +** 13 - RpbDelReq ** 14 - RpbDelResp ** 15 - RpbListBucketsReq ** 16 - RpbListBucketsResp @@ -184,7 +184,7 @@ message RpbGetBucketReq { // Get bucket properties response message RpbGetBucketResp { - required RpbBucketProps props = 1; + required RpbBucketProps props = 1; } // Set bucket properties request @@ -217,8 +217,8 @@ message RpbMapRedResp { message RpbContent { required bytes value = 1; optional bytes content_type = 2; // the media type/format - optional bytes charset = 3; - optional bytes content_encoding = 4; + optional bytes charset = 3; + optional bytes content_encoding = 4; optional bytes vtag = 5; repeated RpbLink links = 6; // links to other resources optional uint32 last_mod = 7; diff --git a/riak/transports/transport.py b/riak/transports/transport.py index 056326a4..889022f3 100644 --- a/riak/transports/transport.py +++ b/riak/transports/transport.py @@ -17,7 +17,7 @@ specific language governing permissions and limitations under the License. """ -from riak import RiakError +from riak import RiakError import base64 import random import threading