[z3-checkins] r9785 - in z3/Five/branch/paris-local-sitemanager-branch: . doc tests tests/products/FiveTest

dreamcatcher at codespeak.net dreamcatcher at codespeak.net
Tue Mar 15 13:39:21 MET 2005


Author: dreamcatcher
Date: Tue Mar 15 13:39:21 2005
New Revision: 9785

Added:
   z3/Five/branch/paris-local-sitemanager-branch/localsite.py   (contents, props changed)
   z3/Five/branch/paris-local-sitemanager-branch/tests/products/FiveTest/localsite.py   (contents, props changed)
Removed:
   z3/Five/branch/paris-local-sitemanager-branch/adapter.py
Modified:
   z3/Five/branch/paris-local-sitemanager-branch/   (props changed)
   z3/Five/branch/paris-local-sitemanager-branch/__init__.py
   z3/Five/branch/paris-local-sitemanager-branch/configure.zcml
   z3/Five/branch/paris-local-sitemanager-branch/doc/features.txt
   z3/Five/branch/paris-local-sitemanager-branch/fiveconfigure.py
   z3/Five/branch/paris-local-sitemanager-branch/tests/products/FiveTest/__init__.py
   z3/Five/branch/paris-local-sitemanager-branch/tests/products/FiveTest/classes.py
   z3/Five/branch/paris-local-sitemanager-branch/tests/products/FiveTest/configure.zcml
   z3/Five/branch/paris-local-sitemanager-branch/tests/products/FiveTest/interfaces.py
   z3/Five/branch/paris-local-sitemanager-branch/tests/test_localservice.py
   z3/Five/branch/paris-local-sitemanager-branch/traversable.py
Log:

- Moved some code around at Martijn's request into localsite.py
- Added tests for a Local Site with utilities stored in a folder


Modified: z3/Five/branch/paris-local-sitemanager-branch/__init__.py
==============================================================================
--- z3/Five/branch/paris-local-sitemanager-branch/__init__.py	(original)
+++ z3/Five/branch/paris-local-sitemanager-branch/__init__.py	Tue Mar 15 13:39:21 2005
@@ -25,13 +25,3 @@
 
 def initialize(context):
     zcml.load_site()
-
-    import traversable
-    context.registerClass(
-        meta_type='Five: Add Local Site Hook',
-        permission='Manage Access Rules',
-        constructors=(traversable.manage_addLocalSiteHook,))
-    context.registerClass(
-        meta_type='Five: Remove Local Site Hook',
-        permission='Manage Access Rules',
-        constructors=(traversable.manage_removeLocalSiteHook,))

Deleted: /z3/Five/branch/paris-local-sitemanager-branch/adapter.py
==============================================================================
--- /z3/Five/branch/paris-local-sitemanager-branch/adapter.py	Tue Mar 15 13:39:21 2005
+++ (empty file)
@@ -1,31 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004 Five Contributors. All rights reserved.
-#
-# This software is distributed under the terms of the Zope Public
-# License (ZPL) v2.1. See COPYING.txt for more information.
-#
-##############################################################################
-"""Generic Components ZCML Handlers
-
-$Id: metaconfigure.py 9769 2005-03-14 17:37:00Z dreamcatcher $
-"""
-from Acquisition import aq_inner, aq_parent
-from zope.app.site.interfaces import ISite
-from zope.component.exceptions import ComponentLookupError
-
-def serviceServiceAdapter(ob):
-    """An adapter * -> IServiceService.
-
-    This is registered in place of the one in Zope 3 so that we lookup
-    using acquisition instead of ILocation.
-    """
-    current = ob
-    while True:
-        if ISite.providedBy(current):
-            return current.getSiteManager()
-        current = aq_parent(aq_inner(current))
-        if current is None:
-            raise ComponentLookupError("Could not adapt %r to"
-                                       " IServiceService" % (ob, ))
-

Modified: z3/Five/branch/paris-local-sitemanager-branch/configure.zcml
==============================================================================
--- z3/Five/branch/paris-local-sitemanager-branch/configure.zcml	(original)
+++ z3/Five/branch/paris-local-sitemanager-branch/configure.zcml	Tue Mar 15 13:39:21 2005
@@ -111,7 +111,7 @@
       />
 
   <adapter
-      factory=".adapter.serviceServiceAdapter"
+      factory=".localsite.serviceServiceAdapter"
       provides="zope.component.IServiceService"
       for="zope.interface.Interface"
       />

Modified: z3/Five/branch/paris-local-sitemanager-branch/doc/features.txt
==============================================================================
--- z3/Five/branch/paris-local-sitemanager-branch/doc/features.txt	(original)
+++ z3/Five/branch/paris-local-sitemanager-branch/doc/features.txt	Tue Mar 15 13:39:21 2005
@@ -84,3 +84,23 @@
 ignored by views anyway, as they are trusted -- it only serves to
 protect directly exposed methods on content classes (the python
 scripts and the ZPublisher).
+
+Local Site Manager
+==================
+
+Five can support the concept of a Local Site Manager. The steps for
+creating one are:
+
+  - Register your Zope 2 class with the 'local site hook' using the
+    <five:localsitehook> directive. Doing that will mixin the FiveSite
+    class into your class by means of 'structured monkey patching'.
+
+  - Implement an ``IFiveSite`` adapter for your Zope 2 class. For the full
+    interface definition refer to
+    ``Products.Five.interfaces.IFiveSite``.
+
+  - To enable the Local Site Hook for an instance of your class, use::
+
+    from Products.Five.localsite import enableLocalSiteHook
+    enableLocalSiteHook(obj)
+

Modified: z3/Five/branch/paris-local-sitemanager-branch/fiveconfigure.py
==============================================================================
--- z3/Five/branch/paris-local-sitemanager-branch/fiveconfigure.py	(original)
+++ z3/Five/branch/paris-local-sitemanager-branch/fiveconfigure.py	Tue Mar 15 13:39:21 2005
@@ -19,9 +19,10 @@
 from zope.interface import classImplements
 from zope.configuration import xmlconfig
 from zope.app.component.interface import provideInterface
+from zope.app.site.interfaces import IPossibleSite
 from viewable import Viewable
 from traversable import Traversable
-from traversable import FiveSite
+from localsite import FiveSite
 from bridge import fromZ2Interface
 from browserconfigure import page
 
@@ -213,3 +214,8 @@
         callable = classFiveSiteHook,
         args=(class_,)
         )
+    _context.action(
+        discriminator = None,
+        callable = classImplements,
+        args=(class_, IPossibleSite)
+        )

Added: z3/Five/branch/paris-local-sitemanager-branch/localsite.py
==============================================================================
--- (empty file)
+++ z3/Five/branch/paris-local-sitemanager-branch/localsite.py	Tue Mar 15 13:39:21 2005
@@ -0,0 +1,89 @@
+##############################################################################
+#
+# Copyright (c) 2004 Five Contributors. All rights reserved.
+#
+# This software is distributed under the terms of the Zope Public
+# License (ZPL) v2.1. See COPYING.txt for more information.
+#
+##############################################################################
+"""
+$Id: traversable.py 9776 2005-03-15 09:18:43Z dreamcatcher $
+"""
+
+from zope.event import notify
+from zope.interface import directlyProvides, directlyProvidedBy
+from zope.component.exceptions import ComponentLookupError
+from zope.app.site.interfaces import ISite
+from zope.app.site.interfaces import IPossibleSite
+from zope.app.publication.zopepublication import BeforeTraverseEvent
+
+from interfaces import IFiveSite
+from ExtensionClass import Base
+from Acquisition import aq_base, aq_inner, aq_parent
+from Products.SiteAccess.AccessRule import AccessRule
+from ZPublisher.BeforeTraverse import registerBeforeTraverse
+from ZPublisher.BeforeTraverse import unregisterBeforeTraverse
+
+class FiveSite:
+
+    def getSiteManager(self):
+        adapted = IFiveSite(self, None)
+        if adapted is None:
+            return None
+        return adapted.getSiteManager()
+
+    def setSiteManager(self, sm):
+        adapted = IFiveSite(self, None)
+        if adapted is None:
+            return None
+        return adapted.setSiteManager(sm)
+
+def serviceServiceAdapter(ob):
+    """An adapter * -> IServiceService.
+
+    This is registered in place of the one in Zope 3 so that we lookup
+    using acquisition instead of ILocation.
+    """
+    current = ob
+    while True:
+        if ISite.providedBy(current):
+            return current.getSiteManager()
+        current = aq_parent(aq_inner(current))
+        if current is None:
+            raise ComponentLookupError("Could not adapt %r to"
+                                       " IServiceService" % (ob, ))
+
+HOOK_NAME = '__local_site_hook__'
+
+class LocalSiteHook(Base):
+    def __call__(self, container, request):
+        notify(BeforeTraverseEvent(container, request))
+
+
+def enableLocalSiteHook(obj):
+    """Install __before_traverse__ hook for Local Site
+    """
+    # We want the original object, not stuff in between, and no acquisition
+    obj = aq_base(obj)
+    if not IPossibleSite.providedBy(obj):
+        raise TypeError, 'Must provide IPossibleSite'
+    hook = AccessRule(HOOK_NAME)
+    registerBeforeTraverse(obj, hook, HOOK_NAME, 1)
+
+    if not hasattr(obj, HOOK_NAME):
+        setattr(obj, HOOK_NAME, LocalSiteHook())
+
+    directlyProvides(obj, ISite, directlyProvidedBy(obj))
+
+def disableLocalSiteHook(obj):
+    """Remove __before_traverse__ hook for Local Site
+    """
+    # We want the original object, not stuff in between, and no acquisition
+    obj = aq_base(obj)
+    if not ISite.providedBy(obj):
+        raise TypeError, 'Must provide IPossibleSite'
+    rules = unregisterBeforeTraverse(obj, HOOK_NAME)
+    if hasattr(obj, HOOK_NAME):
+        delattr(obj, HOOK_NAME)
+
+    directlyProvides(obj, directlyProvidedBy(obj) - ISite)

Modified: z3/Five/branch/paris-local-sitemanager-branch/tests/products/FiveTest/__init__.py
==============================================================================
--- z3/Five/branch/paris-local-sitemanager-branch/tests/products/FiveTest/__init__.py	(original)
+++ z3/Five/branch/paris-local-sitemanager-branch/tests/products/FiveTest/__init__.py	Tue Mar 15 13:39:21 2005
@@ -1,5 +1,6 @@
 import simplecontent
 import fancycontent
+import localsite
 
 def initialize(context):
 
@@ -32,5 +33,7 @@
                         simplecontent.manage_addFieldSimpleContent,)
         )
 
-
-
+    context.registerClass(
+        localsite.DummySite,
+        constructors = (localsite.manage_addDummySite,)
+        )

Modified: z3/Five/branch/paris-local-sitemanager-branch/tests/products/FiveTest/classes.py
==============================================================================
--- z3/Five/branch/paris-local-sitemanager-branch/tests/products/FiveTest/classes.py	(original)
+++ z3/Five/branch/paris-local-sitemanager-branch/tests/products/FiveTest/classes.py	Tue Mar 15 13:39:21 2005
@@ -36,3 +36,4 @@
 
     def method(self):
         return "Overridden"
+

Modified: z3/Five/branch/paris-local-sitemanager-branch/tests/products/FiveTest/configure.zcml
==============================================================================
--- z3/Five/branch/paris-local-sitemanager-branch/tests/products/FiveTest/configure.zcml	(original)
+++ z3/Five/branch/paris-local-sitemanager-branch/tests/products/FiveTest/configure.zcml	Tue Mar 15 13:39:21 2005
@@ -295,7 +295,7 @@
       />
 
   <five:traversable class="OFS.ObjectManager.ObjectManager" />
-  
+
   <browser:addform
      schema=".interfaces.IFieldSimpleContent"
      content_factory=".simplecontent.FieldSimpleContent"
@@ -420,4 +420,14 @@
 
   <include package="zope.app.form.browser"/>
 
+  <adapter
+      for=".interfaces.IDummySite"
+      provides="Products.Five.interfaces.IFiveSite"
+      factory=".localsite.SimpleFiveSiteAdapter"
+      />
+
+  <five:localsitehook
+      class=".localsite.DummySite"
+      />
+
 </configure>

Modified: z3/Five/branch/paris-local-sitemanager-branch/tests/products/FiveTest/interfaces.py
==============================================================================
--- z3/Five/branch/paris-local-sitemanager-branch/tests/products/FiveTest/interfaces.py	(original)
+++ z3/Five/branch/paris-local-sitemanager-branch/tests/products/FiveTest/interfaces.py	Tue Mar 15 13:39:21 2005
@@ -37,6 +37,9 @@
 class IFancyContent(Interface):
     pass
 
+class IDummySite(Interface):
+    pass
+
 class IFieldSimpleContent(ISimpleContent):
     title = TextLine(
         title=u"Title",

Added: z3/Five/branch/paris-local-sitemanager-branch/tests/products/FiveTest/localsite.py
==============================================================================
--- (empty file)
+++ z3/Five/branch/paris-local-sitemanager-branch/tests/products/FiveTest/localsite.py	Tue Mar 15 13:39:21 2005
@@ -0,0 +1,92 @@
+from zope.interface import implements
+from zope.component.servicenames import Utilities
+from zope.component.exceptions import ComponentLookupError
+from zope.component import getGlobalServices
+from zope.component.interfaces import IServiceService
+from zope.component.interfaces import IUtilityService
+from zope.component.exceptions import ComponentLookupError
+
+from OFS.Folder import Folder
+from Products.FiveTest.interfaces import IDummySite
+
+class SimpleService:
+    implements(IServiceService)
+
+    def __init__(self, context):
+        self.context = context
+
+    def getServiceDefinitions(self):
+        """Retrieve all Service Definitions
+
+        Should return a list of tuples (name, interface)
+        """
+        return getGlobalServices().getServiceDefinitions()
+
+    def getInterfaceFor(self, name):
+        """Retrieve the service interface for the given name
+        """
+        return getGlobalServices().getInterfaceFor(name)
+
+    def getService(self, name):
+        """Retrieve a service implementation
+
+        Raises ComponentLookupError if the service can't be found.
+        """
+        if name == Utilities:
+            return SimpleLocalUtilityService(self.context)
+        return getGlobalServices().getService(name)
+
+class SimpleLocalUtilityService:
+    implements(IUtilityService)
+
+    def __init__(self, context):
+        self.context = context
+
+    def getUtility(self, interface, name=''):
+        """See IUtilityService interface
+        """
+        c = self.queryUtility(interface, name)
+        if c is not None:
+            return c
+        raise ComponentLookupError(interface, name)
+
+    def queryUtility(self, interface, name='', default=None):
+        """See IUtilityService interface
+        """
+        utilities = getattr(self.context, 'utilities')
+        utility = utilities._getOb(name, None)
+        if utility is None:
+            return default
+        if not interface.providedBy(utility):
+            return default
+        return utility
+
+    def getUtilitiesFor(self, interface):
+        utilities = getattr(self.context, 'utilities')
+        for utility in utilities.objectValues():
+            if interface.providedBy(utility):
+                yield utility
+
+    def getAllUtilitiesRegisteredFor(self, interface):
+        return ()
+
+class SimpleFiveSiteAdapter:
+
+    def __init__(self, context):
+        self.context = context
+
+    def getSiteManager(self):
+        return SimpleService(self.context)
+
+    def setSiteManager(self, sm):
+        return
+
+class DummySite(Folder):
+    """A very dummy Site
+    """
+    implements(IDummySite)
+
+def manage_addDummySite(self, id, REQUEST=None):
+    """Add the dummy site."""
+    id = self._setObject(id, DummySite(id))
+    return ''

Modified: z3/Five/branch/paris-local-sitemanager-branch/tests/test_localservice.py
==============================================================================
--- z3/Five/branch/paris-local-sitemanager-branch/tests/test_localservice.py	(original)
+++ z3/Five/branch/paris-local-sitemanager-branch/tests/test_localservice.py	Tue Mar 15 13:39:21 2005
@@ -5,20 +5,25 @@
 
 import unittest
 from Testing import ZopeTestCase
+ZopeTestCase.installProduct('FiveTest')
 ZopeTestCase.installProduct('Five')
 
-from zope.component import getGlobalServices, getServices
-from zope.app.component.hooks import getServices_hook
-from zope.app.site.interfaces import IPossibleSite, ISite, ISiteManager
-from zope.app.traversing.interfaces import IContainmentRoot
+from zope.interface import implements
+from zope.interface import directlyProvides, directlyProvidedBy
+from zope.interface import Interface
 from zope.component.exceptions import ComponentLookupError
 from zope.component.interfaces import IServiceService
 from zope.component.service import serviceManager
-from zope.interface import implements, directlyProvides, directlyProvidedBy
+from zope.component.servicenames import Utilities
+from zope.component import getGlobalServices, getServices, getService
+from zope.app.component.hooks import getServices_hook
 from zope.app.component.hooks import setSite, getSite
+from zope.app.site.interfaces import IPossibleSite, ISite, ISiteManager
+from zope.app.traversing.interfaces import IContainmentRoot
 
 from Acquisition import Implicit
 from OFS.ObjectManager import ObjectManager
+from OFS.SimpleItem import SimpleItem
 
 class ServiceManager(Implicit):
     implements(ISiteManager)
@@ -60,6 +65,12 @@
 def Wrapper(ob, container):
     return ob.__of__(container)
 
+class IDummyUtility(Interface):
+    pass
+
+class DummyUtility(SimpleItem):
+    implements(IDummyUtility)
+
 class Test(ZopeTestCase.ZopeTestCase):
 
     def afterSetUp(self):
@@ -200,7 +211,7 @@
                           getLocalServices, unrooted_subfolder)
 
     def test_serviceServiceAdapter(self):
-        from Products.Five.adapter import serviceServiceAdapter
+        from Products.Five.localsite import serviceServiceAdapter
 
         # If it is a site, return the service service.
         ss = ServiceServiceStub()
@@ -258,19 +269,21 @@
         clearSite()
 
     def test_before_traversal_event(self):
-        self.folder.manage_addProduct['Five'].manage_addLocalSiteHook()
+        from Products.Five.localsite import enableLocalSiteHook
+        enableLocalSiteHook(self.folder)
         path = '/'.join(self.folder.getPhysicalPath())
         response = self.publish(path)
         self.assertEqual(getSite(), self.folder)
 
     def test_before_traversal_event_and_hook(self):
+        from Products.Five.localsite import enableLocalSiteHook
         f1 = Folder()
         f1.id = 'f1'
         self.folder._setObject('f1', f1)
         f1 = self.folder._getOb('f1')
         ss = ServiceServiceStub()
         f1.setSiteManager(ss)
-        f1.manage_addProduct['Five'].manage_addLocalSiteHook()
+        enableLocalSiteHook(f1)
         path = '/'.join(f1.getPhysicalPath())
         response = self.publish(path)
         self.assertEqual(getServices(), ss)
@@ -280,11 +293,52 @@
         response = self.publish(path)
         self.assertEqual(getSite(), None)
 
+class LocalUtilityServiceTest(ZopeTestCase.FunctionalTestCase):
+
+    def afterSetUp(self):
+        from Products.Five.localsite import enableLocalSiteHook
+        self.folder.manage_addProduct['FiveTest'].manage_addDummySite('site')
+        self.site = self.folder.site
+        self.site.manage_addFolder('utilities')
+        self.utils = self.site.utilities
+        enableLocalSiteHook(self.site)
+        self.path = '/'.join(self.site.getPhysicalPath())
+        # Traverse to the site so that the local-thread site gets
+        # setup correctly.
+        self.publish(self.path)
+
+    def beforeTearDown(self):
+        from zope.app.component.localservice import clearSite
+        clearSite()
+
+    def test_getServicesHook(self):
+        from Products.FiveTest.localsite import SimpleService
+        local_sm = getServices(None)
+        self.failIf(local_sm is serviceManager)
+        self.failUnless(isinstance(local_sm, SimpleService))
+
+        local_sm = getServices(self.site)
+        self.failIf(local_sm is serviceManager)
+        self.failUnless(isinstance(local_sm, SimpleService))
+
+    def test_getUtilityService(self):
+        from Products.FiveTest.localsite import SimpleLocalUtilityService
+        utils = getService(Utilities)
+        self.failUnless(isinstance(utils, SimpleLocalUtilityService))
+
+        self.assertRaises(ComponentLookupError, utils.getUtility, IDummyUtility)
+
+        self.utils._setObject('dummy', DummyUtility('dummy'))
+        dummy = self.utils._getOb('dummy')
+        self.assertEquals(utils.getUtility(IDummyUtility, name='dummy'), dummy)
+
+        self.assertEquals(list(utils.getUtilitiesFor(IDummyUtility)), [dummy])
 
 def test_suite():
     suite = unittest.TestSuite()
     suite.addTest(unittest.makeSuite(Test))
     suite.addTest(unittest.makeSuite(BeforeTraversalTest))
+    suite.addTest(unittest.makeSuite(LocalUtilityServiceTest))
     return suite
 
 if __name__ == '__main__':

Modified: z3/Five/branch/paris-local-sitemanager-branch/traversable.py
==============================================================================
--- z3/Five/branch/paris-local-sitemanager-branch/traversable.py	(original)
+++ z3/Five/branch/paris-local-sitemanager-branch/traversable.py	Tue Mar 15 13:39:21 2005
@@ -11,27 +11,17 @@
 $Id$
 """
 from zExceptions import NotFound
-from zope.event import notify
 from zope.exceptions import NotFoundError
 from zope.component import getView, ComponentLookupError
 from zope.interface import implements
-from zope.interface import directlyProvides, directlyProvidedBy
 from zope.publisher.interfaces.browser import IBrowserRequest
 from zope.security.management import thread_local
-from zope.app.site.interfaces import ISite
 from zope.app.traversing.interfaces import ITraverser, ITraversable
 from zope.app.traversing.adapters import DefaultTraversable
 from zope.app.traversing.adapters import traversePathElement
-from zope.app.publication.zopepublication import BeforeTraverseEvent
 from monkey import DebugFlags
-from interfaces import IFiveSite
 
-from Globals import MessageDialog
 from AccessControl import getSecurityManager
-from ExtensionClass import Base
-from Products.SiteAccess.AccessRule import AccessRule
-from ZPublisher.BeforeTraverse import registerBeforeTraverse
-from ZPublisher.BeforeTraverse import unregisterBeforeTraverse
 
 _marker = object
 
@@ -122,64 +112,3 @@
         # If a view can't be found, then use default traversable
         return super(FiveTraversable, self).traverse(name, furtherPath)
 
-class FiveSite:
-
-    def getSiteManager(self):
-        adapted = IFiveSite(self, None)
-        if adapted is None:
-            return None
-        return adapted.getSiteManager()
-
-    def setSiteManager(self, sm):
-        adapted = IFiveSite(self, None)
-        if adapted is None:
-            return None
-        return adapted.setSiteManager(sm)
-
-HOOK_NAME = '__local_site_hook__'
-
-class LocalSiteHook(Base):
-
-    meta_type = 'Five Local Site Hook'
-
-    def __call__(self, container, request):
-        notify(BeforeTraverseEvent(container, request))
-
-
-def manage_addLocalSiteHook(self, REQUEST=None, **ignored):
-    """Install __before_traverse__ hook for Local Site
-    """
-    # We want the original object, not stuff in between, and no acquisition
-    self = self.this()
-    self = getattr(self, 'aq_base', self)
-
-    hook = AccessRule(HOOK_NAME)
-    registerBeforeTraverse(self, hook, HOOK_NAME, 1)
-
-    if not hasattr(self, HOOK_NAME):
-        setattr(self, HOOK_NAME, LocalSiteHook())
-
-    directlyProvides(self, ISite, directlyProvidedBy(self))
-
-    if REQUEST is not None:
-        return MessageDialog(
-            title='Local Site Hook',
-            message='Local Site Hook has been enabled for this object',
-            action='%s/manage_main' % REQUEST['URL1'])
-
-def manage_removeLocalSiteHook(self, REQUEST=None, **ignored):
-    """Remove __before_traverse__ hook for Local Site
-    """
-    # We want the original object, not stuff in between, and no acquisition
-    self = self.this()
-    self = getattr(self, 'aq_base', self)
-
-    rules = unregisterBeforeTraverse(self, HOOK_NAME)
-    if hasattr(self, HOOK_NAME):
-        delattr(self, HOOK_NAME)
-
-    if REQUEST is not None:
-        return MessageDialog(
-            title='Local Site Hook',
-            message='Local Site Hook has been disabled for this object',
-            action='%s/manage_main' % REQUEST['URL1'])


More information about the z3-checkins mailing list