Commit 8f3ce99a authored by Tres Seaver's avatar Tres Seaver

Move main narrative doctests to 'docs/usage.rst'.

parent 358ac883
.. _glossary:
Glossary
========
.. glossary::
:sorted:
data manager
The object responsible for storing and loading an object's
:term:`pickled data` in a backing store. Also called a :term:`jar`.
jar
Alias for :term:`data manager`: short for "pickle jar", because
it traditionally holds the :term:`pickled data` of persistent objects.
object cache
An MRU cache for objects associated with a given :term:`data manager`.
ghost
An object whose :term:`pickled data` has not yet been loaded from its
:term:`jar`. Accessing or mutating any of its attributes causes
that data to be loaded, which is referred to as :term:`activation`.
volatile attribute
Attributes of a persistent object which are *not* caputured as part
of its :term:`pickled data`. These attributes thus disappear during
:term:`deactivation` or :term:`invalidation`.
pickled data
The serialized data of a persistent object, stored in and retrieved
from a backing store by a :term:`data manager`.
activation
Moving an object from the ``GHOST`` state to the ``UPTODATE`` state,
load its :term:`pickled data` from its :term:`jar`.
deactivation
Moving an object from the ``UPTODATE`` state to the ``GHOST`` state,
discarding its :term:`pickled data`.
invalidation
Moving an object from either the ``UPTODATE`` state or the ``CHANGED``
state to the ``GHOST`` state, discarding its :term:`pickled data`.
......@@ -12,6 +12,7 @@ Contents:
using
api
glossary
Indices and tables
==================
......
This diff is collapsed.
Tests for `persistent.Persistent`
=================================
This document is an extended doc test that covers the basics of the
Persistent base class. The test expects a class named `P` to be
This document covers "edge case" tests for the Persistent base class.
It should be replaced with normal unit tests. (The meat of the narrative
documentation is now in ``docs/usage`` of the distribution).
The test expects a class named `P` to be
provided in its globals. The `P` class implements the `Persistent`
interface.
......@@ -42,236 +45,6 @@ the ``_p_jar`` attribute of a persistent object.
>>> from persistent import Persistent
Test Persistent without Data Manager
------------------------------------
First do some simple tests of a Persistent instance that does not have
a data manager (``_p_jar``).
>>> p = P()
>>> p.x
0
>>> p._p_changed
False
>>> p._p_state
0
>>> p._p_jar
>>> p._p_oid
Verify that modifications have no effect on ``_p_state`` of ``_p_changed``.
>>> p.inc()
>>> p.inc()
>>> p.x
2
>>> p._p_changed
False
>>> p._p_state
0
Try all sorts of different ways to change the object's state.
>>> p._p_deactivate()
>>> p._p_state
0
>>> p._p_changed = True
>>> p._p_state
0
>>> del p._p_changed
>>> p._p_changed
False
>>> p._p_state
0
>>> p.x
2
We can store a size estimation in ``_p_estimated_size``. Its default is 0.
The size estimation can be used by a cache associated with the data manager
to help in the implementation of its replacement strategy or its size bounds.
Of course, the estimated size must not be negative.
>>> p._p_estimated_size
0
>>> p._p_estimated_size = 1000
>>> p._p_estimated_size
1024
Huh? Why is the estimated size coming out different than what we put
in? The reason is that the size isn't stored exactly. For backward
compatibility reasons, the size needs to fit in 24 bits, so,
internally, it is adjusted somewhat.
>>> p._p_estimated_size = -1
Traceback (most recent call last):
....
ValueError: _p_estimated_size must not be negative
Test Persistent with Data Manager
---------------------------------
Next try some tests of an object with a data manager. The `DM` class is
a simple testing stub.
>>> p = P()
>>> dm = DM()
>>> p._p_oid = "00000012"
>>> p._p_jar = dm
>>> p._p_changed
0
>>> dm.called
0
Modifying the object marks it as changed and registers it with the data
manager. Subsequent modifications don't have additional side-effects.
>>> p.inc()
>>> p._p_changed
1
>>> dm.called
1
>>> p.inc()
>>> p._p_changed
1
>>> dm.called
1
It's not possible to deactivate a modified object.
>>> p._p_deactivate()
>>> p._p_changed
1
It is possible to invalidate it. That's the key difference between
deactivation and invalidation.
>>> p._p_invalidate()
>>> p._p_state
-1
Now that the object is a ghost, any attempt to modify it will require that it
be unghosted first. The test data manager has the odd property that it sets
the object's ``x`` attribute to ``42`` when it is unghosted.
>>> p.inc()
>>> p.x
43
>>> dm.called
2
You can manually reset the changed field to ``False``, although it's not clear
why you would want to do that. The object changes to the ``UPTODATE`` state
but retains its modifications.
>>> p._p_changed = False
>>> p._p_state
0
>>> p._p_changed
False
>>> p.x
43
>>> p.inc()
>>> p._p_changed
True
>>> dm.called
3
``__getstate__()`` and ``__setstate__()``
-----------------------------------------
The next several tests cover the ``__getstate__()`` and ``__setstate__()``
implementations.
>>> p = P()
>>> state = p.__getstate__()
>>> isinstance(state, dict)
True
>>> state['x']
0
>>> p._p_state
0
Calling setstate always leaves the object in the uptodate state?
(I'm not entirely clear on this one.)
>>> p.__setstate__({'x': 5})
>>> p._p_state
0
Assigning to a volatile attribute has no effect on the object state.
>>> p._v_foo = 2
>>> p.__getstate__()
{'x': 5}
>>> p._p_state
0
The ``_p_serial`` attribute is not affected by calling setstate.
>>> p._p_serial = "00000012"
>>> p.__setstate__(p.__getstate__())
>>> p._p_serial
'00000012'
Change Ghost test
-----------------
If an object is a ghost and its ``_p_changed`` is set to ``True`` (any true
value), it should activate (unghostify) the object. This behavior is new in
ZODB 3.6; before then, an attempt to do ``ghost._p_changed = True`` was
ignored.
>>> p = P()
>>> p._p_jar = DM()
>>> p._p_oid = 1
>>> p._p_deactivate()
>>> p._p_changed # None
>>> p._p_state # ghost state
-1
>>> p._p_changed = True
>>> p._p_changed
1
>>> p._p_state # changed state
1
>>> p.x
42
Activate, deactivate, and invalidate
------------------------------------
Some of these tests are redundant, but are included to make sure there
are explicit and simple tests of ``_p_activate()``, ``_p_deactivate()``, and
``_p_invalidate()``.
>>> p = P()
>>> p._p_oid = 1
>>> p._p_jar = DM()
>>> p._p_deactivate()
>>> p._p_state
-1
>>> p._p_activate()
>>> p._p_state
0
>>> p.x
42
>>> p.inc()
>>> p.x
43
>>> p._p_state
1
>>> p._p_invalidate()
>>> p._p_state
-1
>>> p.x
42
Test failures
-------------
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment