Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
persistent
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
persistent
Commits
871686e2
Commit
871686e2
authored
Jun 28, 2012
by
Tres Seaver
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Convert pickling doctests to unittests + Sphinx API docs.
parent
8581c0de
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
258 additions
and
188 deletions
+258
-188
docs/api.rst
docs/api.rst
+1
-0
docs/api/pickling.rst
docs/api/pickling.rst
+171
-0
persistent/tests/test_pickle.py
persistent/tests/test_pickle.py
+6
-187
persistent/tests/test_pyPersistence.py
persistent/tests/test_pyPersistence.py
+80
-1
No files found.
docs/api.rst
View file @
871686e2
...
...
@@ -5,3 +5,4 @@
:maxdepth: 2
api/interfaces
api/pickling
docs/api/pickling.rst
0 → 100644
View file @
871686e2
Pickling Persistent Objects
===========================
Persistent objects are designed to make the standard Python pickling
machinery happy:
.. doctest::
>>> import pickle
>>> from persistent.tests.test_pickle import Simple
>>> from persistent.tests.test_pickle import print_dict
>>> x = Simple('x', aaa=1, bbb='foo')
>>> print_dict(x.__dict__)
{'__name__': 'x', 'aaa': 1, 'bbb': 'foo'}
>>> print_dict(x.__getstate__())
{'__name__': 'x', 'aaa': 1, 'bbb': 'foo'}
>>> f, (c,), state = x.__reduce__()
>>> f.__name__
'__newobj__'
>>> f.__module__
'copy_reg'
>>> c.__name__
'Simple'
>>> print_dict(state)
{'__name__': 'x', 'aaa': 1, 'bbb': 'foo'}
>>> import pickle
>>> pickle.loads(pickle.dumps(x)) == x
True
>>> pickle.loads(pickle.dumps(x, 0)) == x
True
>>> pickle.loads(pickle.dumps(x, 1)) == x
True
>>> pickle.loads(pickle.dumps(x, 2)) == x
True
>>> x.__setstate__({'z': 1})
>>> x.__dict__
{'z': 1}
This support even works well for derived classes which customize pickling
by overriding :meth:`__getnewargs__`, :meth:`__getstate__` and
:meth:`__setstate__`.
.. doctest::
>>> from persistent.tests.test_pickle import Custom
>>> x = Custom('x', 'y')
>>> x.__getnewargs__()
('x', 'y')
>>> x.a = 99
>>> (f, (c, ax, ay), a) = x.__reduce__()
>>> f.__name__
'__newobj__'
>>> f.__module__
'copy_reg'
>>> c.__name__
'Custom'
>>> ax, ay, a
('x', 'y', 99)
>>> pickle.loads(pickle.dumps(x)) == x
True
>>> pickle.loads(pickle.dumps(x, 0)) == x
True
>>> pickle.loads(pickle.dumps(x, 1)) == x
True
>>> pickle.loads(pickle.dumps(x, 2)) == x
True
The support works for derived classes which define :attr:`__slots__`. It
ignores any slots which map onto the "persistent" namespace (prefixed with
``_p_``) or the "volatile" namespace (prefixed with ``_v_``):
.. doctest::
>>> import copy_reg
>>> from persistent.tests.test_pickle import SubSlotted
>>> x = SubSlotted('x', 'y', 'z')
Note that we haven't yet assiged a value to the ``s4`` attribute:
.. doctest::
>>> d, s = x.__getstate__()
>>> d
>>> print_dict(s)
{'s1': 'x', 's2': 'y', 's3': 'z'}
>>> import pickle
>>> pickle.loads(pickle.dumps(x)) == x
True
>>> pickle.loads(pickle.dumps(x, 0)) == x
True
>>> pickle.loads(pickle.dumps(x, 1)) == x
True
>>> pickle.loads(pickle.dumps(x, 2)) == x
True
After assigning it:
.. doctest::
>>> x.s4 = 'spam'
>>> d, s = x.__getstate__()
>>> d
>>> print_dict(s)
{'s1': 'x', 's2': 'y', 's3': 'z', 's4': 'spam'}
>>> pickle.loads(pickle.dumps(x)) == x
True
>>> pickle.loads(pickle.dumps(x, 0)) == x
True
>>> pickle.loads(pickle.dumps(x, 1)) == x
True
>>> pickle.loads(pickle.dumps(x, 2)) == x
True
:class:`persistent.Persistent` supports derived classes which have base
classes defining :attr:`__slots`, but which do not define attr:`__slots__`
themselves:
.. doctest::
>>> from persistent.tests.test_pickle import SubSubSlotted
>>> x = SubSubSlotted('x', 'y', 'z')
>>> d, s = x.__getstate__()
>>> print_dict(d)
{}
>>> print_dict(s)
{'s1': 'x', 's2': 'y', 's3': 'z'}
>>> import pickle
>>> pickle.loads(pickle.dumps(x)) == x
1
>>> pickle.loads(pickle.dumps(x, 0)) == x
1
>>> pickle.loads(pickle.dumps(x, 1)) == x
1
>>> pickle.loads(pickle.dumps(x, 2)) == x
1
>>> x.s4 = 'spam'
>>> x.foo = 'bar'
>>> x.baz = 'bam'
>>> d, s = x.__getstate__()
>>> print_dict(d)
{'baz': 'bam', 'foo': 'bar'}
>>> print_dict(s)
{'s1': 'x', 's2': 'y', 's3': 'z', 's4': 'spam'}
>>> pickle.loads(pickle.dumps(x)) == x
1
>>> pickle.loads(pickle.dumps(x, 0)) == x
1
>>> pickle.loads(pickle.dumps(x, 1)) == x
1
>>> pickle.loads(pickle.dumps(x, 2)) == x
1
persistent/tests/test_pickle.py
View file @
871686e2
...
...
@@ -11,7 +11,7 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
import
unittest
# Example objects for pickling.
from
persistent
import
Persistent
...
...
@@ -42,41 +42,6 @@ class Simple(Persistent):
def
__cmp__
(
self
,
other
):
return
cmpattrs
(
self
,
other
,
'__class__'
,
*
(
self
.
__dict__
.
keys
()))
def
test_basic_pickling
():
"""
>>> x = Simple('x', aaa=1, bbb='foo')
>>> print_dict(x.__getstate__())
{'__name__': 'x', 'aaa': 1, 'bbb': 'foo'}
>>> f, (c,), state = x.__reduce__()
>>> f.__name__
'__newobj__'
>>> f.__module__
'copy_reg'
>>> c.__name__
'Simple'
>>> print_dict(state)
{'__name__': 'x', 'aaa': 1, 'bbb': 'foo'}
>>> import pickle
>>> pickle.loads(pickle.dumps(x)) == x
1
>>> pickle.loads(pickle.dumps(x, 0)) == x
1
>>> pickle.loads(pickle.dumps(x, 1)) == x
1
>>> pickle.loads(pickle.dumps(x, 2)) == x
1
>>> x.__setstate__({'z': 1})
>>> x.__dict__
{'z': 1}
"""
class
Custom
(
Simple
):
def
__new__
(
cls
,
x
,
y
):
...
...
@@ -97,88 +62,28 @@ class Custom(Simple):
self
.
a
=
a
def
test_pickling_w_overrides
():
"""
>>> x = Custom('x', 'y')
>>> x.a = 99
>>> (f, (c, ax, ay), a) = x.__reduce__()
>>> f.__name__
'__newobj__'
>>> f.__module__
'copy_reg'
>>> c.__name__
'Custom'
>>> ax, ay, a
('x', 'y', 99)
>>> import pickle
>>> pickle.loads(pickle.dumps(x)) == x
1
>>> pickle.loads(pickle.dumps(x, 0)) == x
1
>>> pickle.loads(pickle.dumps(x, 1)) == x
1
>>> pickle.loads(pickle.dumps(x, 2)) == x
1
"""
class
Slotted
(
Persistent
):
__slots__
=
's1'
,
's2'
,
'_p_splat'
,
'_v_eek'
def
__init__
(
self
,
s1
,
s2
):
self
.
s1
,
self
.
s2
=
s1
,
s2
self
.
_v_eek
=
1
self
.
_p_splat
=
2
class
SubSlotted
(
Slotted
):
__slots__
=
's3'
,
's4'
def
__init__
(
self
,
s1
,
s2
,
s3
):
Slotted
.
__init__
(
self
,
s1
,
s2
)
self
.
s3
=
s3
def
__cmp__
(
self
,
other
):
return
cmpattrs
(
self
,
other
,
'__class__'
,
's1'
,
's2'
,
's3'
,
's4'
)
def
test_pickling_w_slots_only
():
"""
>>> x = SubSlotted('x', 'y', 'z')
>>> d, s = x.__getstate__()
>>> d
>>> print_dict(s)
{'s1': 'x', 's2': 'y', 's3': 'z'}
>>> import pickle
>>> pickle.loads(pickle.dumps(x)) == x
1
>>> pickle.loads(pickle.dumps(x, 0)) == x
1
>>> pickle.loads(pickle.dumps(x, 1)) == x
1
>>> pickle.loads(pickle.dumps(x, 2)) == x
1
>>> x.s4 = 'spam'
>>> d, s = x.__getstate__()
>>> d
>>> print_dict(s)
{'s1': 'x', 's2': 'y', 's3': 'z', 's4': 'spam'}
>>> pickle.loads(pickle.dumps(x)) == x
1
>>> pickle.loads(pickle.dumps(x, 0)) == x
1
>>> pickle.loads(pickle.dumps(x, 1)) == x
1
>>> pickle.loads(pickle.dumps(x, 2)) == x
1
"""
class
SubSubSlotted
(
SubSlotted
):
def
__init__
(
self
,
s1
,
s2
,
s3
,
**
kw
):
...
...
@@ -191,89 +96,3 @@ class SubSubSlotted(SubSlotted):
return
cmpattrs
(
self
,
other
,
'__class__'
,
's1'
,
's2'
,
's3'
,
's4'
,
*
(
self
.
__dict__
.
keys
()))
def
test_pickling_w_slots
():
"""
>>> x = SubSubSlotted('x', 'y', 'z', aaa=1, bbb='foo')
>>> d, s = x.__getstate__()
>>> print_dict(d)
{'aaa': 1, 'bbb': 'foo'}
>>> print_dict(s)
{'s1': 'x', 's2': 'y', 's3': 'z'}
>>> import pickle
>>> pickle.loads(pickle.dumps(x)) == x
1
>>> pickle.loads(pickle.dumps(x, 0)) == x
1
>>> pickle.loads(pickle.dumps(x, 1)) == x
1
>>> pickle.loads(pickle.dumps(x, 2)) == x
1
>>> x.s4 = 'spam'
>>> d, s = x.__getstate__()
>>> print_dict(d)
{'aaa': 1, 'bbb': 'foo'}
>>> print_dict(s)
{'s1': 'x', 's2': 'y', 's3': 'z', 's4': 'spam'}
>>> pickle.loads(pickle.dumps(x)) == x
1
>>> pickle.loads(pickle.dumps(x, 0)) == x
1
>>> pickle.loads(pickle.dumps(x, 1)) == x
1
>>> pickle.loads(pickle.dumps(x, 2)) == x
1
"""
def
test_pickling_w_slots_w_empty_dict
():
"""
>>> x = SubSubSlotted('x', 'y', 'z')
>>> d, s = x.__getstate__()
>>> print_dict(d)
{}
>>> print_dict(s)
{'s1': 'x', 's2': 'y', 's3': 'z'}
>>> import pickle
>>> pickle.loads(pickle.dumps(x)) == x
1
>>> pickle.loads(pickle.dumps(x, 0)) == x
1
>>> pickle.loads(pickle.dumps(x, 1)) == x
1
>>> pickle.loads(pickle.dumps(x, 2)) == x
1
>>> x.s4 = 'spam'
>>> d, s = x.__getstate__()
>>> print_dict(d)
{}
>>> print_dict(s)
{'s1': 'x', 's2': 'y', 's3': 'z', 's4': 'spam'}
>>> pickle.loads(pickle.dumps(x)) == x
1
>>> pickle.loads(pickle.dumps(x, 0)) == x
1
>>> pickle.loads(pickle.dumps(x, 1)) == x
1
>>> pickle.loads(pickle.dumps(x, 2)) == x
1
"""
def
test_suite
():
from
doctest
import
DocTestSuite
return
unittest
.
TestSuite
((
DocTestSuite
(),
))
persistent/tests/test_pyPersistence.py
View file @
871686e2
...
...
@@ -788,6 +788,17 @@ class _Persistent_Base(object):
self
.
assertEqual
(
second
,
(
self
.
_getTargetClass
(),))
self
.
assertEqual
(
third
,
None
)
def
test___reduce__w_subclass_having_getnewargs
(
self
):
from
copy_reg
import
__newobj__
class
Derived
(
self
.
_getTargetClass
()):
def
__getnewargs__
(
self
):
return
(
'a'
,
'b'
)
inst
=
Derived
()
first
,
second
,
third
=
inst
.
__reduce__
()
self
.
failUnless
(
first
is
__newobj__
)
self
.
assertEqual
(
second
,
(
Derived
,
'a'
,
'b'
))
self
.
assertEqual
(
third
,
{})
def
test___reduce__w_subclass_having_getstate
(
self
):
from
copy_reg
import
__newobj__
class
Derived
(
self
.
_getTargetClass
()):
...
...
@@ -799,7 +810,7 @@ class _Persistent_Base(object):
self
.
assertEqual
(
second
,
(
Derived
,))
self
.
assertEqual
(
third
,
{})
def
test___reduce__w_subclass_having_g
na
_and_getstate
(
self
):
def
test___reduce__w_subclass_having_g
etnewargs
_and_getstate
(
self
):
from
copy_reg
import
__newobj__
class
Derived
(
self
.
_getTargetClass
()):
def
__getnewargs__
(
self
):
...
...
@@ -812,6 +823,74 @@ class _Persistent_Base(object):
self
.
assertEqual
(
second
,
(
Derived
,
'a'
,
'b'
))
self
.
assertEqual
(
third
,
{
'foo'
:
'bar'
})
def
test_pickle_roundtrip_simple
(
self
):
import
pickle
# XXX s.b. 'examples'
from
persistent.tests.test_pickle
import
Simple
inst
=
Simple
(
'testing'
)
copy
=
pickle
.
loads
(
pickle
.
dumps
(
inst
))
self
.
assertEqual
(
copy
,
inst
)
for
protocol
in
0
,
1
,
2
:
copy
=
pickle
.
loads
(
pickle
.
dumps
(
inst
,
protocol
))
self
.
assertEqual
(
copy
,
inst
)
def
test_pickle_roundtrip_w_getnewargs_and_getstate
(
self
):
import
pickle
# XXX s.b. 'examples'
from
persistent.tests.test_pickle
import
Custom
inst
=
Custom
(
'x'
,
'y'
)
copy
=
pickle
.
loads
(
pickle
.
dumps
(
inst
))
self
.
assertEqual
(
copy
,
inst
)
for
protocol
in
0
,
1
,
2
:
copy
=
pickle
.
loads
(
pickle
.
dumps
(
inst
,
protocol
))
self
.
assertEqual
(
copy
,
inst
)
def
test_pickle_roundtrip_w_slots_missing_slot
(
self
):
import
pickle
# XXX s.b. 'examples'
from
persistent.tests.test_pickle
import
SubSlotted
inst
=
SubSlotted
(
'x'
,
'y'
,
'z'
)
copy
=
pickle
.
loads
(
pickle
.
dumps
(
inst
))
self
.
assertEqual
(
copy
,
inst
)
for
protocol
in
0
,
1
,
2
:
copy
=
pickle
.
loads
(
pickle
.
dumps
(
inst
,
protocol
))
self
.
assertEqual
(
copy
,
inst
)
def
test_pickle_roundtrip_w_slots_filled_slot
(
self
):
import
pickle
# XXX s.b. 'examples'
from
persistent.tests.test_pickle
import
SubSlotted
inst
=
SubSlotted
(
'x'
,
'y'
,
'z'
)
inst
.
s4
=
'a'
copy
=
pickle
.
loads
(
pickle
.
dumps
(
inst
))
self
.
assertEqual
(
copy
,
inst
)
for
protocol
in
0
,
1
,
2
:
copy
=
pickle
.
loads
(
pickle
.
dumps
(
inst
,
protocol
))
self
.
assertEqual
(
copy
,
inst
)
def
test_pickle_roundtrip_w_slots_and_empty_dict
(
self
):
import
pickle
# XXX s.b. 'examples'
from
persistent.tests.test_pickle
import
SubSubSlotted
inst
=
SubSubSlotted
(
'x'
,
'y'
,
'z'
)
copy
=
pickle
.
loads
(
pickle
.
dumps
(
inst
))
self
.
assertEqual
(
copy
,
inst
)
for
protocol
in
0
,
1
,
2
:
copy
=
pickle
.
loads
(
pickle
.
dumps
(
inst
,
protocol
))
self
.
assertEqual
(
copy
,
inst
)
def
test_pickle_roundtrip_w_slots_and_filled_dict
(
self
):
import
pickle
# XXX s.b. 'examples'
from
persistent.tests.test_pickle
import
SubSubSlotted
inst
=
SubSubSlotted
(
'x'
,
'y'
,
'z'
,
foo
=
'bar'
,
baz
=
'bam'
)
inst
.
s4
=
'a'
copy
=
pickle
.
loads
(
pickle
.
dumps
(
inst
))
self
.
assertEqual
(
copy
,
inst
)
for
protocol
in
0
,
1
,
2
:
copy
=
pickle
.
loads
(
pickle
.
dumps
(
inst
,
protocol
))
self
.
assertEqual
(
copy
,
inst
)
def
test__p_activate_from_unsaved
(
self
):
inst
=
self
.
_makeOne
()
inst
.
_p_activate
()
# noop w/o jar
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment