dry-python/returns

Breaking deserialization backward compatibility between 0.19.0 and 0.20.0

maybe-hello-world opened this issue · 1 comments

Bug report

In version 0.20.0 changes to returns/primitives/container.py were presented for __setstate__ and __getstate__ functions of BaseContainer to fix None serialization. Unfortunately, these changes break deserialization backward compatibility, so any object serialized with returns<=0.19.0 cannot be deserialized at all with returns==0.20.0.

What's wrong

If an object of type Result was serialized with returns==0.19.0, then during deserialization the next error would be seen:

File /data/anaconda3/lib/python3.9/site-packages/returns/primitives/container.py:62, in BaseContainer.__setstate__(self, state)
     59 def __setstate__(self, state: _PickleState) -> None:
     60     """Loading state from pickled data."""
     61     object.__setattr__(  # noqa: WPS609
---> 62         self, '_inner_value', state['container_value'],
     63     )

TypeError: byte indices must be integers or slices, not str

That happens, because the state object is not a dict with the 'container_value' key (how it should be if serialized with 0.20.0), but a byte-like (serialized) object.

How is that could be

Though backward compatibility is not always a goal, here at least partial (deserialization) backward compatibility could be achieved.

The simple way is to add a check to the __setstate__ function, such as whether the state object is an instance of dict and the 'container_value' key is presented. Probably the only downside of this would be the slightly slower deserialization of containers.

System information

  • python version: 3.10
  • returns version: 0.19.0 and 0.20.0

@maybe-hello-world PR is welcome!