[Checkins] SVN: grok/branches/ulif-adminless/ Merge changes from trunk into adminless-branch.

Uli Fouquet uli at gnufix.de
Thu Jul 10 16:48:39 EDT 2008


Log message for revision 88204:
  Merge changes from trunk into adminless-branch.

Changed:
  U   grok/branches/ulif-adminless/CHANGES.txt
  U   grok/branches/ulif-adminless/doc/.static/grok.css
  A   grok/branches/ulif-adminless/doc/.static/grok_club.gif
  D   grok/branches/ulif-adminless/doc/about.rst
  U   grok/branches/ulif-adminless/doc/conf.py
  U   grok/branches/ulif-adminless/doc/contents.rst
  U   grok/branches/ulif-adminless/doc/docindex.template
  U   grok/branches/ulif-adminless/doc/index.rst
  A   grok/branches/ulif-adminless/doc/layout.html
  U   grok/branches/ulif-adminless/doc/reference/components.rst
  U   grok/branches/ulif-adminless/doc/reference/conf.py
  U   grok/branches/ulif-adminless/doc/reference/events.rst
  U   grok/branches/ulif-adminless/doc/reference/index.rst
  U   grok/branches/ulif-adminless/doc/tutorial.rst
  U   grok/branches/ulif-adminless/doc/upgrade.txt
  U   grok/branches/ulif-adminless/grokdocs/setup.py
  _U  grok/branches/ulif-adminless/grokdocs/src/grokdocs/
  U   grok/branches/ulif-adminless/grokwiki/src/grokwiki/page_templates/edit.pt
  U   grok/branches/ulif-adminless/grokwiki/src/grokwiki/page_templates/index.pt
  U   grok/branches/ulif-adminless/setup.py
  U   grok/branches/ulif-adminless/src/grok/components.py
  U   grok/branches/ulif-adminless/src/grok/ftests/view/macros.py
  A   grok/branches/ulif-adminless/src/grok/ftests/viewlet/template_namespaces.py
  A   grok/branches/ulif-adminless/src/grok/ftests/viewlet/template_namespaces_templates/
  U   grok/branches/ulif-adminless/src/grok/ftests/viewlet/viewletmanager_template_templates/cavemanager.pt
  U   grok/branches/ulif-adminless/src/grok/interfaces.py
  U   grok/branches/ulif-adminless/src/grok/meta.py
  U   grok/branches/ulif-adminless/src/grok/templatereg.py
  U   grok/branches/ulif-adminless/src/grok/testing.py
  U   grok/branches/ulif-adminless/src/grok/tests/view/dirtemplatesonly.py
  U   grok/branches/ulif-adminless/src/grok/tests/view/inline_unassociated.py
  U   grok/branches/ulif-adminless/src/grok/tests/view/unassociated.py
  A   grok/branches/ulif-adminless/src/grok/tests/viewlet/viewlet_references.py

-=-
Modified: grok/branches/ulif-adminless/CHANGES.txt
===================================================================
--- grok/branches/ulif-adminless/CHANGES.txt	2008-07-10 20:42:05 UTC (rev 88203)
+++ grok/branches/ulif-adminless/CHANGES.txt	2008-07-10 20:48:38 UTC (rev 88204)
@@ -1,9 +1,24 @@
 Grok changes
 ************
 
-0.13 (unreleased)
+0.14 (unreleased)
 =================
 
+Bug fixes
+---------
+
+* Replace zope.deprecation.tests.warn with grok.testing.warn to:
+
+    * Make the signature identical to warnings.warn
+
+    * To check for *.pyc and *.pyo files.
+
+  When zope.deprecation is fixed this warn() function can be removed again.
+  Makes all the tests pass under Python-2.5.
+
+0.13 (2008-06-23)
+=================
+
 Restructuring
 -------------
 
@@ -19,11 +34,18 @@
 
 * Refactored class grokkers to make use of Martian's new declarative
   way for retrieving directive data from classes, and Martian's new
-  declarative way to write grokkers.
+  declarative way to write grokkers. See the `upgrade notes`_
+  (``doc/upgrade.txt``) for more information.
 
 Feature changes
 ---------------
 
+* ``GrokTemplate`` sets up the namespaces for the template by calling
+  ``default_namespace() ``on the view component the template is
+  associated with. As a result, ``ViewletManagers`` and ``Viewlet``
+  can now push in the ``viewletmanager`` and ``viewlet`` namespaces
+  into the template.
+
 * Updated tutorial section about grokproject to fit the latest changes.
 
 * Added ``grok.traversable`` directive for easy traversal to attributes and
@@ -34,8 +56,8 @@
   permission ids. Permission components *do* still need the
   grok.name() directive for defining the permission's id.
 
-* Added an optional parameter 'data' to the method 'url()' that accepts
-  a dictionary that is then converted to a query string. See
+* Added an optional parameter ``data`` to the method ``url()`` that
+  accepts a dictionary that is then converted to a query string. See
 
   http://grok.zope.org/documentation/how-to/generate-urls-with-the-url-function-in-views/view
 
@@ -50,9 +72,9 @@
   We are now using the latest Zope 3 releases for all Zope packages.
   For upgrade notes, see doc/upgrade.txt for more information.
 
-* Added support for easier test setup based on z3c.testsetup. This is a
-  more stable and more powerful implementation of
-  grok.testing.register_all_tests(). See
+* Added support for easier test setup based on ``z3c.testsetup``. This
+  is a more stable and more powerful implementation of
+  ``grok.testing.register_all_tests()``. See
 
     http://grok.zope.org/documentation/how-to/tests-with-grok-testing
 
@@ -62,7 +84,7 @@
   your class implement that interface, it (and its subclasses) will be
   candidates for being a context in a module (for automatic context
   lookup if ``grok.context`` is not present). This relies on a feature
-  introduced in grokcore.component 1.1.
+  introduced in ``grokcore.component`` 1.1.
 
 * ``grok.Model`` implements ``grok.interfaces.IContext`` now (which is
   imported from ``grokcore.component``). ``grok.Container`` now
@@ -76,6 +98,10 @@
 Bug fixes
 ---------
 
+* Fix https://bugs.launchpad.net/grok/+bug/226555: the ``url()`` method on
+  ``ViewletManager`` and ``Viewlet`` has been removed now that there's easy
+  access to the view component the viewlet(manager) is registered for.
+
 * Fix https://bugs.launchpad.net/grok/+bug/231106: Use the
   viewletmanager.sort() method for sorting viewlets by using
   util.sort_components().

Modified: grok/branches/ulif-adminless/doc/.static/grok.css
===================================================================
--- grok/branches/ulif-adminless/doc/.static/grok.css	2008-07-10 20:42:05 UTC (rev 88203)
+++ grok/branches/ulif-adminless/doc/.static/grok.css	2008-07-10 20:48:38 UTC (rev 88204)
@@ -1,31 +1,29 @@
-/**
- * Sphinx Doc Design
+/*
+ * Grok Official Documentation CSS
+ *
+ * (clean me up! improve me! make me look nicer!)
+ *
  */
 
-/*
-
-Dunkelblau: #11303d
-Hellblau Rahmen: #1c4e63
-Mittelblau Rahmen: #133f52
-*/
 body {
     font-family: sans-serif;
     font-size: 100%;
-    backg/round-color: #11303d;
-    background-color: #ccc;
+    background-color: #11303d;
+    background-color: #dddddd;
     background: #cfcccc url("top_bg.jpg") repeat-x;
     color: #000;
     margin: 0;
     padding: 0;
 }
 
+td {
+    vertical-align: top;
+}
+
 /* :::: LAYOUT :::: */
 
 div.document {
-    backg/round: #1c4e63 url("top_bg.jpg") repeat-x;
-    background-color: #cccccc;
-    background-color: #eee;
-    ba/ckground-color: #1c4e63;
+    background-color: #dddddd;
 }
 
 div.documentwrapper {
@@ -34,33 +32,22 @@
 }
 
 div.bodywrapper {
-    margin: 0 0 0 230px;
+    margin: 0 0 0 250px;
 }
 
 div.body {
     background-color: white;
-    padding: 0 20px 30px 20px;
+    padding: 1.5em;
+    border-left: 1px solid #999;
+    
 }
 
-div.sidebarwrapper {
-    padding: 10px 5px 0 10px;
-}
-
-div.sidebar {
-    float: left;
-    width: 230px;
-    margin-left: -100%;
-    font-size: 90%;
-}
-
 div.clearer {
     clear: both;
 }
 
 div.footer {
-    c/olor: #fff;
     color: #740;
-    co/lor: #000;
     width: 100%;
     padding: 9px 0 9px 0;
     text-align: center;
@@ -68,115 +55,148 @@
 }
 
 div.footer a {
-    co/lor: #fff;
     color: #740;
-    co/lor: #000;
     text-decoration: underline;
 }
 
-div.related {
-    background-color: #133f52;
-    background-color: #999999;
+div.header {
     background: #999999 url("top_bg.jpg") repeat-x;
-    c/olor: #fff;
-    color: #000;
+    padding: 0.5em 1em 0 1em; 
+}
+
+div.header a{
+    color: #520;
+    padding: 0.5em;
+    text-decoration: none;
+}
+
+div.globalnav {
     color: #740;
+    border-bottom: 1px solid #aaa;
     width: 100%;
-    height: 30px;
-    line-height: 30px;
-    font-size: 90%;
+    font-size: small;
 }
 
-div.related h3 {
+div.globalnav h3 {
     display: none;
 }
 
-div.related ul {
-    margin: 0;
-    padding: 0 0 0 10px;
+#globalnavwrapper {
+   padding: 2px;
+   margin: 0.5em 0 0 0;
+}
+
+div.globalnav ul {
+    margin: 0 0 0 0;
+    padding: 0;
     list-style: none;
 }
 
-div.related li {
+div.globalnav li {
     display: inline;
+    padding: 2px 0.5em;
+    margin: 0 1px;
+    background-color: #eee;
+    border: 1px solid #999;
 }
 
-div.related li.right {
-    float: right;
-    margin-right: 5px;
+div.globalnav a {
+    color: #436976;
+    text-decoration: none;
 }
 
-div.related a {
-    co/lor: white;
-    ba/ckground-color: #bbb;
-    color: #000;
-    color: #520;
+div.globalnav li:hover {
+    background-color: white;
 }
 
-/* ::: TOC :::: */
-div.sidebar h3 {
+/* ::: Table of Contents :::: */
+
+.document > div.sidebarwrapper {
+    padding: 10px 5px 0 10px;
+}
+
+.sphinxsidebar {
+    float: left;
+    width: 250px;
+    margin-left: -100%;
+    font-size: small;
+    color: #333333;
+    padding: 8px;
+}
+
+.sphinxsidebar a {
+    color: #436976;
+}
+
+.sphinxsidebar h3 {
     font-family: 'Trebuchet MS', sans-serif;
-    co/lor: white;
-    color: #960;
     font-size: 1.4em;
     font-weight: normal;
     margin: 0;
     padding: 0;
 }
 
-div.sidebar h4 {
+.sphinxsidebar h4 {
     font-family: 'Trebuchet MS', sans-serif;
-    c/olor: white;
-    color: #960;
     font-size: 1.3em;
     font-weight: normal;
     margin: 5px 0 0 0;
     padding: 0;
 }
 
-div.sidebar p {
-    co/lor: white;
-    color: #960;
-}
-
-div.sidebar p.topless {
+.sphinxsidebar p.topless {
     margin: 5px 10px 10px 10px;
 }
 
-div.sidebar ul {
+.sphinxsidebar ul {
     margin: 10px;
     padding: 0;
     list-style: none;
-    co/lor: white;
     color: #c90;
 }
 
-div.sidebar ul ul,
-div.sidebar ul.want-points {
+.sphinxsidebar ul ul,
+.sphinxsidebar ul.want-points {
     margin-left: 20px;
     list-style: square;
+    color: #436976;
 }
 
-div.sidebar ul ul {
+.sphinxsidebar ul ul {
     margin-top: 0;
     margin-bottom: 0;
 }
 
-div.sidebar a {
-    color: #98dbcc;
-color: #a70;
+.sphinxsidebar ul li {
+    margin: 0.25em 0 0.5em 0;
 }
 
-div.sidebar form {
+.sphinxsidebar form {
     margin-top: 10px;
 }
 
-div.sidebar input {
-    border: 1px solid #98dbcc;
+.sphinxsidebar input {
+    border: 1px solid #555555;
     font-family: sans-serif;
     font-size: 1em;
 }
 
+/* Grok Tutorial style sidebar */
+.section div.sidebar {
+    margin: 1em 2em;
+    padding: 0.5em 2em 1em 100px;
+    background-color: #fafaf8;
+    border: 1px solid #aaa;
+    border-top-width: 6px;
+    background-image: url(grok_club.gif);
+    background-repeat: no-repeat;
+}
+
+.section .sidebar-title {
+    font-weight: bold;
+    font-size: 110%;
+}
+
 /* :::: MODULE CLOUD :::: */
 div.modulecloud {
     margin: -5px 10px 5px 10px;
@@ -440,7 +460,7 @@
 
 /* :::: SUGGEST CHANGES :::: */
 div#suggest-changes-box input, div#suggest-changes-box textarea {
-    border: 1px solid #ccc;
+    border: 1px solid #dddddd;
     background-color: white;
     color: black;
 }
@@ -463,6 +483,8 @@
 
 table.contentstable {
     width: 90%;
+    margin-top: -1em;
+    margin-left: 2em;
 }
 
 table.contentstable p.biglink {
@@ -474,8 +496,8 @@
 }
 
 span.linkdescr {
-    font-style: italic;
-    padding-top: 5px;
+    color: #555;
+    padding-top: 0.25em;
     font-size: 90%;
 }
 
@@ -541,25 +563,22 @@
 div.body h5,
 div.body h6 {
     font-family: 'Trebuchet MS', sans-serif;
-    background-color: #f2f2f2;
     font-weight: normal;
-    fo/nt-weight: bold;
-    color: #20435c;
     color: #c90;
-    border-bottom: 1px solid #ccc;
-    margin: 20px -20px 10px -20px;
-    padding: 3px 0 3px 10px;
+    border-bottom: 1px solid #ddd;
+    margin: 1em 0 0.5em 0;
+    padding: 3px 1em 3px 0.25em;
 }
 
-div.body h1 { margin-top: 0; font-size: 200%; }
-div.body h2 { font-size: 160%; }
-div.body h3 { font-size: 140%; }
-div.body h4 { font-size: 120%; }
-div.body h5 { font-size: 110%; }
-div.body h6 { font-size: 100%; }
+div.body h1 { margin-top: 0; background-color: #f2f2f2; font-size: 200%; }
+div.body h2 { font-size: 160%; background-color: #f2f2f2; }
+div.body h3 { font-size: 140%; border-bottom-width: 0; padding-left: 0;  }
+div.body h4 { font-size: 120%; border-bottom-width: 0; padding-left: 0;  }
+div.body h5 { font-size: 110%; border-bottom-width: 0; padding-left: 0;  }
+div.body h6 { font-size: 100%; border-bottom-width: 0; padding-left: 0;  }
 
 a.headerlink {
-    color: #c60f0f;
+    color: #dddddd;
     font-size: 0.8em;
     padding: 0 4px 0 4px;
     text-decoration: none;
@@ -577,14 +596,11 @@
 }
 
 a.headerlink:hover {
-    background-color: #c60f0f;
-    background-color: #000f0f;
-    color: white;
+    color: #555555;
 }
 
 div.body p, div.body dd, div.body li {
-    text-align: justify;
-    line-height: 130%;
+    line-height: 150%;
 }
 
 div.body td {
@@ -606,8 +622,8 @@
 /* "Topics" */
 
 div.topic {
-    background-color: #eee;
-    border: 1px solid #ccc;
+    background-color: #eeeeee;
+    border: 1px solid #dddddd;
     padding: 0 7px 0 7px;
     margin: 10px 0 10px 0;
 }
@@ -618,12 +634,24 @@
     margin-top: 10px;
 }
 
+.topic ul {
+    margin: 0 0 0.5em 1.5em;
+    padding: 0;
+}
+
+.topic > ul {
+    margin-left: 0;
+}
+
+.simple li {
+    list-style: none;
+}
+
 /* Admonitions */
 
 div.admonition {
-    margin-top: 10px;
-    margin-bottom: 10px;
-    padding: 7px;
+    margin: 0.5em 0;
+    padding: 0.5em;
 }
 
 div.admonition dt {
@@ -639,23 +667,68 @@
 }
 
 div.seealso {
+    padding: 0;
     background-color: #ffc;
     border: 1px solid #ff6;
 }
 
+div.seealso .first {
+    background-color: #ffa;
+    padding: 0.25em 0.5em;
+    display: block;
+    float: left;
+    margin: 0 0.5em 0 0;
+}
+
+div.seealso .last {
+    padding: 0.25em 0;
+    display: block;
+    margin: 0;
+}
+
 div.warning {
     background-color: #ffe4e4;
     border: 1px solid #f66;
 }
 
 div.note {
-    background-color: #eee;
-    border: 1px solid #ccc;
+    background-color: #eeeeee;
+    border: 1px solid #dddddd;
 }
 
+dl.class {
+    color: #555555;
+    background: #fafaf8;
+    padding: 0 1em 1em 1em;
+    border: 1px solid #eed;
+}
+
+dl.class dt {
+    margin: 0;
+    padding: 0;
+}
+
+/* only applies to the class name */
+dl.class > dt {
+    padding: 0.5em;
+    margin: 0 -1em;
+    background-color: #eed;
+}
+
+dl.class dd {
+    color: black;
+    font-size: 100%;
+    padding: 0;
+    margin: 0.5em 1em 0.5em 1em;
+}
+
+dl.class > dd {
+    margin: 0.5em 0 0 0;
+    padding: 0;
+}
+
 p.admonition-title {
-    margin: 0px 10px 5px 0px;
-    font-weight: bold;
+    margin: 0 0.5em 0.5em 0;
     display: inline;
 }
 
@@ -727,18 +800,19 @@
 }
 
 pre {
-    padding: 5px;
-    background-color: #efc;
-    color: #333;
-    border: 1px solid #ac9;
+    padding: 1em;
+    background-color: #fafafa;
+    color: #333333;
+    border: 2px dotted #eee;
     border-left: none;
     border-right: none;
+    font-size: medium;
+    line-height: 150%;
 }
 
 tt {
     background-color: #ecf0f3;
-    padding: 0 1px 0 1px;
-    font-size: 0.95em;
+    padding: 0;
 }
 
 tt.descname {
@@ -749,6 +823,10 @@
 
 tt.descclassname {
     background-color: transparent;
+    font-weight: bold;
+    font-size: 1.2em;
+    /* a little hand kerning for grok.Whatever typography */
+    margin-right: -1px;
 }
 
 tt.xref, a tt {
@@ -786,7 +864,7 @@
 
 form.comment input,
 form.comment textarea {
-    border: 1px solid #ccc;
+    border: 1px solid #dddddd;
     padding: 2px;
     font-family: sans-serif;
     font-size: 100%;
@@ -808,6 +886,11 @@
     border: 3px solid red;
 }
 
+img.logo {
+    border-width: 0;
+    margin-bottom: 1em;
+}
+
 /* :::: PRINT :::: */
 @media print {
     div.document, 
@@ -818,7 +901,7 @@
     }
 
     div.sidebar,
-    div.related,
+    div.globalnav,
     div.footer,
     div#comments div.new-comment-box,
     #top-link {

Copied: grok/branches/ulif-adminless/doc/.static/grok_club.gif (from rev 88203, grok/trunk/doc/.static/grok_club.gif)
===================================================================
(Binary files differ)

Deleted: grok/branches/ulif-adminless/doc/about.rst
===================================================================
--- grok/branches/ulif-adminless/doc/about.rst	2008-07-10 20:42:05 UTC (rev 88203)
+++ grok/branches/ulif-adminless/doc/about.rst	2008-07-10 20:48:38 UTC (rev 88204)
@@ -1,137 +0,0 @@
-======================================
-Grok: now even cavemen can use Zope 3
-======================================
-
-Grok is a web application framework for Python developers. It is aimed
-at both beginners and very experienced web developers. Grok has an
-emphasis on agile development. Grok is easy *and* powerful.
-
-Grok: Experience, Expertise, Extensibility
-------------------------------------------
-
-You will likely have heard about many different web frameworks for
-Python as well as other languages. Why you should you consider Grok?
-
-* Grok offers a *lot* of building blocks for your web application.
-
-* Grok is informed by a *lot* of hard-earned wisdom.
-
-Grok accomplishes this by being based on Zope 3, an advanced
-object-oriented web framework. While Grok is based on Zope 3, and
-benefits a lot from it, you do not need to know Zope at all in order
-to get productive with Grok.
-
-Grok is agile
-.............
-
-Grok doesn't require you to edit cryptic configuration files. Instead
-you just program in Python and create HTML templates. Beyond this,
-Grok also offers a wide range of built-in features at your fingertips,
-from automated form generation to an object database. This way, Grok
-gives you both power and quick satisfaction during development. Grok
-is *fun*.
-
-Grok has an extensive tutorial_ that helps you to get started. And
-thanks to grokproject_, you'll be able to create your first web app
-with Grok in no time.
-
-.. _tutorial: tutorial.html
-
-.. _grokproject: http://cheeseshop.python.org/pypi/grokproject
-
-Grok offers a very wide range of features
-.........................................
-
-Through Zope 3, Grok offers a very wide range of building blocks for
-your web application. What's more, Zope 3 components are typically
-rock-solid due to extensive unit-testing and well-specified API
-documentation.
-
-Grok is grounded in a deep experience with web development
-..........................................................
-
-Grok, through Zope 3, is informed by hard-earned wisdom. Zope 3 is a
-powerful and flexible web application framework for Python that has
-been under continuous development since 2001.  Zope 3's design in turn
-is based on experience with the Zope 2 platform, which has been under
-continuous development (starting with Bobo, Principia and then Zope 1)
-since 1997. The Zope community is supported by an independent
-foundation, the Zope Foundation. 
-
-The Zope community has been around for a while. We've built a lot and
-learned a lot. We are in this for the long run.
-
-Grok for the future
-...................
-
-Successful web applications aren't built for a day - such an
-application will need to be maintained, extended, evolved, over a
-period of many years. Zope developers really know this. Grok, through
-Zope 3, offers an architecture that enables your application to grow
-over time.
-
-
-Grok: Zope 3 for cavemen
-------------------------
-
-Grok stands on a giant's shoulder. That giant is Zope 3.
-
-Zope 3 is an advanced object oriented web framework. Zope 3 features a
-large amount of API documentation and aims for reliability. It has a
-very large automatic test coverage (many thousands of tests). It has a
-large set of core features, and sports an enormous range of plug-in
-components.
-
-The Grok developers think Zope 3 is great. Zope 3, unfortunately, also
-has some problems: its power raises the entry barrier for developers
-to get up to speed with it. Even after you've learned it, Zope 3's
-emphasis on explicit configuration and specification of interfaces can
-slow down development.
-
-Grok aims to remedy these problems. Grok aims to make Zope 3 easier to
-learn, and more agile to work with, while retaining the power of Zope
-3.
-
-Grok appeals to the caveman or woman in all of us. Cavemen, like us
-programmers, want powerful and flexible tools. Cavemen are great at
-tools after all; they invented the whole concept of them. But cavemen,
-and we, also want our tools to be simple and effective.
-
-Cavemen want tools like clubs: a club is powerful, flexible (you can
-bash in anything, mash potatoes too) and also simple and
-effective. Zope 3 is already powerful and flexible. Grok aims to make
-it simpler and more effective, for beginners and experienced
-developers alike. Grok: now even cavemen can use Zope 3.
-
-Grok from the Zope 3 perspective
---------------------------------
-
-Zope 3 allows you to combine different components in an explicit,
-flexible way. You can hook up a view to a model, an event handler to
-an event, and a new API to an existing object. The process of doing
-this is called *configuration*. In a technical sense, Grok can be
-understood as an alternate configuration mechanism for Zope 3.
-
-Zope 3 without Grok uses ZCML for hooking up objects together. ZCML is
-an XML-based configuration language. ZCML statements are stored in
-their own file, next to the code. While using ZCML has the benefit of
-being explicit and flexible, it can also make code harder to read as
-there are more files to consult in order to understand what is going
-on.
-
-Grok does away with ZCML. Instead it analyzes your Python code for the
-use of certain special base classes and directives, and then "groks"
-it. This grokking process results in the same configuration as it
-would have if you used the equivalent ZCML. We believe that having all
-configuration along with your Python code makes the code easier to
-follow and more fun to develop.
-
-Grok has been designed so that if you organize your code in a certain
-way, you can even leave out most of the explicit directives in your
-Python code. This makes code written for Grok look clean and
-uniform. You still have all the power of explicit configuration
-available should you need it, however.
-
-During the development of Grok we have taken a careful look at common
-patterns in Zope 3 code and configuration. Grok aims to make these
-patterns easier to use and more succinct.

Modified: grok/branches/ulif-adminless/doc/conf.py
===================================================================
--- grok/branches/ulif-adminless/doc/conf.py	2008-07-10 20:42:05 UTC (rev 88203)
+++ grok/branches/ulif-adminless/doc/conf.py	2008-07-10 20:48:38 UTC (rev 88204)
@@ -39,7 +39,7 @@
 #extensions = []
 
 # Add any paths that contain templates here, relative to this directory.
-#templates_path = []
+templates_path = ['.']
 
 # The suffix of source filenames.
 source_suffix = '.rst'
@@ -48,7 +48,7 @@
 master_doc = 'index'
 
 # General substitutions.
-project = 'Grok'
+project = 'Official Grok'
 copyright = '2006-2008, The Zope Foundation'
 
 # The default replacements for |version| and |release|, also used in various
@@ -87,16 +87,12 @@
 # typographically correct entities.
 html_use_smartypants = True
 
-# Content template for the index page, filename relative to this file.
-#html_index = ''
-html_index = path.join(path.abspath(curdir), 'docindex.template')
-
 # Custom sidebar templates, maps page names to filenames relative to this file.
 #html_sidebars = {}
 
 # Additional templates that should be rendered to pages, maps page names to
 # filenames relative to this file.
-#html_additional_pages = {}
+html_additional_pages = {'index':'docindex.template'}
 
 # If true, the reST sources are included in the HTML build as _sources/<name>.
 #html_copy_source = True

Modified: grok/branches/ulif-adminless/doc/contents.rst
===================================================================
--- grok/branches/ulif-adminless/doc/contents.rst	2008-07-10 20:42:05 UTC (rev 88203)
+++ grok/branches/ulif-adminless/doc/contents.rst	2008-07-10 20:48:38 UTC (rev 88204)
@@ -6,7 +6,6 @@
    :maxdepth: 2
 
    changes.rst
-   about.rst
    tutorial.rst
    grok_overview.rst
    reference/index.rst

Modified: grok/branches/ulif-adminless/doc/docindex.template
===================================================================
--- grok/branches/ulif-adminless/doc/docindex.template	2008-07-10 20:42:05 UTC (rev 88203)
+++ grok/branches/ulif-adminless/doc/docindex.template	2008-07-10 20:48:38 UTC (rev 88204)
@@ -1,49 +1,54 @@
-  <p><strong>Parts of the documentation:</strong></p>
+{% extends "layout.html" %}
+{% set title = 'Overview' %}
+{% block body %}
+
+  <h1>{{ docstitle }}</h1>
+  <p>
+  This is official documentation for Grok {{ release }}.
+  {% if last_updated %}Last modifed on {{ last_updated }}.{% endif %}
+  </p>
+
+  <p><strong>Sections</strong></p>
   <table class="contentstable" align="center"><tr>
     <td width="50%">
-      <p class="biglink"><a class="biglink" href="{{ pathto("changes") }}"
-      >What's new in Grok {{ version }}?</a><br>
-      <span class="linkdescr">changes during the releases</span></p>
-
       <p class="biglink"><a class="biglink" href="{{ pathto("tutorial") }}"
-      >Tutorial</a><br>
-      <span class="linkdescr">Get started with Grok</span></p>
+      >Grok Tutorial</a><br>
+      <span class="linkdescr">Get started with Grok.</span></p>
 
       <p class="biglink"><a class="biglink" href="{{ pathto("grok_overview") }}"
       >Grok Developer Notes</a><br>
-      <span class="linkdescr">Learn more about Grok</span></p>
+      <span class="linkdescr">Overview of what's in Grok and how to use it.</span></p>
 
+      <p class="biglink"><a class="biglink" href="{{ pathto("reference/index") }}">The Grok Reference</a><br>
+         <span class="linkdescr">Describes syntax and package elements.</span></p>
+
     </td><td width="50%">
+	    <p class="biglink"><a class="biglink" href="{{ pathto("changes") }}"
+	    >What's new in Grok?</a><br>
+	    <span class="linkdescr">Changes made in each Grok release.</span></p>
 
-      <p class="biglink"><a class="biglink" href="{{ pathto("about") }}"
-      >About Grok</a><br>
-      <span class="linkdescr">now even Cavemen can use Zope 3</span></p>
-
-      <p class="biglink"><a class="biglink" href="{{ pathto("reference/index") }}">The Grok Reference</a><br>
-         <span class="linkdescr">describes syntax and package elements</span></p>
-
       <p class="biglink"><a class="biglink" href="{{ pathto("naming_conventions") }}">Naming Conventions</a><br>
-         <span class="linkdescr">how to name your stuff correctly</span></p>
+         <span class="linkdescr">How to name your stuff correctly.</span></p>
 
-
     </td></tr>
   </table>
-  <p><strong>Indices and tables:</strong></p>
+
+  <p><strong>Indices and tables</strong></p>
   <table class="contentstable" align="center"><tr>
     <td width="50%">
-      <p class="biglink"><a class="biglink" href="{{ pathto("contents") }}">Complete Table of Contents</a><br>
-         <span class="linkdescr">lists all sections and subsections</span></p>
+      <p class="biglink"><a class="biglink" href="{{ pathto("contents") }}">Table of Contents</a><br>
+         <span class="linkdescr">Lists all sections and subsections.</span></p>
 <!--
       <p class="biglink"><a class="biglink" href="{{ pathto("search") }}">Search page</a><br>
          <span class="linkdescr">search this documentation</span></p>
 -->
     </td><td width="50%">
-      <p class="biglink"><a class="biglink" href="{{ pathto("genindex") }}">General Index</a><br>
-         <span class="linkdescr">all functions, classes, terms</span></p>
+      <p class="biglink"><a class="biglink" href="{{ pathto("genindex") }}">Index</a><br>
+         <span class="linkdescr">All functions, classes, terms.</span></p>
     </td></tr>
   </table>
 
-  <p><strong>Meta information:</strong></p>
+  <p><strong>Further information</strong></p>
   <table class="contentstable" align="center"><tr>
     <td width="50%">
 
@@ -63,3 +68,13 @@
 
     </td></tr>
   </table>
+
+  <p>
+	The <b>Official Grok Documentation</b> documents the core features of the
+	Grok framework. For further reading, the
+	<a href="http://grok.zope.org/documentation/">Community Grok Documentation</a>
+	contains deeper information on working with Grok, as well as using 
+	additional packages with Grok that are not part of the core framework.
+  </p>
+
+{% endblock %}
\ No newline at end of file

Modified: grok/branches/ulif-adminless/doc/index.rst
===================================================================
--- grok/branches/ulif-adminless/doc/index.rst	2008-07-10 20:42:05 UTC (rev 88203)
+++ grok/branches/ulif-adminless/doc/index.rst	2008-07-10 20:48:38 UTC (rev 88204)
@@ -1,182 +0,0 @@
-=============
-What is Grok?
-=============
-
-.. image:: resources/evencaveman.jpg
-   :alt: Now even cavemen can use Zope3
-   :class: right
-
-Grok is a web application framework for Python developers. It is aimed at both
-beginners and very experienced web developers. Grok has an emphasis on agile
-development. Grok is easy and powerful.
-
-You will likely have heard about many different web frameworks for Python as
-well as other languages. Why should you consider Grok?
-
-* Grok offers a *lot* of building blocks for your web application.
-* Grok is informed by a *lot* of hard-earned wisdom.
-
-Grok accomplishes this by being based on `Zope 3`_, an advanced
-object-oriented web framework. While Grok is based on Zope 3, and
-benefits a lot from it, you do not need to know Zope at all in order
-to get productive with Grok.
-
-`Read More <./about.html>`_
-
-.. _Zope 3: http://wiki.zope.org/zope3
-
-Grok News
----------
-2008-01-20:
-  Grok 0.11.1 has been released! See the `announcement`__ for more details!
-
-  .. __: http://permalink.gmane.org/gmane.comp.web.zope.grok.devel/3565
-
-2007-11-08:
-  Grok 0.11 has been released! See the release `announcement`__
-  for more details! For projects that want to upgrade, please read the
-  `upgrade notes <upgrade.html>`_
-
-  .. __: http://permalink.gmane.org/gmane.comp.web.zope.devel/14171
-
-2007-10-24:
-  Grok 0.10.2 has been released! See the `announcement`__ for more details!
-
-  .. __: http://article.gmane.org/gmane.comp.web.zope.grok.devel/2786
-
-2007-10-10:
-  Grok 0.10.1 has been released! See the original `announcement`__ for more
-  details!
-
-  .. __: http://article.gmane.org/gmane.comp.web.zope.announce/1393
-
-2007-10-05:
-  Read about what was achieved during the `Grok Neanderthal Sprint`__ on the
-  `Sprint Accomplishments`__ page!
-
-  .. __: http://wiki.zope.org/grok/NeanderthalerSprint
-  .. __: http://wiki.zope.org/grok/SprintAccomplishments
-
-2007-09-24:
-  The first week of October (1-5 October) we are having the `Grok Neanderthal
-  Sprint`__ in Cologne, Germany. This sprint is generously sponsored by
-  `GfU Cyrus`__.
-
-  .. __: http://wiki.zope.org/grok/NeanderthalerSprint
-  .. __: http://www.gfu.net
-
-Who is Grok?
-------------
-
-.. image:: ./resources/grok-standing.jpg
-   :alt: Grok!
-   :class: right
-
-Grok is a friendly caveman from the Stone Age. He has a big club that he hunts
-mammoths with. He will also use this club to smash anything he doesn't like.
-
-"ME GROK SMASH ZCML!"
-
-The word grok comes from the novel `Stranger in a Strange Land`_ by Robert A.
-Heinlein, and is defined in his book as:
-
-  Grok means to understand so thoroughly that the observer becomes part of the
-  observed - to merge, blend, intermarry, lose identity in group experience.
-
-.. _Stranger in a Strange Land: http://en.wikipedia.org/wiki/Stranger_in_a_Strange_Land
-
-Watch Grok in Action
---------------------
-
-* `Simple ToDo`_ application is a tutorial-style introduction to Grok by Philipp von Weitershausen.
-* `Introduction to Grok`_ is a talk given by Philipp von Weitershausen to a group of Zope developers.
-
-.. _Simple ToDo: http://www.archive.org/details/grok_todo_part1
-.. _Introduction to Grok: http://comlounge.tv/blog/zope/cltv23-snow-sprint-2007-grok-presentation
-
-What does Grok code look like?
-------------------------------
-
-::
-
-    import grok
-
-    class HelloWorld(grok.Application, grok.Model):
-        pass
-
-    class Index(grok.View):
-        pass
-
-    index = grok.PageTemplate("""
-        <html><body>
-            <p>ME GROK HELLO WORLD!</p>
-        </body></html>
-        """")
-
-* `Herd of Mammoths`_: a very simple application that only goes a bit beyond "hello world".
-* `Grokstar`_: a simple blog application written with Grok.
-* `Grok Wiki`_: a simple wiki application written with Grok.
-* `Paleosoft.org`_: a collection of sample apps written in Grok/Zope3 by
-  Luciano Ramalho as part of the Google Summer of Code.
-
-.. _Herd of Mammoths: http://www.z3lab.org/sections/blogs/philipp-weitershausen/2007_01_09_you-thought-zope-3-wasn
-.. _Grokstar: http://svn.zope.org/Grokstar/
-.. _Grok Wiki: http://svn.zope.org/grok/trunk/grokwiki/
-.. _Paleosoft.org: http://paleosoft.org/
-
-ME GROK HYPERLINKS!
--------------------
-
-* Get the latest version in the form of a `Grok Python Package`_ from the Python Cheese Shop.
-* Feature requests and bugs are tracked in the `Grok Issue Tracker`_ at LaunchPad.
-* `Grok-dev mailing list`_ for discussing the development of Grok.
-* There is a `Grok IRC`_ channel on `freenode.net`_
-
-.. _Grok Python Package: http://cheeseshop.python.org/pypi/grok
-.. _Grok Issue Tracker: https://launchpad.net/grok
-.. _Grok-dev mailing list: http://mail.zope.org/mailman/listinfo/grok-dev
-.. _Grok IRC: irc://irc.freenode.net/grok
-.. _freenode.net: http://freenode.net/
-
-The source code to Grok is kept in the Zope SVN repository. You can do an
-anonymous check out of the latest version of Grok with the following command:::
-
-  svn co svn://svn.zope.org/repos/main/grok/trunk grok
-
-ME GROK TUTORIAL!
-------------------
-
-* `Grok tutorial`__
-
-  .. __: tutorial.html
-
-ME GROK SPRINTS AND BLOGS!
---------------------------
-
-Grok development is often done in the form of sprints. A sprint is a when a
-group of developers get together in the same place and all work on a focused
-set of tasks.
-
-* People `blogged <http://wiki.zope.org/grok/SprintAccomplishments>`_ about
-  the `Grok Neanderthal Sprint <http://wiki.zope.org/grok/NeanderthalerSprint/>`_.
-
-* `Jan-Wijbrand Kolman blogged`_ about the second Grok sprint, and
-  `Martijn Faassen blogged`_ about it as well.
-
-* `Martijn Faassen's blog entry`_ details the first Grok sprint.
-
-.. _Martijn Faassen's blog entry: http://faassen.n--tree.net/blog/view/weblog/2006/11/09/0
-.. _Jan-Wijbrand Kolman blogged: http://jw.n--tree.net/blog/dev/python/second-grok-sprint
-.. _Martijn Faassen blogged: http://faassen.n--tree.net/blog/view/weblog/2007/01/09/0
-
-.. toctree::
-
-   about.rst
-   contents.rst
-   grok_overview.rst
-   reference/index.rst
-
-   bugs.rst
-   README.rst
-   license.rst
-   copyright.rst

Copied: grok/branches/ulif-adminless/doc/layout.html (from rev 88203, grok/trunk/doc/layout.html)
===================================================================
--- grok/branches/ulif-adminless/doc/layout.html	                        (rev 0)
+++ grok/branches/ulif-adminless/doc/layout.html	2008-07-10 20:48:38 UTC (rev 88204)
@@ -0,0 +1,186 @@
+{%- block doctype -%}
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+{%- endblock %}
+{%- set reldelim1 = reldelim1 is not defined and ' &raquo;' or reldelim1 %}
+{%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %}
+{%- macro relbar %}
+    <div class="header">
+        {%- block rootrellink %}
+        <a href="{{ pathto('index') }}">Official Grok Documentation</a> version {{ release }}
+        {%- endblock %}
+    <div class="globalnav">
+      <h3>Navigation</h3>
+      <div id="globalnavwrapper">
+      <ul>
+            <li><a href="{{ pathto("tutorial") }}">Tutorial</a></li>
+            <li><a href="{{ pathto("grok_overview") }}">Developer's Notes</a></li>
+            <li><a href="{{ pathto("reference/index") }}">Reference</a></li>
+            <li><a rel="index" title="Global index" href="{{ pathto('genindex') }}">Index</a></li>
+            <li><a href="{{ pathto("changes") }}">What's Changed</a></li>
+            <li><a href="http://grok.zope.org/documentation/">Grok Community Doucmentation</a></li>
+            {%- block relbaritems %}{% endblock %}
+      </ul>
+      </div>
+    </div>
+    </div>
+{%- endmacro %}
+{%- macro sidebar %}
+      {%- if builder != 'htmlhelp' %}
+      <div class="sphinxsidebar">
+        <div class="sphinxsidebarwrapper">
+          
+          <a href="{{ pathto('index') }}">
+          <img class="logo" src="{{ pathto('_static/logo.gif', 1) }}" alt="Logo"/></a>
+          
+          {%- block sidebartoc %}
+          {%- if display_toc %}
+            <h3>Table Of Contents</h3>
+            {{ toc }}
+          {%- endif %}
+          {%- endblock %}
+          {%- block sidebarrel %}
+          {%- if prev %}
+            <h4>Previous topic</h4>
+            <p class="topless"><a href="{{ prev.link|e }}" title="previous chapter">{{ prev.title }}</a></p>
+          {%- endif %}
+          {%- if next %}
+            <h4>Next topic</h4>
+            <p class="topless"><a href="{{ next.link|e }}" title="next chapter">{{ next.title }}</a></p>
+          {%- endif %}
+          {%- endblock %}
+          {%- if sourcename %}
+            <h3>This Page</h3>
+            <ul class="this-page-menu">
+            {%- if builder == 'web' %}
+              <li><a href="#comments">Comments ({{ comments|length }} so far)</a></li>
+              <li><a href="{{ pathto('@edit/' + sourcename)|e }}">Suggest Change</a></li>
+              <li><a href="{{ pathto('@source/' + sourcename)|e }}">Show Source</a></li>
+            {%- elif builder == 'html' %}
+              <li><a href="{{ pathto('_sources/' + sourcename, true)|e }}">Show Source</a></li>
+            {%- endif %}
+            </ul>
+          {%- endif %}
+          {%- if customsidebar %}
+          {{ rendertemplate(customsidebar) }}
+          {%- endif %}
+          {%- block sidebarsearch %}
+          {%- if pagename != "search" %}
+            <h3>{{ builder == 'web' and 'Keyword' or 'Quick' }} search</h3>
+            <form class="search" action="{{ pathto('search') }}" method="get">
+              <input type="text" name="q" size="18" /> <input type="submit" value="Go" />
+              <input type="hidden" name="check_keywords" value="yes" />
+              <input type="hidden" name="area" value="default" />
+            </form>
+            {%- if builder == 'web' %}
+            <p style="font-size: 90%">Enter a module, class or function name.</p>
+            {%- endif %}
+          {%- endif %}
+          {%- endblock %}
+        </div>
+      </div>
+      {%- endif %}
+{%- endmacro -%}
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    {%- if builder != 'htmlhelp' %}
+      {%- set titlesuffix = " &mdash; " + docstitle %}
+    {%- endif %}
+    <title>{{ title|striptags }}{{ titlesuffix }}</title>
+    {%- if builder == 'web' %}
+    <link rel="stylesheet" href="{{ pathto('index') }}?do=stylesheet{%
+      if in_admin_panel %}&admin=yes{% endif %}" type="text/css" />
+    {%- for link, type, title in page_links %}
+    <link rel="alternate" type="{{ type|e(true) }}" title="{{ title|e(true) }}" href="{{ link|e(true) }}" />
+    {%- endfor %}
+    {%- else %}
+    <link rel="stylesheet" href="{{ pathto('_static/' + style, 1) }}" type="text/css" />
+    <link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css" />
+    {%- endif %}
+    {%- if builder != 'htmlhelp' %}
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+          URL_ROOT:   '{{ pathto("", 1) }}',
+          VERSION:    '{{ release }}',
+          COLLAPSE_MODINDEX: false,
+      };
+    </script>
+    <script type="text/javascript" src="{{ pathto('_static/jquery.js', 1) }}"></script>
+    <script type="text/javascript" src="{{ pathto('_static/interface.js', 1) }}"></script>
+    <script type="text/javascript" src="{{ pathto('_static/doctools.js', 1) }}"></script>
+    {%- if use_opensearch %}
+    <link rel="search" type="application/opensearchdescription+xml"
+          title="Search within {{ docstitle }}"
+          href="{{ pathto('_static/opensearch.xml', 1) }}"/>
+    {%- endif %}
+    {%- if favicon %}
+    <link rel="shortcut icon" href="{{ pathto('_static/' + favicon, 1) }}"/>
+    {%- endif %}
+    {%- endif %}
+{%- block rellinks %}
+    {%- if hasdoc('about') %}
+    <link rel="author" title="About these documents" href="{{ pathto('about') }}" />
+    {%- endif %}
+    <link rel="contents" title="Global table of contents" href="{{ pathto('contents') }}" />
+    <link rel="index" title="Global index" href="{{ pathto('genindex') }}" />
+    <link rel="search" title="Search" href="{{ pathto('search') }}" />
+    {%- if hasdoc('copyright') %}
+    <link rel="copyright" title="Copyright" href="{{ pathto('copyright') }}" />
+    {%- endif %}
+    <link rel="top" title="{{ docstitle }}" href="{{ pathto('index') }}" />
+    {%- if parents %}
+    <link rel="up" title="{{ parents[-1].title|striptags }}" href="{{ parents[-1].link|e }}" />
+    {%- endif %}
+    {%- if next %}
+    <link rel="next" title="{{ next.title|striptags }}" href="{{ next.link|e }}" />
+    {%- endif %}
+    {%- if prev %}
+    <link rel="prev" title="{{ prev.title|striptags }}" href="{{ prev.link|e }}" />
+    {%- endif %}
+{%- endblock %}
+{%- block extrahead %}{% endblock %}
+  </head>
+  <body>
+
+{%- block relbar1 %}{{ relbar() }}{% endblock %}
+
+{%- block sidebar1 %}{# possible location for sidebar #}{% endblock %}
+
+{%- block document %}
+    <div class="document">
+      <div class="documentwrapper">
+      {%- if builder != 'htmlhelp' %}
+        <div class="bodywrapper">
+      {%- endif %}
+          <div class="body">
+            {% block body %}{% endblock %}
+          </div>
+      {%- if builder != 'htmlhelp' %}
+        </div>
+      {%- endif %}
+      </div>
+{%- endblock %}
+
+{%- block sidebar2 %}{{ sidebar() }}{% endblock %}
+      <div class="clearer"></div>
+    </div>
+
+{%- block footer %}
+    <div class="footer">
+    {%- if hasdoc('copyright') %}
+      &copy; <a href="{{ pathto('copyright') }}">Copyright</a> {{ copyright }}.
+    {%- else %}
+      &copy; Copyright {{ copyright }}.
+    {%- endif %}
+    {%- if last_updated %}
+      Last updated on {{ last_updated }}.
+    {%- endif %}
+    {%- if show_sphinx %}
+      Created using <a href="http://sphinx.pocoo.org/">Sphinx</a>.
+    {%- endif %}
+    </div>
+{%- endblock %}
+  </body>
+</html>

Modified: grok/branches/ulif-adminless/doc/reference/components.rst
===================================================================
--- grok/branches/ulif-adminless/doc/reference/components.rst	2008-07-10 20:42:05 UTC (rev 88203)
+++ grok/branches/ulif-adminless/doc/reference/components.rst	2008-07-10 20:48:38 UTC (rev 88204)
@@ -4,16 +4,30 @@
 **********
 
 .. Here we documented the component base classes. For the directive possible
-   for each component we document only the specific within its context. We then
-   refer to the directives documented in the directives.rst file.
+    for each component we document only the specific within its context. We then
+    refer to the directives documented in the directives.rst file.
 
-The :mod:`grok` module defines a set of components that provide basic Zope 3
-functionality in a convenient way. Grok applications are built by subclassing
-these components.
+The :mod:`grok` module defines a set of base classes for creating new 
+components of different types, that provide basic Zope 3 functionality in a
+convenient way. Grok applications are built by subclassing these components.
 
+Components in Grok and Zope 3 can be any plain Python object, that you have
+declared implements one or more Interface(s). The inclusion of these Grok base
+classes in your own Python classes inheritance automatically handles the
+component registration with the Zope Component Architecture. This process of
+introspecting your Grok code during initialization and wiring together
+components based on common conventions that you follow in the structure
+of your source code is called "grokking".
+
+
 Core components
 ~~~~~~~~~~~~~~~
 
+:class:`grok.Application`
+=========================
+
+Base class for applications. Inherits from :class:`grok.Site`.
+
 :class:`grok.Model`
 ===================
 
@@ -23,102 +37,141 @@
 :class:`grok.Container`
 =======================
 
-Mixin base class to define a container object. The container implements the
+Mixin base class to define a container object. Objects in a container are 
+manipulated using the same syntax as you would with the standard
+Python Dictionary object. The container implements the
 zope.app.container.interfaces.IContainer interface using a BTree, providing
 reasonable performance for large collections of objects.
 
-:class:`grok.Application`
-=========================
+**Example 1: Perform Create, Read, Update and Delete (CRUD) on a container**
 
+.. code-block:: python
+
+    # define a container and a model and then create them
+    class BoneBag(grok.Container): pass
+    class Bone(grok.Model): pass    
+    bag = BoneBag()
+    skull = Bone()
+    
+    # ... your classes are then "grokked" by Grok ...
+    
+    # store an object in a container
+    bag['bone1'] = skull
+    
+    # test for containment
+    bag.has_key('bone1')
+    
+    # retrieve an object from a container
+    first_bone = bag['bone1'] 
+    
+    # iterate through objects in a container with .values()
+    # you can also use .keys() and .items()
+    for bone in bag.values():
+        bone.marks = 'teeth'
+    
+    # delete objects using the del keyword
+    del bag['bone1']
+
+:class:`grok.Indexes`
+=====================
+
+Base class for catalog index definitions.
+
 Adapters
 ~~~~~~~~
 
 :class:`grok.Adapter`
 =====================
 
-Implementation, configuration, and registration of Zope 3 adapters.
+Implementation, configuration, and registration of Zope 3 Adapters.
 
+Adapters are components that are constructed from other components. They
+take an existing interface and extend it to provide a new interface.
+
 .. class:: grok.Adapter
 
-   Base class to define an adapter. Adapters are automatically
-   registered when a module is "grokked".
+    Base class to define an adapter. Adapters are automatically
+    registered when a module is "grokked".
 
-   .. attribute:: grok.Adapter.context
+    .. attribute:: grok.Adapter.context
 
-      The adapted object.
+        The adapted object.
 
-   **Directives:**
+    **Directives:**
 
-   :func:`grok.context(context_obj_or_interface)`
-      Maybe required. Identifies the type of objects or interface for
-      the adaptation.
+    :func:`grok.context(context_obj_or_interface)`
+        Maybe required. Identifies the type of objects or interface for
+        the adaptation.
 
-   .. seealso::
+    .. seealso::
 
-      :func:`grok.context`
+        :func:`grok.context`
 
-   :func:`grok.implements(\*interfaces)`
-      Required. Identifies the interface(s) the adapter implements.
+    :func:`grok.implements(\*interfaces)`
+        Required. Identifies the interface(s) the adapter implements.
 
-   .. seealso::
+    .. seealso::
 
-      :func:`grok.implements`
+        :func:`grok.implements`
 
-   :func:`grok.name(name)`
-      Optional. Identifies the name used for the adapter
-      registration. If ommitted, no name will be used.
+    :func:`grok.name(name)`
+        Optional. Identifies the name used for the adapter
+        registration. If ommitted, no name will be used.
 
-      When a name is used for the adapter registration, the adapter
-      can only be retrieved by explicitely using its name.
+        When a name is used for the adapter registration, the adapter
+        can only be retrieved by explicitely using its name.
 
-   .. seealso::
+    .. seealso::
 
-      :func:`grok.name`
+        :func:`grok.name`
 
-   :func:`grok.provides(name)`
-      Maybe required.
+    :func:`grok.provides(name)`
+        Maybe required.
 
-   .. seealso::
+    .. seealso::
 
-      :func:`grok.provides`
+        :func:`grok.provides`
 
-**Example 1:**
+**Example 1: Simple adaptation example**
 
 .. code-block:: python
 
-   import grok
-   from zope import interface
+    import grok
+    from zope import interface
 
-   class Cave(grok.Model):
-       pass
+    class Cave(grok.Model):
+        "start with a cave objects (the adaptee)"
 
-   class IHome(interface.Interface):
-       pass
+    class IHome(interface.Interface):
+        "we want to extend caves with the IHome interface"
 
-   class Home(grok.Adapter):
-       grok.implements(IHome)
+    class Home(grok.Adapter):
+        "the home adapter turns caves into habitable homes!"
+        grok.implements(IHome)
 
-   home = IHome(cave)
+    # Adapation (component look-up) is invoked by passing the adaptee
+    # to the interface as a constructor and returns the component adapted to   
+    home = IHome(cave)
 
 
 **Example 2: Register and retrieve the adapter under a specific name**
 
 .. code-block:: python
 
-   import grok
-   from zope import interface
+    import grok
+    from zope import interface
 
-   class Cave(grok.Model):
-       pass
+    class Cave(grok.Model):
+        pass
     class IHome(interface.Interface):
-       pass
+        pass
 
-   class Home(grok.Adapter):
-       grok.implements(IHome)
-       grok.name('home')
+    class Home(grok.Adapter):
+        grok.implements(IHome)
+        grok.name('home')
 
-   from zope.component import getAdapter
-   home = getAdapter(cave, IHome, name='home')
+    from zope.component import getAdapter
+    home = getAdapter(cave, IHome, name='home')
 
 
 :class:`grok.MultiAdapter`
@@ -126,47 +179,50 @@
 
 .. class:: grok.MultiAdapter
 
-   Base class to define a multi adapter. MultiAdapters are automatically
-   registered when a module is "grokked".
+    Base class to define a Multi Adapter.
+   
+    A simple adapter normally adapts only one object, but an adapter may
+    adapt more than one object. If an adapter adapts more than one objects,
+    it is called multi-adapter.
 
-   **Directives:**
+    **Directives:**
 
-   :func:`grok.adapts(\*objects_or_interfaces)`
-      Required. Identifies the combination of types of objects or interfaces
-      for the adaptation.
+    :func:`grok.adapts(\*objects_or_interfaces)`
+        Required. Identifies the combination of types of objects or interfaces
+        for the adaptation.
 
-   :func:`grok.implements(\*interfaces)`
-      Required. Identifies the interfaces(s) the adapter implements.
+    :func:`grok.implements(\*interfaces)`
+        Required. Identifies the interfaces(s) the adapter implements.
 
-   :func:`grok.name(name)`
-      Optional. Identifies the name used for the adapter registration. If
-      ommitted, no name will be used.
+    :func:`grok.name(name)`
+        Optional. Identifies the name used for the adapter registration. If
+        ommitted, no name will be used.
 
-      When a name is used for the adapter registration, the adapter can only be
-      retrieved by explicitely using its name.
+        When a name is used for the adapter registration, the adapter can only be
+        retrieved by explicitely using its name.
 
-   :func:`grok.provides(name)`
-      Maybe required. If the adapter implements more than one interface,
-      :func:`grok.provides` is required to disambiguate for what interface the
-      adapter will be registered.
+    :func:`grok.provides(name)`
+        Only required if the adapter implements more than one interface.
+        :func:`grok.provides` is required to disambiguate for which interface the
+        adapter will be registered for.
 
-**Example:**
+**Example: A home is made from a cave and a fireplace.**
 
 .. code-block:: python
 
-   import grok
-   from zope import interface
+    import grok
+    from zope import interface
 
-   class Fireplace(grok.Model):
+    class Fireplace(grok.Model):
        pass
 
-   class Cave(grok.Model):
+    class Cave(grok.Model):
        pass
 
-   class IHome(interface.Interface):
+    class IHome(interface.Interface):
        pass
 
-   class Home(grok.MultiAdapter):
+    class Home(grok.MultiAdapter):
        grok.adapts(Cave, Fireplace)
        grok.implements(IHome)
 
@@ -174,12 +230,50 @@
            self.cave = cave
            self.fireplace = fireplace
 
-   home = IHome(cave, fireplace)
+    home = IHome(cave, fireplace)
 
 :class:`grok.Annotation`
 ========================
 
+Annotation components are persistent writeable adapters.
 
+.. class:: grok.Annotation
+
+    Base class to declare an Annotation. Inherits from the
+    persistent.Persistent class.
+
+**Example: Storing annotations on model objects**
+
+.. code-block:: python
+
+    import grok
+    from zope import interface
+
+    # Create a model and an interface you want to adapt it to
+    # and an annotation class to implement the persistent adapter.
+    class Mammoth(grok.Model):
+        pass
+
+    class ISerialBrand(interface.Interface):
+        unique = interface.Attribute("Brands")
+
+    class Branding(grok.Annotation):
+        grok.implements(IBranding)
+        unqiue = 0
+   
+    # Grok the above code, then create some mammoths
+    manfred = Mammoth()
+    mumbles = Mammoth()
+   
+    # creating Annotations work just like Adapters
+    livestock1 = ISerialBrand(manfred)
+    livestock2 = ISerialBrand(mumbles)
+   
+    # except you can store data in them, this data will transparently persist
+    # in the database for as long as the object exists
+    livestock1.serial = 101
+    livestock2.serial = 102
+
 Utilities
 ~~~~~~~~~
 
@@ -188,25 +282,25 @@
 
 .. class:: grok.GlobalUtility
 
-   Base class to define a globally registered utility. Global utilities are
-   automatically registered when a module is "grokked".
+    Base class to define a globally registered utility. Global utilities are
+    automatically registered when a module is "grokked".
 
-   **Directives:**
+    **Directives:**
 
-   :func:`grok.implements(\*interfaces)`
-      Required. Identifies the interfaces(s) the utility implements.
+    :func:`grok.implements(\*interfaces)`
+        Required. Identifies the interfaces(s) the utility implements.
 
-   :func:`grok.name(name)`
-      Optional. Identifies the name used for the adapter registration. If
-      ommitted, no name will be used.
+    :func:`grok.name(name)`
+        Optional. Identifies the name used for the adapter registration. If
+        ommitted, no name will be used.
 
-      When a name is used for the global utility registration, the global
-      utility can only be retrieved by explicitely using its name.
+        When a name is used for the global utility registration, the global
+        utility can only be retrieved by explicitely using its name.
 
-   :func:`grok.provides(name)`
-      Maybe required. If the global utility implements more than one interface,
-      :func:`grok.provides` is required to disambiguate for what interface the
-      global utility will be registered.
+    :func:`grok.provides(name)`
+        Maybe required. If the global utility implements more than one interface,
+        :func:`grok.provides` is required to disambiguate for what interface the
+        global utility will be registered.
 
 
 :class:`grok.LocalUtility`
@@ -214,51 +308,302 @@
 
 .. class:: grok.LocalUtility
 
-   Base class to define a utility that will be registered local to a
-   :class:`grok.Site` or :class:`grok.Application` object by using the
-   :func:`grok.local_utility` directive.
+    Base class to define a utility that will be registered local to a
+    :class:`grok.Site` or :class:`grok.Application` object by using the
+    :func:`grok.local_utility` directive.
 
-   **Directives:**
+    **Directives:**
 
-   :func:`grok.implements(\*interfaces)`
-      Optional. Identifies the interfaces(s) the utility implements.
+    :func:`grok.implements(\*interfaces)`
+        Optional. Identifies the interfaces(s) the utility implements.
 
-   :func:`grok.name(name)`
-      Optional. Identifies the name used for the adapter registration. If
-      ommitted, no name will be used.
+    :func:`grok.name(name)`
+        Optional. Identifies the name used for the adapter registration. If
+        ommitted, no name will be used.
 
-      When a name is used for the local utility registration, the local utility
-      can only be retrieved by explicitely using its name.
+        When a name is used for the local utility registration, the local utility
+        can only be retrieved by explicitely using its name.
 
-   :func:`grok.provides(name)`
-      Maybe required. If the local utility implements more than one interface
-      or if the implemented interface cannot be determined,
-      :func:`grok.provides` is required to disambiguate for what interface the
-      local utility will be registered.
+    :func:`grok.provides(name)`
+        Maybe required. If the local utility implements more than one interface
+        or if the implemented interface cannot be determined,
+        :func:`grok.provides` is required to disambiguate for what interface the
+        local utility will be registered.
 
-  .. seealso::
+  	.. seealso::
 
-    Local utilities need to be registered in the context of :class:`grok.Site`
-    or :class:`grok.Application` using the :func:`grok.local_utility` directive.
+	    Local utilities need to be registered in the context of :class:`grok.Site`
+	    or :class:`grok.Application` using the :func:`grok.local_utility` directive.
 
 :class:`grok.Site`
 ==================
 
+Contains a Site Manager. Site Managers act as containers for registerable
+components.
+
+If a Site Manager is asked for an adapter or utility, it checks for those
+it contains before using a context-based lookup to find another site
+manager to delegate to. If no other site manager is found they defer to
+the global site manager which contains file based utilities and adapters.
+
+.. class:: grok.Site
+
+	.. method:: getSiteManager():
+
+		Returns the site manager contained in this object.
+
+		If there isn't a site manager, raise a component lookup.
+
+	.. method:: setSiteManager(sitemanager):
+	
+		Sets the site manager for this object.
+
 Views
 ~~~~~
 
 :class:`grok.View`
 ==================
 
+View components provide context and request attributes. 
+
+The determination of what View gets used for what Model is made by walking the
+URL in the HTTP Request object sepearted by the / character. This process is
+called Traversal.
+
+.. class:: grok.View
+
+    Base class to define a View.
+
+    .. attribute:: context
+
+        The object that the view is presenting. This is often an instance of
+        a grok.Model class, but can also be a grok.Application or grok.Container
+        object.
+
+    .. attribute:: request
+   
+        The HTTP Request object.
+
+    .. attribute:: response
+
+        The HTTP Response object that is associated with the request. This
+        is also available as self.request.response, but the response attribute
+        is provided as a convenience.
+
+    .. attribute:: static
+
+        Directory resource containing the static files of the view's package.
+
+    .. method:: redirect(url):
+   
+        Redirect to given URL
+
+    .. method:: url(obj=None, name=None, data=None):
+   
+        Construct URL.
+
+        If no arguments given, construct URL to view itself.
+
+        If only obj argument is given, construct URL to obj.
+
+        If only name is given as the first argument, construct URL
+        to context/name.
+
+        If both object and name arguments are supplied, construct
+        URL to obj/name.
+
+        Optionally pass a 'data' keyword argument which gets added to the URL
+        as a cgi query string.
+
+    .. method:: default_namespace():
+
+        Returns a dictionary of namespaces that the template
+        implementation expects to always be available.
+
+        This method is *not* intended to be overridden by application
+        developers.
+
+    .. method:: namespace():
+   
+        Returns a dictionary that is injected in the template
+        namespace in addition to the default namespace.
+
+        This method *is* intended to be overridden by the application
+        developer.
+
+    .. method:: update(**kw):
+   
+        This method is meant to be implemented by grok.View
+        subclasses.  It will be called *before* the view's associated
+        template is rendered and can be used to pre-compute values
+        for the template.
+
+        update() can take arbitrary keyword parameters which will be
+        filled in from the request (in that case they *must* be
+        present in the request).
+
+    .. method:: render(**kw):
+   
+        A view can either be rendered by an associated template, or
+        it can implement this method to render itself from Python.
+        This is useful if the view's output isn't XML/HTML but
+        something computed in Python (plain text, PDF, etc.)
+
+        render() can take arbitrary keyword parameters which will be
+        filled in from the request (in that case they *must* be
+        present in the request).
+
+    .. method:: application_url(name=None):
+   
+        Return the URL of the closest application object in the
+        hierarchy or the URL of a named object (``name`` parameter)
+        relative to the closest application object.
+
+    .. method:: flash(message, type='message'):
+      
+        Send a short message to the user.
+
 :class:`grok.JSON`
 ==================
 
+Specialized View that returns data in JSON format.
+
+Python data returned is automatically converted into JSON format using
+the simplejson library. Every method name in a grok.JSON component is
+registered as the name of a JSON View. The exceptions are names that
+begin with an _ or special names such as __call__. The grok.require
+decorator can be used to protect methods with a permission.
+
+.. class:: grok.JSON
+
+    Base class for JSON methods.
+
+**Example 1: Create a public and a protected JSON view.**
+
+.. code-block:: python
+
+    class MammothJSON(grok.JSON):
+        """
+        Returns JSON from URLs in the form of:
+      
+        http://localhost/stomp
+        http://localhost/dance
+        """
+
+        grok.context(zope.interface.Interface)
+
+        def stomp(self):
+            return {'Manfred stomped.': ''}
+
+        @grok.require('zope.ManageContent')
+        def dance(self):
+            return {'Manfred does not like to dance.': ''}
+
+
 :class:`grok.XMLRPC`
 ====================
 
+Specialized View that responds to XML-RPC.
+
+The grok.require decorator can be used to protect methods with a permission.
+
+.. class:: grok.JSON
+
+    Base class for XML-RPC methods.
+
+**Example 1: Create a public and a protected XML-RPC view.**
+
+.. code-block:: python
+
+    from zope import interface
+   
+    class FooXMLRPC(grok.XMLRPC):
+        """
+        The methods in this class will be available as XML-RPC methods.
+      
+        http://localhost/say will return 'Hello world!' encoded in XML-RPC.
+        """
+        grok.context(interface.Interface)
+
+        def say(self):
+            return 'Hello world!'
+
+
 :class:`grok.Traverser`
 =======================
 
+A Traverser is used to map from a URL to an object being published (Model)
+and the View used to interact with that object.
+
+.. class:: grok.Traverser
+
+    Base class for custom traversers. Override the traverse method to 
+    supply the desired custom traversal behaviour.
+
+    .. attribute:: context
+
+        The object that is being traversed.
+
+    .. attribute:: request
+   
+        The HTTP Request object.
+
+    .. method:: traverse(self, name):
+      
+        You must provide your own implementation of this method to do what
+        you want. If you return None, Grok will use the default traversal
+        behaviour.
+
+    .. method:: browserDefault(request):
+   
+        Returns an object and a sequence of names.
+	  
+        The publisher calls this method at the end of each traversal path.
+        If the sequence of names is not empty, then a traversal step is made
+        for each name. After the publisher gets to the end of the sequence,
+        it will call browserDefault on the last traversed object.
+	  
+        The default behaviour in Grok is to return self.context for the object
+        and 'index' for the default view name.
+	  
+        Note that if additional traversal steps are indicated (via a
+        nonempty sequence of names), then the publisher will try to adjust
+        the base href.
+
+    .. method:: publishTraverse(request, name):
+
+        Lookup a name and return an object with `self.context` as it's parent.
+        The method can use the request to determine the correct object.
+	  
+        The 'request' argument is the publisher request object. The
+        'name' argument is the name that is to be looked up. It must
+        be an ASCII string or Unicode object.
+	  
+        If a lookup is not possible, raise a NotFound error.
+
+**Example 1: Traverse into a Herd Model and return a Mammoth Model**
+
+.. code-block:: python
+
+    import grok
+
+    class Herd(grok.Model):
+
+       def __init__(self, name):
+           self.name = name
+
+    class HerdTraverser(grok.Traverser):
+       grok.context(Herd)
+
+       def traverse(self, name):
+           return Mammoth(name)
+
+    class Mammoth(grok.Model):
+
+       def __init__(self, name):
+           self.name = name
+
+
 :class:`grok.PageTemplate`
 ==========================
 
@@ -268,62 +613,324 @@
 Forms
 ~~~~~
 
+Forms inherit from the `grok.View` class. They are a specialized type of
+View that renders an HTML Form.
+
 :class:`grok.Form`
 ==================
 
-.. Do not forget about the form_fields class attribute!
+.. class:: grok.Form
 
+    Base class for forms.
+
+    .. attribute:: prefix
+    
+        Page-element prefix. All named or identified page elements in a
+        subpage should have names and identifiers that begin with a subpage
+        prefix followed by a dot.
+
+    .. method:: setPrefix(prefix):
+
+        Update the subpage prefix
+
+    .. attribute:: label
+    
+        A label to display at the top of a form.
+        
+    .. attribute:: status
+    
+        An update status message. This is normally generated by success or
+        failure handlers.
+    
+    .. attribute:: errors
+
+        Sequence of errors encountered during validation.
+
+    .. attribute:: form_result
+    
+        Return from action result method.
+
+    .. attribute:: form_reset
+    
+        Boolean indicating whether the form needs to be reset.
+
+    .. attribute:: form_fields
+    
+        The form's form field definitions.
+
+        This attribute is used by many of the default methods.
+
+    .. attribute:: widgets
+    
+        The form's widgets.
+
+        - set by setUpWidgets
+
+        - used by validate
+
+
+    .. method:: setUpWidgets(ignore_request=False):
+    
+        Set up the form's widgets.
+
+        The default implementation uses the form definitions in the
+        form_fields attribute and setUpInputWidgets.
+
+        The function should set the widgets attribute.
+
+    .. method:: validate(action, data):
+    
+        The default form validator
+
+        If an action is submitted and the action doesn't have it's own
+        validator then this function will be called.
+
+    .. attribute:: template
+    
+        Template used to display the form
+
+    .. method:: resetForm():
+    
+        Reset any cached data because underlying content may have changed.
+
+    .. method:: error_views():
+    
+        Return views of any errors.
+
+        The errors are returned as an iterable.
+
+    .. method:: applyData(obj, **data):
+    
+        Save form data to an object.
+
+        This returns a dictionary with interfaces as keys and lists of
+        field names as values to indicate which fields in which
+        schemas had to be changed in order to save the data.  In case
+        the method works in update mode (e.g. on EditForms) and
+        doesn't have to update an object, the dictionary is empty.
+
 :class:`grok.AddForm`
 =====================
 
+Add forms are used for creating new objects. The widgets for this form
+are not bound to any existing content or model object.
+
+.. class:: grok.AddForm
+
+    Base class for add forms.
+
 :class:`grok.EditForm`
 ======================
 
+Edit forms are used for editing existing objects. The widgets for this form
+are bound to the object set in the `context` attribute.
+
+.. class:: grok.EditForm
+
+    Base class for edit forms.
+
 :class:`grok.DisplayForm`
 =========================
 
+Display forms are used to display an existing object. The widgets for this
+form are bound to the object set in the `context` attribute.
+
+.. class:: grok.DisplayForm
+
+    Base class for display forms.
+
 Security
 ~~~~~~~~
 
 :class:`Permission`
 ===================
 
+Permissions are used to protect Views so that they can only be called by
+an authenticated principal. If a View in Grok does not have a `grok.require`
+directive declaring a permission needed to use the View, then the view will
+be public.
+
+.. class:: grok.Permission
+
+    Base class for permissions. You must specify a unique name for every
+    permission using the `grok.name` directive. The convention for ensuring
+    uniqueness is to prefix your permission name with the name of your
+    Grok package followed by a dot, e.g. 'mypackage.MyPermissionName'.
+
+    .. attribute:: id
+    
+        Id as which this permission will be known and used. This is set
+        to the value specified in the `grok.name` directive.
+
+    .. attribute:: title
+
+        Human readable identifier for this permission.
+
+    .. attribute:: description
+
+        Description of the permission.
+
+    **Directives:**
+
+    :func:`grok.name(name)`
+    
+        Required. Identifies the unique name (also used as the id) of the
+        permission.
+
+    :func:`grok.title(title)`
+
+        Optional. Stored as the title attribute for this permission.
+    
+    :func:`grok.description(description)`
+
+        Optional. Stored as the description attribute for this permission.
+
+**Example 1: Define a new Permission and use it to protect a View**
+
+.. code-block:: python
+
+    import grok
+    import zope.interface
+    
+    class Read(grok.Permission):
+        grok.name('mypackage.Read')
+
+    class Index(grok.View):
+        grok.context(zope.interface.Interface)
+        grok.require('mypackage.Read')
+
 :func:`grok.define_permission` -- define a permission
 =====================================================
 
 .. function:: grok.define_permission(name)
 
-   A module-level directive to define a permission with name
-   `name`. Usually permission names are prefixed by a component- or
-   application name and a dot to keep them unique.
+    A module-level directive to define a permission with name
+    `name`. Usually permission names are prefixed by a component- or
+    application name and a dot to keep them unique.
 
-   Because in Grok by default everything is accessible by everybody,
-   it is important to define permissions, which restrict access to
-   certain principals or roles.
+    Because in Grok by default everything is accessible by everybody,
+    it is important to define permissions, which restrict access to
+    certain principals or roles.
 
-   **Example:**
+    **Example:**
 
-   .. code-block:: python
+    .. code-block:: python
 
-      import grok
-      grok.define_permission('cave.enter')
+        import grok
+        grok.define_permission('cave.enter')
 
 
-   .. seealso::
+    .. seealso::
 
-      :func:`grok.require`, :class:`grok.Permission`, :class:`grok.Role`
+        :func:`grok.require`, :class:`grok.Permission`, :class:`grok.Role`
 
-   .. versionchanged:: 0.11
+    .. versionchanged:: 0.11
 
-      replaced by :class:`grok.Permission`.
+        replaced by :class:`grok.Permission`.
 
 :class:`Role`
 =============
 
-Uncategorized
-~~~~~~~~~~~~~
+Roles provide a way to group together a collection of permissions. Principals
+(aka Users) can be granted a Role which will allow them to access all Views
+protected by the Permissions that the Role contains.
 
-.. The weird classes we couldn' categorize yet
+.. class:: grok.Role
 
-:class:`grok.Indexes`
-=====================
+    Base class for roles.
+
+    .. attribute:: id
+    
+        Id as which this role will be known and used. This is set
+        to the value specified in the `grok.name` directive.
+
+    .. attribute:: title
+
+        Human readable identifier for this permission.
+
+    .. attribute:: description
+
+        Description of the permission.
+
+    **Directives:**
+
+    :func:`grok.name(name)`
+
+        Required. Identifies the unique name (also used as the id) of the
+        role.
+
+    :func:`grok.permissions(permissions)`
+
+        Required. Declare the permissions granted to this role.
+
+    :func:`grok.title(title)`
+
+        Optional. Stored as the title attribute for this role.
+
+    :func:`grok.description(description)`
+
+        Optional. Stored as the description attribute for this role.
+
+**Example 1: Define a new 'paint.Artist' Role and assign it to the 'paint.grok' principal**
+
+.. code-block:: python
+
+    import grok
+    import zope.interface
+
+    class ViewPermission(grok.Permission):
+        grok.name('paint.ViewPainting')
+
+    class EditPermission(grok.Permission):
+        grok.name('paint.EditPainting')
+
+    class ErasePermission(grok.Permission):
+        grok.name('paint.ErasePainting')
+
+    class ApprovePermission(grok.Permission):
+        grok.name('paint.ApprovePainting')
+
+    class Artist(grok.Role):
+        """
+        An Artist can view, create and edit paintings. However, they can
+        not approve their painting for display in the Art Gallery Cave.
+        """
+        grok.name('paint.Artist')
+        grok.title('Artist')
+        grok.description('An artist owns the paintings that they create.')
+        grok.permissions(
+            'paint.ViewPainting', 'paint.EditPainting', 'paint.ErasePainting')
+
+    class CavePainting(grok.View):
+        grok.context(zope.interface.Interface)
+        grok.require(ViewPermission)
+
+        def render(self):
+            return 'What a beautiful painting.'
+
+    class EditCavePainting(grok.View):
+        grok.context(zope.interface.Interface)
+        grok.require(EditPermission)
+
+        def render(self):
+            return 'Let\'s make it even prettier.'
+
+    class EraseCavePainting(grok.View):
+        grok.context(zope.interface.Interface)
+        grok.require(ErasePermission)
+
+        def render(self):
+            return 'Oops, mistake, let\'s erase it.'
+
+    class ApproveCavePainting(grok.View):
+        grok.context(zope.interface.Interface)
+        grok.require(ApprovePermission)
+
+        def render(self):
+            return 'Painting owners cannot approve their paintings.'
+
+    # The app variable will typically be your Application instance,
+    # but could also be a container within your application.
+    from zope.securitypolicy.interfaces import IPrincipalRoleManager
+    IPrincipalRoleManager(app).assignRoleToPrincipal(
+       'paint.Artixt', 'paint.grok')

Modified: grok/branches/ulif-adminless/doc/reference/conf.py
===================================================================
--- grok/branches/ulif-adminless/doc/reference/conf.py	2008-07-10 20:42:05 UTC (rev 88203)
+++ grok/branches/ulif-adminless/doc/reference/conf.py	2008-07-10 20:48:38 UTC (rev 88204)
@@ -129,7 +129,7 @@
 # (source start file, target name, title, author, document class [howto/manual]).
 #latex_documents = []
 latex_documents = [
-    ('index', 'reference.tex', 'Grok Reference', 'The Grok Team', 'manual')
+    ('reference.tex', 'Grok Reference', 'The Grok Team', 'manual')
     ]
 
 # Additional stuff for the LaTeX preamble.

Modified: grok/branches/ulif-adminless/doc/reference/events.rst
===================================================================
--- grok/branches/ulif-adminless/doc/reference/events.rst	2008-07-10 20:42:05 UTC (rev 88203)
+++ grok/branches/ulif-adminless/doc/reference/events.rst	2008-07-10 20:48:38 UTC (rev 88204)
@@ -3,63 +3,366 @@
 Events
 ******
 
-grok provides convenient access to a set of often-used events from
+Grok provides convenient access to a set of often-used events from
 Zope 3. Those events include object and containment events. All events
 are available as interface and implemented class.
 
+Subscription: Event interfaces
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-grok.IContainerModifiedEvent
+All events interfaces inherit from the base interface of IObjectEvent.
+
+.. class:: zope.component.interfaces.IObjectEvent
+
+    .. attribute:: object
+
+        The subject of the event taking place.
+
+
+:class:`IObjectModifiedEvent`
+=============================
+
+An object has been modified. This is a general event that encompasses any
+change to a persistent object, such as adding, moving, copying, and removing
+of objects.
+
+.. class:: grok.IObjectModifiedEvent
+
+    Interface to subscribe to for object modifications.
+
+    .. attribute:: object
+
+        The subject of the event.
+
+    .. attribute:: descriptions
+
+        A list of descriptions of the modifications.
+
+:class:`IContainerModifiedEvent`
+================================
+
+The container has been modified. Container modifications is specific to
+addition, removal or reordering of sub-objects. Inherits from
+`grok.IObjectModifiedEvent`.
+
+.. class:: grok.IContainerModifiedEvent
+
+    Interface to subscribe to for container object modifications.
+
+    .. attribute:: object
+
+        The subject of the event.
+
+    .. attribute:: descriptions
+
+        A list of descriptions of the modifications.
+
+
+:class:`IObjectMovedEvent`
+==========================
+
+An object has been moved.
+
+.. class:: grok.IObjectMovedEvent
+
+   Interface to subscribe to for when an object is moved.
+
+   .. attribute:: object
+      
+      The subject of the event.
+   
+   .. attribute:: oldParent
+
+      The container stored in before moving.
+
+   .. attribute:: oldName
+
+      The name before moving.
+   
+   .. attribute:: newParent
+
+      The container stored in after moving.
+
+   .. attribute:: newName
+   
+      The name after moving.
+
+:class:`IObjectAddedEvent`
+==========================
+
+An object has been added to a container.
+
+.. class:: grok.IObjectAddedEvent
+
+   Interface to subscribe to for when an object is added to the database.
+   
+   Inherits from the `grok.IObjectMovedEvent` interface.
+
+   .. attribute:: object
+      
+      The subject of the event.
+   
+   .. attribute:: oldParent
+
+      The container stored in before moving.
+
+   .. attribute:: oldName
+
+      The name before moving.
+   
+   .. attribute:: newParent
+
+      The container stored in after moving.
+
+   .. attribute:: newName
+   
+      The name after moving.
+
+:class:`IObjectCopiedEvent`
+===========================
+
+An object has been copied.
+
+.. class:: grok.IObjectCopiedEvent
+
+   Interface to subscribe to for when an object is cloned.
+
+   Inherits from `grok.IObjectCreatedEvent` interface.
+
+   .. attribute:: object
+   
+      The subject of the event.
+
+   .. attribute:: original
+
+      The original object from which the copy was made.
+
+
+:class:`IObjectCreatedEvent`
 ============================
 
+An object has been created. This event is intended to happen before an
+object has been made persistent, that is it's location attributes
+(__name__ and __parent__) will usually be None.
 
-grok.IObjectAddedEvent
-======================
+.. class:: grok.IObjectCreatedEvent
 
+   Interface to subscribe to for when an object is created.
 
-grok.IObjectCopiedEvent
-=======================
+   .. attribute:: object
+   
+      The subject of the event.
 
 
-grok.IObjectCreatedEvent
-========================
+:class:`IObjectRemovedEvent`
+============================
 
+An object has been removed from a container.
 
-grok.IObjectModifiedEvent
+.. class:: grok.IObjectRemovedEvent
+
+   Interface to subscribe to for object deletions.
+
+   Inherits from `grok.IObjectMovedEvent`.
+
+   .. attribute:: object
+      
+      The subject of the event.
+   
+   .. attribute:: oldParent
+
+      The container stored in before removal.
+
+   .. attribute:: oldName
+
+      The name of the removed object.
+
+
+Notification: Event implementations
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Event objects are notifications that are sent when need to "fire off" an event.
+
+All of these event objects share the same minimal implementation of an event.
+This class is defined at zope.component.interfaces.ObjectEvent and looks like
+this:
+
+.. code-block:: python
+
+    from zope import interface
+    
+    class ObjectEvent(object):
+        interface.implements(IObjectEvent)
+
+        def __init__(self, object):
+            self.object = object
+
+
+:class:`ObjectModifiedEvent`
+============================
+
+Event object to send as a notification when an object is modified.
+
+.. class:: grok.ObjectModifiedEvent(object, *descriptions)
+
+    Default event implementation of the `grok.IObjectMovedEvent` interface.
+
+    .. attribute:: object
+
+       The subject of the event.
+
+    .. attribute:: descriptions
+    
+        A list of descriptions of the modifications.
+
+**Example 1: Send an object modification event with a modified attribute
+named "field".**
+
+.. code-block:: python
+
+    import grok
+    import zope.event
+    import zope.lifecycleevent.Attributes
+    from zope.interface import Interface
+    
+    class ISample(Interface) :
+        field = Attribute("A test field")
+    
+    class Sample(object) :
+        grok.implements(ISample)
+
+    obj = Sample()
+    obj.field = 42
+    zope.event.notify(
+    	grok.ObjectModifiedEvent(obj,
+    	zope.lifecycleevent.Attributes(ISample, "field"))
+    )
+
+:class:`ContainerModifiedEvent`
+===============================
+
+Event object to send as a notification when a container object modified.
+
+.. class:: grok.ContainerModifiedEvent(object, *descriptions)
+
+    Default event implementation of the `grok.IContainerModifiedEvent`
+    interface.
+
+    .. attribute:: object
+
+       The subject of the event.
+
+    .. attribute:: descriptions
+
+        A list of descriptions of the modifications.
+
+
+:class:`ObjectMovedEvent`
 =========================
 
+Event object to send as a notification of when an object is moved.
 
-grok.IObjectMovedEvent
-======================
+.. class:: grok.ObjectMovedEvent(object, oldParent, oldName, newParent, newName)
 
+    Default event implementation of the `grok.IObjectMovedEvent` interface.
 
-grok.IObjectRemovedEvent
-========================
+    .. attribute:: object
 
+       The subject of the event.
 
-grok.ContainerModifiedEvent
+    .. attribute:: oldParent
+
+       The container stored in before moving.
+
+    .. attribute:: oldName
+
+       The name before moving.
+
+    .. attribute:: newParent
+
+       The container stored in after moving.
+
+    .. attribute:: newName
+
+       The name after moving.
+
+
+:class:`ObjectAddedEvent`
+=========================
+
+Event object to send as a notification of when an object is added.
+
+.. class:: grok.ObjectAddedEvent(object, newParent, newName)
+
+    Default event implementation of the `grok.IObjectAddedEvent` interface.
+
+    .. attribute:: object
+
+       The subject of the event.
+
+    .. attribute:: newParent
+
+       The container stored in after moving.
+
+    .. attribute:: newName
+
+       The name after moving.
+
+
+:class:`ObjectCopiedEvent`
+==========================
+
+Event object to send as a notification of when an object is copied.
+
+.. class:: grok.ObjectCopiedEvent(object, original)
+
+    Default event implementation of the `grok.IObjectCopiedEvent` interface.
+
+    Initialize this event with the new copy and the original object as positional
+    arguments.
+    
+    .. attribute:: object
+
+       The subject of the event.
+
+    .. attribute:: original
+
+       The original object from which the copy was made.
+
+
+:class:`ObjectCreatedEvent`
 ===========================
 
+Event object to send as a notification of when an object is created.
 
-grok.ObjectAddedEvent
-=====================
+.. class:: grok.ObjectCreatedEvent(object)
 
+    Default event implementation of the `grok.IObjectCreatedEvent` interface.
 
-grok.ObjectCopiedEvent
-======================
+    Initialize this event with the object created.
 
+    .. attribute:: object
 
-grok.ObjectCreatedEvent
-=======================
+       The subject of the event.
 
+:class:`grok.ObjectRemovedEvent`
+================================
 
-grok.ObjectModifiedEvent
-========================
+Event object to send as a notification of when an object is removed.
 
+.. class:: grok.ObjectRemovedEvent*(object, oldParent, oldName)
 
-grok.ObjectMovedEvent
-=====================
+    Default event implementation of the `grok.IObjectRemovedEvent` interface.
 
+    .. attribute:: object
+    
+        The subject of the event.
 
-grok.ObjectRemovedEvent
-=======================
+    .. attribute:: oldParent
 
+       The container stored in before removal.
+
+    .. attribute:: oldName
+
+       The name of the removed object.
+

Modified: grok/branches/ulif-adminless/doc/reference/index.rst
===================================================================
--- grok/branches/ulif-adminless/doc/reference/index.rst	2008-07-10 20:42:05 UTC (rev 88203)
+++ grok/branches/ulif-adminless/doc/reference/index.rst	2008-07-10 20:48:38 UTC (rev 88204)
@@ -1,27 +1,27 @@
 .. _reference-index:
 
 #################################
-  Grok reference
+  The Grok Reference
 #################################
+(keep this under your pillow)
 
-:Release: |version|
-:Date: |today|
+:Reference for Grok version: |version|
+:Document last updated: |today|
 
    Grok means to understand so thoroughly that the observer becomes a part
    of the observed -- merge, blend, intermarry, lose identity in group
    experience. It means almost everything that we mean by religion,
    philosophy, and science -- it means as little to us (because we are from
-   Earth) as color means to a blind man. -- `Robert A. Heinlein, Stranger in
-   a Strange Land`
+   Earth) as color means to a blind man.
+   
+    -- `From "Stranger in a Strange Land" by Robert A. Heinlein.`
+        
+This is the Grok reference documentation. It is organized by the Python
+artefacts that implement it's concepts.
 
-
-This is the grok reference documentation. It is organized by the Python
-artefacts that implement the concepts.
-
 Grok makes Zope 3 concepts more accessible for application developers. This
 reference is not intended as introductory material for those concepts. Please
-refer to the original Zope 3 documentation and the grok tutorial for
-introductory material.
+refer to the original Zope 3 documentation and the other introductory material within this Official Grok Documentation site.
 
 .. raw:: html
 

Modified: grok/branches/ulif-adminless/doc/tutorial.rst
===================================================================
--- grok/branches/ulif-adminless/doc/tutorial.rst	2008-07-10 20:42:05 UTC (rev 88203)
+++ grok/branches/ulif-adminless/doc/tutorial.rst	2008-07-10 20:48:38 UTC (rev 88204)
@@ -691,7 +691,7 @@
 .. include:: groktut/reading_url_parameters/src/sample/app_templates/index.pt
   :literal:
 
-Restart Zope. Now going to the folllowing URL should display 8:
+Restart Zope. Now going to the following URL should display 8:
 
   http://localhost:8080/test?value1=3&value2=5
 

Modified: grok/branches/ulif-adminless/doc/upgrade.txt
===================================================================
--- grok/branches/ulif-adminless/doc/upgrade.txt	2008-07-10 20:42:05 UTC (rev 88203)
+++ grok/branches/ulif-adminless/doc/upgrade.txt	2008-07-10 20:48:38 UTC (rev 88204)
@@ -10,7 +10,7 @@
 -----------------
 
 * The directive implementations changed tremendously with the upgrade
-  to Martian 0.9.6.  Custom implementations of both directives (see
+  to Martian 0.10.  Custom implementations of both directives (see
   next bullet point) and grokkers will have to be adjusted.
 
   Since the vast majority of directives are class directives, the most
@@ -46,7 +46,8 @@
   - ``grok.provides`` with a computed default.
 
   With the new directive implementation and the extensions to
-  Martian's ``ClassGrokker``, you're now be able to write::
+  Martian's ``ClassGrokker``, you are now able to write (and you
+  should write!)::
 
     def default_provides(factory, module, **data):
         # This function is available for import from grokcore.component.meta.
@@ -56,12 +57,10 @@
         return list(zope.interface.implementedBy(factory))[0]
 
     class RobotGrokker(martian.ClassGrokker):
-        component_class = Robot
-        directives = [
-            grok.name.bind(name='robot_name'),
-            grok.title.bind(default='A Robot'),
-            grok.provides.bind(get_default=default_provides),
-            ]
+        martian.component(Robot)
+        martian.directive(grok.name, name='robot_name')
+        martian.directive(grok.title, default='A Robot')
+        martian.directive(grok.provides, get_default=default_provides)
 
         def execute(self, factory, config, robot_name, title, provides, **kw):
             config.action(
@@ -71,13 +70,14 @@
                 )
             return True
 
-  Basically, all you need to do is provide a list of *bound*
-  directives in the grokker class and then implement the ``execute``
+  What you need to do is provide the directives in the grokker class
+  using ``martian.directive`` and then implement the ``execute``
   method which will get the class (``factory``) and the configuration
   context (``config``) as positional arguments and then the values of
-  the directives as keyword parameters.  Note that when binding the
-  directives, you may
+  the directives as keyword parameters.
 
+  Note that when using ``martian.directive``, you may
+
   - set the name of the keyword parameter if you want it to be
     different than the directive's name,
 
@@ -87,12 +87,25 @@
   - pass in a factory for a computed default value (``get_default``).
 
   If you need still need to manually retrieve directive values from an
-  object (a class, an instance or a module), you can do so by using
-  the ``get`` method of the bound directive, e.g.::
+  object (a class, an instance or a module), you can do so by
+  explicitly calling ``bind`` on the directive (which accepts the same
+  optional parameters as ``martian.directive``), and then the ``get``
+  method of the bound directive, e.g.::
 
     class_context = grok.context.bind().get(factory, module=module)
     just_module_context = grok.context.bind().get(module=module)
 
+  In most cases it's possible to avoid this though, and use the
+  ``martian.directive`` directive on the class level.
+
+  You can look at ``src/grok/meta.py`` in Grok to see examples.
+
+* Your custom grokker could previously use ``component_class`` and
+  ``priority`` as class-level variables. These have been changed to
+  the ``martian.component`` and the ``martian.priority`` directives
+  that take the value as its first argument. The new
+  ``martian.directive`` directive was introduced above.
+ 
 * Custom directives need to be re-implemented using Martian's new
   ``Directive`` base class.  The directive scope, the type of storage,
   the validator and a potential default value are all defined as
@@ -139,14 +152,27 @@
                 if not isinstance(value, type):
                     raise GrokError("%r is not a class!" % value)
 
-* We moved to newer versions of zope packages, using the KGS list for
-  Zope 3.4c1.  This means your code can now get some new deprecation
+* We moved to newer versions of zope packages. Grok's versions for
+  Zope packages are now based on the KGS list for Zope 3.4c1 (the
+  latest list).  This means your code can now get some new deprecation
   warnings for imports that have been moved. Please check your code
   and fix your imports if you get those warnings.
 
-  If you were using ``zope.publisher.http.applySkin``, you now must
-  use ``grok.util.applySkin``.
+* If you were using ``zope.publisher.http.applySkin``, you now must
+  use ``grok.util.applySkin``. This because
+  ``zope.publisher.http.appySkin`` was removed again in later versions
+  of ``zope.publisher``.
 
+* The ``url`` method on ``ViewletManager`` and ``Viewlet`` was
+  removed. Instead you can easily access the ``url`` method of the
+  view itself from within a viewlet or viewlet manager, and the
+  ``view`` name is also available in viewlet templates. There are also
+  new ``viewlet`` and ``viewletmanager`` namespaces in the viewlet
+  templates. Note that ``view`` in a viewlet thus means something else
+  than what it does before. Previous uses of ``view`` in a viewlet
+  template should be renamed to ``viewlet``.
+
+
 Upgrading to 0.12
 -----------------
 

Modified: grok/branches/ulif-adminless/grokdocs/setup.py
===================================================================
--- grok/branches/ulif-adminless/grokdocs/setup.py	2008-07-10 20:42:05 UTC (rev 88203)
+++ grok/branches/ulif-adminless/grokdocs/setup.py	2008-07-10 20:48:38 UTC (rev 88204)
@@ -10,7 +10,7 @@
 Grokdocs: Build the Grok documentation in different formats!
 """,
     install_requires=['docutils==0.4',
-                      'Sphinx==0.1.61950',
+                      'Sphinx==0.4',
                       'Pygments',
                       ],
     package_dir = {'': 'src'},


Property changes on: grok/branches/ulif-adminless/grokdocs/src/grokdocs
___________________________________________________________________
Name: svn:ignore
   + *.pyc


Modified: grok/branches/ulif-adminless/grokwiki/src/grokwiki/page_templates/edit.pt
===================================================================
--- grok/branches/ulif-adminless/grokwiki/src/grokwiki/page_templates/edit.pt	2008-07-10 20:42:05 UTC (rev 88203)
+++ grok/branches/ulif-adminless/grokwiki/src/grokwiki/page_templates/edit.pt	2008-07-10 20:48:38 UTC (rev 88204)
@@ -1,4 +1,4 @@
-<html metal:use-macro="context/@@layout/main">
+<html metal:use-macro="context/@@layout/macros/main">
     <div metal:fill-slot="content">
         <h1>Edit &raquo;<span tal:replace="context/__name__">WikiPage</span>&laquo;</h1>
 

Modified: grok/branches/ulif-adminless/grokwiki/src/grokwiki/page_templates/index.pt
===================================================================
--- grok/branches/ulif-adminless/grokwiki/src/grokwiki/page_templates/index.pt	2008-07-10 20:42:05 UTC (rev 88203)
+++ grok/branches/ulif-adminless/grokwiki/src/grokwiki/page_templates/index.pt	2008-07-10 20:48:38 UTC (rev 88204)
@@ -1,4 +1,4 @@
-<html metal:use-macro="context/@@layout/main">
+<html metal:use-macro="context/@@layout/macros/main">
     <div metal:fill-slot="content">
         <h1 tal:content="context/__name__">WikiPage</h1>
 

Modified: grok/branches/ulif-adminless/setup.py
===================================================================
--- grok/branches/ulif-adminless/setup.py	2008-07-10 20:42:05 UTC (rev 88203)
+++ grok/branches/ulif-adminless/setup.py	2008-07-10 20:48:38 UTC (rev 88204)
@@ -15,7 +15,7 @@
 
 setup(
     name='grok',
-    version='0.13dev',
+    version='0.14dev',
     author='Grok Team',
     author_email='grok-dev at zope.org',
     url='http://grok.zope.org',
@@ -56,7 +56,6 @@
                       'zope.app.publisher',
                       'zope.app.renderer',
                       'zope.app.security',
-                      'zope.app.securitypolicy',
                       'zope.app.testing',
                       'zope.app.twisted',
                       'zope.app.zcmlfiles',
@@ -85,5 +84,9 @@
                       'z3c.flashmessage',
                       'z3c.autoinclude',
                       'z3c.testsetup',
+                      # deprecated packages, there for backwards compatibility
+                      'zope.app.error',
+                      'zope.app.securitypolicy',
+                      'zope.app.session',
                       ],
 )

Modified: grok/branches/ulif-adminless/src/grok/components.py
===================================================================
--- grok/branches/ulif-adminless/src/grok/components.py	2008-07-10 20:42:05 UTC (rev 88203)
+++ grok/branches/ulif-adminless/src/grok/components.py	2008-07-10 20:48:38 UTC (rev 88204)
@@ -175,6 +175,14 @@
     def _render_template(self):
         return self.template.render(self)
 
+    def default_namespace(self):
+        namespace = {}
+        namespace['context'] = self.context
+        namespace['request'] = self.request
+        namespace['static'] = self.static
+        namespace['view'] = self
+        return namespace
+
     def namespace(self):
         return {}
 
@@ -312,7 +320,8 @@
         self.__grok_module__ = martian.util.caller_module()
 
         if not (string is None) ^ (filename is None):
-            raise AssertionError("You must pass in template or filename, but not both.")
+            raise AssertionError(
+                "You must pass in template or filename, but not both.")
 
         if string:
             self.setFromString(string)
@@ -334,15 +343,10 @@
         pass
 
     def namespace(self, view):
-        namespace = {}
-        namespace['request'] = view.request
-        namespace['view'] = view
-        namespace['context'] = view.context
-        # XXX need to check whether we really want to put None here if missing
-        namespace['static'] = view.static
+        # By default use the namespaces that are defined as the
+        # default by the view implementation.
+        return view.default_namespace()
 
-        return namespace
-
     def getNamespace(self, view):
         namespace = self.namespace(view)
         namespace.update(view.namespace())
@@ -667,6 +671,9 @@
 
     def __init__(self, context, request, view):
         super(ViewletManager, self).__init__(context, request, view)
+        self.context = context
+        self.request = request
+        self.view = view
         self.__name__ = self.__view_name__
         self.static = component.queryAdapter(
             self.request,
@@ -698,6 +705,18 @@
         s_viewlets = util.sort_components(s_viewlets)
         return [(viewlet.__viewlet_name__, viewlet) for viewlet in s_viewlets]
 
+    def default_namespace(self):
+        namespace = {}
+        namespace['context'] = self.context
+        namespace['request'] = self.request
+        namespace['static'] = self.static
+        namespace['view'] = self.view
+        namespace['viewletmanager'] = self
+        return namespace
+
+    def namespace(self):
+        return {}
+
     def render(self):
         """See zope.contentprovider.interfaces.IContentProvider"""
         # Now render the view
@@ -706,41 +725,17 @@
         else:
             return u'\n'.join([viewlet.render() for viewlet in self.viewlets])
 
-    def namespace(self):
-        return {}
 
-    @property
-    def response(self):
-        return self.request.response
-
-    def url(self, obj=None, name=None):
-        # if the first argument is a string, that's the name. There should
-        # be no second argument
-        if isinstance(obj, basestring):
-            if name is not None:
-                raise TypeError(
-                    'url() takes either obj argument, obj, string arguments, '
-                    'or string argument')
-            name = obj
-            obj = None
-
-        if name is None and obj is None:
-            # create URL to view itself
-            obj = self
-        elif name is not None and obj is None:
-            # create URL to view on context
-            obj = self.context
-        return util.url(self.request, obj, name)
-
-    def redirect(self, url):
-        return self.request.response.redirect(url)
-
 class Viewlet(ViewletBase):
-    """ Batteries included viewlet """
+    """Batteries included viewlet.
+    """
 
-
     def __init__(self, context, request, view, manager):
         super(Viewlet, self).__init__(context, request, view, manager)
+        self.context = context
+        self.request = request
+        self.view = view
+        self.viewletmanager = manager
         self.__name__ = self.__view_name__
         self.static = component.queryAdapter(
             self.request,
@@ -748,34 +743,21 @@
             name=self.module_info.package_dotted_name
             )
 
-    @property
-    def response(self):
-        return self.request.response
+    def default_namespace(self):
+        namespace = {}
+        namespace['context'] = self.context
+        namespace['request'] = self.request
+        namespace['static'] = self.static
+        namespace['view'] = self.view
+        namespace['viewlet'] = self
+        namespace['viewletmanager'] = self.manager
+        return namespace
 
-    def render(self):
-        return self.template.render(self)
-
     def namespace(self):
         return {}
 
-    def url(self, obj=None, name=None):
-        # if the first argument is a string, that's the name. There should
-        # be no second argument
-        if isinstance(obj, basestring):
-            if name is not None:
-                raise TypeError(
-                    'url() takes either obj argument, obj, string arguments, '
-                    'or string argument')
-            name = obj
-            obj = None
-
-        if name is None and obj is None:
-            # create URL to view itself
-            obj = self
-        elif name is not None and obj is None:
-            # create URL to view on context
-            obj = self.context
-        return util.url(self.request, obj, name)
-
     def update(self):
         pass
+
+    def render(self):
+        return self.template.render(self)

Modified: grok/branches/ulif-adminless/src/grok/ftests/view/macros.py
===================================================================
--- grok/branches/ulif-adminless/src/grok/ftests/view/macros.py	2008-07-10 20:42:05 UTC (rev 88203)
+++ grok/branches/ulif-adminless/src/grok/ftests/view/macros.py	2008-07-10 20:48:38 UTC (rev 88204)
@@ -21,7 +21,7 @@
   Traceback (most recent call last):
   AttributeError: 'DancingHall' object has no attribute 'template'
 
-If the view has an attribute with the same name as a macro, the macro 
+If the view has an attribute with the same name as a macro, the macro
 shadows the view. XXX This should probably generate a warning at runtime.
 
   >>> browser.open("http://localhost/manfred/@@grilldish")
@@ -29,19 +29,19 @@
   <html>
   Curry
   </html>
-  
+
 You can skip the "macro" part of the macro call, but this is deprecated:
 
-  >>> from zope.deprecation.tests import warn
+  >>> from grok.testing import warn
   >>> import warnings
   >>> saved_warn = warnings.warn
   >>> warnings.warn = warn
 
   >>> browser.open("http://localhost/manfred/@@burnt")
-  From tests.py's showwarning():
+  From grok.testing's warn():
   ... DeprecationWarning: Calling macros directly on the view is deprecated. Please use context/@@viewname/macros/macroname
   ...
-  
+
   >>> warnings.warn = saved_warn
 
 """

Copied: grok/branches/ulif-adminless/src/grok/ftests/viewlet/template_namespaces.py (from rev 88203, grok/trunk/src/grok/ftests/viewlet/template_namespaces.py)
===================================================================
--- grok/branches/ulif-adminless/src/grok/ftests/viewlet/template_namespaces.py	                        (rev 0)
+++ grok/branches/ulif-adminless/src/grok/ftests/viewlet/template_namespaces.py	2008-07-10 20:48:38 UTC (rev 88204)
@@ -0,0 +1,56 @@
+"""
+Let's check that the viewlet namespaces are correct. In particular,
+``view`` in a template should refer to the namespace of the view the
+viewlet is registered for, not the actual viewlet itself.
+
+  >>> root = getRootFolder()
+  >>> root['cave'] = Cave()
+
+Let's look at the first template, which includes the viewlet::
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+  >>> browser.open("http://localhost/cave/@@index")
+  >>> print browser.contents
+  <grok.ftests.viewlet.template_namespaces.Cave object at ...>
+  <grok.ftests.viewlet.template_namespaces.Index object at ...>
+  <grok.ftests.viewlet.template_namespaces.MirandaViewlet object at ...>
+  <grok.ftests.viewlet.template_namespaces.CavewomenViewletManager object at ...>
+
+This is indeed what we expected from the viewlet.
+
+Let's look at a template for the viewlet manager too::
+
+  >>> browser.open("http://localhost/cave/@@necklace")
+  >>> print browser.contents
+  <grok.ftests.viewlet.template_namespaces.Cave object at ...>
+  <grok.ftests.viewlet.template_namespaces.Necklace object at ...>
+  <grok.ftests.viewlet.template_namespaces.CavewomenViewletManagerWithTemplate object at ...>
+
+"""
+import grok
+
+
+class Cave(grok.Model):
+    pass
+
+class Index(grok.View):
+    pass
+
+class CavewomenViewletManager(grok.ViewletManager):
+    grok.name('manage.cavewomen')
+    grok.view(Index)
+
+class MirandaViewlet(grok.Viewlet):
+    grok.template('mirandaviewlet')
+    grok.view(Index)
+    grok.viewletmanager(CavewomenViewletManager)
+
+class Necklace(grok.View):
+    pass
+
+class CavewomenViewletManagerWithTemplate(grok.ViewletManager):
+    grok.name('manage.cavewomenwithtemplate')
+    grok.template('mirandaviewletmanager')
+    grok.view(Necklace)

Copied: grok/branches/ulif-adminless/src/grok/ftests/viewlet/template_namespaces_templates (from rev 88203, grok/trunk/src/grok/ftests/viewlet/template_namespaces_templates)

Modified: grok/branches/ulif-adminless/src/grok/ftests/viewlet/viewletmanager_template_templates/cavemanager.pt
===================================================================
--- grok/branches/ulif-adminless/src/grok/ftests/viewlet/viewletmanager_template_templates/cavemanager.pt	2008-07-10 20:42:05 UTC (rev 88203)
+++ grok/branches/ulif-adminless/src/grok/ftests/viewlet/viewletmanager_template_templates/cavemanager.pt	2008-07-10 20:48:38 UTC (rev 88204)
@@ -1,3 +1,3 @@
-<ul tal:define="v_dict view/viewlet_dict; v_keys view/viewlet_keys_sorted;">
+<ul tal:define="v_dict viewletmanager/viewlet_dict; v_keys viewletmanager/viewlet_keys_sorted;">
  <li tal:repeat="k v_keys" tal:content="python:v_dict[k].render().strip()" />
 </ul>

Modified: grok/branches/ulif-adminless/src/grok/interfaces.py
===================================================================
--- grok/branches/ulif-adminless/src/grok/interfaces.py	2008-07-10 20:42:05 UTC (rev 88203)
+++ grok/branches/ulif-adminless/src/grok/interfaces.py	2008-07-10 20:48:38 UTC (rev 88204)
@@ -320,6 +320,22 @@
         as a cgi query string.
         """
 
+    def default_namespace():
+        """Returns a dictionary of namespaces that the template
+        implementation expects to always be available.
+
+        This method is *not* intended to be overridden by application
+        developers.
+        """
+
+    def namespace():
+        """Returns a dictionary that is injected in the template
+        namespace in addition to the default namespace.
+
+        This method *is* intended to be overridden by the application
+        developer.
+        """
+
     def update(**kw):
         """This method is meant to be implemented by grok.View
         subclasses.  It will be called *before* the view's associated
@@ -507,4 +523,3 @@
 class IViewletManager(IViewletManagerBase):
     """The Grok viewlet manager.
     """
-

Modified: grok/branches/ulif-adminless/src/grok/meta.py
===================================================================
--- grok/branches/ulif-adminless/src/grok/meta.py	2008-07-10 20:42:05 UTC (rev 88203)
+++ grok/branches/ulif-adminless/src/grok/meta.py	2008-07-10 20:48:38 UTC (rev 88204)
@@ -49,7 +49,7 @@
 
 import grok
 from grok import components, formlib, templatereg
-from grok.util import check_permission, make_checker
+from grok.util import make_checker
 from grok.interfaces import IRESTSkinType
 from grok.interfaces import IViewletManager as IGrokViewletManager
 

Modified: grok/branches/ulif-adminless/src/grok/templatereg.py
===================================================================
--- grok/branches/ulif-adminless/src/grok/templatereg.py	2008-07-10 20:42:05 UTC (rev 88203)
+++ grok/branches/ulif-adminless/src/grok/templatereg.py	2008-07-10 20:48:38 UTC (rev 88204)
@@ -84,7 +84,7 @@
                 "grokking %r: %s.  Define view classes inheriting "
                 "from grok.View to enable the template(s)." % (
                 module_info.dotted_name, ', '.join(unassociated)))
-            warnings.warn(msg, UserWarning, 2)
+            warnings.warn(msg, UserWarning, 1)
 
     def checkTemplates(self, module_info, factory, component_name,
                        has_render, has_no_render):

Modified: grok/branches/ulif-adminless/src/grok/testing.py
===================================================================
--- grok/branches/ulif-adminless/src/grok/testing.py	2008-07-10 20:42:05 UTC (rev 88203)
+++ grok/branches/ulif-adminless/src/grok/testing.py	2008-07-10 20:48:38 UTC (rev 88204)
@@ -13,6 +13,7 @@
 ##############################################################################
 """Grok test helpers
 """
+import sys
 import os.path
 import z3c.testsetup
 import grokcore.component
@@ -46,3 +47,33 @@
     zcml.do_grok('grok.templatereg', config)
     zcml.do_grok(module_name, config)
     config.execute_actions()
+
+def warn(message, category=None, stacklevel=1):
+    """Intended to replace warnings.warn in tests.
+
+    Modified copy from zope.deprecation.tests to:
+
+      * make the signature identical to warnings.warn
+      * to check for *.pyc and *.pyo files.
+
+    When zope.deprecation is fixed, this warn function can be removed again.
+    """
+    print "From grok.testing's warn():"
+
+    frame = sys._getframe(stacklevel)
+    path = frame.f_globals['__file__']
+    if path.endswith('.pyc') or path.endswith('.pyo'):
+        path = path[:-1]
+
+    file = open(path)
+    lineno = frame.f_lineno
+    for i in range(lineno):
+        line = file.readline()
+
+    print "%s:%s: %s: %s\n  %s" % (
+        path,
+        frame.f_lineno,
+        category.__name__,
+        message,
+        line.strip(),
+        )

Modified: grok/branches/ulif-adminless/src/grok/tests/view/dirtemplatesonly.py
===================================================================
--- grok/branches/ulif-adminless/src/grok/tests/view/dirtemplatesonly.py	2008-07-10 20:42:05 UTC (rev 88203)
+++ grok/branches/ulif-adminless/src/grok/tests/view/dirtemplatesonly.py	2008-07-10 20:48:38 UTC (rev 88204)
@@ -1,13 +1,13 @@
 """
 A template directory may only contain recognized template files::
 
-  >>> from zope.deprecation.tests import warn
+  >>> from grok.testing import warn
   >>> import warnings
   >>> saved_warn = warnings.warn
   >>> warnings.warn = warn
 
   >>> grok.testing.grok(__name__)
-  From tests.py's showwarning():
+  From grok.testing's warn():
   ... UserWarning: File 'invalid.txt' has an unrecognized extension in
   directory '...dirtemplatesonly_templates'...
 

Modified: grok/branches/ulif-adminless/src/grok/tests/view/inline_unassociated.py
===================================================================
--- grok/branches/ulif-adminless/src/grok/tests/view/inline_unassociated.py	2008-07-10 20:42:05 UTC (rev 88203)
+++ grok/branches/ulif-adminless/src/grok/tests/view/inline_unassociated.py	2008-07-10 20:48:38 UTC (rev 88204)
@@ -2,14 +2,16 @@
 Inline templates that are not associated with a view class will
 provoke an error:
 
-  >>> from zope.deprecation.tests import warn
+  >>> from grok.testing import warn
   >>> import warnings
   >>> saved_warn = warnings.warn
   >>> warnings.warn = warn
 
   >>> grok.testing.grok(__name__)
-  From tests.py's showwarning():
-  ...UserWarning: Found the following unassociated template(s) when grokking 'grok.tests.view.inline_unassociated': club.  Define view classes inheriting from grok.View to enable the template(s).
+  From grok.testing's warn():
+  ...UserWarning: Found the following unassociated template(s) when grokking
+  'grok.tests.view.inline_unassociated': club. Define view classes inheriting
+  from grok.View to enable the template(s)...
 
   >>> warnings.warn = saved_warn
 

Modified: grok/branches/ulif-adminless/src/grok/tests/view/unassociated.py
===================================================================
--- grok/branches/ulif-adminless/src/grok/tests/view/unassociated.py	2008-07-10 20:42:05 UTC (rev 88203)
+++ grok/branches/ulif-adminless/src/grok/tests/view/unassociated.py	2008-07-10 20:48:38 UTC (rev 88204)
@@ -2,16 +2,16 @@
 Templates that are not associated with a view class will provoke an
 error:
 
-  >>> from zope.deprecation.tests import warn
+  >>> from grok.testing import warn
   >>> import warnings
   >>> saved_warn = warnings.warn
   >>> warnings.warn = warn
 
   >>> grok.testing.grok(__name__)
-  From tests.py's showwarning():
+  From grok.testing's warn():
   ...UserWarning: Found the following unassociated template(s) when grokking
   'grok.tests.view.unassociated': index.  Define view classes inheriting from
-  grok.View to enable the template(s).
+  grok.View to enable the template(s)...
 
 Also templates of modules named equally as the package name the module
 resides in, should be found without error or warning. We check this
@@ -22,7 +22,7 @@
   >>> pkg = __name__.rsplit('.', 1)[0] + '.modequalspkgname'
   >>> grok.testing.grok(pkg) is None
   True
-  
+
   >>> warnings.warn = saved_warn
 
 """

Copied: grok/branches/ulif-adminless/src/grok/tests/viewlet/viewlet_references.py (from rev 88203, grok/trunk/src/grok/tests/viewlet/viewlet_references.py)
===================================================================
--- grok/branches/ulif-adminless/src/grok/tests/viewlet/viewlet_references.py	                        (rev 0)
+++ grok/branches/ulif-adminless/src/grok/tests/viewlet/viewlet_references.py	2008-07-10 20:48:38 UTC (rev 88204)
@@ -0,0 +1,65 @@
+"""
+A grok.ViewletManager instance has references to the components it was
+registered for::
+
+  >>> grok.testing.grok(__name__)
+  >>> from zope import component
+  >>> from zope.contentprovider.interfaces import IContentProvider
+  >>> from zope.publisher.browser import TestRequest
+  >>> ctxt = AContext()
+  >>> request = TestRequest()
+  >>> view = component.getMultiAdapter((ctxt, request), name='with_items')
+  >>> items_mgr = component.getMultiAdapter(
+  ...     (ctxt, request, view), IContentProvider, name='view_items_manager')
+  >>> items_mgr.context is ctxt
+  True
+  >>> items_mgr.view is view
+  True
+  >>> items_mgr.request is request
+  True
+
+Likewise, grok.Viewlet instances have references to the components they're
+registered for::
+
+  >>> items_mgr.update()
+  >>> for viewlet in items_mgr.viewlets:
+  ...     viewlet.context is ctxt
+  ...     viewlet.view is view
+  ...     viewlet.viewletmanager is items_mgr
+  ...     viewlet.request is request
+  True
+  True
+  True
+  True
+  True
+  True
+  True
+  True
+"""
+
+import grok
+from zope import interface
+
+class AContext(grok.Model):
+    pass
+
+class ViewWithItems(grok.View):
+    grok.name('with_items')
+
+    def render(self):
+        return ''
+
+class ViewItemsManager(grok.ViewletManager):
+    grok.name('view_items_manager')
+
+class ItemOneViewlet(grok.Viewlet):
+    grok.name('item_one')
+
+    def render(self):
+        return "Item one reporting, sir!"
+
+class ItemTwoViewlet(grok.Viewlet):
+    grok.name('item_two')
+
+    def render(self):
+        return "Item two reporting, sir!"



More information about the Checkins mailing list