[Zope3-checkins] CVS: Zope3/src/zope/app/services/tests - test_useconfiguration.py:1.2 placefulsetup.py:1.9 test_cacheconfiguration.py:1.3 test_connectionconfiguration.py:1.3 test_connectionservice.py:1.3 test_eventservice.py:1.11 test_serviceconfiguration.py:1.4

Guido van Rossum guido@python.org
Mon, 3 Mar 2003 18:16:44 -0500


Update of /cvs-repository/Zope3/src/zope/app/services/tests
In directory cvs.zope.org:/tmp/cvs-serv7820/src/zope/app/services/tests

Modified Files:
	placefulsetup.py test_cacheconfiguration.py 
	test_connectionconfiguration.py test_connectionservice.py 
	test_eventservice.py test_serviceconfiguration.py 
Added Files:
	test_useconfiguration.py 
Log Message:
Merge from use-config-branch.  (A joint production by Jim, Tim and Guido.)

- Refactor the service creation and configuration code, making the UI
  for creating and configuring services much more pleasant.

- Add a new marker interface, IUseConfigurable, which is used to say
  that an object records dependencies between it and its
  configurations.  (This applies to other configurable objects besides
  services.)  Another marker interface, IAttributeUseConfigurable,
  says that these dependencies are stored as annotations.  And finally
  IUseConfiguration defines the actual interface for discussing these
  dependencies; implementing IUseConfigurable is a promise that such
  an adapter exists (and implementing IAttributeUseConfigurable is one
  way of making this promise come true :-).

- Add a new view tab for services, called "Configurations", which
  displays links to its configurations with summary information.  (Try
  it for the Events service, which has two configurations by default.)

- Add a new interface, ILocalService, which all local services must
  implement.  Also add ISimpleService, which extends ILocalService
  with IAttributeUseConfigurable.  All existing local service
  implementations implement this.

- Some miscellaneous cleanup (e.g. made the browser namespace the
  default namespace in zope/app/browser/services/configure.zcml).


=== Zope3/src/zope/app/services/tests/test_useconfiguration.py 1.1 => 1.2 ===
--- /dev/null	Mon Mar  3 18:16:44 2003
+++ Zope3/src/zope/app/services/tests/test_useconfiguration.py	Mon Mar  3 18:16:14 2003
@@ -0,0 +1,54 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""
+$Id$
+"""
+
+from unittest import TestCase, TestSuite, main, makeSuite
+from zope.app.services.configuration import UseConfiguration
+from zope.app.interfaces.annotation import IAnnotations
+from zope.app.tests.placelesssetup import PlacelessSetup
+
+class C(dict):
+    __implements__ = IAnnotations
+
+class TestUseConfiguration(PlacelessSetup, TestCase):
+
+    def testVerifyInterface(self):
+        from zope.interface.verify import verifyObject
+        from zope.app.interfaces.services.configuration import IUseConfiguration
+        obj = UseConfiguration(C())
+        verifyObject(IUseConfiguration, obj)
+
+    def test(self):
+        obj = UseConfiguration(C())
+        self.failIf(obj.usages())
+        obj.addUsage('/a/b')
+        obj.addUsage('/c/d')
+        obj.addUsage('/c/e')
+        locs = list(obj.usages())
+        locs.sort()
+        self.assertEqual(locs, ['/a/b', '/c/d', '/c/e'])
+        obj.removeUsage('/c/d')
+        locs = list(obj.usages())
+        locs.sort()
+        self.assertEqual(locs, ['/a/b', '/c/e'])
+
+def test_suite():
+    return TestSuite((
+        makeSuite(TestUseConfiguration),
+        ))
+
+if __name__=='__main__':
+    main(defaultTest='test_suite')


=== Zope3/src/zope/app/services/tests/placefulsetup.py 1.8 => 1.9 ===
--- Zope3/src/zope/app/services/tests/placefulsetup.py:1.8	Tue Feb 11 21:17:34 2003
+++ Zope3/src/zope/app/services/tests/placefulsetup.py	Mon Mar  3 18:16:14 2003
@@ -38,6 +38,14 @@
 from zope.app.traversing import traverse, getPhysicalPathString
 from zope.app.services.service import ServiceManager, ServiceConfiguration
 from zope.app.interfaces.services.configuration import Active
+from zope.app.interfaces.services.configuration import IAttributeUseConfigurable
+from zope.app.interfaces.services.configuration import IUseConfiguration
+from zope.app.services.configuration import UseConfiguration
+from zope.app.attributeannotations import AttributeAnnotations
+from zope.app.interfaces.annotation import IAttributeAnnotatable
+from zope.app.interfaces.annotation import IAnnotations
+from zope.app.interfaces.dependable import IDependable
+from zope.app.dependable import Dependable
 
 class PlacefulSetup(PlacelessSetup):
 
@@ -60,6 +68,13 @@
         provideAdapter(
             IContainmentRoot, IPhysicallyLocatable, RootPhysicallyLocatable)
 
+        provideAdapter(IAttributeUseConfigurable, IUseConfiguration,
+                       UseConfiguration)
+        provideAdapter(IAttributeAnnotatable, IAnnotations,
+                       AttributeAnnotations)
+
+        provideAdapter(IAttributeAnnotatable, IDependable, Dependable)
+
         # set up etc namespace
         provideNamespaceHandler("etc", etc)
 
@@ -156,12 +171,13 @@
         default.setObject(service_name, EventService())
 
         path = "%s/%s" % (getPhysicalPathString(default), service_name)
-        configuration = ServiceConfiguration(Events, path)
+        configuration = ServiceConfiguration(Events, path, self.rootFolder)
         default['configure'].setObject(
                 "%sEventsDir" % service_name, configuration)
         traverse(default, 'configure/1').status = Active
 
-        configuration = ServiceConfiguration(Subscription, path)
+        configuration = ServiceConfiguration(Subscription, path,
+                                             self.rootFolder)
         default['configure'].setObject(
                 "%sSubscriptionServiceDir" % service_name, configuration)
         traverse(default, 'configure/2').status = Active
@@ -175,7 +191,7 @@
             raise RuntimeError('ServiceManager already exists, so cannot '
                                'create standard services')
         root.setServiceManager(ServiceManager())
-        from zope.component import getServiceManager        
+        from zope.component import getServiceManager
         defineService = getServiceManager(None).defineService
 
         from zope.app.interfaces.services.hub import IObjectHub
@@ -194,17 +210,18 @@
         default.setObject("myObjectHub", self.getObjectHub())
 
         path = "%s/Packages/default/myEventService" % getPhysicalPathString(sm)
-        configuration = ServiceConfiguration(Events, path)
+        configuration = ServiceConfiguration(Events, path, self.rootFolder)
         default['configure'].setObject("myEventServiceDir", configuration)
         traverse(default, 'configure/1').status = Active
 
-        configuration = ServiceConfiguration(Subscription, path)
+        configuration = ServiceConfiguration(Subscription, path,
+                                             self.rootFolder)
         default['configure'].setObject(
                 "mySubscriptionServiceDir", configuration)
         traverse(default, 'configure/2').status = Active
 
         path = "%s/Packages/default/myObjectHub" % getPhysicalPathString(sm)
-        configuration = ServiceConfiguration(HubIds, path)
+        configuration = ServiceConfiguration(HubIds, path, self.rootFolder)
         default['configure'].setObject("myHubIdsServiceDir", configuration)
         traverse(default, 'configure/3').status = Active
 


=== Zope3/src/zope/app/services/tests/test_cacheconfiguration.py 1.2 => 1.3 ===
--- Zope3/src/zope/app/services/tests/test_cacheconfiguration.py:1.2	Wed Dec 25 09:13:20 2002
+++ Zope3/src/zope/app/services/tests/test_cacheconfiguration.py	Mon Mar  3 18:16:14 2003
@@ -27,6 +27,7 @@
 from zope.app.interfaces.dependable import IDependable
 from zope.app.interfaces.cache.cache import ICachingService
 from zope.app.interfaces.services.configuration import IConfigurable
+from zope.app.interfaces.services.configuration import IAttributeUseConfigurable
 from zope.app.services.configuration import ConfigurationRegistry
 from zope.app.services.service import ServiceConfiguration
 from zope.proxy.context import ContextMethod
@@ -58,7 +59,8 @@
 
 class CachingServiceStub(DependableStub):
 
-    __implements__ = ICachingService, IConfigurable, IDependable
+    __implements__ = (ICachingService, IConfigurable, IDependable,
+                      IAttributeUseConfigurable)
 
     def __init__(self):
         self.bindings = {}


=== Zope3/src/zope/app/services/tests/test_connectionconfiguration.py 1.2 => 1.3 ===
--- Zope3/src/zope/app/services/tests/test_connectionconfiguration.py:1.2	Wed Dec 25 09:13:20 2002
+++ Zope3/src/zope/app/services/tests/test_connectionconfiguration.py	Mon Mar  3 18:16:14 2003
@@ -36,6 +36,7 @@
 from zope.app.services.service import ServiceConfiguration
 from zope.proxy.context import ContextMethod
 from zope.proxy.context import ContextWrapper
+from zope.app.interfaces.services.configuration import IAttributeUseConfigurable
 
 class DependableStub:
 
@@ -58,7 +59,8 @@
 
 class ConnectionServiceStub(DependableStub):
 
-    __implements__ = IConnectionService, IConfigurable, IDependable
+    __implements__ = (IConnectionService, IConfigurable, IDependable,
+                      IAttributeUseConfigurable)
 
     def __init__(self):
         self.bindings = {}


=== Zope3/src/zope/app/services/tests/test_connectionservice.py 1.2 => 1.3 ===
--- Zope3/src/zope/app/services/tests/test_connectionservice.py:1.2	Wed Dec 25 09:13:20 2002
+++ Zope3/src/zope/app/services/tests/test_connectionservice.py	Mon Mar  3 18:16:14 2003
@@ -42,11 +42,12 @@
      import Active, Unregistered, Registered
 from zope.app.services.connection \
      import ConnectionConfiguration
+from zope.app.interfaces.services.configuration import IAttributeUseConfigurable
 
 
 class ConnectionServiceForTests(ConnectionService):
 
-    __implements__ = ConnectionService.__implements__, IAttributeAnnotatable
+    __implements__ = ConnectionService.__implements__, IAttributeUseConfigurable
 
 class DAStub:
 


=== Zope3/src/zope/app/services/tests/test_eventservice.py 1.10 => 1.11 ===
--- Zope3/src/zope/app/services/tests/test_eventservice.py:1.10	Tue Feb 11 21:17:34 2003
+++ Zope3/src/zope/app/services/tests/test_eventservice.py	Mon Mar  3 18:16:14 2003
@@ -42,6 +42,7 @@
 from zope.app.services.tests.eventsetup import EventSetup
 from zope.component.tests.components import RecordingAdapter
 from zope.component.adapter import provideAdapter
+from zope.app.interfaces.services.interfaces import ISimpleService
 
 class UnpromotingEventService(EventService):
 
@@ -68,7 +69,7 @@
         "gets location"
 
 class DumbObjectHub:
-    __implements__ = IObjectHub
+    __implements__ = IObjectHub, ISimpleService
 
     def __init__(self):
         # (location, object)


=== Zope3/src/zope/app/services/tests/test_serviceconfiguration.py 1.3 => 1.4 ===
--- Zope3/src/zope/app/services/tests/test_serviceconfiguration.py:1.3	Wed Feb 26 11:11:37 2003
+++ Zope3/src/zope/app/services/tests/test_serviceconfiguration.py	Mon Mar  3 18:16:14 2003
@@ -22,15 +22,17 @@
 
 from zope.interface import Interface
 
-from zope.component import getServiceManager
+from zope.component import getServiceManager, getAdapter
 from zope.app.traversing import traverse
 from zope.app.services.service import ServiceConfiguration
 from zope.app.services.tests.placefulsetup import PlacefulSetup
 from zope.app.services.service import ServiceManager
-from zope.component.service import serviceManager
+from zope.component.service import defineService
 from zope.app.interfaces.services.service import IBindingAware
 from zope.app.interfaces.services.configuration import Active, Unregistered
 from zope.app.interfaces.services.configuration import Registered
+from zope.app.interfaces.services.configuration import IUseConfiguration
+from zope.app.interfaces.services.interfaces import ISimpleService
 
 from zope.app.interfaces.dependable import IDependable
 from zope.app.interfaces.dependable import DependencyError
@@ -41,8 +43,8 @@
 class ITestService(Interface):
     pass
 
-class TestService:
-    __implements__ = ITestService, IBindingAware, IDependable
+class TestServiceBase:
+    __implements__ = (ITestService, IBindingAware, IDependable)
 
     _bound = _unbound = ()
 
@@ -69,13 +71,16 @@
     def dependents(self):
         return self._dependents
 
+class TestService(TestServiceBase):
+    __implements__ = TestServiceBase.__implements__, ISimpleService
+
 class Test(PlacefulSetup, TestCase):
 
     def setUp(self):
         PlacefulSetup.setUp(self)
         self.buildFolders()
         self.rootFolder.setServiceManager(ServiceManager())
-        serviceManager.defineService('test_service', ITestService)
+        defineService('test_service', ITestService)
         default = traverse(self.rootFolder,
                            '++etc++Services/Packages/default')
         self.__default = default
@@ -115,6 +120,9 @@
     def test_afterAddHook(self):
         self.assertEqual(self.__c._dependents,
                          ('/++etc++Services/Packages/default/configure/1', ))
+        u = getAdapter(self.__c, IUseConfiguration)
+        self.assertEqual(list(u.usages()),
+                         ['/++etc++Services/Packages/default/configure/1'])
 
     def test_beforeDeleteHook_and_unregistered(self):
         self.__config.status = Registered
@@ -125,6 +133,8 @@
 
         del self.__cm['1']
         self.assertEqual(self.__c._dependents, ())
+        u = getAdapter(self.__c, IUseConfiguration)
+        self.assertEqual(len(u.usages()), 0)
 
         self.failIf(registry, "The components should not be registered")
 
@@ -136,6 +146,18 @@
             pass # OK
         else:
             self.failUnless(0, "Should have gotten a depency error")
+
+    def test_not_a_local_service(self):
+        defineService('test_service_2', ITestService)
+        self.__default.setObject('c2', TestServiceBase())
+
+        self.assertRaises(
+            TypeError,
+            ServiceConfiguration,
+            'test_service',
+            '/++etc++Services/Packages/default/c2',
+            self.__default
+            )
 
 
 def test_suite():