Skip to content

Commit

Permalink
Merge pull request #509 from basho/features/lrb/head-support
Browse files Browse the repository at this point in the history
Add head parameter
  • Loading branch information
lukebakken authored Dec 12, 2016
2 parents d74824d + a663b92 commit 4122875
Show file tree
Hide file tree
Showing 11 changed files with 52 additions and 14 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ Contributors
* Soren Hansen
* Sreejith Kesavan
* Timothée Peignier
* [`tobixx`](https://github.com/tobixx)
* [Tin Tvrtković](https://github.com/Tinche)
* [Vitaly Shestovskiy](https://github.com/lamp0chka)
* William Kral
Expand Down
4 changes: 4 additions & 0 deletions RELNOTES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Riak Python Client Release Notes

## [`2.7.0` Release](https://github.com/basho/riak-python-client/issues?q=milestone%3Ariak-python-client-2.7.0)
* Riak TS 1.5 support
* Support for `head` parameter

## [`2.6.1` Release](https://github.com/basho/riak-python-client/issues?q=milestone%3Ariak-python-client-2.6.0)
* NOTE: Due to pypi upload errors, `2.6.1` takes the place of `2.6.0`.

Expand Down
17 changes: 13 additions & 4 deletions riak/bucket.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ def new(self, key=None, data=None, content_type='application/json',
return obj

def get(self, key, r=None, pr=None, timeout=None, include_context=None,
basic_quorum=None, notfound_ok=None):
basic_quorum=None, notfound_ok=None, head_only=False):
"""
Retrieve a :class:`~riak.riak_object.RiakObject` or
:class:`~riak.datatypes.Datatype`, based on the presence and value
Expand All @@ -216,6 +216,9 @@ def get(self, key, r=None, pr=None, timeout=None, include_context=None,
:type basic_quorum: bool
:param notfound_ok: whether to treat not-found responses as successful
:type notfound_ok: bool
:param head_only: whether to fetch without value, so only metadata
(only available on PB transport)
:type head_only: bool
:rtype: :class:`RiakObject <riak.riak_object.RiakObject>` or
:class:`~riak.datatypes.Datatype`
Expand All @@ -231,10 +234,12 @@ def get(self, key, r=None, pr=None, timeout=None, include_context=None,
obj = RiakObject(self._client, self, key)
return obj.reload(r=r, pr=pr, timeout=timeout,
basic_quorum=basic_quorum,
notfound_ok=notfound_ok)
notfound_ok=notfound_ok,
head_only=head_only)

def multiget(self, keys, r=None, pr=None, timeout=None,
basic_quorum=None, notfound_ok=None):
basic_quorum=None, notfound_ok=None,
head_only=False):
"""
Retrieves a list of keys belonging to this bucket in parallel.
Expand All @@ -251,14 +256,18 @@ def multiget(self, keys, r=None, pr=None, timeout=None,
:type basic_quorum: bool
:param notfound_ok: whether to treat not-found responses as successful
:type notfound_ok: bool
:param head_only: whether to fetch without value, so only metadata
(only available on PB transport)
:type head_only: bool
:rtype: list of :class:`RiakObjects <riak.riak_object.RiakObject>`,
:class:`Datatypes <riak.datatypes.Datatype>`, or tuples of
bucket_type, bucket, key, and the exception raised on fetch
"""
bkeys = [(self.bucket_type.name, self.name, key) for key in keys]
return self._client.multiget(bkeys, r=r, pr=pr, timeout=timeout,
basic_quorum=basic_quorum,
notfound_ok=notfound_ok)
notfound_ok=notfound_ok,
head_only=head_only)

def _get_resolver(self):
if callable(self._resolver):
Expand Down
8 changes: 6 additions & 2 deletions riak/client/operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -678,7 +678,7 @@ def ts_stream_keys(self, table, timeout=None):

@retryable
def get(self, transport, robj, r=None, pr=None, timeout=None,
basic_quorum=None, notfound_ok=None):
basic_quorum=None, notfound_ok=None, head_only=False):
"""
get(robj, r=None, pr=None, timeout=None)
Expand All @@ -700,6 +700,9 @@ def get(self, transport, robj, r=None, pr=None, timeout=None,
:type basic_quorum: bool
:param notfound_ok: whether to treat not-found responses as successful
:type notfound_ok: bool
:param head_only: whether to fetch without value, so only metadata
(only available on PB transport)
:type head_only: bool
"""
_validate_timeout(timeout)
if not isinstance(robj.key, six.string_types):
Expand All @@ -708,7 +711,8 @@ def get(self, transport, robj, r=None, pr=None, timeout=None,

return transport.get(robj, r=r, pr=pr, timeout=timeout,
basic_quorum=basic_quorum,
notfound_ok=notfound_ok)
notfound_ok=notfound_ok,
head_only=head_only)

@retryable
def delete(self, transport, robj, rw=None, r=None, w=None, dw=None,
Expand Down
4 changes: 3 additions & 1 deletion riak/codecs/pbuf.py
Original file line number Diff line number Diff line change
Expand Up @@ -895,7 +895,8 @@ def decode_preflist(self, item):
return result

def encode_get(self, robj, r=None, pr=None, timeout=None,
basic_quorum=None, notfound_ok=None):
basic_quorum=None, notfound_ok=None,
head_only=False):
bucket = robj.bucket
req = riak.pb.riak_kv_pb2.RpbGetReq()
if r:
Expand All @@ -914,6 +915,7 @@ def encode_get(self, robj, r=None, pr=None, timeout=None,
req.bucket = str_to_bytes(bucket.name)
self._add_bucket_type(req, bucket.bucket_type)
req.key = str_to_bytes(robj.key)
req.head = head_only
mc = riak.pb.messages.MSG_CODE_GET_REQ
rc = riak.pb.messages.MSG_CODE_GET_RESP
return Msg(mc, req.SerializeToString(), rc)
Expand Down
2 changes: 2 additions & 0 deletions riak/content.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ def _serialize(self, value):
format(self.content_type))

def _deserialize(self, value):
if not value:
return value
decoder = self._robject.bucket.get_decoder(self.content_type)
if decoder:
return decoder(value)
Expand Down
7 changes: 5 additions & 2 deletions riak/riak_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ def store(self, w=None, dw=None, pw=None, return_body=True,
return self

def reload(self, r=None, pr=None, timeout=None, basic_quorum=None,
notfound_ok=None):
notfound_ok=None, head_only=False):
"""
Reload the object from Riak. When this operation completes, the
object could contain new metadata and a new value, if the object
Expand All @@ -293,10 +293,13 @@ def reload(self, r=None, pr=None, timeout=None, basic_quorum=None,
:type basic_quorum: bool
:param notfound_ok: whether to treat not-found responses as successful
:type notfound_ok: bool
:param head_only: whether to fetch without value, so only metadata
(only available on PB transport)
:type head_only: bool
:rtype: :class:`RiakObject`
"""

self.client.get(self, r=r, pr=pr, timeout=timeout)
self.client.get(self, r=r, pr=pr, timeout=timeout, head_only=head_only)
return self

def delete(self, r=None, w=None, dw=None, pr=None, pw=None,
Expand Down
15 changes: 14 additions & 1 deletion riak/tests/test_kv.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from time import sleep
from riak import ConflictError, RiakBucket, RiakError
from riak.resolver import default_resolver, last_written_resolver
from riak.tests import RUN_KV, RUN_RESOLVE
from riak.tests import RUN_KV, RUN_RESOLVE, PROTOCOL
from riak.tests.base import IntegrationTestBase
from riak.tests.comparison import Comparison

Expand Down Expand Up @@ -79,6 +79,19 @@ def test_no_returnbody(self):
o = bucket.new(self.key_name, "bar").store(return_body=False)
self.assertEqual(o.vclock, None)

@unittest.skipUnless(PROTOCOL == 'pbc', 'Only available on pbc')
def test_get_no_returnbody(self):
bucket = self.client.bucket(self.bucket_name)
o = bucket.new(self.key_name, "Ain't no body")
o.store()

stored_object = bucket.get(self.key_name, head_only=True)
self.assertFalse(stored_object.data)

list_of_objects = bucket.multiget([self.key_name], head_only=True)
for stored_object in list_of_objects:
self.assertFalse(stored_object.data)

def test_many_link_headers_should_work_fine(self):
bucket = self.client.bucket(self.bucket_name)
o = bucket.new("lots_of_links", "My god, it's full of links!")
Expand Down
2 changes: 1 addition & 1 deletion riak/transports/http/transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def get_resources(self):
return {}

def get(self, robj, r=None, pr=None, timeout=None, basic_quorum=None,
notfound_ok=None):
notfound_ok=None, head_only=False):
"""
Get a bucket/key from the server
"""
Expand Down
4 changes: 2 additions & 2 deletions riak/transports/tcp/transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,15 +133,15 @@ def _set_client_id(self, client_id):
doc="""the client ID for this connection""")

def get(self, robj, r=None, pr=None, timeout=None, basic_quorum=None,
notfound_ok=None):
notfound_ok=None, head_only=False):
"""
Serialize get request and deserialize response
"""
msg_code = riak.pb.messages.MSG_CODE_GET_REQ
codec = self._get_codec(msg_code)
msg = codec.encode_get(robj, r, pr,
timeout, basic_quorum,
notfound_ok)
notfound_ok, head_only)
resp_code, resp = self._request(msg, codec)
return codec.decode_get(robj, resp)

Expand Down
2 changes: 1 addition & 1 deletion riak/transports/transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def ping(self):
raise NotImplementedError

def get(self, robj, r=None, pr=None, timeout=None, basic_quorum=None,
notfound_ok=None):
notfound_ok=None, head_only=False):
"""
Fetches an object.
"""
Expand Down

0 comments on commit 4122875

Please sign in to comment.