[Checkins] SVN: persistent/trunk/ Convert attribut hook doctests to unittests + Sphinx API docs.

Tres Seaver cvs-admin at zope.org
Thu Jun 28 22:50:02 UTC 2012


Log message for revision 127159:
  Convert attribut hook doctests to unittests + Sphinx API docs.

Changed:
  _U  persistent/trunk/
  A   persistent/trunk/docs/api/attributes.rst
  U   persistent/trunk/docs/api.rst
  U   persistent/trunk/persistent/tests/test_overriding_attrs.py

-=-
Added: persistent/trunk/docs/api/attributes.rst
===================================================================
--- persistent/trunk/docs/api/attributes.rst	                        (rev 0)
+++ persistent/trunk/docs/api/attributes.rst	2012-06-28 22:49:58 UTC (rev 127159)
@@ -0,0 +1,311 @@
+Customizing Attribute Access
+============================
+
+Hooking :meth:`__getattr__`
+---------------------------
+The __getattr__ method works pretty much the same for persistent
+classes as it does for other classes.  No special handling is
+needed.  If an object is a ghost, then it will be activated before
+__getattr__ is called.
+
+In this example, our objects returns a tuple with the attribute
+name, converted to upper case and the value of _p_changed, for any
+attribute that isn't handled by the default machinery.
+
+.. doctest::
+
+   >>> from persistent.tests.test_overriding_attrs import OverridesGetattr
+   >>> o = OverridesGetattr()
+   >>> o._p_changed
+   False
+   >>> o._p_oid
+   >>> o._p_jar
+   >>> o.spam
+   ('SPAM', False)
+   >>> o.spam = 1
+   >>> o.spam
+   1
+
+We'll save the object, so it can be deactivated:
+
+.. doctest::
+
+   >>> from persistent.tests.test_overriding_attrs import _resettingJar
+   >>> jar = _resettingJar()
+   >>> jar.add(o)
+   >>> o._p_deactivate()
+   >>> o._p_changed
+
+And now, if we ask for an attribute it doesn't have,
+
+.. doctest::
+
+  >>> o.eggs
+  ('EGGS', False)
+
+And we see that the object was activated before calling the
+:meth:`__getattr__` method.
+
+Hooking All Access
+------------------
+
+In this example, we'll provide an example that shows how to
+override the :meth:`__getattribute__`, :meth:`__setattr__`, and
+:meth:`__delattr__` methods.  We'll create a class that stores it's
+attributes in a secret dictionary within the instance dictionary.
+
+The class will have the policy that variables with names starting
+with ``tmp_`` will be volatile.
+
+Our sample class takes initial values as keyword arguments to the constructor:
+
+.. doctest::
+
+   >>> from persistent.tests.test_overriding_attrs import VeryPrivate
+   >>> o = VeryPrivate(x=1)
+
+
+Hooking :meth:`__getattribute__``
+#################################
+
+The :meth:`__getattribute__` method is called for all attribute
+accesses.  It overrides the attribute access support inherited
+from Persistent.
+
+.. doctest::
+
+   >>> o._p_changed
+   False
+   >>> o._p_oid
+   >>> o._p_jar
+   >>> o.x
+   1
+   >>> o.y
+   Traceback (most recent call last):
+   ...
+   AttributeError: y
+
+Next, we'll save the object in a database so that we can deactivate it:
+
+.. doctest::
+
+   >>> from persistent.tests.test_overriding_attrs import _rememberingJar
+   >>> jar = _rememberingJar()
+   >>> jar.add(o)
+   >>> o._p_deactivate()
+   >>> o._p_changed
+
+And we'll get some data:
+
+.. doctest::
+
+   >>> o.x
+   1
+
+which activates the object:
+
+.. doctest::
+
+   >>> o._p_changed
+   False
+
+It works for missing attribes too:
+
+.. doctest::
+
+   >>> o._p_deactivate()
+   >>> o._p_changed
+
+   >>> o.y
+   Traceback (most recent call last):
+   ...
+   AttributeError: y
+
+   >>> o._p_changed
+   False
+
+
+Hooking :meth:`__setattr__``
+############################
+
+The :meth:`__setattr__` method is called for all attribute
+assignments.  It overrides the attribute assignment support
+inherited from Persistent.
+
+Implementors of :meth:`__setattr__` methods:
+
+1. Must call Persistent._p_setattr first to allow it
+   to handle some attributes and to make sure that the object
+   is activated if necessary, and
+
+2. Must set _p_changed to mark objects as changed.
+
+.. doctest::
+
+   >>> o = VeryPrivate()
+   >>> o._p_changed
+   False
+   >>> o._p_oid
+   >>> o._p_jar
+   >>> o.x
+   Traceback (most recent call last):
+   ...
+   AttributeError: x
+
+   >>> o.x = 1
+   >>> o.x
+   1
+
+Because the implementation doesn't store attributes directly
+in the instance dictionary, we don't have a key for the attribute:
+
+.. doctest::
+
+   >>> 'x' in o.__dict__
+   False
+
+Next, we'll give the object a "remembering" jar so we can
+deactivate it:
+
+.. doctest::
+
+   >>> jar = _rememberingJar()
+   >>> jar.add(o)
+   >>> o._p_deactivate()
+   >>> o._p_changed
+
+We'll modify an attribute
+
+.. doctest::
+
+   >>> o.y = 2
+   >>> o.y
+   2
+
+which reactivates it, and markes it as modified, because our
+implementation marked it as modified:
+
+.. doctest::
+
+   >>> o._p_changed
+   True
+
+Now, if fake a commit:
+
+.. doctest::
+
+   >>> jar.fake_commit()
+   >>> o._p_changed
+   False
+
+And deactivate the object:
+
+.. doctest::
+
+   >>> o._p_deactivate()
+   >>> o._p_changed
+
+and then set a variable with a name starting with ``tmp_``,
+The object will be activated, but not marked as modified,
+because our :meth:`__setattr__` implementation  doesn't mark the
+object as changed if the name starts with ``tmp_``:
+
+.. doctest::
+
+   >>> o.tmp_foo = 3
+   >>> o._p_changed
+   False
+   >>> o.tmp_foo
+   3
+
+
+Hooking :meth:`__delattr__``
+############################
+
+The __delattr__ method is called for all attribute
+deletions.  It overrides the attribute deletion support
+inherited from Persistent.
+
+Implementors of :meth:`__delattr__` methods:
+
+1. Must call Persistent._p_delattr first to allow it
+   to handle some attributes and to make sure that the object
+   is activated if necessary, and
+
+2. Must set _p_changed to mark objects as changed.
+
+.. doctest::
+
+   >>> o = VeryPrivate(x=1, y=2, tmp_z=3)
+   >>> o._p_changed
+   False
+   >>> o._p_oid
+   >>> o._p_jar
+   >>> o.x
+   1
+   >>> del o.x
+   >>> o.x
+   Traceback (most recent call last):
+   ...
+   AttributeError: x
+
+Next, we'll save the object in a jar so that we can
+deactivate it:
+
+.. doctest::
+
+   >>> jar = _rememberingJar()
+   >>> jar.add(o)
+   >>> o._p_deactivate()
+   >>> o._p_changed
+
+If we delete an attribute:
+
+.. doctest::
+
+   >>> del o.y
+
+The object is activated.  It is also marked as changed because
+our implementation marked it as changed.
+
+.. doctest::
+
+   >>> o._p_changed
+   True
+   >>> o.y
+   Traceback (most recent call last):
+   ...
+   AttributeError: y
+
+   >>> o.tmp_z
+   3
+
+Now, if fake a commit:
+
+.. doctest::
+
+   >>> jar.fake_commit()
+   >>> o._p_changed
+   False
+
+And deactivate the object:
+
+.. doctest::
+
+   >>> o._p_deactivate()
+   >>> o._p_changed
+
+and then delete a variable with a name starting with ``tmp_``,
+The object will be activated, but not marked as modified,
+because our :meth:`__delattr__` implementation  doesn't mark the
+object as changed if the name starts with ``tmp_``:
+
+.. doctest::
+
+   >>> del o.tmp_z
+   >>> o._p_changed
+   False
+   >>> o.tmp_z
+   Traceback (most recent call last):
+   ...
+   AttributeError: tmp_z

Modified: persistent/trunk/docs/api.rst
===================================================================
--- persistent/trunk/docs/api.rst	2012-06-28 22:49:54 UTC (rev 127158)
+++ persistent/trunk/docs/api.rst	2012-06-28 22:49:58 UTC (rev 127159)
@@ -5,4 +5,5 @@
    :maxdepth: 2
 
    api/interfaces
+   api/attributes
    api/pickling

Modified: persistent/trunk/persistent/tests/test_overriding_attrs.py
===================================================================
--- persistent/trunk/persistent/tests/test_overriding_attrs.py	2012-06-28 22:49:54 UTC (rev 127158)
+++ persistent/trunk/persistent/tests/test_overriding_attrs.py	2012-06-28 22:49:58 UTC (rev 127159)
@@ -13,11 +13,10 @@
 ##############################################################################
 """Overriding attr methods
 
-This module tests and documents, through example, overriding attribute
-access methods.
+Examples for overriding attribute access methods.
 """
 
-from persistent import Persistent # ouch!
+from persistent import Persistent
 
 def _resettingJar():
     from persistent.tests.utils import ResettingJar
@@ -27,47 +26,12 @@
     from persistent.tests.utils import RememberingJar
     return RememberingJar()
 
-class SampleOverridingGetattr(Persistent):
+
+class OverridesGetattr(Persistent):
     """Example of overriding __getattr__
     """
-
     def __getattr__(self, name):
         """Get attributes that can't be gotten the usual way
-
-        The __getattr__ method works pretty much the same for persistent
-        classes as it does for other classes.  No special handling is
-        needed.  If an object is a ghost, then it will be activated before
-        __getattr__ is called.
-
-        In this example, our objects returns a tuple with the attribute
-        name, converted to upper case and the value of _p_changed, for any
-        attribute that isn't handled by the default machinery.
-
-        >>> o = SampleOverridingGetattr()
-        >>> o._p_changed
-        False
-        >>> o._p_oid
-        >>> o._p_jar
-        >>> o.spam
-        ('SPAM', False)
-        >>> o.spam = 1
-        >>> o.spam
-        1
-
-        We'll save the object, so it can be deactivated:
-
-        >>> jar = _resettingJar()
-        >>> jar.add(o)
-        >>> o._p_deactivate()
-        >>> o._p_changed
-
-        And now, if we ask for an attribute it doesn't have,
-
-        >>> o.eggs
-        ('EGGS', False)
-
-        And we see that the object was activated before calling the
-        __getattr__ method.
         """
         # Don't pretend we have any special attributes.
         if name.startswith("__") and name.endswrith("__"):
@@ -75,78 +39,18 @@
         else:
             return name.upper(), self._p_changed
 
-class SampleOverridingGetattributeSetattrAndDelattr(Persistent):
-    """Example of overriding __getattribute__, __setattr__, and __delattr__
 
-    In this example, we'll provide an example that shows how to
-    override the __getattribute__, __setattr__, and __delattr__
-    methods.  We'll create a class that stores it's attributes in a
-    secret dictionary within it's instance dictionary.
-
-    The class will have the policy that variables with names starting
-    with 'tmp_' will be volatile.
-
+class VeryPrivate(Persistent):
+    """Example of overriding __getattribute__, __setattr__, and __delattr__
     """
-
     def __init__(self, **kw):
         self.__dict__['__secret__'] = kw.copy()
 
     def __getattribute__(self, name):
         """Get an attribute value
 
-        The __getattribute__ method is called for all attribute
-        accesses.  It overrides the attribute access support inherited
-        from Persistent.
-
-        Our sample class let's us provide initial values as keyword
-        arguments to the constructor:
-
-        >>> o = SampleOverridingGetattributeSetattrAndDelattr(x=1)
-        >>> o._p_changed
-        0
-        >>> o._p_oid
-        >>> o._p_jar
-        >>> o.x
-        1
-        >>> o.y
-        Traceback (most recent call last):
-        ...
-        AttributeError: y
-
-        Next, we'll save the object in a database so that we can
-        deactivate it:
-
-        >>> jar = _rememberingJar()
-        >>> jar.add(o)
-        >>> o._p_deactivate()
-        >>> o._p_changed
-
-        And we'll get some data:
-
-        >>> o.x
-        1
-
-        which activates the object:
-
-        >>> o._p_changed
-        0
-
-        It works for missing attribes too:
-
-        >>> o._p_deactivate()
-        >>> o._p_changed
-
-        >>> o.y
-        Traceback (most recent call last):
-        ...
-        AttributeError: y
-
-        >>> o._p_changed
-        0
-
         See the very important note in the comment below!
         """
-
         #################################################################
         # IMPORTANT! READ THIS! 8->
         #
@@ -177,84 +81,7 @@
 
     def __setattr__(self, name, value):
         """Set an attribute value
-
-        The __setattr__ method is called for all attribute
-        assignments.  It overrides the attribute assignment support
-        inherited from Persistent.
-
-        Implementors of __setattr__ methods:
-
-        1. Must call Persistent._p_setattr first to allow it
-           to handle some attributes and to make sure that the object
-           is activated if necessary, and
-
-        2. Must set _p_changed to mark objects as changed.
-
-        See the comments in the source below.
-
-        >>> o = SampleOverridingGetattributeSetattrAndDelattr()
-        >>> o._p_changed
-        0
-        >>> o._p_oid
-        >>> o._p_jar
-        >>> o.x
-        Traceback (most recent call last):
-        ...
-        AttributeError: x
-
-        >>> o.x = 1
-        >>> o.x
-        1
-
-        Because the implementation doesn't store attributes directly
-        in the instance dictionary, we don't have a key for the attribute:
-
-        >>> 'x' in o.__dict__
-        False
-
-        Next, we'll give the object a "remembering" jar so we can
-        deactivate it:
-
-        >>> jar = _rememberingJar()
-        >>> jar.add(o)
-        >>> o._p_deactivate()
-        >>> o._p_changed
-
-        We'll modify an attribute
-
-        >>> o.y = 2
-        >>> o.y
-        2
-
-        which reactivates it, and markes it as modified, because our
-        implementation marked it as modified:
-
-        >>> o._p_changed
-        1
-
-        Now, if fake a commit:
-
-        >>> jar.fake_commit()
-        >>> o._p_changed
-        0
-
-        And deactivate the object:
-
-        >>> o._p_deactivate()
-        >>> o._p_changed
-
-        and then set a variable with a name starting with 'tmp_',
-        The object will be activated, but not marked as modified,
-        because our __setattr__ implementation  doesn't mark the
-        object as changed if the name starts with 'tmp_':
-
-        >>> o.tmp_foo = 3
-        >>> o._p_changed
-        0
-        >>> o.tmp_foo
-        3
         """
-
         #################################################################
         # IMPORTANT! READ THIS! 8->
         #
@@ -276,86 +103,7 @@
 
     def __delattr__(self, name):
         """Delete an attribute value
-
-        The __delattr__ method is called for all attribute
-        deletions.  It overrides the attribute deletion support
-        inherited from Persistent.
-
-        Implementors of __delattr__ methods:
-
-        1. Must call Persistent._p_delattr first to allow it
-           to handle some attributes and to make sure that the object
-           is activated if necessary, and
-
-        2. Must set _p_changed to mark objects as changed.
-
-        See the comments in the source below.
-
-        >>> o = SampleOverridingGetattributeSetattrAndDelattr(
-        ...         x=1, y=2, tmp_z=3)
-        >>> o._p_changed
-        0
-        >>> o._p_oid
-        >>> o._p_jar
-        >>> o.x
-        1
-        >>> del o.x
-        >>> o.x
-        Traceback (most recent call last):
-        ...
-        AttributeError: x
-
-        Next, we'll save the object in a jar so that we can
-        deactivate it:
-
-        >>> jar = _rememberingJar()
-        >>> jar.add(o)
-        >>> o._p_deactivate()
-        >>> o._p_changed
-
-        If we delete an attribute:
-
-        >>> del o.y
-
-        The object is activated.  It is also marked as changed because
-        our implementation marked it as changed.
-
-        >>> o._p_changed
-        1
-        >>> o.y
-        Traceback (most recent call last):
-        ...
-        AttributeError: y
-
-        >>> o.tmp_z
-        3
-
-        Now, if fake a commit:
-
-        >>> jar.fake_commit()
-        >>> o._p_changed
-        0
-
-        And deactivate the object:
-
-        >>> o._p_deactivate()
-        >>> o._p_changed
-
-        and then delete a variable with a name starting with 'tmp_',
-        The object will be activated, but not marked as modified,
-        because our __delattr__ implementation  doesn't mark the
-        object as changed if the name starts with 'tmp_':
-
-        >>> del o.tmp_z
-        >>> o._p_changed
-        0
-        >>> o.tmp_z
-        Traceback (most recent call last):
-        ...
-        AttributeError: tmp_z
-
         """
-
         #################################################################
         # IMPORTANT! READ THIS! 8->
         #



More information about the checkins mailing list