[Zope3-checkins] CVS: Zope3/src/zope/app/services/tests -
test_surrogates.py:1.2
Jim Fulton
cvs-admin at zope.org
Fri Nov 21 12:09:53 EST 2003
Update of /cvs-repository/Zope3/src/zope/app/services/tests
In directory cvs.zope.org:/tmp/cvs-serv29907/src/zope/app/services/tests
Added Files:
test_surrogates.py
Log Message:
Local surrogates maintain adapter registration information for local
adapter and presentation services. We actually cache information in
such a way that we don't have to access sites above when doing
lookups.
=== Zope3/src/zope/app/services/tests/test_surrogates.py 1.1 => 1.2 ===
--- /dev/null Fri Nov 21 12:09:53 2003
+++ Zope3/src/zope/app/services/tests/test_surrogates.py Fri Nov 21 12:09:52 2003
@@ -0,0 +1,1002 @@
+##############################################################################
+#
+# 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$
+ """
+
+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.queryNamedAdapter(f0, IB1, 'bob')
+
+ 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_multi_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', with=(IR0,))
+
+ we can query it locally:
+
+ >>> f2 = F2()
+ >>> r = R1()
+
+ >>> a = L1.queryMultiAdapter((f2, r), IB1, 'bob')
+ >>> a.__class__.__name__
+ 'A11G'
+ >>> a.args == (f2, r)
+ True
+
+ >>> a = L2.queryMultiAdapter((f2, r), IB1, 'bob')
+ >>> a.__class__.__name__
+ 'A11G'
+ >>> a.args == (f2, r)
+ True
+
+ We can add local definitions:
+
+ >>> ra011 = Registration(required = IF0, provided=IB1, factory=A011,
+ ... name='bob', with=(IR0,))
+ >>> L1.createRegistrationsFor(ra011).activate(ra011)
+
+ and use it:
+
+ >>> f0 = F0()
+
+ >>> a = L1.queryMultiAdapter((f0, r), IB1, 'bob')
+ >>> a.__class__.__name__
+ 'A011'
+ >>> a.args == (f0, r)
+ True
+
+ >>> a = L2.queryMultiAdapter((f0, r), IB1, 'bob')
+ >>> a.__class__.__name__
+ 'A011'
+ >>> a.args == (f0, r)
+ True
+
+ but not outside L1:
+
+ >>> G.queryMultiAdapter((f0, r), IB1, 'bob')
+
+ Note that it doesn't override the non-local adapter:
+
+ >>> a = L1.queryMultiAdapter((f2, r), IB1, 'bob')
+ >>> a.__class__.__name__
+ 'A11G'
+ >>> a.args == (f2, r)
+ True
+
+ >>> a = L2.queryMultiAdapter((f2, r), IB1, 'bob')
+ >>> a.__class__.__name__
+ 'A11G'
+ >>> a.args == (f2, r)
+ True
+
+ because it was more specific.
+
+ Let's override the adapter in L2:
+
+ >>> ra112 = Registration(required = IF1, provided=IB1, factory=A112,
+ ... name='bob', with=(IR0,))
+ >>> 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.queryMultiAdapter((f2, r), IB1, 'bob')
+ >>> a.__class__.__name__
+ 'A112'
+ >>> a.args == (f2, r)
+ True
+
+ But we still get the old one in L1
+
+ >>> a = L1.queryMultiAdapter((f2, r), IB1, 'bob')
+ >>> a.__class__.__name__
+ 'A11G'
+ >>> a.args == (f2, r)
+ True
+
+ Note that we can ask for less specific interfaces and still get
+ the adapter:
+
+ >>> a = L2.queryMultiAdapter((f2, r), IB0, 'bob')
+ >>> a.__class__.__name__
+ 'A112'
+ >>> a.args == (f2, r)
+ True
+
+ >>> a = L1.queryMultiAdapter((f2, r), IB0, 'bob')
+ >>> a.__class__.__name__
+ 'A11G'
+ >>> a.args == (f2, r)
+ True
+
+ We get the more specific adapter even if there is a less-specific
+ adapter to B0:
+
+ >>> G.provideAdapter(IF1, IB1, [A10G], name='bob', with=(IR0,))
+
+ >>> a = L2.queryMultiAdapter((f2, r), IB0, 'bob')
+ >>> a.__class__.__name__
+ 'A112'
+ >>> a.args == (f2, r)
+ 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', with=(IR0,))
+ >>> L2.createRegistrationsFor(ra102).activate(ra102)
+
+ >>> a = L2.queryMultiAdapter((f2, r), IB0, 'bob')
+ >>> a.__class__.__name__
+ 'A102'
+ >>> a.args == (f2, r)
+ True
+
+ We can deactivate registrations, which has the effect of deleting adapters:
+
+ >>> L2.queryRegistrationsFor(ra112).deactivate(ra112)
+
+ >>> a = L2.queryMultiAdapter((f2, r), IB0, 'bob')
+ >>> a.__class__.__name__
+ 'A102'
+ >>> a.args == (f2, r)
+ True
+
+ >>> a = L2.queryMultiAdapter((f2, r), IB1, 'bob')
+ >>> a.__class__.__name__
+ 'A10G'
+ >>> a.args == (f2, r)
+ True
+
+ >>> L2.queryRegistrationsFor(ra102).deactivate(ra102)
+
+ >>> L2.queryAdapter(f2, IB0)
+ >>> a = L2.queryMultiAdapter((f2, r), IB0, 'bob')
+ >>> a.__class__.__name__
+ 'A10G'
+ >>> a.args == (f2, r)
+ 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()
+ """
+
+
+def test_local_default():
+ """
+ >>> G = SurrogateRegistry()
+ >>> L1 = LocalSurrogateRegistry(G)
+ >>> r = Registration(required = None, provided=IB1, factory=Adapter)
+ >>> L1.createRegistrationsFor(r).activate(r)
+ >>> f2 = F2()
+ >>> L1.queryAdapter(f2, IB1).__class__.__name__
+ 'Adapter'
+ """
+
+
+def test_changing_next():
+ """
+ >>> G = SurrogateRegistry()
+ >>> L1 = LocalSurrogateRegistry(G)
+ >>> L2 = LocalSurrogateRegistry(G, L1)
+ >>> f2 = F2()
+
+ >>> L2.queryAdapter(f2, IB1).__class__.__name__
+ 'NoneType'
+
+ >>> G.provideAdapter(IF1, IB1, [A11G])
+ >>> L2.queryAdapter(f2, IB1).__class__.__name__
+ 'A11G'
+
+
+ >>> class A111(Adapter):
+ ... pass
+ >>> ra111 = Registration(required = IF1, provided=IB1, factory=A111)
+ >>> L1.createRegistrationsFor(ra111).activate(ra111)
+ >>> L2.queryAdapter(f2, IB1).__class__.__name__
+ 'A111'
+
+ >>> L1.next
+ >>> L2.next == L1
+ True
+ >>> L1.subs == (L2,)
+ True
+ >>> L3 = LocalSurrogateRegistry(G, L1)
+ >>> L2.setNext(L3)
+ >>> L2.next == L3
+ True
+ >>> L3.next == L1
+ True
+ >>> L1.subs == (L3,)
+ True
+ >>> L3.subs == (L2,)
+ True
+
+ >>> class A113(Adapter):
+ ... pass
+ >>> ra113 = Registration(required = IF1, provided=IB1, factory=A113)
+ >>> L3.createRegistrationsFor(ra113).activate(ra113)
+
+ >>> L2.queryAdapter(f2, IB1).__class__.__name__
+ 'A113'
+ >>> L2.setNext(L1)
+ >>> L2.next == L1
+ True
+ >>> L3.next == L1
+ True
+ >>> L1.subs == (L3, L2)
+ True
+ >>> L3.subs == ()
+ True
+ >>> L2.queryAdapter(f2, IB1).__class__.__name__
+ 'A111'
+
+ """
+
+def test_LocalSurrogateBasedService():
+ """
+ Setup folders and service managers:
+
+ >>> from zope.app.tests import setup
+ >>> setup.placefulSetUp()
+ >>> root = setup.buildSampleFolderTree()
+ >>> sm = setup.createServiceManager(root)
+ >>> sm1 = setup.createServiceManager(root['folder1'])
+ >>> sm1_1 = setup.createServiceManager(root['folder1']['folder1_1'])
+ >>> sm1_1_1 = setup.createServiceManager(
+ ... root['folder1']['folder1_1']['folder1_1_1'])
+
+ Define the service
+
+ >>> gsm = zapi.getServiceManager(None)
+ >>> gsm.defineService('F', IF1)
+
+ Create the global service
+
+ >>> g = F2()
+ >>> gsm.provideService('F', g)
+
+ Create a local service class, which must define setNext:
+
+ >>> import zope.app.interfaces.services.service
+ >>> class LocalF(LocalSurrogateBasedService):
+ ... zope.interface.implements(
+ ... IF2,
+ ... zope.app.interfaces.services.service.ISimpleService,
+ ... )
+ ... def setNext(self, next, global_):
+ ... self.next, self.global_ = next, global_
+
+ If we add a local service, It gets it's next and global_ attrs set:
+
+ >>> f1 = LocalF()
+ >>> hasattr(f1, 'next') or hasattr(f1, 'global_')
+ False
+ >>> setup.addService(sm1, 'F', f1) is f1
+ True
+ >>> (f1.next, f1.global_) == (None, g)
+ True
+
+ If we add another service below, it's next will point to the one
+ above:
+
+ >>> f1_1_1 = LocalF()
+ >>> setup.addService(sm1_1_1, 'F', f1_1_1) is f1_1_1
+ True
+ >>> (f1_1_1.next, f1_1_1.global_) == (f1, g)
+ True
+
+ We can insert a service in an intermediate site:
+
+ >>> f1_1 = LocalF()
+ >>> setup.addService(sm1_1, 'F', f1_1) is f1_1
+ True
+ >>> (f1_1.next, f1_1.global_) == (f1, g)
+ True
+ >>> (f1_1_1.next, f1_1_1.global_) == (f1_1, g)
+ True
+
+ Deactivating services adjust the relevant next pointers
+
+ >>> default = zapi.traverse(sm1_1, 'default')
+ >>> rm = default.getRegistrationManager()
+ >>> rm.values()[0].status = RegisteredStatus
+ >>> (f1_1_1.next, f1_1_1.global_) == (f1, g)
+ True
+
+ >>> default = zapi.traverse(sm1, 'default')
+ >>> rm = default.getRegistrationManager()
+ >>> rm.values()[0].status = RegisteredStatus
+ >>> (f1_1_1.next, f1_1_1.global_) == (None, g)
+ True
+
+ >>> setup.placefulTearDown()
+ """
+
+
+
+import unittest
+from zope.testing.doctestunit import DocTestSuite
+from zope.interface.surrogate import SurrogateRegistry
+from zope.app.services.surrogate import LocalSurrogateRegistry
+from zope.app.services.surrogate import LocalSurrogateBasedService
+import zope.interface
+from zodb.storage.memory import MemoryFullStorage
+from zodb.db import DB
+from transaction import get_transaction
+from zope.app import zapi
+from zope.app.interfaces.services.registration import RegisteredStatus
+
+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 IR0(zope.interface.Interface):
+ pass
+
+class IR1(IR0):
+ pass
+
+class R1:
+ zope.interface.implements(IR1)
+
+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 __repr__(self):
+ return "<Registration %s>" % self.__dict__
+
+ def factories(self):
+ return self.factory,
+ factories = property(factories)
+
+# 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