Skip to content

Inconsistent datatype reload() behavior between PBC and HTTP. [JIRA: CLIENTS-811] #447

Open
@daroot

Description

@daroot

Python 2.7, using riak-python-client 2.4.2:

Attempting to reload() a new or nonexistent Map datatype raises an Exception when using HTTP transport, but works when using Protobufs:

Python 2.7.11 (default, Jan 23 2016, 12:34:14)
[GCC 5.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from riak import RiakClient
>>> r = RiakClient(host="172.17.0.7", protocol="http")
>>> b = r.bucket_type('maps').bucket('test')
>>> new_item = b.new('foo')
>>> new_item.reload()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/app/ve/lib/python2.7/site-packages/riak/datatypes/datatype.py", line 124, in reload
    self._set_value(value)
  File "/app/ve/lib/python2.7/site-packages/riak/datatypes/datatype.py", line 213, in _set_value
    self._raise_if_badtype(value)
  File "/app/ve/lib/python2.7/site-packages/riak/datatypes/datatype.py", line 206, in _raise_if_badtype
    if not self._check_type(new_value):
  File "/app/ve/lib/python2.7/site-packages/riak/datatypes/map.py", line 286, in _check_type
    for key in value:
TypeError: 'NoneType' object is not iterable
>>> r = RiakClient(host="172.17.0.7", protocol="pbc")
>>> b = r.bucket_type('maps').bucket('test')
>>> new_item = b.new('bar')
>>> new_item.reload()
<riak.datatypes.map.Map object at 0x7f3041cf0a50>

Set fails with different but similar exception:

>>> r = RiakClient(host="172.17.0.7", protocol="http")
>>> b = r.bucket_type('sets').bucket('test')
>>> new_item = b.new('foo')
>>> new_item.reload()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/app/ve/lib/python2.7/site-packages/riak/datatypes/datatype.py", line 124, in reload
    self._set_value(value)
  File "/app/ve/lib/python2.7/site-packages/riak/datatypes/datatype.py", line 213, in _set_value
    self._raise_if_badtype(value)
  File "/app/ve/lib/python2.7/site-packages/riak/datatypes/datatype.py", line 207, in _raise_if_badtype
    raise TypeError(self._type_error_msg)
TypeError: Sets can only be iterables of strings
>>> r = RiakClient(host="172.17.0.7", protocol="pbc")
>>> b = r.bucket_type('sets').bucket('test')
>>> new_item = b.new('foo')
>>> new_item.reload()
<riak.datatypes.set.Set object at 0x7f3041cf0750>

The problem appears to be a mismatch between https://github.com/basho/riak-python-client/blob/master/riak/transports/http/transport.py#L733 and the _check_type methods for each datatype. The PBC transport's codec seems happy creating default python values and filling them in as it decodes, so _check_type gets the right type, even if it's an empty value. But the HTTP transport just blindly throws a None out if it gets a 404 while fetching, causing _check_type to choke, as None is not iterable.

I'm not sure if the right fix is to make each _check_type treat None appropriately, or to make fetch_datatype smarter about returning the appropriate empty set/dict/str/etc, but I definitely think the PBC transport's behavior is more in line with both the documentation and the expected behavior.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions