[Checkins] SVN: grok/trunk/src/grok/ Added an event to Grok. This event, called ApplicationInitializedEvent.
Souheil CHELFOUH
souheil at chelfouh.com
Thu Oct 8 16:35:08 EDT 2009
Log message for revision 104952:
Added an event to Grok. This event, called ApplicationInitializedEvent.
This event is supposed to be fired after the persistence of the site.
It allows to use handlers, at the application creation, that need to be sure they can access the local utilities.
Added a test to demonstrate the behavior.
Changed:
U grok/trunk/src/grok/__init__.py
A grok/trunk/src/grok/events.py
A grok/trunk/src/grok/ftests/events/
A grok/trunk/src/grok/ftests/events/__init__.py
A grok/trunk/src/grok/ftests/events/application_init.py
U grok/trunk/src/grok/ftests/test_grok_functional.py
U grok/trunk/src/grok/interfaces.py
-=-
Modified: grok/trunk/src/grok/__init__.py
===================================================================
--- grok/trunk/src/grok/__init__.py 2009-10-08 20:19:18 UTC (rev 104951)
+++ grok/trunk/src/grok/__init__.py 2009-10-08 20:35:08 UTC (rev 104952)
@@ -77,6 +77,7 @@
ObjectRemovedEvent,
ContainerModifiedEvent)
+from grok.events import ApplicationInitializedEvent
from grok.components import Model, View
from grok.components import XMLRPC, REST, JSON
from grok.components import Traverser
@@ -85,6 +86,7 @@
from grok.components import Indexes
from grok.components import Role
from grok.interfaces import IRESTSkinType, IRESTLayer
+from grok.interfaces import IApplicationInitializedEvent
from grok.directive import (
permissions, site, restskin, traversable)
Added: grok/trunk/src/grok/events.py
===================================================================
--- grok/trunk/src/grok/events.py (rev 0)
+++ grok/trunk/src/grok/events.py 2009-10-08 20:35:08 UTC (rev 104952)
@@ -0,0 +1,31 @@
+##############################################################################
+#
+# Copyright (c) 2006-2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Events for Grok application components.
+
+The events described here are *not* trigged by Grok itself. They are
+conveniently provided to be used in your own application.
+
+"""
+from grok import interfaces
+from zope.interface import implements
+
+
+class ApplicationInitializedEvent(object):
+ """A Grok Application has been created and is now ready to be used.
+ """
+ implements(interfaces.IApplicationInitializedEvent)
+
+ def __init__(self, app):
+ assert interfaces.IApplication.providedBy(app)
+ self.object = app
Added: grok/trunk/src/grok/ftests/events/__init__.py
===================================================================
--- grok/trunk/src/grok/ftests/events/__init__.py (rev 0)
+++ grok/trunk/src/grok/ftests/events/__init__.py 2009-10-08 20:35:08 UTC (rev 104952)
@@ -0,0 +1 @@
+# this is a package
Added: grok/trunk/src/grok/ftests/events/application_init.py
===================================================================
--- grok/trunk/src/grok/ftests/events/application_init.py (rev 0)
+++ grok/trunk/src/grok/ftests/events/application_init.py 2009-10-08 20:35:08 UTC (rev 104952)
@@ -0,0 +1,86 @@
+"""
+==========================
+Application initialization
+==========================
+
+The application initialization is an important moment of your
+application's life. This creation process is responsible for the
+local utilities and the catalog indexes' creation. Let's create a site
+to demonstrate the different steps.
+
+ >>> root = getRootFolder()
+
+The life cycle of an application is made of 2 major events :
+ObjectCreatedEvent and ObjectAddedEvent.
+
+ObjectCreatedEvent shoud be triggered when an application is
+instanciated. At this step, the application doesn't have a site
+manager yet.
+
+ >>> site = Herd()
+ >>> notify(grok.ObjectCreatedEvent(site))
+ >>> setSite(site)
+ Traceback (most recent call last):
+ ...
+ ComponentLookupError: no site manager defined
+
+As the application is instanciated and notified as "created", we can
+now persist it. This operation will fire the "ObjectAddedEvent". This
+event is trigged by the container and the associated event handlers
+will create the site manager. Once the site manager is created, Grok's
+subscribers will create the local utilities and the indexes.
+
+This particular step is often used to trigger the creation of
+content. However, as the event handlers are not ordered, we can not be
+sure that our handler will be called after the local utilities
+creation. This can be quite annoying : the content created by our
+handler may not be regitered in the Catalog and the IntIds utility.
+
+To demonstrate this behavior, we now persist the application. This
+will trigger a test handler that queries the Catalog::
+
+ >>> root['site'] = site
+ Catalog can not be found !
+
+Now our application is persisted, the site manager and the local
+utilities are created. We can safely use our application. An event is
+provided by Grok, to be fired at this step. The same test event shows
+that we can now work on an operational environment:
+
+ >>> notify(grok.ApplicationInitializedEvent(site))
+ <zope.app.catalog.catalog.Catalog object at ...>
+
+"""
+import grok
+from grok import index
+from zope.event import notify
+from zope.schema import TextLine
+from zope.interface import Interface
+from zope.component import queryUtility
+from zope.app.component.hooks import setSite
+from zope.app.catalog.interfaces import ICatalog
+
+
+class Herd(grok.Container, grok.Application):
+ pass
+
+
+class IPachyderm(Interface):
+ tusks = TextLine(title = u"About the tusks")
+
+
+class TuskIndex(grok.Indexes):
+ grok.context(IPachyderm)
+ grok.site(Herd)
+
+ tusks = index.Text()
+
+
+ at grok.subscribe(Herd, grok.IObjectAddedEvent)
+ at grok.subscribe(Herd, grok.IApplicationInitializedEvent)
+def CatalogTester(application, event):
+ catalog = queryUtility(ICatalog, context=application)
+ if catalog is None:
+ print "Catalog can not be found !"
+ else:
+ print catalog
Modified: grok/trunk/src/grok/ftests/test_grok_functional.py
===================================================================
--- grok/trunk/src/grok/ftests/test_grok_functional.py 2009-10-08 20:19:18 UTC (rev 104951)
+++ grok/trunk/src/grok/ftests/test_grok_functional.py 2009-10-08 20:35:08 UTC (rev 104952)
@@ -71,7 +71,7 @@
def test_suite():
suite = unittest.TestSuite()
for name in ['xmlrpc', 'traversal', 'form', 'url', 'security',
- 'catalog', 'site', 'rest', 'viewlet','json']:
+ 'catalog', 'site', 'rest', 'viewlet', 'json', 'events']:
suite.addTest(suiteFromPackage(name))
return suite
Modified: grok/trunk/src/grok/interfaces.py
===================================================================
--- grok/trunk/src/grok/interfaces.py 2009-10-08 20:19:18 UTC (rev 104951)
+++ grok/trunk/src/grok/interfaces.py 2009-10-08 20:35:08 UTC (rev 104952)
@@ -15,6 +15,7 @@
"""
from zope import interface
from zope.interface.interfaces import IInterface
+from zope.component.interfaces import IObjectEvent
from zope.publisher.interfaces.http import IHTTPRequest
from zope.app.container.interfaces import IContainer as IContainerBase
@@ -98,6 +99,11 @@
IBeforeTraverseEvent = interface.Attribute("")
+ IApplicationInitializedEvent = interface.Attribute("")
+
+ ApplicationInitializedEvent = interface.Attribute("")
+
+
class IGrokAPI(grokcore.formlib.interfaces.IGrokcoreFormlibAPI,
grokcore.security.interfaces.IGrokcoreSecurityAPI,
grokcore.site.interfaces.IGrokcoreSiteAPI,
@@ -213,3 +219,11 @@
`grok.Permission` and `grok.require` settings however, will be
applied to such views.
"""
+
+class IApplicationInitializedEvent(IObjectEvent):
+ """A Grok Application has been created with success and is now ready
+ to be used.
+
+ This event can be used to trigger the creation of contents or other tasks
+ that require the application to be fully operational : utilities installed
+ and indexes created in the catalog."""
More information about the checkins
mailing list