[Zope3-checkins] CVS: Zope3/src/zope/app/services/tests -
test_surrogates.py:1.1.2.1
Jim Fulton
cvs-admin at zope.org
Wed Nov 12 15:08:14 EST 2003
Update of /cvs-repository/Zope3/src/zope/app/services/tests
In directory cvs.zope.org:/tmp/cvs-serv25370/src/zope/app/services/tests
Added Files:
Tag: adaptergeddon-branch
test_surrogates.py
Log Message:
Added local surrogates, to be used for local adapter and presentation
services.
=== Added File Zope3/src/zope/app/services/tests/test_surrogates.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""Local Surrogate Tests
Local surrogates and surrogate registries share declarations with
those "above" them.
Suppose we have a global SurrogateRegistry:
>>> G = SurrogateRegistry()
we also have a local surrogate registry, with G as it's base:
>>> L1 = LocalSurrogateRegistry(G)
and so on:
>>> L2 = LocalSurrogateRegistry(G, L1)
Now, if we declare an adapter globally:
>>> G.provideAdapter(IF1, IB1, [A11G])
we can query it locally:
>>> f2 = F2()
>>> a = L1.queryAdapter(f2, IB1)
>>> a.__class__.__name__
'A11G'
>>> a.args == (f2, )
True
>>> a = L2.queryAdapter(f2, IB1)
>>> a.__class__.__name__
'A11G'
>>> a.args == (f2, )
True
We can add local definitions:
>>> ra011 = Registration(required = IF0, provided=IB1, factory=A011)
>>> L1.createRegistrationsFor(ra011).activate(ra011)
and use it:
>>> f0 = F0()
>>> a = L1.queryAdapter(f0, IB1)
>>> a.__class__.__name__
'A011'
>>> a.args == (f0, )
True
>>> a = L2.queryAdapter(f0, IB1)
>>> a.__class__.__name__
'A011'
>>> a.args == (f0, )
True
but not outside L1:
>>> G.queryAdapter(f0, IB1)
Note that it doesn't override the non-local adapter:
>>> a = L1.queryAdapter(f2, IB1)
>>> a.__class__.__name__
'A11G'
>>> a.args == (f2, )
True
>>> a = L2.queryAdapter(f2, IB1)
>>> a.__class__.__name__
'A11G'
>>> a.args == (f2, )
True
because it was more specific.
Let's override the adapter in L2:
>>> ra112 = Registration(required = IF1, provided=IB1, factory=A112)
>>> L2.createRegistrationsFor(ra112).activate(ra112)
Now, in L2, we get the new adapter, because it's as specific and more
local than the one from G:
>>> a = L2.queryAdapter(f2, IB1)
>>> a.__class__.__name__
'A112'
>>> a.args == (f2, )
True
But we still get thye old one in L1
>>> a = L1.queryAdapter(f2, IB1)
>>> a.__class__.__name__
'A11G'
>>> a.args == (f2, )
True
Note that we can ask for less specific interfaces and still get the adapter:
>>> a = L2.queryAdapter(f2, IB0)
>>> a.__class__.__name__
'A112'
>>> a.args == (f2, )
True
>>> a = L1.queryAdapter(f2, IB0)
>>> a.__class__.__name__
'A11G'
>>> a.args == (f2, )
True
We get the more specific adapter even if there is a less-specific
adapter to B0:
>>> G.provideAdapter(IF1, IB1, [A10G])
>>> a = L2.queryAdapter(f2, IB0)
>>> a.__class__.__name__
'A112'
>>> a.args == (f2, )
True
But if we have an equally specific and equally local adapter to B0, it
will win:
>>> ra102 = Registration(required = IF1, provided=IB0, factory=A102)
>>> L2.createRegistrationsFor(ra102).activate(ra102)
>>> a = L2.queryAdapter(f2, IB0)
>>> a.__class__.__name__
'A102'
>>> a.args == (f2, )
True
We can deactivate registrations, which has the effect of deleting adapters:
>>> L2.queryRegistrationsFor(ra112).deactivate(ra112)
>>> a = L2.queryAdapter(f2, IB0)
>>> a.__class__.__name__
'A102'
>>> a.args == (f2, )
True
>>> a = L2.queryAdapter(f2, IB1)
>>> a.__class__.__name__
'A10G'
>>> a.args == (f2, )
True
>>> L2.queryRegistrationsFor(ra102).deactivate(ra102)
>>> a = L2.queryAdapter(f2, IB0)
>>> a.__class__.__name__
'A10G'
>>> a.args == (f2, )
True
$Id: test_surrogates.py,v 1.1.2.1 2003/11/12 20:08:13 jim Exp $
"""
def test_named_adapters():
"""
Suppose we have a global SurrogateRegistry:
>>> G = SurrogateRegistry()
we also have a local surrogate registry, with G as it's base:
>>> L1 = LocalSurrogateRegistry(G)
and so on:
>>> L2 = LocalSurrogateRegistry(G, L1)
Now, if we declare an adapter globally:
>>> G.provideAdapter(IF1, IB1, [A11G], name='bob')
we can query it locally:
>>> f2 = F2()
>>> L1.queryAdapter(f2, IB1)
>>> a = L1.queryNamedAdapter(f2, IB1, 'bob')
>>> a.__class__.__name__
'A11G'
>>> a.args == (f2, )
True
>>> L2.queryAdapter(f2, IB1)
>>> a = L2.queryNamedAdapter(f2, IB1, 'bob')
>>> a.__class__.__name__
'A11G'
>>> a.args == (f2, )
True
We can add local definitions:
>>> ra011 = Registration(required = IF0, provided=IB1, factory=A011,
... name='bob')
>>> L1.createRegistrationsFor(ra011).activate(ra011)
and use it:
>>> f0 = F0()
>>> L1.queryAdapter(f0, IB1)
>>> a = L1.queryNamedAdapter(f0, IB1, 'bob')
>>> a.__class__.__name__
'A011'
>>> a.args == (f0, )
True
>>> L2.queryAdapter(f0, IB1)
>>> a = L2.queryNamedAdapter(f0, IB1, 'bob')
>>> a.__class__.__name__
'A011'
>>> a.args == (f0, )
True
but not outside L1:
>>> G.queryAdapter(f0, IB1)
Note that it doesn't override the non-local adapter:
>>> L1.queryAdapter(f2, IB1)
>>> a = L1.queryNamedAdapter(f2, IB1, 'bob')
>>> a.__class__.__name__
'A11G'
>>> a.args == (f2, )
True
>>> L2.queryAdapter(f2, IB1)
>>> a = L2.queryNamedAdapter(f2, IB1, 'bob')
>>> a.__class__.__name__
'A11G'
>>> a.args == (f2, )
True
because it was more specific.
Let's override the adapter in L2:
>>> ra112 = Registration(required = IF1, provided=IB1, factory=A112,
... name='bob')
>>> L2.createRegistrationsFor(ra112).activate(ra112)
Now, in L2, we get the new adapter, because it's as specific and more
local than the one from G:
>>> L2.queryAdapter(f2, IB1)
>>> a = L2.queryNamedAdapter(f2, IB1, 'bob')
>>> a.__class__.__name__
'A112'
>>> a.args == (f2, )
True
But we still get thye old one in L1
>>> L1.queryAdapter(f2, IB1)
>>> a = L1.queryNamedAdapter(f2, IB1, 'bob')
>>> a.__class__.__name__
'A11G'
>>> a.args == (f2, )
True
Note that we can ask for less specific interfaces and still get the adapter:
>>> L2.queryAdapter(f2, IB0)
>>> a = L2.queryNamedAdapter(f2, IB0, 'bob')
>>> a.__class__.__name__
'A112'
>>> a.args == (f2, )
True
>>> L1.queryAdapter(f2, IB0)
>>> a = L1.queryNamedAdapter(f2, IB0, 'bob')
>>> a.__class__.__name__
'A11G'
>>> a.args == (f2, )
True
We get the more specific adapter even if there is a less-specific
adapter to B0:
>>> G.provideAdapter(IF1, IB1, [A10G], name='bob')
>>> L2.queryAdapter(f2, IB0)
>>> a = L2.queryNamedAdapter(f2, IB0, 'bob')
>>> a.__class__.__name__
'A112'
>>> a.args == (f2, )
True
But if we have an equally specific and equally local adapter to B0, it
will win:
>>> ra102 = Registration(required = IF1, provided=IB0, factory=A102,
... name='bob')
>>> L2.createRegistrationsFor(ra102).activate(ra102)
>>> L2.queryAdapter(f2, IB0)
>>> a = L2.queryNamedAdapter(f2, IB0, 'bob')
>>> a.__class__.__name__
'A102'
>>> a.args == (f2, )
True
We can deactivate registrations, which has the effect of deleting adapters:
>>> L2.queryRegistrationsFor(ra112).deactivate(ra112)
>>> L2.queryAdapter(f2, IB0)
>>> a = L2.queryNamedAdapter(f2, IB0, 'bob')
>>> a.__class__.__name__
'A102'
>>> a.args == (f2, )
True
>>> L2.queryAdapter(f2, IB1)
>>> a = L2.queryNamedAdapter(f2, IB1, 'bob')
>>> a.__class__.__name__
'A10G'
>>> a.args == (f2, )
True
>>> L2.queryRegistrationsFor(ra102).deactivate(ra102)
>>> L2.queryAdapter(f2, IB0)
>>> a = L2.queryNamedAdapter(f2, IB0, 'bob')
>>> a.__class__.__name__
'A10G'
>>> a.args == (f2, )
True
"""
def test_persistence():
"""
>>> storage = MemoryFullStorage('test')
>>> db = DB(storage)
>>> conn1 = db.open()
>>> G = globalSurrogateRegistry
>>> L1 = LocalSurrogateRegistry(G)
>>> L2 = LocalSurrogateRegistry(G, L1)
>>> conn1.root()['L1'] = L1
>>> conn1.root()['L2'] = L2
>>> G.provideAdapter(IF1, IB1, [A11G], name='bob')
>>> f2 = F2()
>>> L1.queryAdapter(f2, IB1)
>>> a = L1.queryNamedAdapter(f2, IB1, 'bob')
>>> a.__class__.__name__
'A11G'
>>> a.args == (f2, )
True
>>> L2.queryAdapter(f2, IB1)
>>> a = L2.queryNamedAdapter(f2, IB1, 'bob')
>>> a.__class__.__name__
'A11G'
>>> a.args == (f2, )
True
We can add local definitions:
>>> ra011 = Registration(required = IF0, provided=IB1, factory=A011,
... name='bob')
>>> L1.createRegistrationsFor(ra011).activate(ra011)
and use it:
>>> f0 = F0()
>>> L1.queryAdapter(f0, IB1)
>>> a = L1.queryNamedAdapter(f0, IB1, 'bob')
>>> a.__class__.__name__
'A011'
>>> a.args == (f0, )
True
>>> L2.queryAdapter(f0, IB1)
>>> a = L2.queryNamedAdapter(f0, IB1, 'bob')
>>> a.__class__.__name__
'A011'
>>> a.args == (f0, )
True
but not outside L1:
>>> G.queryAdapter(f0, IB1)
Note that it doesn't override the non-local adapter:
>>> L1.queryAdapter(f2, IB1)
>>> a = L1.queryNamedAdapter(f2, IB1, 'bob')
>>> a.__class__.__name__
'A11G'
>>> a.args == (f2, )
True
>>> L2.queryAdapter(f2, IB1)
>>> a = L2.queryNamedAdapter(f2, IB1, 'bob')
>>> a.__class__.__name__
'A11G'
>>> a.args == (f2, )
True
because it was more specific.
Let's override the adapter in L2:
>>> ra112 = Registration(required = IF1, provided=IB1, factory=A112,
... name='bob')
>>> L2.createRegistrationsFor(ra112).activate(ra112)
Now, in L2, we get the new adapter, because it's as specific and more
local than the one from G:
>>> L2.queryAdapter(f2, IB1)
>>> a = L2.queryNamedAdapter(f2, IB1, 'bob')
>>> a.__class__.__name__
'A112'
>>> a.args == (f2, )
True
But we still get the old one in L1
>>> L1.queryAdapter(f2, IB1)
>>> a = L1.queryNamedAdapter(f2, IB1, 'bob')
>>> a.__class__.__name__
'A11G'
>>> a.args == (f2, )
True
Note that we can ask for less specific interfaces and still get the adapter:
>>> L2.queryAdapter(f2, IB0)
>>> a = L2.queryNamedAdapter(f2, IB0, 'bob')
>>> a.__class__.__name__
'A112'
>>> a.args == (f2, )
True
>>> L1.queryAdapter(f2, IB0)
>>> a = L1.queryNamedAdapter(f2, IB0, 'bob')
>>> a.__class__.__name__
'A11G'
>>> a.args == (f2, )
True
We get the more specific adapter even if there is a less-specific
adapter to B0:
>>> G.provideAdapter(IF0, IB0, [A00G], name='bob')
>>> L2.queryAdapter(f2, IB0)
>>> a = L2.queryNamedAdapter(f2, IB0, 'bob')
>>> a.__class__.__name__
'A112'
>>> a.args == (f2, )
True
But if we have an equally specific and equally local adapter to B0, it
will win:
>>> ra102 = Registration(required = IF1, provided=IB0, factory=A102,
... name='bob')
>>> L2.createRegistrationsFor(ra102).activate(ra102)
>>> L2.queryAdapter(f2, IB0)
>>> a = L2.queryNamedAdapter(f2, IB0, 'bob')
>>> a.__class__.__name__
'A102'
>>> a.args == (f2, )
True
>>> L1.queryNamedAdapter(f2, IB0, 'bob').__class__.__name__
'A11G'
>>> L1.queryNamedAdapter(f2, IB1, 'bob').__class__.__name__
'A11G'
>>> L2.queryNamedAdapter(f2, IB0, 'bob').__class__.__name__
'A102'
>>> L2.queryNamedAdapter(f2, IB1, 'bob').__class__.__name__
'A112'
>>> get_transaction().commit()
Now, let's open another transaction:
>>> conn2 = db.open()
>>> L1 = conn2.root()['L1']
>>> L2 = conn2.root()['L2']
We should get the same outputs:
>>> L1.queryNamedAdapter(f2, IB0, 'bob').__class__.__name__
'A11G'
>>> L1.queryNamedAdapter(f2, IB1, 'bob').__class__.__name__
'A11G'
>>> L2.queryNamedAdapter(f2, IB0, 'bob').__class__.__name__
'A102'
>>> L2.queryNamedAdapter(f2, IB1, 'bob').__class__.__name__
'A112'
We can deactivate registrations, which has the effect of deleting adapters:
>>> L2.queryRegistrationsFor(ra112).deactivate(ra112)
>>> L2.queryRegistrationsFor(ra102).deactivate(ra102)
>>> L1.queryNamedAdapter(f2, IB0, 'bob').__class__.__name__
'A11G'
>>> L1.queryNamedAdapter(f2, IB1, 'bob').__class__.__name__
'A11G'
>>> L2.queryNamedAdapter(f2, IB0, 'bob').__class__.__name__
'A11G'
>>> L2.queryNamedAdapter(f2, IB1, 'bob').__class__.__name__
'A11G'
>>> get_transaction().commit()
If we look back at the first connection, we should get the same data:
>>> conn1.sync()
>>> L1 = conn1.root()['L1']
>>> L2 = conn1.root()['L2']
We should see the result of the deactivations:
>>> L1.queryNamedAdapter(f2, IB0, 'bob').__class__.__name__
'A11G'
>>> L1.queryNamedAdapter(f2, IB1, 'bob').__class__.__name__
'A11G'
>>> L2.queryNamedAdapter(f2, IB0, 'bob').__class__.__name__
'A11G'
>>> L2.queryNamedAdapter(f2, IB1, 'bob').__class__.__name__
'A11G'
Cleanup:
>>> G.__init__()
>>> db.close()
"""
import unittest
from zope.testing.doctestunit import DocTestSuite
from zope.interface.surrogate import SurrogateRegistry
from zope.app.services.surrogate import LocalSurrogateRegistry
import zope.interface
from zodb.storage.memory import MemoryFullStorage
from zodb.db import DB
from transaction import get_transaction
class IF0(zope.interface.Interface):
pass
class IF1(IF0):
pass
class IF2(IF1):
pass
class IB0(zope.interface.Interface):
pass
class IB1(IB0):
pass
class F0:
zope.interface.implements(IF0)
class F2:
zope.interface.implements(IF2)
class Adapter:
def __init__(self, *args):
self.args = args
class A00G(Adapter):
pass
class A11G(Adapter):
pass
class A112(Adapter):
pass
class A10G(Adapter):
pass
class A102(Adapter):
pass
class A011(Adapter):
pass
class Registration:
name=u''
with=()
provided=zope.interface.Interface
required=None
def __init__(self, **kw):
self.__dict__.update(kw)
def __call__(self, *args):
return self.factory(*args)
# Create a picklable global registry. The pickleability of other
# global surrogate registries is beyond the scope of these tests:
class GlobalSurogateRegistry(SurrogateRegistry):
def __reduce__(self):
return 'globalSurrogateRegistry'
globalSurrogateRegistry = GlobalSurogateRegistry()
class TestStack:
registration = None
def __init__(self, parent):
self.__parent__ = parent
def activate(self, registration):
self.registration = registration
self.__parent__.notifyActivated(self, registration)
def deactivate(self, registration):
self.registration = None
self.__parent__.notifyDeactivated(self, registration)
def active(self):
return self.registration
class LocalSurrogateRegistry(LocalSurrogateRegistry):
"""For testing, use custom stack type
"""
_stackType = TestStack
def test_suite():
return unittest.TestSuite((
DocTestSuite(),
))
if __name__ == '__main__': unittest.main()
More information about the Zope3-Checkins
mailing list