mahmoud / boltons

🔩 Like builtins, but boltons. 250+ constructs, recipes, and snippets which extend (and rely on nothing but) the Python standard library. Nothing like Michael Bolton.
https://boltons.readthedocs.org
Other
6.54k stars 353 forks source link

Non-empty `dictutils.OMD` cannot be loaded from `pickle` #337

Closed allanlei closed 1 year ago

allanlei commented 1 year ago

A non-empty OrderedMultiDict can be serialized, but cannot be deserialized. A empty OrderedMultiDict can be both serialized and deserialized.

In [1]: import pickle

In [2]: import boltons.dictutils

In [3]: pickle.loads(pickle.dumps(boltons.dictutils.OMD()))
Out[3]: OrderedMultiDict([])

In [4]: pickle.loads(pickle.dumps(boltons.dictutils.OMD({'a': 1})))
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[4], line 1
----> 1 pickle.loads(pickle.dumps(boltons.dictutils.OMD({'a': 1})))

File /usr/local/lib/python3.11/site-packages/boltons/dictutils.py:333, in OrderedMultiDict.__setitem__(self, k, v)
    331 if super(OrderedMultiDict, self).__contains__(k):
    332     self._remove_all(k)
--> 333 self._insert(k, v)
    334 super(OrderedMultiDict, self).__setitem__(k, [v])

File /usr/local/lib/python3.11/site-packages/boltons/dictutils.py:198, in OrderedMultiDict._insert(self, k, v)
    197 def _insert(self, k, v):
--> 198     root = self.root
    199     cells = self._map.setdefault(k, [])
    200     last = root[PREV]

AttributeError: 'OrderedMultiDict' object has no attribute 'root'
mahmoud commented 1 year ago

Oh wow, it's been a while since I pickled an OMD, clearly. This worked on py2, but I tested and confirmed the above. PR in #338. Thanks for the report!