[Zope3-checkins] SVN: Zope3/branches/3.3/src/zope/app/ Merge PersistentInterfaceClass fix from trunk r72109 as described in

Christian Theune ct at gocept.com
Mon Jan 22 02:06:32 EST 2007


Hi,

I didn't spot a comment in the CHANGELOG for this.

Christian

Am Freitag, den 19.01.2007, 16:58 -0500 schrieb Ross Patterson:
> Log message for revision 72110:
>   Merge PersistentInterfaceClass fix from trunk r72109 as described in
>   http://www.zope.org/Collectors/Zope3-dev/747.
>   
> 
> Changed:
>   U   Zope3/branches/3.3/src/zope/app/component/tests/test_registration.py
>   U   Zope3/branches/3.3/src/zope/app/interface/__init__.py
>   U   Zope3/branches/3.3/src/zope/app/interface/tests/test_interface.py
> 
> -=-
> Modified: Zope3/branches/3.3/src/zope/app/component/tests/test_registration.py
> ===================================================================
> --- Zope3/branches/3.3/src/zope/app/component/tests/test_registration.py	2007-01-19 21:06:58 UTC (rev 72109)
> +++ Zope3/branches/3.3/src/zope/app/component/tests/test_registration.py	2007-01-19 21:58:52 UTC (rev 72110)
> @@ -419,7 +419,81 @@
>  
>      """
>  
> +barcode = """
> +from zope.interface import Interface
> +class IBar(Interface): pass
> +class IBaz(Interface): pass
> +"""
>  
> +class Bar(persistent.Persistent): pass
> +class Baz(persistent.Persistent): pass
> +
> +def test_persistent_interfaces():
> +    """
> +Registrations for persistent interfaces are accessible from separate
> +connections.
> +
> +Setup the DB and our first connection::
> +
> +    >>> import ZODB.tests.util
> +    >>> db = ZODB.tests.util.DB()
> +    >>> conn1 = db.open()
> +    >>> root1 = conn1.root()
> +
> +Setup the persistent module registry and the local component
> +registry::
> +
> +    >>> from zodbcode.module import ManagedRegistry
> +    >>> registry = root1['registry'] = ManagedRegistry()
> +    >>> from zope.component.persistentregistry import PersistentComponents
> +    >>> manager = root1['manager'] = PersistentComponents()
> +
> +Create a persistent module::
> +
> +    >>> registry.newModule('barmodule', barcode)
> +    >>> barmodule = registry.findModule('barmodule')
> +
> +Create a persistent instance::
> +
> +    >>> bar = root1['bar'] = Bar()
> +    >>> from zope.interface import directlyProvides
> +    >>> directlyProvides(bar, barmodule.IBar)
> +    >>> from transaction import commit
> +    >>> commit()
> +
> +Register an adapter::
> +
> +    >>> manager.queryAdapter(bar, barmodule.IBaz)
> +    >>> manager.registerAdapter(Baz, [barmodule.IBar], barmodule.IBaz)
> +    >>> manager.getAdapter(bar, barmodule.IBaz) # doctest: +ELLIPSIS
> +    <zope.app.component.tests.test_registration.Baz object at ...>
> +
> +Before commit, the adapter is not available from another connection::
> +
> +    >>> conn2 = db.open()
> +    >>> root2 = conn2.root()
> +    >>> registry2 = root2['registry']
> +    >>> barmodule2 = registry2.findModule('barmodule')
> +    >>> bar2 = root2['bar']
> +    >>> manager2 = root2['manager']
> +    >>> manager2.queryAdapter(bar2, barmodule2.IBaz)
> +
> +After commit, it is::
> +
> +    >>> commit()
> +    >>> conn2.sync()
> +    >>> manager2.getAdapter(bar2, barmodule2.IBaz)
> +    ... # doctest: +ELLIPSIS
> +    <zope.app.component.tests.test_registration.Baz object at ...>
> +
> +Cleanup::
> +
> +    >>> conn1.close()
> +    >>> conn2.close()
> +    >>> db.close()
> +"""
> +
> +
>  def test_suite():
>      suite = unittest.TestSuite((
>          doctest.DocFileSuite('deprecated35_statusproperty.txt',
> 
> Modified: Zope3/branches/3.3/src/zope/app/interface/__init__.py
> ===================================================================
> --- Zope3/branches/3.3/src/zope/app/interface/__init__.py	2007-01-19 21:06:58 UTC (rev 72109)
> +++ Zope3/branches/3.3/src/zope/app/interface/__init__.py	2007-01-19 21:58:52 UTC (rev 72110)
> @@ -19,22 +19,90 @@
>  """
>  __docformat__ = 'restructuredtext'
>  
> +
>  from persistent import Persistent
> -from persistent.dict import PersistentDict
> +from persistent.wref import PersistentWeakKeyDictionary
>  from zodbcode.patch import registerWrapper, Wrapper
>  
>  from zope.interface.interface import InterfaceClass
>  from zope.interface import Interface
>  from zope.security.proxy import removeSecurityProxy
>  
> +persistentFactories = {}
> +def getPersistentKey(v_key):
> +    if not hasattr(v_key, '__reduce__'):
> +        return
> +    reduce = v_key.__reduce__()
> +    lookups = reduce[0], type(v_key), getattr(v_key, '__class__')
> +    for lookup in lookups:
> +        p_factory = persistentFactories.get(lookup, None)
> +        if p_factory is not None:
> +            return p_factory(v_key)
> +
> +class DependentsDict(PersistentWeakKeyDictionary):
> +    """Intercept non-persistent keys and swap in persistent
> +    equivalents."""
> +
> +    def __setstate__(self, state):
> +        data = state['data']
> +        for v_key, value in data:
> +            p_key = getPersistentKey(v_key)
> +            if p_key is not None:
> +                data[p_key] = data[v_key]
> +        state['data'] = data
> +        return super(DependentsDict, self).__setstate__(state)
> +                
> +    def __setitem__(self, key, value):
> +        p_key = getPersistentKey(key)
> +        if p_key is not None: key = p_key
> +        return super(DependentsDict, self).__setitem__(key, value)
> +
> +    def __len__(self): return len(self.data)
> +
> +    def get(self, key, default=None):
> +        if not hasattr(key, '_p_oid') or not hasattr(key, '_p_jar'):
> +            return default
> +        return super(DependentsDict, self).get(key, default)
> +
> +    def update(self, adict):
> +        for v_key in adict.keys():
> +            p_key = getPersistentKey(v_key)
> +            if p_key is not None:
> +                adict[p_key] = adict[v_key]
> +        return super(DependentsDict, self).update(adict)
> +
> +    def keys(self): return [k() for k in self.data.keys()]
> +
> +from zope.interface.declarations import ProvidesClass, Provides
> +class PersistentProvidesClass(Persistent, ProvidesClass):
> +    """A persistent Provides class."""
> +    def __init__(self, *args, **kw):
> +        Persistent.__init__(self)
> +        ProvidesClass.__init__(self, *args, **kw)
> +        self.dependents = DependentsDict()
> +def persistentProvides(obj):
> +    return PersistentProvidesClass(*obj.__reduce__()[1:])
> +persistentFactories[Provides] = persistentProvides
> +
> +from zope.interface.declarations import Implements
> +class PersistentImplements(Persistent, Implements):
> +    """A persistent Implements class."""
> +    def __init__(self, *args, **kw):
> +        Persistent.__init__(self)
> +        Implements.__init__(self, *args, **kw)
> +        self.dependents = DependentsDict()
> +def persistentImplements(obj):
> +    return PersistentImplements(*obj.__bases__)
> +persistentFactories[Implements] = persistentImplements
> +
>  class PersistentInterfaceClass(Persistent, InterfaceClass):
>  
>      def __init__(self, *args, **kw):
>          Persistent.__init__(self)
>          InterfaceClass.__init__(self, *args, **kw)
> +        
> +        self.dependents = DependentsDict()
>  
> -        self.dependents = PersistentDict()
> -
>  # PersistentInterface is equivalent to the zope.interface.Interface object
>  # except that it is also persistent.  It is used in conjunction with
>  # zodb.code to support interfaces in persistent modules.
> @@ -50,7 +118,7 @@
>  def getInterfaceStateForPersistentInterfaceCreation(iface):
>      # Need to convert the dependents weakref dict to a persistent dict
>      dict = iface.__dict__.copy()
> -    dependents = PersistentDict()
> +    dependents = DependentsDict()
>      for k, v in dict['dependents'].iteritems():
>          dependents[k] = v
>      dict['dependents'] = dependents
> 
> Modified: Zope3/branches/3.3/src/zope/app/interface/tests/test_interface.py
> ===================================================================
> --- Zope3/branches/3.3/src/zope/app/interface/tests/test_interface.py	2007-01-19 21:06:58 UTC (rev 72109)
> +++ Zope3/branches/3.3/src/zope/app/interface/tests/test_interface.py	2007-01-19 21:58:52 UTC (rev 72110)
> @@ -17,14 +17,18 @@
>  """
>  __docformat__ = 'restructuredtext'
>  
> +from gc import collect
> +
>  import unittest
>  
> +from persistent import Persistent
> +
>  import transaction
>  
>  from ZODB.tests.util import DB
>  from zodbcode.module import ManagedRegistry
>  
> -from zope.interface import Interface, implements
> +from zope.interface import Interface, implements, directlyProvides
>  from zope.app.interface import PersistentInterface
>  
>  # TODO: for some reason changing this code to use implements() does not
> @@ -42,11 +46,24 @@
>  aFoo = Foo()
>  """
>  
> +bar_code = """\
> +from zope.interface import Interface
> +class IBar(Interface): pass
> +class IBaz(Interface): pass
> +"""
> +
> +class Bar(Persistent): pass
> +class Baz(Persistent): pass
> +
> +class IQux(Interface): pass
> +
>  class PersistentInterfaceTest(unittest.TestCase):
>  
>      def setUp(self):
> +
>          self.db = DB()
> -        self.root = self.db.open().root()
> +        self.conn = self.db.open()
> +        self.root = self.conn.root()
>          self.registry = ManagedRegistry()
>          self.root["registry"] = self.registry
>          transaction.commit()
> @@ -76,6 +93,55 @@
>          # the conversion should not affect Interface
>          self.assert_(imodule.Interface is Interface)
>  
> +    def test_provides(self):
> +        """Provides are persistent."""
> +        
> +        self.registry.newModule("barmodule", bar_code)
> +        barmodule = self.registry.findModule("barmodule")
> +        bar = Bar()
> +        directlyProvides(bar, barmodule.IBar)
> +        self.root['bar'] = bar
> +        self.assertTrue(barmodule.IBar.providedBy(bar))
> +        transaction.commit()
> +        self.db.close()
>  
> +        root = self.db.open().root()
> +        barmodule = root['registry'].findModule("barmodule")
> +        bar = root['bar']
> +        self.assertTrue(barmodule.IBar.providedBy(bar))
> +
> +    def test_weakref(self):
> +        """Weak references to persistent objects don't remain after
> +        ZODB pack and garbage collection."""
> +
> +        bar = self.root['bar'] = Bar()
> +        baz = self.root['baz'] = Baz()
> +
> +        self.registry.newModule("barmodule", bar_code)
> +        barmodule = self.registry.findModule("barmodule")
> +
> +        self.assertEqual(IQux.dependents.keys(), [])
> +        self.assertEqual(barmodule.IBar.dependents.keys(), [])
> +        
> +        directlyProvides(baz, IQux)
> +        directlyProvides(bar, barmodule.IBar)
> +
> +        self.assertEqual(len(IQux.dependents), 1)
> +        self.assertEqual(len(barmodule.IBar.dependents), 1)
> +
> +        transaction.commit()
> +        del bar
> +        del self.root['bar']
> +        del baz
> +        del self.root['baz']
> +        self.db.pack()
> +        transaction.commit()
> +        collect()
> +
> +        root = self.db.open().root()
> +        barmodule = root['registry'].findModule("barmodule")
> +
> +        self.assertEqual(barmodule.IBar.dependents.keys(), [])
> +        
>  def test_suite():
>      return unittest.makeSuite(PersistentInterfaceTest)
> 
> _______________________________________________
> Zope3-Checkins mailing list
> Zope3-Checkins at zope.org
> http://mail.zope.org/mailman/listinfo/zope3-checkins
-- 
gocept gmbh & co. kg - forsterstraße 29 - 06112 halle/saale - germany
www.gocept.com - ct at gocept.com - phone +49 345 122 9889 7 -
fax +49 345 122 9889 1 - zope and plone consulting and development
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Dies ist ein digital signierter Nachrichtenteil
Url : http://mail.zope.org/pipermail/zope3-checkins/attachments/20070122/5c419174/attachment.bin


More information about the Zope3-Checkins mailing list