Skip to content
This repository has been archived by the owner on Jan 21, 2021. It is now read-only.

Commit

Permalink
Backport changes from trunk to pass tests on Mac.
Browse files Browse the repository at this point in the history
  • Loading branch information
rpatterson committed Mar 8, 2007
2 parents daf3763 + 58fa96e commit 6510466
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 113 deletions.
100 changes: 11 additions & 89 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,92 +21,21 @@


from persistent import Persistent
from persistent.wref import PersistentWeakKeyDictionary
from zodbcode.patch import registerWrapper, Wrapper
from zodbcode.patch import registerWrapper, Wrapper, NameFinder

from zope.interface.interface import InterfaceClass
from zope.interface import Interface
from zope.security.proxy import removeSecurityProxy

persistentFactories = {}
def getPersistentKey(v_key):
try:
reduce = v_key.__reduce__()
except AttributeError:
return
except TypeError:
return

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
from wref import FlexibleWeakKeyDictionary

class PersistentInterfaceClass(Persistent, InterfaceClass):

def __init__(self, *args, **kw):
Persistent.__init__(self)
InterfaceClass.__init__(self, *args, **kw)

self.dependents = DependentsDict()
self.dependents = FlexibleWeakKeyDictionary()

# PersistentInterface is equivalent to the zope.interface.Interface object
# except that it is also persistent. It is used in conjunction with
Expand All @@ -115,30 +44,18 @@ def __init__(self, *args, **kw):
(Interface, ))


def persistentInterface(iface):
return PersistentInterfaceClass(iface.__name__)
persistentFactories[InterfaceClass] = persistentInterface

class PersistentInterfaceWrapper(Wrapper):

def unwrap(self):
return PersistentInterfaceClass(self._obj.__name__)


def getInterfaceStateForPersistentInterfaceCreation(iface):
# Need to convert the dependents weakref dict to a persistent dict
dict = iface.__dict__.copy()

deps = dict['dependents']
dependents = DependentsDict()
for k, v in deps.iteritems():
dependents = FlexibleWeakKeyDictionary()
for k, v in dict['dependents'].iteritems():
dependents[k] = v
del dict['dependents']

for key, value in dict.iteritems():
p_value = getPersistentKey(value)
if p_value is not None:
dict[key] = p_value

dict['dependents'] = dependents
return dict

Expand All @@ -147,6 +64,11 @@ def getInterfaceStateForPersistentInterfaceCreation(iface):
getInterfaceStateForPersistentInterfaceCreation,
)

NameFinder.classTypes[InterfaceClass] = True
NameFinder.types[InterfaceClass] = True
NameFinder.classTypes[PersistentInterfaceClass] = True
NameFinder.types[PersistentInterfaceClass] = True

from zope.interface.declarations import providedBy

def queryType(object, interface):
Expand Down
51 changes: 27 additions & 24 deletions tests/test_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@

from zope.interface import Interface, implements, directlyProvides
from zope.interface.interfaces import IInterface
from zope.component.interface import provideInterface
from zope.app.interface import PersistentInterface

# TODO: for some reason changing this code to use implements() does not
Expand Down Expand Up @@ -58,15 +57,26 @@ class IBar(Interface): pass
class IBah(IQuux): pass
class IBaz(Interface): pass
class IBlah(IBaz): pass
"""

provide_iface_code = """\
from zope.interface import Interface
from zope.component.interface import provideInterface
from zope.app.interface.tests.test_interface import IBarInterface
class IBar(Interface): pass
provideInterface('', IBar, iface_type=IBarInterface)
"""

class IBarInterface(IInterface): pass

class Bar(Persistent): pass
class Baz(Persistent): pass

class IQux(Interface): pass

class IBarInterface(IInterface): pass

class PersistentInterfaceTest(unittest.TestCase):

def setUp(self):
Expand Down Expand Up @@ -124,9 +134,14 @@ def test_provides(self):
self.root['blah'] = blah
self.assertTrue(barmodule.IBlah.providedBy(blah))

# Update the code to make sure everything works on update
self.registry.updateModule('barmodule',
bar_code + '\nfoo = 1')

transaction.commit()
self.db.close()
root = self.db.open().root()

barmodule = root['registry'].findModule("barmodule")

bar = root['bar']
Expand Down Expand Up @@ -162,30 +177,18 @@ def test_persistentWeakref(self):
barmodule = root['registry'].findModule("barmodule")
self.assertEqual(barmodule.IBar.dependents.keys(), [])

def test_persistentDeclarations(self):
"""Verify equivalency of persistent declarations
def test_persistentProvides(self):
"""Verify that provideInterface works."""

Make sure that the persistent declaration instance are
equivalent to the non-persistent instances they originate
from."""

self.registry.newModule("barmodule", bar_code)
self.registry.newModule("barmodule", provide_iface_code)
barmodule = self.registry.findModule("barmodule")
self.assertTrue(IBarInterface.providedBy(barmodule.IBar))

class Baz(object):
implements(barmodule.IBar)

bar = Bar()
directlyProvides(bar, barmodule.IBar)

self.assertEqual(
bar.__provides__._Provides__args,
barmodule.IBar.dependents.keys()[0]._Provides__args
)
self.assertEqual(
Baz.__implemented__.__bases__,
barmodule.IBar.dependents.keys()[1].__bases__
)
self.registry.updateModule('barmodule',
provide_iface_code + '\nfoo = 1')
transaction.commit()
barmodule = self.registry.findModule("barmodule")
self.assertTrue(IBarInterface.providedBy(barmodule.IBar))

def test_suite():
return unittest.makeSuite(PersistentInterfaceTest)
52 changes: 52 additions & 0 deletions wref.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from weakref import ref

from persistent.interfaces import IPersistent
from persistent.wref import (WeakRef, WeakRefMarker,
PersistentWeakKeyDictionary)

class wref(ref):
def __reduce_ex__(self, proto):
return _wref_reconstructor, ()

class Dummy(object): pass

def _wref_reconstructor():
"""Return a dead reference on reconstruction"""
return wref(Dummy())

def getWeakRef(ob):
"""Get either a persistent or non-presistent weakref"""
if IPersistent.providedBy(ob):
return WeakRef(ob)
else:
return wref(ob)

class FlexibleWeakKeyDictionary(PersistentWeakKeyDictionary):

def __setitem__(self, key, value):
self.data[getWeakRef(key)] = value

def __getitem__(self, key):
return self.data[getWeakRef(key)]

def __delitem__(self, key):
del self.data[getWeakRef(key)]

def get(self, key, default=None):
return self.data.get(getWeakRef(key), default)

def __contains__(self, key):
return getWeakRef(key) in self.data

def update(self, adict):
if isinstance(adict, PersistentWeakKeyDictionary):
self.data.update(adict.update)
else:
for k, v in adict.items():
self.data[getWeakRef(k)] = v

def keys(self):
return [k() for k in self.data.keys()]

def __len__(self):
return len(self.data)

0 comments on commit 6510466

Please sign in to comment.