[Checkins] SVN: grok/trunk/src/grok/components.py Edited and corrected the docstrings I have written so far, following
Brandon Rhodes
brandon at rhodesmill.org
Thu Jan 8 11:25:11 EST 2009
Log message for revision 94627:
Edited and corrected the docstrings I have written so far, following
feedback on the Grok mailing list. Several were plain wrong, I found
when reviewing them; `grok.Site` and `grok.Application` are mixins,
for example, whereas my first descriptions had made them sound like
full-fledged base classes instead.
Changed:
U grok/trunk/src/grok/components.py
-=-
Modified: grok/trunk/src/grok/components.py
===================================================================
--- grok/trunk/src/grok/components.py 2009-01-08 16:04:17 UTC (rev 94626)
+++ grok/trunk/src/grok/components.py 2009-01-08 16:25:11 UTC (rev 94627)
@@ -11,8 +11,13 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
-"""Grok components"""
+"""Base classes for Grok application components.
+When an application developer builds a Grok-based application, the
+classes they define each typically inherit from one of the base classes
+provided here.
+
+"""
import persistent
import simplejson
@@ -46,37 +51,43 @@
class Model(Contained, persistent.Persistent):
+ # XXX Inheritance order is important here. If we reverse this,
+ # then containers can't be models anymore because no unambigous MRO
+ # can be established.
"""The base class for models in Grok applications.
- When an application class inherits from `grok.Model`, it not only
- gains the ability to persist itself in the Zope object database and
- to remember where in the database it lives (so that it can figure
- out its URL), but it is also marked with the `IContext` interface
- which tells Grok that the class is eligible to be auto-associated
- with `grok.View` classes or other adapters in its module which do
- not explicitly define a `grok.context()`.
+ When an application class inherits from `grok.Model`, it gains the
+ ability to persist itself in the Zope object database along with all
+ of its attributes, and to remember the container in which it has
+ been placed (its "parent") so that its URL can be computed. It also
+ inherits the `IContext` marker interface, which can make it the
+ default context for views in its module; the rule is that if a
+ module contains `grok.View` classes or other adapters that do not
+ define a `grok.context()`, but the module also defines exactly one
+ class that provides the `IContext` interface, then that class will
+ automatically be made the `grok.context()` of each of the views.
"""
- # XXX Inheritance order is important here. If we reverse this,
- # then containers can't be models anymore because no unambigous MRO
- # can be established.
interface.implements(IAttributeAnnotatable, interfaces.IContext)
class Container(BTreeContainer):
"""The base class for containers in Grok applications.
- A `grok.Container` subclass acts like a persistent dictionary, and
- knows both how to persist itself inside of a Zope database, and how
- to store other containers and models under its keys (using the
- standard Python getitem/setitem protocol). By default, URLs which
- arrive at the container can continue on to objects inside of it by
- supplying a URL component that matches one of the container's keys.
- A `grok.Container` subclass is also marked with the `IContext`
- interface, which tells Grok that the class is eligible to be
- auto-associated with `grok.View` classes or other adapters in its
- module which do not explicitly define a `grok.context()`.
+ When an application class inherits from `grok.Container`, it not
+ only has the features of a `grok.Model` (persistance, location, and
+ the ability to serve as a default context for other classes), but it
+ also behaves like a persistent dictionary. To store items inside a
+ container, simply use the standard Python getitem/setitem protocol::
+ mycontainer['counter'] = 72
+ mycontainer['address'] = mymodel
+ mycontainer['subfolder'] = another_container
+
+ By default, the URL of each item inside a container is the
+ container's own URL followed by a slash and the key (like 'counter'
+ or 'address') under which that item has been stored.
+
"""
interface.implements(IAttributeAnnotatable, interfaces.IContainer)
@@ -85,12 +96,10 @@
"""A Grok container that remembers the order of its items.
This straightforward extension of the basic `grok.Container`
- remembers the order in which its keys pairs have been inserted, and
- allows their order to be modified later. This means that keys and
- items returned by `keys()`, `values()`, and `items()`, as well as by
- iterating over the container, will appear in the same order as they
- were added to the container. The only way of changing the item
- order in the container is through the method `updateOrder()`.
+ remembers the order in which items have been inserted, so that
+ `keys()`, `values()`, `items()`, and iteration across the container
+ can all return the items in the order they were inserted. The only
+ way of changing the order is to call the `updateOrder()` method.
"""
interface.implements(IOrderedContainer)
@@ -128,10 +137,9 @@
"""Impose a new order on the items in this container.
Items in this container are, by default, returned in the order
- in which they were inserted. To impose a different ordering on
- the items instead, provide an `order` argument to this method
- that is a list containing every key already in the container,
- but in a new order.
+ in which they were inserted. To change the order, provide an
+ argument to this method that is a sequence containing every key
+ already in the container, but in a new order.
"""
if set(order) != set(self._order):
@@ -143,12 +151,12 @@
class Site(SiteManagerContainer):
- """The base class for sites in Grok applications.
+ """Mixin for creating sites in Grok applications.
- A `grok.Site` is a fancy container, with which Component
- Architecture entities like local utilities and indexes can be
- associated, that become active for all URLs that name either the
- site object itself or an object beneath the site.
+ When an application `grok.Model` or `grok.Container` also inherits
+ from `grok.Site`, then it can additionally support the registration
+ of local Component Architecture entities like `grok.LocalUtility`
+ and `grok.Indexes` objects; see those classes for more information.
"""
@@ -158,8 +166,8 @@
"""Add a local site manager to a Grok site object upon its creation.
Grok registers this function so that it gets called each time a
- `grok.Site` instance is added to a container. It creates a new
- local site manager and installs it on the site.
+ `grok.Site` instance is added to a container. It creates a local
+ site manager and installs it on the newly created site.
"""
sitemanager = LocalSiteManager(site)
@@ -171,14 +179,14 @@
class Application(Site):
- """The base class for Grok applications.
+ """Mixin for creating Grok application objects.
- A `grok.Application` not only has all of the abilities of a Grok
- container (it can hold other objects) and a Grok site (it can be a
- registration point for local utilities), but application classes are
- specifically cataloged by Grok so that the Grok admin interface can
- list them in the menu of objects that users can instantiate directly
- inside of the root of their Zope database.
+ When a `grok.Container` (or a `grok.Model`, though most developers
+ use containers) also inherits from `grok.Application`, it not only
+ gains the component registration abilities of a `grok.Site`, but
+ will also be listed in the Grok admin control panel as one of the
+ applications that the admin can install directly at the root of
+ their Zope database.
"""
interface.implements(interfaces.IApplication)
@@ -187,19 +195,18 @@
class LocalUtility(Model):
"""The base class for local utilities in Grok applications.
- By inheriting from this `grok.LocalUtility` class when designing a
- local utility, Grok application authors accomplish three things.
- First, this class is knows how to persist itself to the database,
- which is important because local utilities must be stored in the
- Zope database alongside the `grok.Site` or `grok.Application` for
- which they are registered. Second, Grok can deduce the interface
- that the utility is designed to provide if the utility simply
- `implements()` one interface (that is not already an interface
- provided by `grok.LocalUtility`, otherwise Grok cannot tell the
- difference); this saves the developer from having to supply an
- explicit `grok.provides()` directive. Third, of course, their code
- will be easier to read if their local utilities inherit from
- something with "local utility" in its name.
+ Although application developers can create local utilies without
+ actually subclassing `grok.LocalUtility`, they gain three benefits
+ from doing so. First, their code is more readable because their
+ classes "look like" local utilities to casual readers. Second,
+ their utility will know how to persist itself to the Zope database,
+ which means that they can set its object attributes and know that
+ the values are getting automatically saved. Third, they can omit
+ the `grok.provides()` directive naming the interface that the
+ utility provides, if their class only `grok.implements()` a single
+ interface (unless the interface is one that the `grok.LocalUtility`
+ already implements, in which case Grok cannot tell them apart, and
+ `grok.provides()` must be used explicitly anyway).
"""
@@ -211,17 +218,60 @@
class View(grokcore.view.View):
"""The base class for views in Grok applications.
- Grok automatically registers each subclass of `grok.View` as able to
- render instances of its `grok.context()` for consumption by web
- browsers, when a specific `/name` is appended to the context's URL.
- The name can either be explicitly provided with `grok.name()`, or by
- default will be the downcased name of the class itself; Grok views
- with the name ``index`` are used by default if no `/name` is
- appended to the context's URL.
+ Each class that inherits from `grok.View` is designed to "render" a
+ category of content objects by reducing them to a document (often an
+ HTML document). Every view has a name, and is invoked when users
+ visit the URL of an eligible context object followed by the name of
+ the view itself::
+ http://example.com/app/folder/object/viewname
+
+ If ``viewname`` might conflict with actual content inside of the
+ context (because the context already contains an attribute or item
+ named ``viewname``), then the URL can be explicit that it is asking
+ for the view by preceding its name with ``@@``::
+
+ http://example.com/app/folder/object/@@viewname
+
+ Instead of returning a full document, views are sometimes used to
+ provide only a snippet of information for inclusion in some larger
+ document; the view can then be called from inside of another view's
+ page template::
+
+ <li tal:content="context/@@viewname">snippet goes here</li>
+
+ A view class can specify the category of objects that it can render
+ by calling the `grok.context()` with either a class or an interface.
+ Otherwise, Grok will attempt to determine the context automatically
+ by searching the view's module for exactly one `grok.Model` or
+ `grok.Container` class (or some other class providing the interface
+ `IContext`) and using that class, if found.
+
+ Grok normally creates a view's name (the name used in URLs) by
+ downcasing the name of the view class itself. The developer can
+ override this by supplying the `grok.name()` directive instead.
+
+ The view name ``index`` is special (this works whether the view
+ class itself is named ``Index``, or whether ``grok.name('index')``
+ is used instead). A view named ``index`` is used to render an
+ object when the user visits its URL without appending a view name.
+
+ Each view should either provide a `render()` method that simply
+ returns a document, or should have an accompanying page template.
+ Grok will automatically find the correct page template if (a) it is
+ in a directory next to the view's module, whose name is the module
+ name followed by `_templates`; (b) its filename is the downcased
+ name of the view class; and (c) it has an extension (such as ``.pt``
+ for Zope Page Templates) that Grok recognizes. Otherwise, the
+ developer can name a page template file explicitly with the
+ `grok.template()` directive. Before the template is rendered, Grok
+ will call the `update()` method on the view, if one is supplied,
+ which can pre-compute values that the template will need to display.
+
+ Both `render()` methods and `update()` methods will find the context
+ for which the view is being rendered under ``self.context``.
+
"""
- # XXX the above description needs either more detail, or less; I
- # will ask the Grok mailing list this morning - Brandon
interface.implements(interfaces.IGrokView)
def application_url(self, name=None):
More information about the Checkins
mailing list