[Zope3-checkins] SVN: Zope3/trunk/src/zope/app/ Made getServices()
to use the site stored as a thread global for local
Albertas Agejevas
alga at pov.lt
Fri May 21 21:56:54 EDT 2004
Log message for revision 24871:
Made getServices() to use the site stored as a thread global for local
services lookup. ZopePublication sends events before traversing each
object, and the site thread global is set by a subscriber to that
event if the object being traversed is an ISite.
-=-
Modified: Zope3/trunk/src/zope/app/component/configure.zcml
===================================================================
--- Zope3/trunk/src/zope/app/component/configure.zcml 2004-05-22 01:56:42 UTC (rev 24870)
+++ Zope3/trunk/src/zope/app/component/configure.zcml 2004-05-22 01:56:54 UTC (rev 24871)
@@ -1,51 +1,67 @@
<configure
xmlns="http://namespaces.zope.org/zope"
- >
+ xmlns:event="http://namespaces.zope.org/event"
+ >
- <serviceType
+ <serviceType
id="Utilities"
interface="zope.component.interfaces.IUtilityService" />
-
- <service
+
+ <service
serviceType="Utilities"
permission="zope.Public"
factory="zope.component.utility.GlobalUtilityService" />
-
- <serviceType
+
+ <serviceType
id="Adapters"
interface="zope.component.interfaces.IAdapterService" />
-
- <service
+
+ <service
serviceType="Adapters"
permission="zope.Public"
factory="zope.component.adapter.GlobalAdapterService" />
-
- <serviceType
+
+ <serviceType
id="Presentation"
interface="zope.component.interfaces.IPresentationService" />
-
- <service
+
+ <service
serviceType="Presentation"
permission="zope.Public"
factory="zope.component.presentation.GlobalPresentationService" />
-
+
<vocabulary
name="Interfaces"
factory="zope.app.utility.vocabulary.UtilityVocabulary"
interface="zope.interface.interfaces.IInterface" />
-
- <hook
+
+ <hook
module="zope.component"
- name="getServiceManager"
- implementation="zope.app.component.hooks.getServiceManager_hook" />
-
- <hook
+ name="getServices"
+ implementation="zope.app.component.hooks.getServices_hook" />
+
+ <hook
module="zope.component"
name="queryView"
implementation="zope.app.component.hooks.queryView" />
-
+
<interface interface="zope.interface.Interface" />
+ <adapter
+ factory=".localservice.serviceServiceAdapter"
+ provides="zope.component.IServiceService"
+ for="zope.interface.Interface" />
+
+ <event:subscribe
+ subscriber=".localservice.threadSiteSubscriber"
+ event_types="zope.app.publication.interfaces.IBeforeTraverseEvent"
+ />
+
+ <event:subscribe
+ subscriber=".localservice.clearThreadSiteSubscriber"
+ event_types="zope.app.publication.interfaces.IEndRequestEvent"
+ />
+
</configure>
Modified: Zope3/trunk/src/zope/app/component/hooks.py
===================================================================
--- Zope3/trunk/src/zope/app/component/hooks.py 2004-05-22 01:56:42 UTC (rev 24870)
+++ Zope3/trunk/src/zope/app/component/hooks.py 2004-05-22 01:56:54 UTC (rev 24871)
@@ -16,10 +16,12 @@
$Id$
"""
-from zope.component import getService
+import warnings
+from zope.component import getService, getAdapter, queryAdapter
from zope.component.interfaces import IServiceService
from zope.app.site.interfaces import ISite
from zope.component.service import serviceManager
+from zope.component.exceptions import ComponentLookupError
from zope.proxy import removeAllProxies
from zope.security.proxy import trustedRemoveSecurityProxy
from zope.app.traversing import IContainmentRoot
@@ -27,44 +29,34 @@
from zope.app.location import locate
from zope.component.servicenames import Presentation
from zope.interface import Interface
+from zope.thread import thread_globals
-def getServiceManager_hook(context, local=False, recurse=False):
+def getServices_hook(context=None):
if context is None:
- return serviceManager
-
- clean_context = removeAllProxies(context)
-
- # if the context is actually a service or site manager...
- if IServiceService.providedBy(clean_context):
- return trustedRemoveSecurityProxy(context)
-
- elif (ISite.providedBy(clean_context)):
- return trustedRemoveSecurityProxy(context.getSiteManager())
- else:
- container = getattr(context, '__parent__', None)
- if container is None:
- if local:
- # Check to make sure that when we run out of context, we
- # have a root object:
- if not IContainmentRoot.providedBy(context):
- raise TypeError("Not enough context to get next "
- "site manager")
-
- # Fall back to global:
- sm = serviceManager
+ site = thread_globals().site
+ if site is None:
+ return serviceManager
else:
- # We have a container, so context is a wrapper. We still
- # don't have a site manager, so try again, recursively:
- sm = getServiceManager_hook(container, local, True)
+ return trustedRemoveSecurityProxy(site.getSiteManager())
- return sm
+ try:
+ # This try-except is just backward compatibility really
+ return trustedRemoveSecurityProxy(getAdapter(context, IServiceService))
+ except ComponentLookupError:
+ # Deprecated support for a context that isn't adaptable to
+ # IServiceService. Return the default service manager.
+ ## warnings.warn("getServices' context arg must be None or"
+ ## " adaptable to IServiceService.",
+ ## DeprecationWarning, warningLevel())
+ return serviceManager
-def queryView(object, name, request, default=None, context=None,
- providing=Interface):
- if context is None:
- context = object
+def queryView(object, name, request, default=None,
+ providing=Interface, context=None):
+ # XXX test
+ #if context is None:
+ # context = object
views = getService(context, Presentation)
view = views.queryView(object, name, request, default=default,
providing=providing)
Modified: Zope3/trunk/src/zope/app/publication/interfaces.py
===================================================================
--- Zope3/trunk/src/zope/app/publication/interfaces.py 2004-05-22 01:56:42 UTC (rev 24870)
+++ Zope3/trunk/src/zope/app/publication/interfaces.py 2004-05-22 01:56:54 UTC (rev 24871)
@@ -16,7 +16,8 @@
$Id$
"""
-from zope.interface import Interface
+from zope.interface import implements, Interface
+from zope.app.event.interfaces import IEvent
class IPublicationRequestFactoryFactory(Interface):
@@ -44,3 +45,27 @@
"""This is a pure read-only interface, since the values are set through
a ZCML directive and we shouldn't be able to change them.
"""
+
+
+class IBeforeTraverseEvent(IEvent):
+ """An event which gets sent on publication traverse"""
+
+
+class BeforeTraverseEvent:
+ """An event which gets sent on publication traverse"""
+ implements(IBeforeTraverseEvent)
+ def __init__(self, ob, request):
+ self.object = ob
+ self.request = request
+
+
+class IEndRequestEvent(IEvent):
+ """An event which gets sent when the publication is ended"""
+
+
+class EndRequestEvent:
+ """An event which gets sent when the publication is ended"""
+ implements(IEndRequestEvent)
+ def __init__(self, ob, request):
+ self.object = ob
+ self.request = request
Modified: Zope3/trunk/src/zope/app/publication/tests/test_zopepublication.py
===================================================================
--- Zope3/trunk/src/zope/app/publication/tests/test_zopepublication.py 2004-05-22 01:56:42 UTC (rev 24870)
+++ Zope3/trunk/src/zope/app/publication/tests/test_zopepublication.py 2004-05-22 01:56:54 UTC (rev 24871)
@@ -26,7 +26,7 @@
from zope.interface.verify import verifyClass
from zope.interface import implements, classImplements, implementedBy
from zope.i18n.interfaces import IUserPreferredCharsets
-from zope.component import getServiceManager
+from zope.component import getGlobalServices
from zope.component.interfaces import IServiceService
from zope.publisher.base import TestPublication, TestRequest
from zope.publisher.http import IHTTPRequest, HTTPCharsets
@@ -37,11 +37,13 @@
from zope.app import zapi
from zope.app.tests.placelesssetup import PlacelessSetup
+from zope.app.tests import setup
from zope.app.tests import ztapi
from zope.app.errorservice.interfaces import IErrorReportingService
from zope.app.servicenames import ErrorLogging, Authentication
from zope.app.location.interfaces import ILocation
+from zope.app.traversing.interfaces import IPhysicallyLocatable
from zope.app.security.principalregistry import principalRegistry
from zope.app.security.interfaces import IUnauthenticatedPrincipal, IPrincipal
from zope.app.publication.zopepublication import ZopePublication
@@ -154,6 +156,7 @@
for interface in implementedBy(ZopePublication):
verifyClass(interface, TestPublication)
+
class ZopePublicationErrorHandling(BasePublicationTests):
def testRetryAllowed(self):
@@ -317,7 +320,7 @@
def testAbortTransactionWithErrorLoggingService(self):
# provide our fake error logging service
- sm = getServiceManager(None)
+ sm = getGlobalServices()
sm.defineService(ErrorLogging, IErrorReportingService)
sm.provideService(ErrorLogging, ErrorLoggingService())
@@ -327,7 +330,7 @@
last_txn_info = self.db.undoInfo()[0]
try:
raise FooError
- except:
+ except FooError:
pass
self.publication.handleException(
self.object, self.request, sys.exc_info(), retry_allowed=False)
@@ -434,8 +437,45 @@
self.publication.afterCall(self.request, bar.foo)
self.assertEqual(txn_info['location'], expected_path)
-
+ def testSiteEvents(self):
+ from zope.app.publication.interfaces import IBeforeTraverseEvent
+ from zope.app.publication.interfaces import IEndRequestEvent
+ from zope.app.event.interfaces import ISubscriber
+ from zope.app.servicenames import EventPublication
+ from zope.app.event.localservice import EventService
+ class Subscriber:
+ implements(ISubscriber)
+ def __init__(self):
+ self.events = []
+ def notify(self, event):
+ self.events.append(event)
+
+ events = zapi.getService(EventPublication)
+ set = Subscriber()
+ clear = Subscriber()
+ events.globalSubscribe(set, IBeforeTraverseEvent)
+ events.globalSubscribe(clear, IEndRequestEvent)
+
+ ob = object()
+
+ # This should fire the BeforeTraverseEvent
+ self.publication.callTraversalHooks(self.request, ob)
+
+ self.assertEqual(len(set.events), 1)
+ self.assertEqual(len(clear.events), 0)
+ self.assertEqual(set.events[0].object, ob)
+
+ ob2 = object()
+
+ # This should fire the EndRequestEvent
+ self.publication.endRequest(self.request, ob2)
+
+ self.assertEqual(len(set.events), 1)
+ self.assertEqual(len(clear.events), 1)
+ self.assertEqual(clear.events[0].object, ob2)
+
+
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(ZopePublicationTests),
Modified: Zope3/trunk/src/zope/app/publication/zopepublication.py
===================================================================
--- Zope3/trunk/src/zope/app/publication/zopepublication.py 2004-05-22 01:56:42 UTC (rev 24870)
+++ Zope3/trunk/src/zope/app/publication/zopepublication.py 2004-05-22 01:56:54 UTC (rev 24871)
@@ -22,7 +22,9 @@
from ZODB.POSException import ConflictError
from zope.interface import implements, providedBy
-from zope.component import queryService
+from zope.component import getService
+from zope.app.servicenames import ErrorLogging
+from zope.component.exceptions import ComponentLookupError
from zope.publisher.publish import mapply
from zope.publisher.interfaces import Retry, IExceptionSideEffects
from zope.publisher.interfaces import IRequest, IPublication
@@ -44,6 +46,9 @@
from zope.app.publication.publicationtraverse import PublicationTraverse
from zope.app.traversing.interfaces import IPhysicallyLocatable
from zope.app.location import LocationProxy
+from zope.app.event import publish
+from zope.app.publication.interfaces import BeforeTraverseEvent
+from zope.app.publication.interfaces import EndRequestEvent
class Cleanup(object):
@@ -87,7 +92,7 @@
return
sm = removeAllProxies(ob).getSiteManager()
-
+
auth_service = sm.queryService(Authentication)
if auth_service is None:
# No auth service here
@@ -105,7 +110,7 @@
def callTraversalHooks(self, request, ob):
# Call __before_publishing_traverse__ hooks
-
+ publish(None, BeforeTraverseEvent(ob, request))
# This is also a handy place to try and authenticate.
self._maybePlacefullyAuthenticate(request, ob)
@@ -154,8 +159,8 @@
txn.commit()
def endRequest(self, request, ob):
- # Make sure the interaction is ended
endInteraction()
+ publish(None, EndRequestEvent(ob, request))
def annotateTransaction(self, txn, request, ob):
"""Set some useful meta-information on the transaction. This
@@ -201,9 +206,13 @@
self.beginErrorHandlingTransaction(request, object,
'error reporting service')
try:
- errService = queryService(object, ErrorLogging)
- if errService is not None:
+ try:
+ errService = getService(ErrorLogging)
errService.raising(exc_info, request)
+ except ComponentLookupError:
+ # There is no local error reporting service.
+ # XXX We need to build a local error reporting service.
+ pass
# It is important that an error in errService.raising
# does not propagate outside of here. Otherwise, nothing
# meaningful will be returned to the user.
@@ -224,7 +233,6 @@
ErrorLogging)
get_transaction().abort()
-
def handleException(self, object, request, exc_info, retry_allowed=True):
# This transaction had an exception that reached the publisher.
# It must definitely be aborted.
@@ -233,7 +241,7 @@
# Convert ConflictErrors to Retry exceptions.
if retry_allowed and isinstance(exc_info[1], ConflictError):
tryToLogWarning('ZopePublication',
- 'Competing writes/reads at %s' %
+ 'Competing writes/reads at %s' %
request.get('PATH_INFO', '???'),
exc_info=True)
raise Retry
@@ -280,11 +288,11 @@
if loc is loc:
loc = getattr(loc, '__self__', loc)
loc = ProxyFactory(loc)
-
+
exception = LocationProxy(exc_info[1], loc)
- name = zapi.queryDefaultViewName(exception, request, context=object)
+ name = zapi.queryDefaultViewName(exception, request)
if name is not None:
- view = zapi.queryView(exception, name, request, context=object)
+ view = zapi.queryView(exception, name, request)
except:
# Problem getting a view for this exception. Log an error.
tryToLogException(
More information about the Zope3-Checkins
mailing list