Skip to content

Commit 8f851f7

Browse files
pierreglaserogrisel
authored andcommitted
support property pickling in python 3.8 + (#329)
1 parent c3982ea commit 8f851f7

File tree

3 files changed

+53
-0
lines changed

3 files changed

+53
-0
lines changed

Diff for: CHANGES.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
1.2.3
22
=====
33

4+
- Fix a regression in cloudpickle and python3.8 causing an error when trying to
5+
pickle property objects.
6+
([PR #329](https://github.com/cloudpipe/cloudpickle/pull/329)).
7+
48
- Fix a bug when a thread imports a module while cloudpickle iterates
59
over the module list
610
([PR #322](https://github.com/cloudpipe/cloudpickle/pull/322)).

Diff for: cloudpickle/cloudpickle_fast.py

+5
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,10 @@ def _root_logger_reduce(obj):
291291
return logging.getLogger, ()
292292

293293

294+
def _property_reduce(obj):
295+
return property, (obj.fget, obj.fset, obj.fdel, obj.__doc__)
296+
297+
294298
def _weakset_reduce(obj):
295299
return weakref.WeakSet, (list(obj),)
296300

@@ -406,6 +410,7 @@ class CloudPickler(Pickler):
406410
dispatch[logging.Logger] = _logger_reduce
407411
dispatch[logging.RootLogger] = _root_logger_reduce
408412
dispatch[memoryview] = _memoryview_reduce
413+
dispatch[property] = _property_reduce
409414
dispatch[staticmethod] = _classmethod_reduce
410415
dispatch[types.CellType] = _cell_reduce
411416
dispatch[types.CodeType] = _code_reduce

Diff for: tests/cloudpickle_test.py

+44
Original file line numberDiff line numberDiff line change
@@ -1119,6 +1119,50 @@ def func(x):
11191119
cloned = pickle_depickle(func, protocol=self.protocol)
11201120
self.assertEqual(cloned.__qualname__, func.__qualname__)
11211121

1122+
def test_property(self):
1123+
class MyObject:
1124+
_read_only_value = 1
1125+
_read_write_value = 1
1126+
1127+
@property
1128+
def read_only_value(self):
1129+
"A read-only attribute"
1130+
return self._read_only_value
1131+
1132+
@property
1133+
def read_write_value(self):
1134+
return self._read_write_value
1135+
1136+
@read_write_value.setter
1137+
def read_write_value(self, value):
1138+
self._read_write_value = value
1139+
1140+
1141+
1142+
my_object = MyObject()
1143+
1144+
assert my_object.read_only_value == 1
1145+
assert MyObject.read_only_value.__doc__ == "A read-only attribute"
1146+
1147+
with pytest.raises(AttributeError):
1148+
my_object.read_only_value = 2
1149+
my_object.read_write_value = 2
1150+
1151+
depickled_obj = pickle_depickle(my_object)
1152+
1153+
assert depickled_obj.read_only_value == 1
1154+
assert depickled_obj.read_write_value == 2
1155+
1156+
# make sure the depickled read_only_value attribute is still read-only
1157+
with pytest.raises(AttributeError):
1158+
my_object.read_only_value = 2
1159+
1160+
# make sure the depickled read_write_value attribute is writeable
1161+
depickled_obj.read_write_value = 3
1162+
assert depickled_obj.read_write_value == 3
1163+
type(depickled_obj).read_only_value.__doc__ == "A read-only attribute"
1164+
1165+
11221166
def test_namedtuple(self):
11231167
MyTuple = collections.namedtuple('MyTuple', ['a', 'b', 'c'])
11241168
t1 = MyTuple(1, 2, 3)

0 commit comments

Comments
 (0)