[Checkins] SVN: zope.copy/trunk/ Get doctest snippets testable.

Tres Seaver cvs-admin at zope.org
Wed Jun 13 15:23:34 UTC 2012


Log message for revision 126847:
  Get doctest snippets testable.

Changed:
  _U  zope.copy/trunk/
  U   zope.copy/trunk/docs/narr.rst
  A   zope.copy/trunk/src/zope/copy/examples.py

-=-
Modified: zope.copy/trunk/docs/narr.rst
===================================================================
--- zope.copy/trunk/docs/narr.rst	2012-06-13 15:23:27 UTC (rev 126846)
+++ zope.copy/trunk/docs/narr.rst	2012-06-13 15:23:31 UTC (rev 126847)
@@ -50,35 +50,31 @@
 
 So, here is a simple object that stores a boolean on a special object.
 
-.. doctest::
+.. literalinclude:: ../src/zope/copy/examples.py
+   :pyobject: Demo
+   :prepend: # zope.copy.examples.Demo
 
-    >>> class Demo(object):
-    ...     _frozen = None
-    ...     def isFrozen(self):
-    ...         return self._frozen is not None
-    ...     def freeze(self):
-    ...         self._frozen = Data()
-    ...
-    >>> class Data(object):
-    ...     pass
-    ...
+.. literalinclude:: ../src/zope/copy/examples.py
+   :pyobject: Data
+   :prepend: # zope.copy.examples.Data
 
 Here's what happens if we copy one of these objects without a copy hook.
 
 .. doctest::
 
-    >>> original = Demo()
-    >>> original.isFrozen()
-    False
-    >>> original.freeze()
-    >>> original.isFrozen()
-    True
-    >>> import zope.copy
-    >>> copy = zope.copy.copy(original)
-    >>> copy is original
-    False
-    >>> copy.isFrozen()
-    True
+   >>> from zope.copy.examples import Demo, Data
+   >>> original = Demo()
+   >>> original.isFrozen()
+   False
+   >>> original.freeze()
+   >>> original.isFrozen()
+   True
+   >>> import zope.copy
+   >>> copy = zope.copy.copy(original)
+   >>> copy is original
+   False
+   >>> copy.isFrozen()
+   True
 
 Now let's make a super-simple copy hook that always returns None, no
 matter what the top-level object being copied is.  We'll register it and
@@ -86,23 +82,23 @@
 
 .. doctest::
 
-    >>> import zope.component
-    >>> import zope.interface
-    >>> import zope.copy.interfaces
-    >>> def _factory(obj, register):
-    ...     return None
-    >>> @zope.component.adapter(Data)
-    ... @zope.interface.implementer(zope.copy.interfaces.ICopyHook)
-    ... def data_copyfactory(obj):
-    ...     return _factory
-    ...
+   >>> import zope.component
+   >>> import zope.interface
+   >>> import zope.copy.interfaces
+   >>> def _factory(obj, register):
+   ...     return None
+   >>> @zope.component.adapter(Data)
+   ... @zope.interface.implementer(zope.copy.interfaces.ICopyHook)
+   ... def data_copyfactory(obj):
+   ...     return _factory
+   ...
 
-    >>> zope.component.provideAdapter(data_copyfactory)
-    >>> copy2 = zope.copy.copy(original)
-    >>> copy2 is original
-    False
-    >>> copy2.isFrozen()
-    False
+   >>> zope.component.provideAdapter(data_copyfactory)
+   >>> copy2 = zope.copy.copy(original)
+   >>> copy2 is original
+   False
+   >>> copy2.isFrozen()
+   False
 
 Much better.
 
@@ -118,47 +114,44 @@
 Imagine an object with a subobject that is "located" (i.e., zope.location) on
 the parent and should be replaced whenever the main object is copied.
 
+.. literalinclude:: ../src/zope/copy/examples.py
+   :pyobject: Subobject
+   :prepend: # zope.copy.examples.Subobject
+
 .. doctest::
 
-    >>> import zope.location.location
-    >>> class Subobject(zope.location.location.Location):
-    ...     def __init__(self):
-    ...         self.counter = 0
-    ...     def __call__(self):
-    ...         res = self.counter
-    ...         self.counter += 1
-    ...         return res
-    ...
-    >>> o = zope.location.location.Location()
-    >>> s = Subobject()
-    >>> o.subobject = s
-    >>> zope.location.location.locate(s, o, 'subobject')
-    >>> s.__parent__ is o
-    True
-    >>> o.subobject()
-    0
-    >>> o.subobject()
-    1
-    >>> o.subobject()
-    2
+   >>> import zope.location.location
+   >>> from zope.copy.examples import Subobject
+   >>> o = zope.location.location.Location()
+   >>> s = Subobject()
+   >>> o.subobject = s
+   >>> zope.location.location.locate(s, o, 'subobject')
+   >>> s.__parent__ is o
+   True
+   >>> o.subobject()
+   0
+   >>> o.subobject()
+   1
+   >>> o.subobject()
+   2
 
 Without an ICopyHook, this will simply duplicate the subobject, with correct
 new pointers.
 
 .. doctest::
 
-    >>> c = zope.copy.copy(o)
-    >>> c.subobject.__parent__ is c
-    True
+   >>> c = zope.copy.copy(o)
+   >>> c.subobject.__parent__ is c
+   True
 
 Note that the subobject has also copied state.
 
 .. doctest::
 
-    >>> c.subobject()
-    3
-    >>> o.subobject()
-    3
+   >>> c.subobject()
+   3
+   >>> o.subobject()
+   3
 
 Our goal will be to make the counters restart when they are copied.  We'll do
 that with a copy hook.
@@ -172,34 +165,34 @@
 
 .. doctest::
 
-    >>> import zope.component
-    >>> import zope.interface
-    >>> import zope.copy.interfaces
-    >>> @zope.component.adapter(Subobject)
-    ... @zope.interface.implementer(zope.copy.interfaces.ICopyHook)
-    ... def subobject_copyfactory(original):
-    ...     def factory(obj, register):
-    ...         obj = Subobject()
-    ...         def reparent(translate):
-    ...             obj.__parent__ = translate(original.__parent__)
-    ...         register(reparent)
-    ...         return obj
-    ...     return factory
-    ...
-    >>> zope.component.provideAdapter(subobject_copyfactory)
+   >>> import zope.component
+   >>> import zope.interface
+   >>> import zope.copy.interfaces
+   >>> @zope.component.adapter(Subobject)
+   ... @zope.interface.implementer(zope.copy.interfaces.ICopyHook)
+   ... def subobject_copyfactory(original):
+   ...     def factory(obj, register):
+   ...         obj = Subobject()
+   ...         def reparent(translate):
+   ...             obj.__parent__ = translate(original.__parent__)
+   ...         register(reparent)
+   ...         return obj
+   ...     return factory
+   ...
+   >>> zope.component.provideAdapter(subobject_copyfactory)
 
 Now when we copy, the new subobject will have the correct, revised __parent__,
 but will be otherwise reset (here, just the counter)
 
 .. doctest::
 
-    >>> c = zope.copy.copy(o)
-    >>> c.subobject.__parent__ is c
-    True
-    >>> c.subobject()
-    0
-    >>> o.subobject()
-    4
+   >>> c = zope.copy.copy(o)
+   >>> c.subobject.__parent__ is c
+   True
+   >>> c.subobject()
+   0
+   >>> o.subobject()
+   4
 
 Resuming recursive copy
 -----------------------
@@ -213,23 +206,23 @@
 
 .. doctest::
 
-    >>> root = zope.location.location.Location()
+   >>> root = zope.location.location.Location()
 
-    >>> content = zope.location.location.Location()
-    >>> zope.location.location.locate(content, root, 'content')
+   >>> content = zope.location.location.Location()
+   >>> zope.location.location.locate(content, root, 'content')
 
-    >>> image = zope.location.location.Location()
-    >>> zope.location.location.locate(image, root, 'image.jpg')
+   >>> image = zope.location.location.Location()
+   >>> zope.location.location.locate(image, root, 'image.jpg')
 
-    >>> content.cover = image
+   >>> content.cover = image
   
 Without any hooks, the image object will be cloned as well:
 
 .. doctest::
 
-    >>> new = zope.copy.copy(content)
-    >>> new.cover is image
-    False
+   >>> new = zope.copy.copy(content)
+   >>> new.cover is image
+   False
 
 That's not what we'd expect though, so, let's provide a copy hook
 to deal with that. The copy hook for this case is provided by zope.location
@@ -238,16 +231,16 @@
 
 .. doctest::
 
-    >>> @zope.component.adapter(zope.location.interfaces.ILocation)
-    ... @zope.interface.implementer(zope.copy.interfaces.ICopyHook)
-    ... def location_copyfactory(obj):
-    ...     def factory(location, register):
-    ...         if not zope.location.location.inside(obj, location):
-    ...             return obj
-    ...         raise zope.copy.interfaces.ResumeCopy
-    ...     return factory
-    ...
-    >>> zope.component.provideAdapter(location_copyfactory)
+   >>> @zope.component.adapter(zope.location.interfaces.ILocation)
+   ... @zope.interface.implementer(zope.copy.interfaces.ICopyHook)
+   ... def location_copyfactory(obj):
+   ...     def factory(location, register):
+   ...         if not zope.location.location.inside(obj, location):
+   ...             return obj
+   ...         raise zope.copy.interfaces.ResumeCopy
+   ...     return factory
+   ...
+   >>> zope.component.provideAdapter(location_copyfactory)
 
 This hook returns objects as they are if they are not located inside
 object that's being copied, or raises ResumeCopy to signal that the
@@ -255,9 +248,9 @@
 
 .. doctest::
 
-    >>> new = zope.copy.copy(content)
-    >>> new.cover is image
-    True
+   >>> new = zope.copy.copy(content)
+   >>> new.cover is image
+   True
 
 Much better :-)
 
@@ -273,10 +266,10 @@
 
 .. doctest::
 
-    >>> root = zope.location.location.Location()
-    >>> folder = zope.location.location.Location()
-    >>> folder.__name__ = 'files'
-    >>> folder.__parent__ = root
+   >>> root = zope.location.location.Location()
+   >>> folder = zope.location.location.Location()
+   >>> folder.__name__ = 'files'
+   >>> folder.__parent__ = root
 
 The :func:`clone` function will leave those attributes as is. Note that the
 referenced __parent__ won't be cloned, as we registered a hook for locations
@@ -284,11 +277,11 @@
 
 .. doctest::
 
-    >>> folder_clone = zope.copy.clone(folder)
-    >>> folder_clone.__parent__ is root
-    True
-    >>> folder_clone.__name__ == 'files'
-    True
+   >>> folder_clone = zope.copy.clone(folder)
+   >>> folder_clone.__parent__ is root
+   True
+   >>> folder_clone.__name__ == 'files'
+   True
 
 However, the :func:`copy` function will reset those attributes to None, as
 we will probably want to place our object into another container with
@@ -296,11 +289,11 @@
 
 .. doctest::
 
-    >>> folder_clone = zope.copy.copy(folder)
-    >>> folder_clone.__parent__ is None
-    True
-    >>> folder_clone.__name__ is None
-    True
+   >>> folder_clone = zope.copy.copy(folder)
+   >>> folder_clone.__parent__ is None
+   True
+   >>> folder_clone.__name__ is None
+   True
 
 Notice, that if your object doesn't have __parent__ and __name__
 attributes at all, or these attributes could'nt be got or set because of
@@ -310,53 +303,46 @@
 
 It won't set them if original object doesn't have them:
 
+.. literalinclude:: ../src/zope/copy/examples.py
+   :pyobject: Something
+   :prepend: # zope.copy.examples.Something
+
 .. doctest::
 
-    >>> class Something(object):
-    ...     pass
+   >>> from zope.copy.examples import Something
+   >>> s = Something()
+   >>> s_copy = zope.copy.copy(s)
+   >>> s_copy.__parent__
+   Traceback (most recent call last):
+   ...
+   AttributeError: ...
+   >>> s_copy.__name__
+   Traceback (most recent call last):
+   ...
+   AttributeError: ...
 
-    >>> s = Something()
-    >>> s_copy = zope.copy.copy(s)
-    >>> s_copy.__parent__
-    Traceback (most recent call last):
-    ...
-    AttributeError: ...
-    >>> s_copy.__name__
-    Traceback (most recent call last):
-    ...
-    AttributeError: ...
-
 And it won't fail if original object has them but doesn't allow to set
 them.
 
-.. doctest::
+.. literalinclude:: ../src/zope/copy/examples.py
+   :pyobject: Other
+   :prepend: # zope.copy.examples.Other
 
-    >>> root = object()
-    >>> class Something(object):
-    ...
-    ...     @apply
-    ...     def __name__():
-    ...         def fget(self):
-    ...             return 'something'
-    ...         def fset(self, value):
-    ...             raise AttributeError
-    ...         return property(fget, fset)
-    ...
-    ...     @apply
-    ...     def __parent__():
-    ...         def fget(self):
-    ...             return root
-    ...         def fset(self, value):
-    ...             raise AttributeError
-    ...         return property(fget, fset)
+.. literalinclude:: ../src/zope/copy/examples.py
+   :pyobject: root
+   :prepend: # zope.copy.examples.root
 
-    >>> s = Something()
-    >>> s_copy = zope.copy.copy(s)
-    >>> s_copy.__parent__ is root
-    True
-    >>> s_copy.__name__ == 'something'
-    True
+.. doctest::
 
+   >>> from zope.copy.examples import Other
+   >>> from zope.copy.examples import root
+   >>> s = Other()
+   >>> s_copy = zope.copy.copy(s)
+   >>> s_copy.__parent__ is root
+   True
+   >>> s_copy.__name__ == 'something'
+   True
+
 :class:`~zope.location.pickling.LocationCopyHook`
 -------------------------------------------------
 
@@ -375,30 +361,32 @@
 
 .. doctest::
 
-  >>> from zope.location.location import Location, locate
-  >>> root = Location()
-  >>> page = Location()
-  >>> locate(page, root, 'page')
-  >>> image = Location()
-  >>> locate(page, root, 'image')
-  >>> page.thumbnail = image
+   >>> from zope.component.globalregistry import base
+   >>> base.__init__('base') # blow away previous registrations
+   >>> from zope.location.location import Location, locate
+   >>> root = Location()
+   >>> page = Location()
+   >>> locate(page, root, 'page')
+   >>> image = Location()
+   >>> locate(page, root, 'image')
+   >>> page.thumbnail = image
 
-  >>> from zope.copy import copy
-  >>> page_copy = copy(page)
-  >>> page_copy.thumbnail is image
-  False
+   >>> from zope.copy import copy
+   >>> page_copy = copy(page)
+   >>> page_copy.thumbnail is image
+   False
 
 But if we will provide a hook, the attribute will point to the
 original object as we might want.
 
 .. doctest::
 
-  >>> from zope.component import provideAdapter
-  >>> from zope.location.pickling import LocationCopyHook
-  >>> from zope.location.interfaces import ILocation
-  >>> provideAdapter(LocationCopyHook, (ILocation,))
+   >>> from zope.component import provideAdapter
+   >>> from zope.location.pickling import LocationCopyHook
+   >>> from zope.location.interfaces import ILocation
+   >>> provideAdapter(LocationCopyHook, (ILocation,))
 
-  >>> from zope.copy import copy
-  >>> page_copy = copy(page)
-  >>> page_copy.thumbnail is image
-  True
+   >>> from zope.copy import copy
+   >>> page_copy = copy(page)
+   >>> page_copy.thumbnail is image
+   True

Added: zope.copy/trunk/src/zope/copy/examples.py
===================================================================
--- zope.copy/trunk/src/zope/copy/examples.py	                        (rev 0)
+++ zope.copy/trunk/src/zope/copy/examples.py	2012-06-13 15:23:31 UTC (rev 126847)
@@ -0,0 +1,65 @@
+##############################################################################
+#
+# Copyright (c) 2012 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" Make example classes available at module scope.
+"""
+import zope.location.location
+
+class Demo(object):
+
+    _frozen = None
+
+    def isFrozen(self):
+        return self._frozen is not None
+
+    def freeze(self):
+        self._frozen = Data()
+
+
+class Data(object):
+    pass
+
+
+class Subobject(zope.location.location.Location):
+
+    def __init__(self):
+        self.counter = 0
+
+    def __call__(self):
+        res = self.counter
+        self.counter += 1
+        return res
+
+
+class Something(object):
+    pass
+
+
+root = object()
+
+
+class Other(object):
+    @apply
+    def __name__():
+        def fget(self):
+            return 'something'
+        def fset(self, value):
+            raise AttributeError
+        return property(fget, fset)
+    @apply
+    def __parent__():
+        def fget(self):
+            return root
+        def fset(self, value):
+            raise AttributeError
+        return property(fget, fset)



More information about the checkins mailing list