[Checkins] SVN: grok/trunk/src/grok/ Added a `create_application` function that creates an application, going through all the needed events.
Souheil CHELFOUH
souheil at chelfouh.com
Fri Oct 9 11:28:31 EDT 2009
Log message for revision 104972:
Added a `create_application` function that creates an application, going through all the needed events.
Added a test for that new feature and corrected a bit the previous ones, to get a coherent naming and text.
Changed:
D grok/trunk/src/grok/ftests/lifecycle/application_init.py
A grok/trunk/src/grok/ftests/lifecycle/create_application.py
A grok/trunk/src/grok/ftests/lifecycle/lifecycle_events.py
U grok/trunk/src/grok/util.py
-=-
Deleted: grok/trunk/src/grok/ftests/lifecycle/application_init.py
===================================================================
--- grok/trunk/src/grok/ftests/lifecycle/application_init.py 2009-10-09 15:27:34 UTC (rev 104971)
+++ grok/trunk/src/grok/ftests/lifecycle/application_init.py 2009-10-09 15:28:31 UTC (rev 104972)
@@ -1,86 +0,0 @@
-"""
-==========================
-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
Added: grok/trunk/src/grok/ftests/lifecycle/create_application.py
===================================================================
--- grok/trunk/src/grok/ftests/lifecycle/create_application.py (rev 0)
+++ grok/trunk/src/grok/ftests/lifecycle/create_application.py 2009-10-09 15:28:31 UTC (rev 104972)
@@ -0,0 +1,69 @@
+"""
+====================
+Application creation
+====================
+
+The application creation can be handled by Grok. In order to setup a
+functional application, the creation method will go through all the
+needed events : ObjectCreated, ObjectAdded, ApplicationInitialized.
+
+Let's create our environment. We are at the zope instance root folder.
+
+ >>> root = getRootFolder()
+
+In this folder, we want our Cave applicate. To create it, Grok
+provides a convenient function called `create_application`::
+
+ >>> import grok.util
+ >>> app = grok.util.create_application(Cave, root, 'mycave')
+ Cave <zope.app.event.objectevent.ObjectCreatedEvent object at ...>
+ Cave <zope.app.container.contained.ObjectAddedEvent object at ...>
+ Cave <grok.events.ApplicationInitializedEvent object at ...>
+
+As we can see, the events are effectively trigged, and in the right
+order. The function returns the persisted application method.
+
+ >>> print app
+ <grok.ftests.lifecycle.application_creation.Cave object at ...>
+ >>> print app.__parent__
+ <zope.app.folder.folder.Folder object at ...>
+
+However, if an error occur during the creation process, the exception
+is not caught by `create_application`.
+
+In the case we provide an id that already exists, the exception will
+be raised *BEFORE* the application instanciation. For this reason, and
+intentionally, no event will be trigged.
+
+ >>> app = grok.util.create_application(Cave, root, 'mycave')
+ Traceback (most recent call last):
+ ...
+ DuplicationError: mycave
+
+Please note that the `create_application` function will only accept
+factories implementing IApplication::
+
+ >>> james = grok.util.create_application(Mammoth, root, 'james')
+ Traceback (most recent call last):
+ ...
+ WrongType: <class 'grok.ftests.lifecycle.application_creation.Mammoth'>
+
+"""
+import grok
+
+
+class Mammoth(grok.Model):
+ """A furry creature with tusks.
+ """
+ pass
+
+class Cave(grok.Container, grok.Application):
+ """A shelter for the homeless cavemen.
+ """
+ pass
+
+ at grok.subscribe(Cave, grok.IObjectCreatedEvent)
+ at grok.subscribe(Cave, grok.IObjectAddedEvent)
+ at grok.subscribe(Cave, grok.IApplicationInitializedEvent)
+def EventPrinter(application, event):
+ print application.__class__.__name__, event
Copied: grok/trunk/src/grok/ftests/lifecycle/lifecycle_events.py (from rev 104967, grok/trunk/src/grok/ftests/lifecycle/application_init.py)
===================================================================
--- grok/trunk/src/grok/ftests/lifecycle/lifecycle_events.py (rev 0)
+++ grok/trunk/src/grok/ftests/lifecycle/lifecycle_events.py 2009-10-09 15:28:31 UTC (rev 104972)
@@ -0,0 +1,86 @@
+"""
+==============================
+Application lifecycle overview
+==============================
+
+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
Property changes on: grok/trunk/src/grok/ftests/lifecycle/lifecycle_events.py
___________________________________________________________________
Added: svn:mergeinfo
+
Modified: grok/trunk/src/grok/util.py
===================================================================
--- grok/trunk/src/grok/util.py 2009-10-09 15:27:34 UTC (rev 104971)
+++ grok/trunk/src/grok/util.py 2009-10-09 15:28:31 UTC (rev 104972)
@@ -13,12 +13,17 @@
##############################################################################
"""Grok utility functions.
"""
+import grok
+import zope.event
import zope.location.location
from zope import interface
+from zope.schema.interfaces import WrongType
+from zope.exceptions.interfaces import DuplicationError
from zope.security.checker import NamesChecker, defineChecker
from grokcore.security.util import check_permission
+
def make_checker(factory, view_factory, permission, method_names=None):
"""Make a checker for a view_factory associated with factory.
@@ -35,6 +40,7 @@
checker = NamesChecker(method_names, permission)
defineChecker(view_factory, checker)
+
def safely_locate_maybe(obj, parent, name):
"""Set an object's __parent__ (and __name__) if the object's
__parent__ attribute doesn't exist yet or is None.
@@ -47,6 +53,7 @@
# This either sets __parent__ or wraps 'obj' in a LocationProxy
return zope.location.location.located(obj, parent, name)
+
def applySkin(request, skin, skin_type):
"""Change the presentation skin for this request.
"""
@@ -56,3 +63,31 @@
# Add the new skin.
ifaces.append(skin)
interface.directlyProvides(request, *ifaces)
+
+
+def create_application(factory, container, name):
+ """Creates an application and triggers the events from
+ the application lifecycle.
+ """
+ # Check the factory.
+ if not grok.interfaces.IApplication.implementedBy(factory):
+ raise WrongType(factory)
+
+ # Check the availability of the name in the container.
+ if name in container:
+ raise DuplicationError(name)
+
+ # Instanciate the application
+ application = factory()
+
+ # Trigger the creation event.
+ grok.notify(grok.ObjectCreatedEvent(application))
+
+ # Persist the application.
+ # This may raise a DuplicationError.
+ container[name] = application
+
+ # Trigger the initialization event.
+ grok.notify(grok.ApplicationInitializedEvent(application))
+
+ return application
More information about the checkins
mailing list