Skip to content

Commit 486c3ce

Browse files
rozzabehackett
authored andcommitted
PYTHON-318 - Fix for SON pickling protocol 2
Updated tests to check protocol pickling as well
1 parent 271767f commit 486c3ce

File tree

5 files changed

+39
-6
lines changed

5 files changed

+39
-6
lines changed

bson/son.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ def __init__(self, data=None, **kwargs):
7272
self.update(data)
7373
self.update(kwargs)
7474

75+
def __new__(cls, *args, **kwargs):
76+
instance = super(SON, cls).__new__(cls, *args, **kwargs)
77+
instance.__keys = []
78+
return instance
79+
7580
def __repr__(self):
7681
result = []
7782
for key in self.__keys:
@@ -214,3 +219,4 @@ def __deepcopy__(self, memo):
214219
for k, v in self.iteritems():
215220
out[k] = copy.deepcopy(v, memo)
216221
return out
222+

test/test_dbref.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,10 @@ def test_deepcopy(self):
125125

126126
def test_pickling(self):
127127
dbr = DBRef('coll', 5, foo='bar')
128-
pkl = pickle.dumps(dbr)
129-
dbr2 = pickle.loads(pkl)
130-
self.assertEqual(dbr, dbr2)
128+
for protocol in [0, 1, 2, -1]:
129+
pkl = pickle.dumps(dbr, protocol=protocol)
130+
dbr2 = pickle.loads(pkl)
131+
self.assertEqual(dbr, dbr2)
131132

132133
def test_dbref_hash(self):
133134
dbref_1a = DBRef('collection', 'id', 'database')

test/test_objectid.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,9 @@ def test_from_datetime(self):
133133

134134
def test_pickling(self):
135135
orig = ObjectId()
136-
self.assertEqual(orig, pickle.loads(pickle.dumps(orig)))
136+
for protocol in [0, 1, 2, -1]:
137+
pkl = pickle.dumps(orig, protocol=protocol)
138+
self.assertEqual(orig, pickle.loads(pkl))
137139

138140
def test_pickle_backwards_compatability(self):
139141

test/test_son.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import unittest
1818
import sys
19+
import pickle
1920
sys.path[0:0] = [""]
2021

2122
from bson.son import SON
@@ -53,6 +54,27 @@ def test_to_dict(self):
5354
self.assertEqual(dict, c.to_dict()["blah"][0].__class__)
5455
self.assertEqual(dict, d.to_dict()["blah"]["foo"].__class__)
5556

57+
def test_pickle(self):
58+
59+
simple_son = SON([])
60+
complex_son = SON([('son', simple_son), ('list', [simple_son, simple_son])])
61+
62+
for protocol in [0, 1, 2, -1]:
63+
pickled = pickle.loads(pickle.dumps(complex_son, protocol=protocol))
64+
self.assertEquals(pickled['son'], pickled['list'][0])
65+
self.assertEquals(pickled['son'], pickled['list'][1])
66+
67+
def test_pickle_backwards_compatability(self):
68+
69+
# This string was generated by pickling a SON object in pymongo
70+
# version 2.1.1
71+
pickled_with_2_1_1 = (
72+
"ccopy_reg\n_reconstructor\np0\n(cbson.son\nSON\np1\n"
73+
"c__builtin__\ndict\np2\n(dp3\ntp4\nRp5\n(dp6\n"
74+
"S'_SON__keys'\np7\n(lp8\nsb."
75+
)
76+
son_2_1_1 = pickle.loads(pickled_with_2_1_1)
77+
self.assertEqual(son_2_1_1, SON([]))
5678

5779
if __name__ == "__main__":
5880
unittest.main()

test/test_timestamp.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,10 @@ def test_datetime_copy_pickle(self):
4949
dc = copy.deepcopy(d)
5050
self.assertEqual(dc, t.as_datetime())
5151

52-
dp = pickle.loads(pickle.dumps(d))
53-
self.assertEqual(dp, t.as_datetime())
52+
for protocol in [0, 1, 2, -1]:
53+
pkl = pickle.dumps(d, protocol=protocol)
54+
dp = pickle.loads(pkl)
55+
self.assertEqual(dp, t.as_datetime())
5456

5557
def test_exceptions(self):
5658
self.assertRaises(TypeError, Timestamp)

0 commit comments

Comments
 (0)