[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