Description
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.