[Checkins] SVN: z3c.persistentfactory/tags/0.3/ Tag 0.3 release

Ross Patterson me at rpatterson.net
Thu Apr 10 16:07:55 EDT 2008


Log message for revision 85224:
  Tag 0.3 release

Changed:
  A   z3c.persistentfactory/tags/0.3/
  D   z3c.persistentfactory/tags/0.3/docs/HISTORY.txt
  A   z3c.persistentfactory/tags/0.3/docs/HISTORY.txt
  D   z3c.persistentfactory/tags/0.3/setup.py
  A   z3c.persistentfactory/tags/0.3/setup.py
  D   z3c.persistentfactory/tags/0.3/z3c/persistentfactory/README.txt
  A   z3c.persistentfactory/tags/0.3/z3c/persistentfactory/README.txt
  D   z3c.persistentfactory/tags/0.3/z3c/persistentfactory/declarations.py
  A   z3c.persistentfactory/tags/0.3/z3c/persistentfactory/declarations.py
  D   z3c.persistentfactory/tags/0.3/z3c/persistentfactory/declarations.txt
  A   z3c.persistentfactory/tags/0.3/z3c/persistentfactory/declarations.txt
  D   z3c.persistentfactory/tags/0.3/z3c/persistentfactory/factory.py
  A   z3c.persistentfactory/tags/0.3/z3c/persistentfactory/factory.py
  A   z3c.persistentfactory/tags/0.3/z3c/persistentfactory/factory.txt
  D   z3c.persistentfactory/tags/0.3/z3c/persistentfactory/testing.py
  A   z3c.persistentfactory/tags/0.3/z3c/persistentfactory/testing.py
  D   z3c.persistentfactory/tags/0.3/z3c/persistentfactory/tests.py
  A   z3c.persistentfactory/tags/0.3/z3c/persistentfactory/tests.py

-=-
Copied: z3c.persistentfactory/tags/0.3 (from rev 85202, z3c.persistentfactory/trunk)

Deleted: z3c.persistentfactory/tags/0.3/docs/HISTORY.txt
===================================================================
--- z3c.persistentfactory/trunk/docs/HISTORY.txt	2008-04-09 20:55:25 UTC (rev 85202)
+++ z3c.persistentfactory/tags/0.3/docs/HISTORY.txt	2008-04-10 20:07:55 UTC (rev 85224)
@@ -1,11 +0,0 @@
-Changelog
-=========
-
-0.2 - Unreleased
-----------------
-
-0.1 - 2008-04-08
-----------------
-
-* Initial release
-

Copied: z3c.persistentfactory/tags/0.3/docs/HISTORY.txt (from rev 85222, z3c.persistentfactory/trunk/docs/HISTORY.txt)
===================================================================
--- z3c.persistentfactory/tags/0.3/docs/HISTORY.txt	                        (rev 0)
+++ z3c.persistentfactory/tags/0.3/docs/HISTORY.txt	2008-04-10 20:07:55 UTC (rev 85224)
@@ -0,0 +1,22 @@
+Changelog
+=========
+
+0.3 - 2008-04-10
+----------------
+
+* Declarer's declarations don't track with changes to the
+  class method's declarations.
+
+* Isolate declarations on the declarer's class from declarations on
+  instances.
+
+0.2 - 2008-04-09
+----------------
+
+* Improve README.txt with clearer examples
+
+0.1 - 2008-04-08
+----------------
+
+* Initial release
+

Deleted: z3c.persistentfactory/tags/0.3/setup.py
===================================================================
--- z3c.persistentfactory/trunk/setup.py	2008-04-09 20:55:25 UTC (rev 85202)
+++ z3c.persistentfactory/tags/0.3/setup.py	2008-04-10 20:07:55 UTC (rev 85224)
@@ -1,38 +0,0 @@
-from setuptools import setup, find_packages
-import os
-
-version = '0.2'
-
-setup(name='z3c.persistentfactory',
-      version=version,
-      description=(
-          "Wrap instance methods in persistent factory wrappers for "
-          "using instance methods as ZCA factories."), 
-      long_description=(open(os.path.join(
-          "z3c", "persistentfactory", "README.txt")).read() + "\n" +
-                        open(os.path.join("docs", "HISTORY.txt")).read()),
-      # Get more strings from http://www.python.org/pypi?%3Aaction=list_classifiers
-      classifiers=[
-        "Programming Language :: Python",
-        "Topic :: Software Development :: Libraries :: Python Modules",
-        ],
-      keywords='',
-      author='Ross Patterson',
-      author_email='me at rpatterson.net',
-      url='http://pypi.python.org/pypi/z3c.persistentfactory',
-      license='ZPL',
-      packages=find_packages(exclude=['ez_setup']),
-      namespace_packages=['z3c'],
-      include_package_data=True,
-      zip_safe=False,
-      install_requires=[
-          'setuptools',
-          # -*- Extra requirements: -*-
-          'zope.interface',
-          'zope.component',
-          'ZODB3',
-      ],
-      entry_points="""
-      # -*- Entry points: -*-
-      """,
-      )

Copied: z3c.persistentfactory/tags/0.3/setup.py (from rev 85223, z3c.persistentfactory/trunk/setup.py)
===================================================================
--- z3c.persistentfactory/tags/0.3/setup.py	                        (rev 0)
+++ z3c.persistentfactory/tags/0.3/setup.py	2008-04-10 20:07:55 UTC (rev 85224)
@@ -0,0 +1,38 @@
+from setuptools import setup, find_packages
+import os
+
+version = '0.3'
+
+setup(name='z3c.persistentfactory',
+      version=version,
+      description=(
+          "Wrap instance methods in persistent factory wrappers for "
+          "using instance methods as ZCA factories."), 
+      long_description=(open(os.path.join(
+          "z3c", "persistentfactory", "README.txt")).read() + "\n" +
+                        open(os.path.join("docs", "HISTORY.txt")).read()),
+      # Get more strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[
+        "Programming Language :: Python",
+        "Topic :: Software Development :: Libraries :: Python Modules",
+        ],
+      keywords='',
+      author='Ross Patterson',
+      author_email='me at rpatterson.net',
+      url='http://pypi.python.org/pypi/z3c.persistentfactory',
+      license='ZPL',
+      packages=find_packages(exclude=['ez_setup']),
+      namespace_packages=['z3c'],
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=[
+          'setuptools',
+          # -*- Extra requirements: -*-
+          'zope.interface',
+          'zope.component',
+          'ZODB3',
+      ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )

Deleted: z3c.persistentfactory/tags/0.3/z3c/persistentfactory/README.txt
===================================================================
--- z3c.persistentfactory/trunk/z3c/persistentfactory/README.txt	2008-04-09 20:55:25 UTC (rev 85202)
+++ z3c.persistentfactory/tags/0.3/z3c/persistentfactory/README.txt	2008-04-10 20:07:55 UTC (rev 85224)
@@ -1,195 +0,0 @@
-;-*-Doctest-*-
-
-====================
-Persistent Factories
-====================
-
-z3c.persistentfactory provides a PersistentFactory class that wraps a
-method in a persistent wrapper.  It also provides a function decorator
-for use on class method definitions such that a persistent factory
-will be used when the method is accessed on instance of the class.
-
-Also see declarartions.txt for details about a mixin Declarer class
-for classes implementing callable instances whose declarations should
-pickle and persist correctly.
-
-Factory
-=======
-
-The factory module provides a persistent declarer class for creating
-callable objects wrapping a instance method as factories in the
-persistent registry.
-
-Create an object with a method that has declarations.
-
-    >>> from z3c.persistentfactory import testing
-    >>> bar = testing.Bar()
-
-Verify that the instance method has declarations.
-
-    >>> from zope import interface, component
-    >>> tuple(interface.implementedBy(bar.factory))
-    (<InterfaceClass z3c.persistentfactory.testing.IBar>,)
-    >>> component.adaptedBy(bar.factory)
-    (<InterfaceClass z3c.persistentfactory.testing.IFoo>,)
-
-Wrap the instance method in a persistent factory.
-
-    >>> from z3c.persistentfactory import factory
-    >>> bar_factory = factory.PersistentFactory(bar.factory)
-
-Pickle and unpickle the factory to verify everything is pickleable.
-
-    >>> import pickle
-    >>> bar_factory = pickle.loads(pickle.dumps(bar_factory))
-
-The factory's __call__ method is the original instance method of the
-original object, not a method of the persistent factory object.
-
-    >>> bar_factory.__call__
-    <bound method Bar.factory of
-    <z3c.persistentfactory.testing.Bar object at ...>>
-    >>> bar_factory.__call__.im_self.__class__ is bar.__class__
-    True
-
-The factory is callable.
-
-    >>> bar_factory()
-    <z3c.persistentfactory.testing.Bar object at ...>
-
-The factory has the same declarations as the original method.
-
-    >>> tuple(interface.implementedBy(bar_factory))
-    (<InterfaceClass z3c.persistentfactory.testing.IBar>,)
-    >>> component.adaptedBy(bar_factory)
-    (<InterfaceClass z3c.persistentfactory.testing.IFoo>,)
-
-If the wrapped method's declarations haven't been overridden, then
-changes to the wrapped method's adapts declarations are reflected in
-the factory.  Unfortunately, the zope.interface implementation for
-checking implementer declarations checks the factory's instance
-dictionary directly, so changes to the wrapped method's implements
-declarations aren't reflected in the factory.  This means that any
-changes to the wrapped methods implements declaration that need to be
-reflected in existing persistent factories will require migrating the
-existing factories.
-
-    >>> _ = interface.implementer(testing.IFoo)(bar.factory.im_func)
-    >>> _ = component.adapter(testing.IBar)(bar.factory.im_func)
-
-    >>> tuple(interface.implementedBy(bar.factory))
-    (<InterfaceClass z3c.persistentfactory.testing.IFoo>,)
-    >>> component.adaptedBy(bar.factory)
-    (<InterfaceClass z3c.persistentfactory.testing.IBar>,)
-
-    >>> tuple(interface.implementedBy(bar_factory))
-    (<InterfaceClass z3c.persistentfactory.testing.IBar>,)
-    >>> component.adaptedBy(bar_factory)
-    (<InterfaceClass z3c.persistentfactory.testing.IBar>,)
-
-The wrapped method's declarations can be overridden in the factory.
-
-    >>> _ = interface.implementer(testing.IBaz)(bar_factory)
-    >>> _ = component.adapter(testing.IQux)(bar_factory)
-
-    >>> tuple(interface.implementedBy(bar_factory))
-    (<InterfaceClass z3c.persistentfactory.testing.IBaz>,)
-    >>> component.adaptedBy(bar_factory)
-    (<InterfaceClass z3c.persistentfactory.testing.IQux>,)
-
-Overriding the wrapped method's declarations in the factory doesn't
-modify the declarations on the wrapped method.
-
-    >>> tuple(interface.implementedBy(bar.factory))
-    (<InterfaceClass z3c.persistentfactory.testing.IFoo>,)
-    >>> component.adaptedBy(bar.factory)
-    (<InterfaceClass z3c.persistentfactory.testing.IBar>,)
-
-However, Once the wrapped method's declarations have been overriden in
-the factory, the factory no longer reflects any changes in the wrapped
-method's declarations.
-
-    >>> _ = interface.implementer(testing.IQux)(bar.factory.im_func)
-    >>> _ = component.adapter(testing.IBaz)(bar.factory.im_func)
-
-    >>> tuple(interface.implementedBy(bar.factory))
-    (<InterfaceClass z3c.persistentfactory.testing.IQux>,)
-    >>> component.adaptedBy(bar.factory)
-    (<InterfaceClass z3c.persistentfactory.testing.IBaz>,)
-
-    >>> tuple(interface.implementedBy(bar_factory))
-    (<InterfaceClass z3c.persistentfactory.testing.IBaz>,)
-    >>> component.adaptedBy(bar_factory)
-    (<InterfaceClass z3c.persistentfactory.testing.IQux>,)
-
-Decorator
-=========
-
-A decorator is provided that will return the decorated method wrapped
-in a persistent factory when the method is accessed on an instance.
-
-The Baz class uses the decorator in the python code.  Note that the
-factory decorator must come before the declaration decorators so that
-it will be run last and will reflect the declarations.
-
-    >>> baz = testing.Baz()
-
-On an instance, the method is replaced with a persistent factory on
-first access.
-
-    >>> baz.factory
-    <z3c.persistentfactory.factory.PersistentFactory
-    object at ...>
-
-Pickle and unpickle the object to verify everything is pickleable.
-
-    >>> baz = pickle.loads(pickle.dumps(baz))
-
-The factory is the same object on subsequent accesses.
-
-    >>> baz.factory is baz.factory
-    True
-
-The factory's __call__ method is an instance method of the original
-object, not a method of the persistent factory object.
-
-    >>> baz.factory.__call__
-    <bound method Baz.factory of
-    <z3c.persistentfactory.testing.Baz object at ...>>
-
-The factory is callable and calls the wrapped method.
-
-    >>> baz.factory()
-    <z3c.persistentfactory.testing.Baz object at ...>
-
-The declarations of the factory reflect the declarations on the
-wrapped method.
-
-    >>> tuple(interface.implementedBy(baz.factory))
-    (<InterfaceClass z3c.persistentfactory.testing.IBar>,)
-    >>> component.adaptedBy(baz.factory)
-    (<InterfaceClass z3c.persistentfactory.testing.IFoo>,)
-
-The declarations can be overridden in the factory.
-
-    >>> _ = interface.implementer(testing.IFoo)(baz.factory)
-    >>> _ = component.adapter(testing.IBar)(baz.factory)
-
-Pickle and unpickle again to verify the pickleability of factory
-declarations.
-
-    >>> baz = pickle.loads(pickle.dumps(baz))
-
-The declaration changes are reflected on the factory.
-
-    >>> tuple(interface.implementedBy(baz.factory))
-    (<InterfaceClass z3c.persistentfactory.testing.IFoo>,)
-    >>> component.adaptedBy(baz.factory)
-    (<InterfaceClass z3c.persistentfactory.testing.IBar>,)
-
-But the class methods declarations are unaffected.
-
-    >>> tuple(interface.implementedBy(testing.Baz.factory))
-    (<InterfaceClass z3c.persistentfactory.testing.IBar>,)
-    >>> component.adaptedBy(testing.Baz.factory)
-    (<InterfaceClass z3c.persistentfactory.testing.IFoo>,)

Copied: z3c.persistentfactory/tags/0.3/z3c/persistentfactory/README.txt (from rev 85203, z3c.persistentfactory/trunk/z3c/persistentfactory/README.txt)
===================================================================
--- z3c.persistentfactory/tags/0.3/z3c/persistentfactory/README.txt	                        (rev 0)
+++ z3c.persistentfactory/tags/0.3/z3c/persistentfactory/README.txt	2008-04-10 20:07:55 UTC (rev 85224)
@@ -0,0 +1,92 @@
+;-*-Doctest-*-
+
+=====================
+z3c.persistentfactory
+=====================
+
+The ZCA and the ZODB are a good combination where components require
+persistent state.  ZCA factories or handlers typically retrieve any
+persistent state required from the persistent objects being adapted.
+If the persistent state required is not specific to the objects being
+adapted, a common solution is to register a persistent utility which
+is then looked up in the factory or handler.  The persistent utility
+approach requires, however, that the one appropriate utility is looked
+up which requires support in the ZCA registrations either in the
+interface provided or the utility name.
+
+In some cases, however, it is more consistent with the object oriented
+semantics of Python and the ZCA to think of the factory or handler as
+an instance method of a persistent object.  With this approach the
+non-context specific persistent state can be accessed on self.
+
+Instance Method Event Handler
+=============================
+
+One example where this may be useful is where some non-context
+persistent state is tightly coupled to some event handlers in such a
+way where instance methods are better semantics.
+
+The Baz class uses the decorator in the python code.  Note that the
+factory decorator must come before the declaration decorators so that
+it will be run last and will reflect the declarations.
+
+    >>> from z3c.persistentfactory import testing
+    >>> baz = testing.Baz()
+
+Register the persistent factory wrapped instance method as a handler.
+
+    >>> from zope import component
+    >>> component.provideHandler(factory=baz.factory)
+ 
+The method adapts IFoo, so create an object providing IFoo to be used
+as the event.
+
+    >>> component.adaptedBy(baz.factory)
+    (<InterfaceClass z3c.persistentfactory.testing.IFoo>,)
+
+    >>> from zope import interface
+    >>> foo = testing.Foo()
+    >>> interface.alsoProvides(foo, testing.IFoo)
+
+When the event is notified, the method is called with the event as an
+argument.
+
+    >>> import zope.event
+    >>> zope.event.notify(foo)
+    Called <bound method Baz.factory of
+    <z3c.persistentfactory.testing.Baz object at ...>>
+      args: (<z3c.persistentfactory.testing.Foo object at ...>,)
+      kwargs: {}
+
+Instance Method Adapter Factory
+===============================
+
+Another example is where an adapter factory needs to look up
+persistent state specific to the objects being adapted but where that
+state can't be stored on the adapted objects them selves.  The
+component storing the shared persistent state can register one of it's
+instance methods as the adapter factory which will look up the
+necessary persistent state on self.
+
+Register the persistent factory wrapped instance method as an adapter
+factory.
+
+    >>> component.provideAdapter(factory=baz.factory)
+ 
+The method implements IBar.
+
+    >>> tuple(interface.implementedBy(baz.factory))
+    (<InterfaceClass z3c.persistentfactory.testing.IBar>,)
+
+When the adapter is looked up, the metod is called with the object to
+be adapted as an argument.
+
+    >>> result = component.getAdapter(foo, testing.IBar)
+    Called <bound method Baz.factory of
+    <z3c.persistentfactory.testing.Baz object at ...>>
+      args: (<z3c.persistentfactory.testing.Foo object at ...>,)
+      kwargs: {}
+    >>> result
+    (<bound method Baz.factory of
+     <z3c.persistentfactory.testing.Baz object at ...>>,
+     (<z3c.persistentfactory.testing.Foo object at ...>,), {})

Deleted: z3c.persistentfactory/tags/0.3/z3c/persistentfactory/declarations.py
===================================================================
--- z3c.persistentfactory/trunk/z3c/persistentfactory/declarations.py	2008-04-09 20:55:25 UTC (rev 85202)
+++ z3c.persistentfactory/tags/0.3/z3c/persistentfactory/declarations.py	2008-04-10 20:07:55 UTC (rev 85224)
@@ -1,40 +0,0 @@
-from zope import interface, component
-from zope.interface import declarations
-
-class Implements(declarations.Implements):
-    """A pickleable implements declaration"""
-
-    def __reduce__(self):
-        return Implements, self.__bases__
-
-class ImplementsDescriptor(object):
-
-    def __get__(self, instance, owner):
-        if instance is None:
-            raise AttributeError('__implemented__')
-
-        if '__implemented__' not in instance.__dict__:
-            instance.__implemented__ = interface.implementedBy(
-                instance.__call__)
-        return instance.__dict__['__implemented__']
-    
-    def __set__(self, instance, value):
-        instance.__dict__['__implemented__'] = Implements(*value)
-
-    def __delete__(self, instance):
-        if '__implemented__' not in instance.__dict__:
-            raise AttributeError('__implemented__')
-        del instance.__dict__['__implemented__']
-
-class AdaptsDescriptor(object):
-
-    def __get__(self, instance, owner):
-        if instance is None:
-            raise AttributeError('__implemented__')
-
-        return component.adaptedBy(instance.__call__)
-
-class Declarer(object):
-
-    __implemented__ = ImplementsDescriptor()
-    __component_adapts__ = AdaptsDescriptor()

Copied: z3c.persistentfactory/tags/0.3/z3c/persistentfactory/declarations.py (from rev 85221, z3c.persistentfactory/trunk/z3c/persistentfactory/declarations.py)
===================================================================
--- z3c.persistentfactory/tags/0.3/z3c/persistentfactory/declarations.py	                        (rev 0)
+++ z3c.persistentfactory/tags/0.3/z3c/persistentfactory/declarations.py	2008-04-10 20:07:55 UTC (rev 85224)
@@ -0,0 +1,46 @@
+from zope import interface, component
+from zope.interface import declarations
+
+class Implements(declarations.Implements):
+    """A pickleable implements declaration"""
+
+    def __reduce__(self):
+        return Implements, self.__bases__
+
+class ImplementsDescriptor(declarations.Implements):
+
+    def __get__(self, instance, owner):
+        if instance is None:
+            return self
+
+        if '__implemented__' not in instance.__dict__:
+            raise AttributeError('__implemented__')
+
+        return instance.__dict__['__implemented__']
+    
+    def __set__(self, instance, value):
+        if not isinstance(value, Implements):
+            value = Implements(*value)
+
+        instance.__dict__['__implemented__'] = value
+
+    def __delete__(self, instance):
+        if '__implemented__' not in instance.__dict__:
+            raise AttributeError('__implemented__')
+
+        del instance.__dict__['__implemented__']
+
+class Declarer(object):
+
+    def __init__(self, *args, **kw):
+        self.__implemented__ = interface.implementedBy(
+            self.__call__.im_func)
+        self.__component_adapts__ = component.adaptedBy(
+            self.__call__.im_func)
+        super(Declarer, self).__init__(*args, **kw)
+
+    def __call__(self):
+        return self
+
+implemented = interface.implementedBy(Declarer)
+Declarer.__implemented__ = ImplementsDescriptor(*implemented)

Deleted: z3c.persistentfactory/tags/0.3/z3c/persistentfactory/declarations.txt
===================================================================
--- z3c.persistentfactory/trunk/z3c/persistentfactory/declarations.txt	2008-04-09 20:55:25 UTC (rev 85202)
+++ z3c.persistentfactory/tags/0.3/z3c/persistentfactory/declarations.txt	2008-04-10 20:07:55 UTC (rev 85224)
@@ -1,73 +0,0 @@
-;-*-Doctest-*-
-
-=======================
-Pickleable Declarations
-=======================
-
-The implements declaration class in zope.interface only pickles a
-reference to a class to inherit from if available.  For declarations
-on persistent factories, we need a implements declaration that pickles
-and unpickles with the interfaces it includes.
-
-Create a sample object.
-
-    >>> from z3c.persistentfactory import testing
-    >>> foo = testing.Foo()
-
-Before any declarations have been made, the object doesn't implement
-or adapt anything.
-
-    >>> from zope import interface, component
-    >>> interface.implementedBy(foo)
-    Traceback (most recent call last):
-    TypeError: ('ImplementedBy called for non-factory',
-    <z3c.persistentfactory.testing.Foo object at ...>)
-    >>> component.adaptedBy(foo)
-
-Declare the interfaces the object implements and adapts.
-
-    >>> _ = interface.implementer(testing.IFoo)(foo)
-    >>> _ = component.adapter(testing.IBar)(foo)
-
-Now the objects declarations can be inspected.
-
-    >>> tuple(interface.implementedBy(foo))
-    (<InterfaceClass z3c.persistentfactory.testing.IFoo>,)
-    >>> component.adaptedBy(foo)
-    (<InterfaceClass z3c.persistentfactory.testing.IBar>,)
-
-The implements declaration doesn't survive pickling and unpickling.
-
-    >>> import pickle
-    >>> foo_unpickled = pickle.loads(pickle.dumps(foo))
-    >>> tuple(interface.implementedBy(foo_unpickled))
-    ()
-    >>> component.adaptedBy(foo_unpickled)
-    (<InterfaceClass z3c.persistentfactory.testing.IBar>,)
-
-Replace the implements declaration with a pickleable declaration.
-    
-    >>> from z3c.persistentfactory import declarations
-    >>> foo.__implemented__ = declarations.Implements(*foo.__implemented__)
-
-Now the implements declaration survives pickling and unpickling.
-
-    >>> foo_unpickled = pickle.loads(pickle.dumps(foo))
-    >>> tuple(interface.implementedBy(foo_unpickled))
-    (<InterfaceClass z3c.persistentfactory.testing.IFoo>,)
-    >>> component.adaptedBy(foo_unpickled)
-    (<InterfaceClass z3c.persistentfactory.testing.IBar>,)
-
-A mixin class is provided that supports pickleable implements
-declarations.
-
-    >>> bar = declarations.Declarer()
-
-    >>> _ = interface.implementer(testing.IFoo)(bar)
-    >>> _ = component.adapter(testing.IBar)(bar)
-
-    >>> bar_unpickled = pickle.loads(pickle.dumps(bar))
-    >>> tuple(interface.implementedBy(bar_unpickled))
-    (<InterfaceClass z3c.persistentfactory.testing.IFoo>,)
-    >>> component.adaptedBy(bar_unpickled)
-    (<InterfaceClass z3c.persistentfactory.testing.IBar>,)

Copied: z3c.persistentfactory/tags/0.3/z3c/persistentfactory/declarations.txt (from rev 85221, z3c.persistentfactory/trunk/z3c/persistentfactory/declarations.txt)
===================================================================
--- z3c.persistentfactory/tags/0.3/z3c/persistentfactory/declarations.txt	                        (rev 0)
+++ z3c.persistentfactory/tags/0.3/z3c/persistentfactory/declarations.txt	2008-04-10 20:07:55 UTC (rev 85224)
@@ -0,0 +1,91 @@
+;-*-Doctest-*-
+
+=======================
+Pickleable Declarations
+=======================
+
+The implements declaration class in zope.interface only pickles a
+reference to a class to inherit from if available.  For declarations
+on persistent factories, we need a implements declaration that pickles
+and unpickles with the interfaces it includes.
+
+Create a sample object.
+
+    >>> from z3c.persistentfactory import testing
+    >>> foo = testing.Foo()
+
+Before any declarations have been made, the object doesn't implement
+or adapt anything.
+
+    >>> from zope import interface, component
+    >>> interface.implementedBy(foo)
+    Traceback (most recent call last):
+    TypeError: ('ImplementedBy called for non-factory',
+    <z3c.persistentfactory.testing.Foo object at ...>)
+    >>> component.adaptedBy(foo)
+
+Declare the interfaces the object implements and adapts.
+
+    >>> _ = interface.implementer(testing.IFoo)(foo)
+    >>> _ = component.adapter(testing.IBar)(foo)
+
+Now the objects declarations can be inspected.
+
+    >>> tuple(interface.implementedBy(foo))
+    (<InterfaceClass z3c.persistentfactory.testing.IFoo>,)
+    >>> component.adaptedBy(foo)
+    (<InterfaceClass z3c.persistentfactory.testing.IBar>,)
+
+The implements declaration doesn't survive pickling and unpickling.
+
+    >>> import pickle
+    >>> foo_unpickled = pickle.loads(pickle.dumps(foo))
+    >>> tuple(interface.implementedBy(foo_unpickled))
+    ()
+    >>> component.adaptedBy(foo_unpickled)
+    (<InterfaceClass z3c.persistentfactory.testing.IBar>,)
+
+Replace the implements declaration with a pickleable declaration.
+    
+    >>> from z3c.persistentfactory import declarations
+    >>> foo.__implemented__ = declarations.Implements(*foo.__implemented__)
+
+Now the implements declaration survives pickling and unpickling.
+
+    >>> foo_unpickled = pickle.loads(pickle.dumps(foo))
+    >>> tuple(interface.implementedBy(foo_unpickled))
+    (<InterfaceClass z3c.persistentfactory.testing.IFoo>,)
+    >>> component.adaptedBy(foo_unpickled)
+    (<InterfaceClass z3c.persistentfactory.testing.IBar>,)
+
+A mixin class is provided that supports pickleable implements
+declarations.
+
+    >>> bar = declarations.Declarer()
+
+    >>> _ = interface.implementer(testing.IFoo)(bar)
+    >>> _ = component.adapter(testing.IBar)(bar)
+
+    >>> bar_unpickled = pickle.loads(pickle.dumps(bar))
+    >>> tuple(interface.implementedBy(bar_unpickled))
+    (<InterfaceClass z3c.persistentfactory.testing.IFoo>,)
+    >>> component.adaptedBy(bar_unpickled)
+    (<InterfaceClass z3c.persistentfactory.testing.IBar>,)
+
+The declarations of the class are isolated from the declarations on an
+instance.
+    
+    >>> tuple(interface.implementedBy(declarations.Declarer))
+    ()
+    >>> component.adaptedBy(declarations.Declarer)
+
+Classes the use Declarer as a base class can have declarations.
+
+    >>> class Qux(declarations.Declarer):
+    ...     interface.implements(testing.IQux)
+    ...     component.adapts(testing.IBaz)
+
+    >>> tuple(interface.implementedBy(Qux))
+    (<InterfaceClass z3c.persistentfactory.testing.IQux>,)
+    >>> component.adaptedBy(Qux)
+    (<InterfaceClass z3c.persistentfactory.testing.IBaz>,)

Deleted: z3c.persistentfactory/tags/0.3/z3c/persistentfactory/factory.py
===================================================================
--- z3c.persistentfactory/trunk/z3c/persistentfactory/factory.py	2008-04-09 20:55:25 UTC (rev 85202)
+++ z3c.persistentfactory/tags/0.3/z3c/persistentfactory/factory.py	2008-04-10 20:07:55 UTC (rev 85224)
@@ -1,36 +0,0 @@
-import new
-
-from zope import interface, component
-import persistent
-            
-import declarations
-
-class PersistentFactory(declarations.Declarer, persistent.Persistent):
-
-    def __init__(self, method):
-        self.context = method.im_self
-        self.__name__ = method.__name__
-        self.__implemented__ = interface.implementedBy(method)
-
-    @property
-    def __call__(self):
-        type_ = type(self.context)
-        return new.instancemethod(
-            getattr(type_, self.__name__), self.context, type_)
-
-class Factory(object):
-
-    def __init__(self, callable_):
-        self.callable = callable_
-
-    def __get__(self, instance, owner):
-        method = new.instancemethod(self.callable, instance, owner)
-        if instance is None:
-            # when accessed for the class, just return the method
-            return method
-
-        result = PersistentFactory(method)
-        setattr(instance, method.__name__, result)
-        return result
-
-factory = Factory

Copied: z3c.persistentfactory/tags/0.3/z3c/persistentfactory/factory.py (from rev 85221, z3c.persistentfactory/trunk/z3c/persistentfactory/factory.py)
===================================================================
--- z3c.persistentfactory/tags/0.3/z3c/persistentfactory/factory.py	                        (rev 0)
+++ z3c.persistentfactory/tags/0.3/z3c/persistentfactory/factory.py	2008-04-10 20:07:55 UTC (rev 85224)
@@ -0,0 +1,36 @@
+import new
+
+from zope import interface, component
+import persistent
+            
+import declarations
+
+class PersistentFactory(declarations.Declarer, persistent.Persistent):
+
+    def __init__(self, method):
+        self.context = method.im_self
+        self.__name__ = method.__name__
+        super(PersistentFactory, self).__init__()
+
+    @property
+    def __call__(self):
+        type_ = type(self.context)
+        return new.instancemethod(
+            getattr(type_, self.__name__), self.context, type_)
+
+class Factory(object):
+
+    def __init__(self, callable_):
+        self.callable = callable_
+
+    def __get__(self, instance, owner):
+        method = new.instancemethod(self.callable, instance, owner)
+        if instance is None:
+            # when accessed for the class, just return the method
+            return method
+
+        result = PersistentFactory(method)
+        setattr(instance, method.__name__, result)
+        return result
+
+factory = Factory

Copied: z3c.persistentfactory/tags/0.3/z3c/persistentfactory/factory.txt (from rev 85221, z3c.persistentfactory/trunk/z3c/persistentfactory/factory.txt)
===================================================================
--- z3c.persistentfactory/tags/0.3/z3c/persistentfactory/factory.txt	                        (rev 0)
+++ z3c.persistentfactory/tags/0.3/z3c/persistentfactory/factory.txt	2008-04-10 20:07:55 UTC (rev 85224)
@@ -0,0 +1,197 @@
+;-*-Doctest-*-
+
+====================
+Persistent Factories
+====================
+
+z3c.persistentfactory provides a PersistentFactory class that wraps an
+instance method in a persistent wrapper.  It also provides a function
+decorator for use on class method definitions such that a persistent
+factory will be used when the method is accessed on instance of the
+class.
+
+Also see declarartions.txt for details about a mixin Declarer class
+for classes implementing callable instances whose declarations should
+pickle and persist correctly.
+
+Factory
+=======
+
+The factory module provides a persistent declarer class for creating
+callable objects wrapping a instance method as factories in the
+persistent registry.
+
+Create an object with a method that has declarations.
+
+    >>> from z3c.persistentfactory import testing
+    >>> bar = testing.Bar()
+
+Verify that the instance method has declarations.
+
+    >>> from zope import interface, component
+    >>> tuple(interface.implementedBy(bar.factory))
+    (<InterfaceClass z3c.persistentfactory.testing.IBar>,)
+    >>> component.adaptedBy(bar.factory)
+    (<InterfaceClass z3c.persistentfactory.testing.IFoo>,)
+
+Wrap the instance method in a persistent factory.
+
+    >>> from z3c.persistentfactory import factory
+    >>> bar_factory = factory.PersistentFactory(bar.factory)
+
+Pickle and unpickle the factory to verify everything is pickleable.
+
+    >>> import pickle
+    >>> bar_factory = pickle.loads(pickle.dumps(bar_factory))
+
+The factory's __call__ method is the original instance method of the
+original object, not a method of the persistent factory object.
+
+    >>> bar_factory.__call__
+    <bound method Bar.factory of
+    <z3c.persistentfactory.testing.Bar object at ...>>
+    >>> bar_factory.__call__.im_self.__class__ is bar.__class__
+    True
+
+The factory is callable.
+
+    >>> bar_factory()
+    (<z3c.persistentfactory.testing.Bar object at ...>, (), {})
+
+The factory has the same declarations as the original method.
+
+    >>> tuple(interface.implementedBy(bar_factory))
+    (<InterfaceClass z3c.persistentfactory.testing.IBar>,)
+    >>> component.adaptedBy(bar_factory)
+    (<InterfaceClass z3c.persistentfactory.testing.IFoo>,)
+
+Changes to the wrapped method's declarations are not reflected in the
+factory's declarations even if the wrapped method's declarations
+haven't been overridden.  This means that any changes to the wrapped
+methods implements declaration that need to be reflected in existing
+persistent factories will require migrating the existing factories.
+
+    >>> _ = interface.implementer(testing.IFoo)(bar.factory.im_func)
+    >>> _ = component.adapter(testing.IBar)(bar.factory.im_func)
+
+    >>> tuple(interface.implementedBy(bar.factory))
+    (<InterfaceClass z3c.persistentfactory.testing.IFoo>,)
+    >>> component.adaptedBy(bar.factory)
+    (<InterfaceClass z3c.persistentfactory.testing.IBar>,)
+
+    >>> tuple(interface.implementedBy(bar_factory))
+    (<InterfaceClass z3c.persistentfactory.testing.IBar>,)
+    >>> component.adaptedBy(bar_factory)
+    (<InterfaceClass z3c.persistentfactory.testing.IFoo>,)
+
+The wrapped method's declarations can be overridden in the factory.
+
+    >>> _ = interface.implementer(testing.IBaz)(bar_factory)
+    >>> _ = component.adapter(testing.IQux)(bar_factory)
+
+    >>> tuple(interface.implementedBy(bar_factory))
+    (<InterfaceClass z3c.persistentfactory.testing.IBaz>,)
+    >>> component.adaptedBy(bar_factory)
+    (<InterfaceClass z3c.persistentfactory.testing.IQux>,)
+
+Overriding the wrapped method's declarations in the factory doesn't
+modify the declarations on the wrapped method.
+
+    >>> tuple(interface.implementedBy(bar.factory))
+    (<InterfaceClass z3c.persistentfactory.testing.IFoo>,)
+    >>> component.adaptedBy(bar.factory)
+    (<InterfaceClass z3c.persistentfactory.testing.IBar>,)
+
+However, Once the wrapped method's declarations have been overriden in
+the factory, the factory no longer reflects any changes in the wrapped
+method's declarations.
+
+    >>> _ = interface.implementer(testing.IQux)(bar.factory.im_func)
+    >>> _ = component.adapter(testing.IBaz)(bar.factory.im_func)
+
+    >>> tuple(interface.implementedBy(bar.factory))
+    (<InterfaceClass z3c.persistentfactory.testing.IQux>,)
+    >>> component.adaptedBy(bar.factory)
+    (<InterfaceClass z3c.persistentfactory.testing.IBaz>,)
+
+    >>> tuple(interface.implementedBy(bar_factory))
+    (<InterfaceClass z3c.persistentfactory.testing.IBaz>,)
+    >>> component.adaptedBy(bar_factory)
+    (<InterfaceClass z3c.persistentfactory.testing.IQux>,)
+
+Decorator
+=========
+
+A decorator is provided that will return the decorated method wrapped
+in a persistent factory when the method is accessed on an instance.
+
+The Baz class uses the decorator in the python code.  Note that the
+factory decorator must come before the declaration decorators so that
+it will be run last and will reflect the declarations.
+
+    >>> baz = testing.Baz()
+
+On an instance, the method is replaced with a persistent factory on
+first access.
+
+    >>> baz.factory
+    <z3c.persistentfactory.factory.PersistentFactory
+    object at ...>
+
+Pickle and unpickle the object to verify everything is pickleable.
+
+    >>> baz = pickle.loads(pickle.dumps(baz))
+
+The factory is the same object on subsequent accesses.
+
+    >>> baz.factory is baz.factory
+    True
+
+The factory's __call__ method is an instance method of the original
+object, not a method of the persistent factory object.
+
+    >>> baz.factory.__call__
+    <bound method Baz.factory of
+    <z3c.persistentfactory.testing.Baz object at ...>>
+
+The factory is callable and calls the wrapped method.
+
+    >>> result = baz.factory()
+    Called <bound method Baz.factory of
+    <z3c.persistentfactory.testing.Baz object at ...>>
+      args: () kwargs: {}
+    >>> result
+    (<bound method Baz.factory of
+     <z3c.persistentfactory.testing.Baz object at ...>>, (), {})
+
+The declarations of the factory reflect the declarations on the
+wrapped method.
+
+    >>> tuple(interface.implementedBy(baz.factory))
+    (<InterfaceClass z3c.persistentfactory.testing.IBar>,)
+    >>> component.adaptedBy(baz.factory)
+    (<InterfaceClass z3c.persistentfactory.testing.IFoo>,)
+
+The declarations can be overridden in the factory.
+
+    >>> _ = interface.implementer(testing.IFoo)(baz.factory)
+    >>> _ = component.adapter(testing.IBar)(baz.factory)
+
+Pickle and unpickle again to verify the pickleability of factory
+declarations.
+
+    >>> baz = pickle.loads(pickle.dumps(baz))
+
+The declaration changes are reflected on the factory.
+
+    >>> tuple(interface.implementedBy(baz.factory))
+    (<InterfaceClass z3c.persistentfactory.testing.IFoo>,)
+    >>> component.adaptedBy(baz.factory)
+    (<InterfaceClass z3c.persistentfactory.testing.IBar>,)
+
+But the class methods declarations are unaffected.
+
+    >>> tuple(interface.implementedBy(testing.Baz.factory))
+    (<InterfaceClass z3c.persistentfactory.testing.IBar>,)
+    >>> component.adaptedBy(testing.Baz.factory)
+    (<InterfaceClass z3c.persistentfactory.testing.IFoo>,)

Deleted: z3c.persistentfactory/tags/0.3/z3c/persistentfactory/testing.py
===================================================================
--- z3c.persistentfactory/trunk/z3c/persistentfactory/testing.py	2008-04-09 20:55:25 UTC (rev 85202)
+++ z3c.persistentfactory/tags/0.3/z3c/persistentfactory/testing.py	2008-04-10 20:07:55 UTC (rev 85224)
@@ -1,25 +0,0 @@
-from zope import interface, component
-
-from z3c.persistentfactory import declarations, factory
-
-class IFoo(interface.Interface): pass
-class IBar(interface.Interface): pass
-class IBaz(interface.Interface): pass
-class IQux(interface.Interface): pass
-
-class Foo(object): pass
-
-class Bar(object):
-
-    @interface.implementer(IBar)
-    @component.adapter(IFoo)
-    def factory(self):
-        return self
-
-class Baz(object):
-
-    @factory.factory
-    @interface.implementer(IBar)
-    @component.adapter(IFoo)
-    def factory(self):
-        return self

Copied: z3c.persistentfactory/tags/0.3/z3c/persistentfactory/testing.py (from rev 85203, z3c.persistentfactory/trunk/z3c/persistentfactory/testing.py)
===================================================================
--- z3c.persistentfactory/tags/0.3/z3c/persistentfactory/testing.py	                        (rev 0)
+++ z3c.persistentfactory/tags/0.3/z3c/persistentfactory/testing.py	2008-04-10 20:07:55 UTC (rev 85224)
@@ -0,0 +1,33 @@
+from zope import interface, component
+
+try:
+    from zope.component import eventtesting
+except ImportError:
+    from zope.app.event.tests import placelesssetup as eventtesting
+
+from z3c.persistentfactory import factory
+
+class IFoo(interface.Interface): pass
+class IBar(interface.Interface): pass
+class IBaz(interface.Interface): pass
+class IQux(interface.Interface): pass
+
+class Foo(object): pass
+
+class Bar(object):
+
+    @interface.implementer(IBar)
+    @component.adapter(IFoo)
+    def factory(self, *args, **kw):
+        return self, args, kw
+
+class Baz(object):
+
+    @factory.factory
+    @interface.implementer(IBar)
+    @component.adapter(IFoo)
+    def factory(self, *args, **kw):
+        print 'Called %s' % self.factory.__call__
+        print '  args: %s' % (args,)
+        print '  kwargs: %s' % kw
+        return self.factory.__call__, args, kw

Deleted: z3c.persistentfactory/tags/0.3/z3c/persistentfactory/tests.py
===================================================================
--- z3c.persistentfactory/trunk/z3c/persistentfactory/tests.py	2008-04-09 20:55:25 UTC (rev 85202)
+++ z3c.persistentfactory/tags/0.3/z3c/persistentfactory/tests.py	2008-04-10 20:07:55 UTC (rev 85224)
@@ -1,14 +0,0 @@
-import unittest
-from zope.testing import doctest
-
-def test_suite():
-    return doctest.DocFileSuite(
-        'README.txt',
-        'declarations.txt',
-        optionflags=(
-            doctest.REPORT_NDIFF|
-            doctest.NORMALIZE_WHITESPACE|
-            doctest.ELLIPSIS))
-
-if __name__ == '__main__':
-    unittest.main(defaultTest='test_suite')

Copied: z3c.persistentfactory/tags/0.3/z3c/persistentfactory/tests.py (from rev 85203, z3c.persistentfactory/trunk/z3c/persistentfactory/tests.py)
===================================================================
--- z3c.persistentfactory/tags/0.3/z3c/persistentfactory/tests.py	                        (rev 0)
+++ z3c.persistentfactory/tags/0.3/z3c/persistentfactory/tests.py	2008-04-10 20:07:55 UTC (rev 85224)
@@ -0,0 +1,15 @@
+import unittest
+from zope.testing import doctest
+
+def test_suite():
+    return doctest.DocFileSuite(
+        'README.txt',
+        'declarations.txt',
+        'factory.txt',
+        optionflags=(
+            doctest.REPORT_NDIFF|
+            doctest.NORMALIZE_WHITESPACE|
+            doctest.ELLIPSIS))
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')



More information about the Checkins mailing list